PageRenderTime 28ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/socket.c

https://github.com/mchaland/libusbmuxd
C | 435 lines | 340 code | 57 blank | 38 comment | 59 complexity | b0b1ff115ae4587d0907b7de91d45b2f MD5 | raw file
Possible License(s): LGPL-2.1
  1. /*
  2. * socket.c
  3. *
  4. * Copyright (c) 2012 Martin Szulecki All Rights Reserved.
  5. * Copyright (c) 2012 Nikias Bassen All Rights Reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include <stdio.h>
  22. #include <stddef.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <unistd.h>
  26. #include <errno.h>
  27. #include <sys/time.h>
  28. #include <sys/stat.h>
  29. #ifdef WIN32
  30. #include <winsock2.h>
  31. #include <windows.h>
  32. static int wsa_init = 0;
  33. #else
  34. #include <sys/socket.h>
  35. #include <sys/un.h>
  36. #include <netinet/in.h>
  37. #include <netdb.h>
  38. #include <arpa/inet.h>
  39. #endif
  40. #include "socket.h"
  41. #define RECV_TIMEOUT 20000
  42. static int verbose = 0;
  43. void socket_set_verbose(int level)
  44. {
  45. verbose = level;
  46. }
  47. #ifndef WIN32
  48. int socket_create_unix(const char *filename)
  49. {
  50. struct sockaddr_un name;
  51. int sock;
  52. size_t size;
  53. #ifdef SO_NOSIGPIPE
  54. int yes = 1;
  55. #endif
  56. // remove if still present
  57. unlink(filename);
  58. /* Create the socket. */
  59. sock = socket(PF_LOCAL, SOCK_STREAM, 0);
  60. if (sock < 0) {
  61. perror("socket");
  62. return -1;
  63. }
  64. #ifdef SO_NOSIGPIPE
  65. if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
  66. perror("setsockopt()");
  67. socket_close(sock);
  68. return -1;
  69. }
  70. #endif
  71. /* Bind a name to the socket. */
  72. name.sun_family = AF_LOCAL;
  73. strncpy(name.sun_path, filename, sizeof(name.sun_path));
  74. name.sun_path[sizeof(name.sun_path) - 1] = '\0';
  75. /* The size of the address is
  76. the offset of the start of the filename,
  77. plus its length,
  78. plus one for the terminating null byte.
  79. Alternatively you can just do:
  80. size = SUN_LEN (&name);
  81. */
  82. size = (offsetof(struct sockaddr_un, sun_path)
  83. + strlen(name.sun_path) + 1);
  84. if (bind(sock, (struct sockaddr *) &name, size) < 0) {
  85. perror("bind");
  86. socket_close(sock);
  87. return -1;
  88. }
  89. if (listen(sock, 10) < 0) {
  90. perror("listen");
  91. socket_close(sock);
  92. return -1;
  93. }
  94. return sock;
  95. }
  96. int socket_connect_unix(const char *filename)
  97. {
  98. struct sockaddr_un name;
  99. int sfd = -1;
  100. size_t size;
  101. struct stat fst;
  102. #ifdef SO_NOSIGPIPE
  103. int yes = 1;
  104. #endif
  105. // check if socket file exists...
  106. if (stat(filename, &fst) != 0) {
  107. if (verbose >= 2)
  108. fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename,
  109. strerror(errno));
  110. return -1;
  111. }
  112. // ... and if it is a unix domain socket
  113. if (!S_ISSOCK(fst.st_mode)) {
  114. if (verbose >= 2)
  115. fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__,
  116. filename);
  117. return -1;
  118. }
  119. // make a new socket
  120. if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
  121. if (verbose >= 2)
  122. fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
  123. return -1;
  124. }
  125. #ifdef SO_NOSIGPIPE
  126. if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
  127. perror("setsockopt()");
  128. socket_close(sfd);
  129. return -1;
  130. }
  131. #endif
  132. // and connect to 'filename'
  133. name.sun_family = AF_LOCAL;
  134. strncpy(name.sun_path, filename, sizeof(name.sun_path));
  135. name.sun_path[sizeof(name.sun_path) - 1] = 0;
  136. size = (offsetof(struct sockaddr_un, sun_path)
  137. + strlen(name.sun_path) + 1);
  138. if (connect(sfd, (struct sockaddr *) &name, size) < 0) {
  139. socket_close(sfd);
  140. if (verbose >= 2)
  141. fprintf(stderr, "%s: connect: %s\n", __func__,
  142. strerror(errno));
  143. return -1;
  144. }
  145. return sfd;
  146. }
  147. #endif
  148. int socket_create(uint16_t port)
  149. {
  150. int sfd = -1;
  151. int yes = 1;
  152. #ifdef WIN32
  153. WSADATA wsa_data;
  154. if (!wsa_init) {
  155. if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
  156. fprintf(stderr, "WSAStartup failed!\n");
  157. ExitProcess(-1);
  158. }
  159. wsa_init = 1;
  160. }
  161. #endif
  162. struct sockaddr_in saddr;
  163. if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
  164. perror("socket()");
  165. return -1;
  166. }
  167. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
  168. perror("setsockopt()");
  169. socket_close(sfd);
  170. return -1;
  171. }
  172. #ifdef SO_NOSIGPIPE
  173. if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
  174. perror("setsockopt()");
  175. socket_close(sfd);
  176. return -1;
  177. }
  178. #endif
  179. memset((void *) &saddr, 0, sizeof(saddr));
  180. saddr.sin_family = AF_INET;
  181. saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  182. saddr.sin_port = htons(port);
  183. if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
  184. perror("bind()");
  185. socket_close(sfd);
  186. return -1;
  187. }
  188. if (listen(sfd, 1) == -1) {
  189. perror("listen()");
  190. socket_close(sfd);
  191. return -1;
  192. }
  193. return sfd;
  194. }
  195. int socket_connect(const char *addr, uint16_t port)
  196. {
  197. int sfd = -1;
  198. int yes = 1;
  199. struct hostent *hp;
  200. struct sockaddr_in saddr;
  201. #ifdef WIN32
  202. WSADATA wsa_data;
  203. if (!wsa_init) {
  204. if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
  205. fprintf(stderr, "WSAStartup failed!\n");
  206. ExitProcess(-1);
  207. }
  208. wsa_init = 1;
  209. }
  210. #endif
  211. if (!addr) {
  212. errno = EINVAL;
  213. return -1;
  214. }
  215. if ((hp = gethostbyname(addr)) == NULL) {
  216. if (verbose >= 2)
  217. fprintf(stderr, "%s: unknown host '%s'\n", __func__, addr);
  218. return -1;
  219. }
  220. if (!hp->h_addr) {
  221. if (verbose >= 2)
  222. fprintf(stderr, "%s: gethostbyname returned NULL address!\n",
  223. __func__);
  224. return -1;
  225. }
  226. if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
  227. perror("socket()");
  228. return -1;
  229. }
  230. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(int)) == -1) {
  231. perror("setsockopt()");
  232. socket_close(sfd);
  233. return -1;
  234. }
  235. #ifdef SO_NOSIGPIPE
  236. if (setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&yes, sizeof(int)) == -1) {
  237. perror("setsockopt()");
  238. socket_close(sfd);
  239. return -1;
  240. }
  241. #endif
  242. memset((void *) &saddr, 0, sizeof(saddr));
  243. saddr.sin_family = AF_INET;
  244. saddr.sin_addr.s_addr = *(uint32_t *) hp->h_addr;
  245. saddr.sin_port = htons(port);
  246. if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
  247. perror("connect");
  248. socket_close(sfd);
  249. return -2;
  250. }
  251. return sfd;
  252. }
  253. int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout)
  254. {
  255. fd_set fds;
  256. int sret;
  257. int eagain;
  258. struct timeval to;
  259. struct timeval *pto;
  260. if (fd < 0) {
  261. if (verbose >= 2)
  262. fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
  263. return -1;
  264. }
  265. FD_ZERO(&fds);
  266. FD_SET(fd, &fds);
  267. if (timeout > 0) {
  268. to.tv_sec = (time_t) (timeout / 1000);
  269. to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000);
  270. pto = &to;
  271. } else {
  272. pto = NULL;
  273. }
  274. sret = -1;
  275. do {
  276. eagain = 0;
  277. switch (fdm) {
  278. case FDM_READ:
  279. sret = select(fd + 1, &fds, NULL, NULL, pto);
  280. break;
  281. case FDM_WRITE:
  282. sret = select(fd + 1, NULL, &fds, NULL, pto);
  283. break;
  284. case FDM_EXCEPT:
  285. sret = select(fd + 1, NULL, NULL, &fds, pto);
  286. break;
  287. default:
  288. return -1;
  289. }
  290. if (sret < 0) {
  291. switch (errno) {
  292. case EINTR:
  293. // interrupt signal in select
  294. if (verbose >= 2)
  295. fprintf(stderr, "%s: EINTR\n", __func__);
  296. eagain = 1;
  297. break;
  298. case EAGAIN:
  299. if (verbose >= 2)
  300. fprintf(stderr, "%s: EAGAIN\n", __func__);
  301. break;
  302. default:
  303. if (verbose >= 2)
  304. fprintf(stderr, "%s: select failed: %s\n", __func__,
  305. strerror(errno));
  306. return -1;
  307. }
  308. }
  309. } while (eagain);
  310. return sret;
  311. }
  312. int socket_accept(int fd, uint16_t port)
  313. {
  314. #ifdef WIN32
  315. int addr_len;
  316. #else
  317. socklen_t addr_len;
  318. #endif
  319. int result;
  320. struct sockaddr_in addr;
  321. memset(&addr, 0, sizeof(addr));
  322. addr.sin_family = AF_INET;
  323. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  324. addr.sin_port = htons(port);
  325. addr_len = sizeof(addr);
  326. result = accept(fd, (struct sockaddr*)&addr, &addr_len);
  327. return result;
  328. }
  329. int socket_shutdown(int fd, int how)
  330. {
  331. return shutdown(fd, how);
  332. }
  333. int socket_close(int fd) {
  334. #ifdef WIN32
  335. return closesocket(fd);
  336. #else
  337. return close(fd);
  338. #endif
  339. }
  340. int socket_receive(int fd, void *data, size_t length)
  341. {
  342. return socket_receive_timeout(fd, data, length, 0, RECV_TIMEOUT);
  343. }
  344. int socket_peek(int fd, void *data, size_t length)
  345. {
  346. return socket_receive_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
  347. }
  348. int socket_receive_timeout(int fd, void *data, size_t length, int flags,
  349. unsigned int timeout)
  350. {
  351. int res;
  352. int result;
  353. // check if data is available
  354. res = socket_check_fd(fd, FDM_READ, timeout);
  355. if (res <= 0) {
  356. return res;
  357. }
  358. // if we get here, there _is_ data available
  359. result = recv(fd, data, length, flags);
  360. if (res > 0 && result == 0) {
  361. // but this is an error condition
  362. if (verbose >= 3)
  363. fprintf(stderr, "%s: fd=%d recv returned 0\n", __func__, fd);
  364. return -EAGAIN;
  365. }
  366. if (result < 0) {
  367. return -errno;
  368. }
  369. return result;
  370. }
  371. int socket_send(int fd, void *data, size_t length)
  372. {
  373. int flags = 0;
  374. #ifdef MSG_NOSIGNAL
  375. flags |= MSG_NOSIGNAL;
  376. #endif
  377. return send(fd, data, length, flags);
  378. }