summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/Socket.h5
-rw-r--r--lib/Socket.cc70
2 files changed, 71 insertions, 4 deletions
diff --git a/include/Socket.h b/include/Socket.h
index bb226bc..89df89f 100644
--- a/include/Socket.h
+++ b/include/Socket.h
@@ -48,6 +48,8 @@ class Socket : public Handle {
void CloseWrite();
void CloseRead();
bool FinalizeConnect();
+ static Socket CreatePair() throw (GeneralException);
+ Socket GetPair() throw (GeneralException);
protected:
virtual ssize_t nwrite(const void *, size_t) throw (GeneralException);
virtual ssize_t nread(void *, size_t) throw (GeneralException);
@@ -55,8 +57,9 @@ class Socket : public Handle {
virtual int nclose() throw (GeneralException);
private:
- Socket(int s);
+ Socket(int s, int p = -1);
bool connected, listening, writeclosed, readclosed, connecting;
+ int pair;
};
#endif
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");