From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- .../x-cvsweb-markup/index.html | 658 +++++++++++++++++++++ 1 file changed, 658 insertions(+) create mode 100644 cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html (limited to 'cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html') diff --git a/cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html b/cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html new file mode 100644 index 00000000..581f9cd2 --- /dev/null +++ b/cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html @@ -0,0 +1,658 @@ + + + +code/nelns/naming_service/naming_service.cpp - view - 1.21 + +
[BACK] Return to naming_service.cpp + CVS log [TXT][DIR] Up to Nevrax / code / nelns / naming_service

File: Nevrax / code / nelns / naming_service / naming_service.cpp (download)
+Revision 1.21, Tue Mar 26 09:45:11 2002 UTC (2 months, 4 weeks ago) by lecroart +
Branch: MAIN +
Changes since 1.20: +3 -2 + lines
+CHANGED: unified the command format
+
+

/** \file naming_service.cpp
+ * Naming Service (NS)
+ *
+ * $Id: naming_service.cpp,v 1.21 2002/03/26 09:45:11 lecroart Exp $
+ */
+
+/* Copyright, 2000 Nevrax Ltd.
+ *
+ * This file is part of NEVRAX NeL Network Services.
+ * NEVRAX NeL Network Services 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, or (at your option)
+ * any later version.
+ *
+ * NEVRAX NeL Network Services 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 NEVRAX NeL Network Services; see the file COPYING. If not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif // HAVE_CONFIG_H
+
+#ifndef NELNS_CONFIG
+#define NELNS_CONFIG ""
+#endif // NELNS_CONFIG
+
+#ifndef NELNS_LOGS
+#define NELNS_LOGS ""
+#endif // NELNS_LOGS
+
+//
+// Includes
+//
+
+#include "nel/misc/types_nl.h"
+
+#include <list>
+#include <string>
+
+#include "nel/misc/debug.h"
+#include "nel/misc/command.h"
+#include "nel/misc/displayer.h"
+
+#include "nel/net/service.h"
+
+//
+// Namespaces
+//
+
+using namespace std;
+
+using namespace NLMISC;
+using namespace NLNET;
+
+
+//
+// Structures
+//
+
+struct CServiceEntry
+{
+        CServiceEntry (TSockId sock, CInetAddress a, string n, TServiceId s) : SockId(sock), Addr(a), Name(n), SId (s) { }
+
+        TSockId                        SockId;                        // the connection between the service and the naming service
+        CInetAddress        Addr;                        // address to send to the service who wants to lookup this service
+        string                        Name;                        // name of the service
+        TServiceId                SId;                        // id of the service
+};
+
+
+//
+// Variables
+//
+
+list<CServiceEntry>     RegisteredServices;                /// List of all registred services
+
+uint16                          MinBasePort = 51000;        /// Ports begin at 51000
+uint16                          MaxBasePort = 52000;        /// (note: in this implementation there can be no more than 1000 services)
+
+const TServiceId        BaseSId = 128;                        /// Allocated SIds begin at 128 (except for Agent Service)
+
+
+//
+// Functions
+//
+
+void displayRegisteredServices (CCallbackNetBase &netbase)
+{
+        nlinfo ("Display the %d registered services :", RegisteredServices.size());
+        for (list<CServiceEntry>::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                nlinfo ("> %s '%s' %s-%hu '%s'", (*it).SockId->asString().c_str(), netbase.hostAddress((*it).SockId).asString().c_str(), (*it).Name.c_str(), (uint16)(*it).SId, (*it).Addr.asString().c_str());
+        }
+        nlinfo ("End ot the list");
+}
+
+
+
+/*
+ * Helper procedure for cbLookupAlternate and cbUnregister.
+ * Note: name is used for a LOGS.
+ */
+list<CServiceEntry>::iterator doRemove (list<CServiceEntry>::iterator it)
+{
+        nldebug ("Unregister the service %s-%hu '%s'", (*it).Name.c_str(), (uint16)(*it).SId, (*it).Addr.asString().c_str());
+        
+        // tell to everybody that this service is unregistered
+
+        CMessage msgout ("UNB");
+        msgout.serial ((*it).Name);
+        msgout.serial ((*it).SId);
+        msgout.serial ((*it).Addr);
+        CNetManager::send ("NS", msgout, 0);
+        nlinfo ("Broadcast the Unregistration to everybody");
+
+        // remove the service from the registered service list
+        return RegisteredServices.erase (it);
+}
+
+void doUnregisterService (TServiceId sid)
+{
+        list<CServiceEntry>::iterator it;
+        for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                if ((*it).SId == sid)
+                {
+                        // found it, remove it
+                        doRemove (it);
+                        return;
+                }
+        }
+        nlwarning ("Service %hu not found", (uint16)sid);
+}
+
+void doUnregisterService (TSockId from)
+{
+        list<CServiceEntry>::iterator it;
+        for (it = RegisteredServices.begin(); it != RegisteredServices.end ();)
+        {
+                if ((*it).SockId == from)
+                {
+                        // it's possible that one "from" have more than one registred service, so we have to find in all the list
+                        // found it, remove it
+                        it = doRemove (it);
+                }
+                else
+                {
+                        it++;
+                }
+        }
+}
+
+void doUnregisterService (const CInetAddress &addr)
+{
+        list<CServiceEntry>::iterator it;
+        for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                if ((*it).Addr == addr)
+                {
+                        // found it, remove it
+                        doRemove (it);
+                        return;
+                }
+        }
+        nlwarning ("Service %s not found", addr.asString().c_str());
+}
+
+
+/*
+ * Helper function for cbLookupSId and cbLookupAlternateSId.                    *********** OUT OF DATE ***************
+ * Returns NULL if service not found
+ */
+void doLookup (const string &sname, TServiceId sid, TSockId from, CCallbackNetBase &netbase, bool sendAll, bool useSId)
+{
+        nlstop;
+
+        string name;
+
+        if (useSId)
+                name = toString (sid);
+        else
+                name = sname;
+
+        nlinfo ("Lookup for service '%s' for '%s'...", name.c_str(), netbase.hostAddress(from).asString().c_str());
+
+        displayRegisteredServices (netbase);
+
+        // Send list
+        vector<CInetAddress> addrs;
+        list<CServiceEntry>::iterator it;
+        for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                if ((useSId && (*it).SId == sid) || (!useSId && (*it).Name == name))
+                {
+                        addrs.push_back ((*it).Addr);
+                        // if it only want one, stop now to search
+                        if (!sendAll) break;
+                }
+        }
+
+        if (addrs.size()==0)
+                nldebug ("Service %s is not found", name.c_str());
+        else if (addrs.size()==1)
+                nldebug ("Service %s is at %s", name.c_str(), addrs[0].asString().c_str());
+        else
+                nldebug ("%d Services %s found", addrs.size(), name.c_str());
+        
+        CMessage msgout ("LK");
+        msgout.serialCont (addrs);
+        netbase.send (msgout, from);
+}
+
+/**
+ * Callback for service look-up.                        *********** OUT OF DATE ***************
+ *
+ * Message expected : LK
+ * - Name of service to find (string)
+ *
+ * Message emitted : LK
+ * - Validity time in seconds, or 0 if service not found (uint16)
+ * - Address of service if service found, otherwise nothing (CInetAddress)
+ *
+ * \todo Olivier: Select the best service provider, not the first one in the list
+ */
+static void cbLookup (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        nlstop;
+
+        string name;
+        msgin.serial (name);
+        
+        // Find and return a service
+        doLookup (name, 0, from, netbase, false, false);
+}
+
+/**
+ * Callback for alternate service look-up when a service is not responding                      *********** OUT OF DATE ***************
+ *
+ * Message expected : LA
+ * - Name of service (string)
+ * - Address of server not responding (CInetAddress)
+ *
+ * Message emitted : no name (NS)
+ * - Validity time in seconds, or 0 if service not found (uint16)
+ * - Address of service if service found, otherwise nothing (CInetAddress)
+ */
+static void cbLookupAlternate (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        nlstop;
+
+        string name;
+        CInetAddress addr;
+        msgin.serial (name);
+        msgin.serial (addr);
+
+        nlinfo ("Server %s looks down, looking-up for alternative service %s", addr.asString().c_str(), name.c_str() );
+
+        // Unregister down server
+        doUnregisterService (addr);
+
+        // Find and return another servive
+        doLookup (name, 0, from, netbase, false, false);
+}
+
+/**
+ * Callback for service look-up for all corresponding to a name.                        *********** OUT OF DATE ***************
+ *
+ * Message expected : LKA
+ * - Name of service to find (string)
+ *
+ * Message emitted : no name (ALKA)
+ * - List of addresses (vector<CInetAddress>)
+ */
+static void cbLookupAll (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        nlstop;
+
+        // Receive name
+        string name;
+        msgin.serial (name);
+
+        // Find and return a service
+        doLookup (name, 0, from, netbase, true, false);
+}
+
+/**
+ * Callback for service look-up by identifier                           *********** OUT OF DATE ***************
+ *
+ * Message expected : LKI
+ * - Identifier of service to find (TServiceId)
+ *
+ * Message emitted : no name (NS)
+ * - Validity time in seconds, or 0 if service not found (uint16)
+ * - Address of service if service found, otherwise nothing (CInetAddress)
+ *
+ * \todo Olivier: Select the best service provider, not the first one in the list
+ */
+static void cbLookupSId (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        nlstop;
+
+        // Receive id
+        TServiceId sid;
+        msgin.serial (sid);
+
+        // Find and return a service
+        doLookup ("", sid, from, netbase, false, true);
+}
+
+
+
+/*
+ * Helper function for cbRegister.
+ * If alloc_sid is true, sid is ignored
+ * Returns false in case of failure of sid allocation or bad sid provided
+ * Note: the reply is included in this function, because it must be done before things such as syncUniTime()
+ */
+bool doRegister (const string &name, const CInetAddress &addr, TServiceId sid, TSockId from, CCallbackNetBase &netbase)
+{
+        // find if the service is not already registered
+        uint8 ok = true;
+        bool needRegister = true;
+        for (list<CServiceEntry>::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                if ((*it).Addr.asIPString() == addr.asIPString() )
+                {
+                        // we already have a service on this address, remplace it if it's the same name
+                        if ((*it).Name == name)
+                        {
+                                // it's the same service, replace it
+                                (*it).SockId = from;
+                                sid = (*it).SId;
+                                nlinfo ("Replace the service %s", name.c_str());
+                        }
+                        else
+                        {
+                                nlwarning ("Try to register %s to %s but the service %s already on this address. ignore it!", name.c_str(), addr.asIPString().c_str(), (*it).Name.c_str());
+                                ok = false;
+                        }
+                        needRegister = false;
+                        break;
+                }
+        }
+
+        if (needRegister)
+        {
+                if (sid == 0)
+                {
+                        // we have to find a sid
+                        sid = BaseSId;
+                        bool found = false;
+                        while (!found)
+                        {
+                                list<CServiceEntry>::iterator it;
+                                for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+                                {
+                                        if ((*it).SId == sid)
+                                        {
+                                                break;
+                                        }
+                                }
+                                if (it == RegisteredServices.end ())
+                                {
+                                        // ok, we have an empty sid
+                                        found = true;
+                                }
+                                else
+                                {
+                                        sid++;
+                                        if (sid == 0) // round the clock
+                                        {
+                                                nlwarning ("Service identifier allocation overflow");
+                                                ok = false;
+                                                break;
+                                        }
+                                }
+                        }
+                }
+                else
+                {
+                        // we have to check that the user provided sid is available
+                        list<CServiceEntry>::iterator it;
+                        for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+                        {
+                                if ((*it).SId == sid)
+                                {
+                                        nlwarning ("Sid %d already used by another service", sid);
+                                        ok = false;
+                                        break;
+                                }
+                        }
+                        if (it != RegisteredServices.end ())
+                        {
+                                ok = true;
+                        }
+                }
+
+                // if ok, register the service and send a broadcast to other people
+                if (ok)
+                {
+                        RegisteredServices.push_back (CServiceEntry(from, addr, name, sid));
+
+                        // tell to everybody that this service is registered
+
+                        CMessage msgout ("RGB");
+                        uint8 s = 1;
+                        msgout.serial (s);
+                        msgout.serial (const_cast<string &>(name));
+                        msgout.serial (sid);
+                        msgout.serial (const_cast<CInetAddress &>(addr));
+                        CNetManager::send ("NS", msgout, 0);
+                        nlinfo ("Broadcast the Registration to everybody");
+                }
+        }
+
+        // send the answer to the client
+        CMessage msgout ("RG");
+        msgout.serial (ok);
+        if (ok) msgout.serial (sid);
+        netbase.send (msgout, from);
+        netbase.flush (from);
+
+        displayRegisteredServices (netbase);
+
+        return ok!=0;
+}
+
+
+/**
+ * Callback for service registration.
+ *
+ * Message expected : RG
+ * - Name of service to register (string)
+ * - Address of service (CInetAddress)
+ *
+ * Message emitted : RG
+ * - Allocated service identifier (TServiceId) or 0 if failed
+ */
+static void cbRegister (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        string name;
+        CInetAddress addr;
+        TServiceId sid;
+        msgin.serial (name);
+        msgin.serial (addr);
+        msgin.serial (sid);
+
+        doRegister (name, addr, sid, from, netbase);
+}
+
+
+/**
+ * Callback for service unregistration.
+ *
+ * Message expected : UNI
+ * - Service identifier (TServiceId)
+ */
+static void cbUnregisterSId (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        TServiceId sid;
+        msgin.serial( sid );
+
+        doUnregisterService (sid);
+        displayRegisteredServices (netbase);
+}
+
+
+/*
+ * Helper function for cbQueryPort
+ *
+ * \warning QueryPort + Registration is not atomic so more than one service could ask a port before register
+ */
+uint16 doAllocatePort (const CInetAddress &addr)
+{
+        static uint16 nextAvailablePort = MinBasePort;
+
+        // check if nextavailableport is free
+
+        if (nextAvailablePort >= MaxBasePort) nextAvailablePort = MinBasePort;
+
+        bool ok;
+        do
+        {
+                ok = true;
+                list<CServiceEntry>::iterator it;
+                for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+                {
+                        if ((*it).Addr.port () == nextAvailablePort)
+                        {
+                                nextAvailablePort++;
+                                ok = false;
+                                break;
+                        }
+                }
+        }
+        while (!ok);
+
+        return nextAvailablePort++;
+}
+
+
+/**
+ * Callback for port allocation
+ * Note: if a service queries a port but does not register itself to the naming service, the
+ * port will remain allocated and unused.
+ *
+ * Message expected : QP
+ * - Name of service to register (string)
+ * - Address of service (CInetAddress) (its port can be 0)
+ *
+ * Message emitted : QP
+ * - Allocated port number (uint16)
+ */
+static void cbQueryPort (CMessage& msgin, TSockId from, CCallbackNetBase &netbase)
+{
+        // Allocate port
+        uint16 port = doAllocatePort (netbase.hostAddress (from));
+
+        // Send port back
+        CMessage msgout ("QP");
+        msgout.serial (port);
+        netbase.send (msgout, from);
+
+        nlinfo ("A service got port %hu", port);
+}
+
+
+/*
+ * Unregisters a service if it has not been done before.
+ * Note: this callback is called whenever someone disconnects from the NS.
+ * May be there are too many calls if many clients perform many transactional lookups.
+ */
+static void cbDisconnect (const string &serviceName, TSockId from, void *arg)
+{
+        doUnregisterService (from);
+        displayRegisteredServices (*CNetManager::getNetBase(serviceName));
+}
+
+/*
+ * a service is connected, send him all services infos
+ */
+static void cbConnect (const string &serviceName, TSockId from, void *arg)
+{
+        CMessage msgout ("RGB");
+
+        uint8 s = RegisteredServices.size ();
+        msgout.serial (s);
+
+        for (list<CServiceEntry>::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                msgout.serial ((*it).Name);
+                msgout.serial ((*it).SId);
+                msgout.serial ((*it).Addr);
+        }
+        CNetManager::send ("NS", msgout, from);
+
+        nlinfo ("Sending all services available to the new client");
+        displayRegisteredServices (*CNetManager::getNetBase(serviceName));
+}
+
+
+//
+// Callback array
+//
+
+TCallbackItem CallbackArray[] =
+{
+        { "RG", cbRegister },
+        { "QP", cbQueryPort },
+        { "UNI", cbUnregisterSId },
+};
+
+
+//
+// Service
+//
+
+class CNamingService : public NLNET::IService
+{
+public:
+
+        void init()
+        {
+                // if a baseport is available in the config file, get it
+                try
+                {
+                        uint16 newBasePort = ConfigFile.getVar ("BasePort").asInt ();
+                        nlinfo ("Changing the MinBasePort number from %hu to %hu", MinBasePort, newBasePort);
+                        sint32 delta = MaxBasePort - MinBasePort;
+                        nlassert (delta > 0);
+                        MinBasePort = newBasePort;
+                        MaxBasePort = MinBasePort + uint16 (delta);
+                }
+                catch (EUnknownVar &)
+                {
+                }
+
+
+                // we don't try to associate message from client
+                CNetManager::getNetBase ("NS")->ignoreAllUnknownId (true);
+
+                // add the callback in case of disconnection
+                CNetManager::setConnectionCallback ("NS", cbConnect, NULL);
+                
+                // add the callback in case of disconnection
+                CNetManager::setDisconnectionCallback ("NS", cbDisconnect, NULL);
+
+                // DEBUG
+                // DebugLog->addDisplayer( new CStdDisplayer() );
+        }
+};
+
+
+//
+/// Naming Service
+//
+NLNET_OLD_SERVICE_MAIN (CNamingService, "NS", "naming_service", 50000, CallbackArray, NELNS_CONFIG, NELNS_LOGS)
+
+
+//
+// Commands
+//
+
+
+NLMISC_COMMAND (nsServices, "displays the list of all registered services", "")
+{
+        if(args.size() != 0) return false;
+
+        log.displayNL ("Display the %d registered services :", RegisteredServices.size());
+        for (list<CServiceEntry>::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+        {
+                log.displayNL ("> %s '%s' %s-%hu '%s'", (*it).SockId->asString().c_str(), CNetManager::getNetBase ("NS")->hostAddress((*it).SockId).asString().c_str(), (*it).Name.c_str(), (uint16)(*it).SId, (*it).Addr.asString().c_str());
+        }
+        log.displayNL ("End ot the list");
+
+        return true;
+}
+
\ No newline at end of file -- cgit v1.2.1