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

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

Generated on Tue Jul 1 15:29:59 2008 for Mobile-C by  doxygen 1.5.4