server.cpp

Go to the documentation of this file.
00001 /**
00002  *  Copyright (C) 2004-2005 Alo Sarv <madcat_@users.sourceforge.net>
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /** \file server.cpp Implementation of Detail::Server class */
00020 
00021 #include <hn/hnprec.h>
00022 #include "server.h"                        // class interface
00023 #include "tag.h"                           // Tags for reading/writing
00024 #include "opcodes.h"                       // opcodes
00025 #include "serverlist.h"
00026 #include <boost/lexical_cast.hpp>
00027 #include <boost/algorithm/string/trim.hpp>
00028 #include <boost/tokenizer.hpp>
00029 
00030 namespace Detail {
00031 
00032 IMPLEMENT_EVENT_TABLE(Server, Server*, int);
00033 
00034 // Standard constructor
00035 Server::Server(IPV4Address addr) : Object(&ServerList::instance(), "server"),
00036 m_addr(addr), m_failedCount(), m_preference(), m_ping(), m_lastPing(),
00037 m_maxUsers(), m_softLimit(), m_hardLimit(), m_udpFlags(), m_users(), m_files(),
00038 m_lowIdUsers(), m_lastUdpQuery(), m_pingInProgress() {
00039         // Sanity checking
00040         CHECK_THROW_MSG(addr.getAddr(), "Server IP may not be null.");
00041         CHECK_THROW_MSG(addr.getPort(), "Server Port may not be null.");
00042 
00043         setName(m_addr.getStr());
00044 }
00045 
00046 // Destructor
00047 Server::~Server() {}
00048 
00049 // Construct and load from stream
00050 Server::Server(std::istream &i) : Object(&ServerList::instance(), "server"),
00051 m_failedCount(), m_preference(), m_ping(), m_lastPing(), m_maxUsers(),
00052 m_softLimit(), m_hardLimit(), m_udpFlags(), m_users(), m_files(),
00053 m_lowIdUsers(), m_lastUdpQuery(), m_pingInProgress() {
00054         m_addr.setAddr(Utils::getVal<uint32_t>(i));
00055         m_addr.setPort(Utils::getVal<uint16_t>(i));
00056 
00057         // Sanity checking
00058         CHECK_THROW_MSG(m_addr.getAddr(), "Invalid ip NULL found for server.");
00059         CHECK_THROW_MSG(m_addr.getPort(),"Invalid port NULL found for server.");
00060 
00061         uint32_t tagcount = Utils::getVal<uint32_t>(i);
00062         while (tagcount-- && i) {
00063                 try {
00064                         Tag t(i);
00065                         switch (t.getOpcode()) {
00066                                 case ST_NAME:
00067                                         setName(t.getStr());
00068                                         break;
00069                                 case ST_DESC:
00070                                         m_desc = t.getStr();
00071                                         break;
00072                                 case ST_DYNIP:
00073                                         m_dynip = t.getStr();
00074                                         break;
00075                                 case ST_VERSION:
00076                                         m_version = t.getStr();
00077                                         break;
00078                                 case ST_FAIL:
00079                                         m_failedCount = t.getInt();
00080                                         break;
00081                                 case ST_PREFERENCE:
00082                                         m_preference = t.getInt();
00083                                         break;
00084                                 case ST_PING:
00085                                         m_ping = t.getInt();
00086                                         break;
00087                                 case ST_LASTPING:
00088                                         m_lastPing = t.getInt();
00089                                         break;
00090                                 case ST_MAXUSERS:
00091                                         m_maxUsers = t.getInt();
00092                                         break;
00093                                 case ST_SOFTLIMIT:
00094                                         m_softLimit = t.getInt();
00095                                         break;
00096                                 case ST_HARDLIMIT:
00097                                         m_hardLimit = t.getInt();
00098                                         break;
00099                                 case ST_UDPFLAGS:
00100                                         m_udpFlags = t.getInt();
00101                                         break;
00102                                 case ST_LOWIDUSRS:
00103                                         m_lowIdUsers = t.getInt();
00104                                         break;
00105                                 case ST_AUXPORTLIST:
00106                                         addAuxPorts(t.getStr());
00107                                         break;
00108                                 default:
00109                                         if (!t.getName().compare("users")) {
00110                                                 m_users = t.getInt();
00111                                                 break;
00112                                         }
00113                                         if (!t.getName().compare("files")) {
00114                                                 m_files = t.getInt();
00115                                                 break;
00116                                         }
00117                                         if (!t.getName().compare("maxusers")) {
00118                                                 m_maxUsers = t.getInt();
00119                                                 break;
00120                                         }
00121                                         if (!t.getName().compare("lowusers")) {
00122                                                 m_lowIdUsers = t.getInt();
00123                                                 break;
00124                                         }
00125                                         warnUnHandled("server.met", t);
00126                                         break;
00127                         }
00128                 } catch (TagError &er) {
00129                         logWarning(
00130                                 boost::format("Invalid tag in server.met: %s")
00131                                 % er.what()
00132                         );
00133                 }
00134         }
00135         if (getName() == "server") {
00136                 setName(m_addr.getStr());
00137         }
00138 }
00139 
00140 std::ostream& operator<<(std::ostream &o, const Server &s) {
00141         Utils::putVal<uint32_t>(o, s.getAddr().getAddr());
00142         Utils::putVal<uint16_t>(o, s.getAddr().getPort());
00143         std::ostringstream tmp;
00144         uint32_t tagcount = 0;
00145         if (s.getName().size()) {
00146                 tmp << Tag(ST_NAME, s.getName());
00147                 ++tagcount;
00148         }
00149         if (s.getDesc().size()) {
00150                 tmp << Tag(ST_DESC, s.getDesc());
00151                 ++tagcount;
00152         }
00153         if (s.getDynIp().size()) {
00154                 tmp << Tag(ST_DYNIP, s.getDynIp());
00155                 ++tagcount;
00156         }
00157         if (s.getVersion().size()) {
00158                 tmp << Tag(ST_VERSION, s.getVersion());
00159                 ++tagcount;
00160         }
00161         if (s.getFailedCount()) {
00162                 tmp << Tag(ST_FAIL, s.getFailedCount());
00163                 ++tagcount;
00164         }
00165         if (s.getPreference()) {
00166                 tmp << Tag(ST_PREFERENCE, s.getPreference());
00167                 ++tagcount;
00168         }
00169         if (s.getPing()) {
00170                 tmp << Tag(ST_PING, s.getPing());
00171                 ++tagcount;
00172         }
00173         if (s.getLastPing()) {
00174                 tmp << Tag(ST_LASTPING, s.getLastPing());
00175                 ++tagcount;
00176         }
00177         if (s.getMaxUsers()) {
00178                 tmp << Tag(ST_MAXUSERS, s.getMaxUsers());
00179                 ++tagcount;
00180         }
00181         if (s.getSoftLimit()) {
00182                 tmp << Tag(ST_SOFTLIMIT, s.getSoftLimit());
00183                 ++tagcount;
00184         }
00185         if (s.getHardLimit()) {
00186                 tmp << Tag(ST_HARDLIMIT, s.getHardLimit());
00187                 ++tagcount;
00188         }
00189         if (s.getUdpFlags()) {
00190                 tmp << Tag(ST_UDPFLAGS, s.getUdpFlags());
00191                 ++tagcount;
00192         }
00193         if (s.getUsers()) {
00194                 tmp << Tag("users", s.getUsers());
00195                 ++tagcount;
00196         }
00197         if (s.getFiles()) {
00198                 tmp << Tag("files", s.getFiles());
00199                 ++tagcount;
00200         }
00201         if (s.getMaxUsers()) {
00202                 tmp << Tag("maxusers", s.getMaxUsers());
00203                 ++tagcount;
00204         }
00205         if (s.getLowIdUsers()) {
00206                 tmp << Tag("lowusers", s.getLowIdUsers());
00207                 ++tagcount;
00208         }
00209         if (s.getAuxPorts().size()) {
00210                 using namespace boost::algorithm;
00211                 std::string buf;
00212                 std::vector<uint16_t>::const_iterator it = s.m_auxPorts.begin();
00213                 while (it != s.m_auxPorts.end()) {
00214                         buf += boost::lexical_cast<std::string>(*it++) + ",";
00215                 }
00216                 trim_right_if(buf, is_any_of(","));
00217                 tmp << Tag(ST_AUXPORTLIST, buf);
00218                 ++tagcount;
00219         }
00220         Utils::putVal(o, tagcount);
00221         Utils::putVal(o, tmp.str(), tmp.str().size());
00222         return o;
00223 }
00224 
00225 void Server::addAuxPorts(const std::string &ports) try {
00226         typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00227 
00228         boost::char_separator<char> sep(",");
00229         tokenizer tok(ports, sep);
00230 
00231         for (tokenizer::iterator i = tok.begin(); i != tok.end(); ++i) {
00232                 m_auxPorts.push_back(boost::lexical_cast<uint16_t>(*i));
00233         }
00234 } catch (boost::bad_lexical_cast&) {
00235         logWarning("Invalid AUXPORT tag in server.met (cast failed)");
00236 }
00237 MSVC_ONLY(;)
00238 
00239 } // namespace Detail