# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

udp_sock.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #include "stdnet.h"
00027 
00028 #include "nel/net/udp_sock.h"
00029 
00030 #ifdef NL_OS_WINDOWS
00031 #include <winsock2.h>
00032 #define socklen_t int
00033 #define ERROR_NUM WSAGetLastError()
00034 
00035 #elif defined NL_OS_UNIX
00036 #include <unistd.h>
00037 #include <sys/types.h>
00038 #include <sys/time.h>
00039 #include <sys/socket.h>
00040 #include <netinet/in.h>
00041 #include <netinet/tcp.h>
00042 #include <arpa/inet.h>
00043 #include <netdb.h>
00044 #include <errno.h>
00045 //#include <fcntl.h>
00046 #define SOCKET_ERROR -1
00047 #define INVALID_SOCKET -1
00048 #define ERROR_NUM errno
00049 #define ERROR_MSG strerror(errno)
00050 typedef int SOCKET;
00051 
00052 #endif
00053 
00054 using namespace NLMISC;
00055 
00056 namespace NLNET {
00057 
00058 
00059 /*
00060  * Constructor
00061  */
00062 CUdpSock::CUdpSock( bool logging ) :
00063         CSock( logging ),
00064         _Bound( false )
00065 {
00066         // Socket creation
00067         createSocket( SOCK_DGRAM, IPPROTO_UDP );
00068 }
00069 
00070 
00074 void CUdpSock::bind( uint16 port )
00075 {
00076         CInetAddress addr; // any IP address
00077         addr.setPort( port );
00078         bind( addr );
00079         setLocalAddress(); // will not set the address if the host is multihomed, use bind(CInetAddress) instead
00080 }
00081 
00082 
00083 /*
00084  * Same as bind(uint16) but binds on a specified address/port (useful when the host has several addresses)
00085  */
00086 void CUdpSock::bind( const CInetAddress& addr )
00087 {
00088 #ifndef NL_OS_WINDOWS
00089         // Set Reuse Address On (does not work on Win98 and is useless on Win2000)
00090         int value = true;
00091         if ( setsockopt( _Sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value) ) == SOCKET_ERROR )
00092         {
00093                 throw ESocket( "ReuseAddr failed" );
00094         }
00095 #endif
00096 
00097         _LocalAddr = addr;
00098 
00099         // Bind the socket
00100         if ( ::bind( _Sock, (sockaddr*)(_LocalAddr.sockAddr()), sizeof(sockaddr) ) == SOCKET_ERROR )
00101         {
00102                 throw ESocket( "Bind failed" );
00103         }
00104         _Bound = true;
00105         if ( _Logging )
00106         {
00107                 nldebug( "LNETL0: Socket %d bound at %s", _Sock, _LocalAddr.asString().c_str() );
00108         }
00109 }
00110 
00111 
00112 /*
00113  * Sends a message
00114  */
00115 void CUdpSock::sendTo( const uint8 *buffer, uint len, const CInetAddress& addr )
00116 {
00117         
00118         //  Send
00119         if ( ::sendto( _Sock, (const char*)buffer, len, 0, (sockaddr*)(addr.sockAddr()), sizeof(sockaddr) ) != (sint32)len )
00120         {
00121                 throw ESocket( "Unable to send datagram" );
00122         }
00123         _BytesSent += len;
00124 
00125         if ( _Logging )
00126         {
00127                 nldebug( "LNETL0: Socket %d sent %d bytes to %s", _Sock, len, addr.asString().c_str() );
00128         }
00129 
00130         // If socket is unbound, retrieve local address
00131         if ( ! _Bound )
00132         {
00133                 setLocalAddress();
00134                 _Bound = true;
00135         }
00136 
00137 #ifdef NL_OS_WINDOWS
00138         // temporary by ace to know size of SO_MAX_MSG_SIZE
00139         static bool first = true;
00140         if (first)
00141         {
00142                 uint MMS, SB;
00143                 int  size = sizeof (MMS);
00144                 getsockopt (_Sock, SOL_SOCKET, SO_SNDBUF, (char *)&SB, &size);
00145                 getsockopt (_Sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&MMS, &size);
00146                 nlinfo ("the udp SO_MAX_MSG_SIZE=%u, SO_SNDBUF=%u", MMS, SB);
00147                 first = false;
00148         }
00149 #endif
00150 }
00151 
00152 
00153 /*
00154  * Receives data from the peer. (blocking function)
00155  */
00156 void CUdpSock::receive( uint8 *buffer, uint32& len )
00157 {
00158         nlassert( _Connected && (buffer!=NULL) );
00159 
00160         // Receive incoming message
00161         len = ::recv( _Sock, (char*)buffer, len , 0 );
00162 
00163         // Check for errors (after setting the address)
00164         if ( len == SOCKET_ERROR )
00165         {
00166                 throw ESocket( "Cannot receive data" );
00167         }
00168 
00169         _BytesReceived += len;
00170         if ( _Logging )
00171         {
00172                 nldebug( "LNETL0: Socket %d received %d bytes from peer %s", _Sock, len, _RemoteAddr.asString().c_str() );
00173         }
00174 }
00175 
00176 
00177 /*
00178  * Receives data and say who the sender is. (blocking function)
00179  */
00180 void CUdpSock::receivedFrom( uint8 *buffer, uint& len, CInetAddress& addr )
00181 {
00182         // Receive incoming message
00183         sockaddr_in saddr;
00184         socklen_t saddrlen = sizeof(saddr);
00185 
00186         len = ::recvfrom( _Sock, (char*)buffer, len , 0, (sockaddr*)&saddr, &saddrlen );
00187 
00188         // If an error occurs, the saddr is not valid
00189         // When the remote socket is closed, get sender's address to know who is quitting
00190         addr.setSockAddr( &saddr );
00191 
00192         // Check for errors (after setting the address)
00193         if ( len == SOCKET_ERROR )
00194         {
00195                 throw ESocket( "Cannot receive data" );
00196         }
00197 
00198         _BytesReceived += len;
00199         if ( _Logging )
00200         {
00201                 nldebug( "LNETL0: Socket %d received %d bytes from %s", _Sock, len, addr.asString().c_str() );
00202         }
00203 }
00204 
00205 
00206 } // NLNET