--- channels/chan_sip.c.orig 2011-02-14 12:20:53.000000000 +0100 +++ channels/chan_sip.c 2011-02-14 16:14:58.000000000 +0100 @@ -2355,7 +2355,6 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_request *req, 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); /*--- Domain handling */ static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */ @@ -2639,7 +2638,7 @@ static int parse_minse(const char *p_hdrval, int *const p_interval); static int st_get_se(struct sip_pvt *, int max); static enum st_refresher st_get_refresher(struct sip_pvt *); -static enum st_mode st_get_mode(struct sip_pvt *); +static enum st_mode st_get_mode(struct sip_pvt *, struct sip_peer *); static struct sip_st_dlg* sip_st_alloc(struct sip_pvt *const p); /*!--- SIP MWI Subscription support */ @@ -9157,7 +9156,7 @@ static int add_supported_header(struct sip_pvt *pvt, struct sip_request *req) { int res; - if (st_get_mode(pvt) != SESSION_TIMER_MODE_REFUSE) { + if (st_get_mode(pvt, NULL) != SESSION_TIMER_MODE_REFUSE) { res = add_header(req, "Supported", "replaces, timer"); } else { res = add_header(req, "Supported", "replaces"); @@ -11042,7 +11041,7 @@ } /* Add Session-Timers related headers */ - if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { + if (st_get_mode(p, NULL) == SESSION_TIMER_MODE_ORIGINATE) { char i2astr[10]; if (!p->stimer->st_interval) @@ -14452,14 +14451,6 @@ return res; } -/*! \brief Find user - If we get a match, this will add a reference pointer to the user object in ASTOBJ, that needs to be unreferenced -*/ -static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, char *uri, enum xmittype reliable, struct sockaddr_in *sin) -{ - return check_user_full(p, req, sipmethod, uri, reliable, sin, NULL); -} - /*! \brief Get text out of a SIP MESSAGE packet */ static int get_msg_text(char *buf, int len, struct sip_request *req, int addnewline) { @@ -16753,7 +16744,7 @@ ast_cli(a->fd, "(none)\n"); if (!cur->stimer) - ast_cli(a->fd, " Session-Timer: Uninitiallized\n"); + ast_cli(a->fd, " Session-Timer: Uninitialized\n"); else { ast_cli(a->fd, " Session-Timer: %s\n", cur->stimer->st_active ? "Active" : "Inactive"); if (cur->stimer->st_active == TRUE) { @@ -17994,7 +17985,7 @@ } /* Check for Session-Timers related headers */ - if (st_get_mode(p) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { + if (st_get_mode(p, NULL) != SESSION_TIMER_MODE_REFUSE && p->outgoing_call == TRUE && !reinvite) { p_hdrval = (char*)get_header(req, "Session-Expires"); if (!ast_strlen_zero(p_hdrval)) { /* UAS supports Session-Timers */ @@ -18016,7 +18007,7 @@ start_session_timer(p); } else { /* UAS doesn't support Session-Timers */ - if (st_get_mode(p) == SESSION_TIMER_MODE_ORIGINATE) { + if (st_get_mode(p, NULL) == SESSION_TIMER_MODE_ORIGINATE) { p->stimer->st_ref = SESSION_TIMER_REFRESHER_UAC; p->stimer->st_active_peer_ua = FALSE; start_session_timer(p); @@ -19937,6 +19928,7 @@ int st_interval = 0; /* Session-Timer negotiated refresh interval */ enum st_refresher st_ref; /* Session-Timer session refresher */ int dlg_min_se = -1; + struct sip_peer *authpeer = NULL; struct { char exten[AST_MAX_EXTENSION]; char context[AST_MAX_CONTEXT]; @@ -20251,7 +20243,7 @@ if (!p->lastinvite && !req->ignore && !p->owner) { /* This is a new invite */ /* Handle authentication if this is our first invite */ - res = check_user(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin); + res = check_user_full(p, req, SIP_INVITE, e, XMIT_RELIABLE, sin, &authpeer); if (res == AUTH_CHALLENGE_SENT) { p->invitestate = INV_COMPLETED; /* Needs to restart in another INVITE transaction */ res = 0; @@ -20423,7 +20415,7 @@ } dlg_min_se = st_get_se(p, FALSE); - switch (st_get_mode(p)) { + switch (st_get_mode(p, authpeer)) { case SESSION_TIMER_MODE_ACCEPT: case SESSION_TIMER_MODE_ORIGINATE: if (uac_max_se > 0 && uac_max_se < dlg_min_se) { @@ -20469,14 +20461,14 @@ break; default: - ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p), __FILE__, __LINE__); + ast_log(LOG_ERROR, "Internal Error %d at %s:%d\n", st_get_mode(p, authpeer), __FILE__, __LINE__); break; } } else { /* The UAC did not request session-timers. Asterisk (UAS), will now decide (based on session-timer-mode in sip.conf) whether to run session-timers for this session or not. */ - switch (st_get_mode(p)) { + switch (st_get_mode(p, authpeer)) { case SESSION_TIMER_MODE_ORIGINATE: st_active = TRUE; st_interval = st_get_se(p, TRUE); @@ -20679,6 +20671,9 @@ request_invite_cleanup: + if (authpeer) + unref_peer(authpeer, "unref_peer, from handle_request_invite (authpeer)"); + if (refer_locked && p->refer && p->refer->refer_call) { sip_pvt_unlock(p->refer->refer_call); if (p->refer->refer_call->owner) { @@ -23153,11 +23148,19 @@ /*! \brief Get the session-timer mode * \param p pointer to the SIP dialog */ -enum st_mode st_get_mode(struct sip_pvt *p) +enum st_mode st_get_mode(struct sip_pvt *p, struct sip_peer *peer) { if (!p->stimer) sip_st_alloc(p); + /* If a peer is supplied, ignore what the cache may say. For example, + * this gets called first from the 401-generating code when we are not + * really confident who the caller really is. */ + if (peer) { + p->stimer->st_cached_mode = peer->stimer.st_mode_oper; + return peer->stimer.st_mode_oper; + } + if (p->stimer->st_cached_mode != SESSION_TIMER_MODE_INVALID) return p->stimer->st_cached_mode;