diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Socket.cc | 70 |
1 files changed, 67 insertions, 3 deletions
diff --git a/lib/Socket.cc b/lib/Socket.cc index 8c54f15..41db767 100644 --- a/lib/Socket.cc +++ b/lib/Socket.cc @@ -54,19 +54,83 @@ class dummy_win32_socket_class_t : public Base { typedef int socklen_t; #endif -Socket::Socket() throw (GeneralException) : Handle(socket(AF_INET, SOCK_STREAM, 0)), connected(false), listening(false), writeclosed(false), readclosed(false), connecting(false) { +Socket::Socket() throw (GeneralException) : Handle(socket(AF_INET, SOCK_STREAM, 0)), connected(false), listening(false), writeclosed(false), readclosed(false), connecting(false), pair(-1) { // cerr << "Socket(): connected = " << connected << "; readclosed = " << readclosed << "; writeclosed = " << writeclosed << endl; if (GetHandle() < 0) { throw GeneralException(_("Error creating socket.")); } } -Socket::Socket(const Socket & s) : Handle(s), connected(s.connected), listening(s.listening), writeclosed(s.writeclosed), readclosed(s.readclosed), connecting(s.connecting) { +Socket::Socket(const Socket & s) : Handle(s), connected(s.connected), listening(s.listening), writeclosed(s.writeclosed), readclosed(s.readclosed), connecting(s.connecting), pair(s.pair) { // cerr << "Constructing a socket by copy...\n"; // cerr << "Socket(const Socket &): connected = " << connected << "; readclosed = " << readclosed << "; writeclosed = " << writeclosed << endl; } -Socket::Socket(int h) : Handle(h), connected(true), listening(false), writeclosed(false), readclosed(false), connecting(false) { } +Socket::Socket(int h, int p) : Handle(h), connected(true), listening(false), writeclosed(false), readclosed(false), connecting(false), pair(p) { } + +static Socket CreatePair() throw (GeneralException) { + int socks[2]; +#ifdef _WIN32 + struct sockaddr_in addr; + SOCKET listener; + int e; + int addrlen = sizeof(addr); + DWORD flags = WSA_FLAG_OVERLAPPED + + socks[0] = socks[1] = INVALID_SOCKET; + if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) + throw GeneralException("WIN32 SocketPair: couldn't create the initial listener."); + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(0x7f000001); + addr.sin_port = 0; + + e = bind(listener, (const struct sockaddr*) &addr, sizeof(addr)); + if (e == SOCKET_ERROR) { + e = WSAGetLastError(); + closesocket(listener); + WSASetLastError(e); + throw GeneralException("WIN32 SocketPair: couldn't bind the initial listener."); + } + e = getsockname(listener, (struct sockaddr*) &addr, &addrlen); + if (e == SOCKET_ERROR) { + e = WSAGetLastError(); + closesocket(listener); + WSASetLastError(e); + throw GeneralException("WIN32 SocketPair: couldn't get the port number of the initial listener."); + } + + do { + if (listen(listener, 1) == SOCKET_ERROR) break; + if ((socks[0] = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, flags)) == INVALID_SOCKET) break; + if (connect(socks[0], (const struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR) break; + if ((socks[1] = accept(listener, NULL, NULL)) == INVALID_SOCKET) break; + closesocket(listener); + return Socket(socks[0], socks[1]); + } while (0); + e = WSAGetLastError(); + closesocket(listener); + closesocket(socks[0]); + closesocket(socks[1]); + WSASetLastError(e); + throw GeneralException("WIN32 SocketPair: error during creation..."); +#else + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, socks) == -1) { + throw GeneralException("Couldn't create a socket pair..."); + } + return Socket(socks[0], socks[1]); +#endif +} + +Socket GetPair() throw (GeneralException) { + if (pair != -1) { + int p = pair; + pair = -1; + return Socket(pair); + } + throw GeneralException("Not a paired socket."); +} String Socket::GetName(void) { return String("socket"); |