diff options
author | Kim van der Riet <kpvdr@apache.org> | 2013-02-28 16:14:30 +0000 |
---|---|---|
committer | Kim van der Riet <kpvdr@apache.org> | 2013-02-28 16:14:30 +0000 |
commit | 9c73ef7a5ac10acd6a50d5d52bd721fc2faa5919 (patch) | |
tree | 2a890e1df09e5b896a9b4168a7b22648f559a1f2 /cpp/src/qpid/sys/posix/Socket.cpp | |
parent | 172d9b2a16cfb817bbe632d050acba7e31401cd2 (diff) | |
download | qpid-python-asyncstore.tar.gz |
Update from trunk r1375509 through r1450773asyncstore
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1451244 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/sys/posix/Socket.cpp')
-rw-r--r-- | cpp/src/qpid/sys/posix/Socket.cpp | 263 |
1 files changed, 0 insertions, 263 deletions
diff --git a/cpp/src/qpid/sys/posix/Socket.cpp b/cpp/src/qpid/sys/posix/Socket.cpp deleted file mode 100644 index 77ae1af60c..0000000000 --- a/cpp/src/qpid/sys/posix/Socket.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ - -#include "qpid/sys/Socket.h" - -#include "qpid/sys/SocketAddress.h" -#include "qpid/sys/posix/check.h" -#include "qpid/sys/posix/PrivatePosix.h" - -#include <fcntl.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/errno.h> -#include <unistd.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <netdb.h> -#include <cstdlib> -#include <string.h> - -namespace qpid { -namespace sys { - -namespace { -std::string getName(int fd, bool local) -{ - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - if (local) { - QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) ); - } else { - QPID_POSIX_CHECK( ::getpeername(fd, name, &namelen) ); - } - - return SocketAddress::asString(name, namelen); -} - -uint16_t getLocalPort(int fd) -{ - ::sockaddr_storage name_s; // big enough for any socket address - ::sockaddr* name = (::sockaddr*)&name_s; - ::socklen_t namelen = sizeof(name_s); - - QPID_POSIX_CHECK( ::getsockname(fd, name, &namelen) ); - - return SocketAddress::getPort(name); -} -} - -Socket::Socket() : - IOHandle(new IOHandlePrivate), - nonblocking(false), - nodelay(false) -{} - -Socket::Socket(IOHandlePrivate* h) : - IOHandle(h), - nonblocking(false), - nodelay(false) -{} - -void Socket::createSocket(const SocketAddress& sa) const -{ - int& socket = impl->fd; - if (socket != -1) Socket::close(); - int s = ::socket(getAddrInfo(sa).ai_family, getAddrInfo(sa).ai_socktype, 0); - if (s < 0) throw QPID_POSIX_ERROR(errno); - socket = s; - - try { - if (nonblocking) setNonblocking(); - if (nodelay) setTcpNoDelay(); - if (getAddrInfo(sa).ai_family == AF_INET6) { - int flag = 1; - int result = ::setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&flag, sizeof(flag)); - QPID_POSIX_CHECK(result); - } - } catch (std::exception&) { - ::close(s); - socket = -1; - throw; - } -} - -Socket* Socket::createSameTypeSocket() const { - int& socket = impl->fd; - // Socket currently has no actual socket attached - if (socket == -1) - return new Socket; - - ::sockaddr_storage sa; - ::socklen_t salen = sizeof(sa); - QPID_POSIX_CHECK(::getsockname(socket, (::sockaddr*)&sa, &salen)); - int s = ::socket(sa.ss_family, SOCK_STREAM, 0); // Currently only work with SOCK_STREAM - if (s < 0) throw QPID_POSIX_ERROR(errno); - return new Socket(new IOHandlePrivate(s)); -} - -void Socket::setNonblocking() const { - int& socket = impl->fd; - nonblocking = true; - if (socket != -1) { - QPID_POSIX_CHECK(::fcntl(socket, F_SETFL, O_NONBLOCK)); - } -} - -void Socket::setTcpNoDelay() const -{ - int& socket = impl->fd; - nodelay = true; - if (socket != -1) { - int flag = 1; - int result = ::setsockopt(impl->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag)); - QPID_POSIX_CHECK(result); - } -} - -void Socket::connect(const std::string& host, const std::string& port) const -{ - SocketAddress sa(host, port); - connect(sa); -} - -void Socket::connect(const SocketAddress& addr) const -{ - // The display name for an outbound connection needs to be the name that was specified - // for the address rather than a resolved IP address as we don't know which of - // the IP addresses is actually the one that will be connected to. - peername = addr.asString(false); - - // However the string we compare with the local port must be numeric or it might not - // match when it should as getLocalAddress() will always be numeric - std::string connectname = addr.asString(); - - createSocket(addr); - - const int& socket = impl->fd; - // TODO the correct thing to do here is loop on failure until you've used all the returned addresses - if ((::connect(socket, getAddrInfo(addr).ai_addr, getAddrInfo(addr).ai_addrlen) < 0) && - (errno != EINPROGRESS)) { - throw Exception(QPID_MSG(strError(errno) << ": " << peername)); - } - // When connecting to a port on the same host which no longer has - // a process associated with it, the OS occasionally chooses the - // remote port (which is unoccupied) as the port to bind the local - // end of the socket, resulting in a "circular" connection. - // - // This seems like something the OS should prevent but I have - // confirmed that sporadic hangs in - // cluster_tests.LongTests.test_failover on RHEL5 are caused by - // such a circular connection. - // - // Raise an error if we see such a connection, since we know there is - // no listener on the peer address. - // - if (getLocalAddress() == connectname) { - close(); - throw Exception(QPID_MSG("Connection refused: " << peername)); - } -} - -void -Socket::close() const -{ - int& socket = impl->fd; - if (socket == -1) return; - if (::close(socket) < 0) throw QPID_POSIX_ERROR(errno); - socket = -1; -} - -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& sa, int backlog) const -{ - createSocket(sa); - - const int& socket = impl->fd; - int yes=1; - QPID_POSIX_CHECK(::setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes))); - - if (::bind(socket, getAddrInfo(sa).ai_addr, getAddrInfo(sa).ai_addrlen) < 0) - throw Exception(QPID_MSG("Can't bind to port " << sa.asString() << ": " << strError(errno))); - if (::listen(socket, backlog) < 0) - throw Exception(QPID_MSG("Can't listen on port " << sa.asString() << ": " << strError(errno))); - - return getLocalPort(socket); -} - -Socket* Socket::accept() const -{ - int afd = ::accept(impl->fd, 0, 0); - if ( afd >= 0) { - Socket* s = new Socket(new IOHandlePrivate(afd)); - s->localname = localname; - return s; - } - else if (errno == EAGAIN) - return 0; - else throw QPID_POSIX_ERROR(errno); -} - -int Socket::read(void *buf, size_t count) const -{ - return ::read(impl->fd, buf, count); -} - -int Socket::write(const void *buf, size_t count) const -{ - return ::write(impl->fd, buf, count); -} - -std::string Socket::getPeerAddress() const -{ - if (peername.empty()) { - peername = getName(impl->fd, false); - } - return peername; -} - -std::string Socket::getLocalAddress() const -{ - if (localname.empty()) { - localname = getName(impl->fd, true); - } - return localname; -} - -int Socket::getError() const -{ - int result; - socklen_t rSize = sizeof (result); - - if (::getsockopt(impl->fd, SOL_SOCKET, SO_ERROR, &result, &rSize) < 0) - throw QPID_POSIX_ERROR(errno); - - return result; -} - -}} // namespace qpid::sys |