2 * TCP networking functions
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "tropicssl/config.h"
38 #if defined(TROPICSSL_NET_C)
40 #include "tropicssl/net.h"
42 #if defined(WIN32) || defined(_WIN32_WCE)
47 #if defined(_WIN32_WCE)
48 #pragma comment( lib, "ws2.lib" )
50 #pragma comment( lib, "ws2_32.lib" )
53 #define read(fd,buf,len) recv(fd,buf,len,0)
54 #define write(fd,buf,len) send(fd,buf,len,0)
55 #define close(fd) closesocket(fd)
57 static int wsa_init_done
= 0;
61 #include <sys/types.h>
62 #include <sys/socket.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
80 * htons() is not always available
82 #if defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN
85 #define HTONS(n) (((((unsigned short)(n) & 0xFF)) << 8) | (((unsigned short)(n) & 0xFF00) >> 8))
87 #define net_htons(n) HTONS(n)
89 * Initiate a TCP connection with host:port
91 int net_connect(int *fd
, const char *host
, int port
)
93 struct sockaddr_in server_addr
;
94 struct hostent
*server_host
;
96 #if defined(WIN32) || defined(_WIN32_WCE)
100 if (wsa_init_done
== 0) {
101 if (WSAStartup(MAKEWORD(2, 0), &wsaData
) == SOCKET_ERROR
)
102 return (TROPICSSL_ERR_NET_SOCKET_FAILED
);
108 signal(SIGPIPE
, SIG_IGN
);
111 if ((server_host
= gethostbyname(host
)) == NULL
)
112 return (TROPICSSL_ERR_NET_UNKNOWN_HOST
);
114 if ((*fd
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
)) < 0)
115 return (TROPICSSL_ERR_NET_SOCKET_FAILED
);
117 memcpy((void *)&server_addr
.sin_addr
,
118 (void *)server_host
->h_addr
, server_host
->h_length
);
120 server_addr
.sin_family
= AF_INET
;
121 server_addr
.sin_port
= net_htons(port
);
123 if (connect(*fd
, (struct sockaddr
*)&server_addr
,
124 sizeof(server_addr
)) < 0) {
127 return (TROPICSSL_ERR_NET_CONNECT_FAILED
);
134 * Create a listening socket on bind_ip:port
136 int net_bind(int *fd
, const char *bind_ip
, int port
)
139 struct sockaddr_in server_addr
;
141 #if defined(WIN32) || defined(_WIN32_WCE)
145 if (wsa_init_done
== 0) {
146 if (WSAStartup(MAKEWORD(2, 0), &wsaData
) == SOCKET_ERROR
)
147 return (TROPICSSL_ERR_NET_SOCKET_FAILED
);
153 signal(SIGPIPE
, SIG_IGN
);
156 if ((*fd
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_IP
)) < 0)
157 return (TROPICSSL_ERR_NET_SOCKET_FAILED
);
160 setsockopt(*fd
, SOL_SOCKET
, SO_REUSEADDR
, (const char *)&n
, sizeof(n
));
162 server_addr
.sin_addr
.s_addr
= INADDR_ANY
;
163 server_addr
.sin_family
= AF_INET
;
164 server_addr
.sin_port
= net_htons(port
);
166 if (bind_ip
!= NULL
) {
167 memset(c
, 0, sizeof(c
));
168 sscanf(bind_ip
, "%d.%d.%d.%d", &c
[0], &c
[1], &c
[2], &c
[3]);
170 for (n
= 0; n
< 4; n
++)
171 if (c
[n
] < 0 || c
[n
] > 255)
175 server_addr
.sin_addr
.s_addr
=
176 ((unsigned long)c
[0] << 24) |
177 ((unsigned long)c
[1] << 16) |
178 ((unsigned long)c
[2] << 8) | ((unsigned long)c
[3]);
181 if (bind(*fd
, (struct sockaddr
*)&server_addr
, sizeof(server_addr
)) < 0) {
184 return (TROPICSSL_ERR_NET_BIND_FAILED
);
187 if (listen(*fd
, 10) != 0) {
190 return (TROPICSSL_ERR_NET_LISTEN_FAILED
);
197 * Check if the current operation is blocking
199 static int net_is_blocking(void)
201 #if defined(WIN32) || defined(_WIN32_WCE)
202 return (WSAGetLastError() == WSAEWOULDBLOCK
);
208 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
218 * Accept a connection from a remote client
220 int net_accept(int bind_fd
, int *client_fd
, void *client_ip
)
222 struct sockaddr_in client_addr
;
224 #if defined(__socklen_t_defined)
225 socklen_t n
= (socklen_t
) sizeof(client_addr
);
227 int n
= (int)sizeof(client_addr
);
230 *client_fd
= accept(bind_fd
, (struct sockaddr
*)
233 if (*client_fd
< 0) {
234 if (net_is_blocking() != 0)
235 return (TROPICSSL_ERR_NET_TRY_AGAIN
);
237 return (TROPICSSL_ERR_NET_ACCEPT_FAILED
);
240 if (client_ip
!= NULL
)
241 memcpy(client_ip
, &client_addr
.sin_addr
.s_addr
,
242 sizeof(client_addr
.sin_addr
.s_addr
));
248 * Set the socket blocking or non-blocking
250 int net_set_block(int fd
)
252 #if defined(WIN32) || defined(_WIN32_WCE)
254 return (ioctlsocket(fd
, FIONBIO
, &n
));
256 return (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) & ~O_NONBLOCK
));
260 int net_set_nonblock(int fd
)
262 #if defined(WIN32) || defined(_WIN32_WCE)
264 return (ioctlsocket(fd
, FIONBIO
, &n
));
266 return (fcntl(fd
, F_SETFL
, fcntl(fd
, F_GETFL
) | O_NONBLOCK
));
271 * Portable usleep helper
273 void net_usleep(unsigned long usec
)
278 select(0, NULL
, NULL
, NULL
, &tv
);
282 * Read at most 'len' characters
284 int net_recv(void *ctx
, unsigned char *buf
, int len
)
286 int ret
= read(*((int *)ctx
), buf
, len
);
288 if (len
> 0 && ret
== 0)
289 return (TROPICSSL_ERR_NET_CONN_RESET
);
292 if (net_is_blocking() != 0)
293 return (TROPICSSL_ERR_NET_TRY_AGAIN
);
295 #if defined(WIN32) || defined(_WIN32_WCE)
296 if (WSAGetLastError() == WSAECONNRESET
)
297 return (TROPICSSL_ERR_NET_CONN_RESET
);
299 if (errno
== EPIPE
|| errno
== ECONNRESET
)
300 return (TROPICSSL_ERR_NET_CONN_RESET
);
303 return (TROPICSSL_ERR_NET_TRY_AGAIN
);
306 return (TROPICSSL_ERR_NET_RECV_FAILED
);
313 * Write at most 'len' characters
315 int net_send(void *ctx
, const unsigned char *buf
, int len
)
317 int ret
= write(*((int *)ctx
), buf
, len
);
320 if (net_is_blocking() != 0)
321 return (TROPICSSL_ERR_NET_TRY_AGAIN
);
323 #if defined(WIN32) || defined(_WIN32_WCE)
324 if (WSAGetLastError() == WSAECONNRESET
)
325 return (TROPICSSL_ERR_NET_CONN_RESET
);
327 if (errno
== EPIPE
|| errno
== ECONNRESET
)
328 return (TROPICSSL_ERR_NET_CONN_RESET
);
331 return (TROPICSSL_ERR_NET_TRY_AGAIN
);
334 return (TROPICSSL_ERR_NET_SEND_FAILED
);
341 * Gracefully close the connection
343 void net_close(int fd
)