sockets.inc 10 KB

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