sockets.pp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1993,97 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. unit Sockets;
  12. Interface
  13. Const
  14. { Socket Types }
  15. SOCK_STREAM = 1; { stream (connection) socket }
  16. SOCK_DGRAM = 2; { datagram (conn.less) socket }
  17. SOCK_RAW = 3; { raw socket }
  18. SOCK_RDM = 4; { reliably-delivered message }
  19. SOCK_SEQPACKET = 5; { sequential packet socket }
  20. SOCK_PACKET =10;
  21. { Adress families }
  22. AF_UNSPEC = 0;
  23. AF_UNIX = 1; { Unix domain sockets }
  24. AF_INET = 2; { Internet IP Protocol }
  25. AF_AX25 = 3; { Amateur Radio AX.25 }
  26. AF_IPX = 4; { Novell IPX }
  27. AF_APPLETALK = 5; { Appletalk DDP }
  28. AF_NETROM = 6; { Amateur radio NetROM }
  29. AF_BRIDGE = 7; { Multiprotocol bridge }
  30. AF_AAL5 = 8; { Reserved for Werner's ATM }
  31. AF_X25 = 9; { Reserved for X.25 project }
  32. AF_INET6 = 10; { IP version 6 }
  33. AF_MAX = 12;
  34. { Protocol Families }
  35. PF_UNSPEC = AF_UNSPEC;
  36. PF_UNIX = AF_UNIX;
  37. PF_INET = AF_INET;
  38. PF_AX25 = AF_AX25;
  39. PF_IPX = AF_IPX;
  40. PF_APPLETALK = AF_APPLETALK;
  41. PF_NETROM = AF_NETROM;
  42. PF_BRIDGE = AF_BRIDGE;
  43. PF_AAL5 = AF_AAL5;
  44. PF_X25 = AF_X25;
  45. PF_INET6 = AF_INET6;
  46. PF_MAX = AF_MAX;
  47. const
  48. { Two constants to determine whether part of soket is for in or output }
  49. S_IN = 0;
  50. S_OUT = 1;
  51. Type
  52. TSockAddr = packed Record
  53. family:word; { was byte, fixed }
  54. data :array [0..13] of char;
  55. end;
  56. TUnixSockAddr = packed Record
  57. family:word; { was byte, fixed }
  58. path:array[0..108] of char;
  59. end;
  60. TInetSockAddr = packed Record
  61. family:Word;
  62. port :Word;
  63. addr :Cardinal;
  64. pad :array [1..8] of byte; { to get to the size of sockaddr... }
  65. end;
  66. TSockArray = Array[1..2] of Longint;
  67. Var
  68. SocketError:Longint;
  69. {Basic Socket Functions}
  70. Function Socket(Domain,SocketType,Protocol:Longint):Longint;
  71. Function Send(Sock:Longint;Var Addr;AddrLen,Flags:Longint):Longint;
  72. Function Recv(Sock:Longint;Var Addr;AddrLen,Flags:Longint):Longint;
  73. Function Bind(Sock:Longint;Var Addr;AddrLen:Longint):Boolean;
  74. Function Listen (Sock,MaxConnect:Longint):Boolean;
  75. Function Accept(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  76. Function Connect(Sock:Longint;Var Addr;Addrlen:Longint):Longint;
  77. Function Shutdown(Sock:Longint;How:Longint):Longint;
  78. Function GetSocketName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  79. Function GetPeerName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  80. Function SetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  81. Function GetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  82. Function SocketPair(Domain,SocketType,Protocol:Longint;var Pair:TSockArray):Longint;
  83. {Text Support}
  84. Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
  85. {Untyped File Support}
  86. Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
  87. {Better Pascal Calling, Overloaded Functions!}
  88. Procedure Str2UnixSockAddr(const addr:string;var t:TUnixSockAddr;var len:longint);
  89. Function Bind(Sock:longint;const addr:string):boolean;
  90. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
  91. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
  92. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
  93. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
  94. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
  95. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
  96. Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
  97. Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
  98. Implementation
  99. Uses Linux;
  100. { Include filerec and textrec structures }
  101. {$i filerec.inc}
  102. {$i textrec.inc}
  103. {******************************************************************************
  104. Kernel Socket Callings
  105. ******************************************************************************}
  106. Const
  107. {
  108. Arguments to the Linux Kernel system call for sockets. All
  109. Socket Connected calls go through the same system call,
  110. with an extra argument to determine what action to take.
  111. }
  112. Socket_Sys_SOCKET = 1;
  113. Socket_Sys_BIND = 2;
  114. Socket_Sys_CONNECT = 3;
  115. Socket_Sys_LISTEN = 4;
  116. Socket_Sys_ACCEPT = 5;
  117. Socket_Sys_GETSOCKNAME = 6;
  118. Socket_Sys_GETPEERNAME = 7;
  119. Socket_Sys_SOCKETPAIR = 8;
  120. Socket_Sys_SEND = 9;
  121. Socket_Sys_RECV = 10;
  122. Socket_Sys_SENDTO = 11;
  123. Socket_Sys_RECVFROM = 12;
  124. Socket_Sys_SHUTDOWN = 13;
  125. Socket_Sys_SETSOCKOPT = 14;
  126. Socket_Sys_GETSOCKOPT = 15;
  127. Socket_Sys_SENDMSG = 16;
  128. Socket_Sys_RECVMSG = 17;
  129. Function SocketCall(SockCallNr,a1,a2,a3,a4,a5,a6:longint):longint;
  130. var
  131. Regs:SysCallRegs;
  132. Args:array[1..6] of longint;
  133. begin
  134. args[1]:=a1;
  135. args[2]:=a2;
  136. args[3]:=a3;
  137. args[4]:=a4;
  138. args[5]:=a5;
  139. args[6]:=a6;
  140. regs.reg2:=SockCallNr;
  141. regs.reg3:=Longint(@args);
  142. SocketCall:=Syscall(syscall_nr_socketcall,regs);
  143. If SocketCall<0 then
  144. SocketError:=Errno
  145. else
  146. SocketError:=0;
  147. end;
  148. Function SocketCall(SockCallNr,a1,a2,a3:longint):longint;
  149. begin
  150. SocketCall:=SocketCall(SockCallNr,a1,a2,a3,0,0,0);
  151. end;
  152. {******************************************************************************
  153. Basic Socket Functions
  154. ******************************************************************************}
  155. Function socket(Domain,SocketType,Protocol:Longint):Longint;
  156. begin
  157. Socket:=SocketCall(Socket_Sys_Socket,Domain,SocketType,ProtoCol);
  158. end;
  159. Function Send(Sock:Longint;Var Addr;AddrLen,Flags:Longint):Longint;
  160. begin
  161. Send:=SocketCall(Socket_Sys_Send,Sock,Longint(@Addr),AddrLen,Flags,0,0);
  162. end;
  163. Function Recv(Sock:Longint;Var Addr;AddrLen,Flags:Longint):Longint;
  164. begin
  165. Recv:=SocketCall(Socket_Sys_Recv,Sock,Longint(@Addr),AddrLen,Flags,0,0);
  166. end;
  167. Function Bind(Sock:Longint;Var Addr;AddrLen:Longint):Boolean;
  168. begin
  169. Bind:=(SocketCall(Socket_Sys_Bind,Sock,Longint(@Addr),AddrLen)=0);
  170. end;
  171. Function Listen(Sock,MaxConnect:Longint):Boolean;
  172. begin
  173. Listen:=(SocketCall(Socket_Sys_Listen,Sock,MaxConnect,0)=0);
  174. end;
  175. Function Accept(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  176. begin
  177. Accept:=SocketCall(Socket_Sys_Accept,Sock,longint(@Addr),longint(@AddrLen));
  178. If Accept<0 Then
  179. Accept:=-1;
  180. end;
  181. Function Connect(Sock:Longint;Var Addr;Addrlen:Longint):Longint;
  182. begin
  183. Connect:=SocketCall(Socket_Sys_Connect,Sock,longint(@Addr),AddrLen);
  184. If Connect<0 Then
  185. Connect:=-1;
  186. end;
  187. Function Shutdown(Sock:Longint;How:Longint):Longint;
  188. begin
  189. ShutDown:=SocketCall(Socket_Sys_ShutDown,Sock,How,0);
  190. end;
  191. Function GetSocketName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  192. begin
  193. GetSocketName:=SocketCall(Socket_Sys_GetSockName,Sock,longint(@Addr),longint(@AddrLen));
  194. end;
  195. Function GetPeerName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  196. begin
  197. GetPeerName:=SocketCall(Socket_Sys_GetPeerName,Sock,longint(@Addr),longint(@AddrLen));
  198. end;
  199. Function SetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  200. begin
  201. SetSocketOptions:=SocketCall(Socket_Sys_SetSockOpt,Sock,Level,OptName,Longint(@OptVal),OptLen,0);
  202. end;
  203. Function GetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  204. begin
  205. GetSocketOptions:=SocketCall(Socket_Sys_GetSockOpt,Sock,Level,OptName,Longint(@OptVal),OptLen,0);
  206. end;
  207. Function SocketPair(Domain,SocketType,Protocol:Longint;var Pair:TSockArray):Longint;
  208. begin
  209. SocketPair:=SocketCall(Socket_Sys_SocketPair,Domain,SocketType,Protocol,longint(@Pair),0,0);
  210. end;
  211. {******************************************************************************
  212. Text File Writeln/ReadLn Support
  213. ******************************************************************************}
  214. Procedure OpenSock(var F:Text);
  215. begin
  216. if textrec(f).handle=UnusedHandle then
  217. textrec(f).mode:=fmclosed
  218. else
  219. case textrec(f).userdata[1] of
  220. S_OUT : textrec(f).mode:=fmoutput;
  221. S_IN : textrec(f).mode:=fminput;
  222. else
  223. textrec(f).mode:=fmclosed;
  224. end;
  225. end;
  226. Procedure IOSock(var F:text);
  227. begin
  228. case textrec(f).mode of
  229. fmoutput : fdWrite(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufpos);
  230. fminput : textrec(f).BufEnd:=fdRead(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufsize);
  231. end;
  232. textrec(f).bufpos:=0;
  233. end;
  234. Procedure FlushSock(var F:Text);
  235. begin
  236. if (textrec(f).mode=fmoutput) and (textrec(f).bufpos<>0) then
  237. IOSock(f);
  238. textrec(f).bufpos:=0;
  239. end;
  240. Procedure CloseSock(var F:text);
  241. begin
  242. Close(f);
  243. end;
  244. Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
  245. {
  246. Set up two Pascal Text file descriptors for reading and writing)
  247. }
  248. begin
  249. { First the reading part.}
  250. Assign(SockIn,'.');
  251. Textrec(SockIn).Handle:=Sock;
  252. Textrec(Sockin).userdata[1]:=S_IN;
  253. TextRec(SockIn).OpenFunc:=@OpenSock;
  254. TextRec(SockIn).InOutFunc:=@IOSock;
  255. TextRec(SockIn).FlushFunc:=@FlushSock;
  256. TextRec(SockIn).CloseFunc:=@CloseSock;
  257. { Now the writing part. }
  258. Assign(SockOut,'.');
  259. Textrec(SockOut).Handle:=Sock;
  260. Textrec(SockOut).userdata[1]:=S_OUT;
  261. TextRec(SockOut).OpenFunc:=@OpenSock;
  262. TextRec(SockOut).InOutFunc:=@IOSock;
  263. TextRec(SockOut).FlushFunc:=@FlushSock;
  264. TextRec(SockOut).CloseFunc:=@CloseSock;
  265. end;
  266. {******************************************************************************
  267. Untyped File
  268. ******************************************************************************}
  269. Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
  270. begin
  271. {Input}
  272. Assign(SockIn,'.');
  273. FileRec(SockIn).Handle:=Sock;
  274. FileRec(SockIn).RecSize:=1;
  275. FileRec(Sockin).userdata[1]:=S_IN;
  276. {Output}
  277. Assign(SockOut,'.');
  278. FileRec(SockOut).Handle:=Sock;
  279. FileRec(SockOut).RecSize:=1;
  280. FileRec(SockOut).userdata[1]:=S_OUT;
  281. end;
  282. {******************************************************************************
  283. UnixSock
  284. ******************************************************************************}
  285. Procedure Str2UnixSockAddr(const addr:string;var t:TUnixSockAddr;var len:longint);
  286. begin
  287. Move(Addr[1],t.Path,length(Addr));
  288. t.Family:=AF_UNIX;
  289. t.Path[length(Addr)]:=#0;
  290. Len:=Length(Addr)+3;
  291. end;
  292. Function Bind(Sock:longint;const addr:string):boolean;
  293. var
  294. UnixAddr : TUnixSockAddr;
  295. AddrLen : longint;
  296. begin
  297. Str2UnixSockAddr(addr,UnixAddr,AddrLen);
  298. Bind(Sock,UnixAddr,AddrLen);
  299. Bind:=(SocketError=0);
  300. end;
  301. Function DoAccept(Sock:longint;var addr:string):longint;
  302. var
  303. UnixAddr : TUnixSockAddr;
  304. AddrLen : longint;
  305. begin
  306. AddrLen:=length(addr)+3;
  307. DoAccept:=Accept(Sock,UnixAddr,AddrLen);
  308. Move(UnixAddr.Path,Addr[1],AddrLen);
  309. SetLength(Addr,AddrLen);
  310. end;
  311. Function DoConnect(Sock:longint;const addr:string):Longint;
  312. var
  313. UnixAddr : TUnixSockAddr;
  314. AddrLen : longint;
  315. begin
  316. Str2UnixSockAddr(addr,UnixAddr,AddrLen);
  317. DoConnect:=Connect(Sock,UnixAddr,AddrLen);
  318. end;
  319. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
  320. var
  321. s : longint;
  322. begin
  323. S:=DoAccept(Sock,addr);
  324. if S>0 then
  325. begin
  326. Sock2Text(S,SockIn,SockOut);
  327. Accept:=true;
  328. end
  329. else
  330. Accept:=false;
  331. end;
  332. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
  333. var
  334. s : longint;
  335. begin
  336. S:=DoAccept(Sock,addr);
  337. if S>0 then
  338. begin
  339. Sock2File(S,SockIn,SockOut);
  340. Accept:=true;
  341. end
  342. else
  343. Accept:=false;
  344. end;
  345. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
  346. Var FD : Longint;
  347. begin
  348. FD:=DoConnect(Sock,addr);
  349. If Not(FD=-1) then
  350. begin
  351. Sock2Text(Sock,SockIn,SockOut);
  352. Connect:=true;
  353. end
  354. else
  355. Connect:=false;
  356. end;
  357. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
  358. Var FD : Longint;
  359. begin
  360. FD:=DoConnect(Sock,addr);
  361. if Not(FD=-1) then
  362. begin
  363. Sock2File(Sock,SockIn,SockOut);
  364. Connect:=true;
  365. end
  366. else
  367. Connect:=false;
  368. end;
  369. {******************************************************************************
  370. InetSock
  371. ******************************************************************************}
  372. Function DoAccept(Sock:longint;Var addr:TInetSockAddr):longint;
  373. Var AddrLen : Longint;
  374. begin
  375. AddrLEn:=SizeOf(Addr);
  376. DoAccept:=Accept(Sock,Addr,AddrLen);
  377. end;
  378. Function DoConnect(Sock:longint;const addr: TInetSockAddr): Longint;
  379. begin
  380. DoConnect:=Connect(Sock,Addr,SizeOF(TInetSockAddr));
  381. end;
  382. Function Connect(Sock:longint;const addr: TInetSockAddr;var SockIn,SockOut:text):Boolean;
  383. Var FD : Longint;
  384. begin
  385. FD:=DoConnect(Sock,addr);
  386. If Not(FD=-1) then
  387. begin
  388. Sock2Text(FD,SockIn,SockOut);
  389. Connect:=true;
  390. end
  391. else
  392. Connect:=false;
  393. end;
  394. Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
  395. Var FD : Longint;
  396. begin
  397. FD:=DoConnect(Sock,addr);
  398. If Not (FD=-1) then
  399. begin
  400. Sock2File(FD,SockIn,SockOut);
  401. Connect:=true;
  402. end
  403. else
  404. Connect:=false;
  405. end;
  406. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
  407. var
  408. s : longint;
  409. begin
  410. S:=DoAccept(Sock,addr);
  411. if S>0 then
  412. begin
  413. Sock2Text(S,SockIn,SockOut);
  414. Accept:=true;
  415. end
  416. else
  417. Accept:=false;
  418. end;
  419. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
  420. var
  421. s : longint;
  422. begin
  423. S:=DoAccept(Sock,addr);
  424. if S>0 then
  425. begin
  426. Sock2File(S,SockIn,SockOut);
  427. Accept:=true;
  428. end
  429. else
  430. Accept:=false;
  431. end;
  432. end.
  433. {
  434. $Log$
  435. Revision 1.7 1999-06-08 18:35:24 michael
  436. + Beter return values for connect and accept
  437. Revision 1.6 1999/06/08 18:19:24 michael
  438. + Fixes for connect calls
  439. Revision 1.5 1999/06/08 16:08:33 michael
  440. + completed (hopefully) Fix by stian ([email protected])
  441. Revision 1.4 1999/06/08 16:05:08 michael
  442. + Fix by stian ([email protected])
  443. Revision 1.3 1998/11/16 10:21:30 peter
  444. * fixes for H+
  445. Revision 1.2 1998/07/16 10:36:45 michael
  446. + added connect call for inet sockets
  447. Revision 1.1.1.1 1998/03/25 11:18:43 root
  448. * Restored version
  449. Revision 1.1 1998/02/13 08:35:05 michael
  450. + Initial implementation
  451. }