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