--- channels/chan_sip.c.working 2005-07-23 23:41:23.435918112 +0200 +++ channels/chan_sip.c 2005-07-24 23:42:05.211770728 +0200 @@ -33,6 +33,10 @@ #include "asterisk.h" +/* Include this for message queuing support. Comment out if not wanted. + * You will need to link with sqlite */ +#include "chan_sip_queue.h" + ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.784 $") #include "asterisk/lock.h" @@ -5844,6 +5848,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) { @@ -6610,6 +6617,100 @@ return 0; } +/*--- 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, NULL); + /* 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", callerid); + // 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; +} + /*--- receive_message: Receive SIP MESSAGE method messages ---*/ /* We only handle messages within current calls currently */ /* Reference: RFC 3428 */ @@ -6618,10 +6719,14 @@ 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")) { + if ( (strcmp(content_type, "text/plain")) && (strcmp(content_type, "application/im-iscomposing+xml"))) { /* No text/plain attachment */ transmit_response(p, "415 unsupported media type", req); /* Good enough or? */ ast_set_flag(p, SIP_NEEDDESTROY); @@ -6648,9 +6753,35 @@ 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 */ + /* 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;