/* Copyright (C) 2005-2009 Michel de Boer 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 _PROTOCOL_H #define _PROTOCOL_H #include "twinkle_config.h" #include "parser/hdr_supported.h" /** Carriage Return Line Feed */ #define CRLF "\r\n" /** TCP PING packet to be sent on a TCP connection. */ #define TCP_PING_PACKET CRLF CRLF /** Product name */ #define PRODUCT_NAME "Twinkle" /** Product version */ #define PRODUCT_VERSION VERSION /** * When a SIP message is created, some addresses will be filled in * by the sender thread as only this thread knows the source IP * address of an outgoing message. * The sender thread will look for occurrences of the AUTO_IP4_ADDRESS * and replace it with the source IP address. */ #define AUTO_IP4_ADDRESS "255.255.255.255" /** Display name for anonymous calling */ #define ANONYMOUS_DISPLAY "Anonymous" /** SIP-URI for anonymous calling */ #define ANONYMOUS_URI "sip:anonymous@anonymous.invalid" /** Types of failures. */ enum t_failure { FAIL_TIMEOUT, /**< Transaction timed out */ FAIL_TRANSPORT /**< Transport failure */ }; /** Call transfer types */ enum t_transfer_type { TRANSFER_BASIC, /**< Basic transfer (blind) */ TRANSFER_CONSULT, /**< Transfer with consultation (possibly attended) */ TRANSFER_OTHER_LINE /**< Transfer call to other line */ }; /** State of a call transfer at the referrer. */ enum t_refer_state { REFST_NULL, /**< No REFER in progress */ REFST_W4RESP, /**< REFER sent, waiting for response */ REFST_W4NOTIFY, /**< Response received, waiting for 1st NOTIFY */ REFST_PENDING, /**< REFER received, but not granted yet */ REFST_ACTIVE, /**< Referee granted refer */ }; /** Types of registration requests */ enum t_register_type { REG_REGISTER, REG_QUERY, REG_DEREGISTER, REG_DEREGISTER_ALL }; /** * RFC 3261 Annex A * SIP timers */ enum t_sip_timer { TIMER_T1, TIMER_T2, TIMER_T4, TIMER_A, TIMER_B, TIMER_C, TIMER_D, TIMER_E, TIMER_F, TIMER_G, TIMER_H, TIMER_I, TIMER_J, TIMER_K }; // All durations are in msec #define DURATION_T1 500 #define DURATION_T2 4000 #define DURATION_T4 5000 #define DURATION_A DURATION_T1 #define DURATION_B (64 * DURATION_T1) #define DURATION_C 180000 #define DURATION_D 32000 #define DURATION_E DURATION_T1 #define DURATION_F (64 * DURATION_T1) #define DURATION_G DURATION_T1 #define DURATION_H (64 * DURATION_T1) #define DURATION_I DURATION_T4 #define DURATION_J (64 * DURATION_T1) #define DURATION_K DURATION_T4 /** Time to keep an idle connection open before closing */ #define DUR_IDLE_CONNECTION (64 * DURATION_T1) /** UA (phone) timers */ enum t_phone_timer { PTMR_REGISTRATION, /**< Registration (failure) timeout */ PTMR_NAT_KEEPALIVE, /**< NAT binding refresh timeout for STUN */ PTMR_TCP_PING, /**< TCP ping interval */ }; /** UA (line) timers */ enum t_line_timer { LTMR_ACK_TIMEOUT, /**< Waiting for ACK */ LTMR_ACK_GUARD, /**< After this timer ACK is lost for good */ LTMR_INVITE_COMP, /**< After this timer INVITE transiction is considered complete. */ LTMR_NO_ANSWER, /**< This timer expires if the callee does not answer. The call will be torn down. */ LTMR_RE_INVITE_GUARD, /**< re-INVITE timeout */ LTMR_100REL_TIMEOUT, /**< Waiting for PRACK */ LTMR_100REL_GUARD, /**< After this timer PRACK is lost for good */ LTMR_GLARE_RETRY, /**< Waiting before retry re-INVITE after glare */ LTMR_CANCEL_GUARD, /**< Guard for situation where CANCEL has been responded to, but 487 on INVITE is never received. */ }; /** Subscription timers. */ enum t_subscribe_timer { STMR_SUBSCRIPTION, /**< Subscription timeout */ }; /** Publication timers. */ enum t_publish_timer { PUBLISH_TMR_PUBLICATION, /**< Publication timeout */ }; /** STUN timers. */ enum t_stun_timer { STUN_TMR_REQ_TIMEOUT, /**< Waiting for response */ }; /** No answer timer (ms) */ #define DUR_NO_ANSWER(u) ((u)->get_timer_noanswer() * 1000) /** @name Registration timers */ //@{ /** Registration duration (seconds) */ #define DUR_REGISTRATION(u) ((u)->get_registration_time()) /**< Re-register 5 seconds before expiry **/ #define RE_REGISTER_DELTA 5 /** Re-registration interval after reg. failure */ #define DUR_REG_FAILURE 30 //@} /** NAT keepalive timer (s) default value */ #define DUR_NAT_KEEPALIVE 30 /** Default TCP ping interval (s) */ #define DUR_TCP_PING 30 /** * re-INVITE guard timer (ms). This timer guards against the situation * where a UAC has sent a re-INVITE, received a 1XX but never receives * a final response. No timer for this is defined in RFC 3261 */ #define DUR_RE_INVITE_GUARD 10000 /** * Guard for situation where CANCEL has been * responded to, but 487 on INVITE is never eceived. * This situation is not defined by RFC 3261 */ #define DUR_CANCEL_GUARD (64 * DURATION_T1) // MWI timers (s) #define DUR_MWI(u) ((u)->get_mwi_subscription_time()) #define DUR_MWI_FAILURE 30 // Presence timers (s) #define DUR_PRESENCE(u) ((u)->get_pres_subscription_time()) #define DUR_PRESENCE_FAILURE 30 // RFC 3261 14.1 // Maximum values (10th of sec) for timers for retrying a re-INVITE after // a glare (491 response). #define MAX_GLARE_RETRY_NOT_OWN 20 #define MAX_GLARE_RETRY_OWN 40 // Calculate the glare retry duration (ms) #define DUR_GLARE_RETRY_NOT_OWN ((rand() % (MAX_GLARE_RETRY_NOT_OWN + 1)) * 100) #define DUR_GLARE_RETRY_OWN ((rand() % (MAX_GLARE_RETRY_OWN - \ MAX_GLARE_RETRY_NOT_OWN) + 1 + MAX_GLARE_RETRY_NOT_OWN)\ * 100) // RFC 3262 // PRACK timers #define DUR_100REL_TIMEOUT DURATION_T1 #define DUR_100REL_GUARD (64 * DURATION_T1) // refer subscription timer (s) // RFC 3515 does not define the length of the timer. // It should be long enough to notify the result of an INVITE. #define DUR_REFER_SUBSCRIPTION 60 // Used when refer is always permitted #define DUR_REFER_SUB_INTERACT 90 // Used when user has to grant permission // Minimum duration of a subscription #define MIN_DUR_SUBSCRIPTION 60 // Duration to wait before re-subscribing after termination of // a subscription #define DUR_RESUBSCRIBE 30 // After an unsubscribe has been sent, a NOTIFY will should come in. // In case the NOTIFY does not come, this guard timer (ms) will assure // that the subscription will be cleaned up. #define DUR_UNSUBSCRIBE_GUARD 4000 // RFC 3489 // STUN retransmission timer intervals (ms) // The RFC states that the interval should start at 100ms. But that // seems to short. We start at 200 and do 8 instead of 9 transmissions. #define DUR_STUN_START_INTVAL 200 #define DUR_STUN_MAX_INTVAL 1600 // Maximum number of transmissions #define STUN_MAX_TRANSMISSIONS 8 // RFC 3261 #ifndef RFC3261_COOKIE #define RFC3261_COOKIE "z9hG4bK" #endif // Max forwards RFC 3261 8.1.1.6 #define MAX_FORWARDS 70 // Length of tags in from and to headers #define TAG_LEN 5 // Create a new tag #define NEW_TAG random_token(TAG_LEN) // Length of call-id (before domain) #define CALL_ID_LEN 15 // Create a new call-id #define NEW_CALL_ID(u) (random_token(CALL_ID_LEN) + '@' + LOCAL_HOSTNAME) // Create a new sequence number fo CSeq header #define NEW_SEQNR rand() % 1000 + 1 // Length of cnonce #define CNONCE_LEN 10 // Create a cnonce #define NEW_CNONCE random_hexstr(CNONCE_LEN) /** Length of tuple id in PIDF documents. */ #define PIDF_TUPLE_ID_LEN 6 /** Create a new PIDF tuple id. */ #define NEW_PIDF_TUPLE_ID random_token(PIDF_TUPLE_ID_LEN) /** Character set encoding for outgoing text messages */ #define MSG_TEXT_CHARSET "utf-8" /** @name Definitions for akav1-md5 authentication. */ #define AKA_RANDLEN 16 #define AKA_AUTNLEN 16 #define AKA_CKLEN 16 #define AKA_IKLEN 16 #define AKA_AKLEN 6 #define AKA_OPLEN 16 #define AKA_RESLEN 8 #define AKA_SQNLEN 6 #define AKA_RESHEXLEN 16 #define AKA_AMFLEN 2 #define AKA_KLEN 16 // Set Allow header with methods that can be handled by the phone #define SET_HDR_ALLOW(h, u) { (h).add_method(INVITE); \ (h).add_method(ACK); \ (h).add_method(BYE); \ (h).add_method(CANCEL); \ (h).add_method(OPTIONS); \ if ((u)->get_ext_100rel() != EXT_DISABLED) {\ (h).add_method(PRACK);\ }\ (h).add_method(REFER); \ (h).add_method(NOTIFY); \ (h).add_method(SUBSCRIBE); \ (h).add_method(INFO); \ (h).add_method(MESSAGE); \ } // Set Supported header with supported extensions #define SET_HDR_SUPPORTED(h, u) { if ((u)->get_ext_replaces()) {\ (h).add_feature(EXT_REPLACES);\ }\ (h).add_feature(EXT_NOREFERSUB);\ } // Set Accept header with accepted body types #define SET_HDR_ACCEPT(h) { (h).add_media(t_media("application",\ "sdp")); } /** * Check if the content type of an instant message is supported * @param h [in] A SIP message. */ #define MESSAGE_CONTENT_TYPE_SUPPORTED(h)\ ((h).hdr_content_type.media.type == "application" ||\ (h).hdr_content_type.media.type == "audio" ||\ (h).hdr_content_type.media.type == "image" ||\ (h).hdr_content_type.media.type == "text" ||\ (h).hdr_content_type.media.type == "video") /** * Set Accept header with accepted body types for instant messaging. * @param h [inout] A SIP message. */ #define SET_MESSAGE_HDR_ACCEPT(h) { (h).add_media(t_media("application/*"));\ (h).add_media(t_media("audio/*"));\ (h).add_media(t_media("image/*"));\ (h).add_media(t_media("text/*"));\ (h).add_media(t_media("video/*")); } /** * Set Accept header with accepted body types for presence. * @param h [inout] A SIP message. */ #define SET_PRESENCE_HDR_ACCEPT(h) { (h).add_media(t_media("application",\ "pidf+xml")); } /** * Set Accept header with accepted body types for MWI. * @param h [inout] A SIP message. */ #define SET_MWI_HDR_ACCEPT(h) { (h).add_media(t_media("application",\ "simple-message-summary")); } /** * Set Accept-Encoding header with accepted encodings. * @param h [inout] A SIP message. */ #define SET_HDR_ACCEPT_ENCODING(h)\ { (h).add_coding(t_coding("identity")); } /** * Check if content encoding is supported * @param h [inout] A SIP message. */ #define CONTENT_ENCODING_SUPPORTED(ce)\ (cmp_nocase(ce, "identity") == 0) // Set Accept-Language header with accepted languages #define SET_HDR_ACCEPT_LANGUAGE(h)\ { (h).add_language(t_language("en")); } // Set User-Agent header #define SET_HDR_USER_AGENT(h) { (h).add_server(t_server(PRODUCT_NAME,\ PRODUCT_VERSION)); } // Set Server header #define SET_HDR_SERVER(h) { (h).add_server(t_server(PRODUCT_NAME,\ PRODUCT_VERSION)); } // Set Organization header #define SET_HDR_ORGANIZATION(h, u) { if ((u)->get_organization() != "") {\ (h).set_name((u)->get_organization()); }} // Check if an event is supported by Twinkle #define SIP_EVENT_SUPPORTED(e) ((e) == SIP_EVENT_REFER ||\ (e) == SIP_EVENT_MSG_SUMMARY ||\ (e) == SIP_EVENT_PRESENCE) // Add the supported events to the Allow-Events header #define ADD_SUPPORTED_SIP_EVENTS(h) { (h).add_event_type(SIP_EVENT_REFER);\ (h).add_event_type(SIP_EVENT_MSG_SUMMARY);\ (h).add_event_type(SIP_EVENT_PRESENCE); } #endif