socketConnection.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <limits>
00019
00020 #include "socketConnection.h"
00021
00022 #include "connectionDescription.h"
00023 #include "node.h"
00024
00025 #include <eq/base/base.h>
00026 #include <eq/base/log.h>
00027
00028 #include <errno.h>
00029 #include <sstream>
00030 #include <string.h>
00031 #include <sys/types.h>
00032
00033 #ifdef WIN32
00034 # ifndef WSA_FLAG_SDP
00035 # define WSA_FLAG_SDP 0x40
00036 # endif
00037 # define EQ_SOCKET_ERROR getErrorString( GetLastError( )) << \
00038 "(" << GetLastError() << ")"
00039 # include "socketConnectionWin32.cpp"
00040
00041 #else
00042 # define EQ_SOCKET_ERROR strerror( errno ) << "(" << errno << ")"
00043 # include <arpa/inet.h>
00044 # include <netdb.h>
00045 # include <netinet/tcp.h>
00046 # include <sys/socket.h>
00047 # ifndef AF_INET_SDP
00048 # define AF_INET_SDP 27
00049 # endif
00050
00051 # include "socketConnectionPosix.cpp"
00052 #endif
00053
00054 namespace eq
00055 {
00056 namespace net
00057 {
00058 bool SocketConnection::_createSocket()
00059 {
00060 #ifdef WIN32
00061 const DWORD flags = _description->type == CONNECTIONTYPE_SDP ?
00062 WSA_FLAG_OVERLAPPED | WSA_FLAG_SDP :
00063 WSA_FLAG_OVERLAPPED;
00064
00065 const SOCKET fd = WSASocket( AF_INET, SOCK_STREAM, IPPROTO_TCP, 0,0,flags );
00066
00067 if( _description->type == CONNECTIONTYPE_SDP )
00068 EQINFO << "Created SDP socket" << std::endl;
00069 #else
00070 Socket fd;
00071 if( _description->type == CONNECTIONTYPE_SDP )
00072 fd = ::socket( AF_INET_SDP, SOCK_STREAM, IPPROTO_TCP );
00073 else
00074 fd = ::socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
00075 #endif
00076
00077 if( fd == INVALID_SOCKET )
00078 {
00079 EQERROR << "Could not create socket: " << EQ_SOCKET_ERROR << std::endl;
00080 return false;
00081 }
00082
00083 _tuneSocket( fd );
00084
00085 _readFD = fd;
00086 _writeFD = fd;
00087 return true;
00088 }
00089
00090 void SocketConnection::_tuneSocket( const Socket fd )
00091 {
00092 const int on = 1;
00093 setsockopt( fd, IPPROTO_TCP, TCP_NODELAY,
00094 reinterpret_cast<const char*>( &on ), sizeof( on ));
00095 setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
00096 reinterpret_cast<const char*>( &on ), sizeof( on ));
00097
00098 #ifdef WIN32
00099 const int size = 128768;
00100 setsockopt( fd, SOL_SOCKET, SO_RCVBUF,
00101 reinterpret_cast<const char*>( &size ), sizeof( size ));
00102 setsockopt( fd, SOL_SOCKET, SO_SNDBUF,
00103 reinterpret_cast<const char*>( &size ), sizeof( size ));
00104 #endif
00105 }
00106
00107 bool SocketConnection::_parseAddress( sockaddr_in& socketAddress )
00108 {
00109 socketAddress.sin_family = AF_INET;
00110 socketAddress.sin_addr.s_addr = htonl( INADDR_ANY );
00111 socketAddress.sin_port = htons( _description->TCPIP.port );
00112 memset( &(socketAddress.sin_zero), 0, 8 );
00113
00114 const std::string& hostname = _description->getHostname();
00115 if( !hostname.empty( ))
00116 {
00117 hostent *hptr = gethostbyname( hostname.c_str( ));
00118 if( hptr )
00119 memcpy(&socketAddress.sin_addr.s_addr, hptr->h_addr,hptr->h_length);
00120 else
00121 {
00122 EQWARN << "Can't resolve host " << hostname << std::endl;
00123 return false;
00124 }
00125 }
00126
00127 EQINFO << "Address " << inet_ntoa( socketAddress.sin_addr )
00128 << ":" << ntohs( socketAddress.sin_port ) << std::endl;
00129 return true;
00130 }
00131
00132
00133
00134 bool SocketConnection::listen()
00135 {
00136 EQASSERT( _description->type == CONNECTIONTYPE_TCPIP ||
00137 _description->type == CONNECTIONTYPE_SDP );
00138
00139 if( _state != STATE_CLOSED )
00140 return false;
00141
00142 _state = STATE_CONNECTING;
00143 _fireStateChanged();
00144
00145 if( !_createSocket())
00146 return false;
00147
00148 sockaddr_in socketAddress;
00149 const size_t size = sizeof( sockaddr_in );
00150
00151 if( !_parseAddress( socketAddress ))
00152 {
00153 EQWARN << "Can't parse connection parameters" << std::endl;
00154 close();
00155 return false;
00156 }
00157
00158 const bool bound = (::bind(_readFD, (sockaddr *)&socketAddress, size) == 0);
00159
00160 if( !bound )
00161 {
00162 EQWARN << "Could not bind socket " << _readFD << ": "
00163 << EQ_SOCKET_ERROR << " to "
00164 << inet_ntoa( socketAddress.sin_addr )
00165 << ":" << ntohs( socketAddress.sin_port ) << " AF "
00166 << (int)socketAddress.sin_family << std::endl;
00167
00168 close();
00169 return false;
00170 }
00171 else if( socketAddress.sin_port == 0 )
00172 EQINFO << "Bound to port " << _getPort() << std::endl;
00173
00174 const bool listening = (::listen( _readFD, 10 ) == 0);
00175
00176 if( !listening )
00177 {
00178 EQWARN << "Could not listen on socket: " << EQ_SOCKET_ERROR << std::endl;
00179 close();
00180 return false;
00181 }
00182
00183
00184 sockaddr_in address;
00185 socklen_t used = sizeof(address);
00186 getsockname( _readFD, (struct sockaddr *)&address, &used );
00187
00188 _description->TCPIP.port = ntohs( address.sin_port );
00189
00190 const std::string& hostname = _description->getHostname();
00191 if( hostname.empty( ))
00192 {
00193 if( address.sin_addr.s_addr == INADDR_ANY )
00194 {
00195 char cHostname[256];
00196 gethostname( cHostname, 256 );
00197 _description->setHostname( cHostname );
00198 }
00199 else
00200 _description->setHostname( inet_ntoa( address.sin_addr ));
00201 }
00202
00203 _initAIOAccept();
00204 _state = STATE_LISTENING;
00205 _fireStateChanged();
00206
00207 EQINFO << "Listening on " << _description->getHostname() << "["
00208 << inet_ntoa( socketAddress.sin_addr ) << "]:"
00209 << _description->TCPIP.port << " (" << _description->toString()
00210 << ")" << std::endl;
00211
00212 return true;
00213 }
00214
00215 uint16_t SocketConnection::_getPort() const
00216 {
00217 sockaddr_in address;
00218 socklen_t used = sizeof(address);
00219 getsockname( _readFD, (struct sockaddr *) &address, &used );
00220 return ntohs(address.sin_port);
00221 }
00222
00223 }
00224 }