summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/sys/windows/Socket.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/src/qpid/sys/windows/Socket.cpp')
-rw-r--r--[-rwxr-xr-x]cpp/src/qpid/sys/windows/Socket.cpp188
1 files changed, 69 insertions, 119 deletions
diff --git a/cpp/src/qpid/sys/windows/Socket.cpp b/cpp/src/qpid/sys/windows/Socket.cpp
index 11fb8b4133..1fa4768329 100755..100644
--- a/cpp/src/qpid/sys/windows/Socket.cpp
+++ b/cpp/src/qpid/sys/windows/Socket.cpp
@@ -20,19 +20,18 @@
*/
#include "qpid/sys/Socket.h"
+
#include "qpid/sys/SocketAddress.h"
-#include "qpid/sys/windows/IoHandlePrivate.h"
#include "qpid/sys/windows/check.h"
-#include "qpid/sys/Time.h"
+#include "qpid/sys/windows/IoHandlePrivate.h"
-#include <cstdlib>
-#include <string.h>
+// Ensure we get all of winsock2.h
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
#include <winsock2.h>
-#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
-
// Need to initialize WinSock. Ideally, this would be a singleton or embedded
// in some one-time initialization function. I tried boost singleton and could
// not get it to compile (and others located in google had the same problem).
@@ -84,53 +83,30 @@ namespace sys {
namespace {
-std::string getName(SOCKET fd, bool local, bool includeService = false)
+std::string getName(SOCKET fd, bool local)
{
- sockaddr_in name; // big enough for any socket address
- socklen_t namelen = sizeof(name);
+ ::sockaddr_storage name_s; // big enough for any socket address
+ ::sockaddr* name = (::sockaddr*)&name_s;
+ ::socklen_t namelen = sizeof(name_s);
+
if (local) {
- QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
+ QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
} else {
- QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
+ QPID_WINSOCK_CHECK(::getpeername(fd, name, &namelen));
}
- char servName[NI_MAXSERV];
- char dispName[NI_MAXHOST];
- if (includeService) {
- if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
- dispName, sizeof(dispName),
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- return std::string(dispName) + ":" + std::string(servName);
- } else {
- if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
- dispName, sizeof(dispName),
- 0, 0,
- NI_NUMERICHOST) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- return dispName;
- }
+ return SocketAddress::asString(name, namelen);
}
-std::string getService(SOCKET fd, bool local)
+uint16_t getLocalPort(int fd)
{
- sockaddr_in name; // big enough for any socket address
- socklen_t namelen = sizeof(name);
-
- if (local) {
- QPID_WINSOCK_CHECK(::getsockname(fd, (sockaddr*)&name, &namelen));
- } else {
- QPID_WINSOCK_CHECK(::getpeername(fd, (sockaddr*)&name, &namelen));
- }
+ ::sockaddr_storage name_s; // big enough for any socket address
+ ::sockaddr* name = (::sockaddr*)&name_s;
+ ::socklen_t namelen = sizeof(name_s);
+
+ QPID_WINSOCK_CHECK(::getsockname(fd, name, &namelen));
- char servName[NI_MAXSERV];
- if (int rc = ::getnameinfo((sockaddr*)&name, namelen,
- 0, 0,
- servName, sizeof(servName),
- NI_NUMERICHOST | NI_NUMERICSERV) != 0)
- throw qpid::Exception(QPID_MSG(gai_strerror(rc)));
- return servName;
+ return SocketAddress::getPort(name);
}
} // namespace
@@ -138,13 +114,7 @@ Socket::Socket() :
IOHandle(new IOHandlePrivate),
nonblocking(false),
nodelay(false)
-{
- SOCKET& socket = impl->fd;
- if (socket != INVALID_SOCKET) Socket::close();
- SOCKET s = ::socket (PF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
- socket = s;
-}
+{}
Socket::Socket(IOHandlePrivate* h) :
IOHandle(h),
@@ -152,8 +122,7 @@ Socket::Socket(IOHandlePrivate* h) :
nodelay(false)
{}
-void
-Socket::createSocket(const SocketAddress& sa) const
+void Socket::createSocket(const SocketAddress& sa) const
{
SOCKET& socket = impl->fd;
if (socket != INVALID_SOCKET) Socket::close();
@@ -168,24 +137,24 @@ Socket::createSocket(const SocketAddress& sa) const
if (nonblocking) setNonblocking();
if (nodelay) setTcpNoDelay();
} catch (std::exception&) {
- closesocket(s);
+ ::closesocket(s);
socket = INVALID_SOCKET;
throw;
}
}
-void Socket::setTimeout(const Duration& interval) const
-{
- const SOCKET& socket = impl->fd;
- int64_t nanosecs = interval;
- nanosecs /= (1000 * 1000); // nsecs -> usec -> msec
- int msec = 0;
- if (nanosecs > std::numeric_limits<int>::max())
- msec = std::numeric_limits<int>::max();
- else
- msec = static_cast<int>(nanosecs);
- setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec));
- setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&msec, sizeof(msec));
+Socket* Socket::createSameTypeSocket() const {
+ SOCKET& socket = impl->fd;
+ // Socket currently has no actual socket attached
+ if (socket == INVALID_SOCKET)
+ return new Socket;
+
+ ::sockaddr_storage sa;
+ ::socklen_t salen = sizeof(sa);
+ QPID_WINSOCK_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen));
+ SOCKET s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM
+ if (s == INVALID_SOCKET) throw QPID_WINDOWS_ERROR(WSAGetLastError());
+ return new Socket(new IOHandlePrivate(s));
}
void Socket::setNonblocking() const {
@@ -193,30 +162,25 @@ void Socket::setNonblocking() const {
QPID_WINSOCK_CHECK(ioctlsocket(impl->fd, FIONBIO, &nonblock));
}
-void Socket::connect(const std::string& host, uint16_t port) const
+void Socket::connect(const std::string& host, const std::string& port) const
{
- SocketAddress sa(host, boost::lexical_cast<std::string>(port));
+ SocketAddress sa(host, port);
connect(sa);
}
void
Socket::connect(const SocketAddress& addr) const
{
+ peername = addr.asString(false);
+
+ createSocket(addr);
+
const SOCKET& socket = impl->fd;
- const addrinfo *addrs = &(getAddrInfo(addr));
- int error = 0;
+ int err;
WSASetLastError(0);
- while (addrs != 0) {
- if ((::connect(socket, addrs->ai_addr, addrs->ai_addrlen) == 0) ||
- (WSAGetLastError() == WSAEWOULDBLOCK))
- break;
- // Error... save this error code and see if there are other address
- // to try before throwing the exception.
- error = WSAGetLastError();
- addrs = addrs->ai_next;
- }
- if (error)
- throw qpid::Exception(QPID_MSG(strError(error) << ": " << connectname));
+ if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) != 0) &&
+ ((err = ::WSAGetLastError()) != WSAEWOULDBLOCK))
+ throw qpid::Exception(QPID_MSG(strError(err) << ": " << peername));
}
void
@@ -247,24 +211,26 @@ int Socket::read(void *buf, size_t count) const
return received;
}
-int Socket::listen(uint16_t port, int backlog) const
+int Socket::listen(const std::string& host, const std::string& port, int backlog) const
+{
+ SocketAddress sa(host, port);
+ return listen(sa, backlog);
+}
+
+int Socket::listen(const SocketAddress& addr, int backlog) const
{
+ createSocket(addr);
+
const SOCKET& socket = impl->fd;
BOOL yes=1;
QPID_WINSOCK_CHECK(setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)));
- struct sockaddr_in name;
- memset(&name, 0, sizeof(name));
- name.sin_family = AF_INET;
- name.sin_port = htons(port);
- name.sin_addr.s_addr = 0;
- if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(WSAGetLastError())));
+
+ if (::bind(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) == SOCKET_ERROR)
+ throw Exception(QPID_MSG("Can't bind to " << addr.asString() << ": " << strError(WSAGetLastError())));
if (::listen(socket, backlog) == SOCKET_ERROR)
- throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(WSAGetLastError())));
-
- socklen_t namelen = sizeof(name);
- QPID_WINSOCK_CHECK(::getsockname(socket, (struct sockaddr*)&name, &namelen));
- return ntohs(name.sin_port);
+ throw Exception(QPID_MSG("Can't listen on " <<addr.asString() << ": " << strError(WSAGetLastError())));
+
+ return getLocalPort(socket);
}
Socket* Socket::accept() const
@@ -277,36 +243,20 @@ Socket* Socket::accept() const
else throw QPID_WINDOWS_ERROR(WSAGetLastError());
}
-std::string Socket::getSockname() const
-{
- return getName(impl->fd, true);
-}
-
-std::string Socket::getPeername() const
-{
- return getName(impl->fd, false);
-}
-
std::string Socket::getPeerAddress() const
{
- if (!connectname.empty())
- return std::string (connectname);
- return getName(impl->fd, false, true);
+ if (peername.empty()) {
+ peername = getName(impl->fd, false);
+ }
+ return peername;
}
std::string Socket::getLocalAddress() const
{
- return getName(impl->fd, true, true);
-}
-
-uint16_t Socket::getLocalPort() const
-{
- return atoi(getService(impl->fd, true).c_str());
-}
-
-uint16_t Socket::getRemotePort() const
-{
- return atoi(getService(impl->fd, true).c_str());
+ if (localname.empty()) {
+ localname = getName(impl->fd, true);
+ }
+ return localname;
}
int Socket::getError() const