sockets.pp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  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 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. end;
  179. Function Connect(Sock:Longint;Var Addr;Addrlen:Longint):Boolean;
  180. begin
  181. Connect:=(SocketCall(Socket_Sys_Connect,Sock,longint(@Addr),AddrLen)=0);
  182. end;
  183. Function Shutdown(Sock:Longint;How:Longint):Longint;
  184. begin
  185. ShutDown:=SocketCall(Socket_Sys_ShutDown,Sock,How,0);
  186. end;
  187. Function GetSocketName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  188. begin
  189. GetSocketName:=SocketCall(Socket_Sys_GetSockName,Sock,longint(@Addr),longint(@AddrLen));
  190. end;
  191. Function GetPeerName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  192. begin
  193. GetPeerName:=SocketCall(Socket_Sys_GetPeerName,Sock,longint(@Addr),longint(@AddrLen));
  194. end;
  195. Function SetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  196. begin
  197. SetSocketOptions:=SocketCall(Socket_Sys_SetSockOpt,Sock,Level,OptName,Longint(@OptVal),OptLen,0);
  198. end;
  199. Function GetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;optlen:longint):Longint;
  200. begin
  201. GetSocketOptions:=SocketCall(Socket_Sys_GetSockOpt,Sock,Level,OptName,Longint(@OptVal),OptLen,0);
  202. end;
  203. Function SocketPair(Domain,SocketType,Protocol:Longint;var Pair:TSockArray):Longint;
  204. begin
  205. SocketPair:=SocketCall(Socket_Sys_SocketPair,Domain,SocketType,Protocol,longint(@Pair),0,0);
  206. end;
  207. {******************************************************************************
  208. Text File Writeln/ReadLn Support
  209. ******************************************************************************}
  210. Procedure OpenSock(var F:Text);
  211. begin
  212. if textrec(f).handle=UnusedHandle then
  213. textrec(f).mode:=fmclosed
  214. else
  215. case textrec(f).userdata[1] of
  216. S_OUT : textrec(f).mode:=fmoutput;
  217. S_IN : textrec(f).mode:=fminput;
  218. else
  219. textrec(f).mode:=fmclosed;
  220. end;
  221. end;
  222. Procedure IOSock(var F:text);
  223. begin
  224. case textrec(f).mode of
  225. fmoutput : fdWrite(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufpos);
  226. fminput : textrec(f).BufEnd:=fdRead(textrec(f).handle,textrec(f).bufptr^,textrec(f).bufsize);
  227. end;
  228. textrec(f).bufpos:=0;
  229. end;
  230. Procedure FlushSock(var F:Text);
  231. begin
  232. if (textrec(f).mode=fmoutput) and (textrec(f).bufpos<>0) then
  233. IOSock(f);
  234. textrec(f).bufpos:=0;
  235. end;
  236. Procedure CloseSock(var F:text);
  237. begin
  238. Close(f);
  239. end;
  240. Procedure Sock2Text(Sock:Longint;Var SockIn,SockOut:Text);
  241. {
  242. Set up two Pascal Text file descriptors for reading and writing)
  243. }
  244. begin
  245. { First the reading part.}
  246. Assign(SockIn,'.');
  247. Textrec(SockIn).Handle:=Sock;
  248. Textrec(Sockin).userdata[1]:=S_IN;
  249. TextRec(SockIn).OpenFunc:=@OpenSock;
  250. TextRec(SockIn).InOutFunc:=@IOSock;
  251. TextRec(SockIn).FlushFunc:=@FlushSock;
  252. TextRec(SockIn).CloseFunc:=@CloseSock;
  253. { Now the writing part. }
  254. Assign(SockOut,'.');
  255. Textrec(SockOut).Handle:=Sock;
  256. Textrec(SockOut).userdata[1]:=S_OUT;
  257. TextRec(SockOut).OpenFunc:=@OpenSock;
  258. TextRec(SockOut).InOutFunc:=@IOSock;
  259. TextRec(SockOut).FlushFunc:=@FlushSock;
  260. TextRec(SockOut).CloseFunc:=@CloseSock;
  261. end;
  262. {******************************************************************************
  263. Untyped File
  264. ******************************************************************************}
  265. Procedure Sock2File(Sock:Longint;Var SockIn,SockOut:File);
  266. begin
  267. {Input}
  268. Assign(SockIn,'.');
  269. FileRec(SockIn).Handle:=Sock;
  270. FileRec(SockIn).RecSize:=1;
  271. FileRec(Sockin).userdata[1]:=S_IN;
  272. {Output}
  273. Assign(SockOut,'.');
  274. FileRec(SockOut).Handle:=Sock;
  275. FileRec(SockOut).RecSize:=1;
  276. FileRec(SockOut).userdata[1]:=S_OUT;
  277. end;
  278. {******************************************************************************
  279. UnixSock
  280. ******************************************************************************}
  281. Procedure Str2UnixSockAddr(const addr:string;var t:TUnixSockAddr;var len:longint);
  282. begin
  283. Move(Addr[1],t.Path,length(Addr));
  284. t.Family:=AF_UNIX;
  285. t.Path[length(Addr)]:=#0;
  286. Len:=Length(Addr)+3;
  287. end;
  288. Function Bind(Sock:longint;const addr:string):boolean;
  289. var
  290. UnixAddr : TUnixSockAddr;
  291. AddrLen : longint;
  292. begin
  293. Str2UnixSockAddr(addr,UnixAddr,AddrLen);
  294. Bind(Sock,UnixAddr,AddrLen);
  295. Bind:=(SocketError=0);
  296. end;
  297. Function DoAccept(Sock:longint;var addr:string):longint;
  298. var
  299. UnixAddr : TUnixSockAddr;
  300. AddrLen : longint;
  301. begin
  302. AddrLen:=length(addr)+3;
  303. DoAccept:=Accept(Sock,UnixAddr,AddrLen);
  304. Move(UnixAddr.Path,Addr[1],AddrLen);
  305. Addr[0]:=Chr(AddrLen);
  306. end;
  307. Function DoConnect(Sock:longint;const addr:string):Boolean;
  308. var
  309. UnixAddr : TUnixSockAddr;
  310. AddrLen : longint;
  311. begin
  312. Str2UnixSockAddr(addr,UnixAddr,AddrLen);
  313. DoConnect:=Connect(Sock,UnixAddr,AddrLen);
  314. end;
  315. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:text):Boolean;
  316. var
  317. s : longint;
  318. begin
  319. S:=DoAccept(Sock,addr);
  320. if S>0 then
  321. begin
  322. Sock2Text(S,SockIn,SockOut);
  323. Accept:=true;
  324. end
  325. else
  326. Accept:=false;
  327. end;
  328. Function Accept(Sock:longint;var addr:string;var SockIn,SockOut:File):Boolean;
  329. var
  330. s : longint;
  331. begin
  332. S:=DoAccept(Sock,addr);
  333. if S>0 then
  334. begin
  335. Sock2File(S,SockIn,SockOut);
  336. Accept:=true;
  337. end
  338. else
  339. Accept:=false;
  340. end;
  341. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:text):Boolean;
  342. begin
  343. if DoConnect(Sock,addr) then
  344. begin
  345. Sock2Text(Sock,SockIn,SockOut);
  346. Connect:=true;
  347. end
  348. else
  349. Connect:=false;
  350. end;
  351. Function Connect(Sock:longint;const addr:string;var SockIn,SockOut:file):Boolean;
  352. begin
  353. if DoConnect(Sock,addr) then
  354. begin
  355. Sock2File(Sock,SockIn,SockOut);
  356. Connect:=true;
  357. end
  358. else
  359. Connect:=false;
  360. end;
  361. {******************************************************************************
  362. InetSock
  363. ******************************************************************************}
  364. Function DoAccept(Sock:longint;Var addr:TInetSockAddr):longint;
  365. Var AddrLen : Longint;
  366. begin
  367. AddrLEn:=SizeOf(Addr);
  368. DoAccept:=Accept(Sock,Addr,AddrLen);
  369. end;
  370. Function DoConnect(Sock:longint;const addr: TInetSockAddr):Boolean;
  371. begin
  372. DoConnect:=Connect(Sock,Addr,SizeOF(TInetSockAddr));
  373. end;
  374. Function Connect(Sock:longint;const addr: TInetSockAddr;var SockIn,SockOut:text):Boolean;
  375. begin
  376. if DoConnect(Sock,addr) then
  377. begin
  378. Sock2Text(Sock,SockIn,SockOut);
  379. Connect:=true;
  380. end
  381. else
  382. Connect:=false;
  383. end;
  384. Function Connect(Sock:longint;const addr:TInetSockAddr;var SockIn,SockOut:file):Boolean;
  385. begin
  386. if DoConnect(Sock,addr) then
  387. begin
  388. Sock2File(Sock,SockIn,SockOut);
  389. Connect:=true;
  390. end
  391. else
  392. Connect:=false;
  393. end;
  394. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:text):Boolean;
  395. var
  396. s : longint;
  397. begin
  398. S:=DoAccept(Sock,addr);
  399. if S>0 then
  400. begin
  401. Sock2Text(S,SockIn,SockOut);
  402. Accept:=true;
  403. end
  404. else
  405. Accept:=false;
  406. end;
  407. Function Accept(Sock:longint;var addr:TInetSockAddr;var SockIn,SockOut:File):Boolean;
  408. var
  409. s : longint;
  410. begin
  411. S:=DoAccept(Sock,addr);
  412. if S>0 then
  413. begin
  414. Sock2File(S,SockIn,SockOut);
  415. Accept:=true;
  416. end
  417. else
  418. Accept:=false;
  419. end;
  420. end.
  421. {
  422. $Log$
  423. Revision 1.2 1998-07-16 10:36:45 michael
  424. + added connect call for inet sockets
  425. Revision 1.1.1.1 1998/03/25 11:18:43 root
  426. * Restored version
  427. Revision 1.1 1998/02/13 08:35:05 michael
  428. + Initial implementation
  429. }