/[lcore]/trunk/lsocket.pas
ViewVC logotype

Annotation of /trunk/lsocket.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Fri Mar 28 02:26:58 2008 UTC (11 years, 10 months ago) by plugwash
File size: 20592 byte(s)
initial import

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

Properties

Name Value
svn:executable

No admin address has been configured">No admin address has been configured
ViewVC Help
Powered by ViewVC 1.1.22