* Put ServerConnection into the BPrivate namespace as it should have been.

* Fixed completely broken error reporting; Write()/Read() will now return the
  proper error code (and ssize_t instead of int32).
* Reimplemented WaitForData() using poll() which is more efficient.
* Now uses BNetworkAddress to resolve the server address which also should now
  work with IPv6.
* Removed some unused headers.
* Minor coding style cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43141 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2011-11-02 22:56:50 +00:00
parent afa453ee2a
commit 214853702f
3 changed files with 134 additions and 93 deletions
+12 -13
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010, Haiku Inc. All Rights Reserved. * Copyright 2010-2011, Haiku Inc. All Rights Reserved.
* Copyright 2010 Clemens Zeidler. All rights reserved. * Copyright 2010 Clemens Zeidler. All rights reserved.
* *
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
@@ -11,18 +11,10 @@
#include "SupportDefs.h" #include "SupportDefs.h"
class AbstractConnection { namespace BPrivate {
public:
virtual ~AbstractConnection();
virtual status_t Connect(const char* server, uint32 port) = 0;
virtual status_t Disconnect() = 0;
virtual status_t WaitForData(bigtime_t timeout) = 0; class AbstractConnection;
virtual int32 Read(char* buffer, uint32 nBytes) = 0;
virtual int32 Write(const char* buffer, uint32 nBytes) = 0;
};
class ServerConnection { class ServerConnection {
@@ -39,11 +31,18 @@ public:
status_t WaitForData(bigtime_t timeout); status_t WaitForData(bigtime_t timeout);
int32 Read(char* buffer, uint32 nBytes); ssize_t Read(char* buffer, uint32 length);
int32 Write(const char* buffer, uint32 nBytes); ssize_t Write(const char* buffer, uint32 length);
private: private:
AbstractConnection* fConnection; AbstractConnection* fConnection;
}; };
} // namespace BPrivate
using BPrivate::ServerConnection;
#endif // SERVER_CONNECTION_H #endif // SERVER_CONNECTION_H
+1 -3
View File
@@ -53,9 +53,7 @@ AddResources libmail.so : libmail.rdef ;
SharedLibrary libmail.so : SharedLibrary libmail.so :
$(sources) $(sources)
: :
be be libbnetapi.so libtextencoding.so tracker
libtextencoding.so
tracker
$(TARGET_LIBSTDC++) $(TARGET_LIBSTDC++)
$(TARGET_NETWORK_LIBS) $(TARGET_NETWORK_LIBS)
$(TARGET_SELECT_UNAME_ETC_LIB) $(TARGET_SELECT_UNAME_ETC_LIB)
+119 -75
View File
@@ -1,31 +1,52 @@
/*
* Copyright 2010-2011, Haiku, Inc. All rights reserved.
* Copyright 2010, Clemens Zeidler <[email protected]>
* Distributed under the terms of the MIT License.
*/
#include "ServerConnection.h" #include "ServerConnection.h"
#include <arpa/inet.h> #include <errno.h>
#include <netdb.h> #include <sys/poll.h>
#include <unistd.h> #include <unistd.h>
#ifdef USE_SSL #ifdef USE_SSL
#include <openssl/ssl.h> # include <openssl/ssl.h>
#include <openssl/rand.h> # include <openssl/rand.h>
#else
#include <string.h>
#include <sys/time.h>
#endif #endif
#include <Autolock.h> #include <Autolock.h>
#include <Locker.h> #include <Locker.h>
#include <NetworkAddress.h>
#define DEBUG_SERVER_CONNECTION #define DEBUG_SERVER_CONNECTION
#ifdef DEBUG_SERVER_CONNECTION #ifdef DEBUG_SERVER_CONNECTION
#include <stdio.h> # include <stdio.h>
#define TRACE(x...) printf(x) # define TRACE(x...) printf(x)
#else #else
#define TRACE(x...) /* nothing */ # define TRACE(x...) ;
#endif #endif
namespace BPrivate {
class AbstractConnection {
public:
virtual ~AbstractConnection();
virtual status_t Connect(const char* server, uint32 port) = 0;
virtual status_t Disconnect() = 0;
virtual status_t WaitForData(bigtime_t timeout) = 0;
virtual ssize_t Read(char* buffer, uint32 length) = 0;
virtual ssize_t Write(const char* buffer, uint32 length) = 0;
};
class SocketConnection : public AbstractConnection { class SocketConnection : public AbstractConnection {
public: public:
SocketConnection(); SocketConnection();
@@ -35,8 +56,8 @@ public:
status_t WaitForData(bigtime_t timeout); status_t WaitForData(bigtime_t timeout);
int32 Read(char* buffer, uint32 nBytes); ssize_t Read(char* buffer, uint32 length);
int32 Write(const char* buffer, uint32 nBytes); ssize_t Write(const char* buffer, uint32 length);
protected: protected:
int fSocket; int fSocket;
@@ -44,6 +65,8 @@ protected:
#ifdef USE_SSL #ifdef USE_SSL
class InitSSL { class InitSSL {
public: public:
InitSSL() InitSSL()
@@ -62,8 +85,7 @@ public:
}; };
status_t status_t InitCheck()
InitCheck()
{ {
return fInit ? B_OK : B_ERROR; return fInit ? B_OK : B_ERROR;
} }
@@ -73,9 +95,6 @@ private:
}; };
static InitSSL gInitSSL;
class SSLConnection : public SocketConnection { class SSLConnection : public SocketConnection {
public: public:
SSLConnection(); SSLConnection();
@@ -85,34 +104,40 @@ public:
status_t WaitForData(bigtime_t timeout); status_t WaitForData(bigtime_t timeout);
int32 Read(char* buffer, uint32 nBytes); ssize_t Read(char* buffer, uint32 length);
int32 Write(const char* buffer, uint32 nBytes); ssize_t Write(const char* buffer, uint32 length);
private: private:
SSL_CTX* fCTX; SSL_CTX* fCTX;
SSL* fSSL; SSL* fSSL;
BIO* fBIO; BIO* fBIO;
}; };
#endif
static InitSSL gInitSSL;
#endif // USE_SSL
AbstractConnection::~AbstractConnection() AbstractConnection::~AbstractConnection()
{ {
} }
// #pragma mark -
ServerConnection::ServerConnection() ServerConnection::ServerConnection()
: :
fConnection(NULL) fConnection(NULL)
{ {
} }
ServerConnection::~ServerConnection() ServerConnection::~ServerConnection()
{ {
if (fConnection) if (fConnection != NULL)
fConnection->Disconnect(); fConnection->Disconnect();
delete fConnection; delete fConnection;
} }
@@ -158,7 +183,7 @@ ServerConnection::WaitForData(bigtime_t timeout)
} }
int32 ssize_t
ServerConnection::Read(char* buffer, uint32 nBytes) ServerConnection::Read(char* buffer, uint32 nBytes)
{ {
if (fConnection == NULL) if (fConnection == NULL)
@@ -167,7 +192,7 @@ ServerConnection::Read(char* buffer, uint32 nBytes)
} }
int32 ssize_t
ServerConnection::Write(const char* buffer, uint32 nBytes) ServerConnection::Write(const char* buffer, uint32 nBytes)
{ {
if (fConnection == NULL) if (fConnection == NULL)
@@ -176,11 +201,13 @@ ServerConnection::Write(const char* buffer, uint32 nBytes)
} }
// #pragma mark -
SocketConnection::SocketConnection() SocketConnection::SocketConnection()
: :
fSocket(-1) fSocket(-1)
{ {
} }
@@ -191,29 +218,20 @@ SocketConnection::Connect(const char* server, uint32 port)
Disconnect(); Disconnect();
TRACE("SocketConnection to server %s:%i\n", server, (int)port); TRACE("SocketConnection to server %s:%i\n", server, (int)port);
uint32 hostIP = inet_addr(server);
// first see if we can parse it as a numeric address
if (hostIP == 0 || hostIP == (uint32)-1) {
struct hostent *he = gethostbyname(server);
hostIP = he ? *((uint32*)he->h_addr) : 0;
}
if (hostIP == 0)
return B_ERROR;
fSocket = socket(AF_INET, SOCK_STREAM, 0); BNetworkAddress address;
status_t status = address.SetTo(server, port);
if (status != B_OK)
return status;
fSocket = socket(address.Family(), SOCK_STREAM, 0);
if (fSocket < 0) if (fSocket < 0)
return B_ERROR; return errno;
sockaddr_in saAddr; int result = connect(fSocket, address, address.Length());
memset(&saAddr, 0, sizeof(saAddr));
saAddr.sin_family = AF_INET;
saAddr.sin_port = htons(port);
saAddr.sin_addr.s_addr = hostIP;
int result = connect(fSocket, (struct sockaddr*)&saAddr,
sizeof(saAddr));
if (result < 0) { if (result < 0) {
close(fSocket); close(fSocket);
return B_ERROR; return errno;
} }
TRACE("SocketConnection: connected\n"); TRACE("SocketConnection: connected\n");
@@ -234,47 +252,58 @@ SocketConnection::Disconnect()
status_t status_t
SocketConnection::WaitForData(bigtime_t timeout) SocketConnection::WaitForData(bigtime_t timeout)
{ {
timeval tv; struct pollfd entry;
fd_set fds; entry.fd = fSocket;
tv.tv_sec = long(timeout / 1e6); entry.events = POLLIN;
tv.tv_usec = long(timeout - (tv.tv_sec * 1e6));
/* Initialize (clear) the socket mask. */ int timeoutMillis = -1;
FD_ZERO(&fds); if (timeout > 0)
/* Set the socket in the mask. */ timeoutMillis = timeout / 1000;
FD_SET(fSocket, &fds);
int result = select(fSocket + 1, &fds, NULL, NULL, &tv); int result = poll(&entry, 1, timeoutMillis);
if (result == 0) if (result == 0)
return B_TIMED_OUT; return B_TIMED_OUT;
if (result < 0) if (result < 0)
return B_ERROR; return errno;
return B_OK; return B_OK;
} }
int32 ssize_t
SocketConnection::Read(char* buffer, uint32 nBytes) SocketConnection::Read(char* buffer, uint32 length)
{ {
return recv(fSocket, buffer, nBytes, 0); ssize_t bytesReceived = recv(fSocket, buffer, length, 0);
if (bytesReceived < 0)
return errno;
return bytesReceived;
} }
int32 ssize_t
SocketConnection::Write(const char* buffer, uint32 nBytes) SocketConnection::Write(const char* buffer, uint32 length)
{ {
return send(fSocket, buffer, nBytes, 0); ssize_t bytesWritten = send(fSocket, buffer, length, 0);
if (bytesWritten < 0)
return errno;
return bytesWritten;
} }
// #pragma mark -
#ifdef USE_SSL #ifdef USE_SSL
SSLConnection::SSLConnection() SSLConnection::SSLConnection()
: :
fCTX(NULL), fCTX(NULL),
fSSL(NULL), fSSL(NULL),
fBIO(NULL) fBIO(NULL)
{ {
} }
@@ -329,31 +358,46 @@ SSLConnection::Disconnect()
status_t status_t
SSLConnection::WaitForData(bigtime_t timeout) SSLConnection::WaitForData(bigtime_t timeout)
{ {
if (!fSSL) if (fSSL == NULL)
return B_ERROR; return B_NO_INIT;
if (SSL_pending(fSSL) > 0) { if (SSL_pending(fSSL) > 0)
return B_OK; return B_OK;
}
return SocketConnection::WaitForData(timeout); return SocketConnection::WaitForData(timeout);
} }
int32 ssize_t
SSLConnection::Read(char* buffer, uint32 nBytes) SSLConnection::Read(char* buffer, uint32 length)
{ {
if (!fSSL) if (fSSL == NULL)
return B_NO_INIT;
int bytesRead = SSL_read(fSSL, buffer, length);
if (bytesRead > 0)
return bytesRead;
// TODO: translate SSL error codes!
return B_ERROR; return B_ERROR;
return SSL_read(fSSL, buffer, nBytes);
} }
int32 ssize_t
SSLConnection::Write(const char* buffer, uint32 nBytes) SSLConnection::Write(const char* buffer, uint32 length)
{ {
if (!fSSL) if (fSSL == NULL)
return B_NO_INIT;
int bytesWritten = SSL_write(fSSL, buffer, length);
if (bytesWritten > 0)
return bytesWritten;
// TODO: translate SSL error codes!
return B_ERROR; return B_ERROR;
return SSL_write(fSSL, buffer, nBytes);
} }
#endif #endif // USE_SSL
} // namespace BPrivate