00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
00061
00062 CUdpSock::CUdpSock( bool logging ) :
00063 CSock( logging ),
00064 _Bound( false )
00065 {
00066
00067 createSocket( SOCK_DGRAM, IPPROTO_UDP );
00068 }
00069
00070
00074 void CUdpSock::bind( uint16 port )
00075 {
00076 CInetAddress addr;
00077 addr.setPort( port );
00078 bind( addr );
00079 setLocalAddress();
00080 }
00081
00082
00083
00084
00085
00086 void CUdpSock::bind( const CInetAddress& addr )
00087 {
00088 #ifndef NL_OS_WINDOWS
00089
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
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
00114
00115 void CUdpSock::sendTo( const uint8 *buffer, uint len, const CInetAddress& addr )
00116 {
00117
00118
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
00131 if ( ! _Bound )
00132 {
00133 setLocalAddress();
00134 _Bound = true;
00135 }
00136
00137 #ifdef NL_OS_WINDOWS
00138
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
00155
00156 void CUdpSock::receive( uint8 *buffer, uint32& len )
00157 {
00158 nlassert( _Connected && (buffer!=NULL) );
00159
00160
00161 len = ::recv( _Sock, (char*)buffer, len , 0 );
00162
00163
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
00179
00180 void CUdpSock::receivedFrom( uint8 *buffer, uint& len, CInetAddress& addr )
00181 {
00182
00183 sockaddr_in saddr;
00184 socklen_t saddrlen = sizeof(saddr);
00185
00186 len = ::recvfrom( _Sock, (char*)buffer, len , 0, (sockaddr*)&saddr, &saddrlen );
00187
00188
00189
00190 addr.setSockAddr( &saddr );
00191
00192
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 }