From 2c42f7bcf1de1e01c0ea53aee13eefbec266ebc4 Mon Sep 17 00:00:00 2001 From: Philippe Houdoin Date: Sat, 14 Aug 2004 00:12:28 +0000 Subject: [PATCH] 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 --- src/kits/network/libnet/socket.c | 4 +- src/kits/network/libnetapi/Jamfile | 2 +- src/kits/network/libnetapi/NetBuffer.cpp | 2 +- src/kits/network/libnetapi/NetEndpoint.cpp | 513 +++++++++++++++------ src/kits/network/libsocket/socket.c | 4 +- 5 files changed, 383 insertions(+), 142 deletions(-) diff --git a/src/kits/network/libnet/socket.c b/src/kits/network/libnet/socket.c index 9f9a89f82e..0a104826e1 100644 --- a/src/kits/network/libnet/socket.c +++ b/src/kits/network/libnet/socket.c @@ -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; diff --git a/src/kits/network/libnetapi/Jamfile b/src/kits/network/libnetapi/Jamfile index bc8d5ad7c1..548a227f92 100644 --- a/src/kits/network/libnetapi/Jamfile +++ b/src/kits/network/libnetapi/Jamfile @@ -5,7 +5,7 @@ UsePrivateHeaders net ; SubDirC++Flags -DBUILDING_R5_LIBNET ; SharedLibrary netapi : -# NetEndpoint.cpp + NetEndpoint.cpp NetAddress.cpp NetBuffer.cpp NetDebug.cpp diff --git a/src/kits/network/libnetapi/NetBuffer.cpp b/src/kits/network/libnetapi/NetBuffer.cpp index 539ea5caad..21c6cb7eea 100644 --- a/src/kits/network/libnetapi/NetBuffer.cpp +++ b/src/kits/network/libnetapi/NetBuffer.cpp @@ -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 diff --git a/src/kits/network/libnetapi/NetEndpoint.cpp b/src/kits/network/libnetapi/NetEndpoint.cpp index 3c938be5e9..6370b26299 100644 --- a/src/kits/network/libnetapi/NetEndpoint.cpp +++ b/src/kits/network/libnetapi/NetEndpoint.cpp @@ -16,37 +16,88 @@ #include #include #include +#include + +#include #include + 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() +{ +} + diff --git a/src/kits/network/libsocket/socket.c b/src/kits/network/libsocket/socket.c index f0c4384060..2ee7684de8 100644 --- a/src/kits/network/libsocket/socket.c +++ b/src/kits/network/libsocket/socket.c @@ -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;