test and finish FS
[brdnet.git] / NetAddr.pas
blobf8c645b2718a8877d80600e23dfebc6a750c2919
1 unit NetAddr;
3 INTERFACE
4 uses Sockets
5 ,SysUtils
8 {Redefine socaddr here, becouse original is too short for ipv6 and unix}
9 type tSockAddrL = packed record
10 sa_family: sa_family_t;
11 sa_data: array [0..107] of byte;
12 end;
13 type tSockAddr= type tSockAddrL deprecated;
15 TYPE
16 {$PACKENUM 1}
17 tFamily=(afNil=0, afInet=1, afInet6 );
19 { Network-byte-ordered words }
20 Word2=array [1..2] of byte; {0..65535}
21 Word4=array [1..4] of byte; {0..4294967295}
23 { Object to store Socket Address }
24 t= packed object
26 function Length :word;
27 { Returns length of the structure based on address family }
29 procedure ToSocket( var sockaddr :tSockAddrL );
30 {$HINT Not actually testet, byt seems to work}
31 procedure FromSocket( var sockaddr :tSockAddrL );
32 {$HINT Not actually testet, byt seems to work}
34 procedure ToString( var str :String );
35 {$HINT Not actually testet, byt seems to work}
36 procedure FromString( str :String );
37 {$HINT Not actually testet, byt seems to work}
38 function Hash:Word;
40 procedure LocalHost( af: tFamily );
41 {Generate localhost address of address family af.}
42 {$HINT Not actually testet, byt seems to work}
44 procedure Clear;
45 function isNil:boolean;
47 public
48 data :packed record
49 case Family : tFamily of
50 { note: maximum family is 32 so byte is enough }
51 afInet :( inet :packed record
52 port: Word;
53 addr: tInAddr;
54 end; );
55 afInet6 :( inet6 :packed record
56 port: Word;
57 addr: tIn6Addr;
58 end; );
59 afNil :(
60 pad_pV4IlkA4mKQL :packed array [0..128] of byte;
61 );
62 end;
63 end;
65 tNetAddr=t; {alias}
67 function ConvertFamily( a:tFamily ): sa_family_t;
69 operator := (net : Word2) host:word;
70 operator := (net : Word4) host:Dword;
71 operator := (host : word) net:Word2;
72 operator := (host : Dword) net:Word4;
74 Operator = (aa, ab :t) b : boolean;
76 operator := ( at : t) aString : string;
77 operator := ( aString : string) at : t;
80 Operator := (aa :t ) r : pSockAddr;
81 Operator := ( aa :pSockAddr ) r : t;
84 IMPLEMENTATION
86 Operator = (aa, ab :Sockets.tInAddr) b : boolean;
87 begin
88 b:=aa.s_addr=ab.s_addr;
89 end;
91 Operator = (aa, ab :t) b : boolean;
92 begin
93 b:=false;
94 if aa.data.Family<>ab.data.Family then exit;
95 case aa.data.Family of
96 afInet: if (aa.data.inet.port<>ab.data.inet.port) or (aa.data.inet.addr<>ab.data.inet.addr) then exit;
97 afNil: {null addresses are always equal};
98 else AbstractError;
99 end;
100 b:=true;
101 end;
103 function t.Length :Word;
104 begin
105 result:=(sizeof(self)-sizeof(data))+sizeof(data.Family);
106 case data.Family of
107 afNil: ;
108 afInet: result+=sizeof( data.inet );
109 afInet6: result+=sizeof( data.inet6 );
110 else result:=sizeof(self);
111 end;
112 end;
114 function ConvertFamily( a:tFamily ): sa_family_t;
115 begin
116 case a of
117 afInet: result:=Sockets.AF_INET;
118 afInet6: result:=Sockets.AF_INET6;
119 else AbstractError;
120 end;
121 end;
123 procedure t.ToSocket( var sockaddr :tSockAddrL );
124 begin
125 case data.family of
126 afInet: begin
127 sockaddr.sa_family:=Sockets.AF_INET;
128 Move(data.inet, sockaddr.sa_data, sizeof(data.inet) );
129 end;
130 afInet6: begin
131 sockaddr.sa_family:=Sockets.AF_INET6;
132 with tInetSockAddr6(pointer(@sockaddr)^) do begin
133 sin6_port:=data.inet6.port;
134 sin6_flowinfo:=0;
135 sin6_addr:=data.inet6.addr;
136 sin6_scope_id:=0;
137 end;
138 end;
139 else AbstractError;
140 end;
141 end;
143 procedure t.FromSocket( var sockaddr :tSockAddrL );
144 begin
145 case sockaddr.sa_family of
146 Sockets.AF_INET: begin
147 data.family:=afInet;
148 move(sockaddr.sa_data, data.inet, sizeof(data.inet) );
149 end;
150 Sockets.AF_INET6: begin
151 data.family:=afInet6;
152 move(sockaddr.sa_data, data.inet6, sizeof(data.inet6) );
153 end;
154 else raise Exception.Create('Unknown AF '+IntToStr(sockaddr.sa_family));
155 end;
156 end;
158 {$I NetAddr-str.pas}
160 procedure t.ToString( var str :String );
161 begin
162 case data.Family of
163 afInet: begin
164 str:='//ip4/'+Sockets.NetAddrToStr(data.inet.addr)+
165 '/'+IntToStr(ShortNetToHost(data.inet.port));
166 end;
167 afInet6: begin
168 str:='//ip6/'+Sockets.NetAddrToStr6(data.inet6.addr)+
169 '/'+IntToStr(ShortNetToHost(data.inet6.port));
170 end;
171 afNil: str:='//nil';
172 else str:='//nil/UnknownAddressFamily';
173 end;
174 end;
176 procedure t.FromString( str :String );
177 var i:integer;
178 var fam:string;
179 begin
180 if System.Length(str)=0 then begin Clear; exit end;
181 if Copy(str,1,2)<>'//' then raise eConvertError.Create('');
182 Delete(str,1,2);
183 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
184 fam:=copy(str,1,i-1);
185 delete(str,1,i);
186 if fam='ip4' then begin
187 data.family:=afInet;
189 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
190 fam:=copy(str,1,i-1);
191 delete(str,1,i);
192 data.inet.addr:=StrToNetAddr(fam);
194 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
195 fam:=copy(str,1,i-1);
196 delete(str,1,i);
197 data.inet.port:=ShortHostToNet(StrToInt(fam));
199 end else if fam='ip6' then begin
200 data.family:=afInet6;
202 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
203 fam:=copy(str,1,i-1);
204 delete(str,1,i);
205 data.inet6.addr:=StrToNetAddr6(fam);
207 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
208 fam:=copy(str,1,i-1);
209 delete(str,1,i);
210 data.inet6.port:=ShortHostToNet(StrToInt(fam));
212 end else if fam='nil' then begin
213 data.family:=afNil;
214 end else raise eConvertError.Create('');
215 end;
217 function t.Hash:word;
218 var h:word;
219 var i:byte;
220 procedure hashstep(v:byte);
221 begin
222 h:=((h shl 5)and $FFFF) xor ((h shr 2)and $FFFF) xor v;
223 end;
224 begin
225 h:=0;
226 assert(sizeof(data.family)=1,'simple set size'+IntToStr(sizeof(data.family)));
227 hashstep(byte(data.family));
228 case data.Family of
229 afInet: for i:=1 to 4 do HashStep(data.inet.addr.s_bytes[i]);
230 afInet6: for i:=1 to 16 do HashStep(data.inet6.addr.u6_addr8[i]);
231 else AbstractError;
232 end;
233 case data.Family of
234 afInet,afInet6: begin
235 HashStep(data.inet.port and $FF);
236 HashStep((data.inet.port shr 8) and $FF);
237 end;
238 end;
239 result:=h;
240 end;
242 const cLocalHostIP4:Sockets.tInAddr=( s_bytes:(127,0,0,1) );
243 const cLocalIP4Port:word=1030;
245 procedure t.LocalHost( af: tFamily );
246 begin
247 data.Family:=af;
248 case af of
249 afInet: begin
250 data.inet.port:=ShortHostToNet(cLocalIP4Port);
251 data.inet.addr:=cLocalHostIP4;
252 end;
253 afNil: ;
254 else AbstractError;
255 end;
256 end;
258 procedure t.Clear;
259 begin
260 self.data.family:=afNil;
261 end;
263 function t.isNil:boolean;
264 begin
265 isNil:= self.data.family=afNil;
266 end;
268 operator := ( at : t) aString : string;
269 begin
270 at.ToString( aString );
271 end;
272 operator := ( aString : string) at : t;
273 begin
274 at.FromString( aString );
275 end;
277 operator := (net : Word2) host:word;
278 var pnet:^word;
279 begin
280 pnet:=@net;
281 host:=ShortNetToHost( pnet^ );
282 end;
283 operator := (net : Word4) host:Dword;
284 var pnet:^DWord;
285 begin
286 pnet:=@net;
287 host:=LEtoN( pnet^ );
288 end;
290 operator := (host : word) net:Word2;
291 var pnet:^Word;
292 begin
293 pnet:=@net;
294 pnet^:= ShortHostToNet( host );
295 end;
296 operator := (host : Dword) net:Word4;
297 var pnet:^DWord;
298 begin
299 pnet:=@net;
300 pnet^:=NtoLE( host );
301 end;
303 END.