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:
Oliver Tappe
2008-07-13 19:58:35 +00:00
parent 0af6c60b15
commit 49a22456dd
7 changed files with 566 additions and 118 deletions
+10 -4
View File
@@ -27,22 +27,28 @@ class BNetAddress : public BArchivable {
BNetAddress(in_addr addr, int port = 0); BNetAddress(in_addr addr, int port = 0);
BNetAddress(uint32 addr, int port = 0); BNetAddress(uint32 addr, int port = 0);
BNetAddress(const BNetAddress& other); 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&); 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 char* hostname = NULL, unsigned short port = 0);
status_t SetTo(const struct sockaddr_in& addr); status_t SetTo(const struct sockaddr_in& addr);
status_t SetTo(in_addr addr, int port = 0); status_t SetTo(in_addr addr, int port = 0);
status_t SetTo(uint32 addr = INADDR_ANY, 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(struct sockaddr_in& addr) const;
status_t GetAddr(in_addr& addr, unsigned short* port = NULL) const; status_t GetAddr(in_addr& addr, unsigned short* port = NULL) const;
// TODO: drop this compatibility cruft method after R1
status_t InitCheck();
private: private:
virtual void _ReservedBNetAddressFBCCruft1(); virtual void _ReservedBNetAddressFBCCruft1();
virtual void _ReservedBNetAddressFBCCruft2(); virtual void _ReservedBNetAddressFBCCruft2();
+18 -7
View File
@@ -25,18 +25,19 @@ class BNetEndpoint : public BArchivable {
BNetEndpoint& operator=(const BNetEndpoint& other); BNetEndpoint& operator=(const BNetEndpoint& other);
status_t InitCheck(); status_t InitCheck() const;
virtual status_t Archive(BMessage* into, bool deep = true) const; virtual status_t Archive(BMessage* into, bool deep = true) const;
static BArchivable* Instantiate(BMessage* archive); static BArchivable* Instantiate(BMessage* archive);
status_t SetProtocol(int protocol); 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 SetNonBlocking(bool on = true);
int SetReuseAddr(bool on = true); int SetReuseAddr(bool on = true);
const BNetAddress& LocalAddr(); const BNetAddress& LocalAddr() const;
const BNetAddress& RemoteAddr(); const BNetAddress& RemoteAddr() const;
int Socket() const; int Socket() const;
@@ -71,7 +72,14 @@ class BNetEndpoint : public BArchivable {
virtual bool IsDataPending(bigtime_t timeout = 0); 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: private:
status_t _SetupSocket();
virtual void _ReservedBNetEndpointFBCCruft1(); virtual void _ReservedBNetEndpointFBCCruft1();
virtual void _ReservedBNetEndpointFBCCruft2(); virtual void _ReservedBNetEndpointFBCCruft2();
virtual void _ReservedBNetEndpointFBCCruft3(); virtual void _ReservedBNetEndpointFBCCruft3();
@@ -79,14 +87,17 @@ class BNetEndpoint : public BArchivable {
virtual void _ReservedBNetEndpointFBCCruft5(); virtual void _ReservedBNetEndpointFBCCruft5();
virtual void _ReservedBNetEndpointFBCCruft6(); virtual void _ReservedBNetEndpointFBCCruft6();
status_t fInit; status_t fStatus;
int fFamily;
int fType;
int fProtocol;
int fSocket; int fSocket;
bigtime_t fTimeout; bigtime_t fTimeout;
int fLastError;
BNetAddress fAddr; BNetAddress fAddr;
BNetAddress fPeer; BNetAddress fPeer;
int32 _reserved[18]; int32 _reserved[16];
}; };
#endif // H_NETENDPOINT #endif // H_NETENDPOINT
+7 -1
View File
@@ -241,12 +241,18 @@ status_t BNetAddress::GetAddr( in_addr& addr, unsigned short* port ) const
* Returns: * Returns:
* B_OK if this instance is initialized, B_ERROR if not. * 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; return ( fInit == B_OK ) ? B_OK : B_ERROR;
} }
status_t BNetAddress::InitCheck()
{
return const_cast<const BNetAddress*>(this)->InitCheck();
}
/* Archive /* Archive
*=--------------------------------------------------------------------------=* *=--------------------------------------------------------------------------=*
* Purpose: * Purpose:
+175 -105
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
@@ -20,71 +20,87 @@
BNetEndpoint::BNetEndpoint(int type) BNetEndpoint::BNetEndpoint(int type)
: :
fInit(B_NO_INIT), fStatus(B_NO_INIT),
fFamily(AF_INET),
fType(type),
fProtocol(0),
fSocket(-1), fSocket(-1),
fTimeout(B_INFINITE_TIMEOUT), fTimeout(B_INFINITE_TIMEOUT)
fLastError(0)
{ {
if ((fSocket = socket(AF_INET, type, 0)) < 0) _SetupSocket();
fLastError = errno;
else
fInit = B_OK;
} }
BNetEndpoint::BNetEndpoint(int family, int type, int protocol) BNetEndpoint::BNetEndpoint(int family, int type, int protocol)
: :
fInit(B_NO_INIT), fStatus(B_NO_INIT),
fFamily(family),
fType(type),
fProtocol(protocol),
fSocket(-1), fSocket(-1),
fTimeout(B_INFINITE_TIMEOUT), fTimeout(B_INFINITE_TIMEOUT)
fLastError(0)
{ {
if ((fSocket = socket(family, type, protocol)) < 0) _SetupSocket();
fLastError = errno;
else
fInit = B_OK;
} }
BNetEndpoint::BNetEndpoint(BMessage* archive) BNetEndpoint::BNetEndpoint(BMessage* archive)
: :
fInit(B_NO_INIT), fStatus(B_NO_INIT),
fFamily(AF_INET),
fProtocol(0),
fSocket(-1), fSocket(-1),
fTimeout(B_INFINITE_TIMEOUT), fTimeout(B_INFINITE_TIMEOUT)
fLastError(0)
{ {
// TODO if (!archive)
if (! archive)
return; return;
BMessage msg; in_addr addr, peer;
if (archive->FindMessage("bnendp_peer", &msg) != B_OK) unsigned short addrPort = 0, peerPort = 0;
return;
fPeer = BNetAddress(&msg); 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) fStatus = archive->FindInt64("_BNetEndpoint_timeout", (int64 *)&fTimeout);
return; if (fStatus == B_OK)
fAddr = BNetAddress(&msg); fStatus = archive->FindInt32("_BNetEndpoint_proto", (int32 *)&fType);
fInit = B_OK; if (fStatus == B_OK)
_SetupSocket();
} }
BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint) 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), fTimeout(endpoint.fTimeout),
fLastError(endpoint.fLastError),
fAddr(endpoint.fAddr), fAddr(endpoint.fAddr),
fPeer(endpoint.fPeer) fPeer(endpoint.fPeer)
{ {
fSocket = -1;
if (endpoint.fSocket >= 0) { if (endpoint.fSocket >= 0) {
fSocket = dup(endpoint.fSocket); fSocket = dup(endpoint.fSocket);
if (fSocket < 0) { if (fSocket < 0)
fLastError = errno; fStatus = errno;
fInit = B_NO_INIT;
}
} }
} }
@@ -92,21 +108,24 @@ BNetEndpoint::BNetEndpoint(const BNetEndpoint& endpoint)
BNetEndpoint& BNetEndpoint&
BNetEndpoint::operator=(const BNetEndpoint& endpoint) BNetEndpoint::operator=(const BNetEndpoint& endpoint)
{ {
if (this == &endpoint)
return *this;
Close(); Close();
fInit = endpoint.fInit; fStatus = endpoint.fStatus;
fFamily = endpoint.fFamily;
fType = endpoint.fType;
fProtocol = endpoint.fProtocol;
fTimeout = endpoint.fTimeout; fTimeout = endpoint.fTimeout;
fLastError = endpoint.fLastError;
fAddr = endpoint.fAddr; fAddr = endpoint.fAddr;
fPeer = endpoint.fPeer; fPeer = endpoint.fPeer;
fSocket = -1; fSocket = -1;
if (endpoint.fSocket >= 0) { if (endpoint.fSocket >= 0) {
fSocket = dup(endpoint.fSocket); fSocket = dup(endpoint.fSocket);
if (fSocket < 0) { if (fSocket < 0)
fLastError = errno; fStatus = errno;
fInit = B_NO_INIT;
}
} }
return *this; return *this;
@@ -115,7 +134,8 @@ BNetEndpoint::operator=(const BNetEndpoint& endpoint)
BNetEndpoint::~BNetEndpoint() BNetEndpoint::~BNetEndpoint()
{ {
Close(); if (fSocket >= 0)
Close();
} }
@@ -125,25 +145,38 @@ BNetEndpoint::~BNetEndpoint()
status_t status_t
BNetEndpoint::Archive(BMessage* into, bool deep) const BNetEndpoint::Archive(BMessage* into, bool deep) const
{ {
// TODO if (!into)
if (into == 0)
return B_ERROR; return B_ERROR;
if (fInit != B_OK) status_t status = BArchivable::Archive(into, deep);
return B_NO_INIT; if (status != B_OK)
return status;
BMessage msg; in_addr addr, peer;
if (fPeer.Archive(&msg) != B_OK) unsigned short addrPort, peerPort;
return B_ERROR;
if (into->AddMessage("bnendp_peer", &msg) != B_OK)
return B_ERROR;
if (fAddr.Archive(&msg) != B_OK) status = fAddr.GetAddr(addr, &addrPort);
return B_ERROR; if (status == B_OK) {
if (into->AddMessage("bnendp_addr", &msg) != B_OK) status = into->AddInt32("_BNetEndpoint_addr_addr", addr.s_addr);
return B_ERROR; 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) if (!archive)
return NULL; return NULL;
if (!validate_instantiation(archive, "BNetAddress")) if (!validate_instantiation(archive, "BNetEndpoint"))
return NULL; return NULL;
BNetEndpoint* endpoint = new BNetEndpoint(archive); BNetEndpoint* endpoint = new BNetEndpoint(archive);
@@ -169,9 +202,9 @@ BNetEndpoint::Instantiate(BMessage* archive)
status_t 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& const BNetAddress&
BNetEndpoint::LocalAddr() BNetEndpoint::LocalAddr() const
{ {
return fAddr; return fAddr;
} }
const BNetAddress& const BNetAddress&
BNetEndpoint::RemoteAddr() BNetEndpoint::RemoteAddr() const
{ {
return fPeer; return fPeer;
} }
@@ -200,12 +233,8 @@ status_t
BNetEndpoint::SetProtocol(int protocol) BNetEndpoint::SetProtocol(int protocol)
{ {
Close(); Close();
if ((fSocket = socket(AF_INET, protocol, 0)) < 0) { fType = protocol; // sic (protocol is SOCK_DGRAM or SOCK_STREAM)
fLastError = errno; return _SetupSocket();
return fLastError;
}
fInit = B_OK;
return fInit;
} }
@@ -213,11 +242,11 @@ int
BNetEndpoint::SetOption(int32 option, int32 level, BNetEndpoint::SetOption(int32 option, int32 level,
const void* data, unsigned int length) const void* data, unsigned int length)
{ {
if (fInit < B_OK) if (fSocket < 0 && _SetupSocket() != B_OK)
return fInit; return fStatus;
if (setsockopt(fSocket, level, option, data, length) < 0) { if (setsockopt(fSocket, level, option, data, length) < 0) {
fLastError = errno; fStatus = errno;
return B_ERROR; return B_ERROR;
} }
@@ -228,9 +257,12 @@ BNetEndpoint::SetOption(int32 option, int32 level,
int int
BNetEndpoint::SetNonBlocking(bool enable) BNetEndpoint::SetNonBlocking(bool enable)
{ {
if (fSocket < 0 && _SetupSocket() != B_OK)
return fStatus;
int flags = fcntl(fSocket, F_GETFL); int flags = fcntl(fSocket, F_GETFL);
if (flags < 0) { if (flags < 0) {
fLastError = errno; fStatus = errno;
return B_ERROR; return B_ERROR;
} }
@@ -240,7 +272,7 @@ BNetEndpoint::SetNonBlocking(bool enable)
flags &= ~O_NONBLOCK; flags &= ~O_NONBLOCK;
if (fcntl(fSocket, F_SETFL, flags) < 0) { if (fcntl(fSocket, F_SETFL, flags) < 0) {
fLastError = errno; fStatus = errno;
return B_ERROR; return B_ERROR;
} }
@@ -251,6 +283,9 @@ BNetEndpoint::SetNonBlocking(bool enable)
int int
BNetEndpoint::SetReuseAddr(bool enable) BNetEndpoint::SetReuseAddr(bool enable)
{ {
if (fSocket < 0 && _SetupSocket() != B_OK)
return fStatus;
int onoff = (int) enable; int onoff = (int) enable;
return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff)); return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff));
} }
@@ -266,14 +301,14 @@ BNetEndpoint::SetTimeout(bigtime_t timeout)
int int
BNetEndpoint::Error() const BNetEndpoint::Error() const
{ {
return fLastError; return (int)fStatus;
} }
char* char*
BNetEndpoint::ErrorStr() const BNetEndpoint::ErrorStr() const
{ {
return strerror(fLastError); return strerror(fStatus);
} }
@@ -287,15 +322,15 @@ BNetEndpoint::Close()
close(fSocket); close(fSocket);
fSocket = -1; fSocket = -1;
fInit = B_NO_INIT; fStatus = B_NO_INIT;
} }
status_t status_t
BNetEndpoint::Bind(const BNetAddress& address) BNetEndpoint::Bind(const BNetAddress& address)
{ {
if (fInit < B_OK) if (fSocket < 0 && _SetupSocket() != B_OK)
return fInit; return fStatus;
struct sockaddr_in addr; struct sockaddr_in addr;
status_t status = address.GetAddr(addr); status_t status = address.GetAddr(addr);
@@ -303,28 +338,18 @@ BNetEndpoint::Bind(const BNetAddress& address)
return status; return status;
if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (bind(fSocket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
fLastError = errno; fStatus = errno;
Close(); Close();
return B_ERROR; return B_ERROR;
} }
socklen_t addrSize = sizeof(addr); socklen_t addrSize = sizeof(addr);
if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) { if (getsockname(fSocket, (struct sockaddr *)&addr, &addrSize) < 0) {
fLastError = errno; fStatus = errno;
Close(); Close();
return B_ERROR; 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); fAddr.SetTo(addr);
return B_OK; return B_OK;
} }
@@ -341,8 +366,8 @@ BNetEndpoint::Bind(int port)
status_t status_t
BNetEndpoint::Connect(const BNetAddress& address) BNetEndpoint::Connect(const BNetAddress& address)
{ {
if (fInit < B_OK) if (fSocket < 0 && _SetupSocket() != B_OK)
return fInit; return fStatus;
sockaddr_in addr; sockaddr_in addr;
if (address.GetAddr(addr) != B_OK) if (address.GetAddr(addr) != B_OK)
@@ -350,17 +375,16 @@ BNetEndpoint::Connect(const BNetAddress& address)
if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) { if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) < 0) {
Close(); Close();
fLastError = errno; fStatus = errno;
return B_ERROR; return B_ERROR;
} }
socklen_t addrSize = sizeof(addr); socklen_t addrSize = sizeof(addr);
if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) { if (getpeername(fSocket, (sockaddr *) &addr, &addrSize) < 0) {
Close(); Close();
fLastError = errno; fStatus = errno;
return B_ERROR; return B_ERROR;
} }
fPeer.SetTo(addr); fPeer.SetTo(addr);
return B_OK; return B_OK;
} }
@@ -377,12 +401,12 @@ BNetEndpoint::Connect(const char *hostname, int port)
status_t status_t
BNetEndpoint::Listen(int backlog) BNetEndpoint::Listen(int backlog)
{ {
if (fInit < B_OK) if (fSocket < 0 && _SetupSocket() != B_OK)
return fInit; return fStatus;
if (listen(fSocket, backlog) < 0) { if (listen(fSocket, backlog) < 0) {
Close(); Close();
fLastError = errno; fStatus = errno;
return B_ERROR; return B_ERROR;
} }
return B_OK; return B_OK;
@@ -401,14 +425,14 @@ BNetEndpoint::Accept(int32 timeout)
int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize); int socket = accept(fSocket, (struct sockaddr *) &addr, &addrSize);
if (socket < 0) { if (socket < 0) {
Close(); Close();
fLastError = errno; fStatus = errno;
return NULL; return NULL;
} }
BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this); BNetEndpoint* endpoint = new (std::nothrow) BNetEndpoint(*this);
if (endpoint == NULL) { if (endpoint == NULL) {
close(socket); close(socket);
fLastError = B_NO_MEMORY; fStatus = B_NO_MEMORY;
return NULL; return NULL;
} }
@@ -417,7 +441,7 @@ BNetEndpoint::Accept(int32 timeout)
if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) { if (getsockname(socket, (struct sockaddr *)&addr, &addrSize) < 0) {
delete endpoint; delete endpoint;
fLastError = errno; fStatus = errno;
return NULL; return NULL;
} }
@@ -444,7 +468,7 @@ BNetEndpoint::IsDataPending(bigtime_t timeout)
} }
if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) { if (select(fSocket + 1, &fds, NULL, NULL, timeout > 0 ? &tv : NULL) < 0) {
fLastError = errno; fStatus = errno;
return false; return false;
} }
@@ -455,12 +479,15 @@ BNetEndpoint::IsDataPending(bigtime_t timeout)
int32 int32
BNetEndpoint::Receive(void* buffer, size_t length, int flags) BNetEndpoint::Receive(void* buffer, size_t length, int flags)
{ {
if (fSocket < 0 && _SetupSocket() != B_OK)
return fStatus;
if (fTimeout >= 0 && IsDataPending(fTimeout) == false) if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
return 0; return 0;
ssize_t bytesReceived = recv(fSocket, buffer, length, flags); ssize_t bytesReceived = recv(fSocket, buffer, length, flags);
if (bytesReceived < 0) if (bytesReceived < 0)
fLastError = errno; fStatus = errno;
return bytesReceived; return bytesReceived;
} }
@@ -480,6 +507,9 @@ int32
BNetEndpoint::ReceiveFrom(void* buffer, size_t length, BNetEndpoint::ReceiveFrom(void* buffer, size_t length,
BNetAddress& address, int flags) BNetAddress& address, int flags)
{ {
if (fSocket < 0 && _SetupSocket() != B_OK)
return fStatus;
if (fTimeout >= 0 && IsDataPending(fTimeout) == false) if (fTimeout >= 0 && IsDataPending(fTimeout) == false)
return 0; return 0;
@@ -489,7 +519,7 @@ BNetEndpoint::ReceiveFrom(void* buffer, size_t length,
length = recvfrom(fSocket, buffer, length, flags, length = recvfrom(fSocket, buffer, length, flags,
(struct sockaddr *)&addr, &addrSize); (struct sockaddr *)&addr, &addrSize);
if (length < 0) if (length < 0)
fLastError = errno; fStatus = errno;
else else
address.SetTo(addr); address.SetTo(addr);
@@ -511,9 +541,12 @@ BNetEndpoint::ReceiveFrom(BNetBuffer& buffer, size_t length,
int32 int32
BNetEndpoint::Send(const void* buffer, size_t length, int flags) 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); ssize_t bytesSent = send(fSocket, (const char *) buffer, length, flags);
if (bytesSent < 0) if (bytesSent < 0)
fLastError = errno; fStatus = errno;
return bytesSent; return bytesSent;
} }
@@ -530,6 +563,9 @@ int32
BNetEndpoint::SendTo(const void* buffer, size_t length, BNetEndpoint::SendTo(const void* buffer, size_t length,
const BNetAddress& address, int flags) const BNetAddress& address, int flags)
{ {
if (fSocket < 0 && _SetupSocket() != B_OK)
return fStatus;
struct sockaddr_in addr; struct sockaddr_in addr;
if (address.GetAddr(addr) != B_OK) if (address.GetAddr(addr) != B_OK)
return B_ERROR; return B_ERROR;
@@ -537,7 +573,7 @@ BNetEndpoint::SendTo(const void* buffer, size_t length,
ssize_t bytesSent = sendto(fSocket, buffer, length, flags, ssize_t bytesSent = sendto(fSocket, buffer, length, flags,
(struct sockaddr *) &addr, sizeof(addr)); (struct sockaddr *) &addr, sizeof(addr));
if (bytesSent < 0) if (bytesSent < 0)
fLastError = errno; fStatus = errno;
return bytesSent; return bytesSent;
} }
@@ -554,6 +590,40 @@ BNetEndpoint::SendTo(BNetBuffer& buffer,
// #pragma mark - // #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 // These are virtuals, implemented for binary compatibility purpose
void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {} void BNetEndpoint::_ReservedBNetEndpointFBCCruft1() {}
void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {} void BNetEndpoint::_ReservedBNetEndpointFBCCruft2() {}
+1 -1
View File
@@ -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. * Distributed under the terms of the MIT License.
*/ */
+3
View File
@@ -17,6 +17,9 @@ SimpleTest tcp_connection_test : tcp_connection_test.cpp
SimpleTest NetAddressTest : NetAddressTest.cpp SimpleTest NetAddressTest : NetAddressTest.cpp
: $(TARGET_NETWORK_LIBS) $(HAIKU_NETAPI_LIB) ; : $(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 DialUpPreflet ;
SubInclude HAIKU_TOP src tests kits net multicast ; SubInclude HAIKU_TOP src tests kits net multicast ;
SubInclude HAIKU_TOP src tests kits net netperf ; SubInclude HAIKU_TOP src tests kits net netperf ;
+352
View File
@@ -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;
}