From 9591262f6204c31f622f57be28b3d727470e2fce Mon Sep 17 00:00:00 2001 From: deva Date: Wed, 22 Aug 2007 10:25:43 +0000 Subject: Dummy server created. --- server/src/Makefile.am | 24 +++ server/src/configuration.cc | 67 +++++++++ server/src/configuration.h | 88 +++++++++++ server/src/debug.h | 51 +++++++ server/src/exception.cc | 77 ++++++++++ server/src/exception.h | 65 +++++++++ server/src/log.cc | 43 ++++++ server/src/log.h | 40 +++++ server/src/pracrod.cc | 243 +++++++++++++++++++++++++++++++ server/src/server.cc | 107 ++++++++++++++ server/src/server.h | 32 ++++ server/src/tcpsocket.cc | 346 ++++++++++++++++++++++++++++++++++++++++++++ server/src/tcpsocket.h | 183 +++++++++++++++++++++++ server/src/tostring.cc | 161 +++++++++++++++++++++ server/src/tostring.h | 114 +++++++++++++++ 15 files changed, 1641 insertions(+) create mode 100644 server/src/Makefile.am create mode 100644 server/src/configuration.cc create mode 100644 server/src/configuration.h create mode 100644 server/src/debug.h create mode 100644 server/src/exception.cc create mode 100644 server/src/exception.h create mode 100644 server/src/log.cc create mode 100644 server/src/log.h create mode 100644 server/src/pracrod.cc create mode 100644 server/src/server.cc create mode 100644 server/src/server.h create mode 100644 server/src/tcpsocket.cc create mode 100644 server/src/tcpsocket.h create mode 100644 server/src/tostring.cc create mode 100644 server/src/tostring.h (limited to 'server/src') diff --git a/server/src/Makefile.am b/server/src/Makefile.am new file mode 100644 index 0000000..2ede22d --- /dev/null +++ b/server/src/Makefile.am @@ -0,0 +1,24 @@ + +bin_PROGRAMS = pracrod + +pracrod_LDADD = $(LD_EFENCE) $(PQXX_LIBS) $(CONFIG_LIBS) + +pracrod_CXXFLAGS = $(PQXX_CXXFLAGS) $(CONFIG_CXXFLAGS) + +pracrod_SOURCES = \ + pracrod.cc \ + configuration.cc \ + exception.cc \ + log.cc \ + server.cc \ + tcpsocket.cc \ + tostring.cc + +EXTRA_DIST = \ + configuration.h \ + debug.h \ + exception.h \ + log.h \ + server.h \ + tcpsocket.h \ + tostring.h diff --git a/server/src/configuration.cc b/server/src/configuration.cc new file mode 100644 index 0000000..e6d24a9 --- /dev/null +++ b/server/src/configuration.cc @@ -0,0 +1,67 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * configuration.cc + * + * Tue Aug 15 23:57:13 CEST 2006 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "configuration.h" + +#include "debug.h" + +#include "tostring.h" + +Pentominos::Configuration::Configuration(std::string filename) +{ + this->filename = filename; + + reload(); +} + +void Pentominos::Configuration::reload() + throw(ConfigurationException) +{ + try { + readFile(this->filename.c_str()); + } catch(libconfig::FileIOException) { + throw ConfigurationException("Could not read config file: File does not exist."); + } catch(libconfig::ParseException &e) { + throw ConfigurationException(std::string("Error when parsing the config file in line ") + + toString(e.getLine()) + ": " + e.getError()); + } +} + + +static Pentominos::Configuration *_config = NULL; + +Pentominos::Configuration *Pentominos::config() + throw(ConfigurationException) +{ + if(_config == NULL) + throw ConfigurationException("Configuration has not yet been set."); + return _config; +} + +void Pentominos::initConfig(Pentominos::Configuration *config) +{ + _config = config; +} diff --git a/server/src/configuration.h b/server/src/configuration.h new file mode 100644 index 0000000..38dd233 --- /dev/null +++ b/server/src/configuration.h @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * configuration.h + * + * Tue Aug 15 23:57:12 CEST 2006 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __ARTEFACT_CONFIGURATION_H__ +#define __ARTEFACT_CONFIGURATION_H__ + +#include +#include + +#include "exception.h" + +namespace Pentominos { + + /** + * This exception is thrown by Configuration when reload fails. + */ + class ConfigurationException: public Pentominos::Exception { + public: + ConfigurationException(std::string reason) : + Pentominos::Exception(reason) {} + }; + + /** + * This is the pentominos configuration class.\n + * It simply wraps the libconfig c++ interface. It can be found at + * http://www.hyperrealm.com/libconfig/libconfig.html\n + * To find out how the interface works, see + * http://www.hyperrealm.com/libconfig/libconfig_manual.html#The-C_002b_002b-API + */ + class Configuration : public libconfig::Config { + public: + /** + * Constructor.\n + * @param filename The filename to be loaded. + */ + Configuration(std::string filename); + + /** + * reload, simply reloads the configuration file attached to the configuration + * object. + */ + void reload() throw(ConfigurationException); + + private: + std::string filename; + }; + + /** + * Initialize the global configuration.\n + * This function sets the Configuration global pointer, that can be reaced through + * the Pentominos::config variable. + * @param config The value of the Configuration pointer. + */ + void initConfig(Configuration *config); + + /** + * This function returns the global configuration object pointer.\n + * Use Pentominos::initConfig to set it.\n + * @return The pointer to the global configuration. + */ + Configuration *config() + throw(ConfigurationException); +}; + +#endif/*__ARTEFACT_CONFIGURATION_H__*/ diff --git a/server/src/debug.h b/server/src/debug.h new file mode 100644 index 0000000..9c49f67 --- /dev/null +++ b/server/src/debug.h @@ -0,0 +1,51 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * debug.h + * + * Tue Mar 27 11:06:45 CEST 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __ARTEFACT_DEBUG_H__ +#define __ARTEFACT_DEBUG_H__ + +#ifdef HAVE_CONFIG +// For USE_EFENCE +#include +#ifdef USE_EFENCE +#include +#include +#include +#include + +// Lazy static alocations makes efence freak out. +// Use this to use hardcoded values instead. +// Currently it disables: +// - gethostbyname +// - getsockname +// - getpeername +// - iconv +//#define BYPASS_STATICALLOCATIONS + +#endif/*USE_EFENCE*/ +#endif/*HAVE_CONFIG*/ + +#endif/*__ARTEFACT_DEBUG_H__*/ diff --git a/server/src/exception.cc b/server/src/exception.cc new file mode 100644 index 0000000..3e3bd46 --- /dev/null +++ b/server/src/exception.cc @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * exception.cc + * + * Mon Mar 19 11:33:15 CET 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "exception.h" + +#include "debug.h" + +#include "log.h" + +Pentominos::Exception::Exception(std::string what) +{ + Pentominos::log(what); + _what = what; + +} + +const char* Pentominos::Exception::what() const throw() +{ + return _what.c_str(); +} + + +#ifdef TEST_EXCEPTION + +class MyException : public Pentominos::Exception { +public: + MyException() : + Pentominos::Exception("MyException has been thrown") {} +}; + +class MyExtException : public Pentominos::Exception { +public: + MyExtException(std::string thingy) : + Pentominos::Exception("MyExtException has been thrown: " + thingy) {} +}; + +int main() +{ + try { + throw MyException(); + } catch( MyException &e ) { + printf("%s\n", e.what()); + } + + try { + throw MyExtException("Yeaaah!"); + } catch( MyExtException &e ) { + printf("%s\n", e.what()); + } + + return 0; +} + +#endif/*TEST_EXCEPTION*/ diff --git a/server/src/exception.h b/server/src/exception.h new file mode 100644 index 0000000..4a0ce23 --- /dev/null +++ b/server/src/exception.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * exception.h + * + * Mon Mar 19 11:22:22 CET 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __ARTEFACT_EXCEPTION_H__ +#define __ARTEFACT_EXCEPTION_H__ + +#include + +#include + +namespace Pentominos { + + /** + * Exception is the base class for all Pentominos exceptions + */ + class Exception : public std::exception { + public: + /** + * The constuctor sets the error message (retained by the what() call) and + * adds an entry to the syslog, using the Pentominos::log interface. + */ + Exception(std::string what); + + /** + * Destructor + */ + virtual ~Exception() throw() {} + + /** + * what is used to gain textual information about the exception. + * @return A const char pointer to a zero terminated string containing + * textual information about the exception. + */ + virtual const char* what() const throw(); + + private: + std::string _what; + }; + +}; + +#endif/*__ARTEFACT_EXCEPTION_H__*/ diff --git a/server/src/log.cc b/server/src/log.cc new file mode 100644 index 0000000..384077b --- /dev/null +++ b/server/src/log.cc @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * log.cc + * + * Tue Oct 24 17:44:47 CEST 2006 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "log.h" + +#include "debug.h" + +#include + +/* + void openlog(const char *ident, int option, int facility); // Optional + void syslog(int priority, const char *format, ...); + void closelog(void); // Optional +*/ + +void Pentominos::log(std::string message) +{ + syslog(LOG_CONS, // Write to console if error sending to system logger. + message.c_str()); +} diff --git a/server/src/log.h b/server/src/log.h new file mode 100644 index 0000000..e1c1be0 --- /dev/null +++ b/server/src/log.h @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * log.h + * + * Tue Oct 24 17:44:46 CEST 2006 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __ARTEFACT_LOG_H__ +#define __ARTEFACT_LOG_H__ + +#include + +namespace Pentominos { + /** + * log appends a message to the syslog queue.\n + * @param message An STL string containing the string to be appended. + */ + void log(std::string message); +}; + +#endif/*__ARTEFACT_LOG_H__*/ diff --git a/server/src/pracrod.cc b/server/src/pracrod.cc new file mode 100644 index 0000000..c9fa58b --- /dev/null +++ b/server/src/pracrod.cc @@ -0,0 +1,243 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * pracrod.cc + * + * Wed Aug 22 12:15:59 CEST 2007 + * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup + * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +// For ETC +#include + +// For setuid and setgid +#include +#include + +// For signal +#include + +// For errno and strerror +#include + +#include + +#include +#include + +// For getpwent and getgrent +#include +#include +#include + +// For getopt_long and friends +#include + +#include "configuration.h" + +#include "server.h" + +#include "tcpsocket.h" + +static const char version_str[] = +"Pracro server v" VERSION "\n" +; + +static const char copyright_str[] = +"Copyright (C) 2006-2007 Bent Bisballe Nyeng - Aasimon.org.\n" +"This is free software. You may redistribute copies of it under the terms of\n" +"the GNU General Public License .\n" +"There is NO WARRANTY, to the extent permitted by law.\n" +"\n" +"Written by Bent Bisballe Nyeng (deva@aasimon.org)\n" +; + +static const char usage_str[] = +"Usage: %s [options]\n" +"Options:\n" +" -c, --config file Read configfile from 'file'\n" +" -f, --foreground Run in foreground mode (non-background mode)\n" +" -u, --user user Run as 'user' (overrides the configfile)\n" +" -g, --group group Run as 'group' (overrides the configfile)\n" +" -v, --version Print version information and exit.\n" +" -h, --help Print this message and exit.\n" +; + +void reload(int fisk) +{ + int port; + printf("Reload!\n"); + port = Pentominos::config()->lookup("port"); + Pentominos::config()->reload(); + + { // Force wake the server process for reinitialization. + Pentominos::TCPSocket socket; + socket.connect("localhost", port); + } +} + +int main(int argc, char *argv[]) +{ + int c; + char *configfile = NULL; + char *user = NULL; + char *group = NULL; + bool foreground = false; + + int option_index = 0; + while(1) { + int this_option_optind = optind ? optind : 1; + static struct option long_options[] = { + {"foreground", no_argument, 0, 'f'}, + {"config", required_argument, 0, 'c'}, + {"user", required_argument, 0, 'u'}, + {"group", required_argument, 0, 'g'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'v'}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "hvfc:u:g:", long_options, &option_index); + + if (c == -1) + break; + + switch(c) { + case 'c': + configfile = strdup(optarg); + break; + + case 'f': + foreground = true; + break; + + case 'u': + user = strdup(optarg); + break; + + case 'g': + group = strdup(optarg); + break; + + case '?': + case 'h': + printf(version_str); + printf(usage_str, argv[0]); + return 0; + + case 'v': + printf(version_str); + printf(copyright_str); + return 0; + + default: + break; + } + } + + char *cfname = NULL; + if(!configfile) cfname = ETC"/pracrod.conf"; + else cfname = configfile; + Pentominos::Configuration conf(cfname); + Pentominos::initConfig(&conf); + + if(!user) { + std::string userstr; + try { + userstr = (std::string)Pentominos::config()->lookup("user"); + user = strdup(userstr.c_str()); + } catch( ... ) { + printf("User not found in config.\n"); + } + } + + if(user) { + // Fetch user id + int uid = -1; + struct passwd *p = getpwent(); + while(p) { + if(strcmp(p->pw_name, user) == 0) uid = p->pw_uid; + p = getpwent(); + } + if(uid == -1) { + fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user); + return 1; + } + + if(setuid(uid) == -1) { + fprintf(stderr, "Could not switch to user %s: %s\n", user, strerror(errno)); + return 1; + } + } + + if(!group) { + std::string groupstr; + try { + groupstr = (std::string)Pentominos::config()->lookup("group"); + group = strdup(groupstr.c_str()); + } catch( ... ) { + printf("Group not found in config.\n"); + } + + } + + if(group) { + // Fetch group id + int gid = -1; + struct group *g = getgrent(); + while(g) { + if(strcmp(g->gr_name, group) == 0) gid = g->gr_gid; + g = getgrent(); + } + if(gid == -1) { + fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group); + return 1; + } + + if(setgid(gid) == -1) { + fprintf(stderr, "Could not switch to group %s: %s\n", group, strerror(errno)); + return 1; + } + } + + if(!foreground) { + daemon(0,0); + signal (SIGTERM, SIG_IGN); + signal (SIGINT, SIG_IGN); + } else { + printf("Running in foreground mode.\n"); + } + + // Create callback to reload conf files. + signal (SIGHUP, reload); + + signal(SIGCLD, SIG_IGN); // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes + // (ellers kommer der kernel-brok) + + // Activate the server main loop. + server(); + + // Clean up + if(configfile) free(configfile); + if(user) free(user); + if(group) free(group); + + return 0; +} diff --git a/server/src/server.cc b/server/src/server.cc new file mode 100644 index 0000000..7f78f45 --- /dev/null +++ b/server/src/server.cc @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * server.cc + * + * Wed Aug 22 12:16:03 CEST 2007 + * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup + * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "server.h" + +#include "tcpsocket.h" +#include + +#include + +// For fork +#include +#include + +#include "configuration.h" + +static void connection(Pentominos::TCPSocket &socket) +{ + printf("Got connection...\n"); +} + +void server() +{ + int port; + try { + port = Pentominos::config()->lookup("port"); + } catch( ... ) { + fprintf(stderr, "Could not read port."); + return; + } + + Pentominos::TCPSocket *socket; + + try { + socket = new Pentominos::TCPSocket(); + socket->listen(port); + } catch (Pentominos::Exception &e) { + fprintf(stderr, "Error during parsing:\n%s\n", + e.what()); + delete socket; + return; + } + + while(socket->connected()) { + + { // Reload if new port i assigned. + int old_port = port; + try { + port = Pentominos::config()->lookup("port"); + } catch( ... ) { + fprintf(stderr, "Could not read port."); + return; + } + + if(port != old_port) { + // Start listening on the new port + delete socket; + socket = new Pentominos::TCPSocket(); + socket->listen(port); + } + } + + Pentominos::TCPSocket child = socket->accept(); + if(child.connected()) { + switch(fork()) { + case -1: // error + fprintf(stderr, "Could not fork: %s\n", strerror(errno)); + break; + + case 0: // child + socket->disconnect(); + connection(child); + delete socket; + return; + + default: // parent + break; + } + } + } + + delete socket; + fprintf(stderr, "Oups... dropped out of the main loop\n"); +} diff --git a/server/src/server.h b/server/src/server.h new file mode 100644 index 0000000..78f5ed3 --- /dev/null +++ b/server/src/server.h @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * server.h + * + * Wed Aug 22 12:16:03 CEST 2007 + * Copyright 2007 Bent Bisballe Nyeng, Lars Bisballe Jensen and Peter Skaarup + * deva@aasimon.org, elsenator@gmail.com and piparum@piparum.dk + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_SERVER_H__ +#define __PRACRO_SERVER_H__ + +void server(); + +#endif/*__PRACRO_SERVER_H__*/ diff --git a/server/src/tcpsocket.cc b/server/src/tcpsocket.cc new file mode 100644 index 0000000..19470fe --- /dev/null +++ b/server/src/tcpsocket.cc @@ -0,0 +1,346 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tcpsocket.cc + * + * Thu Oct 19 10:24:25 CEST 2006 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "tcpsocket.h" + +#include "debug.h" + +#include "tostring.h" + +// for gethostbyname +#include + +// for inet_addr +#include +#include +#include + +// for connect, listen, bind and accept +#include +#include + +// For socket +#include +#include + +// For TCP +#include +#include +#include + +// For inet_ntoa +#include +#include +#include + +// For close +#include + +#include +#include +#include + +// For ioctl +#include + +// For socket and friends +#include +#include +#include +#include + +// For fcntl +#include +#include + +Pentominos::TCPSocket::TCPSocket() + throw(TCPSocketException) +{ + if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + throw TCPSocketException(strerror(errno)); + } + isconnected = false; +} + +Pentominos::TCPSocket::~TCPSocket() +{ + disconnect(); +} + + +static int _listen(int sockfd, int backlog){return listen(sockfd, backlog);} +void Pentominos::TCPSocket::listen(unsigned short int port) + throw(TCPListenException) +{ + + if(sock == -1) { + throw TCPListenException("Socket not initialized."); + } + + if(isconnected) { + throw TCPListenException("Socket already connected."); + } + + struct sockaddr_in socketaddr; + memset((char *) &socketaddr, sizeof(socketaddr), 0); + socketaddr.sin_family = AF_INET; + socketaddr.sin_port = htons(port); + socketaddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if(bind(sock, (struct sockaddr*)&socketaddr, sizeof(socketaddr)) == -1) { + throw TCPListenException(std::string("bind failed - ") + strerror(errno)); + } + + if(_listen(sock, 5) == -1) { + throw TCPListenException(std::string("listen failed - ") + strerror(errno)); + } + + isconnected = true; +} + + +static int _accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{return accept(sockfd, addr, addrlen);} +Pentominos::TCPSocket Pentominos::TCPSocket::accept() + throw(TCPAcceptException) +{ + TCPSocket child; + + if(sock == -1) { + throw TCPAcceptException("Socket not initialized."); + } + + if(!isconnected) { + throw TCPAcceptException("Socket not connected."); + } + + // accept new connection and get its connection descriptor + struct sockaddr_in ssocketaddr; + int csalen = sizeof(ssocketaddr); + + child.disconnect(); // We need to close the existing socket + child.sock = _accept(sock, (struct sockaddr*)&ssocketaddr, (socklen_t*)&csalen); + + if (child.sock == -1) { + throw TCPAcceptException(std::string("accept failed - ") + strerror(errno)); + } + + child.isconnected = true; + return child; +} + + +static int _connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +{return connect(sockfd, serv_addr, addrlen);} +void Pentominos::TCPSocket::connect(std::string addr, unsigned short int port) + throw(TCPConnectException) + +{ + if(isconnected) { + throw TCPConnectException("Socket already connected.", "", ""); + } + +#ifndef BYPASS_STATICALLOCATIONS + // Do DNS lookup + char *ip; + struct in_addr **addr_list; + struct hostent *he; + he = gethostbyname(addr.c_str()); + if(!he || !he->h_length) { + throw TCPConnectException(addr, toString(port), + std::string("host lookup failed: ") + hstrerror(h_errno)); + } + + addr_list = (struct in_addr **)he->h_addr_list; + // Get first value. We know for sure that there are at least one. + ip = inet_ntoa(*addr_list[0]); +#else/*BYPASS_STATICALLOCATIONS*/ + char *ip = "127.0.0.1"; +#endif/*BYPASS_STATICALLOCATIONS*/ + + struct sockaddr_in socketaddr; + memset((char *) &socketaddr, sizeof(socketaddr), 0); + socketaddr.sin_family = AF_INET; + socketaddr.sin_port = htons(port); + socketaddr.sin_addr.s_addr = inet_addr(ip); + + if(_connect(sock, (struct sockaddr*)&socketaddr, sizeof(socketaddr))) { + throw TCPConnectException(addr, toString(port), hstrerror(h_errno)); + } + + isconnected = true; +} + +void Pentominos::TCPSocket::disconnect() +{ + if(sock != -1) { + close(sock); + sock = -1; + } + isconnected = false; +} + +bool Pentominos::TCPSocket::connected() +{ + return sock != -1 && isconnected; +} + +int Pentominos::TCPSocket::read(char *buf, int size) + throw(TCPReadException) +{ + int res = 0; + + if(sock == -1) { + throw TCPReadException("Socket not initialized."); + } + + if(!isconnected) { + throw TCPReadException("Socket is not connected."); + } + + /* + if( (res = recv(sock, buf, size, MSG_WAITALL)) == -1 ) { + throw TCPReadException(strerror(errno)); + } + */ + + // Wait until something is ready to be read ( peek'a'loop ). + errno = EAGAIN; + while( recv(sock, buf, 1, MSG_PEEK) == -1 && errno == EAGAIN) { + sleep(1); + } + + // Now read it + if( (res = recv(sock, buf, size, MSG_DONTWAIT)) == -1 ) { + throw TCPReadException(strerror(errno)); + } + + return res; +} + +int Pentominos::TCPSocket::write(char *data, int size) + throw(TCPWriteException) +{ + if(sock == -1) { + throw TCPWriteException("Socket not initialized."); + } + + if(!isconnected) { + throw TCPWriteException("Socket is not connected."); + } + + int res; + if( (res = send(sock, data, size, MSG_WAITALL)) == -1 ) { + throw TCPWriteException(strerror(errno)); + } + + return res; +} + +std::string Pentominos::TCPSocket::srcaddr() + throw(TCPNameException) +{ + std::string addr; + +#ifndef BYPASS_STATICALLOCATIONS + struct sockaddr_in name; + socklen_t namelen = sizeof(name); + if(getpeername(sock, (sockaddr*)&name, &namelen) == -1) { + throw TCPNameException(strerror(errno)); + } + + addr = inet_ntoa(name.sin_addr); +#else/*BYPASS_STATICALLOCATIONS*/ + addr = "127.0.0.1"; +#endif/*BYPASS_STATICALLOCATIONS*/ + + return addr; +} + +std::string Pentominos::TCPSocket::dstaddr() + throw(TCPNameException) +{ + std::string addr; + +#ifndef BYPASS_STATICALLOCATIONS + struct sockaddr_in name; + socklen_t namelen = sizeof(name); + if(getsockname(sock, (sockaddr*)&name, &namelen) == -1) { + throw TCPNameException(strerror(errno)); + } + + addr = inet_ntoa(name.sin_addr); +#else/*BYPASS_STATICALLOCATIONS*/ + addr = "127.0.0.1"; +#endif/*BYPASS_STATICALLOCATIONS*/ + + return addr; +} + +#ifdef TEST_TCPSOCKET + +int main() +{ + char buf[32]; + + switch(fork()) { + case -1: // error + fprintf(stderr, "Could not fork: %s\n", strerror(errno)); + return 1; + + case 0: // child + try { + Pentominos::TCPSocket client; + sleep(1); // We need to wait for the listen socket to be created. + client.connect("localhost", 12345); + sprintf(buf, "hello"); + client.write(buf, sizeof(buf)); + printf("Sent: [%s]\n", buf); + } catch( Pentominos::Exception &e ) { + fprintf(stderr, "%s\n", e.what()); + return 1; + } + break; + + default: // parent + try { + Pentominos::TCPSocket listen_sock; + listen_sock.listen(12345); + Pentominos::TCPSocket sock = listen_sock.accept(); + sock.read(buf, sizeof(buf)); + printf("Got: [%s]\n", buf); + if(std::string(buf) != "hello") return 1; + } catch( Pentominos::Exception &e ) { + fprintf(stderr, "%s\n", e.what()); + return 1; + } + break; + } + + return 0; +} + +#endif/*TEST_TCPSOCKET*/ diff --git a/server/src/tcpsocket.h b/server/src/tcpsocket.h new file mode 100644 index 0000000..f392a2c --- /dev/null +++ b/server/src/tcpsocket.h @@ -0,0 +1,183 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tcpsocket.h + * + * Thu Oct 19 10:24:25 CEST 2006 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __ARTEFACT_TCPSOCKET_H__ +#define __ARTEFACT_TCPSOCKET_H__ + +#include + +#include "exception.h" + +namespace Pentominos { + + /** + * This exception is thrown by TCPSocket when the socket creation fails. + */ + class TCPSocketException: public Pentominos::Exception { + public: + TCPSocketException(std::string reason) : + Pentominos::Exception("Could not create socket: " + reason) {} + }; + + /** + * This exception is thrown by TCPSocket when listen fails. + */ + class TCPListenException: public Pentominos::Exception { + public: + TCPListenException(std::string reason) : + Pentominos::Exception("Listen failed: " + reason) {} + }; + + /** + * This exception is thrown by TCPSocket when accept fails. + */ + class TCPAcceptException: public Pentominos::Exception { + public: + TCPAcceptException(std::string reason) : + Pentominos::Exception("Accept failed: " + reason) {} + }; + + /** + * This exception is thrown by TCPSocket when connection fails. + */ + class TCPConnectException: public Pentominos::Exception { + public: + TCPConnectException(std::string host, std::string port, std::string reason) : + Pentominos::Exception("Could not connect to " + host + ":" + port + ": " + reason) {} + }; + + /** + * This exception is thrown by TCPSocket when reading fails. + */ + class TCPReadException: public Pentominos::Exception { + public: + TCPReadException(std::string reason) : + Pentominos::Exception("TCPSocket could not read data: " + reason) {} + }; + + /** + * This exception is thrown by TCPSocket when writing fails. + */ + class TCPWriteException: public Pentominos::Exception { + public: + TCPWriteException(std::string reason) : + Pentominos::Exception("TCPSocket could not write data: " + reason) {} + }; + + /** + * This exception is thrown by TCPSocket when there is an error in name lookup. + */ + class TCPNameException: public Pentominos::Exception { + public: + TCPNameException(std::string reason) : + Pentominos::Exception("TCPSocket could not get name: " + reason) {} + }; + + /** + * This class is used to commumicate through a TCP/IP connection, wether it + * is a server (listening) or a client (transmitting). + */ + class TCPSocket { + public: + /** + * Constructor. Creates a new tcp socket. + */ + TCPSocket() throw(TCPSocketException); + + /** + * Destructor. Closes the tcp socket. + */ + ~TCPSocket(); + + /** + * Sets the socket in listen mode.\n + * @param port The port number on which to listen. + */ + void listen(unsigned short int port) throw(TCPListenException); + + /** + * Accept an incoming connection.\n + * The call is blocking and returns only when an incoming connection is received.\n + * The socket must be in listen mode in order for this call to work.\n + * Multiple accepts can be made on the same listening socket. + * @return A connected TCPSocket ready to communicate. + */ + TCPSocket accept() throw(TCPAcceptException); + + /** + * Connects to a host for data transmission. + * @param addr The address of the host to connect to. + * @param port The portnumber of the host to connect to. + */ + void connect(std::string addr, unsigned short int port) throw(TCPConnectException); + + /** + * Disconnect the socket. + */ + void disconnect(); + + /** + * Tells whether the socket is connected or not. + * @return true if the socket is connected, false if not. + */ + bool connected(); + + /** + * Reads bytes from the socket into a buffer. + * @param buf The buffer into which the data will be written. + * @param size The maximum number of bytes to read in (the size of the buffer). + * @return The actual number of bytes read. + */ + int read(char *buf, int size) throw(TCPReadException); + + /** + * Writes bytes from a buffer to the socket. + * @param data The buffer from which the data will be read. + * @param size The number of bytes to write. + * @return The actual number of bytes written. + */ + int write(char *data, int size) throw(TCPWriteException); + + /** + * Get the source address of the socket (IP address not DNS name). + * @return An STL string containing the source address. + */ + std::string srcaddr() throw(TCPNameException); + + /** + * Get the destination address of the socket (IP address not DNS name). + * @return An STL string containing the destination address. + */ + std::string dstaddr() throw(TCPNameException); + + private: + bool isconnected; + int sock; + }; + +}; + +#endif/*__ARTEFACT_TCPSOCKET_H__*/ diff --git a/server/src/tostring.cc b/server/src/tostring.cc new file mode 100644 index 0000000..e218a32 --- /dev/null +++ b/server/src/tostring.cc @@ -0,0 +1,161 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tostring.cc + * + * Thu Mar 29 13:16:13 CEST 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "tostring.h" + +#include "debug.h" + +#include + +std::string Pentominos::toString(std::string s) +{ + return s; +} + +std::string Pentominos::toString(char c) +{ + char buf[32]; + sprintf(buf, "%c", c); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(unsigned char c) +{ + char buf[32]; + sprintf(buf, "%c", c); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(short int si) +{ + char buf[32]; + sprintf(buf, "%d", si); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(short unsigned int su) +{ + char buf[32]; + sprintf(buf, "%u", su); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(int li) +{ + char buf[32]; + sprintf(buf, "%ld", li); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(unsigned int lu) +{ + char buf[32]; + sprintf(buf, "%lu", lu); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(bool b) +{ + if(b) return "true"; + else return "false"; +} + +std::string Pentominos::toString(float f, unsigned int precision) +{ + char buf[100]; + char format[12]; + sprintf(format, "%%.%uf", precision); + sprintf(buf, format, f); + std::string out = buf; + return buf; + return ""; +} + +std::string Pentominos::toString(double d, unsigned int precision) +{ + char buf[100]; + char format[12]; + sprintf(format, "%%.%uf", precision); + sprintf(buf, format, d); + std::string out = buf; + return buf; +} + +std::string Pentominos::toString(long double ld, unsigned int precision) +{ + char buf[100]; + char format[12]; + sprintf(format, "%%.%uLg", precision); + sprintf(buf, format, ld); + std::string out = buf; + return buf; +} + +#ifdef TEST_TOSTRING +/* Compile: + * c++ -DTEST_TOSTRING tostring.cc -o test_tostring + */ +using namespace Pentominos; + +int main() +{ + std::string s = "string"; + char c = -4; + unsigned char uc = 'a'; + short int si = 0x8000; + short unsigned int su = 0xffff; + long int li = 0x80000000L; + long unsigned int lu = 0xffffffffL; + bool b = true; + float f = 0.1; + double d = 0.1; + long double ld = 0.1; + +std::string str = + "[" + Pentominos::toString(s) + + "] [" + Pentominos::toString(c) + + "] [" + Pentominos::toString(uc) + + "] [" + Pentominos::toString(si) + + "] [" + Pentominos::toString(su) + // + "] [" + Pentominos::toString(li) + // + "] [" + Pentominos::toString(lu) + + "] [" + Pentominos::toString(b) + + "] [" + Pentominos::toString(f, 10) + + "] [" + Pentominos::toString(d, 18) + + "] [" + Pentominos::toString(ld, 36) + + "]"; + + printf("%s\n", str.c_str()); + + return 0; +} +#endif/*TEST_TOSTRING*/ diff --git a/server/src/tostring.h b/server/src/tostring.h new file mode 100644 index 0000000..0b63fb3 --- /dev/null +++ b/server/src/tostring.h @@ -0,0 +1,114 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + * tostring.h + * + * Thu Mar 29 13:16:13 CEST 2007 + * Copyright 2006 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Artefact. + * + * Artefact is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Artefact 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Artefact; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __ARTEFACT_TOSTRING_H__ +#define __ARTEFACT_TOSTRING_H__ + +#include + +namespace Pentominos { + /** + * toString converts a nonstring variable into an STL string. + * @param s A string, converted into a... string... + * @return The STL string containing the converted value. + */ + std::string toString(std::string s); + + /** + * toString converts a nonstring variable into an STL string. + * @param c A char, converted into a string. + * @return The STL string containing the converted value. + */ + std::string toString(char c); + + /** + * toString converts a nonstring variable into an STL string. + * @param c A unsigned char, converted into a string. + * @return The STL string containing the converted value. + */ + std::string toString(unsigned char c); + + /** + * toString converts a nonstring variable into an STL string. + * @param si A short integer, converted into a string. + * @return The STL string containing the converted value. + */ + std::string toString(short int si); + + /** + * toString converts a nonstring variable into an STL string. + * @param su An unsigned short integer, converted into a string. + * @return The STL string containing the converted value. + */ + std::string toString(short unsigned int su); + + /** + * toString converts a nonstring variable into an STL string. + * @param li A long integer, converted into a string. + * @return The STL string containing the converted value. + */ + std::string toString(int li); + + /** + * toString converts a nonstring variable into an STL string. + * @param lu An unsigned long integer, converted into a string. + * @return The STL string containing the converted value. + */ + std::string toString(unsigned int lu); + + /** + * toString converts a nonstring variable into an STL string. + * @param b A boolean value, converted into a string (true/false). + * @return The STL string containing the converted value. + */ + std::string toString(bool b); + + /** + * toString converts a nonstring variable into an STL string. + * @param f A floating point value, converted into a string. + * @param precision The precision to use when converting. + * @return The STL string containing the converted value. + */ + std::string toString(float f, unsigned int precision = 8); + + /** + * toString converts a nonstring variable into an STL string. + * @param d A double precision floating point value, converted into a string. + * @param precision The precision to use when converting. + * @return The STL string containing the converted value. + */ + std::string toString(double d, unsigned int precision = 16); + + /** + * toString converts a nonstring variable into an STL string. + * @param ld A long double precision floating point value, converted into a string. + * @param precision The precision to use when converting. + * @return The STL string containing the converted value. + */ + std::string toString(long double ld, unsigned int precision = 32); +}; + +#endif/*__ARTEFACT_TOSTRING_H__*/ -- cgit v1.2.3