lcommon.pp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. { lCommon
  2. CopyRight (C) 2004-2006 Ales Katona
  3. This library is Free software; you can rediStribute it and/or modify it
  4. under the terms of the GNU Library General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or (at your
  6. option) any later version.
  7. This program is diStributed in the hope that it will be useful, but WITHOUT
  8. ANY WARRANTY; withOut even the implied warranty of MERCHANTABILITY or
  9. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  10. for more details.
  11. You should have received a Copy of the GNU Library General Public License
  12. along with This library; if not, Write to the Free Software Foundation,
  13. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. This license has been modified. See File LICENSE.ADDON for more inFormation.
  15. Should you find these sources without a LICENSE File, please contact
  16. me at [email protected]
  17. }
  18. unit lCommon;
  19. {$mode objfpc}{$H+}
  20. {$inline on}
  21. interface
  22. uses
  23. {$i sys/osunits.inc}
  24. const
  25. {$IFDEF WINDOWS}
  26. SOL_SOCKET = $ffff;
  27. LMSG = 0;
  28. SOCKET_ERROR = WinSock2.SOCKET_ERROR;
  29. {$ENDIF}
  30. {$IFDEF OS2}
  31. SOL_SOCKET = WinSock.SOL_SOCKET;
  32. LMSG = 0;
  33. SOCKET_ERROR = WinSock.SOCKET_ERROR;
  34. {$ENDIF}
  35. {$IFDEF NETWARE}
  36. SOL_SOCKET = WinSock.SOL_SOCKET;
  37. LMSG = 0;
  38. SOCKET_ERROR = WinSock.SOCKET_ERROR;
  39. {$ENDIF}
  40. {$IFDEF UNIX}
  41. INVALID_SOCKET = -1;
  42. SOCKET_ERROR = -1;
  43. {$IFDEF LINUX} // TODO: fix this crap, some don't even have MSD_NOSIGNAL
  44. LMSG = MSG_NOSIGNAL;
  45. {$ELSE}
  46. LMSG = $20000; // FPC BUG in 2.0.4-
  47. {$ENDIF}
  48. {$ENDIF}
  49. { Default Values }
  50. LDEFAULT_BACKLOG = 5;
  51. BUFFER_SIZE = 65536;
  52. { Base functions }
  53. {$IFNDEF UNIX}
  54. function fpSelect(const nfds: Integer; const readfds, writefds, exceptfds: PFDSet;
  55. const timeout: PTimeVal): Integer; inline;
  56. function fpFD_ISSET(const Socket: Integer; var FDSet: TFDSet): Integer; inline;
  57. procedure fpFD_SET(const Socket: Integer; var FDSet: TFDSet); inline;
  58. procedure fpFD_ZERO(var FDSet: TFDSet); inline;
  59. {$ENDIF}
  60. { DNS }
  61. function GetHostName(const Address: string): string;
  62. function GetHostIP(const Name: string): string;
  63. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  64. function LSocketError: Longint;
  65. function SetBlocking(const aHandle: Integer; const aValue: Boolean): Boolean;
  66. function IsBlockError(const anError: Integer): Boolean; inline;
  67. function TZSeconds: Integer; inline;
  68. function StrToHostAddr(const IP: string): Cardinal; inline;
  69. function HostAddrToStr(const Entry: Cardinal): string; inline;
  70. function StrToNetAddr(const IP: string): Cardinal; inline;
  71. function NetAddrToStr(const Entry: Cardinal): string; inline;
  72. procedure FillAddressInfo(var aAddrInfo: TInetSockAddr; const aFamily: sa_family_t;
  73. const Address: string; const aPort: Word); inline;
  74. implementation
  75. uses
  76. StrUtils, lNet
  77. {$IFNDEF UNIX}
  78. {$IFDEF WINDOWS}
  79. , Windows;
  80. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  81. var
  82. Tmp: string;
  83. TmpW: widestring;
  84. begin
  85. Result := '[' + IntToStr(Ernum) + '] ';
  86. if USEUtf8 then begin
  87. SetLength(TmpW, 256);
  88. SetLength(TmpW, FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM or
  89. FORMAT_MESSAGE_IGNORE_INSERTS or
  90. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  91. nil, Ernum, 0, @TmpW[1], 256, nil));
  92. Tmp := UTF8Encode(TmpW);
  93. end else begin
  94. SetLength(Tmp, 256);
  95. SetLength(Tmp, FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
  96. FORMAT_MESSAGE_IGNORE_INSERTS or
  97. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  98. nil, Ernum, 0, @Tmp[1], 256, nil));
  99. end;
  100. if Length(Tmp) > 2 then
  101. Delete(Tmp, Length(Tmp)-1, 2);
  102. Result := Tmp;
  103. end;
  104. function TZSeconds: integer; inline;
  105. var
  106. lInfo: Windows.TIME_ZONE_INFORMATION;
  107. begin
  108. { lInfo.Bias is in minutes }
  109. if Windows.GetTimeZoneInformation(@lInfo) <> $FFFFFFFF then
  110. Result := lInfo.Bias * 60
  111. else
  112. Result := 0;
  113. end;
  114. {$ELSE}
  115. ; // uses
  116. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  117. begin
  118. Result := IntToStr(Ernum); // TODO: fix for non-windows winsock users
  119. end;
  120. function TZSeconds: integer; inline;
  121. begin
  122. Result := 0; // todo: fix for non-windows non unix
  123. end;
  124. {$ENDIF}
  125. function LSocketError: Longint;
  126. begin
  127. Result := WSAGetLastError;
  128. end;
  129. function CleanError(const Ernum: Longint): Byte;
  130. begin
  131. Result := Byte(Ernum - 10000);
  132. end;
  133. function fpSelect(const nfds: Integer; const readfds, writefds, exceptfds: PFDSet;
  134. const timeout: PTimeVal): Longint; inline;
  135. begin
  136. Result := Select(nfds, readfds, writefds, exceptfds, timeout);
  137. end;
  138. function fpFD_ISSET(const Socket: Longint; var FDSet: TFDSet): Integer; inline;
  139. begin
  140. Result := 0;
  141. if FD_ISSET(Socket, FDSet) then
  142. Result := 1;
  143. end;
  144. procedure fpFD_SET(const Socket: Longint; var FDSet: TFDSet); inline;
  145. begin
  146. FD_SET(Socket, FDSet);
  147. end;
  148. procedure fpFD_ZERO(var FDSet: TFDSet); inline;
  149. begin
  150. FD_ZERO(FDSet);
  151. end;
  152. function GetHostName(const Address: string): string;
  153. var
  154. HE: PHostEnt;
  155. Addr: DWord;
  156. begin
  157. Result := '';
  158. HE := nil;
  159. Addr := inet_addr(PChar(Address));
  160. HE := gethostbyaddr(@Addr, SizeOf(Addr), AF_INET);
  161. if Assigned(HE) then
  162. Result := HE^.h_name;
  163. end;
  164. function GetHostIP(const Name: string): string;
  165. var
  166. HE: PHostEnt;
  167. P: PDWord;
  168. begin
  169. Result := '';
  170. HE := nil;
  171. HE := gethostbyname(PChar(Name));
  172. if Assigned(HE) then begin
  173. P := Pointer(HE^.h_addr_list[0]);
  174. Result := NetAddrToStr(P^);
  175. end;
  176. end;
  177. function SetBlocking(const aHandle: Integer; const aValue: Boolean): Boolean;
  178. const
  179. BlockAr: array[Boolean] of DWord = (1, 0);
  180. var
  181. opt: DWord;
  182. begin
  183. opt := BlockAr[aValue];
  184. if ioctlsocket(aHandle, Longint(FIONBIO), opt) = SOCKET_ERROR then
  185. Exit(False);
  186. Result := True;
  187. end;
  188. function IsBlockError(const anError: Integer): Boolean; inline;
  189. begin
  190. Result := anError = WSAEWOULDBLOCK;
  191. end;
  192. {$ELSE}
  193. // unix
  194. ,Errors, UnixUtil;
  195. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  196. begin
  197. Result := '[' + IntToStr(Ernum) + '] ' + Errors.StrError(Ernum);
  198. end;
  199. function LSocketError: Longint;
  200. begin
  201. Result := fpgeterrno;
  202. end;
  203. function CleanError(const Ernum: Longint): Longint; inline;
  204. begin
  205. Result := Byte(Ernum);
  206. end;
  207. function GetHostName(const Address: string): string;
  208. var
  209. HE: THostEntry;
  210. begin
  211. Result := '';
  212. if GetHostbyAddr(in_addr(StrToHostAddr(Address)), HE) then
  213. Result := HE.Name
  214. else if ResolveHostbyAddr(in_addr(StrToHostAddr(Address)), HE) then
  215. Result := HE.Name;
  216. end;
  217. function GetHostIP(const Name: string): string;
  218. var
  219. HE: THostEntry;
  220. begin
  221. Result := '';
  222. if GetHostByName(Name, HE) then
  223. Result := HostAddrToStr(Cardinal(HE.Addr)) // for localhost
  224. else if ResolveHostByName(Name, HE) then
  225. Result := NetAddrToStr(Cardinal(HE.Addr));
  226. end;
  227. function SetBlocking(const aHandle: Integer; const aValue: Boolean): Boolean;
  228. var
  229. opt: cInt;
  230. begin
  231. opt := fpfcntl(aHandle, F_GETFL);
  232. if opt = SOCKET_ERROR then
  233. Exit(False);
  234. if aValue then
  235. opt := opt and not O_NONBLOCK
  236. else
  237. opt := opt or O_NONBLOCK;
  238. if fpfcntl(aHandle, F_SETFL, opt) = SOCKET_ERROR then
  239. Exit(False);
  240. Result := True;
  241. end;
  242. function IsBlockError(const anError: Integer): Boolean; inline;
  243. begin
  244. Result := (anError = ESysEWOULDBLOCK) or (anError = ESysENOBUFS);
  245. end;
  246. function TZSeconds: Integer; inline;
  247. begin
  248. Result := unixutil.TZSeconds;
  249. end;
  250. {$ENDIF}
  251. function StrToHostAddr(const IP: string): Cardinal; inline;
  252. begin
  253. Result := Cardinal(Sockets.StrToHostAddr(IP));
  254. end;
  255. function HostAddrToStr(const Entry: Cardinal): string; inline;
  256. begin
  257. Result := Sockets.HostAddrToStr(in_addr(Entry));
  258. end;
  259. function StrToNetAddr(const IP: string): Cardinal; inline;
  260. begin
  261. Result := Cardinal(Sockets.StrToNetAddr(IP));
  262. end;
  263. function NetAddrToStr(const Entry: Cardinal): string; inline;
  264. begin
  265. Result := Sockets.NetAddrToStr(in_addr(Entry));
  266. end;
  267. procedure FillAddressInfo(var aAddrInfo: TInetSockAddr; const aFamily: sa_family_t;
  268. const Address: string; const aPort: Word); inline;
  269. begin
  270. aAddrInfo.family := AF_INET;
  271. aAddrInfo.Port := htons(aPort);
  272. aAddrInfo.Addr := StrToNetAddr(Address);
  273. if (Address <> LADDR_ANY) and (aAddrInfo.Addr = 0) then
  274. aAddrInfo.Addr := StrToNetAddr(GetHostIP(Address));
  275. end;
  276. end.