PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/addons/Socket/source/Socket.c

https://github.com/iamaleksey/io
C | 479 lines | 343 code | 96 blank | 40 comment | 72 complexity | a4e5f5668cf9022aadf185de3c365e60 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. //metadoc Socket copyright Steve Dekorte 2002
  2. //metadoc Socket license BSD revised
  3. #include "Socket.h"
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #ifndef WIN32
  7. #include <unistd.h>
  8. #endif
  9. /*
  10. #ifdef WIN32
  11. #define EINPROGRESS 36
  12. #define EDQUOT 69
  13. #endif
  14. */
  15. /*
  16. int
  17. getpeername(int s, struct sockaddr *name, int *namelen);
  18. getsockname
  19. */
  20. void Socket_ignoreSignal(int sig)
  21. {
  22. //printf("Socket_ignoreSignal(%i)\n", sig);
  23. }
  24. void Socket_GlobalInit(void)
  25. {
  26. /*
  27. #ifndef WIN32
  28. signal(SIGPIPE, Socket_ignoreSignal);
  29. #endif
  30. */
  31. #ifdef WIN32
  32. {
  33. WSADATA wsd;
  34. WSAStartup(MAKEWORD(2,0), &wsd);
  35. }
  36. #else
  37. signal(SIGPIPE, Socket_ignoreSignal);
  38. #endif
  39. }
  40. void Socket_GlobalCleanup(void)
  41. {
  42. #ifdef WIN32
  43. WSACleanup();
  44. #endif
  45. }
  46. #ifdef WIN32
  47. long Socket_SetDescriptorLimitToMax(void)
  48. {
  49. return -1;
  50. }
  51. #else
  52. #include <sys/resource.h>
  53. long Socket_SetDescriptorLimitToMax(void)
  54. {
  55. struct rlimit rlp;
  56. // if were root, we could also do:
  57. // system("sysctl -w kern.maxfiles=1000001");
  58. // system("sysctl -w kern.maxfilesperproc=1000000");
  59. if (getrlimit(RLIMIT_NOFILE, &rlp) != 0)
  60. {
  61. return -1;
  62. }
  63. //printf("rlp.rlim_cur = %i\n", (int)rlp.rlim_cur);
  64. //printf("rlp.rlim_max = %i\n", (int)rlp.rlim_max);
  65. rlp.rlim_cur = rlp.rlim_max;
  66. if (setrlimit(RLIMIT_NOFILE, &rlp) != 0)
  67. {
  68. return -2;
  69. }
  70. if (getrlimit(RLIMIT_NOFILE, &rlp) != 0)
  71. {
  72. return -3;
  73. }
  74. //printf(" max listeners = %i\n", (int)rlp.rlim_cur);
  75. return (long)(rlp.rlim_cur);
  76. }
  77. #endif
  78. // -----------------------------------------------------
  79. Socket *Socket_new(void)
  80. {
  81. Socket *self = (Socket *)io_calloc(1, sizeof(Socket));
  82. #ifdef WIN32
  83. self->fd = INVALID_SOCKET;
  84. #else
  85. self->fd = -1;
  86. #endif
  87. return self;
  88. }
  89. void Socket_free(Socket *self)
  90. {
  91. io_free(self);
  92. }
  93. void Socket_setDescriptor_(Socket *self, SOCKET_DESCRIPTOR fd)
  94. {
  95. self->fd = fd;
  96. }
  97. SOCKET_DESCRIPTOR Socket_descriptor(Socket *self)
  98. {
  99. return self->fd;
  100. }
  101. // ----------------------------------------
  102. int Socket_makeReusable(Socket *self)
  103. {
  104. int val = 1;
  105. SocketResetErrorStatus();
  106. if (setsockopt(self->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(int)) < 0)
  107. {
  108. return 0;
  109. }
  110. #ifdef SO_REUSEPORT
  111. SocketResetErrorStatus();
  112. if (setsockopt(self->fd, SOL_SOCKET, SO_REUSEPORT, (char *)&val, sizeof(int)) < 0)
  113. {
  114. return 0;
  115. }
  116. #endif
  117. return 1;
  118. }
  119. int Socket_makeAsync(Socket *self)
  120. {
  121. #ifdef WIN32
  122. unsigned long nonzero = 1;
  123. SocketResetErrorStatus();
  124. if (ioctlsocket(self->fd, FIONBIO, &nonzero) == -1)
  125. #else
  126. SocketResetErrorStatus();
  127. if (fcntl(self->fd, F_SETFL, FASYNC | O_NONBLOCK) == -1)
  128. #endif
  129. {
  130. return 0;
  131. }
  132. return 1;
  133. }
  134. // ----------------------------------------
  135. int Socket_isStream(Socket *self)
  136. {
  137. int ok, optval;
  138. socklen_t optlen;
  139. SocketResetErrorStatus();
  140. ok = getsockopt(self->fd, SOL_SOCKET, SO_TYPE, (void *)(&optval), &optlen);
  141. if (ok != 0)
  142. {
  143. return 0;
  144. }
  145. return optval == SOCK_STREAM;
  146. }
  147. int Socket_isOpen(Socket *self)
  148. {
  149. #ifdef WIN32
  150. return self->fd != INVALID_SOCKET;
  151. #else
  152. return self->fd != -1;
  153. #endif
  154. }
  155. int RawDescriptor_isValid(int fd)
  156. {
  157. #ifdef WIN32
  158. // ask how many bytes there are to read. Not because we
  159. // want to know that but just if the socket is ok.
  160. u_long iToRead = 0;
  161. if (ioctlsocket((SOCKET_DESCRIPTOR) fd, FIONREAD, &iToRead) == SOCKET_ERROR && SocketErrorStatus() == WSAENOTSOCK)
  162. #else
  163. if (fcntl(fd, F_GETFL, NULL) == -1)
  164. #endif
  165. {
  166. return 0;
  167. }
  168. return 1;
  169. }
  170. int Socket_isValid(Socket *self)
  171. {
  172. return RawDescriptor_isValid(self->fd);
  173. }
  174. // ----------------------------------------
  175. int Socket_streamOpen(Socket *self)
  176. {
  177. SocketResetErrorStatus();
  178. self->fd = socket(AF_INET, SOCK_STREAM, 0);
  179. return Socket_isOpen(self);
  180. }
  181. int Socket_udpOpen(Socket *self)
  182. {
  183. SocketResetErrorStatus();
  184. self->fd = socket(AF_INET, SOCK_DGRAM, 0);
  185. return Socket_isOpen(self);
  186. }
  187. // ----------------------------------------
  188. int Socket_connectTo(Socket *self, IPAddress *address)
  189. {
  190. int result;
  191. SocketResetErrorStatus();
  192. result = connect(self->fd, IPAddress_sockaddr(address), IPAddress_size(address));
  193. #ifdef WIN32
  194. return result == 0 || SocketErrorStatus() == WSAEISCONN;
  195. #else
  196. return result == 0 || SocketErrorStatus() == EISCONN;
  197. #endif
  198. }
  199. int Socket_connectToFailed(void)
  200. {
  201. int errorNumber = SocketErrorStatus();
  202. #ifdef WIN32
  203. return errorNumber && errorNumber != WSAEINPROGRESS && errorNumber != WSAEALREADY && errorNumber != WSAEWOULDBLOCK && errorNumber != WSAEINVAL;
  204. #else
  205. return errorNumber && errorNumber != EINPROGRESS && errorNumber != EALREADY && errorNumber != EINTR;
  206. #endif
  207. }
  208. int Socket_close(Socket *self)
  209. {
  210. int result = 0;
  211. #ifdef WIN32
  212. if (self->fd != INVALID_SOCKET)
  213. {
  214. result = closesocket(self->fd);
  215. }
  216. self->fd = INVALID_SOCKET;
  217. #else
  218. if (self->fd != -1)
  219. {
  220. result = close(self->fd);
  221. }
  222. self->fd = -1;
  223. #endif
  224. return result == 0;
  225. }
  226. int Socket_closeFailed(void)
  227. {
  228. int errorNumber = SocketErrorStatus();
  229. #ifdef WIN32
  230. return errorNumber;
  231. #else
  232. return errorNumber && errorNumber != EINTR;
  233. #endif
  234. }
  235. int Socket_bind(Socket *self, IPAddress *address)
  236. {
  237. int result;
  238. SocketResetErrorStatus();
  239. result = bind(self->fd, IPAddress_sockaddr(address), IPAddress_size(address));
  240. return result == 0;
  241. }
  242. int Socket_listen(Socket *self)
  243. {
  244. int result;
  245. SocketResetErrorStatus();
  246. // returns 0 of ok, -1 on error
  247. result = listen(self->fd, SOMAXCONN);
  248. //if (r == -1) Socket_checkErrorNumber(self);
  249. return result == 0;
  250. }
  251. int Socket_asyncFailed(void)
  252. {
  253. int errorNumber = SocketErrorStatus();
  254. #ifdef WIN32
  255. return errorNumber && errorNumber != WSAEWOULDBLOCK;
  256. #else
  257. return errorNumber && errorNumber != EWOULDBLOCK && errorNumber != EAGAIN && errorNumber != EINTR;
  258. #endif
  259. }
  260. Socket *Socket_accept(Socket *self, IPAddress *address)
  261. {
  262. socklen_t addressSize = IPAddress_size(address);
  263. SOCKET_DESCRIPTOR d;
  264. SocketResetErrorStatus();
  265. d = accept(self->fd, IPAddress_sockaddr(address), &addressSize);
  266. IPAddress_setSize_(address, addressSize);
  267. if (d != -1)
  268. {
  269. Socket *socket = Socket_new();
  270. Socket_setDescriptor_(socket, d);
  271. if (Socket_makeReusable(socket) && Socket_makeAsync(socket))
  272. return socket;
  273. else
  274. return NULL;
  275. }
  276. return NULL;
  277. }
  278. // stream ----------------------------------------
  279. ssize_t Socket_streamRead(Socket *self, UArray *buffer, size_t readSize)
  280. {
  281. ssize_t bytesRead;
  282. size_t originalSize = UArray_sizeInBytes(buffer);
  283. UArray_sizeTo_(buffer, originalSize + readSize + 1);
  284. SocketResetErrorStatus();
  285. #ifdef WIN32
  286. bytesRead = (size_t)recv(self->fd, (uint8_t *)UArray_bytes(buffer) + originalSize, readSize, 0);
  287. #else
  288. bytesRead = (size_t)read(self->fd, (uint8_t *)UArray_bytes(buffer) + originalSize, readSize);
  289. #endif
  290. if (bytesRead > 0)
  291. {
  292. UArray_setSize_(buffer, originalSize + bytesRead);
  293. }
  294. else
  295. {
  296. UArray_setSize_(buffer, originalSize);
  297. // Maintain truthy return value semantics
  298. bytesRead = 0;
  299. }
  300. return bytesRead;
  301. }
  302. ssize_t Socket_streamWrite(Socket *self, UArray *buffer, size_t start, size_t writeSize)
  303. {
  304. size_t bufferSize = UArray_sizeInBytes(buffer);
  305. ssize_t bytesWritten;
  306. if (start > bufferSize)
  307. {
  308. return 0;
  309. }
  310. if (start + writeSize > bufferSize)
  311. {
  312. writeSize = bufferSize - start;
  313. }
  314. SocketResetErrorStatus();
  315. #ifdef WIN32
  316. bytesWritten = send(self->fd, UArray_bytes(buffer) + start, writeSize, 0);
  317. #else
  318. bytesWritten = write(self->fd, UArray_bytes(buffer) + start, writeSize);
  319. #endif
  320. // Maintain truthy return value semantics
  321. bytesWritten = (bytesWritten < 0) ? 0 : bytesWritten;
  322. return bytesWritten;
  323. }
  324. ssize_t Socket_udpRead(Socket *self, IPAddress *address, UArray *buffer, size_t readSize)
  325. {
  326. socklen_t addressSize = IPAddress_size(address);
  327. size_t oldSize = UArray_sizeInBytes(buffer);
  328. ssize_t bytesRead;
  329. UArray_setItemType_(buffer, CTYPE_uint8_t);
  330. UArray_sizeTo_(buffer, oldSize + readSize);
  331. SocketResetErrorStatus();
  332. bytesRead = recvfrom(self->fd, (uint8_t *)UArray_bytes(buffer), readSize, 0, IPAddress_sockaddr(address), &addressSize);
  333. if (bytesRead > 0)
  334. {
  335. UArray_setSize_(buffer, oldSize + bytesRead);
  336. IPAddress_setSize_(address, addressSize);
  337. }
  338. else
  339. {
  340. UArray_setSize_(buffer, oldSize);
  341. // Maintain truthy return value semantics
  342. bytesRead = 0;
  343. }
  344. return bytesRead;
  345. }
  346. ssize_t Socket_udpWrite(Socket *self, IPAddress *address, UArray *buffer, size_t start, size_t writeSize)
  347. {
  348. size_t bufferSize = UArray_sizeInBytes(buffer);
  349. ssize_t bytesWritten;
  350. if (start > bufferSize) return 0;
  351. if (start + writeSize > bufferSize)
  352. {
  353. writeSize = bufferSize - start;
  354. }
  355. SocketResetErrorStatus();
  356. bytesWritten = sendto(self->fd, UArray_bytes(buffer), writeSize, 0, IPAddress_sockaddr(address), IPAddress_size(address));
  357. // Maintain truthy return value semantics
  358. bytesWritten = (bytesWritten < 0) ? 0 : bytesWritten;
  359. return bytesWritten;
  360. }
  361. // ----------------------------------------
  362. char *Socket_errorDescription(void)
  363. {
  364. int err = SocketErrorStatus();
  365. #ifdef WIN32
  366. if (err)
  367. {
  368. char *tmpBuffer;
  369. char *messageBuffer;
  370. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, err, 0, &tmpBuffer, 0, NULL);
  371. messageBuffer = calloc(strlen(tmpBuffer) + 1, 1);
  372. strcpy(messageBuffer, tmpBuffer);
  373. LocalFree(tmpBuffer);
  374. return messageBuffer;
  375. }
  376. else
  377. {
  378. return "";
  379. }
  380. #else
  381. return err ? strerror(err) : "";
  382. #endif
  383. }