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>
38 #define vsnprintf _vsnprintf
55 extern "C" void init_tcpip( shawn::SimulationController& sc )
66 bool Socket::init_windows_sockets_ =
true;
67 bool Socket::windows_sockets_initialized_ =
false;
68 int Socket::instance_count_ = 0;
73 Socket(std::string host,
int port)
105 if( init_windows_sockets_ && !windows_sockets_initialized_ )
108 if( WSAStartup(MAKEWORD(1, 1), &wsaData) != 0 )
110 windows_sockets_initialized_ =
true;
122 int sock =
static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
123 struct sockaddr_in self;
124 memset(&
self, 0,
sizeof(
self));
125 self.sin_family = AF_INET;
126 self.sin_port = htons(0);
127 self.sin_addr.s_addr = htonl(INADDR_ANY);
129 socklen_t address_len =
sizeof(
self);
131 if ( bind(sock, (
struct sockaddr*) &
self, address_len) < 0)
134 if ( getsockname(sock, (
struct sockaddr*) &
self, &address_len) < 0)
135 BailOnSocketError(
"tcpip::Socket::getFreeSocketPort() Unable to get socket name");
136 const int port = ntohs(
self.sin_port);
138 ::closesocket( sock );
169 && init_windows_sockets_ && instance_count_ == 0 )
171 windows_sockets_initialized_ =
false;
181 int e = WSAGetLastError();
182 std::string msg = GetWinsockErrorString( e );
184 std::string msg =
strerror( errno );
200 #pragma warning(push)
202 #pragma warning(disable: 4548)
211 FD_SET( (
unsigned int)sock, &fds );
217 int r = select( sock+1, &fds,
nullptr,
nullptr, &tv);
222 if( FD_ISSET( sock, &fds ) )
234 atoaddr( std::string address,
struct sockaddr_in& addr)
237 struct addrinfo *servinfo;
239 struct addrinfo hints;
240 memset(&hints, 0,
sizeof hints);
241 hints.ai_family = AF_INET;
242 hints.ai_socktype = SOCK_STREAM;
243 hints.ai_flags = AI_PASSIVE;
245 if ((status = getaddrinfo(address.c_str(),
nullptr, &hints, &servinfo)) != 0) {
251 for (
struct addrinfo *p = servinfo; p !=
nullptr; p = p->ai_next) {
252 if (p->ai_family == AF_INET) {
253 addr = *(
struct sockaddr_in *)p->ai_addr;
254 addr.sin_port = htons((
unsigned short)
port_);
260 freeaddrinfo(servinfo);
274 struct sockaddr_in client_addr;
276 int addrlen =
sizeof(client_addr);
278 socklen_t addrlen =
sizeof(client_addr);
283 struct sockaddr_in self;
286 server_socket_ =
static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
298 setsockopt(
server_socket_, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,
sizeof(reuseaddr));
303 memset(&
self, 0,
sizeof(
self));
304 self.sin_family = AF_INET;
305 self.sin_port = htons((
unsigned short)
port_);
306 self.sin_addr.s_addr = htonl(INADDR_ANY);
309 if ( bind(
server_socket_, (
struct sockaddr*)&
self,
sizeof(
self)) != 0 )
326 setsockopt(
socket_, IPPROTO_TCP, TCP_NODELAY, (
const char*)&x,
sizeof(x));
348 if (ioctlsocket(
server_socket_, FIONBIO, &NonBlock) == SOCKET_ERROR)
349 BailOnSocketError(
"tcpip::Socket::set_blocking() Unable to initialize non blocking I/O");
374 socket_ =
static_cast<int>(socket( PF_INET, SOCK_STREAM, 0 ));
378 if( ::
connect(
socket_, (sockaddr
const*)&address,
sizeof(address) ) < 0 )
384 setsockopt(
socket_, IPPROTO_TCP, TCP_NODELAY, (
const char*)&x,
sizeof(x));
409 send(
const std::vector<unsigned char> &buffer)
416 size_t numbytes = buffer.size();
417 unsigned char const *bufPtr = &buffer[0];
418 while( numbytes > 0 )
421 int bytesSent =
::send(
socket_, (
const char*)bufPtr,
static_cast<int>(numbytes), 0 );
428 numbytes -= bytesSent;
441 int length =
static_cast<int>(b.
size());
448 std::vector<unsigned char> msg;
449 msg.insert(msg.end(), length_storage.
begin(), length_storage.
end());
450 msg.insert(msg.end(), b.
begin(), b.
end());
458 recvAndCheck(
unsigned char *
const buffer, std::size_t len)
462 const int bytesReceived = recv(
socket_, (
char*)buffer,
static_cast<int>(len), 0 );
464 const int bytesReceived =
static_cast<int>(recv(
socket_, buffer, len, 0 ));
466 if( bytesReceived == 0 )
467 throw SocketException(
"tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
468 if( bytesReceived < 0 )
471 return static_cast<size_t>(bytesReceived);
484 len -= bytesReceived;
485 buffer += bytesReceived;
498 std::cerr << label <<
" " << buffer.size() <<
" bytes via tcpip::Socket: [";
500 const std::vector<unsigned char>::const_iterator end = buffer.end();
501 for (std::vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
502 std::cerr <<
" " <<
static_cast<int>(*it) <<
" ";
503 std::cerr <<
"]" << std::endl;
509 std::vector<unsigned char>
513 std::vector<unsigned char> buffer;
521 buffer.resize(bufSize);
522 const size_t bytesReceived =
recvAndCheck(&buffer[0], bufSize);
524 buffer.resize(bytesReceived);
541 std::vector<unsigned char> buffer(
lengthLen);
546 const int totalLen = length_storage.
readInt();
550 buffer.resize(totalLen);
587 GetWinsockErrorString(
int err)
592 case 0:
return "No error";
593 case WSAEINTR:
return "Interrupted system call";
594 case WSAEBADF:
return "Bad file number";
595 case WSAEACCES:
return "Permission denied";
596 case WSAEFAULT:
return "Bad address";
597 case WSAEINVAL:
return "Invalid argument";
598 case WSAEMFILE:
return "Too many open sockets";
599 case WSAEWOULDBLOCK:
return "Operation would block";
600 case WSAEINPROGRESS:
return "Operation now in progress";
601 case WSAEALREADY:
return "Operation already in progress";
602 case WSAENOTSOCK:
return "Socket operation on non-socket";
603 case WSAEDESTADDRREQ:
return "Destination address required";
604 case WSAEMSGSIZE:
return "Message too long";
605 case WSAEPROTOTYPE:
return "Protocol wrong type for socket";
606 case WSAENOPROTOOPT:
return "Bad protocol option";
607 case WSAEPROTONOSUPPORT:
return "Protocol not supported";
608 case WSAESOCKTNOSUPPORT:
return "Socket type not supported";
609 case WSAEOPNOTSUPP:
return "Operation not supported on socket";
610 case WSAEPFNOSUPPORT:
return "Protocol family not supported";
611 case WSAEAFNOSUPPORT:
return "Address family not supported";
612 case WSAEADDRINUSE:
return "Address already in use";
613 case WSAEADDRNOTAVAIL:
return "Can't assign requested address";
614 case WSAENETDOWN:
return "Network is down";
615 case WSAENETUNREACH:
return "Network is unreachable";
616 case WSAENETRESET:
return "Net Socket reset";
617 case WSAECONNABORTED:
return "Software caused tcpip::Socket abort";
618 case WSAECONNRESET:
return "Socket reset by peer";
619 case WSAENOBUFS:
return "No buffer space available";
620 case WSAEISCONN:
return "Socket is already connected";
621 case WSAENOTCONN:
return "Socket is not connected";
622 case WSAESHUTDOWN:
return "Can't send after socket shutdown";
623 case WSAETOOMANYREFS:
return "Too many references, can't splice";
624 case WSAETIMEDOUT:
return "Socket timed out";
625 case WSAECONNREFUSED:
return "Socket refused";
626 case WSAELOOP:
return "Too many levels of symbolic links";
627 case WSAENAMETOOLONG:
return "File name too long";
628 case WSAEHOSTDOWN:
return "Host is down";
629 case WSAEHOSTUNREACH:
return "No route to host";
630 case WSAENOTEMPTY:
return "Directory not empty";
631 case WSAEPROCLIM:
return "Too many processes";
632 case WSAEUSERS:
return "Too many users";
633 case WSAEDQUOT:
return "Disc quota exceeded";
634 case WSAESTALE:
return "Stale NFS file handle";
635 case WSAEREMOTE:
return "Too many levels of remote in path";
636 case WSASYSNOTREADY:
return "Network system is unavailable";
637 case WSAVERNOTSUPPORTED:
return "Winsock version out of range";
638 case WSANOTINITIALISED:
return "WSAStartup not yet called";
639 case WSAEDISCON:
return "Graceful shutdown in progress";
640 case WSAHOST_NOT_FOUND:
return "Host not found";
641 case WSANO_DATA:
return "No host data of that type was found";
void printBufferOnVerbose(const std::vector< unsigned char > buffer, const std::string &label) const
Print label and buffer to stderr if Socket::verbose_ is set.
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_.
bool datawaiting(int sock) const
size_t recvAndCheck(unsigned char *const buffer, std::size_t len) const
Receive up to len available bytes from Socket::socket_.
static void BailOnSocketError(std::string context)
static int getFreeSocketPort()
Returns an free port on the system.
bool atoaddr(std::string, struct sockaddr_in &addr)
void sendExact(const Storage &)
bool has_client_connection() const
void connect()
Connects to host_:port_.
static const int lengthLen
Length of the message length part of a TraCI message.
Socket * accept(const bool create=false)
Wait for a incoming connection to port_.
void receiveComplete(unsigned char *const buffer, std::size_t len) const
Receive len bytes from Socket::socket_.
void send(const std::vector< unsigned char > &buffer)
Socket(std::string host, int port)
Constructor that prepare to connect to host:port.
virtual void writePacket(unsigned char *packet, int length)
StorageType::const_iterator begin() const
virtual void writeInt(int)
StorageType::const_iterator end() const
StorageType::size_type size() const
static std::string strerror()