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