diff --git a/headers/private/net/SocketMessenger.h b/headers/private/net/SocketMessenger.h new file mode 100644 index 0000000000..488c7e7ee7 --- /dev/null +++ b/headers/private/net/SocketMessenger.h @@ -0,0 +1,56 @@ +/* + * Copyright 2011-2016, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef SOCKET_MESSENGER_H +#define SOCKET_MESSENGER_H + +#include + +class BMessage; +class BMessenger; + + +class BSocketMessenger { +public: + BSocketMessenger(); + BSocketMessenger( + const BNetworkAddress& address, + bigtime_t timeout = B_INFINITE_TIMEOUT); + // adopt an existing already connected socket. + BSocketMessenger(const BSocket& socket); + virtual ~BSocketMessenger(); + + void Unset(); + status_t SetTo(const BNetworkAddress& address, + bigtime_t timeout = B_INFINITE_TIMEOUT); + status_t SetTo(const BSocketMessenger& target, + bigtime_t timeout = B_INFINITE_TIMEOUT); + + status_t InitCheck() const { return fInitStatus; } + + const BNetworkAddress& Address() const { return fSocket.Peer(); } + + virtual status_t SendMessage(const BMessage& message); + virtual status_t SendMessage(const BMessage& message, + BMessage& _reply, + bigtime_t timeout = B_INFINITE_TIMEOUT); + virtual status_t SendMessage(const BMessage& message, + BMessenger& replyTarget, + bigtime_t timeout = B_INFINITE_TIMEOUT); + + // wait for unsolicited message on socket + virtual status_t ReceiveMessage(BMessage& _message, + bigtime_t timeout = B_INFINITE_TIMEOUT); + +private: + status_t _SendMessage(const BMessage& message); + status_t _ReadMessage(BMessage& _message, + bigtime_t timeout); + +private: + BSocket fSocket; + status_t fInitStatus; +}; + +#endif // SOCKET_MESSENGER_H diff --git a/src/kits/network/libnetapi/Jamfile b/src/kits/network/libnetapi/Jamfile index aef88691d9..85f508b8d6 100644 --- a/src/kits/network/libnetapi/Jamfile +++ b/src/kits/network/libnetapi/Jamfile @@ -64,9 +64,10 @@ for architectureObject in [ MultiArchSubDirSetup ] { AbstractSocket.cpp DatagramSocket.cpp - Socket.cpp - SecureSocket.cpp ProxySecureSocket.cpp + SecureSocket.cpp + Socket.cpp + SocketMessenger.cpp # TODO: another add-on for file:// (a much simpler one) FileRequest.cpp diff --git a/src/kits/network/libnetapi/SocketMessenger.cpp b/src/kits/network/libnetapi/SocketMessenger.cpp new file mode 100644 index 0000000000..2b6556d60a --- /dev/null +++ b/src/kits/network/libnetapi/SocketMessenger.cpp @@ -0,0 +1,159 @@ +/* + * Copyright 2009-2011, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2016, Rene Gollent, rene@gollent.com. + */ + + +#include + +#include +#include + +#include + + +BSocketMessenger::BSocketMessenger() + : + fSocket(), + fInitStatus(B_NO_INIT) +{ +} + + +BSocketMessenger::BSocketMessenger(const BNetworkAddress& address, + bigtime_t timeout) +{ + SetTo(address, timeout); +} + + +BSocketMessenger::BSocketMessenger(const BSocket& socket) + : + fSocket(socket) +{ + fInitStatus = socket.InitCheck(); +} + + +BSocketMessenger::~BSocketMessenger() +{ + Unset(); +} + + +void +BSocketMessenger::Unset() +{ + fSocket.Disconnect(); + fInitStatus = B_NO_INIT; +} + + +status_t +BSocketMessenger::SetTo(const BNetworkAddress& address, bigtime_t timeout) +{ + return fInitStatus = fSocket.Connect(address, timeout); +} + + +status_t +BSocketMessenger::SetTo(const BSocketMessenger& target, bigtime_t timeout) +{ + return SetTo(target.Address(), timeout); +} + + +status_t +BSocketMessenger::SendMessage(const BMessage& message) +{ + return _SendMessage(message); +} + + +status_t +BSocketMessenger::SendMessage(const BMessage& message, BMessage& _reply, + bigtime_t timeout) +{ + status_t error = _SendMessage(message); + if (error != B_OK) + return error; + + return _ReadMessage(_reply, timeout); +} + + +status_t +BSocketMessenger::SendMessage(const BMessage& message, + BMessenger& replyTarget, bigtime_t timeout) +{ + BMessage reply; + status_t error = SendMessage(message, reply, timeout); + if (error != B_OK) + return error; + + return replyTarget.SendMessage(&reply); +} + + +status_t +BSocketMessenger::ReceiveMessage(BMessage& _message, bigtime_t timeout) +{ + return _ReadMessage(_message, timeout); +} + + +status_t +BSocketMessenger::_SendMessage(const BMessage& message) +{ + ssize_t flatSize = message.FlattenedSize(); + flatSize += sizeof(ssize_t); + + char* buffer = new(std::nothrow) char[flatSize]; + if (buffer == NULL) + return B_NO_MEMORY; + + ArrayDeleter bufferDeleter(buffer); + *(ssize_t*)buffer = flatSize; + char* messageBuffer = buffer + sizeof(ssize_t); + status_t error = message.Flatten(messageBuffer, flatSize); + if (error != B_OK) + return error; + + ssize_t size = fSocket.Write(buffer, flatSize); + if (size < 0) + return size; + + return B_OK; +} + + +status_t +BSocketMessenger::_ReadMessage(BMessage& _message, bigtime_t timeout) +{ + status_t error = fSocket.WaitForReadable(timeout); + if (error != B_OK) + return error; + + ssize_t size = 0; + ssize_t readSize = fSocket.Read(&size, sizeof(ssize_t)); + if (readSize < 0) + return readSize; + else if (readSize != sizeof(ssize_t)) + return B_BAD_VALUE; + + if (size <= 0) + return B_MISMATCHED_VALUES; + + char* buffer = new(std::nothrow) char[size]; + if (buffer == NULL) + return B_NO_MEMORY; + + ArrayDeleter bufferDeleter(buffer); + readSize = fSocket.Read(buffer, size); + if (readSize < 0) + return readSize; + else if (readSize != size) + return B_MISMATCHED_VALUES; + + return _message.Unflatten(buffer); +}