1 | /* $Id: receivedata.c,v 1.10 2021/03/02 23:33:07 nanard Exp $ */ |
2 | /* Project : miniupnp |
3 | * Website : http://miniupnp.free.fr/ |
4 | * Author : Thomas Bernard |
5 | * Copyright (c) 2011-2021 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 | #include "receivedata.h" |
31 | |
32 | int |
33 | receivedata(SOCKET socket, |
34 | char * data, int length, |
35 | int timeout, unsigned int * scope_id) |
36 | { |
37 | #ifdef MINIUPNPC_GET_SRC_ADDR |
38 | struct sockaddr_storage src_addr; |
39 | socklen_t src_addr_len = sizeof(src_addr); |
40 | #endif /* MINIUPNPC_GET_SRC_ADDR */ |
41 | int n; |
42 | #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) |
43 | /* using poll */ |
44 | struct pollfd fds[1]; /* for the poll */ |
45 | #ifdef MINIUPNPC_IGNORE_EINTR |
46 | do { |
47 | #endif /* MINIUPNPC_IGNORE_EINTR */ |
48 | fds[0].fd = socket; |
49 | fds[0].events = POLLIN; |
50 | n = poll(fds, 1, timeout); |
51 | #ifdef MINIUPNPC_IGNORE_EINTR |
52 | } while(n < 0 && errno == EINTR); |
53 | #endif /* MINIUPNPC_IGNORE_EINTR */ |
54 | if(n < 0) { |
55 | PRINT_SOCKET_ERROR("poll" ); |
56 | return -1; |
57 | } else if(n == 0) { |
58 | /* timeout */ |
59 | return 0; |
60 | } |
61 | #else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ |
62 | /* using select under _WIN32 and amigaos */ |
63 | fd_set socketSet; |
64 | TIMEVAL timeval; |
65 | FD_ZERO(&socketSet); |
66 | FD_SET(socket, &socketSet); |
67 | timeval.tv_sec = timeout / 1000; |
68 | timeval.tv_usec = (timeout % 1000) * 1000; |
69 | n = select(FD_SETSIZE, &socketSet, NULL, NULL, &timeval); |
70 | if(n < 0) { |
71 | PRINT_SOCKET_ERROR("select" ); |
72 | return -1; |
73 | } else if(n == 0) { |
74 | return 0; |
75 | } |
76 | #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ |
77 | #ifdef MINIUPNPC_GET_SRC_ADDR |
78 | memset(&src_addr, 0, sizeof(src_addr)); |
79 | n = recvfrom(socket, data, length, 0, |
80 | (struct sockaddr *)&src_addr, &src_addr_len); |
81 | #else /* MINIUPNPC_GET_SRC_ADDR */ |
82 | n = recv(socket, data, length, 0); |
83 | #endif /* MINIUPNPC_GET_SRC_ADDR */ |
84 | if(n<0) { |
85 | PRINT_SOCKET_ERROR("recv" ); |
86 | } |
87 | #ifdef MINIUPNPC_GET_SRC_ADDR |
88 | if (src_addr.ss_family == AF_INET6) { |
89 | const struct sockaddr_in6 * src_addr6 = (struct sockaddr_in6 *)&src_addr; |
90 | #ifdef DEBUG |
91 | printf("scope_id=%u\n" , src_addr6->sin6_scope_id); |
92 | #endif /* DEBUG */ |
93 | if(scope_id) |
94 | *scope_id = src_addr6->sin6_scope_id; |
95 | } else { |
96 | if(scope_id) |
97 | *scope_id = 0; |
98 | } |
99 | #else /* MINIUPNPC_GET_SRC_ADDR */ |
100 | if(scope_id) |
101 | *scope_id = 0; |
102 | #endif /* MINIUPNPC_GET_SRC_ADDR */ |
103 | return n; |
104 | } |
105 | |
106 | |