diff options
Diffstat (limited to 'src/transaction.h')
-rw-r--r-- | src/transaction.h | 372 |
1 files changed, 372 insertions, 0 deletions
diff --git a/src/transaction.h b/src/transaction.h new file mode 100644 index 0000000..3b10eee --- /dev/null +++ b/src/transaction.h @@ -0,0 +1,372 @@ +/* + Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.com> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef _TRANSACTION_H +#define _TRANSACTION_H + +#include <string> +#include "protocol.h" +#include "parser/request.h" +#include "parser/response.h" +#include "sockets/socket.h" +#include "threads/mutex.h" + +using namespace std; + +typedef unsigned short t_tid; + +///////////////////////////////////////////////////////////// +// Transaction state (see RFC 3261 17) +///////////////////////////////////////////////////////////// +enum t_trans_state { + TS_NULL, // non-state used for initialization + TS_CALLING, + TS_TRYING, + TS_PROCEEDING, + TS_COMPLETED, + TS_CONFIRMED, + TS_TERMINATED, +}; + +string trans_state2str(t_trans_state s); + +///////////////////////////////////////////////////////////// +// General transaction +///////////////////////////////////////////////////////////// +// +// Concurrent creation of transactions is not allowed. If this +// is needed then updates to static members need to be +// synchronized with a mutex. +// All transactions are created by the transaction manager. This +// should not be changed as transactions start timers and all timers +// must be started from a single thread. + +class t_transaction { +private: + static t_mutex mtx_class; // protect static members + static t_tid next_id; // next id to be issued + +protected: + t_tid id; // transaction id + unsigned short tuid; // TU id + t_trans_state state; + string to_tag; // tag for to-header + +public: + // Request that created the transaction + t_request *request; + + t_tid get_id(void) const; + + // Provisional responses in order of arrival/sending + list<t_response *> provisional; + + // Final response for the transaction + t_response *final; + + // The transaction will keep a copy of the request + t_transaction(t_request *r, unsigned short _tuid); + + // All request and response pointers contained by the + // request will be deleted. + virtual ~t_transaction(); + + // Process a provisional repsonse + // Transaction will keep a copy of the response + virtual void process_provisional(t_response *r); + + // Process a final response + // Transaction will keep a copy of the response + virtual void process_final(t_response *r); + + // Process a response + virtual void process_response(t_response *r); + + // Process timer expiry + virtual void timeout(t_sip_timer t) = 0; + + // Get state of the transaction + t_trans_state get_state(void) const; + + // Set TU ID + void set_tuid(unsigned short _tuid); + + // Get type of request + t_method get_method(void) const; + + // Get tag for to-header + string get_to_tag(void); + + // Create response according to general rules + t_response *create_response(int code, string reason = ""); +}; + +///////////////////////////////////////////////////////////// +// Client transaction +///////////////////////////////////////////////////////////// +class t_trans_client : public t_transaction { +protected: + /** Destination for request. */ + t_ip_port dst_ip_port; + +public: + /** + * Create transaction and send request to destination. + * @param r [in] Request creating the transaction. + * @param ip_port [in] Destination of the request. + * @param _tuid [in] Transaction user id assigned to this transaction. + */ + t_trans_client(t_request *r, const t_ip_port &ip_port, + unsigned short _tuid); + + /** + * Match a response with a transaction. + * @param r [in] The response to match. + * @return true if the response matches the transaction. + */ + bool match(t_response *r) const; + + /** + * @param icmp [in] ICMP message to match. + * @return true if the ICMP error matches the transaction + */ + bool match(const t_icmp_msg &icmp) const; + + /** + * Match transaction with a branch and CSeq method value. + * @param branch [in] Branch to match. + * @param cseq_method [in] CSeq method to match. + * @return true if transaction matches, otherwise false. + */ + bool match(const string &branch, const t_method &cseq_method) const; + + virtual void process_provisional(t_response *r); + + /** + * Process ICMP errors. + * @param icmp [in] ICMP message. + */ + virtual void process_icmp(const t_icmp_msg &icmp) = 0; + + /** + * Process failures. + * @param failure [in] Type of failure. + */ + virtual void process_failure(t_failure failure) = 0; + + /** + * Abort a transaction. + * This will send a 408 response internally to finish the transaction. + */ + virtual void abort(void) = 0; +}; + +///////////////////////////////////////////////////////////// +// Client INVITE transaction +///////////////////////////////////////////////////////////// +class t_tc_invite : public t_trans_client { +private: + // Timers + unsigned short timer_A; + unsigned short timer_B; + unsigned short timer_D; + + // Duration of next timer A in msec + long duration_A; + + void start_timer_A(void); + void start_timer_B(void); + void start_timer_D(void); + void stop_timer_A(void); + void stop_timer_B(void); + void stop_timer_D(void); + + +public: + t_request *ack; // ACK request + + // Create transaction and send request to destination + // Start timer A and timer B + t_tc_invite(t_request *r, const t_ip_port &ip_port, + unsigned short _tuid); + + virtual ~t_tc_invite(); + + // Process a provisional repsonse + // Stop timer A + void process_provisional(t_response *r); + + // Process a final response + // Stop timer B. + // Start timer D (for non-2xx final). + void process_final(t_response *r); + + void process_icmp(const t_icmp_msg &icmp); + + void process_failure(t_failure failure); + + void timeout(t_sip_timer t); + + void abort(void); +}; + +///////////////////////////////////////////////////////////// +// Client non-INVITE transaction +///////////////////////////////////////////////////////////// +class t_tc_non_invite : public t_trans_client { +private: + // Timers + unsigned short timer_E; + unsigned short timer_F; + unsigned short timer_K; + + // Duration of next timer E in msec + long duration_E; + + void start_timer_E(void); + void start_timer_F(void); + void start_timer_K(void); + void stop_timer_E(void); + void stop_timer_F(void); + void stop_timer_K(void); + +public: + // Create transaction and send request to destination + // Stop timer E and timer F + t_tc_non_invite(t_request *r, const t_ip_port &ip_port, + unsigned short _tuid); + + virtual ~t_tc_non_invite(); + + // Process a provisional repsonse + void process_provisional(t_response *r); + + // Process final response + // Stop timer E and F. Start timer K. + void process_final(t_response *r); + + void process_icmp(const t_icmp_msg &icmp); + + void process_failure(t_failure failure); + + void timeout(t_sip_timer t); + + void abort(void); +}; + +///////////////////////////////////////////////////////////// +// Server transaction +///////////////////////////////////////////////////////////// +class t_trans_server : public t_transaction { +private: + // Match a the transaction to a request. Argument + // If cancel==true then the target for a CANCEL + // is matched. + // If cancel==false then the request itself is matched, + // eg. retransmission or ACK to INVITE matching + bool match(t_request *r, bool cancel) const; + + // Indicates if a 100 Trying has already been sent. + // A 100 Trying should only be sent once. + // The reason for sending a 100 Trying is to indicate that + // the request has been received but that processing will + // take some time. + // Based on the tasks to perform several parts of the transaction + // user can decide independently to send a 100 Trying. This + // flag assures that only one 100 Trying will be sent out + // though. + bool resp_100_trying_sent; + +public: + t_trans_server(t_request *r, unsigned short _tuid); + + // Process a provisional repsonse + // Send provisional response + void process_provisional(t_response *r); + + // Process a final response + // Send the final response + void process_final(t_response *r); + + // Process a received retransmission of the request + virtual void process_retransmission(void); + + // Returns true if request matches transaction + bool match(t_request *r) const; + + // Returns true if the transaction is the target of CANCEL + bool match_cancel(t_request *r) const; +}; + +///////////////////////////////////////////////////////////// +// Server INIVITE transaction +///////////////////////////////////////////////////////////// +class t_ts_invite : public t_trans_server { +private: + // Timers + unsigned short timer_G; + unsigned short timer_H; + unsigned short timer_I; + + // Duration of next timer G in msec + long duration_G; + + void start_timer_G(void); + void start_timer_H(void); + void start_timer_I(void); + void stop_timer_G(void); + void stop_timer_H(void); + void stop_timer_I(void); + +public: + t_request *ack; // ACK request + + t_ts_invite(t_request *r, unsigned short _tuid); + virtual ~t_ts_invite(); + + void process_provisional(t_response *r); + void process_final(t_response *r); + void process_retransmission(void); + void timeout(t_sip_timer t); + + // Transaction will keep a copy of the ACK. + void acknowledge(t_request *ack_request); +}; + +///////////////////////////////////////////////////////////// +// Server non-INVITE transaction +///////////////////////////////////////////////////////////// +class t_ts_non_invite : public t_trans_server { +private: + // Timers + unsigned short timer_J; + + void start_timer_J(void); + void stop_timer_J(void); + +public: + t_ts_non_invite(t_request *r, unsigned short _tuid); + virtual ~t_ts_non_invite(); + + void process_provisional(t_response *r); + void process_final(t_response *r); + void process_retransmission(void); + void timeout(t_sip_timer t); +}; + +#endif |