Overhauled BNetEndpoint implementation (and BNetAddress, too):
* added NetEndpointTest that exposed a couple of bugs * fixed several bugs in the implementation of BNetEndpoint, some of which kept NetPenguin from working * fixed a couple of constness issues in BNetEndpoint and BNetAddress git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26405 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -27,22 +27,28 @@ class BNetAddress : public BArchivable {
|
||||
BNetAddress(in_addr addr, int port = 0);
|
||||
BNetAddress(uint32 addr, int port = 0);
|
||||
BNetAddress(const BNetAddress& other);
|
||||
BNetAddress(const char* hostname, const char* protocol, const char* service);
|
||||
BNetAddress(const char* hostname, const char* protocol,
|
||||
const char* service);
|
||||
|
||||
BNetAddress& operator=(const BNetAddress&);
|
||||
|
||||
status_t InitCheck();
|
||||
status_t InitCheck() const;
|
||||
|
||||
status_t SetTo(const char* hostname, const char* protocol, const char* service);
|
||||
status_t SetTo(const char* hostname, const char* protocol,
|
||||
const char* service);
|
||||
status_t SetTo(const char* hostname = NULL, unsigned short port = 0);
|
||||
status_t SetTo(const struct sockaddr_in& addr);
|
||||
status_t SetTo(in_addr addr, int port = 0);
|
||||
status_t SetTo(uint32 addr = INADDR_ANY, int port = 0);
|
||||
|
||||
status_t GetAddr(char* hostname = NULL, unsigned short* port = NULL) const;
|
||||
status_t GetAddr(char* hostname = NULL,
|
||||
unsigned short* port = NULL) const;
|
||||
status_t GetAddr(struct sockaddr_in& addr) const;
|
||||
status_t GetAddr(in_addr& addr, unsigned short* port = NULL) const;
|
||||
|
||||
// TODO: drop this compatibility cruft method after R1
|
||||
status_t InitCheck();
|
||||
|
||||
private:
|
||||
virtual void _ReservedBNetAddressFBCCruft1();
|
||||
virtual void _ReservedBNetAddressFBCCruft2();
|
||||
|
||||
@@ -25,18 +25,19 @@ class BNetEndpoint : public BArchivable {
|
||||
|
||||
BNetEndpoint& operator=(const BNetEndpoint& other);
|
||||
|
||||
status_t InitCheck();
|
||||
status_t InitCheck() const;
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* archive);
|
||||
|
||||
status_t SetProtocol(int protocol);
|
||||
int SetOption(int32 option, int32 level, const void* data, unsigned int dataSize);
|
||||
int SetOption(int32 option, int32 level, const void* data,
|
||||
unsigned int dataSize);
|
||||
int SetNonBlocking(bool on = true);
|
||||
int SetReuseAddr(bool on = true);
|
||||
|
||||
const BNetAddress& LocalAddr();
|
||||
const BNetAddress& RemoteAddr();
|
||||
const BNetAddress& LocalAddr() const;
|
||||
const BNetAddress& RemoteAddr() const;
|
||||
|
||||
int Socket() const;
|
||||
|
||||
@@ -71,7 +72,14 @@ class BNetEndpoint : public BArchivable {
|
||||
|
||||
virtual bool IsDataPending(bigtime_t timeout = 0);
|
||||
|
||||
// TODO: drop these compatibility cruft methods after R1
|
||||
status_t InitCheck();
|
||||
const BNetAddress& LocalAddr();
|
||||
const BNetAddress& RemoteAddr();
|
||||
|
||||
private:
|
||||
status_t _SetupSocket();
|
||||
|
||||
virtual void _ReservedBNetEndpointFBCCruft1();
|
||||
virtual void _ReservedBNetEndpointFBCCruft2();
|
||||
virtual void _ReservedBNetEndpointFBCCruft3();
|
||||
@@ -79,14 +87,17 @@ class BNetEndpoint : public BArchivable {
|
||||
virtual void _ReservedBNetEndpointFBCCruft5();
|
||||
virtual void _ReservedBNetEndpointFBCCruft6();
|
||||
|
||||
status_t fInit;
|
||||
status_t fStatus;
|
||||
int fFamily;
|
||||
int fType;
|
||||
int fProtocol;
|
||||
int fSocket;
|
||||
bigtime_t fTimeout;
|
||||
int fLastError;
|
||||
BNetAddress fAddr;
|
||||
BNetAddress fPeer;
|
||||
|
||||
int32 _reserved[18];
|
||||
int32 _reserved[16];
|
||||
};
|
||||
|
||||
|
||||
#endif // H_NETENDPOINT
|
||||
|
||||
@@ -241,12 +241,18 @@ status_t BNetAddress::GetAddr( in_addr& addr, unsigned short* port ) const
|
||||
* Returns:
|
||||
* B_OK if this instance is initialized, B_ERROR if not.
|
||||
*/
|
||||
status_t BNetAddress::InitCheck( void )
|
||||
status_t BNetAddress::InitCheck( void ) const
|
||||
{
|
||||
return ( fInit == B_OK ) ? B_OK : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t BNetAddress::InitCheck()
|
||||
{
|
||||
return const_cast<const BNetAddress*>(this)->InitCheck();
|
||||
}
|
||||
|
||||
|
||||
/* Archive
|
||||
*=--------------------------------------------------------------------------=*
|
||||
* Purpose:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -20,71 +20,87 @@
|
||||
|
||||
BNetEndpoint::BNetEndpoint(int type)
|
||||
:
|
||||
fInit(B_NO_INIT),
|
||||
fStatus(B_NO_INIT),
|
||||
fFamily(AF_INET),
|
||||
fType(type),
|
||||
fProtocol(0),
|
||||
fSocket(-1),
|
||||
fTimeout(B_INFINITE_TIMEOUT),
|
||||
fLastError(0)
|
||||
fTimeout(B_INFINITE_TIMEOUT)
|
||||
{
|
||||
if ((fSocket = socket(AF_INET, type, 0)) < 0)
|
||||
fLastError = errno;
|
||||
else
|
||||
fInit = B_OK;
|
||||
_SetupSocket();
|
||||
}
|
||||
|
||||
|
||||
BNetEndpoint::BNetEndpoint(int family, int type, int protocol)
|
||||
:
|
||||
fInit(B_NO_INIT),
|
||||
fStatus(B_NO_INIT),
|
||||
fFamily(family),
|
||||
fType(type),
|
||||
fProtocol(protocol),
|
||||
fSocket(-1),
|
||||
fTimeout(B_INFINITE_TIMEOUT),
|
||||
fLastError(0)
|
||||
fTimeout(B_INFINITE_TIMEOUT)
|
||||
{
|
||||
if ((fSocket = socket(family, type, protocol)) < 0)
|
||||
fLastError = errno;
|
||||
else
|
||||
fInit = B_OK;
|
||||
_SetupSocket();
|
||||
}
|
||||
|
||||
|
||||
BNetEndpoint::BNetEndpoint(BMessage* archive)
|
||||
:
|
||||
fInit(B_NO_INIT),
|
||||
fStatus(B_NO_INIT),
|
||||
fFamily(AF_INET),
|
||||
fProtocol(0),
|
||||
fSocket(-1),
|
||||
fTimeout(B_INFINITE_TIMEOUT),
|
||||
fLastError(0)
|
||||
fTimeout(B_INFINITE_TIMEOUT)
|
||||
{
|
||||
// TODO
|
||||
if (! archive)
|
||||
if (!archive)
|
||||
return;
|
||||
|
||||
BMessage msg;
|
||||
if (archive->FindMessage("bnendp_peer", &msg) != B_OK)
|
||||
return;
|
||||
fPeer = BNetAddress(&msg);
|
||||
in_addr addr, peer;
|
||||
unsigned short addrPort = 0, peerPort = 0;
|
||||
|
||||
fStatus = archive->FindInt32("_BNetEndpoint_addr_addr",
|
||||
(int32 *)&addr.s_addr);
|
||||
if (fStatus == B_OK) {
|
||||
fStatus = archive->FindInt16("_BNetEndpoint_addr_port",
|
||||
(int16 *)&addrPort);
|
||||
if (fStatus == B_OK)
|
||||
fStatus = fAddr.SetTo(addr, addrPort);
|
||||
}
|
||||
|
||||
fStatus = archive->FindInt32("_BNetEndpoint_peer_addr",
|
||||
(int32 *)&peer.s_addr);
|
||||
if (fStatus == B_OK) {
|
||||
fStatus = archive->FindInt16("_BNetEndpoint_peer_port",
|
||||
(int16 *)&peerPort);
|
||||
if (fStatus == B_OK)
|
||||
fStatus = fPeer.SetTo(peer, peerPort);
|
||||
}
|
||||
|
||||
if (archive->FindMessage("bnendp_addr", &msg) != B_OK)
|
||||
return;
|
||||
fAddr = BNetAddress(&msg);
|
||||
fStatus = archive->FindInt64("_BNetEndpoint_timeout", (int64 *)&fTimeout);
|
||||
if (fStatus == B_OK)
|
||||
fStatus = archive->FindInt32("_BNetEndpoint_proto", (int32 *)&fType);
|
||||
|
||||
fInit = B_OK;
|
||||
if (fStatus == B_OK)
|
||||
_SetupSocket();
|
||||
}
|
||||
|
||||
|
||||
BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint)
|
||||
:
|
||||
fInit(endpoint.fInit),
|
||||
fStatus(endpoint.fStatus),
|
||||
fFamily(endpoint.fFamily),
|
||||
fType(endpoint.fType),
|
||||
fProtocol(endpoint.fProtocol),
|
||||
fSocket(-1),
|
||||
fTimeout(endpoint.fTimeout),
|
||||
fLastError(endpoint.fLastError),
|
||||
fAddr(endpoint.fAddr),
|
||||
fPeer(endpoint.fPeer)
|
||||
|
||||
{
|
||||
fSocket = -1;
|
||||
if (endpoint.fSocket >= 0) {
|
||||
fSocket = dup(endpoint.fSocket);
|
||||
if (fSocket < 0) {
|
||||
fLastError = errno;
|
||||
fInit = B_NO_INIT;
|
||||
}
|
||||
if (fSocket < 0)
|
||||
fStatus = errno;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,21 +108,24 @@ BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint)
|
||||
BNetEndpoint&
|
||||
BNetEndpoint::operator=(const BNetEndpoint& endpoint)
|
||||
{
|
||||
if (this == &endpoint)
|
||||
return *this;
|
||||
|
||||
Close();
|
||||
|
||||
fInit = endpoint.fInit;
|
||||
fStatus = endpoint.fStatus;
|
||||
fFamily = endpoint.fFamily;
|
||||
fType = endpoint.fType;
|
||||
fProtocol = endpoint.fProtocol;
|
||||
fTimeout = endpoint.fTimeout;
|
||||
fLastError = endpoint.fLastError;
|
||||
fAddr = endpoint.fAddr;
|
||||
fPeer = endpoint.fPeer;
|
||||
|
||||
fSocket = -1;
|
||||
if (endpoint.fSocket >= 0) {
|
||||
fSocket = dup(endpoint.fSocket);
|
||||
if (fSocket < 0) {
|
||||
fLastError = errno;
|
||||
fInit = B_NO_INIT;
|
||||
}
|
||||
if (fSocket < 0)
|
||||
fStatus = errno;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@@ -115,7 +134,8 @@ BNetEndpoint::operator=(const BNetEndpoint& endpoint)
|
||||
|
||||
BNetEndpoint::~BNetEndpoint()
|
||||
{
|
||||
Close();
|
||||
if (fSocket >= 0)
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
@@ -125,25 +145,38 @@ BNetEndpoint::~BNetEndpoint()
|
||||
status_t
|
||||
BNetEndpoint::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
// TODO
|
||||
if (into == 0)
|
||||
if (!into)
|
||||
return B_ERROR;
|
||||
|
||||
if (fInit != B_OK)
|
||||
return B_NO_INIT;
|
||||
status_t status = BArchivable::Archive(into, deep);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
BMessage msg;
|
||||
if (fPeer.Archive(&msg) != B_OK)
|
||||
return B_ERROR;
|
||||
if (into->AddMessage("bnendp_peer", &msg) != B_OK)
|
||||
return B_ERROR;
|
||||
in_addr addr, peer;
|
||||
unsigned short addrPort, peerPort;
|
||||
|
||||
if (fAddr.Archive(&msg) != B_OK)
|
||||
return B_ERROR;
|
||||
if (into->AddMessage("bnendp_addr", &msg) != B_OK)
|
||||
return B_ERROR;
|
||||
status = fAddr.GetAddr(addr, &addrPort);
|
||||
if (status == B_OK) {
|
||||
status = into->AddInt32("_BNetEndpoint_addr_addr", addr.s_addr);
|
||||
if (status == B_OK)
|
||||
status = into->AddInt16("_BNetEndpoint_addr_port", addrPort);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
status = fPeer.GetAddr(peer, &peerPort);
|
||||
if (status == B_OK) {
|
||||
status = into->AddInt32("_BNetEndpoint_peer_addr", peer.s_addr);
|
||||
if (status == B_OK)
|
||||
status = into->AddInt16("_BNetEndpoint_peer_port", peerPort);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
status = into->AddInt64("_BNetEndpoint_timeout", fTimeout);
|
||||
if (status == B_OK)
|
||||
status = into->AddInt32("_BNetEndpoint_proto", fType);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,7 +186,7 @@ BNetEndpoint::Instantiate(BMessage* archive)
|
||||
if (!archive)
|
||||
return NULL;
|
||||
|
||||
if (!validate_instantiation(archive, "BNetAddress"))
|
||||
if (!validate_instantiation(archive, "BNetEndpoint"))
|
||||
return NULL;
|
||||
|
||||
BNetEndpoint* endpoint = new BNetEndpoint(archive);
|
||||
@@ -169,9 +202,9 @@ BNetEndpoint::Instantiate(BMessage* archive)
|
||||
|
||||
|
||||
status_t
|
||||
BNetEndpoint::InitCheck()
|
||||
BNetEndpoint::InitCheck() const
|
||||
{
|
||||
return fInit;
|
||||
return fSocket == -1 ? B_NO_INIT : B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,14 +216,14 @@ BNetEndpoint::Socket() const
|
||||
|
||||
|
||||
const BNetAddress&
|
||||
BNetEndpoint::LocalAddr()
|
||||
BNetEndpoint::LocalAddr() const
|
||||
{
|
||||
return fAddr;
|
||||
}
|
||||
|
||||
|
||||
const BNetAddress&
|
||||
BNetEndpoint::RemoteAddr()
|
||||
BNetEndpoint::RemoteAddr() const
|
||||
{
|
||||
return fPeer;
|
||||
}
|
||||
@@ -200,12 +233,8 @@ status_t
|
||||
BNetEndpoint::SetProtocol(int protocol)
|
||||
{
|
||||
Close();
|
||||
if ((fSocket = socket(AF_INET, protocol, 0)) < 0) {
|
||||
fLastError = errno;
|
||||
return fLastError;
|
||||
}
|
||||
fInit = B_OK;
|
||||
return fInit;
|
||||
fType = protocol; // sic (protocol is SOCK_DGRAM or SOCK_STREAM)
|
||||
return _SetupSocket();
|
||||
}
|
||||
|
||||
|
||||
@@ -213,11 +242,11 @@ int
|
||||
BNetEndpoint::SetOption(int32 option, int32 level,
|
||||
const void* data, unsigned int length)
|
||||
{
|
||||
if (fInit < B_OK)
|
||||
return fInit;
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
if (setsockopt(fSocket, level, option, data, length) < 0) {
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -228,9 +257,12 @@ BNetEndpoint::SetOption(int32 option, int32 level,
|
||||
int
|
||||
BNetEndpoint::SetNonBlocking(bool enable)
|
||||
{
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
int flags = fcntl(fSocket, F_GETFL);
|
||||
if (flags < 0) {
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -240,7 +272,7 @@ BNetEndpoint::SetNonBlocking(bool enable)
|
||||
flags &= ~O_NONBLOCK;
|
||||
|
||||
if (fcntl(fSocket, F_SETFL, flags) < 0) {
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -251,6 +283,9 @@ BNetEndpoint::SetNonBlocking(bool enable)
|
||||
int
|
||||
BNetEndpoint::SetReuseAddr(bool enable)
|
||||
{
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
int onoff = (int) enable;
|
||||
return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff));
|
||||
}
|
||||
@@ -266,14 +301,14 @@ BNetEndpoint::SetTimeout(bigtime_t timeout)
|
||||
int
|
||||
BNetEndpoint::Error() const
|
||||
{
|
||||
return fLastError;
|
||||
return (int)fStatus;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
BNetEndpoint::ErrorStr() const
|
||||
{
|
||||
return strerror(fLastError);
|
||||
return strerror(fStatus);
|
||||
}
|
||||
|
||||
|
||||
@@ -287,15 +322,15 @@ BNetEndpoint::Close()
|
||||
close(fSocket);
|
||||
|
||||
fSocket = -1;
|
||||
fInit = B_NO_INIT;
|
||||
fStatus = B_NO_INIT;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BNetEndpoint::Bind(const BNetAddress& address)
|
||||
{
|
||||
if (fInit < B_OK)
|
||||
return fInit;
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
struct sockaddr_in addr;
|
||||
status_t status = address.GetAddr(addr);
|
||||
@@ -303,28 +338,18 @@ BNetEndpoint::Bind(const BNetAddress& address)
|
||||
return status;
|
||||
|
||||
if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
Close();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
socklen_t addrSize = sizeof(addr);
|
||||
if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) {
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
Close();
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
if (addr.sin_addr.s_addr == 0) {
|
||||
// TODO: does this still apply?
|
||||
// Grrr, buggy getsockname!
|
||||
char hostname[MAXHOSTNAMELEN];
|
||||
gethostname(hostname, sizeof(hostname));
|
||||
struct hostent *host = gethostbyname(hostname);
|
||||
if (host != NULL)
|
||||
memcpy(&addr.sin_addr.s_addr, host->h_addr, sizeof(addr.sin_addr.s_addr));
|
||||
}
|
||||
|
||||
fAddr.SetTo(addr);
|
||||
return B_OK;
|
||||
}
|
||||
@@ -341,8 +366,8 @@ BNetEndpoint::Bind(int port)
|
||||
status_t
|
||||
BNetEndpoint::Connect(const BNetAddress& address)
|
||||
{
|
||||
if (fInit < B_OK)
|
||||
return fInit;
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
sockaddr_in addr;
|
||||
if (address.GetAddr(addr) != B_OK)
|
||||
@@ -350,17 +375,16 @@ BNetEndpoint::Connect(const BNetAddress& address)
|
||||
|
||||
if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) {
|
||||
Close();
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
socklen_t addrSize = sizeof(addr);
|
||||
if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) {
|
||||
Close();
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
fPeer.SetTo(addr);
|
||||
return B_OK;
|
||||
}
|
||||
@@ -377,12 +401,12 @@ BNetEndpoint::Connect(const char *hostname, int port)
|
||||
status_t
|
||||
BNetEndpoint::Listen(int backlog)
|
||||
{
|
||||
if (fInit < B_OK)
|
||||
return fInit;
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
if (listen(fSocket, backlog) < 0) {
|
||||
Close();
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return B_ERROR;
|
||||
}
|
||||
return B_OK;
|
||||
@@ -401,14 +425,14 @@ BNetEndpoint::Accept(int32 timeout)
|
||||
int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize);
|
||||
if (socket < 0) {
|
||||
Close();
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this);
|
||||
if (endpoint == NULL) {
|
||||
close(socket);
|
||||
fLastError = B_NO_MEMORY;
|
||||
fStatus = B_NO_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -417,7 +441,7 @@ BNetEndpoint::Accept(int32 timeout)
|
||||
|
||||
if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) {
|
||||
delete endpoint;
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -444,7 +468,7 @@ BNetEndpoint::IsDataPending(bigtime_t timeout)
|
||||
}
|
||||
|
||||
if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) {
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -455,12 +479,15 @@ BNetEndpoint::IsDataPending(bigtime_t timeout)
|
||||
int32
|
||||
BNetEndpoint::Receive(void* buffer, size_t length, int flags)
|
||||
{
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
|
||||
return 0;
|
||||
|
||||
ssize_t bytesReceived = recv(fSocket, buffer, length, flags);
|
||||
if (bytesReceived < 0)
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
|
||||
return bytesReceived;
|
||||
}
|
||||
@@ -480,6 +507,9 @@ int32
|
||||
BNetEndpoint::ReceiveFrom(void* buffer, size_t length,
|
||||
BNetAddress& address, int flags)
|
||||
{
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
|
||||
return 0;
|
||||
|
||||
@@ -489,7 +519,7 @@ BNetEndpoint::ReceiveFrom(void* buffer, size_t length,
|
||||
length = recvfrom(fSocket, buffer, length, flags,
|
||||
(struct sockaddr *)&addr, &addrSize);
|
||||
if (length < 0)
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
else
|
||||
address.SetTo(addr);
|
||||
|
||||
@@ -511,9 +541,12 @@ BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length,
|
||||
int32
|
||||
BNetEndpoint::Send(const void* buffer, size_t length, int flags)
|
||||
{
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags);
|
||||
if (bytesSent < 0)
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
|
||||
return bytesSent;
|
||||
}
|
||||
@@ -530,6 +563,9 @@ int32
|
||||
BNetEndpoint::SendTo(const void* buffer, size_t length,
|
||||
const BNetAddress& address, int flags)
|
||||
{
|
||||
if (fSocket < 0 && _SetupSocket() != B_OK)
|
||||
return fStatus;
|
||||
|
||||
struct sockaddr_in addr;
|
||||
if (address.GetAddr(addr) != B_OK)
|
||||
return B_ERROR;
|
||||
@@ -537,7 +573,7 @@ BNetEndpoint::SendTo(const void* buffer, size_t length,
|
||||
ssize_t bytesSent = sendto(fSocket, buffer, length, flags,
|
||||
(struct sockaddr *) &addr, sizeof(addr));
|
||||
if (bytesSent < 0)
|
||||
fLastError = errno;
|
||||
fStatus = errno;
|
||||
|
||||
return bytesSent;
|
||||
}
|
||||
@@ -554,6 +590,40 @@ BNetEndpoint::SendTo(BNetBuffer& buffer,
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
BNetEndpoint::_SetupSocket()
|
||||
{
|
||||
if ((fSocket = socket(fFamily, fType, fProtocol)) < 0)
|
||||
fStatus = errno;
|
||||
else
|
||||
fStatus = B_OK;
|
||||
return fStatus;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
status_t BNetEndpoint::InitCheck()
|
||||
{
|
||||
return const_cast<const BNetEndpoint*>(this)->InitCheck();
|
||||
}
|
||||
|
||||
|
||||
const BNetAddress& BNetEndpoint::LocalAddr()
|
||||
{
|
||||
return const_cast<const BNetEndpoint*>(this)->LocalAddr();
|
||||
}
|
||||
|
||||
|
||||
const BNetAddress& BNetEndpoint::RemoteAddr()
|
||||
{
|
||||
return const_cast<const BNetEndpoint*>(this)->RemoteAddr();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
// These are virtuals, implemented for binary compatibility purpose
|
||||
void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {}
|
||||
void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2002-2008, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ SimpleTest tcp_connection_test : tcp_connection_test.cpp
|
||||
SimpleTest NetAddressTest : NetAddressTest.cpp
|
||||
: $(TARGET_NETWORK_LIBS) $(HAIKU_NETAPI_LIB) ;
|
||||
|
||||
SimpleTest NetEndpointTest : NetEndpointTest.cpp
|
||||
: $(TARGET_NETWORK_LIBS) $(HAIKU_NETAPI_LIB) be ;
|
||||
|
||||
SubInclude HAIKU_TOP src tests kits net DialUpPreflet ;
|
||||
SubInclude HAIKU_TOP src tests kits net multicast ;
|
||||
SubInclude HAIKU_TOP src tests kits net netperf ;
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright 2008, Oliver Tappe, [email protected].
|
||||
* Distributed under the terms of the MIT license.
|
||||
*/
|
||||
|
||||
|
||||
#include <Message.h>
|
||||
#include <NetEndpoint.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
static BNetAddress serverAddr("127.0.0.1", 1234);
|
||||
static BNetAddress clientAddr("127.0.0.1", 51234);
|
||||
|
||||
|
||||
static int problemCount = 0;
|
||||
|
||||
|
||||
void
|
||||
checkAddrsAreEqual(const BNetAddress& na1, const BNetAddress& na2,
|
||||
const char* fmt)
|
||||
{
|
||||
in_addr addr1, addr2;
|
||||
unsigned short port1, port2;
|
||||
na1.GetAddr(addr1, &port1);
|
||||
na2.GetAddr(addr2, &port2);
|
||||
if (addr1.s_addr == addr2.s_addr && port1 == port2)
|
||||
return;
|
||||
fprintf(stderr, fmt, addr1.s_addr, port1, addr2.s_addr, port2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
checkArchive(const BNetEndpoint ne, int32 protocol,
|
||||
const BNetAddress& localNetAddress, const BNetAddress& remoteNetAddress)
|
||||
{
|
||||
in_addr localAddr, remoteAddr;
|
||||
unsigned short localPort, remotePort;
|
||||
localNetAddress.GetAddr(localAddr, &localPort);
|
||||
remoteNetAddress.GetAddr(remoteAddr, &remotePort);
|
||||
|
||||
BMessage archive(0UL);
|
||||
status_t status = ne.Archive(&archive);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "Archive() failed - %lx:%s\n", status,
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
const char* arcClass;
|
||||
if (archive.FindString("class", &arcClass) != B_OK) {
|
||||
fprintf(stderr, "'class' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if (strcmp(arcClass, "BNetEndpoint") != 0) {
|
||||
fprintf(stderr, "expected 'class' to be 'BNetEndpoint' - is '%s'\n",
|
||||
arcClass);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (ne.LocalAddr().InitCheck() == B_OK) {
|
||||
int32 arcAddr;
|
||||
if (archive.FindInt32("_BNetEndpoint_addr_addr", &arcAddr) != B_OK) {
|
||||
fprintf(stderr, "'_BNetEndpoint_addr_addr' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if ((uint32)localAddr.s_addr != (uint32)arcAddr) {
|
||||
fprintf(stderr,
|
||||
"expected '_BNetEndpoint_addr_addr' to be %x - is %x\n",
|
||||
localAddr.s_addr, (unsigned int)arcAddr);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
int16 arcPort;
|
||||
if (archive.FindInt16("_BNetEndpoint_addr_port", &arcPort) != B_OK) {
|
||||
fprintf(stderr, "'_BNetEndpoint_addr_port' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if ((uint16)localPort != (uint16)arcPort) {
|
||||
fprintf(stderr,
|
||||
"expected '_BNetEndpoint_addr_port' to be %d - is %d\n",
|
||||
localPort, (int)arcPort);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (ne.RemoteAddr().InitCheck() == B_OK) {
|
||||
int32 arcAddr;
|
||||
if (archive.FindInt32("_BNetEndpoint_peer_addr", &arcAddr) != B_OK) {
|
||||
fprintf(stderr, "'_BNetEndpoint_peer_addr' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if ((uint32)remoteAddr.s_addr != (uint32)arcAddr) {
|
||||
fprintf(stderr,
|
||||
"expected '_BNetEndpoint_peer_addr' to be %x - is %x\n",
|
||||
remoteAddr.s_addr, (unsigned int)arcAddr);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
int16 arcPort;
|
||||
if (archive.FindInt16("_BNetEndpoint_peer_port", &arcPort) != B_OK) {
|
||||
fprintf(stderr, "'_BNetEndpoint_peer_port' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if ((uint16)remotePort != (uint16)arcPort) {
|
||||
fprintf(stderr,
|
||||
"expected '_BNetEndpoint_peer_port' to be %u - is %u\n",
|
||||
remotePort, (unsigned short)arcPort);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int64 arcTimeout;
|
||||
if (archive.FindInt64("_BNetEndpoint_timeout", &arcTimeout) != B_OK) {
|
||||
fprintf(stderr, "'_BNetEndpoint_timeout' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if (arcTimeout != B_INFINITE_TIMEOUT) {
|
||||
fprintf(stderr,
|
||||
"expected '_BNetEndpoint_timeout' to be %llu - is %llu\n",
|
||||
B_INFINITE_TIMEOUT, (uint64)arcTimeout);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int32 arcProtocol;
|
||||
if (archive.FindInt32("_BNetEndpoint_proto", &arcProtocol) != B_OK) {
|
||||
fprintf(stderr, "'_BNetEndpoint_proto' not found in archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
if (arcProtocol != protocol) {
|
||||
fprintf(stderr, "expected '_BNetEndpoint_proto' to be %d - is %d\n",
|
||||
(int)protocol, (int)arcProtocol);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
BNetEndpoint* clone
|
||||
= dynamic_cast<BNetEndpoint *>(BNetEndpoint::Instantiate(&archive));
|
||||
if (!clone) {
|
||||
fprintf(stderr, "unable to instantiate endpoint from archive\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
delete clone;
|
||||
}
|
||||
|
||||
void testServer(thread_id clientThread)
|
||||
{
|
||||
char buf[1];
|
||||
|
||||
// check simple UDP "connection"
|
||||
BNetEndpoint server(SOCK_DGRAM);
|
||||
for(int i=0; i < 2; ++i) {
|
||||
status_t status = server.Bind(serverAddr);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "Bind() failed in testServer - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkAddrsAreEqual(server.LocalAddr(), serverAddr,
|
||||
"LocalAddr() doesn't match serverAddr\n");
|
||||
|
||||
if (i == 0)
|
||||
resume_thread(clientThread);
|
||||
|
||||
BNetAddress remoteAddr;
|
||||
status = server.ReceiveFrom(buf, 1, remoteAddr, 0);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "ReceiveFrom() failed in testServer - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (buf[0] != 'U') {
|
||||
fprintf(stderr, "expected to receive %c but got %c\n", 'U', buf[0]);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkAddrsAreEqual(remoteAddr, clientAddr,
|
||||
"remoteAddr(%x:%d) doesn't match clientAddr(%x:%d)\n");
|
||||
|
||||
checkArchive(server, SOCK_DGRAM, serverAddr, clientAddr);
|
||||
|
||||
server.Close();
|
||||
}
|
||||
|
||||
// now switch to TCP and try again
|
||||
server.SetProtocol(SOCK_STREAM);
|
||||
status_t status = server.Bind(serverAddr);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "Bind() failed in testServer - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkAddrsAreEqual(server.LocalAddr(), serverAddr,
|
||||
"LocalAddr() doesn't match serverAddr\n");
|
||||
|
||||
status = server.Listen();
|
||||
BNetEndpoint* acceptedConn = server.Accept();
|
||||
if (acceptedConn == NULL) {
|
||||
fprintf(stderr, "Accept() failed in testServer\n");
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const BNetAddress& remoteAddr = acceptedConn->RemoteAddr();
|
||||
checkAddrsAreEqual(remoteAddr, clientAddr,
|
||||
"remoteAddr(%x:%d) doesn't match clientAddr(%x:%d)\n");
|
||||
|
||||
status = acceptedConn->Receive(buf, 1);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "Receive() failed in testServer - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
delete acceptedConn;
|
||||
|
||||
if (buf[0] != 'T') {
|
||||
fprintf(stderr, "expected to receive %c but got %c\n", 'T', buf[0]);
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkArchive(server, SOCK_STREAM, serverAddr, clientAddr);
|
||||
|
||||
server.Close();
|
||||
}
|
||||
|
||||
|
||||
int32 testClient(void *)
|
||||
{
|
||||
BNetEndpoint client(SOCK_DGRAM);
|
||||
printf("testing udp...\n");
|
||||
for(int i=0; i < 2; ++i) {
|
||||
status_t status = client.Bind(clientAddr);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "Bind() failed in testClient - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkAddrsAreEqual(client.LocalAddr(), clientAddr,
|
||||
"LocalAddr(%x:%d) doesn't match clientAddr(%x:%d)\n");
|
||||
|
||||
status = client.SendTo("U", 1, serverAddr, 0);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "SendTo() failed in testClient - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkArchive(client, SOCK_DGRAM, clientAddr, serverAddr);
|
||||
|
||||
sleep(1);
|
||||
|
||||
client.Close();
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
printf("testing tcp...\n");
|
||||
// now switch to TCP and try again
|
||||
client.SetProtocol(SOCK_STREAM);
|
||||
status_t status = client.Bind(clientAddr);
|
||||
if (status != B_OK) {
|
||||
fprintf(stderr, "Bind() failed in testClient - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkAddrsAreEqual(client.LocalAddr(), clientAddr,
|
||||
"LocalAddr(%x:%d) doesn't match clientAddr(%x:%d)\n");
|
||||
|
||||
status = client.Connect(serverAddr);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "Connect() failed in testClient - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
status = client.Send("T", 1);
|
||||
if (status < B_OK) {
|
||||
fprintf(stderr, "Send() failed in testClient - %s\n",
|
||||
strerror(status));
|
||||
problemCount++;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
checkArchive(client, SOCK_STREAM, clientAddr, serverAddr);
|
||||
|
||||
client.Close();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(int argc, const char* const* argv)
|
||||
{
|
||||
BNetEndpoint dummy(SOCK_DGRAM);
|
||||
if (sizeof(dummy) != 208) {
|
||||
fprintf(stderr, "expected sizeof(netEndpoint) to be 208 - is %ld\n",
|
||||
sizeof(dummy));
|
||||
exit(1);
|
||||
}
|
||||
dummy.Close();
|
||||
|
||||
// start thread for client
|
||||
thread_id tid = spawn_thread(testClient, "client", B_NORMAL_PRIORITY, NULL);
|
||||
if (tid < 0) {
|
||||
fprintf(stderr, "spawn_thread() failed: %s\n", strerror(tid));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
testServer(tid);
|
||||
|
||||
status_t clientStatus;
|
||||
wait_for_thread(tid, &clientStatus);
|
||||
|
||||
if (!problemCount)
|
||||
printf("Everything went fine.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user