yate/libs/ymgcp/yatemgcp.h

1164 lines
39 KiB
C++

/**
* yatemgcp.h
* Yet Another MGCP Stack
* This file is part of the YATE Project http://YATE.null.ro
*
* Yet Another Telephony Engine - a fully featured software PBX and IVR
* Copyright (C) 2004-2023 Null Team
*
* This software is distributed under multiple licenses;
* see the COPYING file in the main directory for licensing
* information for this specific distribution.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __YATEMGCP_H
#define __YATEMGCP_H
#include <yateclass.h>
#include <yatemime.h>
#ifdef _WINDOWS
#ifdef LIBYMGCP_EXPORTS
#define YMGCP_API __declspec(dllexport)
#else
#ifndef LIBYMGCP_STATIC
#define YMGCP_API __declspec(dllimport)
#endif
#endif
#endif /* _WINDOWS */
#ifndef YMGCP_API
#define YMGCP_API
#endif
/**
* Holds all Telephony Engine related classes.
*/
namespace TelEngine {
class MGCPMessage;
class MGCPTransaction;
class MGCPEpInfo;
class MGCPEndpoint;
class MGCPEvent;
class MGCPEngine;
/**
* This class holds an MGCP message, either command or response, along with
* its parameters. The
* @short An MGCP command or response
*/
class YMGCP_API MGCPMessage : public RefObject
{
friend class MGCPTransaction;
public:
/**
* Constructor. Construct an outgoing command message.
* A transaction id will be requested from the endpoint's engine.
* The message will be invalidated if failed to get a transaction id or the
* command name is unknown
* @param engine The engine sending this message
* @param name Command name
* @param ep The id of the endpoint issuing this command
* @param ver The protocol version to use
*/
MGCPMessage(MGCPEngine* engine, const char* name, const char* ep, const char* ver = "MGCP 1.0");
/**
* Constructor. Construct an outgoing response message
* The message will be invalidated if failed to get a transaction id or the
* code is greater then 999
* @param trans The transaction to respond
* @param code The response code ranging from 0 to 999
* @param comment Optional response comment
*/
MGCPMessage(MGCPTransaction* trans, unsigned int code, const char* comment = 0);
/**
* Destructor
*/
virtual ~MGCPMessage();
/**
* Check if this is a valid message
* @return True if this is a valid message
*/
inline bool valid() const
{ return m_valid; }
/**
* Get the command name or response code text representation of this message
* @return The command name or response text representation of this message
*/
inline const String& name() const
{ return m_name; }
/**
* Get the response code if this is a response message
* @return The response code contained in this message
*/
inline int code() const
{ return m_code; }
/**
* Get the protocol version of a command message
* @return The protocol version of this message
*/
inline const String& version() const
{ return m_version; }
/**
* Get the comment from a response message
* @return The comment of this message
*/
inline const String& comment() const
{ return m_comment; }
/**
* Check if this is a command (code is a negative value)
* @return True if this message is a command
*/
inline bool isCommand() const
{ return code() < 0; }
/**
* Check if this is a response message (code is greater then or equal to 100)
* @return True if this message is a response
*/
inline bool isResponse() const
{ return 100 <= code(); }
/**
* Check if this message is a response ACK (code is between 0 and 99, including the margins)
* @return True if this message is a response ACK
*/
inline bool isAck() const
{ return 0 <= code() && code() <= 99; }
/**
* Get the message's transaction id
* @return The message's transaction id
*/
inline unsigned int transactionId() const
{ return m_transaction; }
/**
* Get the message's endpoint id if this is a command
* @return The message's endpoint id if this is a command
*/
inline const String& endpointId() const
{ return m_endpoint; }
/**
* Convert this message to a string representation to be sent to the remote
* endpoint or printed to output
* @param dest Destination string
*/
void toString(String& dest) const;
/**
* Parse a received buffer according to RFC 3435. Command and protocol names are converted to upper case.
* The enpoint id is converted to lower case. Message parameter names are converted to lower case if
* the engine's flag is set. Message parameter values and SDP(s) are stored unchanged
* @param engine The receiving engine
* @param dest The list of received messages
* @param buffer The buffer to parse
* @param len The buffer length
* @param sdpType The MIME SDP content type if the message contains any SDP body
* @return False on failure, true on success. If failed, the destination
* list may contain a response message to be sent
*/
static bool parse(MGCPEngine* engine, ObjList& dest,
const unsigned char* buffer, unsigned int len,
const char* sdpType = "application/sdp");
/**
* Keep the message parameters
*/
NamedList params;
/**
* Keep the SDP(s) carried by this message as MimeSdpBody object(s)
*/
ObjList sdp;
protected:
/**
* Constructor. Used by the parser to construct an incoming message
* @param engine The engine receiving this message
* @param name Command name or response comment
* @param code The response code in the range 0 to 999 or -1 if the received
* message is a command
* @param transId The id of the transaction owning this message
* @param epId The id of the endpoint issuing this command
* @param ver The protocol version
*/
MGCPMessage(MGCPEngine* engine, const char* name, int code,
unsigned int transId, const char* epId, const char* ver);
private:
MGCPMessage() : params("") {} // Avoid using default constructor
// Decode the message line
static MGCPMessage* decodeMessage(const char* line, unsigned int len, unsigned int& trans,
String& error, MGCPEngine* engine);
// Decode message parameters. Return true if found a line containing a dot
static bool decodeParams(const unsigned char* buffer, unsigned int len,
unsigned int& crt, MGCPMessage* msg, String& error, MGCPEngine* engine);
String m_name; // Command or string representation of response code
bool m_valid; // False if this message is invalid
int m_code; // Response code or -1 if this is a command
unsigned int m_transaction; // The id of the transaction this message belongs to
String m_endpoint; // The id of the endpoint issuing this message
String m_version; // The protocol version
String m_comment; // The comment attached to a response message
};
/**
* This class implements an MGCP transaction
* @short An MGCP transaction
*/
class YMGCP_API MGCPTransaction : public RefObject, public Mutex
{
friend class MGCPEngine; // Process a received message
friend class MGCPEvent; // Access to event termination notification
public:
/**
* Transaction state enumeration
*/
enum State {
Invalid = 0, // This is an invalid transaction (constructor failed)
Initiated = 1, // An initial command message was sent/received
Trying = 2, // Sent or received a provisional response to the initial message
Responded = 3, // Sent or received a final response to the initial message
Ack = 4, // Response was ack'd
Destroying = 5, // Waiting to be removed from the engine
};
/**
* Constructor. Construct a transaction from its first message
* @param engine The engine owning this transaction
* @param msg The command creating this transaction
* @param outgoing The direction of this transaction
* @param address Remote enpoint's address
* @param engineProcess Use engine processor thread for this transaction
*/
MGCPTransaction(MGCPEngine* engine, MGCPMessage* msg, bool outgoing,
const SocketAddr& address, bool engineProcess = true);
/**
* Destructor
*/
virtual ~MGCPTransaction();
/**
* Get the current transaction's state
* @return The transaction state as enumeration
*/
inline State state() const
{ return m_state; }
/**
* Get the id of this transaction
* @return The id of this transaction
*/
inline unsigned int id() const
{ return m_id; }
/**
* Get the direction of this transaction
* @return True if this is an outgoing transaction
*/
inline bool outgoing() const
{ return m_outgoing; }
/**
* Get the id of the endpoint owning this transaction
* @return The id of the endpoint owning this transaction
*/
inline const String& ep() const
{ return m_endpoint; }
/**
* Get the remote endpoint's IP address
* @return The remote endpoint's IP address
*/
const SocketAddr& addr() const
{ return m_address; }
/**
* Get the engine owning this transaction
* @return The engine owning this transaction
*/
inline MGCPEngine* engine()
{ return m_engine; }
/**
* Get the initial command message sent or received by this transaction
* @return The transaction's initial message
*/
inline const MGCPMessage* initial() const
{ return m_cmd; }
/**
* Get the provisional response message sent or received by this transaction
* @return The transaction's provisional response message
*/
inline const MGCPMessage* msgProvisional() const
{ return m_provisional; }
/**
* Get the final response message sent or received by this transaction
* @return The transaction's final response message
*/
inline const MGCPMessage* msgResponse() const
{ return m_response; }
/**
* Get the response aknowledgement message sent or received by this transaction
* @return The transaction's response aknowledgement message
*/
inline const MGCPMessage* msgAck() const
{ return m_ack; }
/**
* Check if this transaction timed out
* @return True if this transaction timed out
*/
inline bool timeout() const
{ return m_timeout; }
/**
* Set the remote ACK request flag
* @param request False if remote is not required to send an ACK
*/
inline void ackRequest(bool request)
{ m_ackRequest = request; }
/**
* Get the private user data of this transaction
* @return The private user data of this transaction
*/
inline void* userData() const
{ return m_private; }
/**
* Set the private user data of this transaction
* @param data The new private user data of this transaction
*/
inline void userData(void* data)
{ m_private = data; }
/**
* Set the engine process flag. Allow the engine to process this transaction
* (call getEvent() from engine process thread)
*/
inline void setEngineProcess()
{ m_engineProcess = true; }
/**
* Get an event from this transaction. Check timeouts
* @param time Current time in microseconds
* @return MGCPEvent pointer or 0 if none
*/
MGCPEvent* getEvent(u_int64_t time = Time());
/**
* Explicitely transmits a provisional code
* @param code Provisional response code to send, must be in range 100-199
* @param comment Optional response comment text
* @return True if the provisional response was sent
*/
bool sendProvisional(int code = 100, const char* comment = 0);
/**
* Creates and transmits a final response (code must at least 200) message if
* this is an incoming transaction
* @param code Response code to send
* @param comment Optional response comment text
* @return True if the message was queued for transmission
*/
inline bool setResponse(int code, const char* comment = 0)
{ return setResponse(new MGCPMessage(this,code,comment)); }
/**
* Creates and transmits a final response (code must at least 200) message if
* this is an incoming transaction.
* The SDP(s) will be consumed (appended to the message or destroyed)
* @param code Response code to send
* @param params Parameters to set in response, name will be set as comment
* @param sdp1 Optional SDP to be added to the response
* @param sdp2 Optional second SDP to be added to the response if the first one is not 0
* @return True if the message was queued for transmission
*/
bool setResponse(int code, const NamedList* params, MimeSdpBody* sdp1 = 0,
MimeSdpBody* sdp2 = 0);
/**
* Transmits a final response (code must at least 200)
* message if this is an incoming transaction
* @param msg The message to transmit
* @return True if the message was queued for transmission
*/
bool setResponse(MGCPMessage* msg);
protected:
/**
* Gracefully terminate this transaction. Release memory
*/
virtual void destroyed();
/**
* Consume (process) a received message, other then the initiating one
* @param msg The received message
*/
void processMessage(MGCPMessage* msg);
/**
* Check timeouts. Manage retransmissions
* @param time Current time in milliseconds
* @return MGCPEvent pointer if timeout
*/
MGCPEvent* checkTimeout(u_int64_t time);
/**
* Event termination notification
* @param event The notifier
*/
void eventTerminated(MGCPEvent* event);
/**
* Change transaction's state if the new state is a valid one
* @param newState The new state of this transaction
*/
void changeState(State newState);
/**
* Set and send the provisional response (codes between 100 and 199)
* @param code The response code
*/
void setProvisional(int code = 100);
/**
* (Re)send one the initial, provisional or final response. Change transaction's state
* @param msg The message to send
*/
void send(MGCPMessage* msg);
private:
MGCPTransaction() {} // Avoid using default constructor
// Check if received any final response. Create an event. Init timeout.
// Send a response ACK if requested by the response
MGCPEvent* checkResponse(u_int64_t time);
// Init timeout for retransmission or transaction termination
void initTimeout(u_int64_t time, bool extra);
// Remove from engine. Create event. Deref the transaction
MGCPEvent* terminate();
State m_state; // Current state
unsigned int m_id; // Transaction id
bool m_outgoing; // Transaction direction
SocketAddr m_address; // Remote andpoint's address
MGCPEngine* m_engine; // The engine owning this transaction
MGCPMessage* m_cmd; // The command that created this transaction
MGCPMessage* m_provisional; // The provisional response to the command that created this transaction
MGCPMessage* m_response; // The response to the command that created this transaction
MGCPMessage* m_ack; // The response aknowledgement message sent or received
MGCPEvent* m_lastEvent; // The last generated event
String m_endpoint; // The endpoint owning this transaction
u_int64_t m_nextRetrans; // Retransission or destroy time
unsigned int m_crtRetransInterval; // Current retransmission interval
unsigned int m_retransCount; // Remainig number of retransmissions
bool m_timeout; // Transaction timeout flag
bool m_ackRequest; // Remote is requested to send ACK
void* m_private; // Data used by this transaction's user
String m_debug; // String used to identify the transaction in debug messages
bool m_engineProcess; // Process transaction (getEvent) from engine processor
};
/**
* This class holds an endpoint id in the form "endpoint@host:port"
* @short An endpoint id
*/
class YMGCP_API MGCPEndpointId
{
public:
/**
* Constructor
*/
inline MGCPEndpointId()
: m_port(0)
{}
/**
* Constructor. Construct this endpoint id from a string
* @param src The string to construct from
*/
inline MGCPEndpointId(const String& src)
: m_port(0)
{ set(src); }
/**
* Copy constructor
* @param value Original Endpoint ID to copy
*/
inline MGCPEndpointId(const MGCPEndpointId& value)
: m_id(value.id()), m_endpoint(value.user()),
m_host(value.host()), m_port(value.port())
{ }
/**
* Constructor. Construct this endpoint id
* @param endpoint The user part of the endpoint's URI
* @param host The IP address of the endpoint's URI
* @param port The port used by the endpoint to receive data
* @param addPort Add :port at end of id only if port is not zero
*/
inline MGCPEndpointId(const char* endpoint, const char* host, int port, bool addPort = true)
: m_port(0)
{ set(endpoint,host,port,addPort); }
/**
* Get the full id of the endpoint
* @return The full id of the endpoint
*/
inline const String& id() const
{ return m_id; }
/**
* Get the user part of the endpoint URI
* @return The user part of the endpoint URI
*/
inline const String& user() const
{ return m_endpoint; }
/**
* Get the host part of the endpoint URI
* @return The host part of the endpoint URI
*/
inline const String& host() const
{ return m_host; }
/**
* Get the port used by this endpoint
* @return The port used by this endpoint
*/
inline int port() const
{ return m_port; }
/**
* Set the port used by this endpoint
* @param newPort The new port used by this endpoint
* @param addPort Add :port at end of id only if port is not zero
*/
inline void port(int newPort, bool addPort = true)
{ set(m_endpoint,m_host,newPort,addPort); }
/**
* Set this endpoint id. Convert it to lower case
* @param endpoint The user part of the endpoint's URI
* @param host The IP address of the endpoint's URI
* @param port The port used by the endpoint to receive data
* @param addPort Add :port at end of id only if port is not zero
*/
void set(const char* endpoint, const char* host, int port, bool addPort = true);
/**
* Set this endpoint id. Convert it to lower case
* @param src The string to construct from
*/
inline void set(const String& src) {
URI uri(src);
set(uri.getUser(),uri.getHost(),uri.getPort());
}
/**
* Check if this is a valid endpoint id as defined in RFC 3435 3.2.1.3.
* It is considerred valid if the user and host part lengths are between
* 1 and 255 and the port is not 0
* @return True if this is a valid endpoint id
*/
inline bool valid() const {
return m_endpoint && m_endpoint.length() < 256 &&
m_host && m_host.length() < 256;
}
private:
String m_id; // The complete id
String m_endpoint; // The endpoint's name inside the host
String m_host; // Host of this endpoint
int m_port; // Port used by this endpoint
};
/**
* This class holds data about a remote endpoint (id and address)
* @short Remote endpoint info class
*/
class YMGCP_API MGCPEpInfo : public MGCPEndpointId, public GenObject
{
public:
/**
* Constructor. Construct this endpoint info
* @param endpoint The endpoint part of the endpoint's id
* @param host The IP address of this endpoint
* @param port The port used to send data to this endpoint
* @param addPort Add :port at end of id only if port is not zero
*/
inline MGCPEpInfo(const char* endpoint, const char* host, int port, bool addPort = true)
: MGCPEndpointId(endpoint,host,port,addPort),
m_address(AF_INET), m_resolve(true) {
m_address.port(port);
}
/**
* Get a string representation of this object
* @return The endpoint's id
*/
virtual const String& toString() const
{ return id(); }
/**
* Retrieve the current address for this endpoint information
* @return Address and port of this endpoint info
*/
inline const SocketAddr& address() const
{ return m_address; }
/**
* Retrieve the address for this endpoint information, resolve name if needed
* @return Address and port of this endpoint info
*/
const SocketAddr& address();
/**
* Set a new socket address in the endpoint info
* @param addr New address and port to set in the endpoint
*/
inline void address(const SocketAddr& addr)
{ m_resolve = false; m_address = addr; }
/**
* An alias name of the remote endpoint, may be empty
*/
String alias;
private:
SocketAddr m_address;
bool m_resolve;
};
/**
* This class holds a local MGCP endpoint (either gateway or call agent) along
* with its remote peer(s).
* If the engine owning this endpoint is an MGCP gateway, only 1 remote peer (Call Agent) is allowed
* @short An MGCP endpoint
*/
class YMGCP_API MGCPEndpoint : public RefObject, public MGCPEndpointId, public Mutex
{
public:
/**
* Constructor. Construct this endpoint. Append itself to the engine's list.
* The endpoint's id will be created from the received user and engine's address
* @param engine The engine owning this endpoint
* @param user The user part of the endpoint's id
* @param host The host part of the endpoint's id
* @param port The port part of the endpoint's id
* @param addPort Add :port at end of id only if port is not zero
*/
MGCPEndpoint(MGCPEngine* engine, const char* user, const char* host, int port, bool addPort = true);
/**
* Destructor. Remove itself from engine's list
*/
virtual ~MGCPEndpoint();
/**
* Get a string representation of this endpoint
* @return A string representation of this endpoint
*/
virtual const String& toString() const
{ return MGCPEndpointId::id(); }
/**
* Get the engine owning this endpoint
* @return The engine owning this endpoint
*/
inline MGCPEngine* engine()
{ return m_engine; }
/**
* Append info about a remote endpoint controlled by or controlling this endpoint.
* If the engine owning this endpoint is an MGCP gateway, only 1 remote peer (Call Agent) is allowed
* @param endpoint The endpoint part of the remote endpoint's id
* @param host The IP address of the remote endpoint
* @param port The port used to send data to this endpoint.
* Set to 0 to set it to the default port defined by the protocol and the
* opposite of the engine's mode
* A value of -1 uses the default but doesn't add :port at end of ID
* Other negative values use specified port but don't add :port at end
* @return Valid MGCPEpInfo pointer or 0 if the data wasn't added
*/
MGCPEpInfo* append(const char* endpoint, const char* host, int port = 0);
/**
* Clear the list or remote endpoints
*/
inline void clear()
{ lock(); m_remote.clear(); unlock(); }
/**
* Find the info object associated with a remote peer
* @param epId The remote endpoint's id to find
* @return MGCPEpInfo pointer or 0 if not found
*/
MGCPEpInfo* find(const String& epId);
/**
* Find an info object by remote peer alias
* @param alias Alias of the remote endpoint's id to find
* @return MGCPEpInfo pointer or 0 if not found
*/
MGCPEpInfo* findAlias(const String& alias);
/**
* Find the info object associated with an unique remote peer
* @return MGCPEpInfo pointer or 0 if not exactly one peer
*/
MGCPEpInfo* peer();
private:
MGCPEngine* m_engine; // The engine owning this endpoint
ObjList m_remote; // The remote endpoints
};
/**
* This class carries a copy of the message received by a transaction or a transaction state
* change notification (such as timeout or destroy)
* @short An MGCP event
*/
class YMGCP_API MGCPEvent
{
friend class MGCPTransaction;
public:
/**
* Destructor. Delete the message. Notify and deref the transaction
*/
~MGCPEvent();
/**
* Get the transaction that generated this event
* @return The transaction that generated this event
*/
inline MGCPTransaction* transaction()
{ return m_transaction; }
/**
* Get the message carried by this event
* @return The message carried by this event or 0 if none
*/
inline MGCPMessage* message() const
{ return m_message; }
protected:
/**
* Constructor. Constructs an event from a transaction
* @param trans The transaction that generated this event
* @param msg The message carried by this event, if any
*/
MGCPEvent(MGCPTransaction* trans, MGCPMessage* msg = 0);
private:
MGCPTransaction* m_transaction; // The transaction that generated this event
MGCPMessage* m_message; // The message carried by this event, if any
};
class MGCPPrivateThread;
/**
* The engine may keep gateway endpoints or call agents
* Keep the transaction list and manage it (create/delete/modify/timeout...)
* Keep a list with the endpoints it services
* Generate transaction numbers (IDs)
* Parse received messages, validate and send them to the appropriate transaction
* Send MGCP messages to remote addresses
* @short An MGCP engine
*/
class YMGCP_API MGCPEngine : public DebugEnabler, public Mutex
{
friend class MGCPPrivateThread;
friend class MGCPTransaction;
public:
/**
* Constructor. Construct the engine and, optionally, initialize it
* @param gateway Engine's mode: true if this engine is an MGCP Gateway,
* false if it's a collection of Call Agents
* @param name Optional debug name for this engine
* @param params Optional parameters used to initialize this engine
*/
MGCPEngine(bool gateway, const char* name = 0, const NamedList* params = 0);
/**
* Destructor. Clear all lists
*/
virtual ~MGCPEngine();
/**
* Check if this engine is an MGCP Gateway or a collection of Call Agents
* @return True if this engine is an MGCP Gateway, false if it's a
* collection of Call Agents
*/
inline bool gateway() const
{ return m_gateway; }
/**
* Get the IP address used by this engine to receive data
* @return The IP address used by this engine to receive data
*/
inline const SocketAddr& address() const
{ return m_address; }
/**
* Get the maximum length or received packets. This is the size of the buffer used by
* this engine to read data from the socket
* @return The maximum length or received packets
*/
inline unsigned int maxRecvPacket() const
{ return m_maxRecvPacket; }
/**
* Check if this engine is allowed to send/accept unknown commands
* @return True if this engine is allowed to send/accept unknown commands
*/
inline bool allowUnkCmd() const
{ return m_allowUnkCmd; }
/**
* Get the message retransmission interval
* @return The message retransmission interval
*/
inline unsigned int retransInterval() const
{ return m_retransInterval; }
/**
* Get the maximum number of retransmissions for a message
* @return The maximum number of retransmissions for a message
*/
inline unsigned int retransCount() const
{ return m_retransCount; }
/**
* Get the time to live after the transaction terminated gracefully
* @return The time to live after the transaction terminated gracefully
*/
inline u_int64_t extraTime() const
{ return m_extraTime; }
/**
* Check if the parser should convert received messages' parameters to lower case
* @return True if the parser should convert received messages' parameters to lower case
*/
inline bool parseParamToLower() const
{ return m_parseParamToLower; }
/**
* Check if incoming transactions would send provisional responses
* @return True if incoming transactions would send provisional responses
*/
inline bool provisional() const
{ return m_provisional; }
/**
* Get the remote ACK request flag
* @return True if remote will be requested to send an ACK
*/
inline bool ackRequest() const
{ return m_ackRequest; }
/**
* Set the remote ACK request flag
* @param request False to not request from remote to send an ACK
*/
inline void ackRequest(bool request)
{ m_ackRequest = request; }
/**
* Initialize this engine
* @param params Engine's parameters
*/
virtual void initialize(const NamedList& params);
/**
* Check if a command is known by this engine
* @param cmd The command name to check
* @return True if the given command is known by this engine
*/
inline bool knownCommand(const String& cmd)
{ Lock lock(this); return (m_knownCommands.find(cmd) != 0); }
/**
* Add a command to the list of known commands
* @param cmd The command name to add
*/
void addCommand(const char* cmd);
/**
* Append an endpoint to this engine if not already done
* @param ep The endpoint to append
*/
void attach(MGCPEndpoint* ep);
/**
* Remove an endpoint from this engine and, optionally, remove all its transactions
* @param ep The endpoint to remove
* @param del True to delete it, false to just remove it from the list
* @param delTrans True to remove all its transactions.
* Forced to true if the endpoint is deleted
*/
void detach(MGCPEndpoint* ep, bool del = false, bool delTrans = false);
/**
* Find an endpoint by its pointer
* @param ep The endpoint to find
* @return MGCPEndpoint pointer or 0 if not found
*/
MGCPEndpoint* findEp(MGCPEndpoint* ep);
/**
* Find an endpoint by its id
* @param epId The endpoint's id to find
* @return MGCPEndpoint pointer or 0 if not found
*/
MGCPEndpoint* findEp(const String& epId);
/**
* Find a transaction by its id
* @param id The id of the transaction to find
* @param outgoing The transaction direction. True for outgoing, false for incoming
* @return MGCPTransaction pointer or 0 if not found
*/
MGCPTransaction* findTrans(unsigned int id, bool outgoing);
/**
* Generate a new id for an outgoing transaction
* @return An id for an outgoing transaction
*/
unsigned int getNextId();
/**
* Send a command message. Create a transaction for it.
* The method will fail if the message is not a valid one or isn't a valid command
* @param cmd The message containig the command
* @param address The destination IP address
* @param engineProcess Use engine private processor thread for the new transaction.
* If false the caller is responsable with transaction processing
* @return MGCPTransaction pointer or 0 if failed to create a transaction
*/
MGCPTransaction* sendCommand(MGCPMessage* cmd, const SocketAddr& address,
bool engineProcess = true);
/**
* Read data from the socket. Parse and process the received message
* @param buffer Buffer used for read operation. The buffer must be large enough
* to keep the maximum packet length returned by @ref maxRecvPacket()
* @param addr The sender's address if received any data
* @return True if received any data (a message was successfully parsed)
*/
bool receive(unsigned char* buffer, SocketAddr& addr);
/**
* Try to get an event from a transaction.
* If the event contains an unknown command and this engine is not allowed
* to process such commands, calls the @ref returnEvent() method, otherwise,
* calls the @ref processEvent() method
* @param time Current time in microseconds
* @return True if an event was processed
*/
bool process(u_int64_t time = Time());
/**
* Try to get an event from a given transaction.
* If the event contains an unknown command and this engine is not allowed
* to process such commands, calls the @ref returnEvent() method, otherwise,
* calls the @ref processEvent() method
* @param tr Transaction to process
* @param time Current time in microseconds
* @return True if an event was processed
*/
bool processTransaction(MGCPTransaction* tr, u_int64_t time = Time());
/**
* Repeatedly calls @ref receive() until the calling thread terminates
* @param addr The sender's address if received any data
*/
void runReceive(SocketAddr& addr);
/**
* Repeatedly calls @ref receive() until the calling thread terminates
*/
void runReceive();
/**
* Repeatedly calls @ref process() until the calling thread terminates
*/
void runProcess();
/**
* Try to get an event from a transaction
* @param time Current time in microseconds
* @return MGCPEvent pointer or 0 if none
*/
MGCPEvent* getEvent(u_int64_t time = Time());
/**
* Process an event generated by a transaction. Descendants must override this
* method if they want to process events. By default it calls the version
* of processEvent that accepts separate parameters of event
* @param event The event to process
* @return True if the event was processed. If the event carry a received
* command and it's not processed the transaction will receive an 'unknown command' response
*/
virtual bool processEvent(MGCPEvent* event);
/**
* Process an event generated by a transaction. Descendants must override this
* method if they want to process events
* @param trans Pointer to the transaction that generated the event
* @param msg MGCP message of the event, may be NULL
* @return True if the event was processed. If the event carry a received
* command and it's not processed the transaction will receive an 'unknown command' response
*/
virtual bool processEvent(MGCPTransaction* trans, MGCPMessage* msg);
/**
* Returns an unprocessed event to this engine to be deleted.
* Incoming transactions will be responded. Unknown commands will receive a
* 504 Unknown Command response, the others will receive a 507 Unsupported Functionality one
* @param event The event to return
*/
void returnEvent(MGCPEvent* event);
/**
* Terminate all transactions. Cancel all private threads if any and
* wait for them to terminate
* @param gracefully If true, all incoming transaction will be responded and private
* threads will be gently cancelled. If false, all transactions will be deleted and
* threads will be cancelled the hard way
* @param text Optional text to be sent with the response code of the incoming
* transactions on gracefully cleanup
*/
void cleanup(bool gracefully = true, const char* text = "Shutdown");
/**
* Get the default port defined by the protocol
* @param gateway True to get the default Gateway port,
* false to get the default port for the Call Agent
* @return The default port defined by the protocol
*/
static inline int defaultPort(bool gateway)
{ return gateway ? 2427 : 2727; }
/**
* Handle a transaction that has timed out
* @param tr The transaction that has timed out
*/
virtual void timeout(MGCPTransaction* tr)
{ }
/**
* The list of commands defined in RFC 3435
*/
static TokenDict mgcp_commands[];
/**
* The list of known responses defined in RFC 3435 2.4
*/
static TokenDict mgcp_responses[];
/**
* The list of known reason codes defined in RFC 3435 2.5.
* Reason codes are used by the gateway when deleting a connection to
* inform the Call Agent about the reason for deleting the connection.
* They may also be used in a RestartInProgress command to inform the
* Call Agent of the reason for the RestartInProgress
*/
static TokenDict mgcp_reasons[];
protected:
/**
* Send a string buffer through the socket
* @param msg The buffer to send
* @param address The destination IP address
* @return False if the operation failed
*/
bool sendData(const String& msg, const SocketAddr& address);
/**
* Append a transaction to the list
* @param trans The transaction to append
*/
void appendTrans(MGCPTransaction* trans);
/**
* Remove a transaction from the list
* @param trans The transaction to remove
* @param del True to delete it, false to just remove it from list
*/
void removeTrans(MGCPTransaction* trans, bool del);
/**
* The list of endpoints attached to this engine
*/
ObjList m_endpoints;
/**
* The transaction list
*/
ObjList m_transactions;
/**
* The transaction list iterator used to get events
*/
ListIterator m_iterator;
private:
// Append a private thread to the list
void appendThread(MGCPPrivateThread* thread);
// Remove private thread from the list without deleting it
void removeThread(MGCPPrivateThread* thread);
// Process ACK received with a message or response
// Return a list of ack'd transactions or 0 if the parameter is incorrect
unsigned int* decodeAck(const String& param, unsigned int & count);
bool m_gateway; // True if this engine is an MGCP gateway, false if call agent
bool m_initialized; // True if the engine was already initialized
unsigned int m_nextId; // Next outgoing transaction id
Socket m_socket; // The socket used to send/receive data
SocketAddr m_address; // The IP address used by this engine
unsigned int m_maxRecvPacket; // The maximum length or received packets
unsigned char* m_recvBuf; // Receiving buffer
bool m_allowUnkCmd; // Allow this engine to send/accept unknown commands
unsigned int m_retransInterval; // Message retransmission interval
unsigned int m_retransCount; // Maximum number of retransmissions for a message
u_int64_t m_extraTime; // Time to live after the transaction terminated gracefully
bool m_parseParamToLower; // Convert received messages' params to lower case
bool m_provisional; // Send provisional responses flag
bool m_ackRequest; // Remote is requested to send ACK
ObjList m_knownCommands; // The list of known commands
ObjList m_threads;
};
}
#endif /* __YATEMGCP_H */
/* vi: set ts=8 sw=4 sts=4 noet: */