10 #include <apps/tcpip/socket.h>
11 #include <sys/simulation/simulation_controller.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <netinet/tcp.h>
24 #include <arpa/inet.h>
37 #define vsnprintf _vsnprintf
56 extern "C" void init_tcpip( shawn::SimulationController& sc )
64 const int Socket::lengthLen = 4;
67 bool Socket::init_windows_sockets_ =
true;
68 bool Socket::windows_sockets_initialized_ =
false;
69 int Socket::instance_count_ = 0;
74 Socket(std::string host,
int port)
106 if( init_windows_sockets_ && !windows_sockets_initialized_ )
109 if( WSAStartup(MAKEWORD(1, 1), &wsaData) != 0 )
111 windows_sockets_initialized_ =
true;
139 && init_windows_sockets_ && instance_count_ == 0 )
141 windows_sockets_initialized_ =
false;
152 int e = WSAGetLastError();
153 std::string msg = GetWinsockErrorString( e );
155 std::string msg = strerror( errno );
177 FD_SET( sock, &fds );
183 int r = select( sock+1, &fds, NULL, NULL, &tv);
186 BailOnSocketError(
"tcpip::Socket::datawaiting @ select");
188 if( FD_ISSET( sock, &fds ) )
197 atoaddr( std::string address,
struct in_addr& addr)
199 struct hostent* host;
200 struct in_addr saddr;
203 saddr.s_addr = inet_addr(address.c_str());
204 if (saddr.s_addr != static_cast<unsigned int>(-1))
210 host = gethostbyname(address.c_str());
212 addr = *((
struct in_addr*)host->h_addr_list[0]);
229 struct sockaddr_in client_addr;
231 int addrlen =
sizeof(client_addr);
233 socklen_t addrlen =
sizeof(client_addr);
238 struct sockaddr_in self;
241 server_socket_ =
static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
242 if( server_socket_ < 0 )
253 setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
sizeof(reuseaddr));
258 memset(&
self, 0,
sizeof(
self));
259 self.sin_family = AF_INET;
260 self.sin_port = htons(
port_);
261 self.sin_addr.s_addr = htonl(INADDR_ANY);
264 if ( bind(server_socket_, (
struct sockaddr*)&
self,
sizeof(
self)) != 0 )
269 if ( listen(server_socket_, 10) == -1 )
281 setsockopt(
socket_, IPPROTO_TCP, TCP_NODELAY, (
const char*)&x,
sizeof(x));
291 blocking_ = blocking;
293 if( server_socket_ > 0 )
296 ULONG NonBlock = blocking_ ? 0 : 1;
297 if (ioctlsocket(server_socket_, FIONBIO, &NonBlock) == SOCKET_ERROR)
298 BailOnSocketError(
"tcpip::Socket::set_blocking() Unable to initialize non blocking I/O");
300 long arg = fcntl(server_socket_, F_GETFL, NULL);
307 fcntl(server_socket_, F_SETFL, arg);
324 memset( (
char*)&address, 0,
sizeof(address) );
325 address.sin_family = AF_INET;
326 address.sin_port = htons(
port_ );
327 address.sin_addr.s_addr = addr.s_addr;
329 socket_ =
static_cast<int>(socket( PF_INET, SOCK_STREAM, 0 ));
333 if( ::
connect(
socket_, (sockaddr
const*)&address,
sizeof(address) ) < 0 )
339 setsockopt(
socket_, IPPROTO_TCP, TCP_NODELAY, (
const char*)&x,
sizeof(x));
365 send(
const std::vector<unsigned char> &buffer)
371 printBufferOnVerbose(buffer,
"Send");
373 size_t numbytes = buffer.size();
374 unsigned char const *bufPtr = &buffer[0];
375 while( numbytes > 0 )
378 int bytesSent = ::send( socket_, (
const char*)bufPtr, static_cast<int>(numbytes), 0 );
380 int bytesSent = ::send( socket_, bufPtr, numbytes, 0 );
383 BailOnSocketError(
"send failed" );
385 numbytes -= bytesSent;
399 int length =
static_cast<int>(b.size());
401 length_storage.
writeInt(lengthLen + length);
406 vector<unsigned char> msg;
407 msg.insert(msg.end(), length_storage.
begin(), length_storage.
end());
408 msg.insert(msg.end(), b.begin(), b.end());
420 const int bytesReceived = recv(
socket_, (
char*)buffer, static_cast<int>(len), 0 );
422 const int bytesReceived =
static_cast<int>(recv(
socket_, buffer, len, 0 ));
424 if( bytesReceived == 0 )
425 throw SocketException(
"tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
426 if( bytesReceived < 0 )
429 return static_cast<size_t>(bytesReceived);
442 len -= bytesReceived;
443 buffer += bytesReceived;
456 cerr << label <<
" " << buffer.size() <<
" bytes via tcpip::Socket: [";
458 const vector<unsigned char>::const_iterator end = buffer.end();
459 for (vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
460 cerr <<
" " << static_cast<int>(*it) <<
" ";
467 vector<unsigned char>
472 vector<unsigned char> buffer;
477 if( !datawaiting( socket_) )
480 buffer.resize(bufSize);
481 const size_t bytesReceived = recvAndCheck(&buffer[0], bufSize);
483 buffer.resize(bytesReceived);
485 printBufferOnVerbose(buffer,
"Rcvd");
501 vector<unsigned char> buffer(lengthLen);
504 receiveComplete(&buffer[0], lengthLen);
505 Storage length_storage(&buffer[0], lengthLen);
506 const int totalLen = length_storage.
readInt();
507 assert(totalLen > lengthLen);
510 buffer.resize(totalLen);
513 receiveComplete(&buffer[lengthLen], totalLen - lengthLen);
517 msg.writePacket(&buffer[lengthLen], totalLen - lengthLen);
519 printBufferOnVerbose(buffer,
"Rcvd Storage with");
548 GetWinsockErrorString(
int err)
554 case 0:
return "No error";
555 case WSAEINTR:
return "Interrupted system call";
556 case WSAEBADF:
return "Bad file number";
557 case WSAEACCES:
return "Permission denied";
558 case WSAEFAULT:
return "Bad address";
559 case WSAEINVAL:
return "Invalid argument";
560 case WSAEMFILE:
return "Too many open sockets";
561 case WSAEWOULDBLOCK:
return "Operation would block";
562 case WSAEINPROGRESS:
return "Operation now in progress";
563 case WSAEALREADY:
return "Operation already in progress";
564 case WSAENOTSOCK:
return "Socket operation on non-socket";
565 case WSAEDESTADDRREQ:
return "Destination address required";
566 case WSAEMSGSIZE:
return "Message too long";
567 case WSAEPROTOTYPE:
return "Protocol wrong type for socket";
568 case WSAENOPROTOOPT:
return "Bad protocol option";
569 case WSAEPROTONOSUPPORT:
return "Protocol not supported";
570 case WSAESOCKTNOSUPPORT:
return "Socket type not supported";
571 case WSAEOPNOTSUPP:
return "Operation not supported on socket";
572 case WSAEPFNOSUPPORT:
return "Protocol family not supported";
573 case WSAEAFNOSUPPORT:
return "Address family not supported";
574 case WSAEADDRINUSE:
return "Address already in use";
575 case WSAEADDRNOTAVAIL:
return "Can't assign requested address";
576 case WSAENETDOWN:
return "Network is down";
577 case WSAENETUNREACH:
return "Network is unreachable";
578 case WSAENETRESET:
return "Net Socket reset";
579 case WSAECONNABORTED:
return "Software caused tcpip::Socket abort";
580 case WSAECONNRESET:
return "Socket reset by peer";
581 case WSAENOBUFS:
return "No buffer space available";
582 case WSAEISCONN:
return "Socket is already connected";
583 case WSAENOTCONN:
return "Socket is not connected";
584 case WSAESHUTDOWN:
return "Can't send after socket shutdown";
585 case WSAETOOMANYREFS:
return "Too many references, can't splice";
586 case WSAETIMEDOUT:
return "Socket timed out";
587 case WSAECONNREFUSED:
return "Socket refused";
588 case WSAELOOP:
return "Too many levels of symbolic links";
589 case WSAENAMETOOLONG:
return "File name too long";
590 case WSAEHOSTDOWN:
return "Host is down";
591 case WSAEHOSTUNREACH:
return "No route to host";
592 case WSAENOTEMPTY:
return "Directory not empty";
593 case WSAEPROCLIM:
return "Too many processes";
594 case WSAEUSERS:
return "Too many users";
595 case WSAEDQUOT:
return "Disc quota exceeded";
596 case WSAESTALE:
return "Stale NFS file handle";
597 case WSAEREMOTE:
return "Too many levels of remote in path";
598 case WSASYSNOTREADY:
return "Network system is unavailable";
599 case WSAVERNOTSUPPORTED:
return "Winsock version out of range";
600 case WSANOTINITIALISED:
return "WSAStartup not yet called";
601 case WSAEDISCON:
return "Graceful shutdown in progress";
602 case WSAHOST_NOT_FOUND:
return "Host not found";
603 case WSANO_DATA:
return "No host data of that type was found";
613 #endif // BUILD_TCPIP
bool receiveExact(Storage &)
Receive a complete TraCI message from Socket::socket_.
std::vector< unsigned char > receive(int bufSize=2048)
Receive up to bufSize available bytes from Socket::socket_.
void printBufferOnVerbose(const std::vector< unsigned char > buffer, const std::string &label) const
Print label and buffer to stderr if Socket::verbose_ is set.
void accept()
Wait for a incoming connection to port_.
Socket(std::string host, int port)
Constructor that prepare to connect to host:port.
virtual void writeInt(int)
void connect()
Connects to host_:port_.
bool datawaiting(int sock) const
bool atoaddr(std::string, struct in_addr &addr)
StorageType::const_iterator end() const
void BailOnSocketError(std::string) const
size_t recvAndCheck(unsigned char *const buffer, std::size_t len) const
Receive up to len available bytes from Socket::socket_.
void send(const std::vector< unsigned char > &buffer)
void sendExact(const Storage &)
void receiveComplete(unsigned char *const buffer, std::size_t len) const
Receive len bytes from Socket::socket_.
StorageType::const_iterator begin() const
bool has_client_connection() const