fix memstream
[brdnet.git] / NetAddr.pas
blob86894728896166bafcd6ef4d833af545416c378a
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 tFamily=(afNil=0, afInet=1, afInet6 );
18 { Network-byte-ordered words }
19 Word2=array [1..2] of byte; {0..65535}
20 Word4=array [1..4] of byte; {0..4294967295}
22 { Object to store Socket Address }
23 t= packed object
25 function Length :word;
26 { Returns length of the structure based on address family }
28 procedure ToSocket( var sockaddr :tSockAddrL );
29 {$HINT Not actually testet, byt seems to work}
30 procedure FromSocket( var sockaddr :tSockAddrL );
31 {$HINT Not actually testet, byt seems to work}
33 procedure ToString( var str :String );
34 {$HINT Not actually testet, byt seems to work}
35 procedure FromString( str :String );
36 {$HINT Not actually testet, byt seems to work}
38 procedure LocalHost( af: tFamily );
39 {Generate localhost address of address family af.}
40 {$HINT Not actually testet, byt seems to work}
42 procedure Clear;
43 function isNil:boolean;
45 public
46 data :packed record
47 case Family : tFamily of
48 { note: maximum family is 32 so byte is enough }
49 afInet :( inet :packed record
50 port: Word;
51 addr: tInAddr;
52 end; );
53 afInet6 :( inet6 :packed record
54 port: Word;
55 addr: tIn6Addr;
56 end; );
57 afNil :(
58 pad_pV4IlkA4mKQL :packed array [0..128] of byte;
59 );
60 end;
61 end;
63 tNetAddr=t; {alias}
65 function ConvertFamily( a:tFamily ): sa_family_t;
67 operator := (net : Word2) host:word;
68 operator := (net : Word4) host:Dword;
69 operator := (host : word) net:Word2;
70 operator := (host : Dword) net:Word4;
72 Operator = (aa, ab :t) b : boolean;
74 operator := ( at : t) aString : string;
75 operator := ( aString : string) at : t;
78 Operator := (aa :t ) r : pSockAddr;
79 Operator := ( aa :pSockAddr ) r : t;
82 IMPLEMENTATION
84 Operator = (aa, ab :Sockets.tInAddr) b : boolean;
85 begin
86 b:=aa.s_addr=ab.s_addr;
87 end;
89 Operator = (aa, ab :t) b : boolean;
90 begin
91 b:=false;
92 if aa.data.Family<>ab.data.Family then exit;
93 case aa.data.Family of
94 afInet: if (aa.data.inet.port<>ab.data.inet.port) or (aa.data.inet.addr<>ab.data.inet.addr) then exit;
95 afNil: {null addresses are always equal};
96 else AbstractError;
97 end;
98 b:=true;
99 end;
101 function t.Length :Word;
102 begin
103 result:=(sizeof(self)-sizeof(data))+sizeof(data.Family);
104 case data.Family of
105 afNil: ;
106 afInet: result+=sizeof( data.inet );
107 afInet6: result+=sizeof( data.inet6 );
108 else result:=sizeof(self);
109 end;
110 end;
112 function ConvertFamily( a:tFamily ): sa_family_t;
113 begin
114 case a of
115 afInet: result:=Sockets.AF_INET;
116 afInet6: result:=Sockets.AF_INET6;
117 else AbstractError;
118 end;
119 end;
121 procedure t.ToSocket( var sockaddr :tSockAddrL );
122 begin
123 case data.family of
124 afInet: begin
125 sockaddr.sa_family:=Sockets.AF_INET;
126 Move(data.inet, sockaddr.sa_data, sizeof(data.inet) );
127 end;
128 afInet6: begin
129 sockaddr.sa_family:=Sockets.AF_INET6;
130 with tInetSockAddr6(pointer(@sockaddr)^) do begin
131 sin6_port:=data.inet6.port;
132 sin6_flowinfo:=0;
133 sin6_addr:=data.inet6.addr;
134 sin6_scope_id:=0;
135 end;
136 end;
137 else AbstractError;
138 end;
139 end;
141 procedure t.FromSocket( var sockaddr :tSockAddrL );
142 begin
143 case sockaddr.sa_family of
144 Sockets.AF_INET: begin
145 data.family:=afInet;
146 move(sockaddr.sa_data, data.inet, sizeof(data.inet) );
147 end;
148 Sockets.AF_INET6: begin
149 data.family:=afInet6;
150 move(sockaddr.sa_data, data.inet6, sizeof(data.inet6) );
151 end;
152 else raise Exception.Create('Unknown AF '+IntToStr(sockaddr.sa_family));
153 end;
154 end;
156 {$I NetAddr-str.pas}
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 const cLocalHostIP4:Sockets.tInAddr=( s_bytes:(127,0,0,1) );
216 const cLocalIP4Port:word=1030;
218 procedure t.LocalHost( af: tFamily );
219 begin
220 data.Family:=af;
221 case af of
222 afInet: begin
223 data.inet.port:=ShortHostToNet(cLocalIP4Port);
224 data.inet.addr:=cLocalHostIP4;
225 end;
226 afNil: ;
227 else AbstractError;
228 end;
229 end;
231 procedure t.Clear;
232 begin
233 self.data.family:=afNil;
234 end;
236 function t.isNil:boolean;
237 begin
238 isNil:= self.data.family=afNil;
239 end;
241 operator := ( at : t) aString : string;
242 begin
243 at.ToString( aString );
244 end;
245 operator := ( aString : string) at : t;
246 begin
247 at.FromString( aString );
248 end;
250 operator := (net : Word2) host:word;
251 var pnet:^word;
252 begin
253 pnet:=@net;
254 host:=ShortNetToHost( pnet^ );
255 end;
256 operator := (net : Word4) host:Dword;
257 var pnet:^DWord;
258 begin
259 pnet:=@net;
260 host:=LEtoN( pnet^ );
261 end;
263 operator := (host : word) net:Word2;
264 var pnet:^Word;
265 begin
266 pnet:=@net;
267 pnet^:= ShortHostToNet( host );
268 end;
269 operator := (host : Dword) net:Word4;
270 var pnet:^DWord;
271 begin
272 pnet:=@net;
273 pnet^:=NtoLE( host );
274 end;
276 END.