diff options
author | rizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-10-12 22:07:11 +0000 |
---|---|---|
committer | rizzo <rizzo@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-10-12 22:07:11 +0000 |
commit | a2d8f5d39b534241f61774d46ce6da154f14667e (patch) | |
tree | f9cd4df3c335b76198d0915af89168f298246a54 /channels | |
parent | ff4811fde0c4cb74023cad71cac3beb6329e65ac (diff) |
merge formatting and minor code simplifications from trunk
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@44992 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r-- | channels/chan_sip.c | 304 |
1 files changed, 147 insertions, 157 deletions
diff --git a/channels/chan_sip.c b/channels/chan_sip.c index dcd10bfba..cbafa148b 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -181,10 +181,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") below EXPIRY_GUARD_LIMIT */ #define DEFAULT_EXPIRY 900 /*!< Expire slowly */ -static int min_expiry; /*!< Minimum accepted registration time */ -static int max_expiry; /*!< Maximum accepted registration time */ -static int default_expiry; -static int expiry; +static int min_expiry = DEFAULT_MIN_EXPIRY; /*!< Minimum accepted registration time */ +static int max_expiry = DEFAULT_MAX_EXPIRY; /*!< Maximum accepted registration time */ +static int default_expiry = DEFAULT_DEFAULT_EXPIRY; +static int expiry = DEFAULT_EXPIRY; #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b)) @@ -1260,7 +1260,6 @@ static void add_noncodec_to_sdp(const struct sip_pvt *p, int format, int sample_ static int add_sdp(struct sip_request *resp, struct sip_pvt *p); /*--- Authentication stuff */ -static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init); static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len); static int build_reply_digest(struct sip_pvt *p, int method, char *digest, int digest_len); static int clear_realm_authentication(struct sip_auth *authlist); /* Clear realm authentication list (at reload) */ @@ -1273,8 +1272,6 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin, struct sip_peer **authpeer); static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin); -static int do_proxy_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader, int sipmethod, int init); -static int build_reply_digest(struct sip_pvt *p, int method, char* digest, int digest_len); /*--- Domain handling */ static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */ @@ -1413,7 +1410,6 @@ static char *regstate2str(enum sipregistrystate regstate) attribute_const; static int sip_reregister(void *data); static int __sip_do_register(struct sip_registry *r); static int sip_reg_timeout(void *data); -static int do_register_auth(struct sip_pvt *p, struct sip_request *req, char *header, char *respheader); static int reply_digest(struct sip_pvt *p, struct sip_request *req, char *header, int sipmethod, char *digest, int digest_len); static void sip_send_all_registers(void); @@ -1497,7 +1493,6 @@ static int local_attended_transfer(struct sip_pvt *transferer, struct sip_dual * /*------Response handling functions */ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno); static void handle_response_refer(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int seqno); -static int handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req); static int handle_response_register(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno); static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_request *req, int ignore, int seqno); @@ -4537,6 +4532,8 @@ static int find_sdp(struct sip_request *req) /*! \brief Process SIP SDP offer, select formats and activate RTP channels If offer is rejected, we will not change any properties of the call + Return 0 on success, a negative value on errors. + Must be called after find_sdp(). */ static int process_sdp(struct sip_pvt *p, struct sip_request *req) { @@ -11341,10 +11338,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru /* RFC3261 says we must treat every 1xx response (but not 100) that we don't recognize as if it was 183. */ - if ((resp > 100) && - (resp < 200) && - (resp != 180) && - (resp != 183)) + if (resp > 100 && resp < 200 && resp != 180 && resp != 183) resp = 183; switch (resp) { @@ -11353,6 +11347,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru sip_cancel_destroy(p); check_pendings(p); break; + case 180: /* 180 Ringing */ if (!ast_test_flag(req, SIP_PKT_IGNORE)) sip_cancel_destroy(p); @@ -11372,6 +11367,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru ast_set_flag(&p->flags[0], SIP_CAN_BYE); check_pendings(p); break; + case 183: /* Session progress */ if (!ast_test_flag(req, SIP_PKT_IGNORE)) sip_cancel_destroy(p); @@ -11386,6 +11382,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru ast_set_flag(&p->flags[0], SIP_CAN_BYE); check_pendings(p); break; + case 200: /* 200 OK on invite - someone's answering our call */ if (!ast_test_flag(req, SIP_PKT_IGNORE)) sip_cancel_destroy(p); @@ -11505,6 +11502,7 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru } } break; + case 403: /* Forbidden */ /* First we ACK */ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); @@ -11514,22 +11512,26 @@ static void handle_response_invite(struct sip_pvt *p, int resp, char *rest, stru ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); ast_set_flag(&p->flags[0], SIP_ALREADYGONE); break; + case 404: /* Not found */ transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); if (p->owner && !ast_test_flag(req, SIP_PKT_IGNORE)) ast_queue_control(p->owner, AST_CONTROL_CONGESTION); ast_set_flag(&p->flags[0], SIP_ALREADYGONE); break; + case 481: /* Call leg does not exist */ /* Could be REFER or INVITE */ ast_log(LOG_WARNING, "Re-invite to non-existing call leg on other UA. SIP dialog '%s'. Giving up.\n", p->callid); transmit_request(p, SIP_ACK, seqno, XMIT_UNRELIABLE, FALSE); break; + case 491: /* Pending */ /* we have to wait a while, then retransmit */ /* Transmission is rescheduled, so everything should be taken care of. We should support the retry-after at some point */ break; + case 501: /* Not implemented */ if (p->owner) ast_queue_control(p->owner, AST_CONTROL_CONGESTION); @@ -11717,57 +11719,50 @@ static int handle_response_register(struct sip_pvt *p, int resp, char *rest, str } /*! \brief Handle qualification responses (OPTIONS) */ -static int handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req) +static void handle_response_peerpoke(struct sip_pvt *p, int resp, struct sip_request *req) { - struct sip_peer *peer; - int pingtime; - struct timeval tv; - - if (resp != 100) { - int statechanged = 0; - int newstate = 0; - peer = p->relatedpeer; - gettimeofday(&tv, NULL); - pingtime = ast_tvdiff_ms(tv, peer->ps); - if (pingtime < 1) - pingtime = 1; - if ((peer->lastms < 0) || (peer->lastms > peer->maxms)) { - if (pingtime <= peer->maxms) { - ast_log(LOG_NOTICE, "Peer '%s' is now REACHABLE! (%dms / %dms)\n", peer->name, pingtime, peer->maxms); - statechanged = 1; - newstate = 1; - } - } else if ((peer->lastms > 0) && (peer->lastms <= peer->maxms)) { - if (pingtime > peer->maxms) { - ast_log(LOG_NOTICE, "Peer '%s' is now TOO LAGGED! (%dms / %dms)\n", peer->name, pingtime, peer->maxms); - statechanged = 1; - newstate = 2; - } - } - if (!peer->lastms) - statechanged = 1; - peer->lastms = pingtime; - peer->call = NULL; - if (statechanged) { - ast_device_state_changed("SIP/%s", peer->name); - if (newstate == 2) { - manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Lagged\r\nTime: %d\r\n", peer->name, pingtime); - } else { - manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Reachable\r\nTime: %d\r\n", peer->name, pingtime); - } - } + struct sip_peer *peer = p->relatedpeer; + int statechanged, is_reachable, was_reachable; + int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps); - if (peer->pokeexpire > -1) - ast_sched_del(sched, peer->pokeexpire); - ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + /* + * Compute the response time to a ping (goes in peer->lastms.) + * -1 means did not respond, 0 means unknown, + * 1..maxms is a valid response, >maxms means late response. + */ + if (pingtime < 1) /* zero = unknown, so round up to 1 */ + pingtime = 1; - /* Try again eventually */ - if ((peer->lastms < 0) || (peer->lastms > peer->maxms)) - peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_NOTOK, sip_poke_peer_s, peer); - else - peer->pokeexpire = ast_sched_add(sched, DEFAULT_FREQ_OK, sip_poke_peer_s, peer); + /* Now determine new state and whether it has changed. + * Use some helper variables to simplify the writing + * of the expressions. + */ + was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms; + is_reachable = pingtime <= peer->maxms; + statechanged = peer->lastms == 0 /* yes, unknown before */ + || was_reachable != is_reachable; + + peer->lastms = pingtime; + peer->call = NULL; + if (statechanged) { + const char *s = is_reachable ? "Reachable" : "Lagged"; + + ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n", + peer->name, s, pingtime, peer->maxms); + ast_device_state_changed("SIP/%s", peer->name); + manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", + "Peer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n", + peer->name, s, pingtime); } - return 1; + + if (peer->pokeexpire > -1) + ast_sched_del(sched, peer->pokeexpire); + ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + + /* Try again eventually */ + peer->pokeexpire = ast_sched_add(sched, + is_reachable ? DEFAULT_FREQ_OK : DEFAULT_FREQ_NOTOK, + sip_poke_peer_s, peer); } /*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */ @@ -11819,8 +11814,8 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ /* We don't really care what the response is, just that it replied back. Well, as long as it's not a 100 response... since we might need to hang around for something more "definitive" */ - - res = handle_response_peerpoke(p, resp, req); + if (resp != 100) + handle_response_peerpoke(p, resp, req); } else if (ast_test_flag(&p->flags[0], SIP_OUTGOING)) { switch(resp) { case 100: /* 100 Trying */ @@ -13904,73 +13899,73 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, transmit_response(p, "404 Not Found", req); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); return 0; - } else { - /* XXX reduce nesting here */ - /* Initialize tag for new subscriptions */ - if (ast_strlen_zero(p->tag)) - make_our_tag(p->tag, sizeof(p->tag)); + } - if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ + /* Initialize tag for new subscriptions */ + if (ast_strlen_zero(p->tag)) + make_our_tag(p->tag, sizeof(p->tag)); - /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ - /* Polycom phones only handle xpidf+xml, even if they say they can - handle pidf+xml as well - */ - if (strstr(p->useragent, "Polycom")) { - p->subscribed = XPIDF_XML; - } else if (strstr(accept, "application/pidf+xml")) { - p->subscribed = PIDF_XML; /* RFC 3863 format */ - } else if (strstr(accept, "application/dialog-info+xml")) { - p->subscribed = DIALOG_INFO_XML; - /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ - } else if (strstr(accept, "application/cpim-pidf+xml")) { - p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ - } else if (strstr(accept, "application/xpidf+xml")) { - p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ - } else { - /* Can't find a format for events that we know about */ - transmit_response(p, "489 Bad Event", req); - ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); - return 0; - } - } else if (!strcmp(event, "message-summary")) { - if (!ast_strlen_zero(accept) && strcmp(accept, "application/simple-message-summary")) { - /* Format requested that we do not support */ - transmit_response(p, "406 Not Acceptable", req); - if (option_debug > 1) - ast_log(LOG_DEBUG, "Received SIP mailbox subscription for unknown format: %s\n", accept); - ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); - return 0; - } - /* Looks like they actually want a mailbox status - This version of Asterisk supports mailbox subscriptions - The subscribed URI needs to exist in the dial plan - In most devices, this is configurable to the voicemailmain extension you use - */ - if (!authpeer || ast_strlen_zero(authpeer->mailbox)) { - transmit_response(p, "404 Not found (no mailbox)", req); - ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); - ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name); - return 0; - } + if (!strcmp(event, "presence") || !strcmp(event, "dialog")) { /* Presence, RFC 3842 */ - p->subscribed = MWI_NOTIFICATION; - if (authpeer->mwipvt && authpeer->mwipvt != p) /* Destroy old PVT if this is a new one */ - /* We only allow one subscription per peer */ - sip_destroy(authpeer->mwipvt); - authpeer->mwipvt = p; /* Link from peer to pvt */ - p->relatedpeer = authpeer; /* Link from pvt to peer */ - } else { /* At this point, Asterisk does not understand the specified event */ + /* Header from Xten Eye-beam Accept: multipart/related, application/rlmi+xml, application/pidf+xml, application/xpidf+xml */ + /* Polycom phones only handle xpidf+xml, even if they say they can + handle pidf+xml as well + */ + if (strstr(p->useragent, "Polycom")) { + p->subscribed = XPIDF_XML; + } else if (strstr(accept, "application/pidf+xml")) { + p->subscribed = PIDF_XML; /* RFC 3863 format */ + } else if (strstr(accept, "application/dialog-info+xml")) { + p->subscribed = DIALOG_INFO_XML; + /* IETF draft: draft-ietf-sipping-dialog-package-05.txt */ + } else if (strstr(accept, "application/cpim-pidf+xml")) { + p->subscribed = CPIM_PIDF_XML; /* RFC 3863 format */ + } else if (strstr(accept, "application/xpidf+xml")) { + p->subscribed = XPIDF_XML; /* Early pre-RFC 3863 format with MSN additions (Microsoft Messenger) */ + } else { + /* Can't find a format for events that we know about */ transmit_response(p, "489 Bad Event", req); + ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + return 0; + } + } else if (!strcmp(event, "message-summary")) { + if (!ast_strlen_zero(accept) && strcmp(accept, "application/simple-message-summary")) { + /* Format requested that we do not support */ + transmit_response(p, "406 Not Acceptable", req); if (option_debug > 1) - ast_log(LOG_DEBUG, "Received SIP subscribe for unknown event package: %s\n", event); - ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + ast_log(LOG_DEBUG, "Received SIP mailbox subscription for unknown format: %s\n", accept); + ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); return 0; } - if (p->subscribed != MWI_NOTIFICATION && !resubscribe) - p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p); + /* Looks like they actually want a mailbox status + This version of Asterisk supports mailbox subscriptions + The subscribed URI needs to exist in the dial plan + In most devices, this is configurable to the voicemailmain extension you use + */ + if (!authpeer || ast_strlen_zero(authpeer->mailbox)) { + transmit_response(p, "404 Not found (no mailbox)", req); + ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + ast_log(LOG_NOTICE, "Received SIP subscribe for peer without mailbox: %s\n", authpeer->name); + return 0; + } + + p->subscribed = MWI_NOTIFICATION; + if (authpeer->mwipvt && authpeer->mwipvt != p) /* Destroy old PVT if this is a new one */ + /* We only allow one subscription per peer */ + sip_destroy(authpeer->mwipvt); + authpeer->mwipvt = p; /* Link from peer to pvt */ + p->relatedpeer = authpeer; /* Link from pvt to peer */ + } else { /* At this point, Asterisk does not understand the specified event */ + transmit_response(p, "489 Bad Event", req); + if (option_debug > 1) + ast_log(LOG_DEBUG, "Received SIP subscribe for unknown event package: %s\n", event); + ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); + return 0; } + if (p->subscribed != MWI_NOTIFICATION && !resubscribe) + p->stateid = ast_extension_state_add(p->context, p->exten, cb_extensionstate, p); + if (!ast_test_flag(req, SIP_PKT_IGNORE) && p) p->lastinvite = seqno; if (p && !ast_test_flag(&p->flags[0], SIP_NEEDDESTROY)) { @@ -14001,48 +13996,47 @@ static int handle_request_subscribe(struct sip_pvt *p, struct sip_request *req, ASTOBJ_UNLOCK(p->relatedpeer); } } else { + struct sip_pvt *p_old; + if ((firststate = ast_extension_state(NULL, p->context, p->exten)) < 0) { ast_log(LOG_ERROR, "Got SUBSCRIBE for extension %s@%s from %s, but there is no hint for that extension\n", p->exten, p->context, ast_inet_ntoa(p->sa.sin_addr)); transmit_response(p, "404 Not found", req); ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); return 0; - } else { - /* XXX reduce nesting here */ - struct sip_pvt *p_old; - - transmit_response(p, "200 OK", req); - transmit_state_notify(p, firststate, 1); /* Send first notification */ - append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); - /* hide the 'complete' exten/context in the refer_to field for later display */ - ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); - - /* remove any old subscription from this peer for the same exten/context, - as the peer has obviously forgotten about it and it's wasteful to wait - for it to expire and send NOTIFY messages to the peer only to have them - ignored (or generate errors) - */ - ast_mutex_lock(&iflock); - for (p_old = iflist; p_old; p_old = p_old->next) { - if (p_old == p) - continue; - if (p_old->initreq.method != SIP_SUBSCRIBE) - continue; - if (p_old->subscribed == NONE) - continue; - ast_mutex_lock(&p_old->lock); - if (!strcmp(p_old->username, p->username)) { - if (!strcmp(p_old->exten, p->exten) && - !strcmp(p_old->context, p->context)) { - ast_set_flag(&p_old->flags[0], SIP_NEEDDESTROY); - ast_mutex_unlock(&p_old->lock); - break; - } + } + + transmit_response(p, "200 OK", req); + transmit_state_notify(p, firststate, 1); /* Send first notification */ + append_history(p, "Subscribestatus", "%s", ast_extension_state2str(firststate)); + /* hide the 'complete' exten/context in the refer_to field for later display */ + ast_string_field_build(p, subscribeuri, "%s@%s", p->exten, p->context); + + /* remove any old subscription from this peer for the same exten/context, + as the peer has obviously forgotten about it and it's wasteful to wait + for it to expire and send NOTIFY messages to the peer only to have them + ignored (or generate errors) + */ + ast_mutex_lock(&iflock); + for (p_old = iflist; p_old; p_old = p_old->next) { + if (p_old == p) + continue; + if (p_old->initreq.method != SIP_SUBSCRIBE) + continue; + if (p_old->subscribed == NONE) + continue; + ast_mutex_lock(&p_old->lock); + if (!strcmp(p_old->username, p->username)) { + if (!strcmp(p_old->exten, p->exten) && + !strcmp(p_old->context, p->context)) { + ast_set_flag(&p_old->flags[0], SIP_NEEDDESTROY); + ast_mutex_unlock(&p_old->lock); + break; } - ast_mutex_unlock(&p_old->lock); } - ast_mutex_unlock(&iflock); + ast_mutex_unlock(&p_old->lock); } + ast_mutex_unlock(&iflock); } if (!p->expiry) ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); @@ -15685,10 +15679,6 @@ static int reload_config(enum channelreloadreason reason) allow_external_domains = DEFAULT_ALLOW_EXT_DOM; /* Allow external invites */ global_regcontext[0] = '\0'; expiry = DEFAULT_EXPIRY; - min_expiry = DEFAULT_MIN_EXPIRY; /*!< Minimum accepted registration time */ - max_expiry = DEFAULT_MAX_EXPIRY; /*!< Maximum accepted registration time */ - default_expiry = DEFAULT_DEFAULT_EXPIRY; - expiry = DEFAULT_EXPIRY; global_notifyringing = DEFAULT_NOTIFYRINGING; global_alwaysauthreject = 0; global_allowsubscribe = FALSE; |