diff --git a/headers/os/net/AbstractSocket.h b/headers/os/net/AbstractSocket.h index b0033763e5..761379099e 100644 --- a/headers/os/net/AbstractSocket.h +++ b/headers/os/net/AbstractSocket.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2016, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _ABSTRACT_SOCKET_H @@ -20,8 +20,12 @@ public: status_t InitCheck() const; - virtual status_t Bind(const BNetworkAddress& local) = 0; + virtual status_t Bind(const BNetworkAddress& local, bool reuseAddr) = 0; virtual bool IsBound() const; + virtual bool IsListening() const; + + virtual status_t Listen(int backlog = 10); + virtual status_t Accept(BAbstractSocket*& _socket) = 0; virtual status_t Connect(const BNetworkAddress& peer, bigtime_t timeout = B_INFINITE_TIMEOUT) = 0; @@ -44,9 +48,12 @@ public: int Socket() const; protected: - status_t Bind(const BNetworkAddress& local, int type); + status_t Bind(const BNetworkAddress& local, + bool reuseAddr, int type); status_t Connect(const BNetworkAddress& peer, int type, bigtime_t timeout = B_INFINITE_TIMEOUT); + status_t AcceptNext(int& _acceptedSocket, + BNetworkAddress& _peer); private: status_t _OpenIfNeeded(int family, int type); @@ -60,6 +67,7 @@ protected: BNetworkAddress fPeer; bool fIsBound; bool fIsConnected; + bool fIsListening; }; diff --git a/headers/os/net/DatagramSocket.h b/headers/os/net/DatagramSocket.h index c555a9105d..945e0a6d6c 100644 --- a/headers/os/net/DatagramSocket.h +++ b/headers/os/net/DatagramSocket.h @@ -17,10 +17,13 @@ public: BDatagramSocket(const BDatagramSocket& other); virtual ~BDatagramSocket(); - virtual status_t Bind(const BNetworkAddress& peer); + virtual status_t Bind(const BNetworkAddress& peer, + bool reuseAddr = true); virtual status_t Connect(const BNetworkAddress& peer, bigtime_t timeout = B_INFINITE_TIMEOUT); + virtual status_t Accept(BAbstractSocket*& _socket); + status_t SetBroadcast(bool broadcast); void SetPeer(const BNetworkAddress& peer); diff --git a/headers/os/net/SecureSocket.h b/headers/os/net/SecureSocket.h index 8e13d20836..ebf1e15e39 100644 --- a/headers/os/net/SecureSocket.h +++ b/headers/os/net/SecureSocket.h @@ -1,5 +1,5 @@ /* - * Copyright 2011-2015, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2016, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _SECURE_SOCKET_H @@ -27,6 +27,8 @@ public: // BSocket implementation + virtual status_t Accept(BAbstractSocket*& _socket); + virtual status_t Connect(const BNetworkAddress& peer, bigtime_t timeout = B_INFINITE_TIMEOUT); virtual void Disconnect(); @@ -40,7 +42,9 @@ public: virtual ssize_t Write(const void* buffer, size_t size); protected: - status_t _Setup(); + status_t _SetupCommon(); + status_t _SetupConnect(); + status_t _SetupAccept(); private: friend class BCertificate; diff --git a/headers/os/net/Socket.h b/headers/os/net/Socket.h index 77ed2cb565..94070a3786 100644 --- a/headers/os/net/Socket.h +++ b/headers/os/net/Socket.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Copyright 2011-2016, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _SOCKET_H @@ -17,7 +17,11 @@ public: BSocket(const BSocket& other); virtual ~BSocket(); - virtual status_t Bind(const BNetworkAddress& peer); + virtual status_t Bind(const BNetworkAddress& peer, + bool reuseAddr = true); + + virtual status_t Accept(BAbstractSocket*& _socket); + virtual status_t Connect(const BNetworkAddress& peer, bigtime_t timeout = B_INFINITE_TIMEOUT); @@ -26,8 +30,7 @@ public: virtual ssize_t Read(void* buffer, size_t size); virtual ssize_t Write(const void* buffer, size_t size); -private: - friend class BServerSocket; +protected: void _SetTo(int fd, const BNetworkAddress& local, const BNetworkAddress& peer); diff --git a/src/kits/network/libnetapi/AbstractSocket.cpp b/src/kits/network/libnetapi/AbstractSocket.cpp index b42b4af7b4..1f851a41d3 100644 --- a/src/kits/network/libnetapi/AbstractSocket.cpp +++ b/src/kits/network/libnetapi/AbstractSocket.cpp @@ -1,5 +1,6 @@ /* * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -25,7 +26,8 @@ BAbstractSocket::BAbstractSocket() fInitStatus(B_NO_INIT), fSocket(-1), fIsBound(false), - fIsConnected(false) + fIsConnected(false), + fIsListening(false) { } @@ -35,7 +37,8 @@ BAbstractSocket::BAbstractSocket(const BAbstractSocket& other) fInitStatus(other.fInitStatus), fLocal(other.fLocal), fPeer(other.fPeer), - fIsConnected(other.fIsConnected) + fIsConnected(other.fIsConnected), + fIsListening(other.fIsListening) { fSocket = dup(other.fSocket); if (fSocket < 0) @@ -63,6 +66,13 @@ BAbstractSocket::IsBound() const } +bool +BAbstractSocket::IsListening() const +{ + return fIsListening; +} + + bool BAbstractSocket::IsConnected() const { @@ -70,6 +80,20 @@ BAbstractSocket::IsConnected() const } +status_t +BAbstractSocket::Listen(int backlog) +{ + if (!fIsBound) + return B_NO_INIT; + + if (listen(Socket(), backlog) != 0) + return fInitStatus = errno; + + fIsListening = true; + return B_OK; +} + + void BAbstractSocket::Disconnect() { @@ -163,12 +187,20 @@ BAbstractSocket::Socket() const status_t -BAbstractSocket::Bind(const BNetworkAddress& local, int type) +BAbstractSocket::Bind(const BNetworkAddress& local, bool reuseAddr, int type) { fInitStatus = _OpenIfNeeded(local.Family(), type); if (fInitStatus != B_OK) return fInitStatus; + if (reuseAddr) { + int value = 1; + if (setsockopt(Socket(), SOL_SOCKET, SO_REUSEADDR, &value, + sizeof(value)) != 0) { + return fInitStatus = errno; + } + } + if (bind(fSocket, local, local.Length()) != 0) return fInitStatus = errno; @@ -191,7 +223,7 @@ BAbstractSocket::Connect(const BNetworkAddress& peer, int type, if (fInitStatus == B_OK && !IsBound()) { BNetworkAddress local; local.SetToWildcard(peer.Family()); - fInitStatus = Bind(local); + fInitStatus = Bind(local, true); } if (fInitStatus != B_OK) return fInitStatus; @@ -214,6 +246,22 @@ BAbstractSocket::Connect(const BNetworkAddress& peer, int type, } +status_t +BAbstractSocket::AcceptNext(int& _acceptedSocket, BNetworkAddress& _peer) +{ + sockaddr_storage source; + socklen_t sourceLength = sizeof(sockaddr_storage); + + int fd = accept(fSocket, (sockaddr*)&source, &sourceLength); + if (fd < 0) + return fd; + + _peer.SetTo(source); + _acceptedSocket = fd; + return B_OK; +} + + // #pragma mark - private diff --git a/src/kits/network/libnetapi/DatagramSocket.cpp b/src/kits/network/libnetapi/DatagramSocket.cpp index 23f59ab06c..26ab20703f 100644 --- a/src/kits/network/libnetapi/DatagramSocket.cpp +++ b/src/kits/network/libnetapi/DatagramSocket.cpp @@ -39,9 +39,16 @@ BDatagramSocket::~BDatagramSocket() status_t -BDatagramSocket::Bind(const BNetworkAddress& local) +BDatagramSocket::Bind(const BNetworkAddress& local, bool reuseAddr) { - return BAbstractSocket::Bind(local, SOCK_DGRAM); + return BAbstractSocket::Bind(local, reuseAddr, SOCK_DGRAM); +} + + +status_t +BDatagramSocket::Accept(BAbstractSocket*& _socket) +{ + return B_NOT_SUPPORTED; } diff --git a/src/kits/network/libnetapi/ProxySecureSocket.cpp b/src/kits/network/libnetapi/ProxySecureSocket.cpp index 1ad8a234b0..111dbc3e94 100644 --- a/src/kits/network/libnetapi/ProxySecureSocket.cpp +++ b/src/kits/network/libnetapi/ProxySecureSocket.cpp @@ -70,7 +70,7 @@ BProxySecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) if (httpStatus < 200 || httpStatus > 299) return B_BAD_VALUE; - return _Setup(); + return _SetupConnect(); } diff --git a/src/kits/network/libnetapi/SecureSocket.cpp b/src/kits/network/libnetapi/SecureSocket.cpp index d5e31e3224..ef66cf8a86 100644 --- a/src/kits/network/libnetapi/SecureSocket.cpp +++ b/src/kits/network/libnetapi/SecureSocket.cpp @@ -1,6 +1,7 @@ /* - * Copyright 2013-2015 Haiku, Inc. + * Copyright 2013-2016 Haiku, Inc. * Copyright 2011-2015, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2016, Rene Gollent, rene@gollent.com. * Copyright 2010, Clemens Zeidler * Distributed under the terms of the MIT License. */ @@ -18,6 +19,8 @@ #include #include +#include + #include "CertificatePrivate.h" @@ -256,6 +259,33 @@ BSecureSocket::~BSecureSocket() } +status_t +BSecureSocket::Accept(BAbstractSocket*& _socket) +{ + int fd = -1; + BNetworkAddress peer; + status_t error = AcceptNext(fd, peer); + if (error != B_OK) + return error; + BSecureSocket* socket = new(std::nothrow) BSecureSocket(); + ObjectDeleter socketDeleter(socket); + if (socket == NULL || socket->InitCheck() != B_OK) { + close(fd); + return B_NO_MEMORY; + } + + socket->_SetTo(fd, fLocal, peer); + error = socket->_SetupAccept(); + if (error != B_OK) + return error; + + _socket = socket; + socketDeleter.Detach(); + + return B_OK; +} + + status_t BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) { @@ -267,7 +297,7 @@ BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) if (status != B_OK) return status; - return _Setup(); + return _SetupConnect(); } @@ -351,7 +381,7 @@ BSecureSocket::Write(const void* buffer, size_t size) status_t -BSecureSocket::_Setup() +BSecureSocket::_SetupCommon() { // Do this only after BSocket::Connect has checked wether we're already // connected. We don't want to kill an existing SSL session, as that would @@ -370,6 +400,17 @@ BSecureSocket::_Setup() SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO); SSL_set_ex_data(fPrivate->fSSL, Private::sDataIndex, this); + return B_OK; +} + + +status_t +BSecureSocket::_SetupConnect() +{ + status_t error = _SetupCommon(); + if (error != B_OK) + return error; + int returnValue = SSL_connect(fPrivate->fSSL); if (returnValue <= 0) { TRACE("SSLConnection can't connect\n"); @@ -381,6 +422,24 @@ BSecureSocket::_Setup() } +status_t +BSecureSocket::_SetupAccept() +{ + status_t error = _SetupCommon(); + if (error != B_OK) + return error; + + int returnValue = SSL_accept(fPrivate->fSSL); + if (returnValue <= 0) { + TRACE("SSLConnection can't accept\n"); + BSocket::Disconnect(); + return fPrivate->ErrorCode(returnValue); + } + + return B_OK; +} + + #else // OPENSSL_ENABLED @@ -418,6 +477,13 @@ BSecureSocket::CertificateVerificationFailed(BCertificate& certificate, const ch } +status_t +BSecureSocket::Accept(BAbstractSocket*& _socket) +{ + return B_UNSUPPORTED; +} + + status_t BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) { @@ -463,7 +529,21 @@ BSecureSocket::InitCheck() status_t -BSecureSocket::_Setup() +BSecureSocket::_SetupCommon() +{ + return B_UNSUPPORTED; +} + + +status_t +BSecureSocket::_SetupConnect() +{ + return B_UNSUPPORTED; +} + + +status_t +BSecureSocket::_SetupAccept() { return B_UNSUPPORTED; } diff --git a/src/kits/network/libnetapi/Socket.cpp b/src/kits/network/libnetapi/Socket.cpp index 987549a7be..6b891a7f53 100644 --- a/src/kits/network/libnetapi/Socket.cpp +++ b/src/kits/network/libnetapi/Socket.cpp @@ -1,5 +1,6 @@ /* * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2016, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -39,9 +40,9 @@ BSocket::~BSocket() status_t -BSocket::Bind(const BNetworkAddress& local) +BSocket::Bind(const BNetworkAddress& local, bool reuseAddr) { - return BAbstractSocket::Bind(local, SOCK_STREAM); + return BAbstractSocket::Bind(local, SOCK_STREAM, reuseAddr); } @@ -52,6 +53,26 @@ BSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) } +status_t +BSocket::Accept(BAbstractSocket*& _socket) +{ + int fd = -1; + BNetworkAddress peer; + status_t error = AcceptNext(fd, peer); + if (error != B_OK) + return error; + BSocket* socket = new(std::nothrow) BSocket(); + if (socket == NULL) { + close(fd); + return B_NO_MEMORY; + } + + socket->_SetTo(fd, fLocal, peer); + _socket = socket; + return B_OK; +} + + // #pragma mark - BDataIO implementation @@ -94,6 +115,7 @@ BSocket::_SetTo(int fd, const BNetworkAddress& local, fSocket = fd; fLocal = local; fPeer = peer; + fIsConnected = true; TRACE("%p: accepted from %s to %s\n", this, local.ToString().c_str(), peer.ToString().c_str());