Linux multi-monitor fullscreen support
[ryzomcore.git] / nel / samples / net / net_layer3 / frontend_service.cpp
blob2fbc3c2dbc08f09d0430ddd4369ca3ceba7c0154
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 * Layer 3 and Service example, front-end server.
21 * This front-end server expects pings, and forward them to
22 * the real ping server. When the ping server sends a pong back,
23 * the front-end server forwards it to the client.
25 * To run this program, ensure there is a file "frontend_service.cfg"
26 * containing the location of the naming service (NSHost, NSPort)
27 * in the working directory. The naming service must be running.
31 // We're building a server, using the NeL Service framework.
32 // We need the naming service to know where the ping service is, so we're using CNamingClient.
33 // We're using CCallbackClient when we talk to the naming service.
34 // We're using CCallbackServer when we talk to our clients.
35 #include "nel/net/service.h"
36 #include "nel/net/naming_client.h"
37 #include "nel/net/callback_client.h"
38 #include "nel/net/callback_server.h"
39 using namespace NLNET;
41 #include <deque>
42 using namespace std;
45 // The front-end server is also a client of the ping service
46 CCallbackClient *ToPingService;
48 // Temp storage (a queue because the connection to the ping service is reliable, the order is preserved)
49 deque<TSockId> ClientIds;
53 * Callback function called when receiving a "PING" message
55 * Arguments:
56 * - msgin: the incoming message (coming from a client)
57 * - from: the "sockid" of the sender client
58 * - frontendserver: the CCallbackNetBase object (which really is a CCallbackServer object, for a server)
60 * Input (expected message from a client): PING
61 * - uint32: ping counter
63 * Output (sent message to the ping server): PONG
64 * - uint32: ping counter
66 void cbPing( CMessage& msgin, TSockId from, CCallbackNetBase& frontendserver )
68 uint32 counter;
70 // Input
71 msgin.serial( counter );
72 ClientIds.push_back( from ); // store client sockid
74 // Output
75 CMessage msgout( "PING" );
76 msgout.serial( counter );
77 vector<uint8> vect( 400000 );
78 msgout.serialCont( vect );
79 ToPingService->send( msgout );
81 nlinfo( "Received PING number %u from %s", counter, frontendserver.hostAddress(from).asString().c_str() );
86 * Disconnection callback, called when a client disconnects
88 void discCallback( TSockId from, void *p )
90 // Remove all occurences of from in the queue
91 deque<TSockId>::iterator iq;
92 for ( iq=ClientIds.begin(); iq!=ClientIds.end(); )
94 if ( *iq == from )
96 iq = ClientIds.erase( iq );
98 else
100 iq++;
107 * Callback function called when receiving a "PONG" message
109 * Arguments:
110 * - msgin: the incoming message (coming from the ping server)
111 * - from: the "sockid" of the sender (usually useless for a CCallbackClient)
112 * - clientofthepingserver: the CCallbackNetBase object (which really is a CCallbackClient object)
114 * Input (expected message from the ping server): PONG
115 * - uint32: ping counter
116 * - TSockId: "sock id" of the client who sent the ping
118 * Output (sent message to a client): PONG
119 * - uint32: ping counter
121 void cbPong( CMessage& msgin, TSockId from, CCallbackNetBase& clientofthepingserver )
123 uint32 counter;
124 TSockId clientfrom;
126 // Input: process the reply of the ping service
127 msgin.serial( counter );
128 clientfrom = ClientIds.front(); // retrieve client sockid
129 ClientIds.pop_front();
131 // Output: send the reply to the client
132 CCallbackServer *server = IService::getInstance()->getServer();
133 CMessage msgout( "PONG" );
134 msgout.serial( counter );
135 server->send( msgout, clientfrom );
137 nlinfo( "Sent PONG number %u to %s", counter, clientfrom->asString().c_str() );
142 * Callback array for messages received from a client
144 TCallbackItem CallbackArray[] =
146 { "PING", cbPing } // when receiving a "PING" message, call cbPing()
151 * Callback array for message received from the ping service
153 TCallbackItem PingServiceCallbackArray[] =
155 { "PONG", cbPong } // when receiving a "PONG" message, call cbPong()
160 * CFrontEndService, based on IService
162 class CFrontEndService : public IService
164 public:
167 * Initialization
169 void init()
171 // Connect to the ping service
172 ToPingService = new CCallbackClient( IService::getRecordingState(), "PS.nmr" );
173 ToPingService->addCallbackArray( PingServiceCallbackArray, sizeof(PingServiceCallbackArray)/sizeof(PingServiceCallbackArray[0]) );
174 if ( ! CNamingClient::lookupAndConnect( "PS", *ToPingService ) )
176 nlerror( "Ping Service not available" );
179 // Disconnection callback for the clients
180 IService::getServer()->setDisconnectionCallback( discCallback, NULL );
184 * Update
186 bool update()
188 ToPingService->update( 20 ); // 20 ms max
189 return ToPingService->connected(); // true continues, false stops the service
193 * Finalization
195 void release()
197 delete ToPingService;
203 * Declare a service with the class CFrontEndService, the names "FS" (short) and "frontend_service" (long).
204 * The port is set to 37000 and the main callback array is CallbackArray.
206 NLNET_OLD_SERVICE_MAIN( CFrontEndService, "FS", "frontend_service", 37000, CallbackArray, "", "" )