notes to dht impl and related
[brdnet.git] / NetAddr.pas
blob4f86e8a498aca41c278c73a74a09f86cf791e646
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 procedure t.ToString( var str :String );
159 begin
160 case data.Family of
161 afInet: begin
162 str:='//ip4/'+Sockets.NetAddrToStr(data.inet.addr)+
163 '/'+IntToStr(ShortNetToHost(data.inet.port));
164 end;
165 afInet6: begin
166 str:='//ip6/'+Sockets.NetAddrToStr6(data.inet6.addr)+
167 '/'+IntToStr(ShortNetToHost(data.inet6.port));
168 end;
169 afNil: str:='//nil';
170 else str:='//nil/UnknownAddressFamily';
171 end;
172 end;
174 procedure t.FromString( str :String );
175 var i:integer;
176 var fam:string;
177 begin
178 if System.Length(str)=0 then begin Clear; exit end;
179 if Copy(str,1,2)<>'//' then raise eConvertError.Create('');
180 Delete(str,1,2);
181 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
182 fam:=copy(str,1,i-1);
183 delete(str,1,i);
184 if fam='ip4' then begin
185 data.family:=afInet;
187 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
188 fam:=copy(str,1,i-1);
189 delete(str,1,i);
190 data.inet.addr:=StrToNetAddr(fam);
192 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
193 fam:=copy(str,1,i-1);
194 delete(str,1,i);
195 data.inet.port:=ShortHostToNet(StrToInt(fam));
197 end else if fam='ip6' then begin
198 data.family:=afInet6;
200 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
201 fam:=copy(str,1,i-1);
202 delete(str,1,i);
203 data.inet6.addr:=StrToNetAddr6(fam);
205 i:=pos('/',str); if i=0 then i:=System.Length(str)+1;
206 fam:=copy(str,1,i-1);
207 delete(str,1,i);
208 data.inet6.port:=ShortHostToNet(StrToInt(fam));
210 end else if fam='nil' then begin
211 data.family:=afNil;
212 end else raise eConvertError.Create('');
213 end;
215 function t.Hash:word;
216 var h:word;
217 var i:byte;
218 procedure hashstep(v:byte);
219 begin
220 h:=((h shl 5)and $FFFF) xor ((h shr 2)and $FFFF) xor v;
221 end;
222 begin
223 h:=0;
224 assert(sizeof(data.family)=1,'simple set size'+IntToStr(sizeof(data.family)));
225 hashstep(byte(data.family));
226 case data.Family of
227 afInet: for i:=1 to 4 do HashStep(data.inet.addr.s_bytes[i]);
228 afInet6: for i:=1 to 16 do HashStep(data.inet6.addr.u6_addr8[i]);
229 else AbstractError;
230 end;
231 case data.Family of
232 afInet,afInet6: begin
233 HashStep(data.inet.port and $FF);
234 HashStep((data.inet.port shr 8) and $FF);
235 end;
236 end;
237 result:=h;
238 end;
240 const cLocalHostIP4:Sockets.tInAddr=( s_bytes:(127,0,0,1) );
241 const cLocalIP4Port:word=1030;
243 procedure t.LocalHost( af: tFamily );
244 begin
245 data.Family:=af;
246 case af of
247 afInet: begin
248 data.inet.port:=ShortHostToNet(cLocalIP4Port);
249 data.inet.addr:=cLocalHostIP4;
250 end;
251 afNil: ;
252 else AbstractError;
253 end;
254 end;
256 procedure t.Clear;
257 begin
258 self.data.family:=afNil;
259 end;
261 function t.isNil:boolean;
262 begin
263 isNil:= self.data.family=afNil;
264 end;
266 operator := ( at : t) aString : string;
267 begin
268 at.ToString( aString );
269 end;
270 operator := ( aString : string) at : t;
271 begin
272 at.FromString( aString );
273 end;
275 operator := (net : Word2) host:word;
276 var pnet:^word;
277 begin
278 pnet:=@net;
279 host:=ShortNetToHost( pnet^ );
280 end;
281 operator := (net : Word4) host:Dword;
282 var pnet:^DWord;
283 begin
284 pnet:=@net;
285 host:=LEtoN( pnet^ );
286 end;
288 operator := (host : word) net:Word2;
289 var pnet:^Word;
290 begin
291 pnet:=@net;
292 pnet^:= ShortHostToNet( host );
293 end;
294 operator := (host : Dword) net:Word4;
295 var pnet:^DWord;
296 begin
297 pnet:=@net;
298 pnet^:=NtoLE( host );
299 end;
301 END.