Yate
yatemgcp.h
00001 
00024 #ifndef __YATEMGCP_H
00025 #define __YATEMGCP_H
00026 
00027 #include <yateclass.h>
00028 #include <yatemime.h>
00029 
00030 #ifdef _WINDOWS
00031 
00032 #ifdef LIBYMGCP_EXPORTS
00033 #define YMGCP_API __declspec(dllexport)
00034 #else
00035 #ifndef LIBYMGCP_STATIC
00036 #define YMGCP_API __declspec(dllimport)
00037 #endif
00038 #endif
00039 
00040 #endif /* _WINDOWS */
00041 
00042 #ifndef YMGCP_API
00043 #define YMGCP_API
00044 #endif
00045 
00049 namespace TelEngine {
00050 
00051 class MGCPMessage;
00052 class MGCPTransaction;
00053 class MGCPEpInfo;
00054 class MGCPEndpoint;
00055 class MGCPEvent;
00056 class MGCPEngine;
00057 
00063 class YMGCP_API MGCPMessage : public RefObject
00064 {
00065     friend class MGCPTransaction;
00066 public:
00077     MGCPMessage(MGCPEngine* engine, const char* name, const char* ep, const char* ver = "MGCP 1.0");
00078 
00087     MGCPMessage(MGCPTransaction* trans, unsigned int code, const char* comment = 0);
00088 
00092     virtual ~MGCPMessage();
00093 
00098     inline bool valid() const
00099         { return m_valid; }
00100 
00105     inline const String& name() const
00106         { return m_name; }
00107 
00112     inline int code() const
00113         { return m_code; }
00114 
00119     inline const String& version() const
00120         { return m_version; }
00121 
00126     inline const String& comment() const
00127         { return m_comment; }
00128 
00133     inline bool isCommand() const
00134         { return code() < 0; }
00135 
00140     inline bool isResponse() const
00141         { return 100 <= code(); }
00142 
00147     inline bool isAck() const
00148         { return 0 <= code() && code() <= 99; }
00149 
00154     inline unsigned int transactionId() const
00155         { return m_transaction; }
00156 
00161     inline const String& endpointId() const
00162         { return m_endpoint; }
00163 
00169     void toString(String& dest) const;
00170 
00183     static bool parse(MGCPEngine* engine, ObjList& dest,
00184         const unsigned char* buffer, unsigned int len,
00185         const char* sdpType = "application/sdp");
00186 
00190     NamedList params;
00191 
00195     ObjList sdp;
00196 
00197 protected:
00208     MGCPMessage(MGCPEngine* engine, const char* name, int code,
00209         unsigned int transId, const char* epId, const char* ver);
00210 
00211 private:
00212     MGCPMessage() : params("") {}        // Avoid using default constructor
00213     // Decode the message line
00214     static MGCPMessage* decodeMessage(const char* line, unsigned int len, unsigned int& trans,
00215         String& error, MGCPEngine* engine);
00216     // Decode message parameters. Return true if found a line containing a dot
00217     static bool decodeParams(const unsigned char* buffer, unsigned int len,
00218         unsigned int& crt, MGCPMessage* msg, String& error, MGCPEngine* engine);
00219 
00220     String m_name;                       // Command or string representation of response code
00221     bool m_valid;                        // False if this message is invalid
00222     int m_code;                          // Response code or -1 if this is a command
00223     unsigned int m_transaction;          // The id of the transaction this message belongs to
00224     String m_endpoint;                   // The id of the endpoint issuing this message
00225     String m_version;                    // The protocol version
00226     String m_comment;                    // The comment attached to a response message
00227 };
00228 
00233 class YMGCP_API MGCPTransaction : public RefObject, public Mutex
00234 {
00235     friend class MGCPEngine;             // Process a received message
00236     friend class MGCPEvent;              // Access to event termination notification
00237 public:
00241     enum State {
00242         Invalid      = 0,                // This is an invalid transaction (constructor failed)
00243         Initiated    = 1,                // An initial command message was sent/received
00244         Trying       = 2,                // Sent or received a provisional response to the initial message
00245         Responded    = 3,                // Sent or received a final response to the initial message
00246         Ack          = 4,                // Response was ack'd
00247         Destroying   = 5,                // Waiting to be removed from the engine
00248     };
00249 
00257     MGCPTransaction(MGCPEngine* engine, MGCPMessage* msg, bool outgoing,
00258         const SocketAddr& address);
00259 
00263     virtual ~MGCPTransaction();
00264 
00269     inline State state() const
00270         { return m_state; }
00271 
00276     inline unsigned int id() const
00277         { return m_id; }
00278 
00283     inline bool outgoing() const
00284         { return m_outgoing; }
00285 
00290     inline const String& ep() const
00291         { return m_endpoint; }
00292 
00297     const SocketAddr& addr() const
00298         { return m_address; }
00299 
00304     inline MGCPEngine* engine()
00305         { return m_engine; }
00306 
00311     inline const MGCPMessage* initial() const
00312         { return m_cmd; }
00313 
00318     inline const MGCPMessage* msgProvisional() const
00319         { return m_provisional; }
00320 
00325     inline const MGCPMessage* msgResponse() const
00326         { return m_response; }
00327 
00332     inline const MGCPMessage* msgAck() const
00333         { return m_ack; }
00334 
00339     inline bool timeout() const
00340         { return m_timeout; }
00341 
00346     inline void ackRequest(bool request)
00347         { m_ackRequest = request; }
00348 
00353     inline void* userData() const
00354         { return m_private; }
00355 
00360     inline void userData(void* data)
00361         { m_private = data; }
00362 
00368     MGCPEvent* getEvent(u_int64_t time = Time());
00369 
00376     bool sendProvisional(int code = 100, const char* comment = 0);
00377 
00385     inline bool setResponse(int code, const char* comment = 0)
00386         { return setResponse(new MGCPMessage(this,code,comment)); }
00387 
00398     bool setResponse(int code, const NamedList* params, MimeSdpBody* sdp1 = 0,
00399         MimeSdpBody* sdp2 = 0);
00400 
00407     bool setResponse(MGCPMessage* msg);
00408 
00409 protected:
00413     virtual void destroyed();
00414 
00419     void processMessage(MGCPMessage* msg);
00420 
00426     MGCPEvent* checkTimeout(u_int64_t time);
00427 
00432     void eventTerminated(MGCPEvent* event);
00433 
00438     void changeState(State newState);
00439 
00444     void setProvisional(int code = 100);
00445 
00450     void send(MGCPMessage* msg);
00451 
00452 private:
00453     MGCPTransaction() {}                 // Avoid using default constructor
00454     // Check if received any final response. Create an event. Init timeout.
00455     // Send a response ACK if requested by the response
00456     MGCPEvent* checkResponse(u_int64_t time);
00457     // Init timeout for retransmission or transaction termination
00458     void initTimeout(u_int64_t time, bool extra);
00459     // Remove from engine. Create event. Deref the transaction
00460     MGCPEvent* terminate();
00461 
00462     State m_state;                       // Current state
00463     unsigned int m_id;                   // Transaction id
00464     bool m_outgoing;                     // Transaction direction
00465     SocketAddr m_address;                // Remote andpoint's address
00466     MGCPEngine* m_engine;                // The engine owning this transaction
00467     MGCPMessage* m_cmd;                  // The command that created this transaction
00468     MGCPMessage* m_provisional;          // The provisional response to the command that created this transaction
00469     MGCPMessage* m_response;             // The response to the command that created this transaction
00470     MGCPMessage* m_ack;                  // The response aknowledgement message sent or received
00471     MGCPEvent* m_lastEvent;              // The last generated event
00472     String m_endpoint;                   // The endpoint owning this transaction
00473     u_int64_t m_nextRetrans;             // Retransission or destroy time
00474     unsigned int m_crtRetransInterval;   // Current retransmission interval
00475     unsigned int m_retransCount;         // Remainig number of retransmissions
00476     bool m_timeout;                      // Transaction timeout flag
00477     bool m_ackRequest;                   // Remote is requested to send ACK
00478     void* m_private;                     // Data used by this transaction's user
00479     String m_debug;                      // String used to identify the transaction in debug messages
00480 };
00481 
00486 class YMGCP_API MGCPEndpointId
00487 {
00488 public:
00492     inline MGCPEndpointId()
00493         : m_port(0)
00494         {}
00495 
00500     inline MGCPEndpointId(const String& src)
00501         : m_port(0)
00502         { set(src); }
00503 
00508     inline MGCPEndpointId(const MGCPEndpointId& value)
00509         : m_id(value.id()), m_endpoint(value.user()),
00510           m_host(value.host()), m_port(value.port())
00511         { }
00512 
00520     inline MGCPEndpointId(const char* endpoint, const char* host, int port, bool addPort = true)
00521         : m_port(0)
00522         { set(endpoint,host,port,addPort); }
00523 
00528     inline const String& id() const
00529         { return m_id; }
00530 
00535     inline const String& user() const
00536         { return m_endpoint; }
00537 
00542     inline const String& host() const
00543         { return m_host; }
00544 
00549     inline int port() const
00550         { return m_port; }
00551 
00557     inline void port(int newPort, bool addPort = true)
00558         { set(m_endpoint,m_host,newPort,addPort); }
00559 
00567     void set(const char* endpoint, const char* host, int port, bool addPort = true);
00568 
00573     inline void set(const String& src) {
00574             URI uri(src);
00575             set(uri.getUser(),uri.getHost(),uri.getPort());
00576         }
00577 
00584     inline bool valid() const {
00585             return m_endpoint && m_endpoint.length() < 256 &&
00586                 m_host && m_host.length() < 256;
00587         }
00588 
00589 private:
00590     String m_id;                         // The complete id
00591     String m_endpoint;                   // The endpoint's name inside the host
00592     String m_host;                       // Host of this endpoint
00593     int m_port;                          // Port used by this endpoint
00594 };
00595 
00600 class YMGCP_API MGCPEpInfo : public MGCPEndpointId, public GenObject
00601 {
00602 public:
00610     inline MGCPEpInfo(const char* endpoint, const char* host, int port, bool addPort = true)
00611         : MGCPEndpointId(endpoint,host,port,addPort),
00612           m_address(AF_INET), m_resolve(true) {
00613             m_address.port(port);
00614         }
00615 
00620     virtual const String& toString() const
00621         { return id(); }
00622 
00627     inline const SocketAddr& address() const
00628         { return m_address; }
00629 
00634     const SocketAddr& address();
00635 
00640     inline void address(const SocketAddr& addr)
00641         { m_resolve = false; m_address = addr; }
00642 
00646     String alias;
00647 
00648 private:
00649     SocketAddr m_address;
00650     bool m_resolve;
00651 };
00652 
00659 class YMGCP_API MGCPEndpoint : public RefObject, public MGCPEndpointId, public Mutex
00660 {
00661 public:
00671     MGCPEndpoint(MGCPEngine* engine, const char* user, const char* host, int port, bool addPort = true);
00672 
00676     virtual ~MGCPEndpoint();
00677 
00682     virtual const String& toString() const
00683         { return MGCPEndpointId::id(); }
00684 
00689     inline MGCPEngine* engine()
00690         { return m_engine; }
00691 
00704     MGCPEpInfo* append(const char* endpoint, const char* host, int port = 0);
00705 
00709     inline void clear()
00710         { lock(); m_remote.clear(); unlock(); }
00711 
00717     MGCPEpInfo* find(const String& epId);
00718 
00724     MGCPEpInfo* findAlias(const String& alias);
00725 
00730     MGCPEpInfo* peer();
00731 
00732 private:
00733     MGCPEngine* m_engine;                // The engine owning this endpoint
00734     ObjList m_remote;                    // The remote endpoints
00735 };
00736 
00742 class YMGCP_API MGCPEvent
00743 {
00744     friend class MGCPTransaction;
00745 public:
00749     ~MGCPEvent();
00750 
00755     inline MGCPTransaction* transaction()
00756         { return m_transaction; }
00757 
00762     inline MGCPMessage* message() const
00763         { return m_message; }
00764 
00765 protected:
00771     MGCPEvent(MGCPTransaction* trans, MGCPMessage* msg = 0);
00772 
00773 private:
00774     MGCPTransaction* m_transaction;      // The transaction that generated this event
00775     MGCPMessage* m_message;              // The message carried by this event, if any
00776 };
00777 
00778 class MGCPPrivateThread;
00779 
00789 class YMGCP_API MGCPEngine : public DebugEnabler, public Mutex
00790 {
00791     friend class MGCPPrivateThread;
00792     friend class MGCPTransaction;
00793 public:
00801     MGCPEngine(bool gateway, const char* name = 0, const NamedList* params = 0);
00802 
00806     virtual ~MGCPEngine();
00807 
00813     inline bool gateway() const
00814         { return m_gateway; }
00815 
00820     inline const SocketAddr& address() const
00821         { return m_address; }
00822 
00828     inline unsigned int maxRecvPacket() const
00829         { return m_maxRecvPacket; }
00830 
00835     inline bool allowUnkCmd() const
00836         { return m_allowUnkCmd; }
00837 
00842     inline unsigned int retransInterval() const
00843         { return m_retransInterval; }
00844 
00849     inline unsigned int retransCount() const
00850         { return m_retransCount; }
00851 
00856     inline u_int64_t extraTime() const
00857         { return m_extraTime; }
00858 
00863     inline bool parseParamToLower() const
00864         { return m_parseParamToLower; }
00865 
00870     inline bool provisional() const
00871         { return m_provisional; }
00872 
00877     inline bool ackRequest() const
00878         { return m_ackRequest; }
00879 
00884     inline void ackRequest(bool request)
00885         { m_ackRequest = request; }
00886 
00891     virtual void initialize(const NamedList& params);
00892 
00898     inline bool knownCommand(const String& cmd)
00899         { Lock lock(this); return (m_knownCommands.find(cmd) != 0); }
00900 
00905     void addCommand(const char* cmd);
00906 
00911     void attach(MGCPEndpoint* ep);
00912 
00920     void detach(MGCPEndpoint* ep, bool del = false, bool delTrans = false);
00921 
00927     MGCPEndpoint* findEp(MGCPEndpoint* ep);
00928 
00934     MGCPEndpoint* findEp(const String& epId);
00935 
00942     MGCPTransaction* findTrans(unsigned int id, bool outgoing);
00943 
00948     unsigned int getNextId();
00949 
00957     MGCPTransaction* sendCommand(MGCPMessage* cmd, const SocketAddr& address);
00958 
00966     bool receive(unsigned char* buffer, SocketAddr& addr);
00967 
00976     bool process(u_int64_t time = Time());
00977 
00981     void runReceive();
00982 
00986     void runProcess();
00987 
00993     MGCPEvent* getEvent(u_int64_t time = Time());
00994 
01003     virtual bool processEvent(MGCPEvent* event);
01004 
01013     virtual bool processEvent(MGCPTransaction* trans, MGCPMessage* msg);
01014 
01021     void returnEvent(MGCPEvent* event);
01022 
01032     void cleanup(bool gracefully = true, const char* text = "Shutdown");
01033 
01040     static inline int defaultPort(bool gateway)
01041         { return gateway ? 2427 : 2727; }
01042 
01047     virtual void timeout(MGCPTransaction* tr)
01048         { }
01049 
01053     static TokenDict mgcp_commands[];
01054 
01058     static TokenDict mgcp_responses[];
01059 
01067     static TokenDict mgcp_reasons[];
01068 
01069 protected:
01076     bool sendData(const String& msg, const SocketAddr& address);
01077 
01082     void appendTrans(MGCPTransaction* trans);
01083 
01089     void removeTrans(MGCPTransaction* trans, bool del);
01090 
01094     ObjList m_endpoints;
01095 
01099     ObjList m_transactions;
01100 
01104     ListIterator m_iterator;
01105 
01106 private:
01107     // Append a private thread to the list
01108     void appendThread(MGCPPrivateThread* thread);
01109     // Remove private thread from the list without deleting it
01110     void removeThread(MGCPPrivateThread* thread);
01111     // Process ACK received with a message or response
01112     // Return a list of ack'd transactions or 0 if the parameter is incorrect
01113     unsigned int* decodeAck(const String& param, unsigned int & count);
01114 
01115     bool m_gateway;                      // True if this engine is an MGCP gateway, false if call agent
01116     bool m_initialized;                  // True if the engine was already initialized
01117     unsigned int m_nextId;               // Next outgoing transaction id
01118     Socket m_socket;                     // The socket used to send/receive data
01119     SocketAddr m_address;                // The IP address used by this engine
01120     unsigned int m_maxRecvPacket;        // The maximum length or received packets
01121     unsigned char* m_recvBuf;            // Receiving buffer
01122     bool m_allowUnkCmd;                  // Allow this engine to send/accept unknown commands
01123     unsigned int m_retransInterval;      // Message retransmission interval
01124     unsigned int m_retransCount;         // Maximum number of retransmissions for a message
01125     u_int64_t m_extraTime;               // Time to live after the transaction terminated gracefully
01126     bool m_parseParamToLower;            // Convert received messages' params to lower case
01127     bool m_provisional;                  // Send provisional responses flag
01128     bool m_ackRequest;                   // Remote is requested to send ACK
01129     ObjList m_knownCommands;             // The list of known commands
01130     ObjList m_threads;
01131 };
01132 
01133 }
01134 
01135 #endif /* __YATEMGCP_H */
01136 
01137 /* vi: set ts=8 sw=4 sts=4 noet: */