PageRenderTime 3ms CodeModel.GetById 12ms app.highlight 26ms 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
 22#include <stdio.h>
 23#include <stddef.h>
 24#include <stdlib.h>
 25#include <string.h>
 26#include <unistd.h>
 27#include <errno.h>
 28#include <time.h>
 29#include <sys/stat.h>
 30#ifdef WIN32
 31#include <winsock2.h>
 32#include <windows.h>
 33static int wsa_init = 0;
 34#else
 35#include <sys/socket.h>
 36#include <sys/un.h>
 37#include <netinet/in.h>
 38#include <netdb.h>
 39#include <arpa/inet.h>
 40#endif
 41#include "socket.h"
 42
 43#define RECV_TIMEOUT 20000
 44
 45static int verbose = 0;
 46
 47void socket_set_verbose(int level)
 48{
 49    verbose = level;
 50}
 51
 52#ifndef WIN32
 53int socket_create_unix(const char *filename)
 54{
 55    struct sockaddr_un name;
 56    int sock;
 57    size_t size;
 58
 59    // remove if still present
 60    unlink(filename);
 61
 62    /* Create the socket. */
 63    sock = socket(PF_LOCAL, SOCK_STREAM, 0);
 64    if (sock < 0) {
 65        perror("socket");
 66        return -1;
 67    }
 68
 69    /* Bind a name to the socket. */
 70    name.sun_family = AF_LOCAL;
 71    strncpy(name.sun_path, filename, sizeof(name.sun_path));
 72    name.sun_path[sizeof(name.sun_path) - 1] = '\0';
 73
 74    /* The size of the address is
 75    the offset of the start of the filename,
 76    plus its length,
 77    plus one for the terminating null byte.
 78    Alternatively you can just do:
 79    size = SUN_LEN (&name);
 80    */
 81    size = (offsetof(struct sockaddr_un, sun_path)
 82        + strlen(name.sun_path) + 1);
 83
 84    if (bind(sock, (struct sockaddr *) &name, size) < 0) {
 85        perror("bind");
 86        socket_close(sock);
 87        return -1;
 88    }
 89
 90    if (listen(sock, 10) < 0) {
 91        perror("listen");
 92        socket_close(sock);
 93        return -1;
 94    }
 95
 96    return sock;
 97}
 98
 99int socket_connect_unix(const char *filename)
