lcommon.pp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. { lCommon
  2. CopyRight (C) 2004-2007 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 MSG_NOSIGNAL
  44. LMSG = MSG_NOSIGNAL;
  45. {$ELSE}
  46. {$IFDEF FREEBSD}
  47. LMSG = $20000; // FPC BUG in 2.0.4-, freeBSD value
  48. {$ELSE}
  49. LMSG = 0;
  50. {$ENDIF}
  51. {$ENDIF}
  52. {$IFDEF DARWIN}
  53. SO_NOSIGPIPE = $1022; // for fpc 2.0.4
  54. {$ENDIF}
  55. {$ENDIF}
  56. { Default Values }
  57. LDEFAULT_BACKLOG = 5;
  58. BUFFER_SIZE = 65536;
  59. { Base functions }
  60. {$IFNDEF UNIX}
  61. function fpSelect(const nfds: Integer; const readfds, writefds, exceptfds: PFDSet;
  62. const timeout: PTimeVal): Integer; inline;
  63. function fpFD_ISSET(const Socket: Integer; var FDSet: TFDSet): Integer; inline;
  64. procedure fpFD_SET(const Socket: Integer; var FDSet: TFDSet); inline;
  65. procedure fpFD_ZERO(var FDSet: TFDSet); inline;
  66. {$ENDIF}
  67. { DNS }
  68. function GetHostName(const Address: string): string;
  69. function GetHostIP(const Name: string): string;
  70. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  71. function LSocketError: Longint;
  72. function SetBlocking(const aHandle: Integer; const aValue: Boolean): Boolean;
  73. function IsBlockError(const anError: Integer): Boolean; inline;
  74. function TZSeconds: Integer; inline;
  75. function StrToHostAddr(const IP: string): Cardinal; inline;
  76. function HostAddrToStr(const Entry: Cardinal): string; inline;
  77. function StrToNetAddr(const IP: string): Cardinal; inline;
  78. function NetAddrToStr(const Entry: Cardinal): string; inline;
  79. procedure FillAddressInfo(var aAddrInfo: TInetSockAddr; const aFamily: sa_family_t;
  80. const Address: string; const aPort: Word); inline;
  81. implementation
  82. uses
  83. StrUtils, lNet
  84. {$IFNDEF UNIX}
  85. {$IFDEF WINDOWS}
  86. , Windows;
  87. {$IFDEF WINCE}
  88. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  89. const
  90. MAX_ERROR = 1024;
  91. var
  92. Tmp: string;
  93. TmpW: widestring;
  94. begin
  95. Result := '[' + IntToStr(Ernum) + '] ';
  96. SetLength(TmpW, MAX_ERROR);
  97. SetLength(TmpW, FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM or
  98. FORMAT_MESSAGE_IGNORE_INSERTS or
  99. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  100. nil, Ernum, 0, @TmpW[1], MAX_ERROR, nil));
  101. Tmp := UTF8Encode(TmpW);
  102. if Length(Tmp) > 2 then
  103. Delete(Tmp, Length(Tmp)-1, 2);
  104. Result := Tmp;
  105. end;
  106. {$ELSE} // any other windows
  107. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  108. const
  109. MAX_ERROR = 1024;
  110. var
  111. Tmp: string;
  112. TmpW: widestring;
  113. begin
  114. Result := ' [' + IntToStr(Ernum) + ']: ';
  115. if USEUtf8 then begin
  116. SetLength(TmpW, MAX_ERROR);
  117. SetLength(TmpW, FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM or
  118. FORMAT_MESSAGE_IGNORE_INSERTS or
  119. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  120. nil, Ernum, 0, @TmpW[1], MAX_ERROR, nil));
  121. Tmp := UTF8Encode(TmpW);
  122. end else begin
  123. SetLength(Tmp, MAX_ERROR);
  124. SetLength(Tmp, FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
  125. FORMAT_MESSAGE_IGNORE_INSERTS or
  126. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  127. nil, Ernum, 0, @Tmp[1], MAX_ERROR, nil));
  128. end;
  129. if Length(Tmp) > 2 then
  130. Delete(Tmp, Length(Tmp)-1, 2);
  131. Result := Result + Tmp;
  132. end;
  133. {$ENDIF}
  134. function TZSeconds: integer; inline;
  135. var
  136. lInfo: Windows.TIME_ZONE_INFORMATION;
  137. begin
  138. { lInfo.Bias is in minutes }
  139. if Windows.GetTimeZoneInformation(@lInfo) <> $FFFFFFFF then
  140. Result := lInfo.Bias * 60
  141. else
  142. Result := 0;
  143. end;
  144. {$ELSE}
  145. ; // uses
  146. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  147. begin
  148. Result := IntToStr(Ernum); // TODO: fix for non-windows winsock users
  149. end;
  150. function TZSeconds: integer; inline;
  151. begin
  152. Result := 0; // todo: fix for non-windows non unix
  153. end;
  154. {$ENDIF}
  155. function LSocketError: Longint;
  156. begin
  157. Result := WSAGetLastError;
  158. end;
  159. function CleanError(const Ernum: Longint): Byte;
  160. begin
  161. Result := Byte(Ernum - 10000);
  162. end;
  163. function fpSelect(const nfds: Integer; const readfds, writefds, exceptfds: PFDSet;
  164. const timeout: PTimeVal): Longint; inline;
  165. begin
  166. Result := Select(nfds, readfds, writefds, exceptfds, timeout);
  167. end;
  168. function fpFD_ISSET(const Socket: Longint; var FDSet: TFDSet): Integer; inline;
  169. begin
  170. Result := 0;
  171. if FD_ISSET(Socket, FDSet) then
  172. Result := 1;
  173. end;
  174. procedure fpFD_SET(const Socket: Longint; var FDSet: TFDSet); inline;
  175. begin
  176. FD_SET(Socket, FDSet);
  177. end;
  178. procedure fpFD_ZERO(var FDSet: TFDSet); inline;
  179. begin
  180. FD_ZERO(FDSet);
  181. end;
  182. function GetHostName(const Address: string): string;
  183. var
  184. HE: PHostEnt;
  185. Addr: DWord;
  186. begin
  187. Result := '';
  188. HE := nil;
  189. Addr := inet_addr(PChar(Address));
  190. HE := gethostbyaddr(@Addr, SizeOf(Addr), AF_INET);
  191. if Assigned(HE) then
  192. Result := HE^.h_name;
  193. end;
  194. function GetHostIP(const Name: string): string;
  195. var
  196. HE: PHostEnt;
  197. P: PDWord;
  198. begin
  199. Result := '';
  200. HE := nil;
  201. HE := gethostbyname(PChar(Name));
  202. if Assigned(HE) then begin
  203. P := Pointer(HE^.h_addr_list[0]);
  204. Result := NetAddrToStr(P^);
  205. end;
  206. end;
  207. function SetBlocking(const aHandle: Integer; const aValue: Boolean): Boolean;
  208. const
  209. BlockAr: array[Boolean] of DWord = (1, 0);
  210. var
  211. opt: DWord;
  212. begin
  213. opt := BlockAr[aValue];
  214. if ioctlsocket(aHandle, Longint(FIONBIO), opt) = SOCKET_ERROR then
  215. Exit(False);
  216. Result := True;
  217. end;
  218. function IsBlockError(const anError: Integer): Boolean; inline;
  219. begin
  220. Result := anError = WSAEWOULDBLOCK;
  221. end;
  222. {$ELSE}
  223. // unix
  224. ,Errors, UnixUtil;
  225. function LStrError(const Ernum: Longint; const UseUTF8: Boolean = False): string;
  226. begin
  227. Result := ' [' + IntToStr(Ernum) + ']: ' + Errors.StrError(Ernum);
  228. end;
  229. function LSocketError: Longint;
  230. begin
  231. Result := fpgeterrno;
  232. end;
  233. function CleanError(const Ernum: Longint): Longint; inline;
  234. begin
  235. Result := Byte(Ernum);
  236. end;
  237. function GetHostName(const Address: string): string;
  238. var
  239. HE: THostEntry;
  240. begin
  241. Result := '';
  242. if GetHostbyAddr(in_addr(StrToHostAddr(Address)), HE) then
  243. Result := HE.Name
  244. else if ResolveHostbyAddr(in_addr(StrToHostAddr(Address)), HE) then
  245. Result := HE.Name;
  246. end;
  247. function GetHostIP(const Name: string): string;
  248. var
  249. HE: THostEntry;
  250. begin
  251. Result := '';
  252. if GetHostByName(Name, HE) then
  253. Result := HostAddrToStr(Cardinal(HE.Addr)) // for localhost
  254. else if ResolveHostByName(Name, HE) then
  255. Result := NetAddrToStr(Cardinal(HE.Addr));
  256. end;
  257. function SetBlocking(const aHandle: Integer; const aValue: Boolean): Boolean;
  258. var
  259. opt: cInt;
  260. begin
  261. opt := fpfcntl(aHandle, F_GETFL);
  262. if opt = SOCKET_ERROR then
  263. Exit(False);
  264. if aValue then
  265. opt := opt and not O_NONBLOCK
  266. else
  267. opt := opt or O_NONBLOCK;
  268. if fpfcntl(aHandle, F_SETFL, opt) = SOCKET_ERROR then
  269. Exit(False);
  270. Result := True;
  271. end;
  272. function IsBlockError(const anError: Integer): Boolean; inline;
  273. begin
  274. Result := (anError = ESysEWOULDBLOCK) or (anError = ESysENOBUFS);
  275. end;
  276. function TZSeconds: Integer; inline;
  277. begin
  278. Result := unixutil.TZSeconds;
  279. end;
  280. {$ENDIF}
  281. function StrToHostAddr(const IP: string): Cardinal; inline;
  282. begin
  283. Result := Cardinal(Sockets.StrToHostAddr(IP));
  284. end;
  285. function HostAddrToStr(const Entry: Cardinal): string; inline;
  286. begin
  287. Result := Sockets.HostAddrToStr(in_addr(Entry));
  288. end;
  289. function StrToNetAddr(const IP: string): Cardinal; inline;
  290. begin
  291. Result := Cardinal(Sockets.StrToNetAddr(IP));
  292. end;
  293. function NetAddrToStr(const Entry: Cardinal): string; inline;
  294. begin
  295. Result := Sockets.NetAddrToStr(in_addr(Entry));
  296. end;
  297. procedure FillAddressInfo(var aAddrInfo: TInetSockAddr; const aFamily: sa_family_t;
  298. const Address: string; const aPort: Word); inline;
  299. begin
  300. aAddrInfo.family := AF_INET;
  301. aAddrInfo.Port := htons(aPort);
  302. aAddrInfo.Addr := StrToNetAddr(Address);
  303. if (Address <> LADDR_ANY) and (aAddrInfo.Addr = 0) then
  304. aAddrInfo.Addr := StrToNetAddr(GetHostIP(Address));
  305. end;
  306. end.