diff options
Diffstat (limited to '')
-rw-r--r-- | cvs/cvsweb.cgi/code/nel/src/net/callback_net_base.cpp?rev=1.33&content-type=text/x-cvsweb-markup&sortby=date/index.html | 556 |
1 files changed, 556 insertions, 0 deletions
diff --git a/cvs/cvsweb.cgi/code/nel/src/net/callback_net_base.cpp?rev=1.33&content-type=text/x-cvsweb-markup&sortby=date/index.html b/cvs/cvsweb.cgi/code/nel/src/net/callback_net_base.cpp?rev=1.33&content-type=text/x-cvsweb-markup&sortby=date/index.html new file mode 100644 index 00000000..b3f66b6e --- /dev/null +++ b/cvs/cvsweb.cgi/code/nel/src/net/callback_net_base.cpp?rev=1.33&content-type=text/x-cvsweb-markup&sortby=date/index.html @@ -0,0 +1,556 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML> +<HEAD><style> A { color:black }</style> +<!-- hennerik CVSweb $Revision: 1.93 $ --> +<TITLE>code/nel/src/net/callback_net_base.cpp - view - 1.33</TITLE></HEAD> +<BODY BGCOLOR="#eeeeee"> +<table width="100%" border=0 cellspacing=0 cellpadding=1 bgcolor="#aaaaaa"><tr valign=bottom><td><a href="callback_net_base.cpp?sortby=date"><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="callback_net_base.cpp?sortby=date">callback_net_base.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/?sortby=date">Nevrax</a> / <a href="/cvs/cvsweb.cgi/code/?sortby=date">code</a> / <a href="/cvs/cvsweb.cgi/code/nel/?sortby=date">nel</a> / <a href="/cvs/cvsweb.cgi/code/nel/src/?sortby=date">src</a> / <a href="/cvs/cvsweb.cgi/code/nel/src/net/?sortby=date">net</a></b></td></tr></table><HR noshade><table width="100%"><tr><td bgcolor="#ffffff">File: <a href="/cvs/cvsweb.cgi/?sortby=date">Nevrax</a> / <a href="/cvs/cvsweb.cgi/code/?sortby=date">code</a> / <a href="/cvs/cvsweb.cgi/code/nel/?sortby=date">nel</a> / <a href="/cvs/cvsweb.cgi/code/nel/src/?sortby=date">src</a> / <a href="/cvs/cvsweb.cgi/code/nel/src/net/?sortby=date">net</a> / <a href="/cvs/cvsweb.cgi/code/nel/src/net/callback_net_base.cpp?sortby=date">callback_net_base.cpp</a> (<A HREF="/cvs/cvsweb.cgi/~checkout~/code/nel/src/net/callback_net_base.cpp?rev=1.33&sortby=date" target="cvs_checkout" onClick="window.open('/cvs/cvsweb.cgi/~checkout~/code/nel/src/net/callback_net_base.cpp?rev=1.33','cvs_checkout','resizeable,scrollbars');"><b>download</b></A>)<BR> +Revision <B>1.33</B>, <i>Wed Jun 12 10:16:34 2002 UTC</i> (6 weeks, 4 days ago) by <i>lecroart</i> +<BR>Branch: <b>MAIN</b> +<BR>CVS Tags: <b>HEAD</b><BR>Changes since <b>1.32: +4 -7 + lines</b><PRE> +ADDED: changed NULL into InvalidSockId +</PRE> +</td></tr></table><HR noshade><PRE>/** \file callback_net_base.cpp + * Network engine, layer 3, base + * + * $Id: callback_net_base.cpp,v 1.33 2002/06/12 10:16:34 lecroart Exp $ + */ + +/* Copyright, 2001 Nevrax Ltd. + * + * This file is part of NEVRAX NEL. + * NEVRAX NEL 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 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; see the file COPYING. If not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, + * MA 02111-1307, USA. + */ + +#include "stdnet.h" + +#include "nel/misc/string_id_array.h" +#include "nel/misc/hierarchical_timer.h" + +#include "nel/net/buf_sock.h" +#include "nel/net/callback_net_base.h" + +#ifdef USE_MESSAGE_RECORDER +#pragma message ( "NeL Net layer 3: message recorder enabled" ) +#include "nel/net/message_recorder.h" +#else +#pragma message ( "NeL Net layer 3: message recorder disabled" ) +#endif + + +using namespace std; +using namespace NLMISC; + +namespace NLNET { + + +/* + * + */ +void cbnbMessageRecvAssociations (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // receive a new message association + + CStringIdArray::TStringId size; + msgin.serial (size); + + nldebug ("LNETL3NB_ASSOC: The other side gave me %d association strings", size); + + for (CStringIdArray::TStringId i = 0; i < size; i++) + { + std::string name; + CStringIdArray::TStringId id; + + msgin.serial (name); + msgin.serial (id); + + // if id == -1, it means that there are no callback associated to this message + // it should not happen, it mean that one side send a message that the other side + // can't manage in his callbackarray. + // to resolve the problem, add the callback in the callbackarray in the other side + // and put NULL if you don't want to manage this message + nlassert (id != -1); + + nldebug ("LNETL3NB_ASSOC: association '%s' -> %d", name.c_str (), id); + netbase.getSIDA().addString (name, id); + } +} + + +/* + * the other side want to know some of my association, send them! + */ +void cbnbMessageAskAssociations (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + CMessage msgout (netbase.getSIDA(), "RA"); + CStringIdArray::TStringId size; + msgin.serial (size); + + nldebug ("LNETL3NB_ASSOC: The other side want %d string associations", size); + + msgout.serial (size); + + for (sint i = 0; i < size; i++) + { + string name; + msgin.serial (name); + nldebug ("LNETL3NB_ASSOC: sending association '%s' -> %d", name.c_str (), netbase._OutputSIDA.getId(name)); + + // if this assert occurs, it means that the other side ask an unknown message + // or that there are different types of client (with differents callbackarray) and one of the client doesn't have this callback + nlassert(netbase._OutputSIDA.getId(name) != -1); + + msgout.serial (name); + + CStringIdArray::TStringId id = netbase._OutputSIDA.getId (name); + msgout.serial (id); + } + // send the message to the other side + netbase.send (msgout, from); +} + +static TCallbackItem cbnbMessageAssociationArray[] = +{ + { "AA", cbnbMessageAskAssociations }, + { "RA", cbnbMessageRecvAssociations }, +}; + + +/* + * Disconnection callback + */ +void cbnbNewDisconnection (TSockId from, void *data) +{ + nlassert (data != NULL); + CCallbackNetBase *base = (CCallbackNetBase *)data; + + nldebug("LNETL3NB: cbnbNewDisconnection()"); + +#ifdef USE_MESSAGE_RECORDER + // Record or replay disconnection + base->noticeDisconnection( from ); +#endif + + // Call the client callback if necessary + if (base->_DisconnectionCallback != NULL) + base->_DisconnectionCallback (from, base->_DisconnectionCbArg); +} + + +/* + * Constructor + */ +CCallbackNetBase::CCallbackNetBase( TRecordingState rec, const string& recfilename, bool recordall ) : + _FirstUpdate (true), _DisconnectionCallback(NULL), _DisconnectionCbArg(NULL) +#ifdef USE_MESSAGE_RECORDER + , _MR_RecordingState(rec), _MR_UpdateCounter(0) +#endif +{ + _ThreadId = getThreadId (); + _NewDisconnectionCallback = cbnbNewDisconnection; + + _BytesSent = 0; + _BytesReceived = 0; + + createDebug(); // for addNegativeFilter to work even in release and releasedebug modes + + // add the callback needed to associate messages with id + addCallbackArray (cbnbMessageAssociationArray, sizeof (cbnbMessageAssociationArray) / sizeof (cbnbMessageAssociationArray[0])); + +#ifdef USE_MESSAGE_RECORDER + switch ( _MR_RecordingState ) + { + case Record : + _MR_Recorder.startRecord( recfilename, recordall ); + break; + case Replay : + _MR_Recorder.startReplay( recfilename ); + break; + default:; + // No recording + } +#endif +} + + +/* + * Append callback array with the specified array + */ +void CCallbackNetBase::addCallbackArray (const TCallbackItem *callbackarray, CStringIdArray::TStringId arraysize) +{ + checkThreadId (); + + // be sure that the 2 array have the same size + nlassert (_CallbackArray.size () == (uint)_OutputSIDA.size ()); + + if (arraysize == 1 && callbackarray[0].Callback == NULL && string("") == callbackarray[0].Key) + { + // it's an empty array, ignore it + return; + } + + // resize the array + sint oldsize = _CallbackArray.size(); + + _CallbackArray.resize (oldsize + arraysize); + _OutputSIDA.resize (oldsize + arraysize); + +//TOO MUCH MESSAGE nldebug ("L3NB_CB: Adding %d callback to the array", arraysize); + + for (sint i = 0; i < arraysize; i++) + { + CStringIdArray::TStringId ni = oldsize + i; +//TOO MUCH MESSAGE nldebug ("L3NB_CB: Adding callback to message '%s', id '%d'", callbackarray[i].Key, ni); + // copy callback value + + _CallbackArray[ni] = callbackarray[i]; + // add the string to the string id array + _OutputSIDA.addString (callbackarray[i].Key, ni); + + } +// nldebug ("LNETL3NB_CB: Added %d callback Now, there's %d callback associated with message type", arraysize, _CallbackArray.size ()); +} + + +/* + * processOneMessage() + */ +void CCallbackNetBase::processOneMessage () +{ + checkThreadId (); + + H_AUTO (CCallbackNetBase_processOneMessage); + + CMessage msgin (_OutputSIDA, "", true); + TSockId tsid; + receive (msgin, &tsid); + + _BytesReceived += msgin.length (); + + nldebug ("LNETL3NB: Received a message %s from %s", msgin.toString().c_str(), tsid->asString().c_str()); + + // now, we have to call the good callback + NLMISC::CStringIdArray::TStringId pos = -1; + if (msgin.TypeHasAnId) + { + pos = msgin.getId (); + } + else + { + std::string name = msgin.getName (); + sint16 i; + for (i = 0; i < (sint16) _CallbackArray.size (); i++) + { + if (name == _CallbackArray[i].Key) + { + pos = i; + break; + } + } + } + + TMsgCallback cb = NULL; + if (pos < 0 || pos >= (sint16) _CallbackArray.size ()) + { + if (_DefaultCallback == NULL) + { + nlwarning ("LNETL3NB_CB: Callback %s not found in _CallbackArray", msgin.toString().c_str()); + } + else + { + cb = _DefaultCallback; + } + } + else + { + cb = _CallbackArray[pos].Callback; + } + + TSockId realid = getSockId (tsid); + + if (!realid->AuthorizedCallback.empty() && msgin.getName() != realid->AuthorizedCallback) + { + nlwarning ("LNETL3NB_CB: %s try to call the callback %s but only %s is authorized. Disconnect him!", tsid->asString().c_str(), msgin.toString().c_str(), tsid->AuthorizedCallback.c_str()); + disconnect (tsid); + } + else if (cb == NULL) + { + nlwarning ("LNETL3NB_CB: Callback %s is NULL, can't call it", msgin.toString().c_str()); + } + else + { + nldebug ("LNETL3NB_CB: Calling callback (%s)%s", msgin.getName().c_str(), (cb==_DefaultCallback)?" DEFAULT_CB":""); + cb(msgin, realid, *this); + } + +/* + if (pos < 0 || pos >= (sint16) _CallbackArray.size ()) + { + if (_DefaultCallback == NULL) + nlwarning ("LNETL3NB_CB: Callback %s not found in _CallbackArray", msgin.toString().c_str()); + else + { + // ... + } + } + else + { + TSockId realid = getSockId (tsid); + + if (!realid->AuthorizedCallback.empty() && msgin.getName() != realid->AuthorizedCallback) + { + nlwarning ("LNETL3NB_CB: %s try to call the callback %s but only %s is authorized. Disconnect him!", tsid->asString().c_str(), msgin.toString().c_str(), tsid->AuthorizedCallback.c_str()); + disconnect (tsid); + } + else if (_CallbackArray[pos].Callback == NULL) + { + nlwarning ("LNETL3NB_CB: Callback %s is NULL, can't call it", msgin.toString().c_str()); + } + else + { + nldebug ("LNETL3NB_CB: Calling callback (%s)", _CallbackArray[pos].Key); + _CallbackArray[pos].Callback (msgin, realid, *this); + } + } +*/ +} + + + +/* + * baseUpdate + * Recorded : YES + * Replayed : YES + */ +void CCallbackNetBase::baseUpdate (sint32 timeout) +{ + checkThreadId (); + + H_AUTO (CCallbackNetBase_baseUpdate); + + nlassert( timeout >= -1 ); + TTime t0 = CTime::getLocalTime(); + + // + // The first time, we init time counters + // + if (_FirstUpdate) + { +// nldebug("LNETL3NB: First update()"); + _FirstUpdate = false; + _LastUpdateTime = t0; + _LastMovedStringArray = t0; + } + + // + // Every 1 seconds if we have new unknown association, we ask them to the other side + // + if (t0 - _LastUpdateTime > 1000) + { +// nldebug("LNETL3NB: baseUpdate()"); + _LastUpdateTime = t0; + + const set<string> &sa = _InputSIDA.getNeedToAskedStringArray (); + if (!sa.empty ()) + { + CMessage msgout (_InputSIDA, "AA"); + //nlassert (sa.size () < 65536); // no size limit anymore + CStringIdArray::TStringId size = sa.size (); + nldebug ("LNETL3NB_ASSOC: I need %d string association, ask them to the other side", size); + msgout.serial (size); + for (set<string>::iterator it = sa.begin(); it != sa.end(); it++) + { + nldebug ("LNETL3NB_ASSOC: what is the id of '%s'?", (*it).c_str ()); + string str(*it); + msgout.serial (str); + } + // send the message to the other side + send (msgout, 0); + _InputSIDA.moveNeedToAskToAskedStringArray(); + _LastMovedStringArray = t0; + } + } + + // + // Every 60 seconds if we have not answered association, we ask again to get them! + // + if (!_InputSIDA.getAskedStringArray().empty() && t0 - _LastMovedStringArray > 60000) + { + // we didn't have an answer for the association, resend them + const set<string> sa = _InputSIDA.getAskedStringArray (); + CMessage msgout (_InputSIDA, "AA"); + //nlassert (sa.size () < 65536); // no size limit anymore + CStringIdArray::TStringId size = sa.size (); + nldebug ("LNETL3NB_ASSOC: client didn't answer my asked association, retry! I need %d string association, ask them to the other side", size); + msgout.serial (size); + for (set<string>::iterator it = sa.begin(); it != sa.end(); it++) + { + nldebug ("LNETL3NB_ASSOC: what is the id of '%s'?", (*it).c_str ()); + string str(*it); + msgout.serial (str); + } + // sends the message to the other side + send (msgout, 0); + _LastMovedStringArray = t0; + } + + /* + * timeout -1 => read one message in the queue + * timeout 0 => read all messages in the queue + * timeout other => read all messages in the queue until timeout expired (at least all one time) + */ + + bool exit = false; + + while (!exit) + { + // process all messages in the queue + while (dataAvailable ()) + { + processOneMessage (); + if (timeout == -1) + { + exit = true; + break; + } + } + + // need to exit? + if (timeout == 0 || (sint32)(CTime::getLocalTime() - t0) > timeout) + { + exit = true; + } + else + { + // enable multithreading on windows :-/ + H_AUTO (CCallbackNetBase_baseUpdate_nlSleep); + nlSleep (10); + } + } + +#ifdef USE_MESSAGE_RECORDER + _MR_UpdateCounter++; +#endif + +} + + +const CInetAddress& CCallbackNetBase::hostAddress (TSockId hostid) +{ + // should never be called + nlstop; + static CInetAddress tmp; + return tmp; +} + +void CCallbackNetBase::setOtherSideAssociations (const char **associationarray, NLMISC::CStringIdArray::TStringId arraysize) +{ + checkThreadId (); + + nldebug ("LNETL3NB_ASSOC: setOtherSideAssociations() sets %d association strings", arraysize); + + for (sint i = 0; i < arraysize; i++) + { + nldebug ("LNETL3NB_ASSOC: association '%s' -> %d", associationarray[i], i); + getSIDA().addString (associationarray[i], i); + } +} + +void CCallbackNetBase::displayAllMyAssociations () +{ + checkThreadId (); + + _OutputSIDA.display (); +} + +void CCallbackNetBase::authorizeOnly (const char *callbackName, TSockId hostid) +{ + checkThreadId (); + + nldebug ("LNETL3NB: authorizeOnly (%s, %s)", callbackName, hostid->asString().c_str()); + + hostid = getSockId (hostid); + + nlassert (hostid != InvalidSockId); + + hostid->AuthorizedCallback = (callbackName == NULL)?"":callbackName; +} + + +#ifdef USE_MESSAGE_RECORDER + +/* + * Replay dataAvailable() in replay mode + */ +bool CCallbackNetBase::replayDataAvailable() +{ + nlassert( _MR_RecordingState == Replay ); + + if ( _MR_Recorder.ReceivedMessages.empty() ) + { + // Fill the queue of received messages related to the present update + _MR_Recorder.replayNextDataAvailable( _MR_UpdateCounter ); + } + + return replaySystemCallbacks(); +} + + +/* + * Record or replay disconnection + */ +void CCallbackNetBase::noticeDisconnection( TSockId hostid ) +{ + nlassert (hostid != InvalidSockId); // invalid hostid + if ( _MR_RecordingState != Replay ) + { + if ( _MR_RecordingState == Record ) + { + // Record disconnection + CMessage emptymsg; + _MR_Recorder.recordNext( _MR_UpdateCounter, Disconnecting, hostid, emptymsg ); + } + } + else + { + // Replay disconnection + hostid->disconnect( false ); + } +} + +#endif // USE_MESSAGE_RECORDER + + + +/* + * checkThreadId + */ +void CCallbackNetBase::checkThreadId () const +{ +/* some people use this class in different thread but with a mutex to be sure to have + no concurent access + if (getThreadId () != _ThreadId) + { + nlerror ("You try to access to the same CCallbackClient or CCallbackServer with 2 differents thread (%d and %d)", _ThreadId, getThreadId()); + } +*/ +} + + +} // NLNET + +</PRE>
\ No newline at end of file |