refactor: AddrInfo moved from Socket

master
Denes Matetelki 13 years ago
parent 65c49e071c
commit ac8409c59e

2
.gitignore vendored

@ -26,4 +26,4 @@ other/client
other/server
other/sslclient
other/sslserver
other/server.*

@ -0,0 +1,31 @@
#ifndef ADDR_INFO_HPP
#define ADDR_INFO_HPP
#include <netdb.h>
#include <string>
class AddrInfo
{
public:
AddrInfo();
virtual ~AddrInfo();
bool getHostInfo(const std::string host, const std::string port);
addrinfo* operator[](const unsigned int pos);
void printHostDetails() const;
static bool convertNameInfo(const addrinfo* addrInfo,
std::string &retAddr,
std::string &retService);
private:
AddrInfo(const AddrInfo&);
AddrInfo& operator=(const AddrInfo&);
struct addrinfo *m_addrInfo;
};
#endif // ADDR_INFO_HPP

@ -17,20 +17,20 @@ public:
virtual bool receive() = 0;
std::string getHost() const;
int getPort() const;
std::string getPort() const;
void setHost(const std::string host);
void setPort(const int port);
void setPort(const std::string port);
virtual int getSocket() const = 0;
protected:
Connection(std::string host = std::string("invalid"), int port = -1);
Connection(const std::string host, const std::string port);
std::string m_host;
int m_port;
std::string m_port;
private:

@ -21,20 +21,15 @@ public:
static T* getInstance()
{
if ( not m_instance )
{
if ( not m_instance ) {
std::lock_guard<std::mutex> guard(m_lock);
if ( not m_instance ) // re-check pinstance
{
// Douglas Schmidt proposed volatile
// to prevent "agressive optimalizations"
if ( not m_instance ) {
volatile T *temp = new T();
m_instance = (T*)temp;
}
}
return m_instance;
return (T*)m_instance;
}
static void destroy()
@ -47,12 +42,12 @@ private:
static std::mutex m_lock;
// instance chack shall not be cached
// instance double check shall not be cached
static volatile T* m_instance;
};
template<class T> std::mutex Singleton_DCLP<T>::m_lock;
template<class T> T* Singleton_DCLP<T>::m_instance = 0;
template<class T> volatile T* Singleton_DCLP<T>::m_instance = 0;
#endif // SINGLETON_DCLP_HPP

@ -22,26 +22,16 @@ public:
bool createSocket();
bool closeSocket();
bool connectToHost( const std::string host,
const std::string port );
bool bindToHost( const std::string host,
const std::string port );
bool connect(addrinfo *servinfo);
bool bind(addrinfo *servinfo);
bool listen( const int maxPendingQueueLen = 64 );
void getPeerName(std::string &host,
std::string &port);
bool send( const void *message, const int lenght );
bool receive ( void* buffer, const int bufferLen, ssize_t *msgLen );
void getPeerName(std::string &host, std::string &port);
int getSocket() const;
static bool convertNameInfo( sockaddr* addr,
socklen_t addrLen,
std::string &retAddr,
std::string &retService);
protected:
int m_socket;
@ -49,21 +39,6 @@ protected:
int m_domain;
int m_type;
int m_protocol;
sockaddr m_addr;
socklen_t m_addrLen;
private:
bool connectToFirstAddress(struct addrinfo *servinfo);
bool bindToFirstAddress(struct addrinfo *servinfo);
static bool getHostInfo(const std::string host,
const std::string port,
struct addrinfo **servinfo);
static void printHostDetails(struct addrinfo *servinfo);
};
#endif // SOCKET_HPP

@ -27,7 +27,7 @@ public:
const size_t bufferLength = 1024 );
SslConnection ( const std::string host,
const int port,
const std::string port,
Message *message,
const size_t bufferLength = 1024 );

@ -25,7 +25,7 @@ public:
protected:
StreamConnection(std::string host = std::string("invalid"), int port = -1)
StreamConnection(const std::string host, const std::string port)
: Connection(host, port) {};

@ -18,7 +18,7 @@ public:
const size_t bufferLength = 1024 );
TcpConnection ( const std::string host,
const int port,
const std::string port,
Message *message,
const size_t bufferLength = 1024 );

