aboutsummaryrefslogtreecommitdiff
path: root/cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html')
-rw-r--r--cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp?rev=1.21&content-type=text/x-cvsweb-markup/index.html658
1 files changed, 658 insertions, 0 deletions
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 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML>
+<HEAD><style> A { color:black }</style>
+<!-- hennerik CVSweb $Revision: 1.93 $ -->
+<TITLE>code/nelns/naming_service/naming_service.cpp - view - 1.21</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee">
+<table width="100%" border=0 cellspacing=0 cellpadding=1 bgcolor="#aaaaaa"><tr valign=bottom><td><a href="naming_service.cpp"><IMG SRC="http://www.nevrax.org/inc/img/picto-up.gif" ALT="[BACK]" BORDER="0" WIDTH="14" HEIGHT="13"></a> <b>Return to <A HREF="naming_service.cpp">naming_service.cpp</A>
+ CVS log</b> <IMG SRC="http://www.nevrax.org/inc/img/picto-news.gif" ALT="[TXT]" BORDER="0" WIDTH="13" HEIGHT="15"></td><td align=right><IMG SRC="http://www.nevrax.org/inc/img/picto-dir.gif" ALT="[DIR]" BORDER="0" WIDTH="15" HEIGHT="13"> <b>Up to <a href="/cvs/cvsweb.cgi/">Nevrax</a> / <a href="/cvs/cvsweb.cgi/code/">code</a> / <a href="/cvs/cvsweb.cgi/code/nelns/">nelns</a> / <a href="/cvs/cvsweb.cgi/code/nelns/naming_service/">naming_service</a></b></td></tr></table><HR noshade><table width="100%"><tr><td bgcolor="#ffffff">File: <a href="/cvs/cvsweb.cgi/">Nevrax</a> / <a href="/cvs/cvsweb.cgi/code/">code</a> / <a href="/cvs/cvsweb.cgi/code/nelns/">nelns</a> / <a href="/cvs/cvsweb.cgi/code/nelns/naming_service/">naming_service</a> / <a href="/cvs/cvsweb.cgi/code/nelns/naming_service/naming_service.cpp">naming_service.cpp</a>&nbsp;(<A HREF="/cvs/cvsweb.cgi/~checkout~/code/nelns/naming_service/naming_service.cpp?rev=1.21" target="cvs_checkout" onClick="window.open('/cvs/cvsweb.cgi/~checkout~/code/nelns/naming_service/naming_service.cpp?rev=1.21','cvs_checkout','resizeable,scrollbars');"><b>download</b></A>)<BR>
+Revision <B>1.21</B>, <i>Tue Mar 26 09:45:11 2002 UTC</i> (2 months, 4 weeks ago) by <i>lecroart</i>
+<BR>Branch: <b>MAIN</b>
+<BR>Changes since <b>1.20: +3 -2
+ lines</b><PRE>
+CHANGED: unified the command format
+</PRE>
+</td></tr></table><HR noshade><PRE>/** \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 &quot;config.h&quot;
+#endif // HAVE_CONFIG_H
+
+#ifndef NELNS_CONFIG
+#define NELNS_CONFIG &quot;&quot;
+#endif // NELNS_CONFIG
+
+#ifndef NELNS_LOGS
+#define NELNS_LOGS &quot;&quot;
+#endif // NELNS_LOGS
+
+//
+// Includes
+//
+
+#include &quot;nel/misc/types_nl.h&quot;
+
+#include &lt;list&gt;
+#include &lt;string&gt;
+
+#include &quot;nel/misc/debug.h&quot;
+#include &quot;nel/misc/command.h&quot;
+#include &quot;nel/misc/displayer.h&quot;
+
+#include &quot;nel/net/service.h&quot;
+
+//
+// Namespaces
+//
+
+using namespace std;
+
+using namespace NLMISC;
+using namespace NLNET;
+
+
+//
+// Structures
+//
+
+struct CServiceEntry
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;CServiceEntry (TSockId sock, CInetAddress a, string n, TServiceId s) : SockId(sock), Addr(a), Name(n), SId (s) { }
+
+ &nbsp; &nbsp; &nbsp; &nbsp;TSockId &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SockId; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// the connection between the service and the naming service
+ &nbsp; &nbsp; &nbsp; &nbsp;CInetAddress &nbsp; &nbsp; &nbsp; &nbsp;Addr; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// address to send to the service who wants to lookup this service
+ &nbsp; &nbsp; &nbsp; &nbsp;string &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Name; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// name of the service
+ &nbsp; &nbsp; &nbsp; &nbsp;TServiceId &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SId; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// id of the service
+};
+
+
+//
+// Variables
+//
+
+list&lt;CServiceEntry&gt; &nbsp; &nbsp; RegisteredServices; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/// List of all registred services
+
+uint16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MinBasePort = 51000; &nbsp; &nbsp; &nbsp; &nbsp;/// Ports begin at 51000
+uint16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MaxBasePort = 52000; &nbsp; &nbsp; &nbsp; &nbsp;/// (note: in this implementation there can be no more than 1000 services)
+
+const TServiceId &nbsp; &nbsp; &nbsp; &nbsp;BaseSId = 128; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;/// Allocated SIds begin at 128 (except for Agent Service)
+
+
+//
+// Functions
+//
+
+void displayRegisteredServices (CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Display the %d registered services :&quot;, RegisteredServices.size());
+ &nbsp; &nbsp; &nbsp; &nbsp;for (list&lt;CServiceEntry&gt;::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;&gt; %s '%s' %s-%hu '%s'&quot;, (*it).SockId-&gt;asString().c_str(), netbase.hostAddress((*it).SockId).asString().c_str(), (*it).Name.c_str(), (uint16)(*it).SId, (*it).Addr.asString().c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;End ot the list&quot;);
+}
+
+
+
+/*
+ * Helper procedure for cbLookupAlternate and cbUnregister.
+ * Note: name is used for a LOGS.
+ */
+list&lt;CServiceEntry&gt;::iterator doRemove (list&lt;CServiceEntry&gt;::iterator it)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nldebug (&quot;Unregister the service %s-%hu '%s'&quot;, (*it).Name.c_str(), (uint16)(*it).SId, (*it).Addr.asString().c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;// tell to everybody that this service is unregistered
+
+ &nbsp; &nbsp; &nbsp; &nbsp;CMessage msgout (&quot;UNB&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial ((*it).Name);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial ((*it).SId);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial ((*it).Addr);
+ &nbsp; &nbsp; &nbsp; &nbsp;CNetManager::send (&quot;NS&quot;, msgout, 0);
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Broadcast the Unregistration to everybody&quot;);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// remove the service from the registered service list
+ &nbsp; &nbsp; &nbsp; &nbsp;return RegisteredServices.erase (it);
+}
+
+void doUnregisterService (TServiceId sid)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).SId == sid)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// found it, remove it
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;doRemove (it);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;nlwarning (&quot;Service %hu not found&quot;, (uint16)sid);
+}
+
+void doUnregisterService (TSockId from)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end ();)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).SockId == from)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// it's possible that one &quot;from&quot; have more than one registred service, so we have to find in all the list
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// found it, remove it
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;it = doRemove (it);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;it++;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+}
+
+void doUnregisterService (const CInetAddress &amp;addr)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).Addr == addr)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// found it, remove it
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;doRemove (it);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;nlwarning (&quot;Service %s not found&quot;, addr.asString().c_str());
+}
+
+
+/*
+ * Helper function for cbLookupSId and cbLookupAlternateSId. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*********** OUT OF DATE ***************
+ * Returns NULL if service not found
+ */
+void doLookup (const string &amp;sname, TServiceId sid, TSockId from, CCallbackNetBase &amp;netbase, bool sendAll, bool useSId)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nlstop;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;string name;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;if (useSId)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;name = toString (sid);
+ &nbsp; &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;name = sname;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Lookup for service '%s' for '%s'...&quot;, name.c_str(), netbase.hostAddress(from).asString().c_str());
+
+ &nbsp; &nbsp; &nbsp; &nbsp;displayRegisteredServices (netbase);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Send list
+ &nbsp; &nbsp; &nbsp; &nbsp;vector&lt;CInetAddress&gt; addrs;
+ &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((useSId &amp;&amp; (*it).SId == sid) || (!useSId &amp;&amp; (*it).Name == name))
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;addrs.push_back ((*it).Addr);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// if it only want one, stop now to search
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (!sendAll) break;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp; &nbsp;if (addrs.size()==0)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nldebug (&quot;Service %s is not found&quot;, name.c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp;else if (addrs.size()==1)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nldebug (&quot;Service %s is at %s&quot;, name.c_str(), addrs[0].asString().c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nldebug (&quot;%d Services %s found&quot;, addrs.size(), name.c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;CMessage msgout (&quot;LK&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serialCont (addrs);
+ &nbsp; &nbsp; &nbsp; &nbsp;netbase.send (msgout, from);
+}
+
+/**
+ * Callback for service look-up. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*********** 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&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nlstop;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;string name;
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (name);
+ &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp;// Find and return a service
+ &nbsp; &nbsp; &nbsp; &nbsp;doLookup (name, 0, from, netbase, false, false);
+}
+
+/**
+ * Callback for alternate service look-up when a service is not responding &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*********** 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&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nlstop;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;string name;
+ &nbsp; &nbsp; &nbsp; &nbsp;CInetAddress addr;
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (name);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (addr);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Server %s looks down, looking-up for alternative service %s&quot;, addr.asString().c_str(), name.c_str() );
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Unregister down server
+ &nbsp; &nbsp; &nbsp; &nbsp;doUnregisterService (addr);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Find and return another servive
+ &nbsp; &nbsp; &nbsp; &nbsp;doLookup (name, 0, from, netbase, false, false);
+}
+
+/**
+ * Callback for service look-up for all corresponding to a name. &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*********** OUT OF DATE ***************
+ *
+ * Message expected : LKA
+ * - Name of service to find (string)
+ *
+ * Message emitted : no name (ALKA)
+ * - List of addresses (vector&lt;CInetAddress&gt;)
+ */
+static void cbLookupAll (CMessage&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nlstop;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Receive name
+ &nbsp; &nbsp; &nbsp; &nbsp;string name;
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (name);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Find and return a service
+ &nbsp; &nbsp; &nbsp; &nbsp;doLookup (name, 0, from, netbase, true, false);
+}
+
+/**
+ * Callback for service look-up by identifier &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *********** 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&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;nlstop;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Receive id
+ &nbsp; &nbsp; &nbsp; &nbsp;TServiceId sid;
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (sid);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Find and return a service
+ &nbsp; &nbsp; &nbsp; &nbsp;doLookup (&quot;&quot;, 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 &amp;name, const CInetAddress &amp;addr, TServiceId sid, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;// find if the service is not already registered
+ &nbsp; &nbsp; &nbsp; &nbsp;uint8 ok = true;
+ &nbsp; &nbsp; &nbsp; &nbsp;bool needRegister = true;
+ &nbsp; &nbsp; &nbsp; &nbsp;for (list&lt;CServiceEntry&gt;::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).Addr.asIPString() == addr.asIPString() )
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// we already have a service on this address, remplace it if it's the same name
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).Name == name)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// it's the same service, replace it
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(*it).SockId = from;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sid = (*it).SId;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Replace the service %s&quot;, name.c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlwarning (&quot;Try to register %s to %s but the service %s already on this address. ignore it!&quot;, name.c_str(), addr.asIPString().c_str(), (*it).Name.c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ok = false;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;needRegister = false;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp; &nbsp;if (needRegister)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (sid == 0)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// we have to find a sid
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sid = BaseSId;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bool found = false;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;while (!found)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).SId == sid)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (it == RegisteredServices.end ())
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// ok, we have an empty sid
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;found = true;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sid++;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (sid == 0) // round the clock
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlwarning (&quot;Service identifier allocation overflow&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ok = false;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// we have to check that the user provided sid is available
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).SId == sid)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlwarning (&quot;Sid %d already used by another service&quot;, sid);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ok = false;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (it != RegisteredServices.end ())
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ok = true;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// if ok, register the service and send a broadcast to other people
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (ok)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;RegisteredServices.push_back (CServiceEntry(from, addr, name, sid));
+
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// tell to everybody that this service is registered
+
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CMessage msgout (&quot;RGB&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uint8 s = 1;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (s);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (const_cast&lt;string &amp;&gt;(name));
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (sid);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (const_cast&lt;CInetAddress &amp;&gt;(addr));
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CNetManager::send (&quot;NS&quot;, msgout, 0);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Broadcast the Registration to everybody&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// send the answer to the client
+ &nbsp; &nbsp; &nbsp; &nbsp;CMessage msgout (&quot;RG&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (ok);
+ &nbsp; &nbsp; &nbsp; &nbsp;if (ok) msgout.serial (sid);
+ &nbsp; &nbsp; &nbsp; &nbsp;netbase.send (msgout, from);
+ &nbsp; &nbsp; &nbsp; &nbsp;netbase.flush (from);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;displayRegisteredServices (netbase);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;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&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;string name;
+ &nbsp; &nbsp; &nbsp; &nbsp;CInetAddress addr;
+ &nbsp; &nbsp; &nbsp; &nbsp;TServiceId sid;
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (name);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (addr);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial (sid);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;doRegister (name, addr, sid, from, netbase);
+}
+
+
+/**
+ * Callback for service unregistration.
+ *
+ * Message expected : UNI
+ * - Service identifier (TServiceId)
+ */
+static void cbUnregisterSId (CMessage&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;TServiceId sid;
+ &nbsp; &nbsp; &nbsp; &nbsp;msgin.serial( sid );
+
+ &nbsp; &nbsp; &nbsp; &nbsp;doUnregisterService (sid);
+ &nbsp; &nbsp; &nbsp; &nbsp;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 &amp;addr)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;static uint16 nextAvailablePort = MinBasePort;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// check if nextavailableport is free
+
+ &nbsp; &nbsp; &nbsp; &nbsp;if (nextAvailablePort &gt;= MaxBasePort) nextAvailablePort = MinBasePort;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;bool ok;
+ &nbsp; &nbsp; &nbsp; &nbsp;do
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ok = true;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;list&lt;CServiceEntry&gt;::iterator it;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for (it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if ((*it).Addr.port () == nextAvailablePort)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nextAvailablePort++;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ok = false;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;while (!ok);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;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&amp; msgin, TSockId from, CCallbackNetBase &amp;netbase)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;// Allocate port
+ &nbsp; &nbsp; &nbsp; &nbsp;uint16 port = doAllocatePort (netbase.hostAddress (from));
+
+ &nbsp; &nbsp; &nbsp; &nbsp;// Send port back
+ &nbsp; &nbsp; &nbsp; &nbsp;CMessage msgout (&quot;QP&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (port);
+ &nbsp; &nbsp; &nbsp; &nbsp;netbase.send (msgout, from);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;A service got port %hu&quot;, 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 &amp;serviceName, TSockId from, void *arg)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;doUnregisterService (from);
+ &nbsp; &nbsp; &nbsp; &nbsp;displayRegisteredServices (*CNetManager::getNetBase(serviceName));
+}
+
+/*
+ * a service is connected, send him all services infos
+ */
+static void cbConnect (const string &amp;serviceName, TSockId from, void *arg)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;CMessage msgout (&quot;RGB&quot;);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;uint8 s = RegisteredServices.size ();
+ &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial (s);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;for (list&lt;CServiceEntry&gt;::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial ((*it).Name);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial ((*it).SId);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;msgout.serial ((*it).Addr);
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;CNetManager::send (&quot;NS&quot;, msgout, from);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Sending all services available to the new client&quot;);
+ &nbsp; &nbsp; &nbsp; &nbsp;displayRegisteredServices (*CNetManager::getNetBase(serviceName));
+}
+
+
+//
+// Callback array
+//
+
+TCallbackItem CallbackArray[] =
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;{ &quot;RG&quot;, cbRegister },
+ &nbsp; &nbsp; &nbsp; &nbsp;{ &quot;QP&quot;, cbQueryPort },
+ &nbsp; &nbsp; &nbsp; &nbsp;{ &quot;UNI&quot;, cbUnregisterSId },
+};
+
+
+//
+// Service
+//
+
+class CNamingService : public NLNET::IService
+{
+public:
+
+ &nbsp; &nbsp; &nbsp; &nbsp;void init()
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// if a baseport is available in the config file, get it
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;try
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uint16 newBasePort = ConfigFile.getVar (&quot;BasePort&quot;).asInt ();
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlinfo (&quot;Changing the MinBasePort number from %hu to %hu&quot;, MinBasePort, newBasePort);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;sint32 delta = MaxBasePort - MinBasePort;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nlassert (delta &gt; 0);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MinBasePort = newBasePort;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MaxBasePort = MinBasePort + uint16 (delta);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;catch (EUnknownVar &amp;)
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}
+
+
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// we don't try to associate message from client
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CNetManager::getNetBase (&quot;NS&quot;)-&gt;ignoreAllUnknownId (true);
+
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// add the callback in case of disconnection
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CNetManager::setConnectionCallback (&quot;NS&quot;, cbConnect, NULL);
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// add the callback in case of disconnection
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CNetManager::setDisconnectionCallback (&quot;NS&quot;, cbDisconnect, NULL);
+
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// DEBUG
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// DebugLog-&gt;addDisplayer( new CStdDisplayer() );
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+};
+
+
+//
+/// Naming Service
+//
+NLNET_OLD_SERVICE_MAIN (CNamingService, &quot;NS&quot;, &quot;naming_service&quot;, 50000, CallbackArray, NELNS_CONFIG, NELNS_LOGS)
+
+
+//
+// Commands
+//
+
+
+NLMISC_COMMAND (nsServices, &quot;displays the list of all registered services&quot;, &quot;&quot;)
+{
+ &nbsp; &nbsp; &nbsp; &nbsp;if(args.size() != 0) return false;
+
+ &nbsp; &nbsp; &nbsp; &nbsp;log.displayNL (&quot;Display the %d registered services :&quot;, RegisteredServices.size());
+ &nbsp; &nbsp; &nbsp; &nbsp;for (list&lt;CServiceEntry&gt;::iterator it = RegisteredServices.begin(); it != RegisteredServices.end (); it++)
+ &nbsp; &nbsp; &nbsp; &nbsp;{
+ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log.displayNL (&quot;&gt; %s '%s' %s-%hu '%s'&quot;, (*it).SockId-&gt;asString().c_str(), CNetManager::getNetBase (&quot;NS&quot;)-&gt;hostAddress((*it).SockId).asString().c_str(), (*it).Name.c_str(), (uint16)(*it).SId, (*it).Addr.asString().c_str());
+ &nbsp; &nbsp; &nbsp; &nbsp;}
+ &nbsp; &nbsp; &nbsp; &nbsp;log.displayNL (&quot;End ot the list&quot;);
+
+ &nbsp; &nbsp; &nbsp; &nbsp;return true;
+}
+</PRE> \ No newline at end of file