/home/dko/projects/mobilec/trunk/src/security/xyssl-0.7/library/net.c

Go to the documentation of this file.
00001 /*
00002  *  TCP networking functions
00003  *
00004  *  Copyright (C) 2006-2007  Christophe Devine
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Lesser General Public
00008  *  License, version 2.1 as published by the Free Software Foundation.
00009  *
00010  *  This library is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  *  Lesser General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU Lesser General Public
00016  *  License along with this library; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00018  *  MA  02110-1301  USA
00019  */
00020 
00021 #ifndef _CRT_SECURE_NO_DEPRECATE
00022 #define _CRT_SECURE_NO_DEPRECATE 1
00023 #endif
00024 
00025 #if defined(WIN32) || defined(_WIN32_WCE)
00026 
00027 #include <winsock2.h>
00028 #include <windows.h>
00029 
00030 #if defined(_WIN32_WCE)
00031 #pragma comment( lib, "ws2.lib" )
00032 #else
00033 #pragma comment( lib, "ws2_32.lib" )
00034 #endif
00035 
00036 #define  read(fd,buf,len) recv(fd,buf,len,0)
00037 #define write(fd,buf,len) send(fd,buf,len,0)
00038 #define close(fd)         closesocket(fd)
00039 
00040 static int wsa_init_done = 0;
00041 
00042 #else
00043 
00044 #include <sys/types.h>
00045 #include <sys/socket.h>
00046 #include <netinet/in.h>
00047 #include <arpa/inet.h>
00048 #include <sys/time.h>
00049 #include <unistd.h>
00050 #include <signal.h>
00051 #include <fcntl.h>
00052 #include <netdb.h>
00053 #include <errno.h>
00054 
00055 #endif
00056 
00057 #include <string.h>
00058 #include <stdlib.h>
00059 #include <stdio.h>
00060 #include <time.h>
00061 
00062 #include "xyssl/net.h"
00063 
00064 /*
00065  * Initiate a TCP connection with host:port
00066  */
00067 int net_connect( int *fd, char *host, unsigned int port )
00068 {
00069     struct sockaddr_in server_addr;
00070     struct hostent *server_host;
00071 
00072 #if defined(WIN32) || defined(_WIN32_WCE)
00073     WSADATA wsaData;
00074 
00075     if( wsa_init_done == 0 )
00076     {
00077         if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
00078             return( ERR_NET_SOCKET_FAILED );
00079 
00080         wsa_init_done = 1;
00081     }
00082 #else
00083     signal( SIGPIPE, SIG_IGN );
00084 #endif
00085 
00086     if( ( server_host = gethostbyname( host ) ) == NULL )
00087         return( ERR_NET_UNKNOWN_HOST );
00088 
00089     if( ( *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) < 0 )
00090         return( ERR_NET_SOCKET_FAILED );
00091 
00092     memcpy( (void *) &server_addr.sin_addr,
00093             (void *) server_host->h_addr,
00094                      server_host->h_length );
00095 
00096     server_addr.sin_family = AF_INET;
00097     server_addr.sin_port = htons( (unsigned short) port );
00098 
00099     if( connect( *fd, (struct sockaddr *) &server_addr,
00100                  sizeof( server_addr ) ) < 0 )
00101     {
00102         close( *fd );
00103         return( ERR_NET_CONNECT_FAILED );
00104     }
00105 
00106     return( 0 );
00107 }
00108 
00109 /*
00110  * Create a listening socket on bind_ip:port
00111  */
00112 int net_bind( int *fd, char *bind_ip, unsigned int port )
00113 {
00114     int n, c[4];
00115     struct sockaddr_in server_addr;
00116 
00117 #if defined(WIN32) || defined(_WIN32_WCE)
00118     WSADATA wsaData;
00119 
00120     if( wsa_init_done == 0 )
00121     {
00122         if( WSAStartup( MAKEWORD(2,0), &wsaData ) == SOCKET_ERROR )
00123             return( ERR_NET_SOCKET_FAILED );
00124 
00125         wsa_init_done = 1;
00126     }
00127 #else
00128     signal( SIGPIPE, SIG_IGN );
00129 #endif
00130 
00131     *fd = socket( AF_INET, SOCK_STREAM, IPPROTO_IP );
00132     if( *fd < 0 )
00133         return( ERR_NET_SOCKET_FAILED );
00134 
00135     n = 1;
00136     setsockopt( *fd, SOL_SOCKET, SO_REUSEADDR,
00137                 (const char *) &n, sizeof( n ) );
00138 
00139     server_addr.sin_addr.s_addr = INADDR_ANY;
00140     server_addr.sin_family      = AF_INET;
00141     server_addr.sin_port        = htons( (unsigned short) port );
00142 
00143     if( bind_ip != NULL )
00144     {
00145         memset( c, 0, sizeof( c ) );
00146         sscanf( bind_ip, "%d.%d.%d.%d", &c[0], &c[1],
00147                                         &c[2], &c[3] );
00148 
00149         for( n = 0; n < 4; n++ )
00150             if( c[n] < 0 || c[n] > 255 )
00151                 break;
00152 
00153         if( n == 4 )
00154             server_addr.sin_addr.s_addr =
00155                 ( c[0] << 24 ) | ( c[1] << 16 ) |
00156                 ( c[2] <<  8 ) | ( c[3]       );
00157     }
00158 
00159     if( bind( *fd, (struct sockaddr *) &server_addr,
00160               sizeof( server_addr ) ) < 0 )
00161     {
00162         close( *fd );
00163         return( ERR_NET_BIND_FAILED );
00164     }
00165 
00166     if( listen( *fd, 10 ) != 0 )
00167     {
00168         close( *fd );
00169         return( ERR_NET_LISTEN_FAILED );
00170     }
00171 
00172     return( 0 );
00173 }
00174 
00175 /*
00176  * Check if the current operation is blocking
00177  */
00178 static int net_is_blocking( void )
00179 {
00180 #if defined(WIN32) || defined(_WIN32_WCE)
00181     return( WSAGetLastError() == WSAEWOULDBLOCK );
00182 #else
00183     switch( errno )
00184     {
00185 #if defined EAGAIN
00186         case EAGAIN:
00187 #endif
00188 #if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
00189         case EWOULDBLOCK:
00190 #endif
00191             return( 1 );
00192     }
00193     return( 0 );
00194 #endif
00195 }
00196 
00197 /*
00198  * Accept a connection from a remote client
00199  */
00200 int net_accept( int bind_fd, int *client_fd,
00201                 unsigned char client_ip[4] )
00202 {
00203     struct sockaddr_in client_addr;
00204 
00205 #if defined(__socklen_t_defined)
00206     socklen_t n = (socklen_t) sizeof( client_addr );
00207 #else
00208     int n = (int) sizeof( client_addr );
00209 #endif
00210 
00211     *client_fd = accept( bind_fd, (struct sockaddr *)
00212                          &client_addr, &n );
00213 
00214     if( *client_fd < 0 )
00215     {
00216         if( net_is_blocking() != 0 )
00217             return( ERR_NET_WOULD_BLOCK );
00218 
00219         return( ERR_NET_ACCEPT_FAILED );
00220     }
00221 
00222     if( client_ip != NULL )
00223         memcpy( client_ip, &client_addr.sin_addr.s_addr, 4 );
00224 
00225     return( 0 );
00226 }
00227 
00228 /*
00229  * Set the socket blocking or non-blocking
00230  */
00231 int net_set_block( int fd )
00232 {
00233 #if defined(WIN32) || defined(_WIN32_WCE)
00234     long n = 0;
00235     return( ioctlsocket( fd, FIONBIO, &n ) );
00236 #else
00237     return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) & ~O_NONBLOCK ) );
00238 #endif
00239 }
00240 
00241 int net_set_nonblock( int fd )
00242 {
00243 #if defined(WIN32) || defined(_WIN32_WCE)
00244     long n = 1;
00245     return( ioctlsocket( fd, FIONBIO, &n ) );
00246 #else
00247     return( fcntl( fd, F_SETFL, fcntl( fd, F_GETFL ) | O_NONBLOCK ) );
00248 #endif
00249 }
00250 
00251 /*
00252  * Portable usleep helper
00253  */
00254 void net_usleep( unsigned long usec )
00255 {
00256     struct timeval tv;
00257     tv.tv_sec  = 0;
00258     tv.tv_usec = usec;
00259     select( 0, NULL, NULL, NULL, &tv );
00260 }
00261 
00262 /*
00263  * Read at most 'len' characters
00264  */
00265 int net_recv( int fd, unsigned char *buf, int *len )
00266 { 
00267     int ret, n;
00268 
00269     n = *len;
00270     *len = 0;
00271 
00272     while( *len < n )
00273     {
00274         if( ( ret = read( fd, buf + *len, n - *len ) ) <= 0 )
00275         {
00276             if( ret == 0 )
00277                 return( ERR_NET_CONN_RESET );
00278 
00279             if( net_is_blocking() != 0 )
00280                 return( ERR_NET_WOULD_BLOCK );
00281 
00282 #if defined(WIN32) || defined(_WIN32_WCE)
00283             if( WSAGetLastError() == WSAECONNRESET )
00284                 return( ERR_NET_CONN_RESET );
00285 #else
00286             if( errno == EINTR )
00287                 continue;
00288 #endif
00289 
00290             return( ERR_NET_RECV_FAILED );
00291         }
00292 
00293         *len += ret;
00294     }
00295 
00296     return( 0 );
00297 }
00298 
00299 /*
00300  * Write at most 'len' characters
00301  */
00302 int net_send( int fd, unsigned char *buf, int *len )
00303 {
00304     int ret, n = 0;
00305 
00306     while( *len > 0 )
00307     {
00308         if( ( ret = write( fd, buf + n, *len ) ) < 0 )
00309         {
00310             if( net_is_blocking() != 0 )
00311                 return( ERR_NET_WOULD_BLOCK );
00312 
00313 #if defined(WIN32) || defined(_WIN32_WCE)
00314             if( WSAGetLastError() == WSAECONNRESET )
00315                 return( ERR_NET_CONN_RESET );
00316 #else
00317             if( errno == EINTR )
00318                 continue;
00319 
00320             if( errno == EPIPE )
00321                 return( ERR_NET_CONN_RESET );
00322 #endif
00323 
00324             return( ERR_NET_SEND_FAILED );
00325         }
00326 
00327         *len -= ret;
00328            n += ret;
00329     }
00330 
00331     return( 0 );
00332 }
00333 
00334 /*
00335  * Gracefully close the connection
00336  */
00337 void net_close( int fd )
00338 {
00339     shutdown( fd, 2 );
00340     close( fd );
00341 }

Generated on Fri May 16 14:49:55 2008 for Mobile-C by  doxygen 1.5.4