sockets.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2002 Yuri Prokushev
  4. Copyright (c) 2005 Soren Ager
  5. Sockets implementation for OS/2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$MODE ObjFPC}
  13. { $DEFINE notUnix} // To make ssockets.pp compile
  14. unit Sockets;
  15. Interface
  16. Uses
  17. so32dll,ctypes;
  18. Const
  19. // AF_LOCAL = so32dll.AF_LOCAL;
  20. AF_UNSPEC = so32dll.AF_UNSPEC;
  21. AF_LOCAL = so32dll.AF_LOCAL;
  22. AF_UNIX = so32dll.AF_UNIX;
  23. AF_OS2 = so32dll.AF_OS2;
  24. AF_INET = so32dll.AF_INET;
  25. AF_IMPLINK = so32dll.AF_IMPLINK; // arpanet imp addresses
  26. AF_PUP = so32dll.AF_PUP; // pup protocols: e.g. BSP
  27. AF_CHAOS = so32dll.AF_CHAOS; // mit CHAOS protocols
  28. AF_NS = so32dll.AF_NS; // XEROX NS protocols
  29. AF_ISO = so32dll.AF_ISO; // ISO protocols
  30. AF_OSI = so32dll.AF_OSI;
  31. AF_ECMA = so32dll.AF_ECMA; // european computer manufacturers
  32. AF_DATAKIT = so32dll.AF_DATAKIT; // datakit protocols
  33. AF_CCITT = so32dll.AF_CCITT; // CCITT protocols, X.25 etc
  34. AF_SNA = so32dll.AF_SNA; // IBM SNA
  35. AF_DECnet = so32dll.AF_DECnet; // DECnet
  36. AF_DLI = so32dll.AF_DLI; // DEC Direct data link interface
  37. AF_LAT = so32dll.AF_LAT; // LAT
  38. AF_HYLINK = so32dll.AF_HYLINK; // NSC Hyperchannel
  39. AF_APPLETALK = so32dll.AF_APPLETALK; // Apple Talk
  40. AF_NB = so32dll.AF_NB; // Netbios
  41. AF_NETBIOS = so32dll.AF_NETBIOS; // Netbios
  42. AF_LINK = so32dll.AF_LINK; // Link layer interface
  43. pseudo_AF_XTP = so32dll.pseudo_AF_XTP; // eXpress Transfer Protocol (no AF)
  44. AF_COIP = so32dll.AF_COIP; // connection-oriented IP, aka ST II
  45. AF_CNT = so32dll.AF_CNT; // Computer Network Technology
  46. pseudo_AF_RTIP = so32dll.pseudo_AF_RTIP; // Help Identify RTIP packets
  47. AF_IPX = so32dll.AF_IPX; // Novell Internet Protocol
  48. AF_SIP = so32dll.AF_SIP; // Simple Internet Protocol
  49. AF_INET6 = so32dll.AF_INET6;
  50. pseudo_AF_PIP = so32dll.pseudo_AF_PIP; // Help Identify PIP packets
  51. AF_ROUTE = so32dll.AF_ROUTE; // Internal Routing Protocol
  52. AF_FWIP = so32dll.AF_FWIP; // firewall support
  53. AF_IPSEC = so32dll.AF_IPSEC; // IPSEC and encryption techniques
  54. AF_DES = so32dll.AF_DES; // DES
  55. AF_MD5 = so32dll.AF_MD5;
  56. AF_CDMF = so32dll.AF_CDMF;
  57. AF_MAX = so32dll.AF_MAX;
  58. // PF_LOCAL = so32dll.PF_LOCAL;
  59. PF_OS2 = so32dll.PF_OS2;
  60. PF_IMPLINK = so32dll.PF_IMPLINK;
  61. PF_PUP = so32dll.PF_PUP;
  62. PF_CHAOS = so32dll.PF_CHAOS;
  63. PF_NS = so32dll.PF_NS;
  64. PF_ISO = so32dll.PF_ISO;
  65. PF_OSI = so32dll.PF_OSI;
  66. PF_ECMA = so32dll.PF_ECMA;
  67. PF_DATAKIT = so32dll.PF_DATAKIT;
  68. PF_CCITT = so32dll.PF_CCITT;
  69. PF_SNA = so32dll.PF_SNA;
  70. PF_DECnet = so32dll.PF_DECnet;
  71. PF_DLI = so32dll.PF_DLI;
  72. PF_LAT = so32dll.PF_LAT;
  73. PF_HYLINK = so32dll.PF_HYLINK;
  74. PF_APPLETALK = so32dll.PF_APPLETALK;
  75. PF_NETBIOS = so32dll.PF_NB;
  76. PF_NB = so32dll.PF_NB;
  77. PF_ROUTE = so32dll.PF_ROUTE;
  78. PF_LINK = so32dll.PF_LINK;
  79. PF_XTP = so32dll.PF_XTP; // really just proto family, no AF
  80. PF_COIP = so32dll.PF_COIP;
  81. PF_CNT = so32dll.PF_CNT;
  82. PF_SIP = so32dll.PF_SIP;
  83. PF_INET6 = so32dll.PF_INET6;
  84. PF_IPX = so32dll.PF_IPX; // same format as AF_NS
  85. PF_RTIP = so32dll.PF_RTIP; // same format as AF_INET
  86. PF_PIP = so32dll.PF_PIP;
  87. PF_MAX = so32dll.PF_MAX;
  88. const EsockEINTR = SOCEINTR;
  89. EsockEBADF = SOCEBADF;
  90. EsockEFAULT = SOCEFAULT;
  91. EsockEINVAL = SOCEINVAL;
  92. EsockEACCESS = SOCEACCES;
  93. EsockEMFILE = SOCEMFILE;
  94. EsockEMSGSIZE = SOCEMSGSIZE;
  95. EsockENOBUFS = SOCENOBUFS;
  96. EsockENOTCONN = SOCENOTCONN;
  97. EsockENOTSOCK = SOCENOTSOCK;
  98. EsockEPROTONOSUPPORT = SOCEPROTONOSUPPORT;
  99. EsockEWOULDBLOCK = SOCEWOULDBLOCK;
  100. Type
  101. cushort=word;
  102. cuint16=word;
  103. cuint32=cardinal;
  104. size_t =cuint32;
  105. ssize_t=cuint16;
  106. cint =longint;
  107. pcint =^cint;
  108. tsocklen=cint;
  109. psocklen=^tsocklen;
  110. function InitEMXHandles: boolean;
  111. (* This procedure shall be called before touching any socket. Once called, *)
  112. (* it forces dynamic loading of emx.dll and all functions start with socket *)
  113. (* handles compatible to EMX in order to allow interworking with external *)
  114. (* libraries using EMX libc (e.g. OpenSSL compiled with EMX port of GCC). *)
  115. (* It returns true in case of successful initialization, false otherwise. *)
  116. function CheckEMXHandles: boolean;
  117. (* This function checks whether EMX compatible socket handles are used. *)
  118. function EMXSocket (ANativeSocket: cInt): cInt;
  119. function NativeSocket (AEMXSocket: cInt): cInt;
  120. // OS/2 stack based on BSD stack
  121. {$DEFINE BSD}
  122. {$I socketsh.inc}
  123. INVALID_SOCKET = TSocket(not(0));
  124. SOCKET_ERROR = -1;
  125. Implementation
  126. uses
  127. DosCalls;
  128. {Include filerec and textrec structures}
  129. {$I filerec.inc}
  130. {$I textrec.inc}
  131. {******************************************************************************
  132. Basic Socket Functions
  133. ******************************************************************************}
  134. const
  135. EMXHandles: boolean = false;
  136. EMXSysCall: pointer = nil;
  137. EMXLibHandle: THandle = THandle (-1);
  138. function CheckEMXHandles: boolean;
  139. begin
  140. CheckEMXHandles := EMXHandles;
  141. end;
  142. function InitEMXHandles: boolean;
  143. const
  144. EMXLib: string [8] = 'emx.dll'#0;
  145. CBufLen = 260;
  146. var
  147. CBuf: array [1..CBufLen] of char;
  148. begin
  149. if not EMXHandles then
  150. begin
  151. if DosLoadModule (@CBuf [1], SizeOf (CBuf), @EMXLib [1], EMXLibHandle) = 0
  152. then
  153. begin
  154. if DosQueryProcAddr (EMXLibHandle, 2, nil, EMXSysCall) = 0 then
  155. EMXHandles := true;
  156. end;
  157. InitEMXHandles := EMXHandles;
  158. end;
  159. end;
  160. {$ASMMODE INTEL}
  161. function EMXSocket (ANativeSocket: cInt): cInt; assembler;
  162. asm
  163. or EMXHandles, 0
  164. jz @EMXSocketEnd
  165. mov edx, eax
  166. mov eax, 7F54h
  167. mov ecx, 0
  168. call EMXSysCall
  169. @EMXSocketEnd:
  170. end;
  171. function NativeSocket (AEMXSocket: cInt): cInt; assembler;
  172. asm
  173. or EMXHandles, 0
  174. jz @NativeSocketEnd
  175. push ebx
  176. mov ebx, eax
  177. mov eax, 7F3Bh
  178. call EMXSysCall
  179. pop ebx
  180. @NativeSocketEnd:
  181. end;
  182. function SocketError: cint;
  183. begin
  184. SocketError := so32dll.Sock_ErrNo;
  185. end;
  186. Function Socket(Domain,SocketType,Protocol:Longint):Longint;
  187. begin
  188. Socket := fpSocket (Domain, SocketType, Protocol);
  189. end;
  190. Function Send(Sock:Longint;Const Buf;BufLen,Flags:Longint):Longint;
  191. begin
  192. Send:=fpSend(Sock,@Buf,BufLen,Flags);
  193. end;
  194. Function SendTo(Sock:Longint;Const Buf;BufLen,Flags:Longint;Var Addr; AddrLen : Longint):Longint;
  195. begin
  196. SendTo:=fpSendTo(Sock,@Buf,BufLen,Flags,@Addr,AddrLen);
  197. end;
  198. Function Recv(Sock:Longint;Var Buf;BufLen,Flags:Longint):Longint;
  199. begin
  200. Sock := NativeSocket (Sock);
  201. Recv:=so32dll.Recv(Sock,Buf,BufLen,Flags);
  202. end;
  203. Function RecvFrom(Sock : Longint; Var Buf; Buflen,Flags : Longint; Var Addr; var AddrLen : longInt) : longint;
  204. begin
  205. Sock := NativeSocket (Sock);
  206. RecvFrom:=so32dll.RecvFrom(Sock,Buf,BufLen,Flags,so32dll.SockAddr(Addr),AddrLen);
  207. end;
  208. Function Bind(Sock:Longint;Const Addr;AddrLen:Longint):Boolean;
  209. begin
  210. Bind:=fpBind(Sock,@Addr,AddrLen)=0;
  211. end;
  212. Function Listen(Sock,MaxConnect:Longint):Boolean;
  213. begin
  214. Sock := NativeSocket (Sock);
  215. Listen := so32dll.Listen(Sock,MaxConnect) = 0;
  216. end;
  217. Function Accept(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  218. begin
  219. Sock := NativeSocket (Sock);
  220. Accept:=so32dll.Accept(Sock,so32dll.SockAddr(Addr), AddrLen);
  221. end;
  222. Function Connect(Sock:Longint;const Addr; Addrlen:Longint):Boolean;
  223. begin
  224. Connect:=fpConnect(Sock,@Addr,AddrLen)=0;
  225. end;
  226. Function Shutdown(Sock:Longint;How:Longint):Longint;
  227. begin
  228. ShutDown:=fpShutDown(Sock,How);
  229. end;
  230. Function GetSocketName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  231. begin
  232. Sock := NativeSocket (Sock);
  233. GetSocketName:=so32dll.GetSockName(Sock, so32dll.SockAddr(Addr),AddrLen);
  234. end;
  235. Function GetPeerName(Sock:Longint;Var Addr;Var Addrlen:Longint):Longint;
  236. begin
  237. Sock := NativeSocket (Sock);
  238. GetPeerName:=so32dll.GetPeerName(Sock,so32dll.SockAddr(Addr),AddrLen);
  239. end;
  240. Function SetSocketOptions(Sock,Level,OptName:Longint;Const OptVal;optlen:longint):Longint;
  241. begin
  242. SetSocketOptions:=fpSetSockOpt(Sock,Level,OptName,@OptVal,OptLen);
  243. end;
  244. Function GetSocketOptions(Sock,Level,OptName:Longint;Var OptVal;Var optlen:longint):Longint;
  245. begin
  246. Sock := NativeSocket (Sock);
  247. GetSocketOptions:=so32dll.GetSockOpt(Sock,Level,OptName,OptVal,OptLen);
  248. end;
  249. Function SocketPair(Domain,SocketType,Protocol:Longint;var Pair:TSockArray):Longint;
  250. begin
  251. {!!TODO!!
  252. SocketPair:=so32dll.socketpair(Domain,SocketType,Protocol,Pair);}
  253. //SocketCall(Socket_Sys_SocketPair,Domain,SocketType,Protocol,longint(@Pair),0,0);
  254. SocketPair:=-1;
  255. end;
  256. { mimic the linux fpWrite/fpRead calls for the file/text socket wrapper }
  257. function fpWrite(handle : longint;Const bufptr;size : dword) : dword;
  258. begin
  259. fpWrite := dword(fpsend(handle, @bufptr, size, 0));
  260. if fpWrite = dword(-1) then
  261. fpWrite := 0;
  262. end;
  263. function fpRead(handle : longint;var bufptr;size : dword) : dword;
  264. var
  265. d : dword;
  266. begin
  267. Handle := NativeSocket (Handle);
  268. d:=dword(so32dll.os2_ioctl(handle,FIONREAD,d,SizeOf(d)));
  269. if d=dword(-1) then
  270. fpRead:=0
  271. else
  272. begin
  273. if size>d then
  274. size:=d;
  275. fpRead := dword(so32dll.recv(handle, bufptr, size, 0));
  276. if fpRead = dword(-1) then
  277. fpRead := 0
  278. end;
  279. end;
  280. {$i sockets.inc}
  281. function fpsocket (domain:cint; xtype:cint; protocol: cint):cint;
  282. begin
  283. if EMXHandles then
  284. fpSocket := EMXSocket (so32dll.Socket (Domain, xtype, Protocol))
  285. else
  286. fpSocket:=so32dll.Socket(Domain,xtype,Protocol);
  287. end;
  288. function fpsend (s:cint; msg:pointer; len:size_t; flags:cint):ssize_t;
  289. begin
  290. S := NativeSocket (S);
  291. fpSend:=so32dll.Send(S,msg^,len,flags);
  292. end;
  293. function fpsendto (s:cint; msg:pointer; len:size_t; flags:cint; tox :psockaddr; tolen: tsocklen):ssize_t;
  294. begin
  295. S := NativeSocket (S);
  296. // Dubious construct, this should be checked. (IPV6 fails ?)
  297. fpSendTo:=so32dll.SendTo(S,msg^,Len,Flags,so32dll.SockAddr(tox^),toLen);
  298. end;
  299. function fprecv (s:cint; buf: pointer; len: size_t; flags: cint):ssize_t;
  300. begin
  301. S := NativeSocket (S);
  302. fpRecv:=so32dll.Recv(S,Buf,Len,Flags);
  303. end;
  304. function fprecvfrom (s:cint; buf: pointer; len: size_t; flags: cint; from : psockaddr; fromlen : psocklen):ssize_t;
  305. begin
  306. S := NativeSocket (S);
  307. fpRecvFrom:=so32dll.RecvFrom(S,Buf,Len,Flags,so32dll.SockAddr(from^),FromLen^);
  308. end;
  309. function fpconnect (s:cint; name : psockaddr; namelen : tsocklen):cint;
  310. begin
  311. S := NativeSocket (S);
  312. fpConnect:=so32dll.Connect(S,so32dll.SockAddr(name^),nameLen);
  313. end;
  314. function fpshutdown (s:cint; how:cint):cint;
  315. begin
  316. S := NativeSocket (S);
  317. fpShutDown:=so32dll.ShutDown(S,How);
  318. end;
  319. function fpbind (s:cint; addrx : psockaddr; addrlen : tsocklen):cint;
  320. begin
  321. S := NativeSocket (S);
  322. fpbind:=so32dll.Bind(S,so32dll.SockAddr(Addrx^),AddrLen);
  323. end;
  324. function fplisten (s:cint; backlog : cint):cint;
  325. begin
  326. S := NativeSocket (S);
  327. fplisten:=so32dll.Listen(S,backlog);
  328. end;
  329. function fpaccept (s:cint; addrx : psockaddr; addrlen : psocklen):cint;
  330. begin
  331. S := NativeSocket (S);
  332. fpAccept:=so32dll.Accept(S,so32dll.SockAddr(Addrx^),longint(@AddrLen));
  333. end;
  334. function fpgetsockname (s:cint; name : psockaddr; namelen : psocklen):cint;
  335. begin
  336. S := NativeSocket (S);
  337. fpGetSockName:=so32dll.GetSockName(S,so32dll.SockAddr(name^),nameLen^);
  338. end;
  339. function fpgetpeername (s:cint; name : psockaddr; namelen : psocklen):cint;
  340. begin
  341. S := NativeSocket (S);
  342. fpGetPeerName:=so32dll.GetPeerName(S,so32dll.SockAddr(name^),NameLen^);
  343. end;
  344. function fpgetsockopt (s:cint; level:cint; optname:cint; optval:pointer; optlen : psocklen):cint;
  345. begin
  346. S := NativeSocket (S);
  347. fpGetSockOpt:=so32dll.GetSockOpt(S,Level,OptName,OptVal,OptLen^);
  348. end;
  349. function fpsetsockopt (s:cint; level:cint; optname:cint; optval:pointer; optlen :tsocklen):cint;
  350. begin
  351. S := NativeSocket (S);
  352. fpSetSockOpt:=so32dll.SetSockOpt(S,Level,OptName,OptVal,OptLen);
  353. end;
  354. function fpsocketpair (d:cint; xtype:cint; protocol:cint; sv:pcint):cint;
  355. begin
  356. fpsocketpair:=-1;
  357. end;
  358. Function CloseSocket(Sock:Longint):Longint;
  359. begin
  360. Sock := NativeSocket (Sock);
  361. CloseSocket:=so32dll.soclose (Sock);
  362. end;
  363. Begin
  364. so32dll.sock_init;
  365. End.