100{
101    struct sockaddr_un name;
102    int sfd = -1;
103    size_t size;
104    struct stat fst;
105
106    // check if socket file exists...
107    if (stat(filename, &fst) != 0) {
108        if (verbose >= 2)
109            fprintf(stderr, "%s: stat '%s': %s\n", __func__, filename,
110            strerror(errno));
111        return -1;
112    }
113    // ... and if it is a unix domain socket
114    if (!S_ISSOCK(fst.st_mode)) {
115        if (verbose >= 2)
116            fprintf(stderr, "%s: File '%s' is not a socket!\n", __func__,
117            filename);
118        return -1;
119    }
120    // make a new socket
121    if ((sfd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) {
122        if (verbose >= 2)
123            fprintf(stderr, "%s: socket: %s\n", __func__, strerror(errno));
124        return -1;
125    }
126    // and connect to 'filename'
127    name.sun_family = AF_LOCAL;
128    strncpy(name.sun_path, filename, sizeof(name.sun_path));
129    name.sun_path[sizeof(name.sun_path) - 1] = 0;
130
131    size = (offsetof(struct sockaddr_un, sun_path)
132        + strlen(name.sun_path) + 1);
133
134    if (connect(sfd, (struct sockaddr *) &name, size) < 0) {
135        socket_close(sfd);
136        if (verbose >= 2)
137            fprintf(stderr, "%s: connect: %s\n", __func__,
138            strerror(errno));
139        return -1;
140    }
141
142    return sfd;
143}
144#endif
145
146int socket_create(uint16_t port)
147{
148    return socket_create(port, false);
149}
150
151int socket_create(uint16_t port, int nonblocking)
152{
153    int sfd = -1;
154    int yes = 1;
155#ifdef WIN32
156    WSADATA wsa_data;
157    if (!wsa_init) {
158        if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != ERROR_SUCCESS) {
159            fprintf(stderr, "WSAStartup failed!\n");
160            ExitProcess(-1);
161        }
162        wsa_init = 1;
163    }
164#endif
165    struct sockaddr_in saddr;
166
167    if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
168        perror("socket()");
169        return -1;
170    }
171
172    if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
173        perror("setsockopt()");
174        socket_close(sfd);
175        return -1;
176    }
177
178    if (nonblocking) {
179        u_long iMode = 1;
180        if (ioctlsocket(sfd, FIONBIO, &iMode) != 0) {
181            perror("ioctlsocket()");
182            socket_close(sfd);
183            return -1;
184        }
185    }
186
187    memset((void *)&saddr, 0, sizeof(saddr));
188    saddr.sin_family = AF_INET;
189    saddr.sin_addr.s_addr = htonl(INADDR_ANY);
190    saddr.sin_port = htons(port);
191
192    if (0 > bind(sfd, (struct sockaddr *) &saddr, sizeof(saddr))) {
193        perror("bind()");
194        socket_close(sfd);
195        return -1;
196    }
197
198    if (listen(sfd, 1) == -1) {
199        perror("listen()");
200        socket_close(sfd);
201        return -1;
202    }
203
204    return sfd;
205}
206
207int socket_connect(const char *addr, uint16_t port)
208{
209    int sfd = -1;
210    int yes = 1;
211    struct hostent *hp;
212    struct sockaddr_in saddr;
213#ifdef WIN32
214    WSADATA wsa_data;
215    if (!wsa_init) {
216        if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != ERROR_SUCCESS) {
217            fprintf(stderr, "WSAStartup failed!\n");
218            ExitProcess(-1);
219        }
220        wsa_init = 1;
221    }
222#endif
223
224    if (!addr) {
225        errno = EINVAL;
226        return -1;
227    }
228
229    if ((hp = gethostbyname(addr)) == NULL) {
230        if (verbose >= 2)
231            fprintf(stderr, "%s: unknown host '%s'\n", __FUNCTION__, addr);
232        return -1;
233    }
234
235    if (!hp->h_addr) {
236        if (verbose >= 2)
237            fprintf(stderr, "%s: gethostbyname returned NULL address!\n",
238            __FUNCTION__);
239        return -1;
240    }
241
242    if (0 > (sfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP))) {
243        perror("socket()");
244        return -1;
245    }
246
247    if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (const char *)(void*)&yes, sizeof(int)) == -1) {
248        perror("setsockopt()");
249        socket_close(sfd);
250        return -1;
251    }
252
253    memset((void *)&saddr, 0, sizeof(saddr));
254    saddr.sin_family = AF_INET;
255    saddr.sin_addr.s_addr = *(uint32_t *)hp->h_addr;
256    saddr.sin_port = htons(port);
257
258    if (connect(sfd, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) {
259        perror("connect");
260        socket_close(sfd);
261        return -2;
262    }
263
264    return sfd;
265}
266
267int socket_check_fd(int fd, fd_mode fdm, unsigned int timeout)
268{
269    fd_set fds;
270    int sret;
271    int eagain;
272    struct timeval to;
273    struct timeval *pto;
274
275    if (fd <= 0) {
276        if (verbose >= 2)
277            fprintf(stderr, "ERROR: invalid fd in check_fd %d\n", fd);
278        return -1;
279    }
280
281    FD_ZERO(&fds);
282    FD_SET(fd, &fds);
283
284    if (timeout > 0) {
285        to.tv_sec = (time_t)(timeout / 1000);
286        to.tv_usec = (time_t)((timeout - (to.tv_sec * 1000)) * 1000);
287        pto = &to;
288    }
289    else {
290        pto = NULL;
291    }
292
293    sret = -1;
294
295    do {
296        eagain = 0;
297        switch (fdm) {
298        case FDM_READ:
299            sret = select(fd + 1, &fds, NULL, NULL, pto);
300            break;
301        case FDM_WRITE:
302            sret = select(fd + 1, NULL, &fds, NULL, pto);
303            break;
304        case FDM_EXCEPT:
305            sret = select(fd + 1, NULL, NULL, &fds, pto);
306            break;
307        default:
308            return -1;
309        }
310
311        if (sret < 0) {
312            switch (errno) {
313            case EINTR:
314                // interrupt signal in select
315                if (verbose >= 2)
316                    fprintf(stderr, "%s: EINTR\n", __FUNCTION__);
317                eagain = 1;
318                break;
319            case EAGAIN:
320                if (verbose >= 2)
321                    fprintf(stderr, "%s: EAGAIN\n", __FUNCTION__);
322                break;
323            default:
324                if (verbose >= 2)
325                    fprintf(stderr, "%s: select failed: %s\n", __FUNCTION__,
326                    strerror(errno));
327                return -1;
328            }
329        }
330    } while (eagain);
331
332    return sret;
333}
334
335int socket_accept(int fd, uint16_t port)
336{
337#ifdef WIN32
338    int addr_len;
339#else
340    socklen_t addr_len;
341#endif
342    int result;
343    struct sockaddr_in addr;
344
345    memset(&addr, 0, sizeof(addr));
346    addr.sin_family = AF_INET;
347    addr.sin_addr.s_addr = htonl(INADDR_ANY);
348    addr.sin_port = htons(port);
349
350    addr_len = sizeof(addr);
351    result = accept(fd, (struct sockaddr*)&addr, &addr_len);
352
353    return result;
354}
355
356int socket_shutdown(int fd, int how)
357{
358    return shutdown(fd, how);
359}
360
361int socket_close(int fd) {
362#ifdef WIN32
363    return closesocket(fd);
364#else
365    return close(fd);
366#endif
367}
368
369int socket_receive(int fd, void *data, size_t length)
370{
371    return socket_receive_timeout(fd, data, length, 0, RECV_TIMEOUT);
372}
373
374int socket_peek(int fd, void *data, size_t length)
375{
376    return socket_receive_timeout(fd, data, length, MSG_PEEK, RECV_TIMEOUT);
377}
378
379int socket_receive_timeout(int fd, void *data, size_t length, int flags,
380    unsigned int timeout)
381{
382    int res;
383    int result;
384
385    // check if data is available
386    res = socket_check_fd(fd, FDM_READ, timeout);
387    if (res <= 0) {
388        return res;
389    }
390    // if we get here, there _is_ data available
391    result = recv(fd, (char *)data, length, flags);
392    if (res > 0 && result == 0) {
393        // but this is an error condition
394        if (verbose >= 3)
395            fprintf(stderr, "%s: fd=%d recv returned 0\n", __FUNCTION__, fd);
396        return -EAGAIN;
397    }
398    if (result < 0) {
399        return -errno;
400    }
401    return result;
402}
403
404int socket_send(int fd, void *data, size_t length)
405{
406    return send(fd, (char *)data, length, 0);
407}