Updated license
[anna.git] / include / anna / diameter.comm / Engine.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //     * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 //     * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 //     * Neither the name of Google Inc. nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_diameter_comm_Engine_hpp
38 #define anna_diameter_comm_Engine_hpp
39
40
41 // STL
42 #include <map>
43 #include <string>
44 #include <algorithm>
45
46 #include <anna/app/Component.hpp>
47 #include <anna/core/util/Recycler.hpp>
48
49 #include <anna/diameter.comm/Server.hpp>
50 #include <anna/diameter.comm/ServerSession.hpp>
51 #include <anna/config/defines.hpp>
52 #include <anna/diameter.comm/ClientSession.hpp>
53 #include <anna/diameter.comm/ServerSession.hpp>
54
55 // Standard
56 #include <time.h>
57
58
59 //------------------------------------------------------------------------------
60 //---------------------------------------------------------------------- #define
61 //------------------------------------------------------------------------------
62
63 namespace anna {
64 class DataBlock;
65 class Millisecond;
66 }
67
68
69
70 namespace anna {
71
72 namespace diameter {
73
74 namespace codec {
75 class Engine;
76 }
77
78 namespace comm {
79
80
81 class Entity;
82 class Server;
83 class LocalServer;
84
85 /**
86  *  General manager for connections to several diameter servers and from diameter clients.
87  *
88  *  Optimizes creation, finding and releasing of established client-sessions to a certain number of
89  *  diameter servers through entities.
90  *  Optimizes creation, finding and releasing of established server-sessions from a certain number of
91  *  diameter clients through local servers.
92  *
93  *  Implementation example:
94  *
95  *  \code
96  *
97  *     class MyEngine : public diameter::comm::Engine {
98  *     public:
99  *        MyEngine () {;}
100  *
101  *     private:
102  *        anna::Recycler<MyEntity> a_entities;
103  *
104  *        anna::diameter::comm::Entity* allocateEntity () throw () { return a_entities.create (); }
105  *
106  *        void releaseEntity (anna::diameter::comm::Entity* entity) throw () {
107  *           MyEntity* aux = static_cast <MyEntity*> (entity);
108  *           a_entities.release (aux);
109  *        }
110  *
111  *
112  *        anna::diameter::comm::LocalServer* allocateLocalServer () throw () { return a_localServers.create (); }
113  *
114  *        void releaseLocalServer (anna::diameter::comm::LocalServer* localServer) throw () {
115  *           MyLocalServer* aux = static_cast <MyLocalServer*> (localServer);
116  *           a_localServers.release (aux);
117  *        }
118  *     };
119  *
120  *  \endcode
121  */
122 class Engine : public anna::app::Component {
123 public:
124
125   /**
126      Logical name for this anna::app::Component.
127      \return Logical name for this anna::app::Component.
128   */
129   static const char* getClassName() throw() { return "anna::diameter::comm::Engine"; }
130
131   /**
132      Diameter application node realm name (used to be the site domain name).
133
134      @param name Diameter application node realm name. Used in order to configure the Origin-Realm for outgoing messages.
135      If not configured or empty string provided, host domainname will be set.
136   */
137   void setRealm(const std::string & name) throw();
138
139
140   /**
141      Gets the configured diameter application node realm name.
142
143      @return Diameter application node realm name.
144   */
145   const std::string & getRealm() const throw() { return a_realm; }
146
147
148   /**
149      Diameter application host name as solved by #anna::functions::getHostname()
150
151      @param name Host name. Used in order to configure the Origin-Host for outgoing messages.
152      If not configured or empty string provided, hostname (system name) will be set.
153   */
154   void setHost(const std::string & name) throw();
155
156
157   /**
158      Gets the configured diameter application host name.
159
160      @return Diameter application host name.
161   */
162   const std::string & getHost() const throw() { return a_host; }
163
164
165   /**
166    * Propagate auto recovery configuration to entities within engine. Recovery period is configured at
167    * #anna::comm::Communicator::setRecoveryTime. All the client client-sessions created throught #createEntity,
168    * will be created based on the engine auto-recovery value (enable by default). But you could access entities,
169    * servers or client-sessions independently to change this behaviour.
170    *
171    * @param autoRecovery Auto recovery indicator. True by default.
172    */
173   void raiseAutoRecovery(bool autoRecovery = true) throw(anna::RuntimeException);
174
175   /**
176    * Returns automatic bind indicator for client-sessions. By default \em true will be used.
177    * \return Value for automatic connection bind.
178    */
179   bool getAutoBind() const throw() { return a_autoBind; }
180
181   /**
182    * Sets automatic connection bind indicator for client-sessions. If not asigned, it will be \em true.
183    * \param autoBind Value for automatic connection bind.
184    *
185    * In order to change bind timer, first client-session must be created without autobind, modify time
186    * parameter and then invoking bind.
187    */
188   void setAutoBind(const bool autoBind) throw() { a_autoBind = autoBind; }
189
190   /**
191      Sets the milliseconds wait to achieve a client connection to server by mean connect primitive.
192      This is a general value for born client-sessions over engine. Particular configuration could be done
193      through #ClientSession::setMaxConnectionDelay.
194
195      \param maxConnectionDelay Milliseconds wait to get connection
196   */
197   void setMaxConnectionDelay(const anna::Millisecond & maxConnectionDelay) throw() { a_maxConnectionDelay = maxConnectionDelay; }
198
199   /**
200      Gets the milliseconds wait to achieve a client connection to server by mean connect primitive.
201      Returns the global engine value, but it could be overwritten through each client session (#ClientSession::setMaxConnectionDelay).
202      Default value is 'anna::comm::ClientSocket::DefaultMaxConnectionDelay'.
203
204      \return Milliseconds wait to get connection
205   */
206   const anna::Millisecond & getMaxConnectionDelay() throw() { return a_maxConnectionDelay; }
207
208   /**
209    * Binds engine entities.
210    *
211    * @return Returns true if all client-session were successfully bound
212    */
213   bool bind() throw(anna::RuntimeException);
214
215   /**
216    * Sets CER and DWR diameter messages to be used over created client-sessions.
217    * Its recommended to set this global configuration although it is possible to configure each client-session separately.
218    *
219    * @param cer Capabilities-Exchange-Request message (encoded) for the client-sessions bind.
220    * @param dwr Device-Watchdog-Request message (encoded) for the client-sessions keep-alive.
221    */
222   void setCERandDWR(const anna::DataBlock & cer, const anna::DataBlock & dwr) throw(anna::RuntimeException);
223
224
225   /**
226    * Sets the watchdog period (DWR) for client-sessions.
227    * Its recommended to set this global configuration although it is possible to configure each client-session separately.
228    *
229    * @param wp Watchdog period.
230    */
231   void setWatchdogPeriod(const anna::Millisecond & wp) throw(anna::RuntimeException);
232
233   /**
234    * Gets the number of client-sessions per server.
235    * \return numberOfClientSessionsPerServer Number of client-sessions per server.
236    */
237   int getNumberOfClientSessionsPerServer() const throw() { return a_numberOfClientSessionsPerServer; }
238
239   /**
240    * Sets the number of client-sessions per server.
241    * Its recommended to set this global configuration although it is possible to configure each client-session separately.
242    * \param numberOfClientSessionsPerServer Number of client-sessions per server.
243    */
244   void setNumberOfClientSessionsPerServer(int numberOfClientSessionsPerServer) throw() { a_numberOfClientSessionsPerServer = numberOfClientSessionsPerServer; }
245
246   /**
247    * Gets true when end-to-end sequence is freezed on requests sendings.
248    * Engine starts with false value, sequencing end-to-end as hop-by-hop does.
249    * \return Freeze end-to-end indicator.
250    */
251   bool getFreezeEndToEndOnSending() const throw() { return a_freezeEndToEndOnSending; }
252
253   /**
254    * Freeze end-to-end indicator on requests sendings.
255    * \param freezeEndToEndOnSending Freeze end-to-end indicator.
256    */
257   void setFreezeEndToEndOnSending(bool freezeEndToEndOnSending = true) throw() { a_freezeEndToEndOnSending = freezeEndToEndOnSending; }
258
259   /**
260    * Returns client-session instance identified by (address, port, socketId) provided.
261    *
262    * \param addr Diameter server address (ip or hostname).
263    * \param port Diameter server port.
264    * @param socketId Diameter server socket id.
265    * \param emode Action when no client-session is found with provided parameters (Throw/Ignore).
266    *
267    * \return The client-session instance identified by (address, port, socketId) provided.
268    *
269    * \warning If no client-session found, an exception is launched by default.
270    */
271   ClientSession* findClientSession(const std::string & addr, int port, int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
272
273
274   /**
275    * Same as #findClientSession, but providing client session key (<address>:<port>|<socket id>)
276    */
277   ClientSession* findClientSession(const std::string & key, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
278
279
280   /**
281    * Returns server instance identified by pair (address, port) provided.
282    *
283    * \param addr Diameter server address (ip or hostname).
284    * \param port Diameter server port.
285    * \param emode Action when no client-session is found with provided parameters (Throw/Ignore).
286    *
287    * \return The server instance identified by pair (address, port) provided.
288    *
289    * \warning If no server found, an exception is launched by default.
290    */
291   Server* findServer(const std::string & addr, int port, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
292
293   /**
294    * Returns entity instance identified by internal index.
295    *
296    * \param socketList Diameter entity servers list.
297    * \param emode Action when no client-session is found with provided parameters (Throw/Ignore).
298    *
299    * \return The entity instance identified by id provided.
300    *
301    * \warning If no entity found, an exception is launched by default.
302    */
303   Entity* findEntity(const socket_v & socketList, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
304
305   /**
306    * Returns entity instance identified by internal index.
307    *
308    * \param addr1 Diameter primary server address (ip or hostname).
309    * \param port1 Diameter primary server port.
310    * \param addr2 Diameter secondary server address (ip or hostname).
311    * \param port2 Diameter secondary server port.
312    * \param emode Action when no client-session is found with provided parameters (Throw/Ignore).
313    *
314    * \return The entity instance identified by id provided.
315    *
316    * \warning If no entity found, an exception is launched by default.
317    */
318   Entity* findEntity(const std::string & addr1, int port1, const std::string & addr2, int port2, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
319
320   /**
321    * Creates a diameter entity with provided parameters.
322    *
323    * Depending on auto-bind configuration, capabilities exchange request will be or won't be performed over the entity client-sessions.
324    *
325    * \param socketList Diameter server priority list (priority-ordered) in order to define whole entity.
326    * @param description Optional entity description (empty by default)
327    *
328    * \return The entity created or exception when any server (address/port) already exists for another entity.
329    *
330    * \warning The entity won't be almost operative until a notification by mean 'ClientSession::eventResponse'
331    * indicates that 'ClassCode::Bind' has been correctly performed for any included client-session.
332    */
333   Entity* createEntity(const socket_v & socketList, const std::string & description = "")
334   throw(anna::RuntimeException);
335
336   /**
337    * Creates a standard (dual) diameter entity with provided parameters.
338    *
339    * Depending on auto-bind configuration, capabilities exchange request will be or won't be performed over the entity client-sessions.
340    *
341    * \param addr1 Diameter primary server address (ip or hostname).
342    * \param port1 Diameter primary server port.
343    * \param addr2 Diameter secondary server address (ip or hostname).
344    * \param port2 Diameter secondary server port.
345    * @param description Optional entity description (empty by default)
346    *
347    * \return The standard entity created or exception when any server (address/port) already exists for another entity.
348    *
349    * \warning The entity won't be almost operative until a notification by mean 'ClientSession::eventResponse'
350    * indicates that 'ClassCode::Bind' has been correctly performed for any included client-session.
351    */
352   Entity* createEntity(const std::string & addr1, int port1, const std::string & addr2, int port2, const std::string & description = "")
353   throw(anna::RuntimeException);
354
355
356   /**
357    * Returns local server instance identified by pair (address, port) provided.
358    *
359    * @param addr Diameter server socket address (ip or hostname).
360    * @param port Diameter server socket port.
361    * \param emode Action when no local server is found with provided parameters (Throw/Ignore).
362    *
363    * \return The local server instance identified by pair (address, port) provided.
364    *
365    * \warning If no local server found, an exception is launched by default.
366    */
367   LocalServer* findLocalServer(const std::string & addr, int port, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
368
369   /**
370    * Returns server-session instance identified by INetAddress serialization provided.
371    *
372    * @param socketId Hash for Client Socket INetAddress serialization
373    * \param emode Action when no server-session is found with provided parameters (Throw/Ignore).
374    *
375    * \return The server-session instance identified by global unique socketId provided.
376    *
377    * \warning If no server-session found, an exception is launched by default.
378    */
379   ServerSession* findServerSession(int socketId, anna::Exception::Mode::_v emode = anna::Exception::Mode::Throw) throw(anna::RuntimeException);
380
381   /**
382    * Creates a diameter local server with provided parameters.
383    *
384    * Server socket address could be an IPv4 or hostname. Default port will be standard 3868 for diameter agents,
385    * but any other could be configured. Socket server could be created with any max accepted connections: zero
386    * value means temporarily disabled and negative values assume no limit (shared bind) for incomming connections.
387    *
388    * @param addr Diameter server socket address (ip or hostname).
389    * @param port Diameter server socket port (standard 3868 by default).
390    * @param maxConnections Diameter server max sessions allowed (no limit by default).
391    * @param allowedInactivityTime Max inactivity time for server sessions over the local server before being reset.
392    * @param category Optional socket server category (1 by default).
393    * @param description Optional socket server description (empty by default).
394    *
395    * \return The local server created or exception when is already created.
396    */
397   LocalServer *createLocalServer(const std::string & addr, int port = Session::DefaultPort, int maxConnections = -1, const anna::Millisecond & allowedInactivityTime = ServerSession::DefaultAllowedInactivityTime, int category = 1, const std::string & description = "")
398   throw(anna::RuntimeException);
399
400
401   /**
402      Close all the engine resources (entities and local servers)
403      Optionally all resources may be freed passing true
404
405      @param destroy Free all engine entity resources
406   */
407   void close(bool destroy = false) throw(anna::RuntimeException) { closeEntities(destroy); closeLocalServers(destroy); }
408
409
410   /**
411      Close all the engine entities (close servers, then close client-sessions within them). Depending on client-session configuration
412      ('OnDisconnect' behaviour), pending answers will be wait (graceful) or ignored (immediate-abrupt close).
413      Optionally all entities resources may be freed passing true; in this case, close is immediately performed:
414      @param destroy Free all engine entity resources
415   */
416   void closeEntities(bool destroy = false) throw(anna::RuntimeException);
417
418
419   /**
420    * Close entity servers (then, client-sessions included) and optionally free resources including entity itself.
421    * If entity is null, this operation has no effect.
422    *
423    * \param entity Diameter entity to be closed.
424    * \param destroy Deletes entity over the engine and all its resources.
425    */
426   void closeEntity(Entity* entity, bool destroy = false) throw(anna::RuntimeException);
427
428
429   /**
430      Close all the engine local server sockets including their children server sessions.
431      Optionally all local server resources may be freed passing true.
432
433      @param destroy Free all engine local servers resources and server sessions within them.
434   */
435   void closeLocalServers(bool destroy = false) throw(anna::RuntimeException);
436
437   /**
438    * Close local server socket and its children server sessions.
439    * This is useful when detecting service lost. When service is ready to handle traffic, a new server socket would
440    * be created by mean #LocalServer::enable() and new connections could be accepted.
441    * Optionally local server resources may be freed passing true.
442    *
443    * \param localServer Local server to be closed.
444    * \param destroy Deletes local server over engine and all its resources (server sessions within it).
445    */
446   void closeLocalServer(LocalServer * localServer, bool destroy = false) throw(anna::RuntimeException);
447
448   /**
449      Gets the number of requests messages over-the-air for entities.
450
451      @return OTA messages.
452   */
453   int getOTARequestsForEntities() const throw();
454
455   /**
456      Gets the number of requests messages over-the-air for local servers.
457
458      @return OTA messages.
459   */
460   int getOTARequestsForLocalServers() const throw();
461
462   /**
463      Gets the number of requests messages over-the-air for entities plus local servers.
464
465      @return OTA messages.
466   */
467   int getOTARequests() const throw() { return (getOTARequestsForEntities() + getOTARequestsForLocalServers()); }
468
469   /**
470      Returns idle state (no pending answers) for entities.
471
472      @return Idle state.
473   */
474   bool idleForEntities() const throw() { return (getOTARequestsForEntities() == 0); }
475
476   /**
477      Returns idle state (no pending answers).
478
479      @return Idle state.
480   */
481   bool idleForLocalServers() const throw() { return (getOTARequestsForLocalServers() == 0); }
482
483   /**
484      Returns idle state (no pending answers for entities or local servers).
485
486      @return Idle state.
487   */
488   bool idle() const throw() { return (getOTARequests() == 0); }
489
490   /**
491      Sent a message to all the engine entities.
492      It is used, i.e., in Disconnect-Peer-Request procedure over the engine.
493
494      \param message Message which is being sent.
495
496      @return Returns true (success) only when broadcast is success over all the engine entities. If any entity fails,
497      then false is returned. Broadcast try to send all over the resources in spite of any fail.
498   */
499   bool broadcastEntities(const Message*message) throw(anna::RuntimeException);
500   bool broadcastEntities(const Message& message) throw(anna::RuntimeException) { return broadcastEntities(&message); }
501
502   /**
503      Sent a message through all the engine local servers.
504      It is used, i.e., in Disconnect-Peer-Request procedure over the engine.
505
506      \param message Message which is being sent.
507
508      @return Returns true (success) only when broadcast is success over all the engine local servers. If any local server fails,
509      then false is returned. Broadcast try to send all over the resources in spite of any fail.
510   */
511   bool broadcastLocalServers(const Message*message) throw(anna::RuntimeException);
512   bool broadcastLocalServers(const Message& message) throw(anna::RuntimeException) { return broadcastLocalServers(&message); }
513
514   /**
515   * Class string representation
516   *
517   * @return String with class content
518   */
519   virtual std::string asString(void) const throw();
520
521   /**
522      Class XML representation.
523      \param parent XML node over which we will put instance information.
524      \return XML documentcon with class content.
525   */
526   virtual anna::xml::Node* asXML(anna::xml::Node* parent) const throw();
527
528
529   /**
530      When there is not bound server session over the engine, this virtual method will be invoked.
531      Applications must decide to do any other tasks at this idle/isolated situation.
532      Default implementation do nothing.
533   */
534   virtual void availabilityLostForLocalServers(Engine *) const throw() {;}
535
536   /**
537      When there is any bound server session over the engine, this virtual method will be invoked.
538      Applications must decide to do be ready for incoming traffic.
539      Default implementation do nothing.
540   */
541   virtual void availabilityRecoveredForLocalServers(Engine *) const throw() {;}
542
543   /**
544      When there is not bound entity over the engine, this virtual method will be invoked.
545      Many applications must change communicator status to Unavailable when no engines are available.
546      Default implementation do nothing.
547   */
548   virtual void availabilityLostForEntities(Engine *) const throw() {;}
549
550   /**
551      When there is any bound entity over the engine, this virtual method will be invoked.
552      Many applications must recover communicator status to Available when any engine are available.
553      Default implementation do nothing.
554   */
555   virtual void availabilityRecoveredForEntities(Engine *) const throw() {;}
556
557   /**
558      When there is not bound server-session over the local server, this virtual method will be invoked.
559      Default implementation do nothing.
560   */
561   virtual void availabilityLost(LocalServer *) const throw() {;}
562
563   /**
564      When there is any bound server-session over the local server, this virtual method will be invoked.
565      Default implementation do nothing.
566   */
567   virtual void availabilityRecovered(LocalServer *) const throw() {;}
568
569   /**
570      When there is not bound server over the entity, this virtual method will be invoked.
571      Default implementation do nothing.
572   */
573   virtual void availabilityLost(Entity *) const throw() {;}
574
575   /**
576      When there is any bound server over the entity, this virtual method will be invoked.
577      Default implementation do nothing.
578   */
579   virtual void availabilityRecovered(Entity *) const throw() {;}
580
581   /**
582      When there is not bound client-session over the server, this virtual method will be invoked.
583      Default implementation do nothing.
584   */
585   virtual void availabilityLost(Server *) const throw() {;}
586
587   /**
588      When there is any bound client-session over the server, this virtual method will be invoked.
589      Default implementation do nothing.
590   */
591   virtual void availabilityRecovered(Server *) const throw() {;}
592
593   /**
594      When a subyacent client session is going to be bound, this method is invoked before.
595      Default implementation do nothing.
596   */
597   virtual void bindingClientSession(const ClientSession *) const throw() {;}
598
599   /**
600    * Class user should implement this method in order to define Disconnect-Peer-Answer for last received DPR.
601    * Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name).
602    * Default implementation imply DPA with DIAMETER_SUCCESS Result-Code, allowing remote disconnection.
603    * Any other implementation is responsible to build a valid DPA diameter message.
604    * DPR/DPA procedure is disabled with empty definition of this method: no DPA will be sent when DPR is received.
605    *
606    * @param dpa DPA datablock passed as reference
607    * @param dpr Corresponding DPR received (sequence values must be taken into account in order to build DPA)
608   */
609   virtual void readDPA(anna::DataBlock &dpa, const anna::DataBlock & dpr) throw();
610
611   /**
612    * Class user should implement this method in order to define Capabilities-Exchange-Answer for received CER over server socket.
613    * Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name).
614    * Default implementation imply CEA with DIAMETER_SUCCESS Result-Code, and own domain node parameters, but application should
615    * analyze the CER message in order to accept it or not (with apropiate non-success Result-Code).
616    * Any other implementation is responsible to build a valid CEA diameter message:
617    *
618    * If one peer sends a CER message to another Peer and receiver does not have support for
619    *
620    *  1) any common application then it must return the CEA with Result-Code Avp set to DIAMETER_NO_COMMON_APPLICATION
621    *     and should disconnect the transport layer connection (automatically done by diameter::comm module).
622    *  2) no common security mechanism then it must return the CEA with Result-Code Avp set to DIAMETER_NO_COMMON_SECURITY
623    *     and should disconnect the transport layer connection (automatically done by diameter::comm module).
624    *  3) if CER is received from any unknown peer then receiver should discard the message, or send the CEA with the
625    *     Result-Code Avp set to DIAMETER_UNKNOWN_PEER.
626    *
627    *  If the local implementation policy permits to receive CER from unknown hosts, a successful CEA MAY be returned,
628    *  and the life time of the peer entry in PEER-Table is equal to the lifetime of the transport connection.
629    *  If in any case transport connection fails then all the pending transactions destined to the unknown peer can be discarded.
630    *
631    *  The CER and CEA messages MUST NOT be proxied, redirected or relayed. Since CER/CEA messages can not be proxied, but still
632    *  it is possible that proxy will receive a CER message and proxy does not have any peer to handle the application requested
633    *  in CER, in this case proxy set the E bit in CEA and set the Result-Code Avp to DIAMETER_UNABLE_TO_DELIVER, sends back to
634    *  CER generator peer.
635    *
636    * @param cea CEA datablock passed as reference. Empty cea implies to discard CER received.
637    * @param cer Corresponding CER received (sequence values must be taken into account in order to build CEA)
638   */
639   virtual void readCEA(anna::DataBlock &cea, const anna::DataBlock & cer) throw();
640
641   /**
642    * Class user should implement this method in order to define Device-Watchdog-Answer for received DWR over server socket.
643    * Origin-Host and Origin-Realm are configured at comm::Engine with hostname and FQDN (Fully Qualified Domain Name).
644    * Default implementation imply DWA with DIAMETER_SUCCESS Result-Code, and own domain node parameters.
645    * Any other implementation is responsible to build a valid DWA diameter message.
646    *
647    * @param dwa DWA datablock passed as reference
648    * @param dwr Corresponding DWR received (sequence values must be taken into account in order to build DWA)
649   */
650   virtual void readDWA(anna::DataBlock &dwa, const anna::DataBlock & dwr) throw();
651
652   /**
653      Reset engine statistics.
654      At the moment, only diameter servers processing time is observed.
655   */
656   void resetStatistics() throw();
657
658
659 protected:
660   /**
661      Constructor.
662   */
663   Engine();
664
665
666   // INTERNAL CREATORS AND CLOSE METHODS
667   Server *createServer(Entity*, const socket_t&) throw(anna::RuntimeException);
668   void closeServer(Server*, bool) throw(anna::RuntimeException);
669   ClientSession *createClientSession(Server*, int) throw(anna::RuntimeException);
670   void closeClientSession(ClientSession*, bool) throw(anna::RuntimeException);
671
672   // INTERNAL ALLOCATORS
673   Server* allocateServer() throw();
674   void releaseServer(Server*) throw();
675   ClientSession* allocateClientSession() throw();
676   void releaseClientSession(ClientSession*) throw();
677
678
679   /**
680      Entity allocator method.
681
682      It is recommended to use anna::Recycler for entities creation/releasing.
683
684      \see anna::Recycler
685   */
686   virtual Entity* allocateEntity() throw() { return NULL; }
687
688
689   /**
690      Invoked to free entities.
691      \see anna::Recycler
692   */
693   virtual void releaseEntity(Entity*) throw() {;}
694
695
696   /**
697      Local server allocator method.
698
699      It is recommended to use anna::Recycler for entities creation/releasing.
700
701      \see anna::Recycler
702   */
703   virtual LocalServer* allocateLocalServer() throw() { return NULL; }
704
705
706   /**
707      Invoked to free local servers.
708      \see anna::Recycler
709   */
710   virtual void releaseLocalServer(LocalServer*) throw() {;}
711
712
713
714 private:
715
716   std::string a_realm;
717   std::string a_host;
718   bool a_autoBind;
719   int a_numberOfClientSessionsPerServer;
720   bool a_freezeEndToEndOnSending;
721
722
723   // ClientSessions messages:
724   anna::DataBlock a_cer;
725   anna::DataBlock a_dwr;
726   anna::Millisecond a_watchdogPeriod;
727
728 //   // ServerSessions messages:
729 //   anna::DataBlock a_cea;
730 //   anna::DataBlock a_dwa;
731
732   // Client connectivity
733   anna::Millisecond a_maxConnectionDelay;
734
735
736   // Availability
737   bool a_availableForEntities; // any of the entities must be bound
738   void availabilityLostForEntities() throw();
739   void availabilityRecoveredForEntities() throw();
740   bool refreshAvailabilityForEntities() throw(); // return true if change
741
742   bool a_availableForLocalServers; // any of the local servers must be bound
743   void availabilityLostForLocalServers() throw();
744   void availabilityRecoveredForLocalServers() throw();
745   bool refreshAvailabilityForLocalServers() throw(); // return true if change
746
747   void eraseDeprecatedIdleEntities() throw();
748
749   // Component:
750   void do_initialize() throw() {;}
751   void do_stop() throw();
752
753   // Integrity:
754   void checkEntityCollision(const socket_v &) throw(anna::RuntimeException);
755
756
757   //////////////////////////
758   // CLIENT FUNCTIONALITY //
759   //////////////////////////
760
761   //typedef int clientSession_key; // exclusiveHash('ADDR:PORT|id')
762   typedef std::string clientSession_key; // 'ADDR:PORT|id'
763   typedef std::map <clientSession_key, ClientSession*> clientSession_container;
764   typedef clientSession_container::value_type clientSession_value_type;
765   typedef clientSession_container::iterator clientSession_iterator;
766   typedef clientSession_container::const_iterator const_clientSession_iterator;
767   clientSession_container a_clientSessions;
768   anna::Recycler<ClientSession> a_clientSessionsRecycler;
769   clientSession_iterator clientSession_find(const clientSession_key&) throw();
770   clientSession_iterator clientSession_begin() throw() { return a_clientSessions.begin(); }
771   clientSession_iterator clientSession_end() throw() { return a_clientSessions.end(); }
772   static ClientSession* clientSession(clientSession_iterator ii) throw() { return ii->second; }
773   const_clientSession_iterator clientSession_begin() const throw() { return a_clientSessions.begin(); }
774   const_clientSession_iterator clientSession_end() const throw() { return a_clientSessions.end(); }
775   static const ClientSession* clientSession(const_clientSession_iterator ii) throw() { return ii->second; }
776
777   typedef socket_t server_key;
778   server_key getServerKey(const std::string & addr, int port) const throw();
779   typedef std::map <server_key, Server*> server_container;
780   typedef server_container::value_type server_value_type;
781   typedef server_container::iterator server_iterator;
782   typedef server_container::const_iterator const_server_iterator;
783   server_container a_servers;
784   anna::Recycler<Server> a_serversRecycler;
785   server_iterator server_find(const server_key&) throw();
786   server_iterator server_begin() throw() { return a_servers.begin(); }
787   server_iterator server_end() throw() { return a_servers.end(); }
788   static Server* server(server_iterator ii) throw() { return ii->second; }
789   const_server_iterator server_begin() const throw() { return a_servers.begin(); }
790   const_server_iterator server_end() const throw() { return a_servers.end(); }
791   static const Server* server(const_server_iterator ii) throw() { return ii->second; }
792
793   //typedef int entity_key; // exclusiveHash('IP1:PORT1 IP2:PORT2 IP3:PORT3 ...')
794   typedef std::string entity_key; // 'ADDR1:PORT1 ADDR2:PORT2 ADDR3:PORT3 ...'
795   entity_key getEntityKey(const socket_v &) const throw();
796   entity_key getEntityKey(const std::string & addr1, int port1, const std::string & addr2, int port2) const throw();
797   typedef std::map <entity_key, Entity*> entity_container;
798   typedef entity_container::value_type entity_value_type;
799   typedef entity_container::iterator entity_iterator;
800   typedef entity_container::const_iterator const_entity_iterator;
801   entity_container a_entities;
802   entity_iterator entity_find(const entity_key&) throw();
803   entity_iterator entity_begin() throw() { return a_entities.begin(); }
804   entity_iterator entity_end() throw() { return a_entities.end(); }
805   static Entity* entity(entity_iterator ii) throw() { return ii->second; }
806   const_entity_iterator entity_begin() const throw() { return a_entities.begin(); }
807   const_entity_iterator entity_end() const throw() { return a_entities.end(); }
808   static const Entity* entity(const_entity_iterator ii) throw() { return ii->second; }
809
810
811   //////////////////////////
812   // SERVER FUNCTIONALITY //
813   //////////////////////////
814
815   // Local servers
816   typedef std::map <socket_t, LocalServer*> localServer_container;
817   typedef localServer_container::value_type localServer_value_type;
818   typedef localServer_container::iterator localServer_iterator;
819   typedef localServer_container::const_iterator const_localServer_iterator;
820   localServer_container a_localServers;
821   localServer_iterator localServer_find(const socket_t&) throw();
822   localServer_iterator localServer_begin() throw() { return a_localServers.begin(); }
823   localServer_iterator localServer_end() throw() { return a_localServers.end(); }
824   static LocalServer* localServer(localServer_iterator ii) throw() { return ii->second; }
825   const_localServer_iterator localServer_begin() const throw() { return a_localServers.begin(); }
826   const_localServer_iterator localServer_end() const throw() { return a_localServers.end(); }
827   static const LocalServer* localServer(const_localServer_iterator ii) throw() { return ii->second; }
828
829   // Server sessions are managed within LocalServer (not at engine) due to dynamic cration nature
830
831
832   friend class Session;
833   friend class ServerSession;
834   friend class ServerSocket;
835   friend class Server;
836   friend class Entity;
837   friend class LocalServer;
838   //friend class Message;
839 };
840
841 }
842 }
843 }
844
845 #endif
846