From 0e478f5aec9c927e74e335c03cde8a7f623ddc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 21 Nov 2011 22:07:52 +0100 Subject: [PATCH] Added experimental version of a Socket API with SSL support. * Each class has a Socket() method to retrieve the underlaying file descriptor to be able to do the more advanced stuff, if necessary. * A server socket is yet missing, but the rest is pretty much covered. --- headers/os/net/AbstractSocket.h | 66 +++++ headers/os/net/DatagramSocket.h | 41 +++ headers/os/net/SecureSocket.h | 38 +++ headers/os/net/Socket.h | 37 +++ src/kits/network/libnetapi/AbstractSocket.cpp | 268 ++++++++++++++++++ src/kits/network/libnetapi/DatagramSocket.cpp | 142 ++++++++++ src/kits/network/libnetapi/SSL.cpp | 31 ++ src/kits/network/libnetapi/SecureSocket.cpp | 233 +++++++++++++++ src/kits/network/libnetapi/Socket.cpp | 100 +++++++ 9 files changed, 956 insertions(+) create mode 100644 headers/os/net/AbstractSocket.h create mode 100644 headers/os/net/DatagramSocket.h create mode 100644 headers/os/net/SecureSocket.h create mode 100644 headers/os/net/Socket.h create mode 100644 src/kits/network/libnetapi/AbstractSocket.cpp create mode 100644 src/kits/network/libnetapi/DatagramSocket.cpp create mode 100644 src/kits/network/libnetapi/SSL.cpp create mode 100644 src/kits/network/libnetapi/SecureSocket.cpp create mode 100644 src/kits/network/libnetapi/Socket.cpp diff --git a/headers/os/net/AbstractSocket.h b/headers/os/net/AbstractSocket.h new file mode 100644 index 0000000000..b0033763e5 --- /dev/null +++ b/headers/os/net/AbstractSocket.h @@ -0,0 +1,66 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _ABSTRACT_SOCKET_H +#define _ABSTRACT_SOCKET_H + + +#include +#include + +#include + + +class BAbstractSocket : public BDataIO { +public: + BAbstractSocket(); + BAbstractSocket(const BAbstractSocket& other); + virtual ~BAbstractSocket(); + + status_t InitCheck() const; + + virtual status_t Bind(const BNetworkAddress& local) = 0; + virtual bool IsBound() const; + + virtual status_t Connect(const BNetworkAddress& peer, + bigtime_t timeout = B_INFINITE_TIMEOUT) = 0; + virtual bool IsConnected() const; + virtual void Disconnect(); + + virtual status_t SetTimeout(bigtime_t timeout); + virtual bigtime_t Timeout() const; + + virtual const BNetworkAddress& Local() const; + virtual const BNetworkAddress& Peer() const; + + virtual size_t MaxTransmissionSize() const; + + virtual status_t WaitForReadable(bigtime_t timeout + = B_INFINITE_TIMEOUT) const; + virtual status_t WaitForWritable(bigtime_t timeout + = B_INFINITE_TIMEOUT) const; + + int Socket() const; + +protected: + status_t Bind(const BNetworkAddress& local, int type); + status_t Connect(const BNetworkAddress& peer, int type, + bigtime_t timeout = B_INFINITE_TIMEOUT); + +private: + status_t _OpenIfNeeded(int family, int type); + status_t _UpdateLocalAddress(); + status_t _WaitFor(int flags, bigtime_t timeout) const; + +protected: + status_t fInitStatus; + int fSocket; + BNetworkAddress fLocal; + BNetworkAddress fPeer; + bool fIsBound; + bool fIsConnected; +}; + + +#endif // _ABSTRACT_SOCKET_H diff --git a/headers/os/net/DatagramSocket.h b/headers/os/net/DatagramSocket.h new file mode 100644 index 0000000000..c4c2a2033b --- /dev/null +++ b/headers/os/net/DatagramSocket.h @@ -0,0 +1,41 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _DATAGRAM_SOCKET_H +#define _DATAGRAM_SOCKET_H + + +#include + + +class BDatagramSocket : public BAbstractSocket { +public: + BDatagramSocket(); + BDatagramSocket(const BNetworkAddress& peer, + bigtime_t timeout = -1); + BDatagramSocket(const BDatagramSocket& other); + virtual ~BDatagramSocket(); + + virtual status_t Bind(const BNetworkAddress& peer); + virtual status_t Connect(const BNetworkAddress& peer, + bigtime_t timeout = B_INFINITE_TIMEOUT); + + status_t SetBroadcast(bool broadcast); + void SetPeer(const BNetworkAddress& peer); + + virtual size_t MaxTransmissionSize() const; + + virtual size_t SendTo(const BNetworkAddress& address, + const void* buffer, size_t size); + virtual size_t ReceiveFrom(void* buffer, size_t bufferSize, + BNetworkAddress& from); + + // BDataIO implementation + + virtual ssize_t Read(void* buffer, size_t size); + virtual ssize_t Write(const void* buffer, size_t size); +}; + + +#endif // _DATAGRAM_SOCKET_H diff --git a/headers/os/net/SecureSocket.h b/headers/os/net/SecureSocket.h new file mode 100644 index 0000000000..bd59fc5505 --- /dev/null +++ b/headers/os/net/SecureSocket.h @@ -0,0 +1,38 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _SECURE_SOCKET_H +#define _SECURE_SOCKET_H + + +#include + + +class BSecureSocket : public BSocket { +public: + BSecureSocket(); + BSecureSocket(const BNetworkAddress& peer, + bigtime_t timeout = B_INFINITE_TIMEOUT); + BSecureSocket(const BSecureSocket& other); + virtual ~BSecureSocket(); + + virtual status_t Connect(const BNetworkAddress& peer, + bigtime_t timeout = B_INFINITE_TIMEOUT); + virtual void Disconnect(); + + virtual status_t WaitForReadable(bigtime_t timeout + = B_INFINITE_TIMEOUT) const; + + // BDataIO implementation + + virtual ssize_t Read(void* buffer, size_t size); + virtual ssize_t Write(const void* buffer, size_t size); + +private: + class Private; + Private* fPrivate; +}; + + +#endif // _SECURE_SOCKET_H diff --git a/headers/os/net/Socket.h b/headers/os/net/Socket.h new file mode 100644 index 0000000000..77ed2cb565 --- /dev/null +++ b/headers/os/net/Socket.h @@ -0,0 +1,37 @@ +/* + * Copyright 2011, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _SOCKET_H +#define _SOCKET_H + + +#include + + +class BSocket : public BAbstractSocket { +public: + BSocket(); + BSocket(const BNetworkAddress& peer, + bigtime_t timeout = B_INFINITE_TIMEOUT); + BSocket(const BSocket& other); + virtual ~BSocket(); + + virtual status_t Bind(const BNetworkAddress& peer); + virtual status_t Connect(const BNetworkAddress& peer, + bigtime_t timeout = B_INFINITE_TIMEOUT); + + // BDataIO implementation + + virtual ssize_t Read(void* buffer, size_t size); + virtual ssize_t Write(const void* buffer, size_t size); + +private: + friend class BServerSocket; + + void _SetTo(int fd, const BNetworkAddress& local, + const BNetworkAddress& peer); +}; + + +#endif // _SOCKET_H diff --git a/src/kits/network/libnetapi/AbstractSocket.cpp b/src/kits/network/libnetapi/AbstractSocket.cpp new file mode 100644 index 0000000000..cc928f18de --- /dev/null +++ b/src/kits/network/libnetapi/AbstractSocket.cpp @@ -0,0 +1,268 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include +#include +#include + + +//#define TRACE_SOCKET +#ifdef TRACE_SOCKET +# define TRACE(x...) printf(x) +#else +# define TRACE(x...) ; +#endif + + +BAbstractSocket::BAbstractSocket() + : + fInitStatus(B_NO_INIT), + fSocket(-1), + fIsBound(false), + fIsConnected(false) +{ +} + + +BAbstractSocket::BAbstractSocket(const BAbstractSocket& other) + : + fInitStatus(other.fInitStatus), + fLocal(other.fLocal), + fPeer(other.fPeer), + fIsConnected(other.fIsConnected) +{ + fSocket = dup(other.fSocket); + if (fSocket < 0) + fInitStatus = errno; +} + + +BAbstractSocket::~BAbstractSocket() +{ + Disconnect(); +} + + +status_t +BAbstractSocket::InitCheck() const +{ + return fInitStatus; +} + + +bool +BAbstractSocket::IsBound() const +{ + return fIsBound; +} + + +bool +BAbstractSocket::IsConnected() const +{ + return fIsConnected; +} + + +void +BAbstractSocket::Disconnect() +{ + if (fSocket < 0) + return; + + TRACE("%p: BAbstractSocket::Disconnect()\n", this); + + close(fSocket); + fSocket = -1; + fIsConnected = false; + fIsBound = false; +} + + +status_t +BAbstractSocket::SetTimeout(bigtime_t timeout) +{ + if (timeout < 0) + timeout = 0; + + struct timeval tv; + tv.tv_sec = timeout / 1000000LL; + tv.tv_usec = timeout % 1000000LL; + + if (setsockopt(fSocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(timeval)) != 0 + || setsockopt(fSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, + sizeof(timeval)) != 0) + return errno; + + return B_OK; +} + + +bigtime_t +BAbstractSocket::Timeout() const +{ + struct timeval tv; + socklen_t size = sizeof(tv); + if (getsockopt(fSocket, SOL_SOCKET, SO_SNDTIMEO, &tv, &size) != 0) + return B_INFINITE_TIMEOUT; + + return tv.tv_sec * 1000000LL + tv.tv_usec; +} + + +const BNetworkAddress& +BAbstractSocket::Local() const +{ + return fLocal; +} + + +const BNetworkAddress& +BAbstractSocket::Peer() const +{ + return fPeer; +} + + +size_t +BAbstractSocket::MaxTransmissionSize() const +{ + return SSIZE_MAX; +} + + +status_t +BAbstractSocket::WaitForReadable(bigtime_t timeout) const +{ + return _WaitFor(POLLIN, timeout); +} + + +status_t +BAbstractSocket::WaitForWritable(bigtime_t timeout) const +{ + return _WaitFor(POLLOUT, timeout); +} + + +int +BAbstractSocket::Socket() const +{ + return fSocket; +} + + +// #pragma mark - protected + + +status_t +BAbstractSocket::Bind(const BNetworkAddress& local, int type) +{ + fInitStatus = _OpenIfNeeded(local.Family(), type); + if (fInitStatus != B_OK) + return fInitStatus; + + if (bind(fSocket, local, local.Length()) != 0) + return fInitStatus = errno; + + fIsBound = true; + _UpdateLocalAddress(); + return B_OK; +} + + +status_t +BAbstractSocket::Connect(const BNetworkAddress& peer, int type, + bigtime_t timeout) +{ + Disconnect(); + + fInitStatus = _OpenIfNeeded(peer.Family(), type); + if (fInitStatus == B_OK) + fInitStatus = SetTimeout(timeout); + + if (fInitStatus == B_OK && !IsBound()) { + BNetworkAddress local; + local.SetToWildcard(peer.Family()); + fInitStatus = Bind(local); + } + if (fInitStatus != B_OK) + return fInitStatus; + + BNetworkAddress normalized = peer; + if (connect(fSocket, normalized, normalized.Length()) != 0) { + TRACE("%p: connecting to %s: %s\n", this, + normalized.ToString().c_str(), strerror(errno)); + return fInitStatus = errno; + } + + fIsConnected = true; + fPeer = normalized; + _UpdateLocalAddress(); + + TRACE("%p: connected to %s (local %s)\n", this, peer.ToString().c_str(), + fLocal.ToString().c_str()); + + return fInitStatus = B_OK; +} + + +// #pragma mark - private + + +status_t +BAbstractSocket::_OpenIfNeeded(int family, int type) +{ + if (fSocket >= 0) + return B_OK; + + fSocket = socket(family, type, 0); + if (fSocket < 0) + return errno; + + TRACE("%p: socket opened FD %d\n", this, fSocket); + return B_OK; +} + + +status_t +BAbstractSocket::_UpdateLocalAddress() +{ + socklen_t localLength = sizeof(sockaddr_storage); + if (getsockname(fSocket, fLocal, &localLength) != 0) + return errno; + + return B_OK; +} + + +status_t +BAbstractSocket::_WaitFor(int flags, bigtime_t timeout) const +{ + if (fInitStatus != B_OK) + return fInitStatus; + + int millis = 0; + if (timeout == B_INFINITE_TIMEOUT) + millis = -1; + if (timeout > 0) + millis = timeout / 1000; + + struct pollfd entry; + entry.fd = Socket(); + entry.events = flags; + + int result = poll(&entry, 1, -1); + if (result < 0) + return errno; + if (result == 0) + return millis > 0 ? B_TIMED_OUT : B_WOULD_BLOCK; + + return B_OK; +} diff --git a/src/kits/network/libnetapi/DatagramSocket.cpp b/src/kits/network/libnetapi/DatagramSocket.cpp new file mode 100644 index 0000000000..15be2fac86 --- /dev/null +++ b/src/kits/network/libnetapi/DatagramSocket.cpp @@ -0,0 +1,142 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +//#define TRACE_SOCKET +#ifdef TRACE_SOCKET +# define TRACE(x...) printf(x) +#else +# define TRACE(x...) ; +#endif + + +BDatagramSocket::BDatagramSocket() +{ +} + + +BDatagramSocket::BDatagramSocket(const BNetworkAddress& peer, bigtime_t timeout) +{ + Connect(peer, timeout); +} + + +BDatagramSocket::BDatagramSocket(const BDatagramSocket& other) + : + BAbstractSocket(other) +{ +} + + +BDatagramSocket::~BDatagramSocket() +{ +} + + +status_t +BDatagramSocket::Bind(const BNetworkAddress& local) +{ + return BAbstractSocket::Bind(local, SOCK_DGRAM); +} + + +status_t +BDatagramSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) +{ + return BAbstractSocket::Connect(peer, SOCK_DGRAM, timeout); +} + + +status_t +BDatagramSocket::SetBroadcast(bool broadcast) +{ + int value = broadcast ? 1 : 0; + if (setsockopt(fSocket, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value)) + != 0) + return errno; + + return B_OK; +} + + +void +BDatagramSocket::SetPeer(const BNetworkAddress& peer) +{ + fPeer = peer; +} + + +size_t +BDatagramSocket::MaxTransmissionSize() const +{ + // TODO: might vary on family! + return 32768; +} + + +size_t +BDatagramSocket::SendTo(const BNetworkAddress& address, const void* buffer, + size_t size) +{ + ssize_t bytesSent = sendto(fSocket, buffer, size, 0, address, + address.Length()); + if (bytesSent < 0) + return errno; + + return bytesSent; +} + + +size_t +BDatagramSocket::ReceiveFrom(void* buffer, size_t bufferSize, + BNetworkAddress& from) +{ + socklen_t fromLength = sizeof(sockaddr_storage); + ssize_t bytesReceived = recvfrom(fSocket, buffer, bufferSize, 0, + from, &fromLength); + if (bytesReceived < 0) + return errno; + + return bytesReceived; +} + + +// #pragma mark - BDataIO implementation + + +ssize_t +BDatagramSocket::Read(void* buffer, size_t size) +{ + ssize_t bytesReceived = recv(Socket(), buffer, size, 0); + if (bytesReceived < 0) { + TRACE("%p: BSocket::Read() error: %s\n", this, strerror(errno)); + return errno; + } + + return bytesReceived; +} + + +ssize_t +BDatagramSocket::Write(const void* buffer, size_t size) +{ + ssize_t bytesSent; + + if (!fIsConnected) + bytesSent = sendto(Socket(), buffer, size, 0, fPeer, fPeer.Length()); + else + bytesSent = send(Socket(), buffer, size, 0); + + if (bytesSent < 0) { + TRACE("%p: BDatagramSocket::Write() error: %s\n", this, + strerror(errno)); + return errno; + } + + return bytesSent; +} diff --git a/src/kits/network/libnetapi/SSL.cpp b/src/kits/network/libnetapi/SSL.cpp new file mode 100644 index 0000000000..f60c673d35 --- /dev/null +++ b/src/kits/network/libnetapi/SSL.cpp @@ -0,0 +1,31 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + +#include +#include + + +namespace BPrivate { + + +class SSL { +public: + SSL() + { + SSL_library_init(); + + int64 seed = find_thread(NULL) ^ system_time(); + RAND_seed(&seed, sizeof(seed)); + } +}; + + +static SSL sSSL; + + +} // namespace BPrivate diff --git a/src/kits/network/libnetapi/SecureSocket.cpp b/src/kits/network/libnetapi/SecureSocket.cpp new file mode 100644 index 0000000000..6965874862 --- /dev/null +++ b/src/kits/network/libnetapi/SecureSocket.cpp @@ -0,0 +1,233 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2010, Clemens Zeidler + * Distributed under the terms of the MIT License. + */ + + +#include + +#ifdef OPENSSL_ENABLED +# include +#endif + + +//#define TRACE_SOCKET +#ifdef TRACE_SOCKET +# define TRACE(x...) printf(x) +#else +# define TRACE(x...) ; +#endif + + +#ifdef OPENSSL_ENABLED + + +class BSecureSocket::Private { +public: + SSL_CTX* fCTX; + SSL* fSSL; + BIO* fBIO; +}; + + +BSecureSocket::BSecureSocket() + : + fPrivate(NULL) +{ +} + + +BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout) + : + fPrivate(NULL) +{ + Connect(peer, timeout); +} + + +BSecureSocket::BSecureSocket(const BSecureSocket& other) + : + BSocket(other) +{ + // TODO: this won't work this way! + fPrivate = (BSecureSocket::Private*)malloc(sizeof(BSecureSocket::Private)); + if (fPrivate != NULL) + memcpy(fPrivate, other.fPrivate, sizeof(BSecureSocket::Private)); + else + fInitStatus = B_NO_MEMORY; +} + + +BSecureSocket::~BSecureSocket() +{ + free(fPrivate); +} + + +status_t +BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) +{ + if (fPrivate == NULL) { + fPrivate = (BSecureSocket::Private*)calloc(1, + sizeof(BSecureSocket::Private)); + if (fPrivate == NULL) + return B_NO_MEMORY; + } + + status_t status = BSocket::Connect(peer, timeout); + if (status != B_OK) + return status; + + fPrivate->fCTX = SSL_CTX_new(SSLv23_method()); + fPrivate->fSSL = SSL_new(fPrivate->fCTX); + fPrivate->fBIO = BIO_new_socket(fSocket, BIO_NOCLOSE); + SSL_set_bio(fPrivate->fSSL, fPrivate->fBIO, fPrivate->fBIO); + + if (SSL_connect(fPrivate->fSSL) <= 0) { + TRACE("SSLConnection can't connect\n"); + BSocket::Disconnect(); + // TODO: translate ssl to Haiku error + return B_ERROR; + } + + return B_OK; +} + + +void +BSecureSocket::Disconnect() +{ + if (IsConnected()) { + if (fPrivate->fSSL != NULL) { + SSL_shutdown(fPrivate->fSSL); + fPrivate->fSSL = NULL; + } + if (fPrivate->fCTX != NULL) { + SSL_CTX_free(fPrivate->fCTX); + fPrivate->fCTX = NULL; + } + if (fPrivate->fBIO != NULL) { + BIO_free(fPrivate->fBIO); + fPrivate->fBIO = NULL; + } + } + return BSocket::Disconnect(); +} + + +status_t +BSecureSocket::WaitForReadable(bigtime_t timeout) const +{ + if (fInitStatus != B_OK) + return fInitStatus; + if (!IsConnected()) + return B_ERROR; + + if (SSL_pending(fPrivate->fSSL) > 0) + return B_OK; + + return BSocket::WaitForReadable(timeout); +} + + +// #pragma mark - BDataIO implementation + + +ssize_t +BSecureSocket::Read(void* buffer, size_t size) +{ + if (!IsConnected()) + return B_ERROR; + + int bytesRead = SSL_read(fPrivate->fSSL, buffer, size); + if (bytesRead > 0) + return bytesRead; + + // TODO: translate SSL error codes! + return B_ERROR; +} + + +ssize_t +BSecureSocket::Write(const void* buffer, size_t size) +{ + if (!IsConnected()) + return B_ERROR; + + int bytesWritten = SSL_write(fPrivate->fSSL, buffer, size); + if (bytesWritten > 0) + return bytesWritten; + + // TODO: translate SSL error codes! + return B_ERROR; +} + + +#else // OPENSSL_ENABLED + + +// #pragma mark - No-SSL stubs + + +BSecureSocket::BSecureSocket() +{ +} + + +BSecureSocket::BSecureSocket(const BNetworkAddress& peer, bigtime_t timeout) +{ + fInitStatus = B_UNSUPPORTED; +} + + +BSecureSocket::BSecureSocket(const BSecureSocket& other) + : + BSocket(other) +{ +} + + +BSecureSocket::~BSecureSocket() +{ +} + + +status_t +BSecureSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) +{ + return fInitStatus = B_UNSUPPORTED; +} + + +void +BSecureSocket::Disconnect() +{ +} + + +status_t +BSecureSocket::WaitForReadable(bigtime_t timeout) const +{ + return B_UNSUPPORTED; +} + + +// #pragma mark - BDataIO implementation + + +ssize_t +BSecureSocket::Read(void* buffer, size_t size) +{ + return B_UNSUPPORTED; +} + + +ssize_t +BSecureSocket::Write(const void* buffer, size_t size) +{ + return B_UNSUPPORTED; +} + + +#endif // !OPENSSL_ENABLED diff --git a/src/kits/network/libnetapi/Socket.cpp b/src/kits/network/libnetapi/Socket.cpp new file mode 100644 index 0000000000..987549a7be --- /dev/null +++ b/src/kits/network/libnetapi/Socket.cpp @@ -0,0 +1,100 @@ +/* + * Copyright 2011, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include + + +//#define TRACE_SOCKET +#ifdef TRACE_SOCKET +# define TRACE(x...) printf(x) +#else +# define TRACE(x...) ; +#endif + + +BSocket::BSocket() +{ +} + + +BSocket::BSocket(const BNetworkAddress& peer, bigtime_t timeout) +{ + Connect(peer, timeout); +} + + +BSocket::BSocket(const BSocket& other) + : + BAbstractSocket(other) +{ +} + + +BSocket::~BSocket() +{ +} + + +status_t +BSocket::Bind(const BNetworkAddress& local) +{ + return BAbstractSocket::Bind(local, SOCK_STREAM); +} + + +status_t +BSocket::Connect(const BNetworkAddress& peer, bigtime_t timeout) +{ + return BAbstractSocket::Connect(peer, SOCK_STREAM, timeout); +} + + +// #pragma mark - BDataIO implementation + + +ssize_t +BSocket::Read(void* buffer, size_t size) +{ + ssize_t bytesReceived = recv(Socket(), buffer, size, 0); + if (bytesReceived < 0) { + TRACE("%p: BSocket::Read() error: %s\n", this, strerror(errno)); + return errno; + } + + return bytesReceived; +} + + +ssize_t +BSocket::Write(const void* buffer, size_t size) +{ + ssize_t bytesSent = send(Socket(), buffer, size, 0); + if (bytesSent < 0) { + TRACE("%p: BSocket::Write() error: %s\n", this, strerror(errno)); + return errno; + } + + return bytesSent; +} + + +// #pragma mark - private + + +void +BSocket::_SetTo(int fd, const BNetworkAddress& local, + const BNetworkAddress& peer) +{ + Disconnect(); + + fInitStatus = B_OK; + fSocket = fd; + fLocal = local; + fPeer = peer; + + TRACE("%p: accepted from %s to %s\n", this, local.ToString().c_str(), + peer.ToString().c_str()); +}