initial import
[lcore.git] / httpserver_20080306 / lsocket.pas
1 {lsocket.pas}\r
2 \r
3 {socket code by plugwash}\r
4 \r
5 { Copyright (C) 2005 Bas Steendijk and Peter Green\r
6   For conditions of distribution and use, see copyright notice in zlib_license.txt\r
7   which is included in the package\r
8   ----------------------------------------------------------------------------- }\r
9 {\r
10 changes by plugwash (20030728)\r
11 * created handlefdtrigger virtual method in tlasio (overridden in tlsocket) and moved a lot of code from messageloop into it\r
12 * changed tlasio to tlasio\r
13 * split fdhandle into fdhandlein and fdhandleout\r
14 * i now use fdsrmaster and fdswmaster instead of rebuilding the lists every loop\r
15 * split lsocket.pas into lsocket.pas and lcore.pas\r
16 \r
17 \r
18 changes by beware (20030903)\r
19 * added getxaddr, getxport (local addr, port, as string)\r
20 * added getpeername, remote addr+port as binary\r
21 * added htons and htonl functions (endian swap, same interface as windows API)\r
22 \r
23 beware (20030905)\r
24 * if connect failed (conn refused) set state to connected and call internalclose, to get closed handler (instead of fdclose)\r
25 * (lcore) if closing the fd's in internalcose, set fd's to -1 because closing an fd makes it invalid\r
26 \r
27 beware (20030927)\r
28 * fixed: on connect failed, tried to close fdhandle's which were already set to -1, added check\r
29 \r
30 beware (20031017)\r
31 * added getpeeraddr, getpeerport, remote addr+port as string\r
32 }\r
33 \r
34 \r
35 unit lsocket;\r
36 {$ifdef fpc}\r
37   {$mode delphi}\r
38 {$endif}\r
39 interface\r
40   uses\r
41     sysutils,\r
42     {$ifdef win32}\r
43       windows,winsock,\r
44     {$else}\r
45 \r
46       {$ifdef VER1_0}\r
47         linux,\r
48       {$else}\r
49         baseunix,unix,\r
50       {$endif}\r
51       sockets,\r
52     {$endif}\r
53     classes,{pgdebugout,}pgtypes,lcore,fd_utils,binipstuff,dnssync;\r
54 type\r
55   sunB = packed record\r
56     s_b1, s_b2, s_b3, s_b4: byte;\r
57   end;\r
58 \r
59   SunW = packed record\r
60     s_w1, s_w2: word;\r
61   end;\r
62 \r
63   TInAddr = packed record\r
64     case integer of\r
65       0: (S_un_b: SunB);\r
66       1: (S_un_w: SunW);\r
67       2: (S_addr: cardinal);\r
68   end;\r
69   {$ifdef ipv6}\r
70     {$ifdef ver1_0}\r
71       cuint16=word;\r
72       cuint32=dword;\r
73       sa_family_t=word;\r
74 \r
75 \r
76       TInetSockAddr6 = packed Record\r
77         sin6_family   : sa_family_t;\r
78         sin6_port     : cuint16;\r
79         sin6_flowinfo : cuint32;\r
80         sin6_addr     : Tin6_addr;\r
81         sin6_scope_id : cuint32;\r
82       end;\r
83     {$endif}\r
84   {$endif}\r
85   TinetSockAddrv = packed record\r
86     case integer of\r
87       0: (InAddr:TInetSockAddr);\r
88       {$ifdef ipv6}\r
89       1: (InAddr6:TInetSockAddr6);\r
90       {$endif}\r
91   end;\r
92   Pinetsockaddrv = ^Tinetsockaddrv;\r
93 \r
94 \r
95   type\r
96     tsockaddrin=TInetSockAddr;\r
97 \r
98   type\r
99     TLsocket = class(tlasio)\r
100     public\r
101       //a: string;\r
102 \r
103       inAddr             : TInetSockAddrV;\r
104 {      inAddrSize:integer;}\r
105 \r
106       //host               : THostentry      ;\r
107 \r
108       //mainthread         : boolean         ; //for debuggin only\r
109       addr:string;\r
110       port:string;\r
111       localaddr:string;\r
112       localport:string;\r
113       proto:string;\r
114       udp:boolean;\r
115       listenqueue:integer;\r
116       function getaddrsize:integer;\r
117       procedure connect; virtual;\r
118       procedure bindsocket;\r
119       procedure listen;\r
120       function accept : longint;\r
121       function sendto(dest:TInetSockAddr;destlen:integer;data:pointer;len:integer):integer; virtual;\r
122       function receivefrom(data:pointer;len:integer;var src:TInetSockAddr;var srclen:integer):integer; virtual;\r
123       //procedure internalclose(error:word);override;\r
124       procedure handlefdtrigger(readtrigger,writetrigger:boolean); override;\r
125       function send(data:pointer;len:integer):integer;override;\r
126       procedure sendstr(const str : string);override;\r
127       function Receive(Buf:Pointer;BufSize:integer):integer; override;\r
128       function getpeername(var addr:tsockaddrin;addrlen:integer):integer; virtual;\r
129       procedure getXaddrbin(var binip:tbinip); virtual;\r
130       procedure getpeeraddrbin(var binip:tbinip); virtual;\r
131       function getXaddr:string; virtual;\r
132       function getpeeraddr:string; virtual;\r
133       function getXport:string; virtual;\r
134       function getpeerport:string; virtual;\r
135       constructor Create(AOwner: TComponent); override;\r
136       {$ifdef win32}\r
137         procedure myfdclose(fd : integer); override;\r
138         function myfdwrite(fd: LongInt;const buf;size: LongInt):LongInt; override;\r
139         function myfdread(fd: LongInt;var buf;size: LongInt):LongInt; override;\r
140       {$endif}\r
141     end;\r
142     tsocket=longint; // for compatibility with twsocket\r
143 \r
144   twsocket=tlsocket; {easy}\r
145 \r
146 function htons(w:word):word;\r
147 function htonl(i:integer):integer;\r
148 {!!!function longipdns(s:string):longint;}\r
149 \r
150 {$ifdef ipv6}\r
151 const\r
152   v4listendefault:boolean=false;\r
153 {$endif}\r
154 \r
155 \r
156 const\r
157   TCP_NODELAY=1;\r
158   IPPROTO_TCP=6;\r
159 \r
160 implementation\r
161 {$include unixstuff.inc}\r
162 \r
163 function longip(s:string):longint;{$ifdef fpc}inline;{$endif}\r
164 var\r
165   l:longint;\r
166   a,b:integer;\r
167 \r
168 function convertbyte(const s:string):integer;{$ifdef fpc}inline;{$endif}\r
169 begin\r
170   result := strtointdef(s,-1);\r
171   if result < 0 then exit;\r
172   if result > 255 then exit;\r
173 \r
174   {01 exception}\r
175   if (result <> 0) and (s[1] = '0') then begin\r
176     result := -1;\r
177     exit;\r
178   end;\r
179 \r
180   {+1 exception}\r
181   if not (s[1] in ['0'..'9']) then begin\r
182     result := -1;\r
183     exit\r
184   end;\r
185 end;\r
186 \r
187 begin\r
188   result := 0;\r
189   a := pos('.',s);\r
190   if a = 0 then exit;\r
191   b := convertbyte(copy(s,1,a-1));if (b < 0) then exit;\r
192   l := b shl 24;\r
193   s := copy(s,a+1,256);\r
194   a := pos('.',s);\r
195   if a = 0 then exit;\r
196   b := convertbyte(copy(s,1,a-1));if (b < 0) then exit;\r
197   l := l or b shl 16;\r
198   s := copy(s,a+1,256);\r
199   a := pos('.',s);\r
200   if a = 0 then exit;\r
201   b := convertbyte(copy(s,1,a-1));if (b < 0) then exit;\r
202   l := l or b shl 8;\r
203   s := copy(s,a+1,256);\r
204   b := convertbyte(copy(s,1,256));if (b < 0) then exit;\r
205   l := l or b;\r
206   result := l;\r
207 end;\r
208 \r
209 (*!!!\r
210 function longipdns(s:string):longint;\r
211 var\r
212   host : thostentry;\r
213 begin\r
214   if s = '0.0.0.0' then begin\r
215     result := 0;\r
216   end else begin\r
217     result := longip(s);\r
218     if result = 0 then begin\r
219       if gethostbyname(s,host) then begin;\r
220         result := htonl(Longint(Host.Addr));\r
221       end;\r
222       //writeln(inttohex(longint(host.addr),8))\r
223     end;\r
224     if result = 0 then begin\r
225       if resolvehostbyname(s,host) then begin;\r
226         result := htonl(Longint(Host.Addr));\r
227       end;\r
228       //writeln(inttohex(longint(host.addr),8))\r
229     end;\r
230   end;\r
231 end;\r
232 *)\r
233 \r
234 \r
235 function htons(w:word):word;\r
236 begin\r
237   {$ifndef ENDIAN_BIG}\r
238   result := ((w and $ff00) shr 8) or ((w and $ff) shl 8);\r
239   {$else}\r
240   result := w;\r
241   {$endif}\r
242 end;\r
243 \r
244 function htonl(i:integer):integer;\r
245 begin\r
246   {$ifndef ENDIAN_BIG}\r
247   result := (i shr 24) or (i shr 8 and $ff00) or (i shl 8 and $ff0000) or (i shl 24 and $ff000000);\r
248   {$else}\r
249   result := i;\r
250   {$endif}\r
251 end;\r
252 \r
253 function tlsocket.getaddrsize:integer;\r
254 begin\r
255   {$ifdef ipv6}\r
256   if inaddr.inaddr.family = AF_INET6 then result := sizeof(tinetsockaddr6) else\r
257   {$endif}\r
258   result := sizeof(tinetsockaddr);\r
259 end;\r
260 \r
261 function makeinaddrv(addr,port:string;var inaddr:tinetsockaddrv):integer;\r
262 var\r
263   biniptemp:tbinip;\r
264 begin\r
265   result := 0;\r
266   biniptemp := forwardlookup(addr,10);\r
267   fillchar(inaddr,sizeof(inaddr),0);\r
268   //writeln('converted address '+addr+' to binip '+ipbintostr(biniptemp));\r
269   if biniptemp.family = AF_INET then begin\r
270     inAddr.InAddr.family:=AF_INET;\r
271     inAddr.InAddr.port:=htons(strtointdef(port,0));\r
272     inAddr.InAddr.addr:=biniptemp.ip;\r
273     result := sizeof(tinetsockaddr);\r
274   end else\r
275   {$ifdef ipv6}\r
276   if biniptemp.family = AF_INET6 then begin\r
277     inAddr.InAddr6.sin6_family:=AF_INET6;\r
278     inAddr.InAddr6.sin6_port:=htons(strtointdef(port,0));\r
279     inAddr.InAddr6.sin6_addr:=biniptemp.ip6;\r
280     result := sizeof(tinetsockaddr6);\r
281   end else\r
282   {$endif}\r
283   raise esocketexception.create('unable to resolve address: '+addr);\r
284 end;\r
285 \r
286 procedure tlsocket.connect;\r
287 var\r
288   a:integer;\r
289 begin\r
290   if state <> wsclosed then close;\r
291   //prevtime := 0;\r
292   makeinaddrv(addr,port,inaddr);\r
293 \r
294   udp := uppercase(proto) = 'UDP';\r
295   if udp then a := SOCK_DGRAM else a := SOCK_STREAM;\r
296   a := Socket(inaddr.inaddr.family,a,0);\r
297 \r
298   //writeln(ord(inaddr.inaddr.family));\r
299   if a = -1 then begin\r
300     lasterror := {$ifdef win32}getlasterror{$else}socketerror{$endif};\r
301     raise esocketexception.create('unable to create socket');\r
302   end;\r
303   try\r
304     dup(a);\r
305     bindsocket;\r
306     if udp then begin\r
307       {$ifndef win32}\r
308         SetSocketOptions(fdhandleout, SOL_SOCKET, SO_BROADCAST, 'TRUE', Length('TRUE'));\r
309       {$endif}\r
310       state := wsconnected;\r
311       if assigned(onsessionconnected) then onsessionconnected(self,0);\r
312     end else begin\r
313       state :=wsconnecting;\r
314       {$ifdef win32}\r
315         //writeln(inaddr.inaddr.port);\r
316         winsock.Connect(fdhandlein,winsock.psockaddr(@inADDR)^,getaddrsize);\r
317       {$else}\r
318         sockets.Connect(fdhandlein,inADDR,getaddrsize);\r
319       {$endif}\r
320     end;\r
321     eventcore.rmasterset(fdhandlein,false);\r
322     if udp then begin\r
323       eventcore.wmasterclr(fdhandleout);\r
324     end else begin\r
325       eventcore.wmasterset(fdhandleout);\r
326     end;\r
327     //sendq := '';\r
328   except\r
329     on e: exception do begin\r
330       fdcleanup;\r
331       raise; //reraise the exception\r
332     end;\r
333   end;\r
334 end;\r
335 \r
336 procedure tlsocket.sendstr(const str : string);\r
337 begin\r
338   if udp then begin\r
339     send(@str[1],length(str))\r
340   end else begin\r
341     inherited sendstr(str);\r
342   end;\r
343 end;\r
344 \r
345 function tlsocket.send(data:pointer;len:integer):integer;\r
346 begin\r
347   if udp then begin\r
348     //writeln('sending to '+inttohex(inaddr.inaddr.addr,8));\r
349     result := sendto(inaddr.inaddr,getaddrsize,data,len)\r
350 ;\r
351     //writeln('send result',result);\r
352     //writeln('errno',errno);\r
353   end else begin\r
354     result := inherited send(data,len);\r
355   end;\r
356 end;\r
357 \r
358 \r
359 function tlsocket.receive(Buf:Pointer;BufSize:integer):integer;\r
360 begin\r
361   if udp then begin\r
362     result := myfdread(self.fdhandlein,buf^,bufsize);\r
363   end else begin\r
364     result := inherited receive(buf,bufsize);\r
365   end;\r
366 end;\r
367 \r
368 procedure tlsocket.bindsocket;\r
369 var\r
370   a:integer;\r
371   inAddrtemp:TInetSockAddrV;\r
372   inAddrtempx:{$ifdef win32}winsock.TSockaddr{$else}TInetSockAddrV{$endif} absolute inaddrtemp;\r
373   inaddrtempsize:integer;\r
374 begin\r
375   try\r
376     if (localaddr <> '') or (localport <> '') then begin\r
377       if localaddr = '' then begin\r
378         {$ifdef ipv6}\r
379         if inaddr.inaddr.family = AF_INET6 then localaddr := '::' else\r
380         {$endif}\r
381         localaddr := '0.0.0.0';\r
382       end;\r
383       //gethostbyname(localaddr,host);\r
384 \r
385       inaddrtempsize := makeinaddrv(localaddr,localport,inaddrtemp);\r
386 \r
387       If Bind(fdhandlein,inaddrtempx,inaddrtempsize)<> {$ifdef win32}0{$else}true{$endif} Then begin\r
388         state := wsclosed;\r
389         lasterror := {$ifdef win32}getlasterror{$else}socketerror{$endif};\r
390         raise ESocketException.create('unable to bind, error '+inttostr(lasterror));\r
391       end;\r
392       state := wsbound;\r
393     end;\r
394   except\r
395     on e: exception do begin\r
396       fdcleanup;\r
397       raise; //reraise the exception\r
398     end;\r
399   end;\r
400 end;\r
401 \r
402 procedure tlsocket.listen;\r
403 var\r
404   yes:longint;\r
405   socktype:integer;\r
406   biniptemp:tbinip;\r
407   origaddr:string;\r
408 begin\r
409   if state <> wsclosed then close;\r
410   udp := uppercase(proto) = 'UDP';\r
411   if udp then socktype := SOCK_DGRAM else socktype := SOCK_STREAM;\r
412   origaddr := addr;\r
413 \r
414   if addr = '' then begin\r
415     {$ifdef ipv6}\r
416     if not v4listendefault then begin\r
417       addr := '::';\r
418     end else\r
419     {$endif}\r
420     addr := '0.0.0.0';\r
421   end;\r
422   biniptemp := forwardlookup(addr,10);\r
423   addr := ipbintostr(biniptemp);\r
424   fdhandlein := socket(biniptemp.family,socktype,0);\r
425   {$ifdef ipv6}\r
426   if (addr = '::') and (origaddr = '') and (fdhandlein < 0) then begin\r
427     addr := '0.0.0.0';\r
428     fdhandlein := socket(AF_INET,socktype,0);\r
429   end;\r
430   {$endif}\r
431   if fdhandlein = -1 then raise ESocketException.create('unable to create socket');\r
432   dupnowatch(fdhandlein); // sets up maxs and copies handle to fdhandleout among other things\r
433   //eventcore.setfdreverse(fdhandlein,self); //already taken care of by dup\r
434   state := wsclosed; // then set this back as it was an undesired side effect of dup\r
435 \r
436   try\r
437     yes := $01010101;  {Copied this from existing code. Value is empiric,\r
438                     but works. (yes=true<>0) }\r
439     {$ifndef win32}\r
440       if SetSocketOptions(fdhandlein, SOL_SOCKET, SO_REUSEADDR,yes,sizeof(yes))=-1 then begin\r
441         raise ESocketException.create('unable to set socket options');\r
442       end;\r
443     {$endif}\r
444     localaddr := addr;\r
445     localport := port;\r
446     bindsocket;\r
447 \r
448     if not udp then begin\r
449       {!!! allow custom queue length? default 5}\r
450       if listenqueue = 0 then listenqueue := 5;\r
451       If {$ifdef win32}winsock{$else}sockets{$endif}.Listen(fdhandlein,listenqueue)<>{$ifdef win32}0{$else}true{$endif} Then raise esocketexception.create('unable to listen');\r
452       state := wsListening;\r
453     end else begin\r
454       {$ifndef win32}\r
455         SetSocketOptions(fdhandleout, SOL_SOCKET, SO_BROADCAST, 'TRUE', Length('TRUE'));\r
456       {$endif}\r
457       state := wsconnected;\r
458     end;\r
459   finally\r
460     if state = wsclosed then begin\r
461       if fdhandlein >= 0 then begin\r
462         {one *can* get here without fd -beware}\r
463         eventcore.rmasterclr(fdhandlein);\r
464         myfdclose(fdhandlein); // we musnt leak file discriptors\r
465         eventcore.setfdreverse(fdhandlein,nil);\r
466         fdhandlein := -1;\r
467       end;\r
468     end else begin\r
469       eventcore.rmasterset(fdhandlein,true);\r
470     end;\r
471     if fdhandleout >= 0 then eventcore.wmasterclr(fdhandleout);\r
472   end;\r
473   //writeln('listened on addr '+addr+':'+port+' '+proto+' using socket number ',fdhandlein); \r
474 end;\r
475 \r
476 function tlsocket.accept : longint;\r
477 var\r
478   FromAddrSize     : LongInt;        // i don't realy know what to do with these at this\r
479   FromAddr         : TInetSockAddrV;  // at this point time will tell :)\r
480 begin\r
481 \r
482   FromAddrSize := Sizeof(FromAddr);\r
483   {$ifdef win32}\r
484     result := winsock.accept(fdhandlein,@fromaddr,@fromaddrsize);\r
485   {$else}\r
486     result := sockets.accept(fdhandlein,fromaddr,fromaddrsize);\r
487   {$endif}\r
488   //now we have accepted one request start monitoring for more again\r
489   eventcore.rmasterset(fdhandlein,true);\r
490 \r
491   if result = -1 then raise esocketexception.create('error '+inttostr({$ifdef win32}getlasterror{$else}socketerror{$endif})+' while accepting');\r
492   if result > absoloutemaxs then begin\r
493     myfdclose(result);\r
494     result := -1;\r
495     raise esocketexception.create('file discriptor out of range');\r
496   end;\r
497 end;\r
498 \r
499 function tlsocket.sendto(dest:TInetSockAddr;destlen:integer;data:pointer;len:integer):integer;\r
500 var\r
501   destx : {$ifdef win32}winsock.TSockAddr{$else}TInetSockAddr{$endif} absolute dest;\r
502 begin\r
503   result := {$ifdef win32}winsock{$else}sockets{$endif}.sendto(self.fdhandleout,data^,len,0,destx,destlen);\r
504 end;\r
505 \r
506 function tlsocket.receivefrom(data:pointer;len:integer;var src:TInetSockAddr;var srclen:integer):integer;\r
507 var\r
508   srcx : {$ifdef win32}winsock.TSockAddr{$else}TInetSockAddr{$endif} absolute src;\r
509 begin\r
510   result := {$ifdef win32}winsock{$else}sockets{$endif}.recvfrom(self.fdhandlein,data^,len,0,srcx,srclen);\r
511 end;\r
512 \r
513 procedure tlsocket.handlefdtrigger(readtrigger,writetrigger:boolean);\r
514 var\r
515   tempbuf:array[0..receivebufsize-1] of byte;\r
516 begin\r
517   //writeln('got a fd trigger, readtrigger=',readtrigger,' writetrigger=',writetrigger);\r
518   if (state =wslistening) and readtrigger then begin\r
519 {    debugout('listening socket triggered on read');}\r
520     eventcore.rmasterclr(fdhandlein);\r
521     if assigned(onsessionAvailable) then onsessionAvailable(self,0);\r
522   end;\r
523   if udp and readtrigger then begin\r
524     if assigned(ondataAvailable) then ondataAvailable(self,0);\r
525     {!!!test}\r
526     exit;\r
527   end;\r
528   if (state =wsconnecting) and writetrigger then begin\r
529     // code for dealing with the reults of a non-blocking connect is\r
530     // rather complex\r
531     // if just write is triggered it means connect suceeded\r
532     // if both read and write are triggered it can mean 2 things\r
533     // 1: connect ok and data availible\r
534     // 2: connect fail\r
535     // to find out which you must read from the socket and look for errors\r
536     // there if we read successfully we drop through into the code for fireing\r
537     // the read event\r
538     if not readtrigger then begin\r
539       state := wsconnected;\r
540       if assigned(onsessionconnected) then onsessionconnected(self,0);\r
541     end else begin\r
542       numread := myfdread(fdhandlein,tempbuf,sizeof(tempbuf));\r
543       if numread <> -1 then begin\r
544         state := wsconnected;\r
545         if assigned(onsessionconnected) then onsessionconnected(self,0);\r
546         //connectread := true;\r
547         recvq.add(@tempbuf,numread);\r
548       end else begin\r
549         state := wsconnected;\r
550         if assigned(onsessionconnected) then onsessionconnected(self,{$ifdef win32}wsagetlasterror{$else}linuxerror{$endif});\r
551 {        debugout('connect fail');}\r
552         self.internalclose(0);\r
553         recvq.del(maxlongint);\r
554       end;\r
555       // if things went well here we are now in the state wsconnected with data sitting in our receive buffer\r
556       // so we drop down into the processing for data availible\r
557     end;\r
558     if fdhandlein >= 0 then begin\r
559       if state = wsconnected then begin\r
560         eventcore.rmasterset(fdhandlein,false);\r
561       end else begin\r
562         eventcore.rmasterclr(fdhandlein);\r
563       end;\r
564     end;\r
565     if fdhandleout >= 0 then begin\r
566       if sendq.size = 0 then begin\r
567         //don't clear the bit in fdswmaster if data is in the sendq\r
568         eventcore.wmasterclr(fdhandleout);\r
569       end;\r
570     end;\r
571 \r
572   end;\r
573   inherited handlefdtrigger(readtrigger,writetrigger);\r
574 end;\r
575 \r
576 constructor tlsocket.Create(AOwner: TComponent);\r
577 begin\r
578   inherited create(aowner);\r
579   closehandles := true;\r
580 end;\r
581 \r
582 \r
583 function tlsocket.getpeername(var addr:tsockaddrin;addrlen:integer):integer;\r
584 var\r
585   addrx : {$ifdef win32}winsock.tsockaddr{$else}tsockaddrin{$endif} absolute addr;\r
586 begin\r
587   result := {$ifdef win32}winsock{$else}sockets{$endif}.getpeername(self.fdhandlein,addrx,addrlen);\r
588 end;\r
589 \r
590 procedure tlsocket.getxaddrbin(var binip:tbinip);\r
591 var\r
592   addr:tinetsockaddrv;\r
593   i:integer;\r
594 begin\r
595   i := sizeof(addr);\r
596   fillchar(addr,sizeof(addr),0);\r
597 \r
598   {$ifdef win32}\r
599     winsock.getsockname(self.fdhandlein,psockaddr(@addr)^,i);\r
600   {$else}\r
601     sockets.getsocketname(self.fdhandlein,addr,i);\r
602   {$endif}\r
603   binip.family := addr.inaddr.family;\r
604   {$ifdef ipv6}\r
605   if addr.inaddr6.sin6_family = AF_INET6 then begin\r
606     binip.ip6 := addr.inaddr6.sin6_addr;\r
607   end else\r
608   {$endif}\r
609   begin\r
610     binip.ip := addr.inaddr.addr;\r
611   end;\r
612   converttov4(binip);\r
613 end;\r
614 \r
615 procedure tlsocket.getpeeraddrbin(var binip:tbinip);\r
616 var\r
617   addr:tinetsockaddrv;\r
618   i:integer;\r
619 begin\r
620   i := sizeof(addr);\r
621   fillchar(addr,sizeof(addr),0);\r
622   {$ifdef win32}\r
623     winsock.getpeername(self.fdhandlein,psockaddr(@addr)^,i);\r
624   {$else}\r
625     sockets.getpeername(self.fdhandlein,addr,i);\r
626   {$endif}\r
627 \r
628   binip.family := addr.inaddr.family;\r
629   {$ifdef ipv6}\r
630   if addr.inaddr6.sin6_family = AF_INET6 then begin\r
631     binip.ip6 := addr.inaddr6.sin6_addr;\r
632   end else\r
633   {$endif}\r
634   begin\r
635     binip.ip := addr.inaddr.addr;\r
636   end;\r
637   converttov4(binip);\r
638 end;\r
639 \r
640 function tlsocket.getXaddr:string;\r
641 var\r
642   biniptemp:tbinip;\r
643 begin\r
644   getxaddrbin(biniptemp);\r
645   result := ipbintostr(biniptemp);\r
646   if result = '' then result := 'error';\r
647 end;\r
648 \r
649 function tlsocket.getpeeraddr:string;\r
650 var\r
651   biniptemp:tbinip;\r
652 begin\r
653   getpeeraddrbin(biniptemp);\r
654   result := ipbintostr(biniptemp);\r
655   if result = '' then result := 'error';\r
656 end;\r
657 \r
658 function tlsocket.getXport:string;\r
659 var\r
660   addr:{$ifdef win32}winsock.tsockaddr{$else}tinetsockaddr{$endif};\r
661   i:integer;\r
662 begin\r
663   i := sizeof(addr);\r
664   {$ifdef win32}\r
665     winsock.getsockname(self.fdhandlein,addr,i);\r
666     i := htons(addr.sin_port);\r
667   {$else}\r
668     sockets.getsocketname(self.fdhandlein,addr,i);\r
669     i := htons(addr.port);\r
670   {$endif}\r
671   result := inttostr(i);\r
672 end;\r
673 \r
674 function tlsocket.getpeerport:string;\r
675 var\r
676   addr:{$ifdef win32}winsock.tsockaddr{$else}tinetsockaddr{$endif};\r
677   i:integer;\r
678 begin\r
679   i := sizeof(addr);\r
680   {$ifdef win32}\r
681     winsock.getpeername(self.fdhandlein,addr,i);\r
682     i := htons(addr.sin_port);\r
683   {$else}\r
684     sockets.getpeername(self.fdhandlein,addr,i);\r
685     i := htons(addr.port);\r
686   {$endif}\r
687   result := inttostr(i);\r
688 end;\r
689 \r
690 {$ifdef win32}\r
691   procedure tlsocket.myfdclose(fd : integer);\r
692   begin\r
693     closesocket(fd);\r
694   end;\r
695   function tlsocket.myfdwrite(fd: LongInt;const buf;size: LongInt):LongInt;\r
696   begin\r
697     result := winsock.send(fd,(@buf)^,size,0);\r
698   end;\r
699   function tlsocket.myfdread(fd: LongInt;var buf;size: LongInt):LongInt;\r
700   begin\r
701     result := winsock.recv(fd,buf,size,0);\r
702   end;\r
703 {$endif}\r
704
705 end.\r
706 \r