/* * Receives data and say who the sender is. (blocking function) */ bool CUdpSock::receivedFrom( uint8 *buffer, uint& len, CInetAddress& addr, bool throw_exception ) { // Receive incoming message sockaddr_in saddr; socklen_t saddrlen = sizeof(saddr); len = ::recvfrom( _Sock, (char*)buffer, len , 0, (sockaddr*)&saddr, &saddrlen ); // If an error occurs, the saddr is not valid // When the remote socket is closed, get sender's address to know who is quitting addr.setSockAddr( &saddr ); // Check for errors (after setting the address) if ( ((int)len) == SOCKET_ERROR ) { if ( throw_exception ) throw ESocket( "Cannot receive data" ); return false; } _BytesReceived += len; if ( _Logging ) { LNETL0_DEBUG( "LNETL0: Socket %d received %d bytes from %s", _Sock, len, addr.asString().c_str() ); } return true; }
void ListenSock::init( const Address& addr ) { // Create socket createSocket(SOCK_STREAM, IPPROTO_TCP); setBacklog(-1); // Bind socket to port if ( ::bind( _socket, (const sockaddr *)addr.sockAddr(), sizeof(sockaddr_in) ) != 0 ) { throw ESocket( "Unable to bind listen socket to port" ); } _LocalAddr = addr; _Bound = true; // Listen if ( ::listen( _socket, _BackLog ) != 0 ) // SOMAXCONN = maximum length of the queue of pending connections { throw ESocket( "Unable to listen on specified port" ); } }
/* * Same as bind(uint16) but binds on a specified address/port (useful when the host has several addresses) */ void CUdpSock::bind( const CInetAddress& addr ) { #ifndef NL_OS_WINDOWS // Set Reuse Address On (does not work on Win98 and is useless on Win2000) int value = true; if ( setsockopt( _Sock, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value) ) == SOCKET_ERROR ) { throw ESocket( "ReuseAddr failed" ); } #endif _LocalAddr = addr; // Bind the socket if ( ::bind( _Sock, (sockaddr*)(_LocalAddr.sockAddr()), sizeof(sockaddr) ) == SOCKET_ERROR ) { throw ESocket( "Bind failed" ); } _Bound = true; if ( _Logging ) { LNETL0_DEBUG( "LNETL0: Socket %d bound at %s", _Sock, _LocalAddr.asString().c_str() ); } }
void ListenSock::setBacklog( s32 backlog ) { if ( backlog == -1 ) { _BackLog = SOMAXCONN; // SOMAXCONN = maximum length of the queue of pending connections } else { _BackLog = backlog; } if ( _Bound ) { if ( ::listen( _socket, _BackLog ) != 0 ) { throw ESocket( "Unable to listen on specified port, while changing backlog" ); } } }
TCPSocket * ListenSock::accept() { // Accept connection sockaddr_in saddr; socklen_t saddrlen = (socklen_t)sizeof(saddr); SOCKET newsock = (SOCKET)::accept( _socket, (sockaddr*)&saddr, &saddrlen ); if ( newsock == INVALID_SOCKET ) { if (_socket == INVALID_SOCKET) // normal case, the listen sock have been closed, just return NULL. return NULL; throw ESocket( "Accept returned an invalid socket"); } // Construct and save a CTcpSock object Address addr; addr.setSockAddr( &saddr ); TCPSocket *connection = new TCPSocket( newsock, addr ); return connection; }
/* * Receives data from the peer. (blocking function) */ bool CUdpSock::receive( uint8 *buffer, uint32& len, bool throw_exception ) { nlassert( _Connected && (buffer!=NULL) ); // Receive incoming message len = ::recv( _Sock, (char*)buffer, len , 0 ); // Check for errors (after setting the address) if ( ((int)len) == SOCKET_ERROR ) { if ( throw_exception ) throw ESocket( "Cannot receive data" ); return false; } _BytesReceived += len; if ( _Logging ) { LNETL0_DEBUG( "LNETL0: Socket %d received %d bytes from peer %s", _Sock, len, _RemoteAddr.asString().c_str() ); } return true; }
/* * Sends a message */ void CUdpSock::sendTo( const uint8 *buffer, uint len, const CInetAddress& addr ) { // Send if ( ::sendto( _Sock, (const char*)buffer, len, 0, (sockaddr*)(addr.sockAddr()), sizeof(sockaddr) ) != (sint32)len ) { throw ESocket( "Unable to send datagram" ); } _BytesSent += len; if ( _Logging ) { LNETL0_DEBUG( "LNETL0: Socket %d sent %d bytes to %s", _Sock, len, addr.asString().c_str() ); } // If socket is unbound, retrieve local address if ( ! _Bound ) { setLocalAddress(); _Bound = true; } #ifdef NL_OS_WINDOWS // temporary by ace to know size of SO_MAX_MSG_SIZE static bool first = true; if (first) { uint MMS, SB; int size = sizeof (MMS); getsockopt (_Sock, SOL_SOCKET, SO_SNDBUF, (char *)&SB, &size); getsockopt (_Sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&MMS, &size); LNETL0_INFO ("LNETL0: The udp SO_MAX_MSG_SIZE=%u, SO_SNDBUF=%u", MMS, SB); first = false; } #endif }