Index: channels/chan_sip.c =================================================================== --- channels/chan_sip.c (revision 324236) +++ channels/chan_sip.c (working copy) @@ -21433,6 +21433,7 @@ int res = 0; const char *event = get_header(req, "Event"); char *sep; + int cache_to_db = FALSE; if( (sep = strchr(event, ';')) ) { /* XXX bug here - overwriting string ? */ *sep++ = '\0'; @@ -21552,14 +21553,88 @@ } else if (!strcmp(event, "message-summary")) { const char *mailbox = NULL; char *c = ast_strdupa(get_body(req, "Voice-Message", ':')); + char *context = "SIP_Remote"; if (!p->mwi) { - struct sip_peer *peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); + ast_debug(4, "Unsolicited MWI received from: %s\n", ast_sockaddr_stringify(&p->recv)); + /* note: If you intend to light unsolicited MWI lights on your phones, + they must be in the same context as the unsolicited_mailbox parameter in the format of: + default_box@context */ + struct sip_peer *peer = find_peer(NULL, &p->recv, TRUE, FINDPEERS, FALSE, p->socket.type); + if (peer) { - mailbox = ast_strdupa(peer->unsolicited_mailbox); + char *unsolicited_mailbox = ast_strdupa(peer->unsolicited_mailbox); + if(!unsolicited_mailbox || ast_strlen_zero(unsolicited_mailbox)) { + ast_debug(2, "unsolicited_mailbox was not set for peer %s, unsolicited MWI will not be delivered.\n", ast_sockaddr_stringify(&p->recv)); + } + else { + { + char* mailbox_only = strchr(unsolicited_mailbox, '@'); + if (mailbox_only) { + *mailbox_only = '\0'; + } + } + + /* If the unsolicited_mailbox parameter has an @ symbol, use that for the context, otherwise leave it at the default of SIP_Remote. */ + char *unsolicited_context = ast_strdupa(peer->unsolicited_mailbox); + if(unsolicited_context) { + unsolicited_context = strchr(unsolicited_context, '@'); + if(unsolicited_context) { + unsolicited_context++; + } + if(unsolicited_context && !ast_strlen_zero(unsolicited_context)) { + context = unsolicited_context; + } + } + //If the user has specfied a mailbox to send *all* unsolicited messages to, send them directly there. + if(unsolicited_mailbox && !ast_strlen_zero(unsolicited_mailbox)) { + mailbox = unsolicited_mailbox; + } + else + { + /* RFC3842 (For the Message-Account header) states: + If the Request-URI or To header in a message-summary subscription + corresponds to a group or collection of individual messaging + accounts, the notifier MUST specify to which account the message- + summary body corresponds. + + Therefore, use Message-Account from the body first, and then failback to the To header. + */ + char *specified_extension = ast_strdupa(get_body(req, "Message-Account", ':')); + if(!specified_extension || ast_strlen_zero(specified_extension)) { + specified_extension = ast_strdupa(get_header(req, "To")); + } + + if(specified_extension && !ast_strlen_zero(specified_extension)) { + /* Get the mailbox from the format: */ + char *specified_mailbox = strchr(specified_extension, '@'); + if (specified_mailbox) { + *specified_mailbox = '\0'; + } + specified_mailbox = strchr(specified_extension, ':'); + if (specified_mailbox) { + specified_mailbox++; + + if(specified_mailbox && !ast_strlen_zero(specified_mailbox)) { + mailbox = specified_mailbox; + } + } + } + } + if(mailbox && !ast_strlen_zero(mailbox)) { + ast_debug(4, "Unsolicited MWI being delivered to: %s@%s\n", mailbox, context); + cache_to_db = TRUE; + } + else + ast_debug(2, "Could not find a valid mailbox. Unsolicited MWI will not be delivered."); + } + unref_peer(peer, "removing unsolicited mwi ref"); } + else { + ast_debug(2, "Unsolicited MWI received from an unknown peer and wont be routed: %s\n", ast_sockaddr_stringify(&p->recv)); + } } else { mailbox = p->mwi->mailbox; } @@ -21571,12 +21646,20 @@ if ((event = ast_event_new(AST_EVENT_MWI, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox, - AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, "SIP_Remote", + AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(new), AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, atoi(old), AST_EVENT_IE_END))) { ast_event_queue_and_cache(event); } + if (cache_to_db) { + ast_debug(4, "caching status of unsolicited MWI for '%s@%s' in ast_db\n", mailbox, context); + char mailbox_key[256]; + char data[SIPBUFSIZE]; + snprintf(mailbox_key, sizeof(mailbox_key), "%s@%s", mailbox, context); + snprintf(data, sizeof(data), "%s:%s:%s:%s", mailbox, context, new, old); + ast_db_put("SIP/unsolicited_MWI_cache", mailbox_key, data); + } transmit_response(p, "200 OK", req); } else { transmit_response(p, "489 Bad event", req); @@ -25336,12 +25419,41 @@ if (event) { newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS); oldmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_OLDMSGS); - } else if (!cache_only) { /* Fall back to manually checking the mailbox */ + } else if (!get_cached_mwi(peer, &newmsgs, &oldmsgs)) { + /* got it! Don't keep looking. */ + } else if (cache_only) { + return 0; + } else { /* Fall back to manually checking the mailbox */ struct ast_str *mailbox_str = ast_str_alloca(512); peer_mailboxes_to_str(&mailbox_str, peer); - ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs); - } else { - get_cached_mwi(peer, &newmsgs, &oldmsgs); + + if (!ast_app_inboxcount(mailbox_str->str, &newmsgs, &oldmsgs)) { + /* if no mailbox found, try to fetch from ast DB */ + /* KH@ciphron.de */ + struct ast_event *event; + char data[256]; + ast_debug(4, "trying to read cached status of unsolicited MWI for '%s' from ast_db\n", mailbox_str->str); + if (!ast_db_get("SIP/unsolicited_MWI_cache", mailbox_str->str, data, sizeof(data))) { + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(mailbox); + AST_APP_ARG(context); + AST_APP_ARG(newmsgs); + AST_APP_ARG(oldmsgs); + ); + AST_NONSTANDARD_RAW_ARGS(args, data, ':'); + newmsgs = atoi(args.newmsgs); + oldmsgs = atoi(args.oldmsgs); + if ((event = ast_event_new(AST_EVENT_MWI, + AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, args.mailbox, + AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, args.context, + AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_UINT, newmsgs, + AST_EVENT_IE_OLDMSGS, AST_EVENT_IE_PLTYPE_UINT, oldmsgs, + AST_EVENT_IE_END))) { + ast_event_queue_and_cache(event); + } + ast_debug(4, "restored unsolicited MWI from ast_db to event cache. mailbox '%s' has %s new, %s old messages\n", mailbox_str->str, newmsgs, oldmsgs); + } + } } if (peer->mwipvt) {