@ -1,4 +1,4 @@
// gpp sslclient_main.cpp -o sslclient -I../include ../src/Logger.cpp ../src/Thread.cpp ../src/Socket.cpp -lpthread ../src/SocketClient.cpp ../src/Poll.cpp ../src/Connection.cpp ../src/SslConnection.cpp -lssl -lcrypto ../src/TcpConnection.cpp
// gpp sslclient_main.cpp -o sslclient -I../include ../src/Logger.cpp ../src/Thread.cpp ../src/Socket.cpp -lpthread ../src/SocketClient.cpp ../src/Poll.cpp ../src/Connection.cpp ../src/SslConnection.cpp -lssl -lcrypto ../src/TcpConnection.cpp ../src/Addrinfo.cpp
#include "Logger.hpp"
@ -77,7 +77,7 @@ int main(int argc, char* argv[] )
bool finished = false;
SimpleMessage msg(&finished);
SslConnection conn(argv[1], StrToT<int>(argv[2]), &msg);
SslConnection conn(argv[1], argv[2], &msg);
conn.initClientContext();
SocketClient socketClient(&conn);

@ -1,4 +1,4 @@
// gpp sslserver_main.cpp -o sslserver -I../include ../src/Logger.cpp ../src/Socket.cpp -ggdb ../src/SocketServer.cpp ../src/Connection.cpp ../src/Poll.cpp ../src/TcpConnection.cpp ../src/SslConnection.cpp -lssl -lcrypto
// gpp sslserver_main.cpp -o sslserver -I../include ../src/Logger.cpp ../src/Socket.cpp -ggdb ../src/SocketServer.cpp ../src/Connection.cpp ../src/Poll.cpp ../src/TcpConnection.cpp ../src/SslConnection.cpp -lssl -lcrypto ../src/Addrinfo.cpp
#include "Logger.hpp"
#include "Common.hpp"
@ -99,7 +99,7 @@ int main(int argc, char* argv[] )
SslConnection::init();
EchoMessage msg;
SslConnection conn(argv[1], StrToT<int>(argv[2]), &msg);
SslConnection conn(argv[1], argv[2], &msg);
if ( !conn.initServerContext(argv[3], argv[4]) ) {
LOG_STATIC( Logger::ERR, "Failed to init SSL context, exiting...");
SslConnection::destroy();

@ -0,0 +1,133 @@
#include "AddrInfo.hpp"
#include "Logger.hpp"
#include <arpa/inet.h> // inet_ntop
AddrInfo::AddrInfo()
: m_addrInfo(0)
{
TRACE;
}
AddrInfo::~AddrInfo()
{
TRACE;
if (m_addrInfo != 0)
freeaddrinfo(m_addrInfo);
}
bool AddrInfo::getHostInfo( const std::string host,
const std::string port )
{
TRACE;
addrinfo hints;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_socktype = SOCK_DGRAM; // Datagram socket
hints.ai_flags = AI_PASSIVE; // For wildcard IP address
hints.ai_protocol = 0; // Any protocol
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
int status = getaddrinfo(host.c_str(), port.c_str(), &hints, &m_addrInfo);
if (status != 0) {
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message: ", gai_strerror(status))
LOG_END("Error at network address translation.");
return false;
}
return true;
}
addrinfo* AddrInfo::operator[](const unsigned int pos)
{
if (m_addrInfo == 0) {
LOG(Logger::ERR, "Inner address info structure is null.");
return 0;
}
unsigned int counter(0);
addrinfo *it(0);
for ( it = m_addrInfo; it != 0 && counter != pos; it = it->ai_next)
++counter;
if (it == 0) {
LOG(Logger::ERR, "Position is out of range.");
return 0;
}
return it;
}
void AddrInfo::printHostDetails() const
{
TRACE;
int counter(0);
for ( addrinfo *it = m_addrInfo; it != 0; it = it->ai_next) {
counter++;
void *addr;
std::string ipver;
if ( it->ai_family == AF_INET) { // IPv4
sockaddr_in *ipv4 = (sockaddr_in *)it->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else { // IPv6
sockaddr_in6 *ipv6 = (sockaddr_in6 *)it->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
char ipstr[INET6_ADDRSTRLEN];
inet_ntop( it->ai_family, addr, ipstr, sizeof ipstr );
LOG_BEGIN(Logger::DEBUG)
LOG_PROP("Address index", counter)
LOG_PROP("IP version", ipver)
LOG_PROP("IP", ipstr)
LOG_END("Host addresses.");
}
}
bool AddrInfo::convertNameInfo(const addrinfo *addrInfo,
std::string &retAddr,
std::string &retService)
{
TRACE_STATIC;
char hostBuffer[256];
char serviceBuffer[256];
int status = getnameinfo( addrInfo->ai_addr, addrInfo->ai_addrlen,
hostBuffer, sizeof(hostBuffer),
serviceBuffer, sizeof(serviceBuffer),
NI_NAMEREQD );
if ( status != 0 ) {
LOG_BEGIN(Logger::WARNING)
LOG_PROP("Error message: ", gai_strerror(status))
LOG_END_STATIC("Could not resolve hostname.");
return false;
}
retAddr.assign(hostBuffer);
retService.assign(serviceBuffer);
return true;
}

@ -3,7 +3,7 @@
#include "Logger.hpp"
Connection::Connection(std::string host, int port)
Connection::Connection(const std::string host, const std::string port)
: m_host(host)
, m_port(port)
{
@ -24,7 +24,7 @@ std::string Connection::getHost() const
}
int Connection::getPort() const
std::string Connection::getPort() const
{
TRACE;
return m_port;
@ -38,7 +38,7 @@ void Connection::setHost(const std::string host)
}
void Connection::setPort(const int port)
void Connection::setPort(const std::string port)
{
TRACE;
m_port = port;

@ -3,11 +3,16 @@
#include "Logger.hpp"
#include "Common.hpp"
#include "AddrInfo.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h> // inet_ntop
#include <sys/select.h>
#include <string.h> // strerror
#include <errno.h> // errno
Socket::Socket(const int domain,
const int type,
@ -16,8 +21,6 @@ Socket::Socket(const int domain,
, m_domain(domain)
, m_type(type)
, m_protocol(protocol)
, m_addr()
, m_addrLen(0)
{
TRACE;
}
@ -28,8 +31,6 @@ Socket::Socket(const int socket)
, m_domain(-1)
, m_type(-1)
, m_protocol(-1)
, m_addr()
, m_addrLen(0)
{
TRACE;
@ -49,10 +50,11 @@ bool Socket::createSocket()
m_socket = socket(m_domain, m_type, m_protocol);
if ( m_socket == -1 ) {
LOG( Logger::ERR, errnoToString("ERROR creating socket. ").c_str() );
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could not create socket.");
return false;
}
return true;
}
@ -70,40 +72,52 @@ bool Socket::closeSocket()
}
bool Socket::connectToHost( const std::string host,
const std::string port )
bool Socket::connect(struct addrinfo *servinfo)
{
TRACE;
struct addrinfo *results(0);
if ( !Socket::getHostInfo(host, port, &results) )
if (servinfo == 0)
return false;
Socket::printHostDetails(results);
if ( !connectToFirstAddress(results) )
if (::connect(m_socket, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could not connect to peer.");
return false;
}
freeaddrinfo(results);
std::string address, service;
if ( AddrInfo::convertNameInfo( servinfo, address, service) ) {
LOG_BEGIN(Logger::INFO)
LOG_PROP("Host", address)
LOG_PROP("Port", service)
LOG_END("Connected to peer.");
}
return true;
}
bool Socket::bindToHost( const std::string host,
const std::string port )
bool Socket::bind(struct addrinfo *servinfo )
{
TRACE;
struct addrinfo *results(0);
if ( !Socket::getHostInfo(host, port, &results) )
if (servinfo == 0)
return false;
Socket::printHostDetails(results);
if ( !bindToFirstAddress(results) )
if (::bind(m_socket, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could not bind name to socket.");
return false;
}
freeaddrinfo(results);
std::string address, service;
if ( AddrInfo::convertNameInfo( servinfo, address, service) ) {
LOG_BEGIN(Logger::INFO)
LOG_PROP("Host", address)
LOG_PROP("Port", service)
LOG_END("Binded to socket.");
}
return true;
}
@ -113,7 +127,9 @@ bool Socket::listen ( const int maxPendingQueueLen )
TRACE;
if ( ::listen(m_socket, maxPendingQueueLen) == -1 ) {
LOG( Logger::ERR, errnoToString("ERROR listening. ").c_str() );
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could not listen on socket.");
return false;
}
return true;
@ -125,10 +141,11 @@ bool Socket::send ( const void *message, const int length )
TRACE;
if ( ::send(m_socket, message, length, MSG_NOSIGNAL) == -1 ) {
LOG( Logger::ERR, errnoToString("ERROR sending. ").c_str() );
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could not send message to socket.");
return false;
}
return true;
}
@ -138,61 +155,15 @@ bool Socket::receive( void *buffer, const int bufferLen, ssize_t *msgLen )
TRACE;
*msgLen = recv(m_socket, buffer, bufferLen, 0);
return (*msgLen > 0);
}
int Socket::getSocket() const
{
TRACE;
return m_socket;
}
bool Socket::connectToFirstAddress(struct addrinfo *servinfo)
{
TRACE;
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next)
if (::connect(m_socket, it->ai_addr, it->ai_addrlen) != -1) {
std::string address, service;
if ( convertNameInfo( it->ai_addr, it->ai_addrlen, address, service) ) {
LOG( Logger::INFO, std::string("Connected to ").
append(address).append(":").
append(service).c_str() );
}
return true;
}
LOG( Logger::ERR, "Could not connect to host, connection refused." );
if (*msgLen == -1) {
LOG_BEGIN(Logger::ERR)
LOG_PROP("Error message", strerror(errno))
LOG_END("Could not read from socket.");
return false;
}
bool Socket::bindToFirstAddress(struct addrinfo *servinfo )
{
TRACE;
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next)
if (bind(m_socket, it->ai_addr, it->ai_addrlen) == 0) {
memcpy(&m_addr, it->ai_addr, it->ai_addrlen);
m_addrLen = it->ai_addrlen;
std::string address, service;
if ( Socket::convertNameInfo( &m_addr, m_addrLen, address, service) ) {
LOG( Logger::INFO, std::string("Binded to ").
append(address).append(":").
append(service).c_str() );
}
return true;
}
LOG( Logger::ERR, "Could not bind to host. Address already in use." );
return false;
}
void Socket::getPeerName( std::string &host,
std::string &port )
@ -210,90 +181,8 @@ void Socket::getPeerName( std::string &host,
}
bool Socket::getHostInfo( const std::string host,
const std::string port,
struct addrinfo **servinfo)
{
TRACE_STATIC;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6
hints.ai_socktype = SOCK_DGRAM; // Datagram socket
hints.ai_flags = AI_PASSIVE; // For wildcard IP address
hints.ai_protocol = 0; // Any protocol
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
struct addrinfo *results;
int status = getaddrinfo(host.c_str(), port.c_str(), &hints, &results);
if (status != 0) {
LOG_STATIC( Logger::ERR, std::string("Error at network address translation: ").
append(gai_strerror(status)).c_str() ) ;
return false;
}
*servinfo = results;
return true;
}
void Socket::printHostDetails(struct addrinfo *servinfo)
{
TRACE_STATIC;
int counter(0);
for ( struct addrinfo *it = servinfo; it != 0; it = it->ai_next) {
counter++;
void *addr;
std::string ipver;
if ( it->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)it->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)it->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}
char ipstr[INET6_ADDRSTRLEN];
inet_ntop( it->ai_family, addr, ipstr, sizeof ipstr );
LOG_STATIC( Logger::DEBUG, std::string(TToStr(counter)).append(". address is ").
append(ipver).append(": ").
append(ipstr).c_str() );
}
}
bool Socket::convertNameInfo(sockaddr* addr,
socklen_t addrLen,
std::string &retAddr,
std::string &retService)
int Socket::getSocket() const
{
TRACE_STATIC;
char hostBuffer[256];
char serviceBuffer[256];
int status = getnameinfo( addr, addrLen,
hostBuffer, sizeof(hostBuffer),
serviceBuffer, sizeof(serviceBuffer),
NI_NAMEREQD );
if ( status != 0 ) {
LOG_STATIC( Logger::WARNING, std::string("Could not resolve hostname. ").
append(gai_strerror(status)).c_str() );
return false;
}
retAddr.assign(hostBuffer);
retService.assign(serviceBuffer);
return true;
TRACE;
return m_socket;
}

@ -29,7 +29,7 @@ void SslConnection::destroy()
SslConnection::SslConnection ( const int socket,
Message *message,
const size_t bufferLength )
: StreamConnection()
: StreamConnection("invalid", "invalid")
, m_tcpConnection(socket, message, 0)
, m_message(message)
, m_buffer(0)
@ -48,7 +48,7 @@ SslConnection::SslConnection ( const int socket,
SslConnection::SslConnection ( const std::string host,
const int port,
const std::string port,
Message *message,
const size_t bufferLength )
: StreamConnection(host, port)
@ -100,6 +100,8 @@ bool SslConnection::connect()
return false;
}
showCertificates();
return true;
}
@ -194,8 +196,6 @@ bool SslConnection::initServerContext( const std::string certificateFile,
if ( !loadCertificates(certificateFile, privateKeyFile) )
return false;
showCertificates();
return initHandle();
}

@ -3,11 +3,13 @@
#include "Logger.hpp"
#include "Common.hpp"
#include "AddrInfo.hpp"
TcpConnection::TcpConnection ( const int socket,
Message *message,
const size_t bufferLength )
: StreamConnection()
: StreamConnection("invalid", "invalid")
, m_socket(socket)
, m_message(message)
, m_buffer(0)
@ -18,7 +20,7 @@ TcpConnection::TcpConnection ( const int socket,
std::string host, port;
m_socket.getPeerName(host, port);
setHost(host);
setPort(StrToT<int>(port));
setPort(port);
m_buffer = new unsigned char[m_bufferLength];
m_message->setConnection(this);
@ -26,7 +28,7 @@ TcpConnection::TcpConnection ( const int socket,
TcpConnection::TcpConnection ( const std::string host,
const int port,
const std::string port,
Message *message,
const size_t bufferLength )
: StreamConnection(host, port)
@ -63,14 +65,34 @@ Connection* TcpConnection::clone(const int socket)
bool TcpConnection::connect()
{
TRACE;
return m_socket.connectToHost(m_host, TToStr(m_port));
AddrInfo addrInfo;
if (!addrInfo.getHostInfo(m_host, m_port))
return false;
addrInfo.printHostDetails();
if (!m_socket.connect(addrInfo[0]))
return false;
return true;
}
bool TcpConnection::bind()
{
TRACE;
return m_socket.bindToHost(m_host, TToStr(m_port));
AddrInfo addrInfo;
if (!addrInfo.getHostInfo(m_host, m_port))
return false;
addrInfo.printHostDetails();
if (!m_socket.bind(addrInfo[0]))
return false;
return true;
}
@ -87,6 +109,7 @@ int TcpConnection::accept()
sockaddr clientAddr;
socklen_t clientAddrLen;
/// @todo move accept to Socket
int client_socket = ::accept( getSocket(), &clientAddr, &clientAddrLen ) ;
if ( client_socket == -1 ) {
@ -101,8 +124,8 @@ int TcpConnection::accept()
bool TcpConnection::disconnect()
{
TRACE;
if ( getSocket() == -1 )
return false;
// if ( getSocket() == -1 )
// return false;
return m_socket.closeSocket();
}
@ -121,10 +144,7 @@ bool TcpConnection::receive()
ssize_t length;
if ( !m_socket.receive(m_buffer, m_bufferLength, &length) ) {
if (length == -1) {
LOG( Logger::ERR, errnoToString("ERROR reading from socket. ").c_str() );
}
else if (length == 0) {
if (length == 0) {
LOG( Logger::INFO, std::string("Connection closed by ").
append(m_host).append(":").append(TToStr(m_port)).c_str() );
}

@ -19,21 +19,22 @@ if(CXXTEST_FOUND)
generated_main.cpp
Fixture.hpp
test_ArgParse.hpp
test_Common.hpp
test_ConditionalVariable.hpp
test_Multiton.hpp
test_Mutex.hpp
test_ObjectPool.hpp
test_ScopedLock.hpp
test_Semaphore.hpp
test_Singleton_DCLP.hpp
test_Singleton_call_once.hpp
# test_Singleton.hpp Cannot test private member, Ficture.hpp loads it
test_Singleton_meyers.hpp
test_Thread.hpp
test_ThreadPool.hpp
# test_Timer.hpp Takes too much time&buggy
test_Logger.hpp
# test_ArgParse.hpp
# test_Common.hpp
# test_ConditionalVariable.hpp
# test_Multiton.hpp
# test_Mutex.hpp
# test_ObjectPool.hpp
# test_ScopedLock.hpp
# test_Semaphore.hpp
# test_Singleton_DCLP.hpp
# test_Singleton_call_once.hpp
# # test_Singleton.hpp Cannot test private member, Ficture.hpp loads it
# test_Singleton_meyers.hpp
# test_Thread.hpp
# test_ThreadPool.hpp
# # test_Timer.hpp Takes too much time&buggy
)
target_link_libraries(testCppUtils CppUtils gcov)
endif()

@ -27,7 +27,7 @@ class TestFixture : public CxxTest::GlobalFixture
static TestFixture testCommon;
/// @todo remove the dot at prev line from cxxtest
#define TEST_HEADER \
MSG( std::string("\n+++ ").append(__PRETTY_FUNCTION__).append(" +++\n").c_str());

Loading…
Cancel
Save