1/* $Id: receivedata.c,v 1.6 2014/11/13 13:51:52 nanard Exp $ */ 2/* Project : miniupnp 3 * Website : http://miniupnp.free.fr/ 4 * Author : Thomas Bernard 5 * Copyright (c) 2011-2014 Thomas Bernard 6 * This software is subject to the conditions detailed in the 7 * LICENCE file provided in this distribution. */ 8 9#include <stdio.h> 10#include <string.h> 11#ifdef _WIN32 12#include <winsock2.h> 13#include <ws2tcpip.h> 14#else /* _WIN32 */ 15#include <unistd.h> 16#if defined(__amigaos__) && !defined(__amigaos4__) 17#define socklen_t int 18#else /* #if defined(__amigaos__) && !defined(__amigaos4__) */ 19#include <sys/select.h> 20#endif /* #else defined(__amigaos__) && !defined(__amigaos4__) */ 21#include <sys/socket.h> 22#include <netinet/in.h> 23#if !defined(__amigaos__) && !defined(__amigaos4__) 24#include <poll.h> 25#endif /* !defined(__amigaos__) && !defined(__amigaos4__) */ 26#include <errno.h> 27#define MINIUPNPC_IGNORE_EINTR 28#endif /* _WIN32 */ 29 30#ifdef _WIN32 31#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); 32#else 33#define PRINT_SOCKET_ERROR(x) perror(x) 34#endif 35 36#include "receivedata.h" 37 38int 39receivedata(int socket, 40 char * data, int length, 41 int timeout, unsigned int * scope_id) 42{ 43#if MINIUPNPC_GET_SRC_ADDR 44 struct sockaddr_storage src_addr; 45 socklen_t src_addr_len = sizeof(src_addr); 46#endif /* MINIUPNPC_GET_SRC_ADDR */ 47 int n; 48#if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) 49 /* using poll */ 50 struct pollfd fds[1]; /* for the poll */ 51#ifdef MINIUPNPC_IGNORE_EINTR 52 do { 53#endif /* MINIUPNPC_IGNORE_EINTR */ 54 fds[0].fd = socket; 55 fds[0].events = POLLIN; 56 n = poll(fds, 1, timeout); 57#ifdef MINIUPNPC_IGNORE_EINTR 58 } while(n < 0 && errno == EINTR); 59#endif /* MINIUPNPC_IGNORE_EINTR */ 60 if(n < 0) { 61 PRINT_SOCKET_ERROR("poll"); 62 return -1; 63 } else if(n == 0) { 64 /* timeout */ 65 return 0; 66 } 67#else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ 68 /* using select under _WIN32 and amigaos */ 69 fd_set socketSet; 70 TIMEVAL timeval; 71 FD_ZERO(&socketSet); 72 FD_SET(socket, &socketSet); 73 timeval.tv_sec = timeout / 1000; 74 timeval.tv_usec = (timeout % 1000) * 1000; 75 n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); 76 if(n < 0) { 77 PRINT_SOCKET_ERROR("select"); 78 return -1; 79 } else if(n == 0) { 80 return 0; 81 } 82#endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ 83#if MINIUPNPC_GET_SRC_ADDR 84 memset(&src_addr, 0, sizeof(src_addr)); 85 n = recvfrom(socket, data, length, 0, 86 (struct sockaddr *)&src_addr, &src_addr_len); 87#else /* MINIUPNPC_GET_SRC_ADDR */ 88 n = recv(socket, data, length, 0); 89#endif /* MINIUPNPC_GET_SRC_ADDR */ 90 if(n<0) { 91 PRINT_SOCKET_ERROR("recv"); 92 } 93#if MINIUPNPC_GET_SRC_ADDR 94 if (src_addr.ss_family == AF_INET6) { 95 const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; 96#ifdef DEBUG 97 printf("scope_id=%u\n", src_addr6->sin6_scope_id); 98#endif /* DEBUG */ 99 if(scope_id) 100 *scope_id = src_addr6->sin6_scope_id; 101 } 102#endif /* MINIUPNPC_GET_SRC_ADDR */ 103 return n; 104} 105 106