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(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();
+18 -7
View File
@@ -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
+7 -1
View File
@@ -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:
+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.
*/
@@ -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 -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.
*/
+3
View File
@@ -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 ;
+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;
}