Yate
|
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: */