sockets.pp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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):Boolean;
  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 Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
  93. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
  94. Implementation
  95. Uses Linux;
  96. { Include filerec and textrec structures }
  97. {$i filerec.inc}
  98. {$i textrec.inc}
  99. {******************************************************************************
  100. Kernel Socket Callings
  101. ******************************************************************************}
  102. Const
  103. {
  104. Arguments to the Linux Kernel system call for sockets. All
  105. Socket Connected calls go through the same system call,
  106. with an extra argument to determine what action to take.
  107. }
  108. Socket_Sys_SOCKET = 1;
  109. Socket_Sys_BIND = 2;
  110. Socket_Sys_CONNECT = 3;
  111. Socket_Sys_LISTEN = 4;
  112. Socket_Sys_ACCEPT = 5;
  113. Socket_Sys_GETSOCKNAME = 6;
  114. Socket_Sys_GETPEERNAME = 7;
  115. Socket_Sys_SOCKETPAIR = 8;
  116. Socket_Sys_SEND = 9;
  117. Socket_Sys_RECV = 10;
  118. Socket_Sys_SENDTO = 11;
  119. Socket_Sys_RECVFROM = 12;
  120. Socket_Sys_SHUTDOWN = 13;
  121. Socket_Sys_SETSOCKOPT = 14;
  122. Socket_Sys_GETSOCKOPT = 15;
  123. Socket_Sys_SENDMSG = 16;
  124. Socket_Sys_RECVMSG = 17;
  125. Function SocketCall(SockCallNr,a1,a2,a3,a4,a5,a6:longint):longint;
  126. var
  127. Regs:SysCallRegs;
  128. Args:array[1..6] of longint;
  129. begin
  130. args[1]:=a1;
  131. args[2]:=a2;
  132. args[3]:=a3;
  133. args[4]:=a4;
  134. args[5]:=a5;
  135. args[6]:=a6;
  136. regs.reg2:=SockCallNr;
  137. regs.reg3:=Longint(@args);
  138. SocketCall:=Syscall(syscall_nr_socketcall,regs);
  139. If SocketCall<0 then
  140. SocketError:=Errno
  141. else
  142. SocketError:=0;
  143. end;
  144. Function SocketCall(SockCallNr,a1,a2,a3:longint):longint;
  145. begin
  146. SocketCall:=SocketCall(SockCallNr,a1,a2,a3,0,0,0);
  147. end;
  148. {******************************************************************************
  149. Basic Socket Functions
  150. ******************************************************************************}
  151. Function socket(Domain,SocketType,Protocol:Longint):Longint;
  152. begin
  153. Socket:=SocketCall(Socket_Sys_Socket,Domain,SocketType,ProtoCol);
  154. end;
  155. Function Send(Sock:Longint;Var Addr;AddrLen,Flags:Longint):Longint;
  156. begin
  157. Send:=SocketCall(Socket_Sys_Send,Sock,Longint(@Addr),AddrLen,Flags,0,0);
  158. end;
  159. Function Recv(Sock:Longint;Var Addr;AddrLen,Flags:Longint):Longint;
  160. begin
  161. Recv:=SocketCall(Socket_Sys_Recv,Sock,Longint(@Addr),AddrLen,Flags,0,0);
  162. end;
  163. Function Bind(Sock:Longint;Var Addr;AddrLen:Longint):Boolean;
  164. begin
  165. Bind:=(SocketCall(Socket_Sys_Bind,Sock,Longint(@Addr),AddrLen)=0);
  166. end;
  167. Function Listen(Sock,MaxConnect:Longint):Boolean;
  168. begin
  169. Listen:=(SocketCall(Socket_Sys_Listen,Sock,MaxConnect,0)=0);
  170. end;
  171. Function Accept(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  172. begin
  173. Accept:=SocketCall(Socket_Sys_Accept,Sock,longint(@Addr),longint(@AddrLen));
  174. end;
  175. Function Connect(Sock:Longint;Var Addr;Addrlen:Longint):Boolean;
  176. begin
  177. Connect:=(SocketCall(Socket_Sys_Connect,Sock,longint(@Addr),AddrLen)=0);
  178. end;
  179. Function Shutdown(Sock:Longint;How:Longint):Longint;
  180. begin
  181. ShutDown:=SocketCall(Socket_Sys_ShutDown,Sock,How,0);
  182. end;
  183. Function GetSocketName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  184. begin
  185. GetSocketName:=SocketCall(Socket_Sys_GetSockName,Sock,longint(@Addr),longint(@AddrLen));
  186. end;
  187. Function GetPeerName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  188. begin
  189. GetPeerName:=SocketCall(Socket_Sys_GetPeerName,Sock,longint(@Addr),longint(@AddrLen));
  190. end;
  191. Function SetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  192. begin
  193. SetSocketOptions:=SocketCall(Socket_Sys_SetSockOpt,Sock,Level,OptName,Longint(@OptVal),OptLen,0);
  194. end;
  195. Function GetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  196. begin
  197. GetSocketOptions:=SocketCall(Socket_Sys_GetSockOpt,Sock,Level,OptName,Longint(@OptVal),OptLen,0);
  198. end;
  199. Function SocketPair(Domain,SocketType,Protocol:Longint;var Pair:TSockArray):Longint;
  200. begin
  201. SocketPair:=SocketCall(Socket_Sys_SocketPair,Domain,SocketType,Protocol,longint(@Pair),0,0);
  202. end;
  203. {******************************************************************************
  204. Text File Writeln/ReadLn Support
  205. ******************************************************************************}
  206. Procedure OpenSock(var F:Text);
  207. begin
  208. if textrec(f).handle=UnusedHandle then
  209. textrec(f).mode:=fmclosed
  210. else
  211. case textrec(f).userdata[1] of
  212. S_OUT : textrec(f).mode:=fmoutput;
  213. S_IN : textrec(f).mode:=fminput;
  214. else
  215. textrec(f).mode:=fmclosed;
  216. end;
  217. end;
  218. Procedure IOSock(var F:text);
  219. begin
  220. case textrec(f).mode of
  221. fmoutput : fdWrite(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufpos);
  222. fminput : textrec(f).BufEnd:=fdRead(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufsize);
  223. end;
  224. textrec(f).bufpos:=0;
  225. end;
  226. Procedure FlushSock(var F:Text);
  227. begin
  228. if (textrec(f).mode=fmoutput) and (textrec(f).bufpos<>0) then
  229. IOSock(f);
  230. textrec(f).bufpos:=0;
  231. end;
  232. Procedure CloseSock(var F:text);
  233. begin
  234. Close(f);
  235. end;
  236. Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
  237. {
  238. Set up two Pascal Text file descriptors for reading and writing)
  239. }
  240. begin
  241. { First the reading part.}
  242. Assign(SockIn,'.');
  243. Textrec(SockIn).Handle:=Sock;
  244. Textrec(Sockin).userdata[1]:=S_IN;
  245. TextRec(SockIn).OpenFunc:=@OpenSock;
  246. TextRec(SockIn).InOutFunc:=@IOSock;
  247. TextRec(SockIn).FlushFunc:=@FlushSock;
  248. TextRec(SockIn).CloseFunc:=@CloseSock;
  249. { Now the writing part. }
  250. Assign(SockOut,'.');
  251. Textrec(SockOut).Handle:=Sock;
  252. Textrec(SockOut).userdata[1]:=S_OUT;
  253. TextRec(SockOut).OpenFunc:=@OpenSock;
  254. TextRec(SockOut).InOutFunc:=@IOSock;
  255. TextRec(SockOut).FlushFunc:=@FlushSock;
  256. TextRec(SockOut).CloseFunc:=@CloseSock;
  257. end;
  258. {******************************************************************************
  259. Untyped File
  260. ******************************************************************************}
  261. Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
  262. begin
  263. {Input}
  264. Assign(SockIn,'.');
  265. FileRec(SockIn).Handle:=Sock;
  266. FileRec(SockIn).RecSize:=1;
  267. FileRec(Sockin).userdata[1]:=S_IN;
  268. {Output}
  269. Assign(SockOut,'.');
  270. FileRec(SockOut).Handle:=Sock;
  271. FileRec(SockOut).RecSize:=1;
  272. FileRec(SockOut).userdata[1]:=S_OUT;
  273. end;
  274. {******************************************************************************
  275. UnixSock
  276. ******************************************************************************}
  277. Procedure Str2UnixSockAddr(const addr:string;var t:TUnixSockAddr;var len:longint);
  278. begin
  279. Move(Addr[1],t.Path,length(Addr));
  280. t.Family:=AF_UNIX;
  281. t.Path[length(Addr)]:=#0;
  282. Len:=Length(Addr)+3;
  283. end;
  284. Function Bind(Sock:longint;const addr:string):boolean;
  285. var
  286. UnixAddr : TUnixSockAddr;
  287. AddrLen : longint;
  288. begin
  289. Str2UnixSockAddr(addr,UnixAddr,AddrLen);
  290. Bind(Sock,UnixAddr,AddrLen);
  291. Bind:=(SocketError=0);
  292. end;
  293. Function DoAccept(Sock:longint;var addr:string):longint;
  294. var
  295. UnixAddr : TUnixSockAddr;
  296. AddrLen : longint;
  297. begin
  298. AddrLen:=length(addr)+3;
  299. DoAccept:=Accept(Sock,UnixAddr,AddrLen);
  300. Move(UnixAddr.Path,Addr[1],AddrLen);
  301. Addr[0]:=Chr(AddrLen);
  302. end;
  303. Function DoConnect(Sock:longint;const addr:string):Boolean;
  304. var
  305. UnixAddr : TUnixSockAddr;
  306. AddrLen : longint;
  307. begin
  308. Str2UnixSockAddr(addr,UnixAddr,AddrLen);
  309. DoConnect:=Connect(Sock,UnixAddr,AddrLen);
  310. end;
  311. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
  312. var
  313. s : longint;
  314. begin
  315. S:=DoAccept(Sock,addr);
  316. if S>0 then
  317. begin
  318. Sock2Text(S,SockIn,SockOut);
  319. Accept:=true;
  320. end
  321. else
  322. Accept:=false;
  323. end;
  324. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
  325. var
  326. s : longint;
  327. begin
  328. S:=DoAccept(Sock,addr);
  329. if S>0 then
  330. begin
  331. Sock2File(S,SockIn,SockOut);
  332. Accept:=true;
  333. end
  334. else
  335. Accept:=false;
  336. end;
  337. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
  338. begin
  339. if DoConnect(Sock,addr) then
  340. begin
  341. Sock2Text(Sock,SockIn,SockOut);
  342. Connect:=true;
  343. end
  344. else
  345. Connect:=false;
  346. end;
  347. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
  348. begin
  349. if DoConnect(Sock,addr) then
  350. begin
  351. Sock2File(Sock,SockIn,SockOut);
  352. Connect:=true;
  353. end
  354. else
  355. Connect:=false;
  356. end;
  357. end.
  358. {
  359. $Log$
  360. Revision 1.1 1998-03-25 11:18:43 root
  361. Initial revision
  362. Revision 1.1 1998/02/13 08:35:05 michael
  363. + Initial implementation
  364. }