sockets.inc 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {******************************************************************************
  12. Text File Writeln/ReadLn Support
  13. ******************************************************************************}
  14. Procedure OpenSock(var F:Text);
  15. begin
  16. if textrec(f).handle=UnusedHandle then
  17. textrec(f).mode:=fmclosed
  18. else
  19. case textrec(f).userdata[1] of
  20. S_OUT : textrec(f).mode:=fmoutput;
  21. S_IN : textrec(f).mode:=fminput;
  22. else
  23. textrec(f).mode:=fmclosed;
  24. end;
  25. end;
  26. Procedure IOSock(var F:text);
  27. begin
  28. case textrec(f).mode of
  29. fmoutput : {$ifdef unix}fpWrite{$else}fdwrite{$endif}(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufpos);
  30. fminput : textrec(f).BufEnd:={$ifdef Unix}fpRead{$else}fdread{$endif}(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufsize);
  31. end;
  32. textrec(f).bufpos:=0;
  33. end;
  34. Procedure FlushSock(var F:Text);
  35. begin
  36. if (textrec(f).mode=fmoutput) and (textrec(f).bufpos<>0) then
  37. begin
  38. IOSock(f);
  39. textrec(f).bufpos:=0;
  40. end;
  41. end;
  42. Procedure CloseSock(var F:text);
  43. begin
  44. { Nothing special has to be done here }
  45. end;
  46. Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
  47. {
  48. Set up two Pascal Text file descriptors for reading and writing)
  49. }
  50. begin
  51. { First the reading part.}
  52. Assign(SockIn,'.');
  53. Textrec(SockIn).Handle:=Sock;
  54. Textrec(Sockin).userdata[1]:=S_IN;
  55. TextRec(SockIn).OpenFunc:=@OpenSock;
  56. TextRec(SockIn).InOutFunc:=@IOSock;
  57. TextRec(SockIn).FlushFunc:=@FlushSock;
  58. TextRec(SockIn).CloseFunc:=@CloseSock;
  59. TextRec(SockIn).Mode := fmInput;
  60. { Now the writing part. }
  61. Assign(SockOut,'.');
  62. Textrec(SockOut).Handle:=Sock;
  63. Textrec(SockOut).userdata[1]:=S_OUT;
  64. TextRec(SockOut).OpenFunc:=@OpenSock;
  65. TextRec(SockOut).InOutFunc:=@IOSock;
  66. TextRec(SockOut).FlushFunc:=@FlushSock;
  67. TextRec(SockOut).CloseFunc:=@CloseSock;
  68. TextRec(SockOut).Mode := fmOutput;
  69. end;
  70. {******************************************************************************
  71. Untyped File
  72. ******************************************************************************}
  73. Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
  74. begin
  75. {Input}
  76. Assign(SockIn,'.');
  77. FileRec(SockIn).Handle:=Sock;
  78. FileRec(SockIn).RecSize:=1;
  79. FileRec(Sockin).userdata[1]:=S_IN;
  80. FileRec(SockIn).Mode := fmInput;
  81. {Output}
  82. Assign(SockOut,'.');
  83. FileRec(SockOut).Handle:=Sock;
  84. FileRec(SockOut).RecSize:=1;
  85. FileRec(SockOut).userdata[1]:=S_OUT;
  86. FileRec(SockOut).Mode := fmOutput;
  87. end;
  88. {******************************************************************************
  89. InetSock
  90. ******************************************************************************}
  91. Function DoAccept(Sock:longint;Var addr:TInetSockAddr):longint;
  92. Var AddrLen : Longint;
  93. begin
  94. AddrLEn:=SizeOf(Addr);
  95. DoAccept:=Accept(Sock,Addr,AddrLen);
  96. end;
  97. Function DoConnect(Sock:longint;const addr: TInetSockAddr): Boolean;
  98. begin
  99. DoConnect:=Connect(Sock,Addr,SizeOF(TInetSockAddr));
  100. end;
  101. Function Connect(Sock:longint;const addr: TInetSockAddr;var SockIn,SockOut:text):Boolean;
  102. begin
  103. Connect:=DoConnect(Sock,addr);
  104. If Connect then
  105. Sock2Text(Sock,SockIn,SockOut);
  106. end;
  107. Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
  108. begin
  109. Connect:=DoConnect(Sock,addr);
  110. If Connect then
  111. Sock2File(Sock,SockIn,SockOut);
  112. end;
  113. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
  114. var
  115. s : longint;
  116. begin
  117. S:=DoAccept(Sock,addr);
  118. if S>0 then
  119. begin
  120. Sock2Text(S,SockIn,SockOut);
  121. Accept:=true;
  122. end
  123. else
  124. Accept:=false;
  125. end;
  126. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
  127. var
  128. s : longint;
  129. begin
  130. S:=DoAccept(Sock,addr);
  131. if S>0 then
  132. begin
  133. Sock2File(S,SockIn,SockOut);
  134. Accept:=true;
  135. end
  136. else
  137. Accept:=false;
  138. end;
  139. type thostaddr= packed array[1..4] of byte;
  140. function htonl( host : longint):longint; {$ifdef HASINLINE} inline; {$ENDIF}
  141. begin
  142. {$ifdef FPC_BIG_ENDIAN}
  143. htonl:=host;
  144. {$else}
  145. htonl:=THostAddr(host)[4];
  146. htonl:=htonl or ( (THostAddr(host)[3]) shl 8);
  147. htonl:=htonl or ( (THostAddr(host)[2]) shl 16);
  148. htonl:=htonl or ( (THostAddr(host)[1]) shl 24);
  149. {$endif}
  150. end;
  151. Function NToHl (Net : Longint) : Longint; {$ifdef HASINLINE} inline; {$ENDIF}
  152. begin
  153. {$ifdef FPC_BIG_ENDIAN}
  154. ntohl:=net;
  155. {$else}
  156. ntohl:=THostAddr(Net)[4];
  157. ntohl:=ntohl or ( (THostAddr(Net)[3]) shl 8);
  158. ntohl:=ntohl or ( (THostAddr(Net)[2]) shl 16);
  159. ntohl:=ntohl or ( (THostAddr(Net)[1]) shl 24);
  160. {$endif}
  161. end;
  162. function htons( host : word):word; {$ifdef HASINLINE} inline; {$ENDIF}
  163. begin
  164. {$ifdef FPC_BIG_ENDIAN}
  165. htons:=host;
  166. {$else}
  167. htons:=swap(host);
  168. {$endif}
  169. end;
  170. Function NToHs (Net : word):word;{$ifdef HASINLINE} inline; {$ENDIF}
  171. begin
  172. {$ifdef FPC_BIG_ENDIAN}
  173. ntohs:=net;
  174. {$else}
  175. ntohs:=swap(net);
  176. {$endif}
  177. end;
  178. Type array4int = array[1..4] of byte;
  179. function NetAddrToStr (Entry : in_addr) : AnsiString;
  180. Var Dummy : Ansistring;
  181. i,j : Longint;
  182. begin
  183. NetAddrToStr:='';
  184. j:=entry.s_addr;
  185. For I:=1 to 4 do
  186. begin
  187. Str(array4int(j)[i],Dummy);
  188. NetAddrToStr:=NetAddrToStr+Dummy;
  189. If I<4 Then
  190. NetAddrToStr:=NetAddrToStr+'.';
  191. end;
  192. end;
  193. function HostAddrToStr (Entry : in_addr) : AnsiString;
  194. Var x: in_addr;
  195. begin
  196. x.s_addr:=htonl(entry.s_addr);
  197. HostAddrToStr:=NetAddrToStr(x);
  198. end;
  199. function StrToHostAddr(IP : AnsiString) : in_addr ;
  200. Var
  201. Dummy : AnsiString;
  202. I,j,k : Longint;
  203. Temp : in_addr;
  204. begin
  205. strtohostaddr.s_addr:=0; //:=NoAddress;
  206. For I:=1 to 4 do
  207. begin
  208. If I<4 Then
  209. begin
  210. J:=Pos('.',IP);
  211. If J=0 then
  212. exit;
  213. Dummy:=Copy(IP,1,J-1);
  214. Delete (IP,1,J);
  215. end
  216. else
  217. Dummy:=IP;
  218. Val (Dummy,k,J);
  219. array4int(temp.s_addr)[i]:=k;
  220. If J<>0 then Exit;
  221. end;
  222. strtohostaddr.s_addr:=ntohl(Temp.s_addr);
  223. end;
  224. function StrToNetAddr(IP : AnsiString) : in_addr;
  225. begin
  226. StrToNetAddr.s_addr:=htonl(StrToHostAddr(IP).s_addr);
  227. end;
  228. Function HostToNet (Host : in_addr):in_addr;
  229. begin
  230. HostToNet.s_addr:=htonl(host.s_addr);
  231. end;
  232. Function NetToHost (Net : in_addr) : in_addr;
  233. begin
  234. NetToHost.s_addr:=ntohl(net.s_addr);
  235. end;
  236. Function HostToNet (Host : Longint) : Longint;
  237. begin
  238. HostToNet:=htonl(host);
  239. end;
  240. Function NetToHost (Net : Longint) : Longint;
  241. begin
  242. NetToHost:=ntohl(net);
  243. end;
  244. Function ShortHostToNet (Host : Word) : Word;
  245. begin
  246. ShortHostToNet:=htons(host);
  247. end;
  248. Function ShortNetToHost (Net : Word) : Word;
  249. begin
  250. ShortNEtToHost:=ntohs(net);
  251. end;
  252. const digittab : shortstring = ('0123456789ABCDEF');
  253. function lclinttohex (i:integer;digits:longint): ansistring;
  254. var j,k : integer;
  255. begin
  256. SetLength(lclinttohex,4);
  257. lclinttohex[4]:=digittab[1+(i and 15)];
  258. lclinttohex[3]:=digittab[1+((i shr 4) and 15)];
  259. lclinttohex[2]:=digittab[1+((i shr 8) and 15)];
  260. lclinttohex[1]:=digittab[1+((i shr 12) and 15)];;
  261. end;
  262. function HostAddrToStr6 (Entry : TIn6_Addr) :ansiString;
  263. var
  264. i: byte;
  265. zr1,zr2: set of byte;
  266. zc1,zc2: byte;
  267. have_skipped: boolean;
  268. begin
  269. zr1 := [];
  270. zr2 := [];
  271. zc1 := 0;
  272. zc2 := 0;
  273. for i := 0 to 7 do begin
  274. if Entry.u6_addr16[i] = 0 then begin
  275. include(zr2, i);
  276. inc(zc2);
  277. end else begin
  278. if zc1 < zc2 then begin
  279. zc1 := zc2;
  280. zr1 := zr2;
  281. zc2 := 0; zr2 := [];
  282. end;
  283. end;
  284. end;
  285. if zc1 < zc2 then begin
  286. zc1 := zc2;
  287. zr1 := zr2;
  288. end;
  289. SetLength(HostAddrToStr6, 8*5-1);
  290. SetLength(HostAddrToStr6, 0);
  291. have_skipped := false;
  292. for i := 0 to 7 do begin
  293. if not (i in zr1) then begin
  294. if have_skipped then begin
  295. if HostAddrToStr6 = ''
  296. then HostAddrToStr6 := '::'
  297. else HostAddrToStr6 := HostAddrToStr6 + ':';
  298. have_skipped := false;
  299. end;
  300. // FIXME: is that shortnettohost really proper there? I wouldn't be too sure...
  301. HostAddrToStr6 := HostAddrToStr6 +lclIntToHex(ShortNetToHost(Entry.u6_addr16[i]), 1) + ':';
  302. end else begin
  303. have_skipped := true;
  304. end;
  305. end;
  306. if have_skipped then
  307. if HostAddrToStr6 = ''
  308. then HostAddrToStr6 := '::'
  309. else HostAddrToStr6 := HostAddrToStr6 + ':';
  310. if HostAddrToStr6 = '' then HostAddrToStr6 := '::';
  311. if not (7 in zr1) then
  312. SetLength(HostAddrToStr6, Length(HostAddrToStr6)-1);
  313. end;
  314. function StrToHostAddr6(IP : String) : TIn6_addr;
  315. begin
  316. end;
  317. function NetAddrToStr6 (Entry : TIn6_Addr) : ansiString;
  318. begin
  319. netaddrtostr6 := HostAddrToStr6((Entry));
  320. end;
  321. function StrToNetAddr6(IP : ansiString) : TIn6_Addr;
  322. begin
  323. StrToNetAddr6 := StrToHostAddr6(IP);
  324. end;
  325. {
  326. $Log$
  327. Revision 1.17 2005-03-18 10:04:31 marco
  328. * cosmetic fix in netaddrtostr
  329. Revision 1.16 2005/02/14 17:13:26 peter
  330. * truncate log
  331. Revision 1.15 2005/02/13 19:59:57 marco
  332. * More htons like functionality. IPV6 string support still missing
  333. }