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

Generated on Fri Jul 11 17:59:46 2008 for Mobile-C by  doxygen 1.5.4