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_port(0)
00510         { set(value.user(),value.host(),value.port()); }
00511 
00518     inline MGCPEndpointId(const char* endpoint, const char* host, int port)
00519         : m_port(0)
00520         { set(endpoint,host,port); }
00521 
00526     inline const String& id() const
00527         { return m_id; }
00528 
00533     inline const String& user() const
00534         { return m_endpoint; }
00535 
00540     inline const String& host() const
00541         { return m_host; }
00542 
00547     inline int port() const
00548         { return m_port; }
00549 
00554     inline void port(int newPort)
00555         { set(m_endpoint,m_host,newPort); }
00556 
00563     void set(const char* endpoint, const char* host, int port);
00564 
00569     inline void set(const String& src) {
00570             URI uri(src);
00571             set(uri.getUser(),uri.getHost(),uri.getPort());
00572         }
00573 
00580     inline bool valid() const {
00581             return m_endpoint && m_endpoint.length() < 256 &&
00582                 m_host && m_host.length() < 256;
00583         }
00584 
00585 private:
00586     String m_id;                         // The complete id
00587     String m_endpoint;                   // The endpoint's name inside the host
00588     String m_host;                       // Host of this endpoint
00589     int m_port;                          // Port used by this endpoint
00590 };
00591 
00596 class YMGCP_API MGCPEpInfo : public MGCPEndpointId, public GenObject
00597 {
00598 public:
00605     inline MGCPEpInfo(const char* endpoint, const char* host, int port)
00606         : MGCPEndpointId(endpoint,host,port), address(AF_INET) {
00607             address.host(host);
00608             address.port(port);
00609         }
00610 
00615     virtual const String& toString() const
00616         { return id(); }
00617 
00621     SocketAddr address;
00622 
00626     String alias;
00627 };
00628 
00635 class YMGCP_API MGCPEndpoint : public RefObject, public MGCPEndpointId, public Mutex
00636 {
00637 public:
00646     MGCPEndpoint(MGCPEngine* engine, const char* user, const char* host, int port);
00647 
00651     virtual ~MGCPEndpoint();
00652 
00657     virtual const String& toString() const
00658         { return MGCPEndpointId::id(); }
00659 
00664     inline MGCPEngine* engine()
00665         { return m_engine; }
00666 
00677     MGCPEpInfo* append(const char* endpoint, const char* host, int port = 0);
00678 
00682     inline void clear()
00683         { lock(); m_remote.clear(); unlock(); }
00684 
00690     MGCPEpInfo* find(const String& epId);
00691 
00697     MGCPEpInfo* findAlias(const String& alias);
00698 
00703     MGCPEpInfo* peer();
00704 
00705 private:
00706     MGCPEngine* m_engine;                // The engine owning this endpoint
00707     ObjList m_remote;                    // The remote endpoints
00708 };
00709 
00715 class YMGCP_API MGCPEvent
00716 {
00717     friend class MGCPTransaction;
00718 public:
00722     ~MGCPEvent();
00723 
00728     inline MGCPTransaction* transaction()
00729         { return m_transaction; }
00730 
00735     inline MGCPMessage* message() const
00736         { return m_message; }
00737 
00738 protected:
00744     MGCPEvent(MGCPTransaction* trans, MGCPMessage* msg = 0);
00745 
00746 private:
00747     MGCPTransaction* m_transaction;      // The transaction that generated this event
00748     MGCPMessage* m_message;              // The message carried by this event, if any
00749 };
00750 
00751 class MGCPPrivateThread;
00752 
00762 class YMGCP_API MGCPEngine : public DebugEnabler, public Mutex
00763 {
00764     friend class MGCPPrivateThread;
00765     friend class MGCPTransaction;
00766 public:
00774     MGCPEngine(bool gateway, const char* name = 0, const NamedList* params = 0);
00775 
00779     virtual ~MGCPEngine();
00780 
00786     inline bool gateway() const
00787         { return m_gateway; }
00788 
00793     inline const SocketAddr& address() const
00794         { return m_address; }
00795 
00801     inline unsigned int maxRecvPacket() const
00802         { return m_maxRecvPacket; }
00803 
00808     inline bool allowUnkCmd() const
00809         { return m_allowUnkCmd; }
00810 
00815     inline unsigned int retransInterval() const
00816         { return m_retransInterval; }
00817 
00822     inline unsigned int retransCount() const
00823         { return m_retransCount; }
00824 
00829     inline u_int64_t extraTime() const
00830         { return m_extraTime; }
00831 
00836     inline bool parseParamToLower() const
00837         { return m_parseParamToLower; }
00838 
00843     inline bool provisional() const
00844         { return m_provisional; }
00845 
00850     inline bool ackRequest() const
00851         { return m_ackRequest; }
00852 
00857     inline void ackRequest(bool request)
00858         { m_ackRequest = request; }
00859 
00864     virtual void initialize(const NamedList& params);
00865 
00871     inline bool knownCommand(const char* cmd)
00872         { Lock lock(this); return (m_knownCommands.find(cmd) != 0); }
00873 
00878     void addCommand(const char* cmd);
00879 
00884     void attach(MGCPEndpoint* ep);
00885 
00893     void detach(MGCPEndpoint* ep, bool del = false, bool delTrans = false);
00894 
00900     MGCPEndpoint* findEp(MGCPEndpoint* ep);
00901 
00907     MGCPEndpoint* findEp(const String& epId);
00908 
00915     MGCPTransaction* findTrans(unsigned int id, bool outgoing);
00916 
00921     unsigned int getNextId();
00922 
00930     MGCPTransaction* sendCommand(MGCPMessage* cmd, const SocketAddr& address);
00931 
00939     bool receive(unsigned char* buffer, SocketAddr& addr);
00940 
00949     bool process(u_int64_t time = Time());
00950 
00954     void runReceive();
00955 
00959     void runProcess();
00960 
00966     MGCPEvent* getEvent(u_int64_t time = Time());
00967 
00976     virtual bool processEvent(MGCPEvent* event);
00977 
00987     virtual bool processEvent(MGCPTransaction* trans, MGCPMessage* msg, void* data);
00988 
00995     void returnEvent(MGCPEvent* event);
00996 
01006     void cleanup(bool gracefully = true, const char* text = "Shutdown");
01007 
01014     static inline int defaultPort(bool gateway)
01015         { return gateway ? 2427 : 2727; }
01016 
01020     static TokenDict mgcp_commands[];
01021 
01025     static TokenDict mgcp_responses[];
01026 
01034     static TokenDict mgcp_reasons[];
01035 
01036 protected:
01043     bool sendData(const String& msg, const SocketAddr& address);
01044 
01049     void appendTrans(MGCPTransaction* trans);
01050 
01056     void removeTrans(MGCPTransaction* trans, bool del);
01057 
01061     ObjList m_endpoints;
01062 
01066     ObjList m_transactions;
01067 
01068 private:
01069     // Append a private thread to the list
01070     void appendThread(MGCPPrivateThread* thread);
01071     // Remove private thread from the list without deleting it
01072     void removeThread(MGCPPrivateThread* thread);
01073     // Process ACK received with a message or response
01074     // Return a list of ack'd transactions or 0 if the parameter is incorrect
01075     unsigned int* decodeAck(const String& param, unsigned int & count);
01076 
01077     bool m_gateway;                      // True if this engine is an MGCP gateway, false if call agent
01078     bool m_initialized;                  // True if the engine was already initialized
01079     unsigned int m_nextId;               // Next outgoing transaction id
01080     Socket m_socket;                     // The socket used to send/receive data
01081     SocketAddr m_address;                // The IP address used by this engine
01082     unsigned int m_maxRecvPacket;        // The maximum length or received packets
01083     unsigned char* m_recvBuf;            // Receiving buffer
01084     bool m_allowUnkCmd;                  // Allow this engine to send/accept unknown commands
01085     unsigned int m_retransInterval;      // Message retransmission interval
01086     unsigned int m_retransCount;         // Maximum number of retransmissions for a message
01087     u_int64_t m_extraTime;               // Time to live after the transaction terminated gracefully
01088     bool m_parseParamToLower;            // Convert received messages' params to lower case
01089     bool m_provisional;                  // Send provisional responses flag
01090     bool m_ackRequest;                   // Remote is requested to send ACK
01091     ObjList m_knownCommands;             // The list of known commands
01092     ObjList m_threads;
01093 };
01094 
01095 }
01096 
01097 #endif /* __YATEMGCP_H */
01098 
01099 /* vi: set ts=8 sw=4 sts=4 noet: */