PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/vendors/socket/socket.c

https://bitbucket.org/hjwhang/libimobiledevice-win32
C | 407 lines | 315 code | 54 blank | 38 comment | 54 complexity | 1286513200f32ba1b6e6d292695db1d2 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. return socket_create(port, false);
  131. }
  132. int socket_create(uint16_t port, int nonblocking)
  133. {
  134. int sfd = -1;
  135. int yes = 1;
  136. #ifdef WIN32
  137. WSADATA wsa_data;
  138. if (!wsa_init) {
  139. if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != ERROR_SUCCESS) {
  140. fprintf(stderr, "WSAStartup failed!\n");
  141. ExitProcess(-1);
  142. }
  143. wsa_init = 1;
  144. }
  145. #endif
  146. struct sockaddr_in saddr;
  147. if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
  148. perror("socket()");
  149. return -1;
  150. }
  151. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
  152. perror("setsockopt()");
  153. socket_close(sfd);
  154. return -1;
  155. }
  156. if (nonblocking) {
  157. u_long iMode = 1;
  158. if (ioctlsocket(sfd, FIONBIO, &iMode) != 0) {
  159. perror("ioctlsocket()");
  160. socket_close(sfd);
  161. return -1;
  162. }
  163. }
  164. memset((void *)&saddr, 0, sizeof(saddr));
  165. saddr.sin_family = AF_INET;
  166. saddr.sin_addr.s_addr = htonl(INADDR_ANY);
  167. saddr.sin_port = htons(port);
  168. if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
  169. perror("bind()");
  170. socket_close(sfd);
  171. return -1;
  172. }
  173. if (listen(sfd, 1) == -1) {
  174. perror("listen()");
  175. socket_close(sfd);
  176. return -1;
  177. }
  178. return sfd;
  179. }
  180. int socket_connect(const char *addr, uint16_t port)
  181. {
  182. int sfd = -1;
  183. int yes = 1;
  184. struct hostent *hp;
  185. struct sockaddr_in saddr;
  186. #ifdef WIN32
  187. WSADATA wsa_data;
  188. if (!wsa_init) {
  189. if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != ERROR_SUCCESS) {
  190. fprintf(stderr, "WSAStartup failed!\n");
  191. ExitProcess(-1);
  192. }
  193. wsa_init = 1;
  194. }
  195. #endif
  196. if (!addr) {
  197. errno = EINVAL;
  198. return -1;
  199. }
  200. if ((hp = gethostbyname(addr)) == NULL) {
  201. if (verbose >= 2)
  202. fprintf(stderr, "%s: unknown host '%s'\n", __FUNCTION__, addr);
  203. return -1;
  204. }
  205. if (!hp->h_addr) {
  206. if (verbose >= 2)
  207. fprintf(stderr, "%s: gethostbyname returned NULL address!\n",
  208. __FUNCTION__);
  209. return -1;
  210. }
  211. if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
  212. perror("socket()");
  213. return -1;
  214. }
  215. if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
  216. perror("setsockopt()");
  217. socket_close(sfd);
  218. return -1;
  219. }
  220. memset((void *)&saddr, 0, sizeof(saddr));
  221. saddr.sin_family = AF_INET;
  222. saddr.sin_addr.s_addr = *(uint32_t *)hp->h_addr;
  223. saddr.sin_port = htons(port);
  224. if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
  225. perror("connect");
  226. socket_close(sfd);
  227. return -2;
  228. }
  229. return sfd;
  230. }
  231. int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout)
  232. {
  233. fd_set fds;
  234. int sret;
  235. int eagain;
  236. struct timeval to;
  237. struct timeval *pto;
  238. if (fd <= 0) {
  239. if (verbose >= 2)
  240. fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
  241. return -1;
  242. }
  243. FD_ZERO(&fds);
  244. FD_SET(fd, &fds);
  245. if (timeout > 0) {
  246. to.tv_sec = (time_t)(timeout / 1000);
  247. to.tv_usec = (time_t)((timeout - (to.tv_sec * 1000)) * 1000);
  248. pto = &to;
  249. }
  250. else {
  251. pto = NULL;
  252. }
  253. sret = -1;
  254. do {
  255. eagain = 0;
  256. switch (fdm) {
  257. case FDM_READ:
  258. sret = select(fd + 1, &fds, NULL, NULL, pto);
  259. break;
  260. case FDM_WRITE:
  261. sret = select(fd + 1, NULL, &fds, NULL, pto);
  262. break;
  263. case FDM_EXCEPT:
  264. sret = select(fd + 1, NULL, NULL, &fds, pto);
  265. break;
  266. default:
  267. return -1;
  268. }
  269. if (sret < 0) {
  270. switch (errno) {
  271. case EINTR:
  272. // interrupt signal in select
  273. if (verbose >= 2)
  274. fprintf(stderr, "%s: EINTR\n", __FUNCTION__);
  275. eagain = 1;
  276. break;
  277. case EAGAIN:
  278. if (verbose >= 2)
  279. fprintf(stderr, "%s: EAGAIN\n", __FUNCTION__);
  280. break;
  281. default:
  282. if (verbose >= 2)
  283. fprintf(stderr, "%s: select failed: %s\n", __FUNCTION__,
  284. strerror(errno));
  285. return -1;
  286. }
  287. }
  288. } while (eagain);
  289. return sret;
  290. }
  291. int socket_accept(int fd, uint16_t port)
  292. {
  293. #ifdef WIN32
  294. int addr_len;
  295. #else
  296. socklen_t addr_len;
  297. #endif
  298. int result;
  299. struct sockaddr_in addr;
  300. memset(&addr, 0, sizeof(addr));
  301. addr.sin_family = AF_INET;
  302. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  303. addr.sin_port = htons(port);
  304. addr_len = sizeof(addr);
  305. result = accept(fd, (struct sockaddr*)&addr, &addr_len);
  306. return result;
  307. }
  308. int socket_shutdown(int fd, int how)
  309. {
  310. return shutdown(fd, how);
  311. }
  312. int socket_close(int fd) {
  313. #ifdef WIN32
  314. return closesocket(fd);
  315. #else
  316. return close(fd);
  317. #endif
  318. }
  319. int socket_receive(int fd, void *data, size_t length)
  320. {
  321. return socket_receive_timeout(fd, data, length, 0, RECV_TIMEOUT);
  322. }
  323. int socket_peek(int fd, void *data, size_t length)
  324. {
  325. return socket_receive_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
  326. }
  327. int socket_receive_timeout(int fd, void *data, size_t length, int flags,
  328. unsigned int timeout)
  329. {
  330. int res;
  331. int result;
  332. // check if data is available
  333. res = socket_check_fd(fd, FDM_READ, timeout);
  334. if (res <= 0) {
  335. return res;
  336. }
  337. // if we get here, there _is_ data available
  338. result = recv(fd, (char *)data, length, flags);
  339. if (res > 0 && result == 0) {
  340. // but this is an error condition
  341. if (verbose >= 3)
  342. fprintf(stderr, "%s: fd=%d recv returned 0\n", __FUNCTION__, fd);
  343. return -EAGAIN;
  344. }
  345. if (result < 0) {
  346. return -errno;
  347. }
  348. return result;
  349. }
  350. int socket_send(int fd, void *data, size_t length)
  351. {
  352. return send(fd, (char *)data, length, 0);
  353. }