mbed client lightswitch demo

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of mbed-client-classic-example-lwip by Austin Blackstone

Committer:
mbedAustin
Date:
Thu Jun 09 17:08:36 2016 +0000
Revision:
11:cada08fc8a70
Commit for public Consumption

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mbedAustin 11:cada08fc8a70 1 /*
mbedAustin 11:cada08fc8a70 2 * TCP/IP or UDP/IP networking functions
mbedAustin 11:cada08fc8a70 3 *
mbedAustin 11:cada08fc8a70 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
mbedAustin 11:cada08fc8a70 5 * SPDX-License-Identifier: Apache-2.0
mbedAustin 11:cada08fc8a70 6 *
mbedAustin 11:cada08fc8a70 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
mbedAustin 11:cada08fc8a70 8 * not use this file except in compliance with the License.
mbedAustin 11:cada08fc8a70 9 * You may obtain a copy of the License at
mbedAustin 11:cada08fc8a70 10 *
mbedAustin 11:cada08fc8a70 11 * http://www.apache.org/licenses/LICENSE-2.0
mbedAustin 11:cada08fc8a70 12 *
mbedAustin 11:cada08fc8a70 13 * Unless required by applicable law or agreed to in writing, software
mbedAustin 11:cada08fc8a70 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
mbedAustin 11:cada08fc8a70 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
mbedAustin 11:cada08fc8a70 16 * See the License for the specific language governing permissions and
mbedAustin 11:cada08fc8a70 17 * limitations under the License.
mbedAustin 11:cada08fc8a70 18 *
mbedAustin 11:cada08fc8a70 19 * This file is part of mbed TLS (https://tls.mbed.org)
mbedAustin 11:cada08fc8a70 20 */
mbedAustin 11:cada08fc8a70 21
mbedAustin 11:cada08fc8a70 22 #if !defined(MBEDTLS_CONFIG_FILE)
mbedAustin 11:cada08fc8a70 23 #include "mbedtls/config.h"
mbedAustin 11:cada08fc8a70 24 #else
mbedAustin 11:cada08fc8a70 25 #include MBEDTLS_CONFIG_FILE
mbedAustin 11:cada08fc8a70 26 #endif
mbedAustin 11:cada08fc8a70 27
mbedAustin 11:cada08fc8a70 28 #if defined(MBEDTLS_NET_C)
mbedAustin 11:cada08fc8a70 29
mbedAustin 11:cada08fc8a70 30 #include "mbedtls/net.h"
mbedAustin 11:cada08fc8a70 31
mbedAustin 11:cada08fc8a70 32 #include <string.h>
mbedAustin 11:cada08fc8a70 33
mbedAustin 11:cada08fc8a70 34 #if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 35 !defined(EFI32)
mbedAustin 11:cada08fc8a70 36
mbedAustin 11:cada08fc8a70 37 #ifdef _WIN32_WINNT
mbedAustin 11:cada08fc8a70 38 #undef _WIN32_WINNT
mbedAustin 11:cada08fc8a70 39 #endif
mbedAustin 11:cada08fc8a70 40 /* Enables getaddrinfo() & Co */
mbedAustin 11:cada08fc8a70 41 #define _WIN32_WINNT 0x0501
mbedAustin 11:cada08fc8a70 42 #include <ws2tcpip.h>
mbedAustin 11:cada08fc8a70 43
mbedAustin 11:cada08fc8a70 44 #include <winsock2.h>
mbedAustin 11:cada08fc8a70 45 #include <windows.h>
mbedAustin 11:cada08fc8a70 46
mbedAustin 11:cada08fc8a70 47 #if defined(_MSC_VER)
mbedAustin 11:cada08fc8a70 48 #if defined(_WIN32_WCE)
mbedAustin 11:cada08fc8a70 49 #pragma comment( lib, "ws2.lib" )
mbedAustin 11:cada08fc8a70 50 #else
mbedAustin 11:cada08fc8a70 51 #pragma comment( lib, "ws2_32.lib" )
mbedAustin 11:cada08fc8a70 52 #endif
mbedAustin 11:cada08fc8a70 53 #endif /* _MSC_VER */
mbedAustin 11:cada08fc8a70 54
mbedAustin 11:cada08fc8a70 55 #define read(fd,buf,len) recv(fd,(char*)buf,(int) len,0)
mbedAustin 11:cada08fc8a70 56 #define write(fd,buf,len) send(fd,(char*)buf,(int) len,0)
mbedAustin 11:cada08fc8a70 57 #define close(fd) closesocket(fd)
mbedAustin 11:cada08fc8a70 58
mbedAustin 11:cada08fc8a70 59 static int wsa_init_done = 0;
mbedAustin 11:cada08fc8a70 60
mbedAustin 11:cada08fc8a70 61 #else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
mbedAustin 11:cada08fc8a70 62
mbedAustin 11:cada08fc8a70 63 #include <sys/types.h>
mbedAustin 11:cada08fc8a70 64 #include <sys/socket.h>
mbedAustin 11:cada08fc8a70 65 #include <netinet/in.h>
mbedAustin 11:cada08fc8a70 66 #include <arpa/inet.h>
mbedAustin 11:cada08fc8a70 67 #include <sys/time.h>
mbedAustin 11:cada08fc8a70 68 #include <unistd.h>
mbedAustin 11:cada08fc8a70 69 #include <signal.h>
mbedAustin 11:cada08fc8a70 70 #include <fcntl.h>
mbedAustin 11:cada08fc8a70 71 #include <netdb.h>
mbedAustin 11:cada08fc8a70 72 #include <errno.h>
mbedAustin 11:cada08fc8a70 73
mbedAustin 11:cada08fc8a70 74 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
mbedAustin 11:cada08fc8a70 75
mbedAustin 11:cada08fc8a70 76 /* Some MS functions want int and MSVC warns if we pass size_t,
mbedAustin 11:cada08fc8a70 77 * but the standard fucntions use socklen_t, so cast only for MSVC */
mbedAustin 11:cada08fc8a70 78 #if defined(_MSC_VER)
mbedAustin 11:cada08fc8a70 79 #define MSVC_INT_CAST (int)
mbedAustin 11:cada08fc8a70 80 #else
mbedAustin 11:cada08fc8a70 81 #define MSVC_INT_CAST
mbedAustin 11:cada08fc8a70 82 #endif
mbedAustin 11:cada08fc8a70 83
mbedAustin 11:cada08fc8a70 84 #include <stdlib.h>
mbedAustin 11:cada08fc8a70 85 #include <stdio.h>
mbedAustin 11:cada08fc8a70 86
mbedAustin 11:cada08fc8a70 87 #include <time.h>
mbedAustin 11:cada08fc8a70 88
mbedAustin 11:cada08fc8a70 89 #include <stdint.h>
mbedAustin 11:cada08fc8a70 90
mbedAustin 11:cada08fc8a70 91 /*
mbedAustin 11:cada08fc8a70 92 * Prepare for using the sockets interface
mbedAustin 11:cada08fc8a70 93 */
mbedAustin 11:cada08fc8a70 94 static int net_prepare( void )
mbedAustin 11:cada08fc8a70 95 {
mbedAustin 11:cada08fc8a70 96 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 97 !defined(EFI32)
mbedAustin 11:cada08fc8a70 98 WSADATA wsaData;
mbedAustin 11:cada08fc8a70 99
mbedAustin 11:cada08fc8a70 100 if( wsa_init_done == 0 )
mbedAustin 11:cada08fc8a70 101 {
mbedAustin 11:cada08fc8a70 102 if( WSAStartup( MAKEWORD(2,0), &wsaData ) != 0 )
mbedAustin 11:cada08fc8a70 103 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
mbedAustin 11:cada08fc8a70 104
mbedAustin 11:cada08fc8a70 105 wsa_init_done = 1;
mbedAustin 11:cada08fc8a70 106 }
mbedAustin 11:cada08fc8a70 107 #else
mbedAustin 11:cada08fc8a70 108 #if !defined(EFIX64) && !defined(EFI32)
mbedAustin 11:cada08fc8a70 109 signal( SIGPIPE, SIG_IGN );
mbedAustin 11:cada08fc8a70 110 #endif
mbedAustin 11:cada08fc8a70 111 #endif
mbedAustin 11:cada08fc8a70 112 return( 0 );
mbedAustin 11:cada08fc8a70 113 }
mbedAustin 11:cada08fc8a70 114
mbedAustin 11:cada08fc8a70 115 /*
mbedAustin 11:cada08fc8a70 116 * Initialize a context
mbedAustin 11:cada08fc8a70 117 */
mbedAustin 11:cada08fc8a70 118 void mbedtls_net_init( mbedtls_net_context *ctx )
mbedAustin 11:cada08fc8a70 119 {
mbedAustin 11:cada08fc8a70 120 ctx->fd = -1;
mbedAustin 11:cada08fc8a70 121 }
mbedAustin 11:cada08fc8a70 122
mbedAustin 11:cada08fc8a70 123 /*
mbedAustin 11:cada08fc8a70 124 * Initiate a TCP connection with host:port and the given protocol
mbedAustin 11:cada08fc8a70 125 */
mbedAustin 11:cada08fc8a70 126 int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto )
mbedAustin 11:cada08fc8a70 127 {
mbedAustin 11:cada08fc8a70 128 int ret;
mbedAustin 11:cada08fc8a70 129 struct addrinfo hints, *addr_list, *cur;
mbedAustin 11:cada08fc8a70 130
mbedAustin 11:cada08fc8a70 131 if( ( ret = net_prepare() ) != 0 )
mbedAustin 11:cada08fc8a70 132 return( ret );
mbedAustin 11:cada08fc8a70 133
mbedAustin 11:cada08fc8a70 134 /* Do name resolution with both IPv6 and IPv4 */
mbedAustin 11:cada08fc8a70 135 memset( &hints, 0, sizeof( hints ) );
mbedAustin 11:cada08fc8a70 136 hints.ai_family = AF_UNSPEC;
mbedAustin 11:cada08fc8a70 137 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
mbedAustin 11:cada08fc8a70 138 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
mbedAustin 11:cada08fc8a70 139
mbedAustin 11:cada08fc8a70 140 if( getaddrinfo( host, port, &hints, &addr_list ) != 0 )
mbedAustin 11:cada08fc8a70 141 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
mbedAustin 11:cada08fc8a70 142
mbedAustin 11:cada08fc8a70 143 /* Try the sockaddrs until a connection succeeds */
mbedAustin 11:cada08fc8a70 144 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
mbedAustin 11:cada08fc8a70 145 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
mbedAustin 11:cada08fc8a70 146 {
mbedAustin 11:cada08fc8a70 147 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
mbedAustin 11:cada08fc8a70 148 cur->ai_protocol );
mbedAustin 11:cada08fc8a70 149 if( ctx->fd < 0 )
mbedAustin 11:cada08fc8a70 150 {
mbedAustin 11:cada08fc8a70 151 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
mbedAustin 11:cada08fc8a70 152 continue;
mbedAustin 11:cada08fc8a70 153 }
mbedAustin 11:cada08fc8a70 154
mbedAustin 11:cada08fc8a70 155 if( connect( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) == 0 )
mbedAustin 11:cada08fc8a70 156 {
mbedAustin 11:cada08fc8a70 157 ret = 0;
mbedAustin 11:cada08fc8a70 158 break;
mbedAustin 11:cada08fc8a70 159 }
mbedAustin 11:cada08fc8a70 160
mbedAustin 11:cada08fc8a70 161 close( ctx->fd );
mbedAustin 11:cada08fc8a70 162 ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
mbedAustin 11:cada08fc8a70 163 }
mbedAustin 11:cada08fc8a70 164
mbedAustin 11:cada08fc8a70 165 freeaddrinfo( addr_list );
mbedAustin 11:cada08fc8a70 166
mbedAustin 11:cada08fc8a70 167 return( ret );
mbedAustin 11:cada08fc8a70 168 }
mbedAustin 11:cada08fc8a70 169
mbedAustin 11:cada08fc8a70 170 /*
mbedAustin 11:cada08fc8a70 171 * Create a listening socket on bind_ip:port
mbedAustin 11:cada08fc8a70 172 */
mbedAustin 11:cada08fc8a70 173 int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto )
mbedAustin 11:cada08fc8a70 174 {
mbedAustin 11:cada08fc8a70 175 int n, ret;
mbedAustin 11:cada08fc8a70 176 struct addrinfo hints, *addr_list, *cur;
mbedAustin 11:cada08fc8a70 177
mbedAustin 11:cada08fc8a70 178 if( ( ret = net_prepare() ) != 0 )
mbedAustin 11:cada08fc8a70 179 return( ret );
mbedAustin 11:cada08fc8a70 180
mbedAustin 11:cada08fc8a70 181 /* Bind to IPv6 and/or IPv4, but only in the desired protocol */
mbedAustin 11:cada08fc8a70 182 memset( &hints, 0, sizeof( hints ) );
mbedAustin 11:cada08fc8a70 183 hints.ai_family = AF_UNSPEC;
mbedAustin 11:cada08fc8a70 184 hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
mbedAustin 11:cada08fc8a70 185 hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
mbedAustin 11:cada08fc8a70 186 if( bind_ip == NULL )
mbedAustin 11:cada08fc8a70 187 hints.ai_flags = AI_PASSIVE;
mbedAustin 11:cada08fc8a70 188
mbedAustin 11:cada08fc8a70 189 if( getaddrinfo( bind_ip, port, &hints, &addr_list ) != 0 )
mbedAustin 11:cada08fc8a70 190 return( MBEDTLS_ERR_NET_UNKNOWN_HOST );
mbedAustin 11:cada08fc8a70 191
mbedAustin 11:cada08fc8a70 192 /* Try the sockaddrs until a binding succeeds */
mbedAustin 11:cada08fc8a70 193 ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
mbedAustin 11:cada08fc8a70 194 for( cur = addr_list; cur != NULL; cur = cur->ai_next )
mbedAustin 11:cada08fc8a70 195 {
mbedAustin 11:cada08fc8a70 196 ctx->fd = (int) socket( cur->ai_family, cur->ai_socktype,
mbedAustin 11:cada08fc8a70 197 cur->ai_protocol );
mbedAustin 11:cada08fc8a70 198 if( ctx->fd < 0 )
mbedAustin 11:cada08fc8a70 199 {
mbedAustin 11:cada08fc8a70 200 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
mbedAustin 11:cada08fc8a70 201 continue;
mbedAustin 11:cada08fc8a70 202 }
mbedAustin 11:cada08fc8a70 203
mbedAustin 11:cada08fc8a70 204 n = 1;
mbedAustin 11:cada08fc8a70 205 if( setsockopt( ctx->fd, SOL_SOCKET, SO_REUSEADDR,
mbedAustin 11:cada08fc8a70 206 (const char *) &n, sizeof( n ) ) != 0 )
mbedAustin 11:cada08fc8a70 207 {
mbedAustin 11:cada08fc8a70 208 close( ctx->fd );
mbedAustin 11:cada08fc8a70 209 ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
mbedAustin 11:cada08fc8a70 210 continue;
mbedAustin 11:cada08fc8a70 211 }
mbedAustin 11:cada08fc8a70 212
mbedAustin 11:cada08fc8a70 213 if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
mbedAustin 11:cada08fc8a70 214 {
mbedAustin 11:cada08fc8a70 215 close( ctx->fd );
mbedAustin 11:cada08fc8a70 216 ret = MBEDTLS_ERR_NET_BIND_FAILED;
mbedAustin 11:cada08fc8a70 217 continue;
mbedAustin 11:cada08fc8a70 218 }
mbedAustin 11:cada08fc8a70 219
mbedAustin 11:cada08fc8a70 220 /* Listen only makes sense for TCP */
mbedAustin 11:cada08fc8a70 221 if( proto == MBEDTLS_NET_PROTO_TCP )
mbedAustin 11:cada08fc8a70 222 {
mbedAustin 11:cada08fc8a70 223 if( listen( ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG ) != 0 )
mbedAustin 11:cada08fc8a70 224 {
mbedAustin 11:cada08fc8a70 225 close( ctx->fd );
mbedAustin 11:cada08fc8a70 226 ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
mbedAustin 11:cada08fc8a70 227 continue;
mbedAustin 11:cada08fc8a70 228 }
mbedAustin 11:cada08fc8a70 229 }
mbedAustin 11:cada08fc8a70 230
mbedAustin 11:cada08fc8a70 231 /* I we ever get there, it's a success */
mbedAustin 11:cada08fc8a70 232 ret = 0;
mbedAustin 11:cada08fc8a70 233 break;
mbedAustin 11:cada08fc8a70 234 }
mbedAustin 11:cada08fc8a70 235
mbedAustin 11:cada08fc8a70 236 freeaddrinfo( addr_list );
mbedAustin 11:cada08fc8a70 237
mbedAustin 11:cada08fc8a70 238 return( ret );
mbedAustin 11:cada08fc8a70 239
mbedAustin 11:cada08fc8a70 240 }
mbedAustin 11:cada08fc8a70 241
mbedAustin 11:cada08fc8a70 242 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 243 !defined(EFI32)
mbedAustin 11:cada08fc8a70 244 /*
mbedAustin 11:cada08fc8a70 245 * Check if the requested operation would be blocking on a non-blocking socket
mbedAustin 11:cada08fc8a70 246 * and thus 'failed' with a negative return value.
mbedAustin 11:cada08fc8a70 247 */
mbedAustin 11:cada08fc8a70 248 static int net_would_block( const mbedtls_net_context *ctx )
mbedAustin 11:cada08fc8a70 249 {
mbedAustin 11:cada08fc8a70 250 ((void) ctx);
mbedAustin 11:cada08fc8a70 251 return( WSAGetLastError() == WSAEWOULDBLOCK );
mbedAustin 11:cada08fc8a70 252 }
mbedAustin 11:cada08fc8a70 253 #else
mbedAustin 11:cada08fc8a70 254 /*
mbedAustin 11:cada08fc8a70 255 * Check if the requested operation would be blocking on a non-blocking socket
mbedAustin 11:cada08fc8a70 256 * and thus 'failed' with a negative return value.
mbedAustin 11:cada08fc8a70 257 *
mbedAustin 11:cada08fc8a70 258 * Note: on a blocking socket this function always returns 0!
mbedAustin 11:cada08fc8a70 259 */
mbedAustin 11:cada08fc8a70 260 static int net_would_block( const mbedtls_net_context *ctx )
mbedAustin 11:cada08fc8a70 261 {
mbedAustin 11:cada08fc8a70 262 /*
mbedAustin 11:cada08fc8a70 263 * Never return 'WOULD BLOCK' on a non-blocking socket
mbedAustin 11:cada08fc8a70 264 */
mbedAustin 11:cada08fc8a70 265 if( ( fcntl( ctx->fd, F_GETFL ) & O_NONBLOCK ) != O_NONBLOCK )
mbedAustin 11:cada08fc8a70 266 return( 0 );
mbedAustin 11:cada08fc8a70 267
mbedAustin 11:cada08fc8a70 268 switch( errno )
mbedAustin 11:cada08fc8a70 269 {
mbedAustin 11:cada08fc8a70 270 #if defined EAGAIN
mbedAustin 11:cada08fc8a70 271 case EAGAIN:
mbedAustin 11:cada08fc8a70 272 #endif
mbedAustin 11:cada08fc8a70 273 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
mbedAustin 11:cada08fc8a70 274 case EWOULDBLOCK:
mbedAustin 11:cada08fc8a70 275 #endif
mbedAustin 11:cada08fc8a70 276 return( 1 );
mbedAustin 11:cada08fc8a70 277 }
mbedAustin 11:cada08fc8a70 278 return( 0 );
mbedAustin 11:cada08fc8a70 279 }
mbedAustin 11:cada08fc8a70 280 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
mbedAustin 11:cada08fc8a70 281
mbedAustin 11:cada08fc8a70 282 /*
mbedAustin 11:cada08fc8a70 283 * Accept a connection from a remote client
mbedAustin 11:cada08fc8a70 284 */
mbedAustin 11:cada08fc8a70 285 int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
mbedAustin 11:cada08fc8a70 286 mbedtls_net_context *client_ctx,
mbedAustin 11:cada08fc8a70 287 void *client_ip, size_t buf_size, size_t *ip_len )
mbedAustin 11:cada08fc8a70 288 {
mbedAustin 11:cada08fc8a70 289 int ret;
mbedAustin 11:cada08fc8a70 290 int type;
mbedAustin 11:cada08fc8a70 291
mbedAustin 11:cada08fc8a70 292 struct sockaddr_storage client_addr;
mbedAustin 11:cada08fc8a70 293
mbedAustin 11:cada08fc8a70 294 #if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
mbedAustin 11:cada08fc8a70 295 defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t)
mbedAustin 11:cada08fc8a70 296 socklen_t n = (socklen_t) sizeof( client_addr );
mbedAustin 11:cada08fc8a70 297 socklen_t type_len = (socklen_t) sizeof( type );
mbedAustin 11:cada08fc8a70 298 #else
mbedAustin 11:cada08fc8a70 299 int n = (int) sizeof( client_addr );
mbedAustin 11:cada08fc8a70 300 int type_len = (int) sizeof( type );
mbedAustin 11:cada08fc8a70 301 #endif
mbedAustin 11:cada08fc8a70 302
mbedAustin 11:cada08fc8a70 303 /* Is this a TCP or UDP socket? */
mbedAustin 11:cada08fc8a70 304 if( getsockopt( bind_ctx->fd, SOL_SOCKET, SO_TYPE,
mbedAustin 11:cada08fc8a70 305 (void *) &type, &type_len ) != 0 ||
mbedAustin 11:cada08fc8a70 306 ( type != SOCK_STREAM && type != SOCK_DGRAM ) )
mbedAustin 11:cada08fc8a70 307 {
mbedAustin 11:cada08fc8a70 308 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
mbedAustin 11:cada08fc8a70 309 }
mbedAustin 11:cada08fc8a70 310
mbedAustin 11:cada08fc8a70 311 if( type == SOCK_STREAM )
mbedAustin 11:cada08fc8a70 312 {
mbedAustin 11:cada08fc8a70 313 /* TCP: actual accept() */
mbedAustin 11:cada08fc8a70 314 ret = client_ctx->fd = (int) accept( bind_ctx->fd,
mbedAustin 11:cada08fc8a70 315 (struct sockaddr *) &client_addr, &n );
mbedAustin 11:cada08fc8a70 316 }
mbedAustin 11:cada08fc8a70 317 else
mbedAustin 11:cada08fc8a70 318 {
mbedAustin 11:cada08fc8a70 319 /* UDP: wait for a message, but keep it in the queue */
mbedAustin 11:cada08fc8a70 320 char buf[1] = { 0 };
mbedAustin 11:cada08fc8a70 321
mbedAustin 11:cada08fc8a70 322 ret = (int) recvfrom( bind_ctx->fd, buf, sizeof( buf ), MSG_PEEK,
mbedAustin 11:cada08fc8a70 323 (struct sockaddr *) &client_addr, &n );
mbedAustin 11:cada08fc8a70 324
mbedAustin 11:cada08fc8a70 325 #if defined(_WIN32)
mbedAustin 11:cada08fc8a70 326 if( ret == SOCKET_ERROR &&
mbedAustin 11:cada08fc8a70 327 WSAGetLastError() == WSAEMSGSIZE )
mbedAustin 11:cada08fc8a70 328 {
mbedAustin 11:cada08fc8a70 329 /* We know buf is too small, thanks, just peeking here */
mbedAustin 11:cada08fc8a70 330 ret = 0;
mbedAustin 11:cada08fc8a70 331 }
mbedAustin 11:cada08fc8a70 332 #endif
mbedAustin 11:cada08fc8a70 333 }
mbedAustin 11:cada08fc8a70 334
mbedAustin 11:cada08fc8a70 335 if( ret < 0 )
mbedAustin 11:cada08fc8a70 336 {
mbedAustin 11:cada08fc8a70 337 if( net_would_block( bind_ctx ) != 0 )
mbedAustin 11:cada08fc8a70 338 return( MBEDTLS_ERR_SSL_WANT_READ );
mbedAustin 11:cada08fc8a70 339
mbedAustin 11:cada08fc8a70 340 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
mbedAustin 11:cada08fc8a70 341 }
mbedAustin 11:cada08fc8a70 342
mbedAustin 11:cada08fc8a70 343 /* UDP: hijack the listening socket to communicate with the client,
mbedAustin 11:cada08fc8a70 344 * then bind a new socket to accept new connections */
mbedAustin 11:cada08fc8a70 345 if( type != SOCK_STREAM )
mbedAustin 11:cada08fc8a70 346 {
mbedAustin 11:cada08fc8a70 347 struct sockaddr_storage local_addr;
mbedAustin 11:cada08fc8a70 348 int one = 1;
mbedAustin 11:cada08fc8a70 349
mbedAustin 11:cada08fc8a70 350 if( connect( bind_ctx->fd, (struct sockaddr *) &client_addr, n ) != 0 )
mbedAustin 11:cada08fc8a70 351 return( MBEDTLS_ERR_NET_ACCEPT_FAILED );
mbedAustin 11:cada08fc8a70 352
mbedAustin 11:cada08fc8a70 353 client_ctx->fd = bind_ctx->fd;
mbedAustin 11:cada08fc8a70 354 bind_ctx->fd = -1; /* In case we exit early */
mbedAustin 11:cada08fc8a70 355
mbedAustin 11:cada08fc8a70 356 n = sizeof( struct sockaddr_storage );
mbedAustin 11:cada08fc8a70 357 if( getsockname( client_ctx->fd,
mbedAustin 11:cada08fc8a70 358 (struct sockaddr *) &local_addr, &n ) != 0 ||
mbedAustin 11:cada08fc8a70 359 ( bind_ctx->fd = (int) socket( local_addr.ss_family,
mbedAustin 11:cada08fc8a70 360 SOCK_DGRAM, IPPROTO_UDP ) ) < 0 ||
mbedAustin 11:cada08fc8a70 361 setsockopt( bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
mbedAustin 11:cada08fc8a70 362 (const char *) &one, sizeof( one ) ) != 0 )
mbedAustin 11:cada08fc8a70 363 {
mbedAustin 11:cada08fc8a70 364 return( MBEDTLS_ERR_NET_SOCKET_FAILED );
mbedAustin 11:cada08fc8a70 365 }
mbedAustin 11:cada08fc8a70 366
mbedAustin 11:cada08fc8a70 367 if( bind( bind_ctx->fd, (struct sockaddr *) &local_addr, n ) != 0 )
mbedAustin 11:cada08fc8a70 368 {
mbedAustin 11:cada08fc8a70 369 return( MBEDTLS_ERR_NET_BIND_FAILED );
mbedAustin 11:cada08fc8a70 370 }
mbedAustin 11:cada08fc8a70 371 }
mbedAustin 11:cada08fc8a70 372
mbedAustin 11:cada08fc8a70 373 if( client_ip != NULL )
mbedAustin 11:cada08fc8a70 374 {
mbedAustin 11:cada08fc8a70 375 if( client_addr.ss_family == AF_INET )
mbedAustin 11:cada08fc8a70 376 {
mbedAustin 11:cada08fc8a70 377 struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
mbedAustin 11:cada08fc8a70 378 *ip_len = sizeof( addr4->sin_addr.s_addr );
mbedAustin 11:cada08fc8a70 379
mbedAustin 11:cada08fc8a70 380 if( buf_size < *ip_len )
mbedAustin 11:cada08fc8a70 381 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
mbedAustin 11:cada08fc8a70 382
mbedAustin 11:cada08fc8a70 383 memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
mbedAustin 11:cada08fc8a70 384 }
mbedAustin 11:cada08fc8a70 385 else
mbedAustin 11:cada08fc8a70 386 {
mbedAustin 11:cada08fc8a70 387 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
mbedAustin 11:cada08fc8a70 388 *ip_len = sizeof( addr6->sin6_addr.s6_addr );
mbedAustin 11:cada08fc8a70 389
mbedAustin 11:cada08fc8a70 390 if( buf_size < *ip_len )
mbedAustin 11:cada08fc8a70 391 return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
mbedAustin 11:cada08fc8a70 392
mbedAustin 11:cada08fc8a70 393 memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
mbedAustin 11:cada08fc8a70 394 }
mbedAustin 11:cada08fc8a70 395 }
mbedAustin 11:cada08fc8a70 396
mbedAustin 11:cada08fc8a70 397 return( 0 );
mbedAustin 11:cada08fc8a70 398 }
mbedAustin 11:cada08fc8a70 399
mbedAustin 11:cada08fc8a70 400 /*
mbedAustin 11:cada08fc8a70 401 * Set the socket blocking or non-blocking
mbedAustin 11:cada08fc8a70 402 */
mbedAustin 11:cada08fc8a70 403 int mbedtls_net_set_block( mbedtls_net_context *ctx )
mbedAustin 11:cada08fc8a70 404 {
mbedAustin 11:cada08fc8a70 405 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 406 !defined(EFI32)
mbedAustin 11:cada08fc8a70 407 u_long n = 0;
mbedAustin 11:cada08fc8a70 408 return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
mbedAustin 11:cada08fc8a70 409 #else
mbedAustin 11:cada08fc8a70 410 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) & ~O_NONBLOCK ) );
mbedAustin 11:cada08fc8a70 411 #endif
mbedAustin 11:cada08fc8a70 412 }
mbedAustin 11:cada08fc8a70 413
mbedAustin 11:cada08fc8a70 414 int mbedtls_net_set_nonblock( mbedtls_net_context *ctx )
mbedAustin 11:cada08fc8a70 415 {
mbedAustin 11:cada08fc8a70 416 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 417 !defined(EFI32)
mbedAustin 11:cada08fc8a70 418 u_long n = 1;
mbedAustin 11:cada08fc8a70 419 return( ioctlsocket( ctx->fd, FIONBIO, &n ) );
mbedAustin 11:cada08fc8a70 420 #else
mbedAustin 11:cada08fc8a70 421 return( fcntl( ctx->fd, F_SETFL, fcntl( ctx->fd, F_GETFL ) | O_NONBLOCK ) );
mbedAustin 11:cada08fc8a70 422 #endif
mbedAustin 11:cada08fc8a70 423 }
mbedAustin 11:cada08fc8a70 424
mbedAustin 11:cada08fc8a70 425 /*
mbedAustin 11:cada08fc8a70 426 * Portable usleep helper
mbedAustin 11:cada08fc8a70 427 */
mbedAustin 11:cada08fc8a70 428 void mbedtls_net_usleep( unsigned long usec )
mbedAustin 11:cada08fc8a70 429 {
mbedAustin 11:cada08fc8a70 430 #if defined(_WIN32)
mbedAustin 11:cada08fc8a70 431 Sleep( ( usec + 999 ) / 1000 );
mbedAustin 11:cada08fc8a70 432 #else
mbedAustin 11:cada08fc8a70 433 struct timeval tv;
mbedAustin 11:cada08fc8a70 434 tv.tv_sec = usec / 1000000;
mbedAustin 11:cada08fc8a70 435 #if defined(__unix__) || defined(__unix) || \
mbedAustin 11:cada08fc8a70 436 ( defined(__APPLE__) && defined(__MACH__) )
mbedAustin 11:cada08fc8a70 437 tv.tv_usec = (suseconds_t) usec % 1000000;
mbedAustin 11:cada08fc8a70 438 #else
mbedAustin 11:cada08fc8a70 439 tv.tv_usec = usec % 1000000;
mbedAustin 11:cada08fc8a70 440 #endif
mbedAustin 11:cada08fc8a70 441 select( 0, NULL, NULL, NULL, &tv );
mbedAustin 11:cada08fc8a70 442 #endif
mbedAustin 11:cada08fc8a70 443 }
mbedAustin 11:cada08fc8a70 444
mbedAustin 11:cada08fc8a70 445 /*
mbedAustin 11:cada08fc8a70 446 * Read at most 'len' characters
mbedAustin 11:cada08fc8a70 447 */
mbedAustin 11:cada08fc8a70 448 int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len )
mbedAustin 11:cada08fc8a70 449 {
mbedAustin 11:cada08fc8a70 450 int ret;
mbedAustin 11:cada08fc8a70 451 int fd = ((mbedtls_net_context *) ctx)->fd;
mbedAustin 11:cada08fc8a70 452
mbedAustin 11:cada08fc8a70 453 if( fd < 0 )
mbedAustin 11:cada08fc8a70 454 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
mbedAustin 11:cada08fc8a70 455
mbedAustin 11:cada08fc8a70 456 ret = (int) read( fd, buf, len );
mbedAustin 11:cada08fc8a70 457
mbedAustin 11:cada08fc8a70 458 if( ret < 0 )
mbedAustin 11:cada08fc8a70 459 {
mbedAustin 11:cada08fc8a70 460 if( net_would_block( ctx ) != 0 )
mbedAustin 11:cada08fc8a70 461 return( MBEDTLS_ERR_SSL_WANT_READ );
mbedAustin 11:cada08fc8a70 462
mbedAustin 11:cada08fc8a70 463 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 464 !defined(EFI32)
mbedAustin 11:cada08fc8a70 465 if( WSAGetLastError() == WSAECONNRESET )
mbedAustin 11:cada08fc8a70 466 return( MBEDTLS_ERR_NET_CONN_RESET );
mbedAustin 11:cada08fc8a70 467 #else
mbedAustin 11:cada08fc8a70 468 if( errno == EPIPE || errno == ECONNRESET )
mbedAustin 11:cada08fc8a70 469 return( MBEDTLS_ERR_NET_CONN_RESET );
mbedAustin 11:cada08fc8a70 470
mbedAustin 11:cada08fc8a70 471 if( errno == EINTR )
mbedAustin 11:cada08fc8a70 472 return( MBEDTLS_ERR_SSL_WANT_READ );
mbedAustin 11:cada08fc8a70 473 #endif
mbedAustin 11:cada08fc8a70 474
mbedAustin 11:cada08fc8a70 475 return( MBEDTLS_ERR_NET_RECV_FAILED );
mbedAustin 11:cada08fc8a70 476 }
mbedAustin 11:cada08fc8a70 477
mbedAustin 11:cada08fc8a70 478 return( ret );
mbedAustin 11:cada08fc8a70 479 }
mbedAustin 11:cada08fc8a70 480
mbedAustin 11:cada08fc8a70 481 /*
mbedAustin 11:cada08fc8a70 482 * Read at most 'len' characters, blocking for at most 'timeout' ms
mbedAustin 11:cada08fc8a70 483 */
mbedAustin 11:cada08fc8a70 484 int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
mbedAustin 11:cada08fc8a70 485 uint32_t timeout )
mbedAustin 11:cada08fc8a70 486 {
mbedAustin 11:cada08fc8a70 487 int ret;
mbedAustin 11:cada08fc8a70 488 struct timeval tv;
mbedAustin 11:cada08fc8a70 489 fd_set read_fds;
mbedAustin 11:cada08fc8a70 490 int fd = ((mbedtls_net_context *) ctx)->fd;
mbedAustin 11:cada08fc8a70 491
mbedAustin 11:cada08fc8a70 492 if( fd < 0 )
mbedAustin 11:cada08fc8a70 493 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
mbedAustin 11:cada08fc8a70 494
mbedAustin 11:cada08fc8a70 495 FD_ZERO( &read_fds );
mbedAustin 11:cada08fc8a70 496 FD_SET( fd, &read_fds );
mbedAustin 11:cada08fc8a70 497
mbedAustin 11:cada08fc8a70 498 tv.tv_sec = timeout / 1000;
mbedAustin 11:cada08fc8a70 499 tv.tv_usec = ( timeout % 1000 ) * 1000;
mbedAustin 11:cada08fc8a70 500
mbedAustin 11:cada08fc8a70 501 ret = select( fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv );
mbedAustin 11:cada08fc8a70 502
mbedAustin 11:cada08fc8a70 503 /* Zero fds ready means we timed out */
mbedAustin 11:cada08fc8a70 504 if( ret == 0 )
mbedAustin 11:cada08fc8a70 505 return( MBEDTLS_ERR_SSL_TIMEOUT );
mbedAustin 11:cada08fc8a70 506
mbedAustin 11:cada08fc8a70 507 if( ret < 0 )
mbedAustin 11:cada08fc8a70 508 {
mbedAustin 11:cada08fc8a70 509 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 510 !defined(EFI32)
mbedAustin 11:cada08fc8a70 511 if( WSAGetLastError() == WSAEINTR )
mbedAustin 11:cada08fc8a70 512 return( MBEDTLS_ERR_SSL_WANT_READ );
mbedAustin 11:cada08fc8a70 513 #else
mbedAustin 11:cada08fc8a70 514 if( errno == EINTR )
mbedAustin 11:cada08fc8a70 515 return( MBEDTLS_ERR_SSL_WANT_READ );
mbedAustin 11:cada08fc8a70 516 #endif
mbedAustin 11:cada08fc8a70 517
mbedAustin 11:cada08fc8a70 518 return( MBEDTLS_ERR_NET_RECV_FAILED );
mbedAustin 11:cada08fc8a70 519 }
mbedAustin 11:cada08fc8a70 520
mbedAustin 11:cada08fc8a70 521 /* This call will not block */
mbedAustin 11:cada08fc8a70 522 return( mbedtls_net_recv( ctx, buf, len ) );
mbedAustin 11:cada08fc8a70 523 }
mbedAustin 11:cada08fc8a70 524
mbedAustin 11:cada08fc8a70 525 /*
mbedAustin 11:cada08fc8a70 526 * Write at most 'len' characters
mbedAustin 11:cada08fc8a70 527 */
mbedAustin 11:cada08fc8a70 528 int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len )
mbedAustin 11:cada08fc8a70 529 {
mbedAustin 11:cada08fc8a70 530 int ret;
mbedAustin 11:cada08fc8a70 531 int fd = ((mbedtls_net_context *) ctx)->fd;
mbedAustin 11:cada08fc8a70 532
mbedAustin 11:cada08fc8a70 533 if( fd < 0 )
mbedAustin 11:cada08fc8a70 534 return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
mbedAustin 11:cada08fc8a70 535
mbedAustin 11:cada08fc8a70 536 ret = (int) write( fd, buf, len );
mbedAustin 11:cada08fc8a70 537
mbedAustin 11:cada08fc8a70 538 if( ret < 0 )
mbedAustin 11:cada08fc8a70 539 {
mbedAustin 11:cada08fc8a70 540 if( net_would_block( ctx ) != 0 )
mbedAustin 11:cada08fc8a70 541 return( MBEDTLS_ERR_SSL_WANT_WRITE );
mbedAustin 11:cada08fc8a70 542
mbedAustin 11:cada08fc8a70 543 #if ( defined(_WIN32) || defined(_WIN32_WCE) ) && !defined(EFIX64) && \
mbedAustin 11:cada08fc8a70 544 !defined(EFI32)
mbedAustin 11:cada08fc8a70 545 if( WSAGetLastError() == WSAECONNRESET )
mbedAustin 11:cada08fc8a70 546 return( MBEDTLS_ERR_NET_CONN_RESET );
mbedAustin 11:cada08fc8a70 547 #else
mbedAustin 11:cada08fc8a70 548 if( errno == EPIPE || errno == ECONNRESET )
mbedAustin 11:cada08fc8a70 549 return( MBEDTLS_ERR_NET_CONN_RESET );
mbedAustin 11:cada08fc8a70 550
mbedAustin 11:cada08fc8a70 551 if( errno == EINTR )
mbedAustin 11:cada08fc8a70 552 return( MBEDTLS_ERR_SSL_WANT_WRITE );
mbedAustin 11:cada08fc8a70 553 #endif
mbedAustin 11:cada08fc8a70 554
mbedAustin 11:cada08fc8a70 555 return( MBEDTLS_ERR_NET_SEND_FAILED );
mbedAustin 11:cada08fc8a70 556 }
mbedAustin 11:cada08fc8a70 557
mbedAustin 11:cada08fc8a70 558 return( ret );
mbedAustin 11:cada08fc8a70 559 }
mbedAustin 11:cada08fc8a70 560
mbedAustin 11:cada08fc8a70 561 /*
mbedAustin 11:cada08fc8a70 562 * Gracefully close the connection
mbedAustin 11:cada08fc8a70 563 */
mbedAustin 11:cada08fc8a70 564 void mbedtls_net_free( mbedtls_net_context *ctx )
mbedAustin 11:cada08fc8a70 565 {
mbedAustin 11:cada08fc8a70 566 if( ctx->fd == -1 )
mbedAustin 11:cada08fc8a70 567 return;
mbedAustin 11:cada08fc8a70 568
mbedAustin 11:cada08fc8a70 569 shutdown( ctx->fd, 2 );
mbedAustin 11:cada08fc8a70 570 close( ctx->fd );
mbedAustin 11:cada08fc8a70 571
mbedAustin 11:cada08fc8a70 572 ctx->fd = -1;
mbedAustin 11:cada08fc8a70 573 }
mbedAustin 11:cada08fc8a70 574
mbedAustin 11:cada08fc8a70 575 #endif /* MBEDTLS_NET_C */