t2n_exception.cpp command.cpp container.cpp
include_HEADERS = server.hxx socket_server.hxx t2n_exception.hxx client.hxx \
- socket_client.hxx connection.hxx types.hxx socket_handler.hxx command.hxx container.hxx \
- command_client.hxx command_server.hxx
+ socket_client.hxx connection.hxx types.hxx socket_handler.hxx command.hxx container.hxx \
+ command_client.hxx command_server.hxx log.hxx
namespace libt2n
{
+client_connection::client_connection()
+ : connection()
+{
+ set_logging(NULL,none);
+}
+
+/// get pointer to logging stream, returns NULL if no logging needed
+std::ostream* client_connection::get_logstream(log_level_values level)
+{
+ if (logstream && level >= log_level)
+ return logstream;
+}
+
+/// activate logging to the given stream. everything above the given level is logged.
+void client_connection::set_logging(std::ostream *_logstream, log_level_values _log_level)
+{
+ log_level=_log_level;
+ logstream=_logstream;
+}
};
*/
class client_connection : public connection
{
+ private:
+ log_level_values log_level;
+ std::ostream *logstream;
+
public:
- client_connection()
- : connection()
- { }
+ client_connection();
+
+ void set_logging(std::ostream *_logstream, log_level_values _log_level);
+
+ std::ostream* get_logstream(log_level_values level);
};
}
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+
#include "command.hxx"
-#include <boost/serialization/export.hpp>
-using namespace libt2n;
+#include <boost/serialization/export.hpp>
-BOOST_CLASS_EXPORT(result)
-BOOST_CLASS_EXPORT(command)
+BOOST_CLASS_EXPORT(libt2n::result)
+BOOST_CLASS_EXPORT(libt2n::command)
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
- {
- std::cerr << "ser: command" << std::endl;
- }
+ { }
public:
/// this calls the wanted target function on the server
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
-#include <boost/serialization/export.hpp>
#include "command_server.hxx"
#include "container.hxx"
+#include "log.hxx"
using namespace std;
/// handle a command including deserialization and answering
void command_server::handle_packet(const std::string& packet, server_connection* conn)
{
+ OBJLOGSTREAM(s,debug,"handling packet from connection " << conn->get_id());
+
// deserialize packet
istringstream ifs(packet);
boost::archive::binary_iarchive ia(ifs);
#include <string>
#include <sstream>
+#include <iostream>
#include "connection.hxx"
#include <string>
+#include "types.hxx"
+
+
namespace libt2n
{
protected:
connection()
- { closed=false; }
+ { closed=false; }
std::string buffer;
virtual void real_write(const std::string& data)=0;
+ virtual std::ostream* get_logstream(log_level_values level)=0;
+
public:
virtual ~connection()
{ close(); }
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+
#include "container.hxx"
#include <boost/serialization/export.hpp>
-using namespace libt2n;
+BOOST_CLASS_EXPORT(libt2n::result_container)
+BOOST_CLASS_EXPORT(libt2n::command_container)
+
+namespace libt2n
+{
+
+template<class Archive>
+void result_container::serialize(Archive & ar, const unsigned int version)
+{
+ // When the class Archive corresponds to an output archive, the
+ // & operator is defined similar to <<. Likewise, when the class Archive
+ // is a type of input archive the & operator is defined similar to >>.
+
+ ar & BOOST_SERIALIZATION_NVP(result_type);
+ ar & BOOST_SERIALIZATION_NVP(res);
+ ar & BOOST_SERIALIZATION_NVP(ex);
+}
+
+/// deletes the carried result or exception objects
+result_container::~result_container()
+{
+ if (res)
+ delete res;
+ if (ex)
+ delete ex;
+}
+
+/** @brief returns the result or throw the carried exception.
+ ATTENTION: the result object is deleted in the destructor
+*/
+result* result_container::get_result(void)
+{
+ if (result_type==exception)
+ ex->do_throw();
+ return res;
+}
+
+template<class Archive>
+void command_container::serialize(Archive & ar, const unsigned int version)
+{
+ ar & BOOST_SERIALIZATION_NVP(cmd);
+}
+
+/// deletes the carried command
+command_container::~command_container()
+{
+ if (cmd)
+ delete cmd;
+}
-BOOST_CLASS_EXPORT(result_container)
-BOOST_CLASS_EXPORT(command_container)
+} // namespace libt2n
#ifndef __LIBT2N_CONTAINER
#define __LIBT2N_CONTAINER
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/archive/xml_oarchive.hpp>
+#include <boost/archive/xml_iarchive.hpp>
+#include <boost/serialization/serialization.hpp>
+
#include "command.hxx"
#include "t2n_exception.hxx"
t2n_exception *ex;
friend class boost::serialization::access;
- // When the class Archive corresponds to an output archive, the
- // & operator is defined similar to <<. Likewise, when the class Archive
- // is a type of input archive the & operator is defined similar to >>.
template<class Archive>
- void serialize(Archive & ar, const unsigned int version)
- {
- ar & BOOST_SERIALIZATION_NVP(result_type);
- ar & BOOST_SERIALIZATION_NVP(res);
- ar & BOOST_SERIALIZATION_NVP(ex);
- }
+ void serialize(Archive & ar, const unsigned int version);
public:
result_container()
result_container(t2n_exception *_ex)
{ set_exception(_ex); }
+ ~result_container();
+
void set_result(result *_res)
{ res=_res; ex=0; result_type=regular; }
void set_exception(t2n_exception *_ex)
{ res=0; ex=_ex; result_type=exception; }
- /** @brief returns the result or throw the carried exception.
- ATTENTION: the result object is deleted in the destructor
- */
- result* get_result(void)
- {
- if (result_type==exception)
- ex->do_throw();
- return res;
- }
-
- /// deletes the carried result or exception objects
- ~result_container()
- {
- if (res)
- delete res;
- if (ex)
- delete ex;
- }
+ result* get_result(void);
};
/** @brief contains a command
friend class boost::serialization::access;
template<class Archive>
- void serialize(Archive & ar, const unsigned int version)
- {
- std::cerr << "ser: command_container" << std::endl;
- ar & BOOST_SERIALIZATION_NVP(cmd);
- }
+ void serialize(Archive & ar, const unsigned int version);
public:
command_container()
command_container(command *_cmd)
{ cmd=_cmd; }
+ ~command_container();
+
/// return the contained command
command* get_command()
{ return cmd; }
-
- ~command_container()
- {
- if (cmd)
- delete cmd;
- }
};
} // namespace libt2n
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2006 by Gerd v. Egidy *
+ * gve@intra2net.com *
+ * *
+ * This library is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Lesser General Public License version *
+ * 2.1 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+ ***************************************************************************/
+#ifndef __LIBT2N_LOG
+#define __LIBT2N_LOG
+
+#include <iostream>
+#include <sstream>
+
+#define LOGGING
+
+#ifdef LOGGING
+
+#define LOGSTREAM(level,pipe) \
+ do { \
+ std::ostream* streamptr; \
+ if ((streamptr=get_logstream(level))!=NULL) \
+ (*streamptr) << pipe << std::endl; \
+ } while (0)
+
+#define OBJLOGSTREAM(obj,level,pipe) \
+ do { \
+ std::ostream* streamptr; \
+ if ((streamptr=obj.get_logstream(level))!=NULL) \
+ (*streamptr) << pipe << std::endl; \
+ } while (0)
+
+#define EXCEPTIONSTREAM(loglevel,exception,pipe) \
+ do { \
+ std::ostringstream ostr; \
+ ostr << pipe; \
+ std::ostream* streamptr; \
+ if ((streamptr=get_logstream(loglevel))!=NULL) \
+ (*streamptr) << ostr.str() << std::endl; \
+ throw exception(ostr.str()); \
+ } while (0)
+
+#else
+
+#define LOGSTREAM(level,pipe)
+#define OBJLOGSTREAM(obj,level,pipe)
+#define EXCEPTIONSTREAM(loglevel,exception,pipe)
+
+#endif
+
+#endif
#include <sstream>
#include "server.hxx"
+#include "log.hxx"
namespace libt2n
{
+server_connection::server_connection(int _timeout)
+ : connection()
+{
+ set_timeout(_timeout);
+ reset_timeout();
+ connection_id=0;
+ my_server=0;
+}
+
+
+/// get pointer to logging stream, returns NULL if no logging needed
+std::ostream* server_connection::get_logstream(log_level_values level)
+{
+ if (my_server != NULL)
+ return my_server->get_logstream(level);
+}
+
+/// check if timeout is expired, close connection if so
void server_connection::check_timeout()
{
- if (timeout != -1 && last_action_time+timeout >= time(NULL))
+ if (timeout != -1 && last_action_time+timeout < time(NULL))
+ {
+ LOGSTREAM(debug,"timeout on connection " << connection_id << ", closing");
this->close();
+ }
}
+/// reset the timeout, e.g. if something is received
void server_connection::reset_timeout()
{
last_action_time=time(NULL);
}
+server::server()
+{
+ set_default_timeout(30);
+ set_logging(NULL,none);
+ next_id=1;
+}
+
server::~server()
{
std::map<unsigned int, server_connection*>::iterator ie=connections.end();
newconn->set_id(cid);
newconn->set_server(this);
connections[cid]=newconn;
+
+ LOGSTREAM(debug,"new connection accepted, id: " << cid);
+
return cid;
}
+/// activate logging to the given stream. everything above the given level is logged.
+void server::set_logging(std::ostream *_logstream, log_level_values _log_level)
+{
+ log_level=_log_level;
+ logstream=_logstream;
+}
+
/**
@brief Gets a connection by id
if (i->second->is_closed() && !i->second->packet_available())
{
// closed and no usable data in buffer -> remove
+ LOGSTREAM(debug,"removing conneciton " << i->first << " because it is closed and no more data waiting");
+
delete i->second;
connections.erase(i);
i=connections.begin();
}
}
+/** @brief get a complete data packet from any client. The packet is removed from the
+ connection buffer.
+ @param[out] data the data package
+ @param[out] conn_id the connection id we got this packet from
+ @retval true if packet found
+*/
bool server::get_packet(std::string& data, unsigned int& conn_id)
{
// todo: this is somehow unfair: the first connections in the map get checked more
for(std::map<unsigned int, server_connection*>::iterator i=connections.begin(); i != ie; i++)
if (i->second->get_packet(data))
{
+ LOGSTREAM(debug,"got packet (" << data.size() << " bytes) from connection " << i->first);
+
conn_id=i->first;
return true;
}
return false;
}
-void server::log(log_level_values level, const char* message)
+/// get pointer to logging stream, returns NULL if no logging needed
+std::ostream* server::get_logstream(log_level_values level)
{
if (logstream && level >= log_level)
- (*logstream) << message << std::endl;
+ return logstream;
}
-
};
{ connection_id=_connection_id; }
protected:
- server_connection(int _timeout)
- : connection()
- {
- set_timeout(_timeout);
- reset_timeout();
- connection_id=0;
- my_server=0;
- }
-
server *my_server;
+ server_connection(int _timeout);
+
+ std::ostream* get_logstream(log_level_values level);
+
public:
- /// check if timeout is expired, close connection if so
void check_timeout();
-
- /// reset the timeout, e.g. if something is received
void reset_timeout();
-
void set_timeout(int _timeout)
{ timeout=_timeout; }
protected:
std::map<unsigned int, server_connection*> connections;
- server()
- {
- set_default_timeout(30);
- set_logging(NULL,none);
- next_id=1;
- }
+ server();
virtual bool fill_connection_buffers(void)=0;
int get_default_timeout(void)
{ return default_timeout; }
- /// activate logging to the given stream. everything above the given level is logged.
- void set_logging(std::ostream *_logstream, log_level_values _log_level)
- {
- log_level=_log_level;
- logstream=_logstream;
- }
+ void set_logging(std::ostream *_logstream, log_level_values _log_level);
server_connection* get_connection(unsigned int conn_id);
bool get_packet(std::string& data)
{ unsigned int x; return get_packet(data,x); }
- /** @brief get a complete data packet from any client. The packet is removed from the
- connection buffer.
- @param[out] data the data package
- @param[out] conn_id the connection id we got this packet from
- @retval true if packet found
- */
bool get_packet(std::string& data, unsigned int& conn_id);
- /// write a message to the log if logging is enabled
- void log(log_level_values level, const std::string& message)
- { log(level,message.c_str()); }
- /// write a message to the log if logging is enabled
- void log(log_level_values level, const char* message);
+ std::ostream* get_logstream(log_level_values level);
};
}
std::string server;
int port;
+ std::ostream* get_logstream(log_level_values level)
+ { return client_connection::get_logstream(level); }
+
public:
socket_client_connection(const std::string& _server, int _port, int _max_retries=max_retries_default);
socket_client_connection(const std::string& _path, int _max_retries=max_retries_default);
#include "socket_handler.hxx"
#include "t2n_exception.hxx"
+#include "log.hxx"
using namespace std;
/* fast reuse enable */
if (setsockopt(sock,SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
- {
- string err="error setting socket option: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_communication_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_communication_error,"error setting socket option: " << strerror(errno));
/* keepalive enable */
if (setsockopt(sock,SOL_SOCKET, SO_KEEPALIVE, &i, sizeof(i)) < 0)
- {
- string err="error setting socket option: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_communication_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_communication_error,"error setting socket option: " << strerror(errno));
/* close on exec */
int fdflags;
fdflags=fcntl(sock,F_GETFD, 0);
if (fdflags < 0)
- {
- string err="fcntl error on socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_communication_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_communication_error,"fcntl error on socket: " << strerror(errno));
+
fdflags |= FD_CLOEXEC;
if (fcntl(sock,F_SETFD,fdflags) < 0)
- {
- string err="fcntl error on socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_communication_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_communication_error,"fcntl error on socket: " << strerror(errno));
/* non-blocking mode */
int flflags;
flflags=fcntl(sock,F_GETFL,0);
if (flflags < 0)
- {
- string err="fcntl error on socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_communication_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_communication_error,"fcntl error on socket: " << strerror(errno));
+
flflags |= O_NONBLOCK;
if (fcntl(sock,F_SETFL,flflags) < 0)
- {
- string err="fcntl error on socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_communication_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_communication_error,"fcntl error on socket: " << strerror(errno));
}
/// close the underlying socket connection. Don't call directly, use the version provided
else if (errno == EINTR)
{
// interrupted, try again
+ LOGSTREAM(debug,"EINTR received on read(), trying again");
try_again=true;
}
else
{
- log(error,string("error reading from socket : ")+strerror(errno));
+ LOGSTREAM(error,"error reading from socket : " << strerror(errno));
// TODO: exception?
return false;
}
// End-of-file
if (nbytes == 0 && !try_again)
{
+ LOGSTREAM(debug,"0 bytes received on read(), closing connection");
close();
return false;
}
// Data read -> store it
if (nbytes > 0)
+ {
buffer.assign(socket_buffer,nbytes);
+ LOGSTREAM(debug,nbytes << " read");
+ }
// more data waiting -> recurse
if (data_waiting(0))
rtn == -1 && (errno == EAGAIN || errno == EINTR))
{
usleep (80000);
- log(debug,"resuming write() call after EAGAIN or EINTR");
+ LOGSTREAM(debug,"resuming write() call after EAGAIN or EINTR");
}
if (rtn == -1)
{
- log(error,string("write() returned ")+strerror(errno));
+ LOGSTREAM(error,"write() returned " << strerror(errno));
// TODO: exception?
return;
}
else if (rtn != write_size)
{
- ostringstream msg;
- msg << "write() wrote " << rtn << " bytes, should have been "
- << write_size << " (complete: " << data.size() << ")";
-
- log(error,msg.str());
+ LOGSTREAM(error,"write() wrote " << rtn << " bytes, should have been "
+ << write_size << " (complete: " << data.size() << ")");
// TODO: exception?
return;
offset += write_size;
}
+ LOGSTREAM(debug,"wrote " << data.size() << " bytes");
+
return;
}
#ifndef __LIBT2N_SOCKET_HANDLER
#define __LIBT2N_SOCKET_HANDLER
+#include <iostream>
+
#include "types.hxx"
namespace libt2n
void set_socket_options(int sock);
- void log(log_level_values level, const std::string& message)
- { log(level,message.c_str()); }
- virtual void log(log_level_values level, const char* message)
- { return; }
+ virtual std::ostream* get_logstream(log_level_values level)
+ { return NULL; }
void socket_write(const std::string& data);
#include "socket_server.hxx"
#include "t2n_exception.hxx"
+#include "log.hxx"
using namespace std;
/* Create the socket. */
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0)
- {
- string err="error opening socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error opening socket: " << strerror(errno));
set_socket_options(sock);
sockaddr.sin_port = htons(port);
if (inet_aton(ip.c_str(),&sockaddr.sin_addr) == 0)
- {
- string err="failed listening on invalid ip ";
- err+=ip;
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"failed listening on invalid ip " << ip);
if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
- {
- string err="error binding socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error binding socket: " << strerror(errno));
start_listening();
}
/* Create the socket. */
sock = socket (PF_UNIX, SOCK_STREAM, 0);
if (sock < 0)
- {
- string err="error opening socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error opening socket: " << strerror(errno));
set_socket_options(sock);
unlink (unix_name.sun_path);
if (bind (sock, (struct sockaddr *) &unix_name, sizeof (unix_name)) < 0)
- {
- string err="error binding socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error binding socket: " << strerror(errno));
/* change permissions */
if (chmod (unix_name.sun_path, filemode) != 0)
- {
- string err="error changing permission: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error changing permission: " << strerror(errno));
if (!user.empty() && !group.empty())
{
struct passwd *socket_user = getpwnam (user.c_str());
if (socket_user == NULL)
- {
- string err="error getting socket user: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
-
+ EXCEPTIONSTREAM(error,t2n_server_error,"error getting socket user: " << strerror(errno));
+
struct group *socket_group = getgrnam (group.c_str());
if (socket_group == NULL)
- {
- string err="error getting socket group: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
-
+ EXCEPTIONSTREAM(error,t2n_server_error,"error getting socket group: " << strerror(errno));
+
if (chown (unix_name.sun_path, socket_user->pw_uid, socket_group->gr_gid) != 0)
- {
- string err="error changing socket ownership: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error changing socket ownership: " << strerror(errno));
}
start_listening();
void socket_server::start_listening()
{
if (listen (sock, 5) < 0)
- {
- string err="error listening to socket: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"error listening to socket: " << strerror(errno));
/* clear & insert server sock into the fd_tab to prepare select */
FD_ZERO(&connection_set);
{
if (errno == EAGAIN)
{
- log(error, "accept error (EAGAIN): no connection waiting");
+ LOGSTREAM(error,"accept error (EAGAIN): no connection waiting");
return;
}
/* default: break */
- string err="error accepting connection: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
+ EXCEPTIONSTREAM(error,t2n_server_error,"error accepting connection: " << strerror(errno));
}
FD_SET (newsock, &connection_set);
ret=0;
}
else
- {
- string err="select error: ";
- err+=strerror(errno);
- log(error, err);
- throw t2n_server_error(err);
- }
+ EXCEPTIONSTREAM(error,t2n_server_error,"select error: " << strerror(errno));
}
if (ret > 0)
FD_CLR(sock, &connection_set);
}
-void socket_server_connection::log(log_level_values level, const char* message)
-{
- if(my_server)
- {
- ostringstream msg;
- msg << "connection id " << get_id() << ": " << message;
- my_server->log(level,msg.str().c_str());
- }
-}
-
/// close this connection. complete data waiting in the buffer can still be retrieved.
void socket_server_connection::close()
{
void remove_connection_socket(int sock);
protected:
- void log(log_level_values level, const std::string& message)
- { log(level,message.c_str()); }
- void log(log_level_values level, const char* message)
- { server::log(level,message); }
+ std::ostream* get_logstream(log_level_values level)
+ { return server::get_logstream(level); }
public:
socket_server(int port, const std::string& ip="0.0.0.0");
: server_connection(_timeout), socket_handler(_sock,_stype)
{ }
- void log(log_level_values level, const char* message);
+ std::ostream* get_logstream(log_level_values level)
+ { return server_connection::get_logstream(level); }
void real_write(const std::string& data)
{ socket_write(data); }
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
+
+#include <boost/archive/binary_oarchive.hpp>
+#include <boost/archive/binary_iarchive.hpp>
+#include <boost/serialization/serialization.hpp>
+
#include <container.hxx>
#include <socket_client.hxx>
#include <socket_server.hxx>
#include <command_client.hxx>
#include <command_server.hxx>
-#include <boost/serialization/serialization.hpp>
-#include <boost/serialization/level.hpp>
-#include <boost/serialization/tracking.hpp>
-#include <boost/serialization/export.hpp>
-
using namespace std;
using namespace libt2n;
using namespace CppUnit;
}
};
+
class testfunc_cmd : public libt2n::command
{
private:
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
- cerr << "ser: testfunc_cmd" << endl;
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(libt2n::command);
ar & BOOST_SERIALIZATION_NVP(param);
}
}
};
+#include <boost/serialization/export.hpp>
BOOST_CLASS_EXPORT(testfunc_cmd)
BOOST_CLASS_EXPORT(testfunc_res)
// child
{
socket_server ss("./socket");
- ss.set_logging(&cerr,debug);
command_server cs(ss);
// max 10 sec
// wait till server is up
sleep(1);
socket_client_connection sc("./socket");
+ sc.set_logging(&cerr,debug);
command_client cc(sc);
result_container rc;