PageRenderTime 54ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/vendors/socket/socket.c

https://github.com/outbred/libimobiledevice-win32
C | 392 lines | 302 code | 52 blank | 38 comment | 51 complexity | 8964894a11489210a42e4f904cd17412 MD5 | raw file
  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 <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. // remove if still present
  54. unlink(filename);
  55. /* Create the socket. */
  56. sock = socket(PF_LOCAL, SOCK_STREAM, 0);
  57. if (sock < 0) {
  58. perror("socket");
  59. return -1;
  60. }
  61. /* Bind a name to the socket. */
  62. name.sun_family = AF_LOCAL;
  63. strncpy(name.sun_path, filename, sizeof(name.sun_path));
  64. name.sun_path[sizeof(name.sun_path) - 1] = '\0';
  65. /* The size of the address is
  66. the offset of the start of the filename,
  67. plus its length,
  68. plus one for the terminating null byte.
  69. Alternatively you can just do:
  70. size = SUN_LEN (&name);
  71. */
  72. size = (offsetof(struct sockaddr_un, sun_path)
  73. + strlen(name.sun_path) + 1);
  74. if (bind(sock, (struct sockaddr *) &name, size) < 0) {
  75. perror("bind");
  76. socket_close(sock);
  77. return -1;
  78. }
  79. if (listen(sock, 10) < 0) {
  80. perror("listen");
  81. socket_close(sock);
  82. return -1;
  83. }
  84. return sock;
  85. }
  86. int socket_connect_unix(const char *filename)
  87. {
  88. struct sockaddr_un name;
  89. int sfd = -1;
  90. size_t size;
  91. struct stat fst;
  92. // check if socket file exists...
  93. if (stat(filename, &fst) != 0) {
  94. if (verbose >= 2)
  95. fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename,
  96. strerror(errno));
  97. return -1;
  98. }
  99. // ... and if it is a unix domain socket
  100. if (!S_ISSOCK(fst.st_mode)) {
  101. if (verbose >= 2)
  102. fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__,
  103. filename);
  104. return -1;
  105. }
  106. // make a new socket
  107. if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
  108. if (verbose >= 2)
  109. fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
  110. return -1;
  111. }
  112. // and connect to 'filename'
  113. name.sun_family = AF_LOCAL;
  114. strncpy(name.sun_path, filename, sizeof(name.sun_path));
  115. name.sun_path[sizeof(name.sun_path) - 1] = 0;
  116. size = (offsetof(struct sockaddr_un, sun_path)
  117. + strlen(name.sun_path) + 1);
  118. if (connect(sfd, (struct sockaddr *) &name, size) < 0) {
  119. socket_close(sfd);
  120. if (verbose >= 2)
  121. fprintf(stderr, "%s: connect: %s\n", __func__,
  122. strerror(errno));
  123. return -1;
  124. }
  125. return sfd;
  126. }
  127. #endif
  128. int socket_create(uint16_t port)
  129. {
  130. int sfd = -1;
  131. int yes = 1;
  132. #ifdef WIN32
  133. WSADATA wsa_data;
  134. if (!wsa_init) {
  135. if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
  136. fprintf(stderr, "WSAStartup failed!\n");
  137. ExitProcess(-1);
  138. }
  139. wsa_init = 1;
  140. }
  141. #endif
  142. struct sockaddr_in saddr;
  143. if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
  144. perror("socket()");
  145. return -1;
  146. }
  147. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
  148. perror("setsockopt()");
  149. socket_close(sfd);
  150. return -1;
  151. }
  152. memset((void *) &saddr, 0, sizeof(saddr));
  153. saddr.sin_family = AF_INET;
  154. saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  155. saddr.sin_port = htons(port);
  156. if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
  157. perror("bind()");
  158. socket_close(sfd);
  159. return -1;
  160. }
  161. if (listen(sfd, 1) == -1) {
  162. perror("listen()");
  163. socket_close(sfd);
  164. return -1;
  165. }
  166. return sfd;
  167. }
  168. int socket_connect(const char *addr, uint16_t port)
  169. {
  170. int sfd = -1;
  171. int yes = 1;
  172. struct hostent *hp;
  173. struct sockaddr_in saddr;
  174. #ifdef WIN32
  175. WSADATA wsa_data;
  176. if (!wsa_init) {
  177. if (WSAStartup(MAKEWORD(2,2), &wsa_data) != ERROR_SUCCESS) {
  178. fprintf(stderr, "WSAStartup failed!\n");
  179. ExitProcess(-1);
  180. }
  181. wsa_init = 1;
  182. }
  183. #endif
  184. if (!addr) {
  185. errno = EINVAL;
  186. return -1;
  187. }
  188. if ((hp = gethostbyname(addr)) == NULL) {
  189. if (verbose >= 2)
  190. fprintf(stderr, "%s: unknown host '%s'\n", __FUNCTION__, addr);
  191. return -1;
  192. }
  193. if (!hp->h_addr) {
  194. if (verbose >= 2)
  195. fprintf(stderr, "%s: gethostbyname returned NULL address!\n",
  196. __FUNCTION__);
  197. return -1;
  198. }
  199. if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
  200. perror("socket()");
  201. return -1;
  202. }
  203. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
  204. perror("setsockopt()");
  205. socket_close(sfd);
  206. return -1;
  207. }
  208. memset((void *) &saddr, 0, sizeof(saddr));
  209. saddr.sin_family = AF_INET;
  210. saddr.sin_addr.s_addr = *(uint32_t *) hp->h_addr;
  211. saddr.sin_port = htons(port);
  212. if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
  213. perror("connect");
  214. socket_close(sfd);
  215. return -2;
  216. }
  217. return sfd;
  218. }
  219. int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout)
  220. {
  221. fd_set fds;
  222. int sret;
  223. int eagain;
  224. struct timeval to;
  225. struct timeval *pto;
  226. if (fd <= 0) {
  227. if (verbose >= 2)
  228. fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
  229. return -1;
  230. }
  231. FD_ZERO(&fds);
  232. FD_SET(fd, &fds);
  233. if (timeout > 0) {
  234. to.tv_sec = (time_t) (timeout / 1000);
  235. to.tv_usec = (time_t) ((timeout - (to.tv_sec * 1000)) * 1000);
  236. pto = &to;
  237. } else {
  238. pto = NULL;
  239. }
  240. sret = -1;
  241. do {
  242. eagain = 0;
  243. switch (fdm) {
  244. case FDM_READ:
  245. sret = select(fd + 1, &fds, NULL, NULL, pto);
  246. break;
  247. case FDM_WRITE:
  248. sret = select(fd + 1, NULL, &fds, NULL, pto);
  249. break;
  250. case FDM_EXCEPT:
  251. sret = select(fd + 1, NULL, NULL, &fds, pto);
  252. break;
  253. default:
  254. return -1;
  255. }
  256. if (sret < 0) {
  257. switch (errno) {
  258. case EINTR:
  259. // interrupt signal in select
  260. if (verbose >= 2)
  261. fprintf(stderr, "%s: EINTR\n", __FUNCTION__);
  262. eagain = 1;
  263. break;
  264. case EAGAIN:
  265. if (verbose >= 2)
  266. fprintf(stderr, "%s: EAGAIN\n", __FUNCTION__);
  267. break;
  268. default:
  269. if (verbose >= 2)
  270. fprintf(stderr, "%s: select failed: %s\n", __FUNCTION__,
  271. strerror(errno));
  272. return -1;
  273. }
  274. }
  275. } while (eagain);
  276. return sret;
  277. }
  278. int socket_accept(int fd, uint16_t port)
  279. {
  280. #ifdef WIN32
  281. int addr_len;
  282. #else
  283. socklen_t addr_len;
  284. #endif
  285. int result;
  286. struct sockaddr_in addr;
  287. memset(&addr, 0, sizeof(addr));
  288. addr.sin_family = AF_INET;
  289. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  290. addr.sin_port = htons(port);
  291. addr_len = sizeof(addr);
  292. result = accept(fd, (struct sockaddr*)&addr, &addr_len);
  293. return result;
  294. }
  295. int socket_shutdown(int fd, int how)
  296. {
  297. return shutdown(fd, how);
  298. }
  299. int socket_close(int fd) {
  300. #ifdef WIN32
  301. return closesocket(fd);
  302. #else
  303. return close(fd);
  304. #endif
  305. }
  306. int socket_receive(int fd, void *data, size_t length)
  307. {
  308. return socket_receive_timeout(fd, data, length, 0, RECV_TIMEOUT);
  309. }
  310. int socket_peek(int fd, void *data, size_t length)
  311. {
  312. return socket_receive_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
  313. }
  314. int socket_receive_timeout(int fd, void *data, size_t length, int flags,
  315. unsigned int timeout)
  316. {
  317. int res;
  318. int result;
  319. // check if data is available
  320. res = socket_check_fd(fd, FDM_READ, timeout);
  321. if (res <= 0) {
  322. return res;
  323. }
  324. // if we get here, there _is_ data available
  325. result = recv(fd, (char *)data, length, flags);
  326. if (res > 0 && result == 0) {
  327. // but this is an error condition
  328. if (verbose >= 3)
  329. fprintf(stderr, "%s: fd=%d recv returned 0\n", __FUNCTION__, fd);
  330. return -EAGAIN;
  331. }
  332. if (result < 0) {
  333. return -errno;
  334. }
  335. return result;
  336. }
  337. int socket_send(int fd, void *data, size_t length)
  338. {
  339. return send(fd, (char *)data, length, 0);
  340. }