--- channels/chan_sip.c 2006-02-27 16:14:53.000000000 +0100 +++ channels/chan_sip.c 2006-06-21 01:39:27.000000000 +0700 @@ -6439,6 +6443,9 @@ } if (!res) { ast_device_state_changed("SIP/%s", peer->name); +#ifdef HAVE_MESSAGE_QUEUING + queue_try_deliver(peer->name); +#endif } if (res < 0) { switch (res) { @@ -7218,6 +7225,101 @@ return 0; } + +/*! \brief send_message_by_name: Sends SIP MESSAGE to user peername. ---*/ +/* Does a lookup on callerid for correct from address setting (will */ +/* probably not work if sender's domain is different) */ +static int send_message_by_name(char *from, char *peername, char *content_type, char *text) +{ + struct sip_pvt *p; + struct sip_peer *r; + struct sip_request req; + char *sender_peername, *tmp, *tmp1; + char clen[256]; + + p = sip_alloc(NULL, NULL, 0, SIP_MESSAGE); + if (!p) { + ast_log(LOG_WARNING, "Unable to build sip pvt data for message\n"); + return RESULT_FAILURE; + } + + if (create_addr(p, peername)) { + sip_destroy(p); + ast_verbose("Could not create address for message delivery to '%s', try delivery later...\n", peername); + return RESULT_FAILURE; + } + + + /* parse from and get their callerid */ + + sender_peername=ast_strdupa(from); + tmp=strstr(sender_peername,"sip:"); + if (tmp) { + tmp+=4; + sender_peername=tmp; + if ((tmp=strstr(sender_peername,"@"))) + { + *tmp='\0'; + tmp++; + if ((tmp1=strstr(tmp,">"))) { + *tmp1='\0'; + strcpy(p->fromdomain,tmp); + } + } + r=find_peer(sender_peername,NULL,1); + if (r) { + if (!ast_strlen_zero(r->cid_name)) + strcpy(p->fromname,r->cid_name); + if (!ast_strlen_zero(r->cid_num)) + strcpy(p->fromuser,r->cid_num); + if (!ast_strlen_zero(r->fromdomain)) + strcpy(p->fromdomain,r->fromdomain); + } + } + + initreqprep(&req, p, SIP_MESSAGE); + /* Recalculate our side, and recalculate Call ID */ + if (ast_sip_ouraddrfor(&p->sa.sin_addr, &p->ourip)) + memcpy(&p->ourip, &__ourip, sizeof(p->ourip)); + build_via(p, p->via, sizeof(p->via)); + build_callid(p->callid, sizeof(p->callid), p->ourip, p->fromdomain); + + + // These are added by initreqprep + // add_header(&req, "From", sender_peername); + // add_header(&req, "To", peername); + + // we could use addtext, but we want to support different content-types, such + // as application/im-iscomposing+xml + // add_text(&req, text); + + snprintf(clen, sizeof(clen), "%d", strlen(text)); + add_header(&req, "Content-Type", content_type); + add_header(&req, "Content-Length", clen); + add_line(&req, text); + + transmit_sip_request(p, &req); + sip_scheddestroy(p, 15000); + return RESULT_SUCCESS; +} + +#ifdef HAVE_MESSAGE_QUEUING +#include "chan_sip_queue.c" +#endif + +static int send_message_by_name_or_queue(char *from, char *peername, char *content_type, char *text) +{ + if (send_message_by_name(from,peername,content_type,text)) { +#ifdef HAVE_MESSAGE_QUEUING + /* we were not able to deliver the message, queue for later delivery */ + if (!strcmp(content_type,"text/plain")) + return queue_message(from,peername,content_type,text); +#endif + return RESULT_FAILURE; + } + return RESULT_SUCCESS; +} + /*! \brief receive_message: Receive SIP MESSAGE method messages ---*/ /* We only handle messages within current calls currently */ @@ -7227,9 +7329,13 @@ char buf[1024]; struct ast_frame f; char *content_type; + char *message_to = ""; + char *type; + char *tmp; + char hint[AST_MAX_EXTENSION]; content_type = get_header(req, "Content-Type"); - if (strcmp(content_type, "text/plain")) { /* No text/plain attachment */ + if ( (strcmp(content_type, "text/plain")) && (strcmp(content_type, "application/im-iscomposing+xml")) && (strcmp(content_type, "text/html"))) { transmit_response(p, "415 Unsupported Media Type", req); /* Good enough, or? */ ast_set_flag(p, SIP_NEEDDESTROY); return; @@ -7253,9 +7359,36 @@ f.datalen = strlen(buf); ast_queue_frame(p->owner, &f); transmit_response(p, "202 Accepted", req); /* We respond 202 accepted, since we relay the message */ - } else { /* Message outside of a call, we do not support that */ - ast_log(LOG_WARNING,"Received message to %s from %s, dropped it...\n Content-Type:%s\n Message: %s\n", get_header(req,"To"), get_header(req,"From"), content_type, buf); - transmit_response(p, "405 Method Not Allowed", req); /* Good enough, or? */ + } else { + /* Preliminary support for SIP MESSAGE sending based on hints */ + tmp=get_header(req,"To"); + if (! (tmp=strstr(tmp,"sip:"))) + { + ast_log(LOG_WARNING,"Received message to %s from %s, dropped it because target is not sip and we don't support that...\n Content-Type:%s\n Message: %s\n", get_header(req,"To"), get_header(req,"From"), content_type, buf); + transmit_response(p, "405 Method not allowed", req); + return; + } + tmp+=4; + message_to=ast_strdupa(tmp); + if ((tmp=strstr(message_to,"@"))) + *tmp='\0'; + if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, "default", message_to)) { + message_to=hint; + type=strsep(&message_to,"/"); + if (strncmp(type,"SIP",3)) { + ast_log(LOG_WARNING,"Received message to %s from %s, dropped it, because hint channel type is not SIP, but %s. We don't support this...\n Content-Type:%s\n Message: %s\n", get_header(req,"To"), get_header(req,"From"), type, content_type, buf); + transmit_response(p, "405 Method not allowed", req); + return; + } + if (send_message_by_name_or_queue(get_header(req,"From"), message_to, + content_type, buf)) + transmit_response(p, "405 Method not allowed", req); + else + transmit_response(p, "202 Accepted", req); + } else { + ast_log(LOG_WARNING,"Received message to %s from %s, dropped it...\n Content-Type:%s\n Message: %s\n", get_header(req,"To"), get_header(req,"From"), content_type, buf); + transmit_response(p, "405 Method Not Allowed", req); /* Good enough, or? */ + } } ast_set_flag(p, SIP_NEEDDESTROY); return;