Complete BNetEdnpoint implementation, based on Alexandre Bique contribution.

Fix sendto() and recvfrom() sockaddr length argument to int, not size_t.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@8564 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Philippe Houdoin 2004-08-14 00:12:28 +00:00
parent b1a1ca6c03
commit 2c42f7bcf1
5 changed files with 383 additions and 142 deletions

View File

@ -208,7 +208,7 @@ _EXPORT int accept(int sock, struct sockaddr *addr, int *addrlen)
_EXPORT ssize_t recvfrom(int sock, void *buffer, size_t buflen, int flags,
struct sockaddr *addr, size_t *addrlen)
struct sockaddr *addr, int *addrlen)
{
struct sockaddr temp;
struct msghdr mh;
@ -244,7 +244,7 @@ _EXPORT ssize_t recvfrom(int sock, void *buffer, size_t buflen, int flags,
}
_EXPORT ssize_t sendto(int sock, const void *buffer, size_t buflen, int flags,
const struct sockaddr *addr, size_t addrlen)
const struct sockaddr *addr, int addrlen)
{
struct sockaddr temp;
struct msghdr mh;

View File

@ -5,7 +5,7 @@ UsePrivateHeaders net ;
SubDirC++Flags -DBUILDING_R5_LIBNET ;
SharedLibrary netapi :
# NetEndpoint.cpp
NetEndpoint.cpp
NetAddress.cpp
NetBuffer.cpp
NetDebug.cpp

View File

@ -70,7 +70,7 @@
* size : Initial size of buffer (default is zero).
*
* Remarks:
* This bad boy doubles up as the defalt ctor.
* This bad boy doubles up as the default ctor.
*/
BNetBuffer::BNetBuffer( size_t size )
: CTOR_INIT_LIST

View File

@ -16,37 +16,88 @@
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <Message.h>
#include <NetEndpoint.h>
BNetEndpoint::BNetEndpoint(int protocol)
: fStatus(B_OK),
fSocket(0),
fTimeout(B_INFINITE_TIMEOUT),
fLocalAddr(),
fRemoteAddr()
: m_init(B_NO_INIT), m_socket(-1), m_timeout(B_INFINITE_TIMEOUT), m_last_error(0)
{
if ((fSocket = socket(AF_INET, protocol, 0)) < 0)
fStatus = B_ERROR;
if ((m_socket = socket(AF_INET, protocol, 0)) < 0)
m_last_error = errno;
else
m_init = B_OK;
}
BNetEndpoint::BNetEndpoint(int handle, bigtime_t timeout)
: fStatus(B_OK),
fSocket(0),
fTimeout(timeout),
fLocalAddr(),
fRemoteAddr()
BNetEndpoint::BNetEndpoint(int family, int type, int protocol)
: m_init(B_NO_INIT), m_socket(-1), m_timeout(B_INFINITE_TIMEOUT), m_last_error(0)
{
if ((fSocket = dup(handle)) < 0)
fStatus = B_ERROR;
if ((m_socket = socket(family, type, protocol)) < 0)
m_last_error = errno;
else
m_init = B_OK;
}
BNetEndpoint::BNetEndpoint(const BNetEndpoint & endpoint)
: fStatus(endpoint.fStatus),
fSocket(endpoint.fSocket),
fTimeout(endpoint.fTimeout),
fLocalAddr(endpoint.fLocalAddr),
fRemoteAddr(endpoint.fRemoteAddr)
BNetEndpoint::BNetEndpoint(BMessage *archive)
: m_init(B_NO_INIT),
m_socket(-1),
m_timeout(B_INFINITE_TIMEOUT),
m_last_error(0)
{
// TODO
if (! archive)
return;
BMessage msg;
if (archive->FindMessage("bnendp_peer", &msg) != B_OK)
return;
m_peer = BNetAddress(&msg);
if (archive->FindMessage("bnendp_addr", &msg) != B_OK)
return;
m_addr = BNetAddress(&msg);
if (archive->FindMessage("bnendp_conaddr", &msg) != B_OK)
return;
m_conaddr = BNetAddress(&msg);
m_init = B_OK;
}
BNetEndpoint::BNetEndpoint(const BNetEndpoint & ep)
: m_init(ep.m_init), m_timeout(ep.m_timeout), m_last_error(ep.m_last_error),
m_addr(ep.m_addr), m_peer(ep.m_peer)
{
m_socket = -1;
if (ep.m_socket >= 0)
m_socket = dup(ep.m_socket);
}
BNetEndpoint & BNetEndpoint::operator=(const BNetEndpoint & ep)
{
Close();
m_init = ep.m_init;
m_timeout = ep.m_timeout;
m_last_error = ep.m_last_error;
m_addr = ep.m_addr;
m_peer = ep.m_peer;
m_socket = -1;
if (ep.m_socket >= 0)
m_socket = dup(ep.m_socket);
if (m_socket >= 0)
m_init = B_OK;
return *this;
}
BNetEndpoint::~BNetEndpoint()
@ -54,236 +105,426 @@ BNetEndpoint::~BNetEndpoint()
Close();
}
BNetEndpoint::BNetEndpoint(BMessage *archive)
: fStatus(B_OK),
fSocket(0),
fTimeout(B_INFINITE_TIMEOUT),
fLocalAddr(),
fRemoteAddr()
{
// TODO
fStatus = B_ERROR;
}
// #pragma mark -
status_t BNetEndpoint::Archive(BMessage *into, bool deep = true) const
{
// TODO
return B_ERROR;
if( into == 0 )
return B_ERROR;
if ( m_init != B_OK )
return B_NO_INIT;
BMessage msg;
if (m_peer.Archive(&msg) != B_OK)
return B_ERROR;
if (into->AddMessage("bnendp_peer", &msg) != B_OK)
return B_ERROR;
if (m_addr.Archive(&msg) != B_OK)
return B_ERROR;
if (into->AddMessage("bnendp_addr", &msg) != B_OK)
return B_ERROR;
if (m_conaddr.Archive(&msg) != B_OK)
return B_ERROR;
if (into->AddMessage("bnendp_conaddr", &msg) != B_OK)
return B_ERROR;
return B_OK;
}
BArchivable *BNetEndpointInstantiate(BMessage *archive)
BArchivable *BNetEndpoint::Instantiate(BMessage *archive)
{
// TODO
if (! archive)
return NULL;
if (! validate_instantiation(archive, "BNetAddress") )
return NULL;
BNetEndpoint *ep = new BNetEndpoint(archive);
if (ep && ep->InitCheck() == B_OK)
return ep;
delete ep;
return NULL;
}
// #pragma mark -
status_t BNetEndpoint::InitCheck() const
{
return fStatus;
return m_init;
}
int BNetEndpoint::Socket() const
{
return fSocket;
return m_socket;
}
const BNetAddress & BNetEndpoint::LocalAddr() const
{
return fLocalAddr;
return m_addr;
}
const BNetAddress & BNetEndpoint::RemoteAddr() const
{
return fRemoteAddr;
return m_peer;
}
status_t BNetEndpoint::SetProtocol(int protocol)
{
Close();
if ((fSocket = ::socket(AF_INET, protocol, 0)) < 0)
return B_ERROR;
return B_OK;
if ((m_socket = socket(AF_INET, protocol, 0)) < 0) {
m_last_error = errno;
return m_last_error;
}
m_init = B_OK;
return m_init;
}
status_t BNetEndpoint::SetOption(int32 option, int32 level,
int BNetEndpoint::SetOption(int32 option, int32 level,
const void * data, unsigned int length)
{
if (setsockopt(fSocket, level, option, data, length) < 0)
if (m_socket < 0)
return B_ERROR;
if (setsockopt(m_socket, level, option, data, length) < 0) {
m_last_error = errno;
return B_ERROR;
}
return B_OK;
}
status_t BNetEndpoint::SetNonBlocking(bool enable)
int BNetEndpoint::SetNonBlocking(bool enable)
{
int flags = fcntl(fSocket, F_GETFL);
int flags = fcntl(m_socket, F_GETFL);
if (enable)
flags |= O_NONBLOCK;
else
flags &= ~O_NONBLOCK;
if (fcntl(fSocket, F_SETFL, flags) < 0)
if (fcntl(m_socket, F_SETFL, flags) < 0) {
m_last_error = errno;
return B_ERROR;
}
return B_OK;
}
status_t BNetEndpoint::SetReuseAddr(bool enable)
int BNetEndpoint::SetReuseAddr(bool enable)
{
return SetOption(SO_REUSEADDR, SOL_SOCKET, &enable, sizeof(enable));
int onoff = (int) enable;
return SetOption(SO_REUSEADDR, SOL_SOCKET, &onoff, sizeof(onoff));
}
void BNetEndpoint::SetTimeout(bigtime_t timeout)
{
fTimeout = timeout;
m_timeout = timeout;
}
status_t BNetEndpoint::Bind(const BNetAddress & address)
int BNetEndpoint::Error() const
{
sockaddr_in addr;
if (address.GetAddr(addr) == B_OK) {
if (bind(fSocket, (sockaddr *) &addr, sizeof(addr)) >= 0) {
sockaddr_in name;
int length = sizeof(name);
if (getsockname(fSocket, (sockaddr *) &name, &length) >= 0)
fLocalAddr.SetTo(name);
return B_OK;
}
}
return B_ERROR;
return m_last_error;
}
status_t BNetEndpoint::Bind(int port)
char * BNetEndpoint::ErrorStr() const
{
char hostname[256];
if (gethostname(hostname, sizeof(hostname)) >= 0)
return BNetEndpoint::Bind(BNetAddress(hostname, port));
return B_ERROR;
return strerror(m_last_error);
}
// #pragma mark -
void BNetEndpoint::Close()
{
close(fSocket);
fSocket = 0;
if (m_socket >= 0)
close(m_socket);
m_socket = -1;
m_init = B_NO_INIT;
}
status_t BNetEndpoint::Bind(const BNetAddress & address)
{
struct sockaddr_in addr;
status_t status;
status = address.GetAddr(addr);
if (status != B_OK)
return status;
if (bind(m_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
m_last_error = errno;
Close();
return B_ERROR;
}
int sz = sizeof(addr);
if (getsockname(m_socket, (struct sockaddr *) &addr, &sz) < 0) {
m_last_error = errno;
Close();
return B_ERROR;
}
#ifdef _NETDB_H_
if (addr.sin_addr.s_addr == 0) {
// Grrr, buggy getsockname!
char hostname[MAXHOSTNAMELEN];
struct hostent *he;
gethostname(hostname, sizeof(hostname));
he = gethostbyname(hostname);
if (he)
memcpy(&addr.sin_addr.s_addr, he->h_addr, sizeof(addr.sin_addr.s_addr));
}
#endif
m_addr.SetTo(addr);
return B_OK;
}
status_t BNetEndpoint::Bind(int port)
{
BNetAddress addr(INADDR_ANY, port);
return Bind(addr);
}
status_t BNetEndpoint::Connect(const BNetAddress & address)
{
sockaddr_in addr;
if (address.GetAddr(addr) == B_OK) {
if (connect(fSocket, (sockaddr *) &addr, sizeof(addr)) >= 0) {
sockaddr_in name;
int length = sizeof(name);
if (getpeername(fSocket, (sockaddr *) &name, &length) >= 0)
fRemoteAddr.SetTo(name);
return B_OK;
}
}
return B_ERROR;
}
status_t BNetEndpoint::Connect(const char * hostname, int port)
{
BNetAddress address(hostname, port);
return BNetEndpoint::Connect(address);
}
status_t BNetEndpoint::Listen(int backlog)
{
if (listen(fSocket, backlog) < 0)
if (address.GetAddr(addr) != B_OK)
return B_ERROR;
if (connect(m_socket, (sockaddr *) &addr, sizeof(addr)) < 0) {
Close();
m_last_error = errno;
return B_ERROR;
}
int sz = sizeof(addr);
if (getpeername(m_socket, (sockaddr *) &addr, &sz) < 0) {
Close();
return B_ERROR;
}
m_peer.SetTo(addr);
return B_OK;
}
BNetEndpoint *BNetEndpoint::Accept(int32 timeout)
{
if (IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout)) {
sockaddr_in name;
int length = sizeof(name);
int handle = accept(fSocket, (sockaddr *) &name, &length);
if (handle >= 0) {
BNetEndpoint * endpoint = new BNetEndpoint(handle, fTimeout);
if (endpoint != NULL) {
endpoint->fRemoteAddr.SetTo(name);
if (getsockname(handle, (sockaddr *) &name, &length) >= 0)
endpoint->fLocalAddr.SetTo(name);
}
return endpoint;
}
}
return NULL;
status_t BNetEndpoint::Connect(const char *hostname, int port)
{
BNetAddress addr(hostname, port);
return Connect(addr);
}
status_t BNetEndpoint::Listen(int backlog)
{
if (listen(m_socket, backlog) < 0) {
Close();
m_last_error = errno;
return B_ERROR;
}
return B_OK;
}
BNetEndpoint * BNetEndpoint::Accept(int32 timeout)
{
if (! IsDataPending(timeout < 0 ? B_INFINITE_TIMEOUT : 1000LL * timeout))
return NULL;
struct sockaddr_in addr;
int sz = sizeof(addr);
int handle = accept(m_socket, (struct sockaddr *) &addr, &sz);
if (handle < 0) {
Close();
m_last_error = errno;
return NULL;
}
BNetEndpoint * ep = new BNetEndpoint(*this);
if (! ep) {
close(handle);
return NULL;
}
ep->m_socket = handle;
ep->m_peer.SetTo(addr);
if (getsockname(handle, (struct sockaddr *) &addr, &sz) < 0) {
ep->Close();
delete ep;
return NULL;
}
ep->m_addr.SetTo(addr);
return ep;
}
// #pragma mark -
bool BNetEndpoint::IsDataPending(bigtime_t timeout)
{
fd_set fds;
struct timeval tv;
struct timeval tv, *tv_ptr = NULL;
FD_ZERO(&fds);
FD_SET(fSocket, &fds);
FD_SET(m_socket, &fds);
tv.tv_sec = timeout / 1000000;
tv.tv_usec = (timeout % 1000000);
if (timeout > 0) {
tv.tv_sec = timeout / 1000000;
tv.tv_usec = (timeout % 1000000);
tv_ptr = &tv;
}
if (select(m_socket + 1, &fds, NULL, NULL, &tv) < 0) {
m_last_error = errno;
return false;
}
return (select(fSocket + 1, &fds, NULL, NULL, &tv) > 0);
return FD_ISSET(m_socket, &fds);
}
int32 BNetEndpoint::Receive(void * buffer, size_t length, int flags)
{
if (IsDataPending(fTimeout))
return recv(fSocket, buffer, length, flags);
return -1;
if (m_timeout >= 0 && IsDataPending(m_timeout) == false)
return 0;
ssize_t sz = recv(m_socket, buffer, length, flags);
if (sz < 0)
m_last_error = errno;
return sz;
}
int32 BNetEndpoint::Receive(BNetBuffer & buffer, size_t length, int flags)
{
BNetBuffer chunk(length);
length = Receive(chunk.Data(), chunk.Size(), flags);
length = Receive(chunk.Data(), length, flags);
buffer.AppendData(chunk.Data(), length);
return length;
}
int32 BNetEndpoint::ReceiveFrom(void * buffer, size_t length,
const BNetAddress & address, int flags)
BNetAddress & address, int flags)
{
sockaddr_in addr;
int addrlen = sizeof(addr);
if (address.GetAddr(addr) == B_OK && IsDataPending(fTimeout))
return recvfrom(fSocket, buffer, length, flags,
(sockaddr *) &addr, &addrlen);
return -1;
if (m_timeout >= 0 && IsDataPending(m_timeout) == false)
return 0;
struct sockaddr_in addr;
int sz = sizeof(addr);
length = recvfrom(m_socket, buffer, length, flags,
(struct sockaddr *) &addr, &sz);
if (length < 0)
m_last_error = errno;
else
address.SetTo(addr);
return length;
}
int32 BNetEndpoint::ReceiveFrom(BNetBuffer & buffer,
const BNetAddress & address, int flags)
int32 BNetEndpoint::ReceiveFrom(BNetBuffer & buffer, size_t length,
BNetAddress & address, int flags)
{
return ReceiveFrom(buffer.Data(), buffer.Size(), address, flags);
BNetBuffer chunk(length);
length = ReceiveFrom(chunk.Data(), length, address, flags);
buffer.AppendData(chunk.Data(), length);
return length;
}
int32 BNetEndpoint::Send(const void * buffer, size_t length, int flags)
{
return send(fSocket, (const char *) buffer, length, flags);
ssize_t sz;
sz = send(m_socket, (const char *) buffer, length, flags);
if (sz < 0)
m_last_error = errno;
return sz;
}
int32 BNetEndpoint::Send(const BNetBuffer & buffer, int flags)
int32 BNetEndpoint::Send(BNetBuffer & buffer, int flags)
{
return Send(buffer.Data(), buffer.Size(), flags);
}
int32 BNetEndpoint::SendTo(const void * buffer, size_t length,
const BNetAddress & address, int flags)
{
sockaddr_in addr;
address.GetAddr(addr);
return sendto(fSocket, buffer, length, flags,
(sockaddr *) &addr, sizeof(addr));
ssize_t sz;
struct sockaddr_in addr;
if (address.GetAddr(addr) != B_OK)
return B_ERROR;
sz = sendto(m_socket, buffer, length, flags,
(struct sockaddr *) &addr, sizeof(addr));
if (sz < 0)
m_last_error = errno;
return sz;
}
int32 BNetEndpoint::SendTo(const BNetBuffer & buffer,
int32 BNetEndpoint::SendTo(BNetBuffer & buffer,
const BNetAddress & address, int flags)
{
return SendTo(buffer.Data(), buffer.Size(), address, flags);
}
// #pragma mark -
// These are virtuals, implemented for binary compatibility purpose
void BNetEndpoint::_ReservedBNetEndpointFBCCruft1()
{
}
void BNetEndpoint::_ReservedBNetEndpointFBCCruft2()
{
}
void BNetEndpoint::_ReservedBNetEndpointFBCCruft3()
{
}
void BNetEndpoint::_ReservedBNetEndpointFBCCruft4()
{
}
void BNetEndpoint::_ReservedBNetEndpointFBCCruft5()
{
}
void BNetEndpoint::_ReservedBNetEndpointFBCCruft6()
{
}

View File

@ -128,7 +128,7 @@ _EXPORT int accept(int sock, struct sockaddr *addr, int *addrlen)
_EXPORT ssize_t recvfrom(int sock, void *buffer, size_t buflen, int flags,
struct sockaddr *addr, size_t *addrlen)
struct sockaddr *addr, int *addrlen)
{
struct msghdr mh;
struct iovec iov;
@ -156,7 +156,7 @@ _EXPORT ssize_t recvfrom(int sock, void *buffer, size_t buflen, int flags,
}
_EXPORT ssize_t sendto(int sock, const void *buffer, size_t buflen, int flags,
const struct sockaddr *addr, size_t addrlen)
const struct sockaddr *addr, int addrlen)
{
struct msghdr mh;
struct iovec iov;