コード例 #1
0
ファイル: bearerbox.c プロジェクト: markjeee/mbuni
static Octstr  *mm7http_send(MmscGrp *mmc, Octstr *from, Octstr *to,
			     MmsMsg *m, Octstr **error,
			     int *retry)
{
     Octstr *ret = NULL;
     int mtype = mms_messagetype(m);
     int hstatus = HTTP_OK;
     List *rh, *ph = NULL;
     Octstr *body = NULL, *rbody = NULL; 
     Octstr *mms;
     MIMEEntity *form_data = make_multipart_formdata();
     
     mms_info(0, "MM7", mmc->id,  "MMSBox: Send [http] to MMC[%s], msg type [%s], from %s, to %s", 
	  mmc ? octstr_get_cstr(mmc->id) : "", 
	  mms_message_type_to_cstr(mtype), 
	  octstr_get_cstr(from), octstr_get_cstr(to));

     mms = mms_tobinary(m);
     
     add_multipart_form_field(form_data, "to", "text/plain", NULL, to);
     add_multipart_form_field(form_data, "from", "text/plain", NULL, from);
     add_multipart_form_field(form_data, "mms", "application/vnd.wap.mms-message", NULL, mms);

     
     rh = mime_entity_headers(form_data);
     body = mime_entity_body(form_data);

     hstatus = mmsbox_url_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph, &rbody);

     if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
	  *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status = %d !",
				 mmc->mmsc_url, hstatus);
     } else {
	  ret = rbody ? octstr_duplicate(rbody) : NULL;
	  if (ret)
	       octstr_strip_blanks(ret);
     }
     
     *retry = (ret == NULL && (http_status_class(hstatus) == HTTP_STATUS_SERVER_ERROR || hstatus < 0));

     if (ret)
	  mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL);

     http_destroy_headers(rh);
     octstr_destroy(body);
     http_destroy_headers(ph);
     octstr_destroy(rbody);
     octstr_destroy(mms);
     mime_entity_destroy(form_data);
     
     return ret;
}
コード例 #2
0
ファイル: mmsmobilesender.c プロジェクト: frese/mbuni
static int sendNotify(MmsEnvelope *e)
{
     Octstr *to;
     MmsMsg *msg, *smsg = NULL;
     MmsEnvelopeTo *xto = gwlist_get(e->to, 0);
     Octstr *err = NULL;
     time_t tnow = time(NULL);
     int j, k, len;
     Octstr *phonenum = NULL, *rcpt_ip = NULL, *msgId, *from, *fromproxy;
     int mtype, msize;
     int res = MMS_SEND_OK, dlr;
     time_t expiryt;
     char *prov_notify_event = NULL;
     char *rtype = NULL;

          
     if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */	  
	  e->sendt = e->expiryt + 3600*24*30*12;
	  info(0, "MM1: Message [ID: %s] fetched/touched at least once. Skipping",
	       e->xqfname);
	  return settings->qfs->mms_queue_update(e);
     }

     if (!xto) {
	  error(0, "mobilesender: Queue entry %s with no recipients!", 
		e->xqfname);
	  return 0;
     }

     msg = settings->qfs->mms_queue_getdata(e);
     to = octstr_duplicate(xto->rcpt);
     expiryt = e->expiryt;
     msgId = e->msgId ? octstr_duplicate(e->msgId) : NULL;
     from = octstr_duplicate(e->from);
     fromproxy = e->fromproxy ? octstr_duplicate(e->fromproxy) : NULL;
     msize = e->msize;
     dlr = e->dlr;

     if (e->expiryt != 0 &&  /* Handle message expiry. */
	 e->expiryt < tnow) {
	  err = octstr_format("MMSC error: Message expired while sending to %S!", to);
	  res = MMS_SEND_ERROR_FATAL;
	  prov_notify_event = "failedfetch";
	  rtype = "Expired";	  
	  goto done;
     } else if (e->attempts >= settings->maxsendattempts) {
	  err = octstr_format("MMSC error: Failed to deliver to %S after %ld attempts!", 
			      to, e->attempts);
	  res = MMS_SEND_ERROR_FATAL;

	  prov_notify_event = "failedfetch";
	  rtype = "Expired";	  
	  goto done;
     }
     
     j = octstr_case_search(to, octstr_imm("/TYPE=PLMN"), 0);
     k = octstr_case_search(to, octstr_imm("/TYPE=IPv"), 0);
     len = octstr_len(to);
     
     if (j > 0 && j - 1 +  sizeof "/TYPE=PLMN" == len) { /* A proper number. */
	  phonenum = octstr_copy(to, 0, j);
#if 0
	  normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
#else
	  mms_normalize_phonenum(&phonenum, 
				 octstr_get_cstr(settings->unified_prefix), 
				 settings->strip_prefixes);	  
#endif
     }     else if (k > 0 && k + sizeof "/TYPE=IPv" == len) 
	  rcpt_ip = octstr_copy(to, 0, k);
     else {
	  /* We only handle phone numbers here. */
	  err = octstr_format("Unexpected recipient %s in MT queue!", octstr_get_cstr(to));	  
	  res = MMS_SEND_ERROR_FATAL;	  
	  goto done;
     }
     
     mtype = mms_messagetype(msg);     
     
     /* For phone, getting here means the message can be delivered. So: 
      * - Check whether the recipient is provisioned, if not, wait (script called will queue creation req)
      * - If the recipient can't take MMS, then send SMS.
      */
     
     /* We handle two types of requests: send and delivery/read notifications. 
      * other types of messages cannot possibly be in this queue!
      */
     
     if (mtype == MMS_MSGTYPE_SEND_REQ ||
	 mtype == MMS_MSGTYPE_RETRIEVE_CONF) {
	  Octstr *url, *transid;
	  
	  if (phonenum) {
	       int send_ind = mms_ind_send(settings->prov_getstatus, phonenum);
	       
	       if (send_ind < 0 && 
		   settings->notify_unprovisioned)
		    send_ind = 0;

	       if (send_ind < 0) { /* That is, recipient is not (yet) provisioned. */
		    res = MMS_SEND_ERROR_TRANSIENT;
		    err = octstr_format("%S is not provisioned for MMS reception, delivery deferred!", 
					phonenum);
		    
		    /* Do not increase delivery attempts counter. */
		    e->lasttry = tnow;		    
		    e->sendt = e->lasttry + settings->send_back_off * (1 + e->attempts);
		    
		    if (settings->qfs->mms_queue_update(e) == 1) 
			 e = NULL; /* Queue entry gone. */	
		    else 	  
			 settings->qfs->mms_queue_free_env(e);		    		    
		    goto done;
	       } else if (send_ind == 0) { /*  provisioned but does not support */		    
		    Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt),
					      from);
		    if (settings->notify_unprovisioned && s && octstr_len(s) > 0) { /* Only send if the string was set. */
			 List *pheaders;					    
			 Octstr *sto = octstr_duplicate(phonenum);
			 
			 octstr_url_encode(s);
			 octstr_url_encode(sto);
			 
			 url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, sto);
			 pheaders = http_create_empty_headers();
			 http_header_add(pheaders, "Connection", "close");
			 http_header_add(pheaders, "User-Agent", MM_NAME "/" VERSION);      
			 
			 http_start_request(httpcaller, HTTP_METHOD_GET, url, 
					    pheaders, NULL, 0, &edummy, NULL);			 			 
			 http_destroy_headers(pheaders);
			 octstr_destroy(url);
			 octstr_destroy(sto);		   		 
		    } else if (s)
			 octstr_destroy(s);	
		    res = MMS_SEND_OK;
		    err = octstr_imm("No MMS Ind support, sent SMS instead");
		    
		    xto->process = 0; /* No more processing. */
		    if (settings->qfs->mms_queue_update(e) == 1) 
			 e = NULL; 
		    else 	  
			 settings->qfs->mms_queue_free_env(e);		    
		    goto done;

	       }	       
	  }
	  
	  /* To get here means we can send Ind. */
	  url = mms_makefetchurl(e->xqfname, e->token, MMS_LOC_MQUEUE,
				 phonenum ? phonenum : to,
				 settings);
	  info(0, "Preparing to notify client to fetch message at URL: %s",
	       octstr_get_cstr(url));
	  transid = mms_maketransid(e->xqfname, settings->host_alias);	  
	  
	  smsg = mms_notification(msg, e->msize, url, transid, 
				  e->expiryt ? e->expiryt :
				  tnow + settings->default_msgexpiry,
				  settings->optimize_notification_size);
	  octstr_destroy(transid);
	  octstr_destroy(url);
     } else if (mtype == MMS_MSGTYPE_DELIVERY_IND ||
		mtype == MMS_MSGTYPE_READ_ORIG_IND) 
	  smsg = msg;
     else {
	  error(0, "Unexpected message type %s for %s found in MT queue!", 
		mms_message_type_to_cstr(mtype), octstr_get_cstr(to));
	  res = MMS_SEND_ERROR_FATAL;
	  goto done;
     }
     
     if (smsg)
	  start_push(phonenum ? phonenum : rcpt_ip, 
		     phonenum ? 1 : 0, 
		     e, smsg); /* Send the message. 
				* Don't touch 'e' after this point!
				* It may be freed by receive thread. 
				*/
     
     if (smsg != msg && smsg)
	  mms_destroy(smsg);
    
 done:
     if (err != NULL && 
	 res != MMS_SEND_ERROR_TRANSIENT) { /* If there was a report request and this is a legit error
					     *  queue it. 
					     */
	  
	  if (dlr) {	       
	       MmsMsg *m = mms_deliveryreport(msgId, to, tnow, 
					      rtype ? octstr_imm(rtype) : 
					      octstr_imm("Indeterminate"));
	       
	       List *l = gwlist_create();
	       Octstr *res;
	       gwlist_append(l, from);
	       
	       /* Add to queue, switch via proxy to be from proxy. */
	       res = settings->qfs->mms_queue_add(to ? to : settings->system_user, l,  err, 
						  NULL, fromproxy,  
						  tnow, tnow+settings->default_msgexpiry, m, NULL, 
						  NULL, NULL,
						  NULL, NULL,
						  NULL,
						  0,
						  octstr_get_cstr(settings->mm1_queuedir), 
						  "MM2",
						  settings->host_alias);
	       gwlist_destroy(l, NULL);
	       mms_destroy(m);
	       octstr_destroy(res);
	  }
	  
     }
     
     /* Write to log */
     info(0, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s", 
	  SEND_ERROR_STR(res),
	  octstr_get_cstr(from), octstr_get_cstr(to), msize,
	  err ? octstr_get_cstr(err) : "");
     
     
     if (res == MMS_SEND_ERROR_FATAL) {
	  xto->process = 0;  /* No more attempts to deliver, delete this. */	       
	  if (settings->qfs->mms_queue_update(e) == 1) 
	       e = NULL; /* Queue entry gone. */	
	  else 	  
	       settings->qfs->mms_queue_free_env(e);
     }    /* Else queue will be updated/freed elsewhere. */
     
     
     if (prov_notify_event)
	  notify_prov_server(octstr_get_cstr(settings->prov_notify), 
			     to ? octstr_get_cstr(to) : "unknown", 
			     prov_notify_event, 
			     rtype ? rtype : "",
			     e ? e->msgId : NULL, NULL, NULL);

     if (msg) mms_destroy(msg);       

     octstr_destroy(phonenum);
     
     octstr_destroy(rcpt_ip);
     octstr_destroy(to);
     octstr_destroy(msgId);
     octstr_destroy(fromproxy);
     octstr_destroy(from);
     octstr_destroy(err);

     return 1;
}
コード例 #3
0
ファイル: bearerbox.c プロジェクト: markjeee/mbuni
static int sendMsg(MmsEnvelope *e)
{
     MmsMsg *msg = NULL;
     int i, n;     
     Octstr *otransid = e->hdrs ? http_header_value(e->hdrs, octstr_imm("X-Mbuni-TransactionID")) : NULL;

     if ((msg = qfs->mms_queue_getdata(e)) == NULL)  {
	  mms_error(0,  "MM7", NULL, "MMSBox queue error: Failed to load message for queue id [%s]!", e->xqfname);
	  goto done2;
     }
     
     for (i = 0, n = gwlist_len(e->to); i<n; i++) {
	  int res = MMS_SEND_OK;
	  MmsEnvelopeTo *to = gwlist_get(e->to, i);
	  Octstr *err = NULL;
	  time_t tnow = time(NULL);
	  MmscGrp *mmc = NULL;
	  Octstr *new_msgid = NULL;
	  List *errl = NULL;
	  int is_email = 0;

	  if (!to || !to->process)
	       continue;
	  
	  if (e->expiryt != 0 &&  /* Handle message expiry. */
	      e->expiryt < tnow) {
               err = octstr_format("MMSC error: Message expired while sending to %S!", to->rcpt);
               res = MMS_SEND_ERROR_FATAL;
	       
               goto done;
          } else if (e->attempts >= maxsendattempts) {
               err = octstr_format("MMSBox error: Failed to deliver to "
				   "%S after %ld attempts. (max attempts allowed is %ld)!", 
                                   to->rcpt, e->attempts, 
                                   maxsendattempts);
               res = MMS_SEND_ERROR_FATAL;
               goto done;
          }

	  is_email = (octstr_search_char(to->rcpt, '@', 0) > 0);
	  
	  if ((mmc = get_handler_mmc(e->viaproxy, to->rcpt, e->from)) == NULL && !is_email) {
               err = octstr_format("MMSBox error: Failed to deliver to "
				   "%S. Don't know how to route!", 
                                   to->rcpt);
               res = MMS_SEND_ERROR_TRANSIENT;
	       goto done;
	  }
	  
	  if (is_email) {
               int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
               int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
               int len = octstr_len(e->from);
               Octstr *pfrom;
	       
               
               if (j > 0 && j - 1 +  sizeof "/TYPE=PLMN" == len) 
                    pfrom = octstr_copy(e->from, 0, j);
               else if (k > 0 && k + sizeof "/TYPE=IPv" == len) 
                    pfrom = octstr_copy(e->from, 0, k);
               else
                    pfrom = octstr_duplicate(e->from);

               if (octstr_search_char(e->from, '@', 0) < 0)
                    octstr_format_append(pfrom,"@%S", myhostname);
	       
	       res = mms_sendtoemail(pfrom, to->rcpt, 
				     e->subject ? e->subject : octstr_imm(""),
				     e->msgId, msg, 0, &err, octstr_get_cstr(sendmail_cmd),
				     myhostname, 0, 0, 
				     "", 
				     "", 0, 
				     e->xqfname, 
				     e->hdrs);
	       octstr_destroy(pfrom);
	  } else {
	       res = mms_sendtommsc(mmc, e, 
				    to->rcpt, 
				    otransid,
				    msg, 
				    &new_msgid,
				    &errl);
	       if (errl)
		    err = http_header_value(errl, octstr_imm("X-Mbuni-Error"));
	  }
	  if (mmc) {
	       if (res == MMS_SEND_OK)
		    mmc->mt_pdus++;
	       else
		    mmc->mt_errors++;	  
	       mmc->last_pdu = time(NULL);
	       return_mmsc_conn(mmc); /* important. */
	  }
     done:
	  if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED) {
	       to->process = 0;
	       
	       if (e->msgtype == MMS_MSGTYPE_SEND_REQ ||
		   e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */
		    queue_dlr(mmc, e->from, to->rcpt, new_msgid, octstr_imm("Forwarded"), "MM7-Out", errl);
	  } else if (res == MMS_SEND_ERROR_FATAL && mmc) {
	       if (e->msgtype == MMS_MSGTYPE_SEND_REQ ||
		   e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF) /* queue dlr as needed. */		    
		    queue_dlr(mmc, e->from, to->rcpt, e->msgId, 			
			      (e->expiryt != 0 && e->expiryt < tnow) ? 
			 octstr_imm("Expired") : octstr_imm("Rejected"), 
			      "MM7-Out", errl);
	  }
	  if (res == MMS_SEND_ERROR_FATAL)
	       to->process = 0; /* No more attempts. */        


	  /* handle CDR */
	  if (res == MMS_SEND_OK || res == MMS_SEND_QUEUED || res == MMS_SEND_ERROR_FATAL) {
	       Octstr *mclass = mms_get_header_value(msg, octstr_imm("X-Mms-Message-Class"));
	       Octstr *prio = mms_get_header_value(msg, octstr_imm("X-Mms-Priority"));
	       Octstr *mstatus  = mms_get_header_value(msg, octstr_imm("X-Mms-Status"));
	       
	       /* Do CDR */
	       cdrfs->logcdr(e->created, 
			     octstr_get_cstr(e->from),
			     octstr_get_cstr(to->rcpt),
			     octstr_get_cstr(e->msgId),
			     mmc ? octstr_get_cstr(mmc->id) : NULL, /* Should we touch mmc here? XXX */ 
			     e->src_interface, 
			     "MM7",
			     e->msize, 
			     (char *)mms_message_type_to_cstr(e->msgtype),
			     
			     prio ? octstr_get_cstr(prio) : NULL,
			     mclass ? octstr_get_cstr(mclass) : NULL,
			     res == MMS_SEND_ERROR_FATAL ? "dropped" : (mstatus ? octstr_get_cstr(mstatus) : "sent"),
			     e->dlr,
			     0);
	       
	       octstr_destroy(mclass);
	       octstr_destroy(prio);
	       octstr_destroy(mstatus);	       
	  }

	  if (err == NULL)
	       mms_info(0, "MM7", NULL, "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: msgid=[%s]", 
			SEND_ERROR_STR(res),
			octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
			new_msgid ? octstr_get_cstr(new_msgid) : "N/A");
	  else 
	       mms_error_ex("MT", 0, 
			    "MM7", NULL, 
			    "%s MMSBox Outgoing Queue MMS Send: From %s, to %s, msgsize=%ld: %s", 
			    SEND_ERROR_STR(res),
			    octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize, octstr_get_cstr(err));
	  
	  octstr_destroy(new_msgid);
	  octstr_destroy(err);
	  http_destroy_headers(errl);
	  
	  e->lasttry = tnow;
          if (qfs->mms_queue_update(e) == 1) { 
               e = NULL;
               break; /* Queue entry gone. */             
          }
     }

done2:
     mms_destroy(msg);     
     octstr_destroy(otransid);
     
     if (e) { /* Update the queue if it is still valid (e.g. recipients not handled) 
	       * XXX can this happen here??... 
	       */
	  e->lasttry = time(NULL);
	  e->attempts++;  /* Update count of number of delivery attempts. */   
	  e->sendt = e->lasttry + mmsbox_send_back_off * e->attempts;
	  
	  if (qfs->mms_queue_update(e) != 1)
	       qfs->mms_queue_free_env(e);
     }

     
     return 1; /* always delete queue entry. */
}
コード例 #4
0
ファイル: bearerbox.c プロジェクト: markjeee/mbuni
static Octstr  *mm7eaif_send(MmscGrp *mmc, Octstr *from, Octstr *to, 
			     Octstr *transid,
			     char *vasid,
			     List *hdrs,
			     MmsMsg *m, Octstr **error,
			     int *retry)
{
     Octstr *ret = NULL, *resp = NULL;
     int mtype = mms_messagetype(m);
     int hstatus = HTTP_OK;
     List *rh = http_create_empty_headers(), *ph = NULL;
     Octstr *body = NULL, *rbody = NULL, *xver = NULL; 
     char *msgtype;

     
     mms_info(0, "MM7", mmc->id,  "MMSBox: Send [eaif] to MMC[%s], msg type [%s], from %s, to %s", 
	  mmc ? octstr_get_cstr(mmc->id) : "", 
	  mms_message_type_to_cstr(mtype), 
	  octstr_get_cstr(from), octstr_get_cstr(to));

     http_header_remove_all(rh, "X-Mms-Allow-Adaptations");	
     http_header_add(rh, "X-NOKIA-MMSC-To", octstr_get_cstr(to));
     http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from));

     xver = octstr_format(EAIF_VERSION, mmc->ver.major, mmc->ver.minor1);
     http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver));
     octstr_destroy(xver);

     if (mtype == MMS_MSGTYPE_SEND_REQ || 
	 mtype == MMS_MSGTYPE_RETRIEVE_CONF) {
	  msgtype = "MultiMediaMessage";
	  mms_make_sendreq(m); /* ensure it is a sendreq. */
     } else if (mtype == MMS_MSGTYPE_DELIVERY_IND)
	  msgtype = "DeliveryReport";
     else
	  msgtype = "ReadReply";
     http_header_add(rh, "X-NOKIA-MMSC-Message-Type", msgtype);

     if (hdrs)
	  http_header_combine(rh, hdrs);  /* If specified, then update and pass on. */

     http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");

     /* Patch the message FROM and TO fields. */
     mms_replace_header_value(m, "From", octstr_get_cstr(from));
     mms_replace_header_value(m, "To", octstr_get_cstr(to));
     mms_replace_header_value(m,"X-Mms-Transaction-ID",
			      transid ? octstr_get_cstr(transid) : "000");
     body = mms_tobinary(m);	       

     hstatus = mmsbox_url_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph, &rbody);

     if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
	  *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status = %d !",
				 mmc->mmsc_url, hstatus);
     } else {
	  MmsMsg *mresp = rbody ? mms_frombinary(rbody, octstr_imm("anon@anon")) : NULL;
	  
	  resp = octstr_imm("Ok");
	  if (mresp && mms_messagetype(mresp) == MMS_MSGTYPE_SEND_CONF)
	       resp = mms_get_header_value(mresp, octstr_imm("X-Mms-Response-Status"));	  
	  if (octstr_case_compare(resp, octstr_imm("ok")) != 0)
	       hstatus = HTTP_STATUS_SERVER_ERROR; /* error. */
	  else if (mresp)
	       ret = mms_get_header_value(mresp, octstr_imm("Message-ID"));

	  mms_destroy(mresp);
     }

     if (hstatus < 0)
	  ret = NULL; 
     else {
	  hstatus = http_status_class(hstatus);	  
	  if (hstatus == HTTP_STATUS_SERVER_ERROR ||
	      hstatus == HTTP_STATUS_CLIENT_ERROR) 
	       ret = NULL;
	  else if (!ret) 
	       ret = http_header_value(ph, octstr_imm("X-Nokia-MMSC-Message-Id"));
     }
     *retry = (ret == NULL && (hstatus == HTTP_STATUS_SERVER_ERROR || hstatus < 0));

     if (ret)
	  mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL);

#if 0
     mms_info(0, "MM7", mmc->id,"Sent to MMC[%s], code=[%d], resp=[%s] msgid [%s]", 
	  octstr_get_cstr(mmc->id), 
	  hstatus, resp ? octstr_get_cstr(resp) : "(none)", ret ? octstr_get_cstr(ret) : "(none)");
#endif 

     http_destroy_headers(rh);
     octstr_destroy(body);
     http_destroy_headers(ph);
     octstr_destroy(rbody);

     octstr_destroy(resp);
     return ret;
}
コード例 #5
0
ファイル: bearerbox.c プロジェクト: markjeee/mbuni
/* XXX Returns msgid in mmsc or NULL if error. Caller uses this for DLR issues. 
 * Caller must make sure throughput issues
 * are observed!
 * Don't remove from queue on fail, just leave it to expire. 
 */
static Octstr *mm7soap_send(MmscGrp *mmc, Octstr *from, Octstr *to, 
			    Octstr *transid,
			    Octstr *linkedid, 
			    char *vasid,
			    Octstr *service_code,
			    List *hdrs,
			    MmsMsg *m, Octstr **error,
			    List **errl,
			    int *retry)
{
     Octstr *ret = NULL;
     int mtype = mms_messagetype(m);
     int hstatus = HTTP_OK, tstatus  = -1;
     List *xto = gwlist_create();
     MSoapMsg_t *mreq = NULL, *mresp = NULL;
     List *rh = NULL, *ph = NULL;
     Octstr *body = NULL, *rbody = NULL, *url = NULL; 
     Octstr *s;
     char *xvasid = vasid ? vasid : (mmc->default_vasid ? octstr_get_cstr(mmc->default_vasid) : NULL);

     mms_info(0, "MM7", mmc->id,  "MMSBox: Send[soap] to MMSC[%s], msg type [%s], from %s, to %s", 
	  mmc->id ? octstr_get_cstr(mmc->id) : "", 
	  mms_message_type_to_cstr(mtype), 
	  octstr_get_cstr(from), octstr_get_cstr(to));    
     
     gwlist_append(xto, to);
     
     if ((mreq = mm7_mmsmsg_to_soap(m, (mmc == NULL || mmc->no_senderaddress == 0) ? from : NULL, 
				    xto, transid,
				    service_code, 
				    linkedid, 
				    1, octstr_get_cstr(mmc->vasp_id), xvasid, NULL, 0,/* UA N/A on this side. */
				    hdrs)) == NULL) {
	  *error = octstr_format("Failed to convert Msg[%S] 2 SOAP message!",
				 mms_message_type_to_string(mtype));
	  goto done1;
     }
     
     if (mm7_soapmsg_to_httpmsg(mreq, &mmc->ver, &rh, &body) < 0) {
	  *error = octstr_format("Failed to convert SOAP message to HTTP Msg!");
	  goto done1;
     } 

     if (hdrs)
	  http_header_combine(rh, hdrs);  /* If specified, then update and pass on. */
     
     hstatus = mmsbox_url_fetch_content(HTTP_METHOD_POST, mmc->mmsc_url, rh, body, &ph,&rbody);     
     if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
	  *error = octstr_format("Failed to contact MMC[url=%S] => HTTP returned status=[%d]!",
				 mmc->mmsc_url, hstatus);
	  goto done1;
     }
     
     if ((mresp = mm7_parse_soap(ph, rbody)) == NULL) {
	  *error = octstr_format("Failed to parse MMSC[url=%S, id=%S]  response!",
				 mmc->mmsc_url,  mmc->id);
	  goto done1;
     } 

     if (errl) { /* Pick up status stuff -- for DLR */
	  if (*errl == NULL)
	       *errl = http_create_empty_headers();
	  if ((s = mm7_soap_header_value(mresp, octstr_imm("StatusText"))) != NULL) {	  
	       http_header_add(*errl, "X-Mbuni-StatusText", octstr_get_cstr(s));
	       octstr_destroy(s);
	  }

	  if ((s = mm7_soap_header_value(mresp, octstr_imm("Details"))) != NULL) {	  
	       http_header_add(*errl, "X-Mbuni-StatusDetails", octstr_get_cstr(s));
	       octstr_destroy(s);
	  }
     }

     /* Now look at response code and use it to tell you what you want. */
     if ((s = mm7_soap_header_value(mresp, octstr_imm("StatusCode"))) != NULL) {
	  tstatus = atoi(octstr_get_cstr(s));
	  octstr_destroy(s);
     } else if ((s = mm7_soap_header_value(mresp, octstr_imm("faultstring"))) != NULL) {
	  tstatus = atoi(octstr_get_cstr(s));
	  octstr_destroy(s);
     } else
	  tstatus = MM7_SOAP_FORMAT_CORRUPT; 
     

     if (!MM7_SOAP_STATUS_OK(tstatus) && tstatus != MM7_SOAP_COMMAND_REJECTED) {
	  Octstr *detail =  mm7_soap_header_value(mresp, octstr_imm("Details"));
	  char *tmp = (char *)mms_soap_status_to_cstr(tstatus);
	  if (detail == NULL)
	       detail = mm7_soap_header_value(mresp, octstr_imm("faultcode"));
	  ret = NULL;
	  mms_info(0, "MM7", mmc->id, "Send to MMSC[%s], failed, code=[%d=>%s], detail=[%s]", 
	       mmc ? octstr_get_cstr(mmc->id) : "", 
	       tstatus, tmp ? tmp : "", 
	       detail ? octstr_get_cstr(detail) : "");

	  *error = octstr_format("Failed to deliver to MMC[url=%S, id=%S], status=[%d=>%s]!",
				 mmc->mmsc_url, 
				 mmc->id,
				 tstatus, 
				 tmp ? tmp : "");	  
	  octstr_destroy(detail);	  
     } else {	  
	  ret = mm7_soap_header_value(mresp, octstr_imm("MessageID"));	  
	  mms_info(0, "MM7", NULL, "Sent to MMC[%s], code=[%d=>%s], msgid=[%s]", octstr_get_cstr(mmc->id), 
	       tstatus, mms_soap_status_to_cstr(tstatus), ret ? octstr_get_cstr(ret) : "(none)");
     }


     if (ret)
	  mms_log2("Sent", from, to, -1, ret, NULL, mmc->id, "MMSBox", NULL, NULL);
done1:
     *retry = (ret == NULL && (!MM7_SOAP_CLIENT_ERROR(tstatus) || tstatus < 0));
     
     mm7_soap_destroy(mreq);
     mm7_soap_destroy(mresp);	  
     http_destroy_headers(rh);
     octstr_destroy(body);
     http_destroy_headers(ph);
     octstr_destroy(rbody);
     octstr_destroy(url);

     gwlist_destroy(xto, NULL);

     return ret;
}
コード例 #6
0
ファイル: mms_queue.c プロジェクト: frese/mbuni
/* 
 * Attempt to read an envelope from queue file:
 * - opens and locks the file. 
 * - if the lock succeeds, check that file hasn't changed since opening. If it has
 *   return NULL (i.e. file is being processed elsewhere -- race condition), otherwise read it.
 * - If should block is 1, then does a potentially blocking attempt to lock the file.
 */
static MmsEnvelope *mms_queue_readenvelope(char *qf, char *mms_queuedir, int shouldblock)
{
     Octstr *fname;
     int fd;
     Octstr *qdata, *s;
     ParseContext *p;
     MmsEnvelope *e;
     int okfile = 0;
     char subdir[64];
     char realqf[QFNAMEMAX];
     char xqf[QFNAMEMAX+64];
     struct qfile_t *qfs;
     
     get_subdir(qf, subdir, realqf); /* break it down... */

     fname = octstr_format( "%.128s/%s%s", mms_queuedir, subdir, realqf);
     
     strncpy(xqf, octstr_get_cstr(fname), sizeof xqf);
     
#ifdef SunOS
     if ((fd = open(octstr_get_cstr(fname), O_RDWR)) < 0) {
#else
     if ((fd = open(octstr_get_cstr(fname), O_RDONLY)) < 0) {
#endif
		debug("",0,"mms_queue_readenvelope: could not open file %s", octstr_get_cstr(fname));
	  octstr_destroy(fname);
	  return NULL;
     } else if (mm_lockfile(fd, octstr_get_cstr(fname), shouldblock) != 0) {
		debug("",0,"mms_queue_readenvelope: could not lock file %s", octstr_get_cstr(fname));
	  unlock_and_close(fd);
	  octstr_destroy(fname);
	  return NULL;
     }

	debug("",0,"locked and opened file: %s", octstr_get_cstr(fname));
     
     e = mms_queue_create_envelope(NULL, NULL, 
				   NULL, 
				   NULL, NULL, 
				   0, 0, 
				   NULL, 
				   NULL, NULL, 
				   NULL, NULL, 
				   NULL,
				   0, 
				   NULL, 
				   NULL,
				   qf,
				   NULL,
				   sizeof (struct qfile_t), NULL);
     qfs = e->qfs_data;
     
     qfs->fd = fd;
     strncpy(qfs->name, realqf, sizeof qfs->name);
     strncpy(qfs->subdir, subdir, sizeof qfs->subdir);
     strncpy(qfs->dir, mms_queuedir, sizeof qfs->dir);

     qdata = octstr_read_file(octstr_get_cstr(fname));
     octstr_destroy(fname);
     if (qdata == NULL)
	  qdata = octstr_imm("");
     p = parse_context_create(qdata);
     
     for (s = parse_get_line(p); s;  
	  s = parse_get_line(p)) {
	  char *line = octstr_get_cstr(s);
	  int ch = line[0];
	  char *res = line + 1;
	  char *ptmp;

	  switch (ch) {
	       Octstr *t;
	       MmsEnvelopeTo *to;
	  case 'T':
	       t = octstr_create(res);
	       e->msgtype = mms_string_to_message_type(t);
	       octstr_destroy(t);
	       if (e->msgtype < 0) {
		    e->msgtype = 0;
		    error(0, "mms_queueread: Unknown MMS message type (%s) in file %s, skipped!\n",
			  res, xqf);
	       }
	       break;
	  case 'I':
	       e->msgId = octstr_create(res);	       
	       break;
	  case 'i':
	       strncpy(e->src_interface, res, sizeof e->src_interface);
	       break;
	  case 'F':
	       e->from = octstr_create(res);
	       if (mms_validate_address(e->from) != 0) {
		    warning(0, "mms_queueread: Mal-formed address [%s] in file %s! "
			    "Attempting fixup.", res, xqf);
		    _mms_fixup_address(&e->from, NULL, NULL, 1);
	       }
	       break;
	  case 'R':

	       t = octstr_create(res);
	       if (mms_validate_address(t) != 0) {
		    warning(0, "mms_queueread: Mal-formed address [%s] in file %s! " 
			    "Attempting fixup.", res, xqf);
		    _mms_fixup_address(&t, NULL, NULL, 1);
	       }
	       to = gw_malloc(sizeof *to);
	       to->rcpt = t;
	       to->process = 1;	       
	       gwlist_append(e->to, to);
	       break;
	  case 'C':
	       e->created = atol(res);
	       break;
	  case 'L':
	       e->lasttry = atol(res);
	       break;
	  case 'D':
	       e->sendt = atol(res);
	       break;
	  case 'X':
	       e->expiryt = atol(res);
	       break;
	  case 'N':
	       e->attempts = atol(res);
	       break;
	  case 'P':
	       e->fromproxy = octstr_create(res);
	       break;
	  case 'M':
	       e->mdata = octstr_create(res);
	       break;
	  case 'p':
	       e->viaproxy = octstr_create(res);
	       break;
	  case 'S':
	       e->msize = atol(res);
	    break;
	  case 's':
	       e->subject = octstr_create(res);
	       break;	
	  case 't':
	       e->token = octstr_create(res);
	       break;
	  case 'f':
	       e->lastaccess = atol(res);
	       break;
	  case 'b':
	       e->bill.billed = 1;
	       e->bill.amt = atof(res);
	    break;
	  case 'r':
	       e->dlr = 1;
	       break;
	  case 'V':
	       e->vaspid = octstr_create(res);
	       break;
	  case 'v':
	       e->vasid = octstr_create(res);
	       break;

	  case 'U':
	       e->url1 = octstr_create(res);
	       break;

	  case 'u':
	       e->url2 = octstr_create(res);
	       break;
	  case 'H':
	       if (e->hdrs == NULL)
		    e->hdrs = http_create_empty_headers();
	       if ((ptmp = index(res, ':')) == NULL)
		    error(0, "Incorrectly formatted line %s in queue file %s!",
			  line, xqf);
	       else {
		    char *value = ptmp + 1;
		    char hname[512];
		    int xlen = (ptmp - res < sizeof hname) ? ptmp - res : -1 + sizeof hname;
		    strncpy(hname, res, xlen);
		    hname[xlen] = 0; /* terminate it. */
		    http_header_add(e->hdrs, hname, value);
	       }
	       break;
	  case '.':
	       okfile = 1;
	       break;
	  default:
	       error(0, "Unknown QF header %c in file %s!", ch, xqf);
	       break;
	  }
	  octstr_destroy(s);
	  if (okfile) 
	       break; /* We are done. */
     }
     parse_context_destroy(p);
     octstr_destroy(qdata);

     /* We should properly validate the queue file here. */
     if (!okfile) {
	  free_envelope(e,0);
	  e = NULL;
	  error(0, "Corrupt queue control file: %s",  xqf);
     }
     return e;     
}

/* Updates envelope to queue file:
 * - opens temp file
 * - writes output to temp file, if not new else writes directly.
 * - renames temp file to queue file (if not new)
 * This function doesn't check that this envelope is useless (i.e. no recipients)
 * - If function returns -1, caller should check errno for error.
 */
static int writeenvelope(MmsEnvelope *e, int newenv)
{
     Octstr *tfname = NULL;
     char *s;
     char buf[512];
     int fd;
     int i, n;
     int res = 0;
     struct qfile_t *qfs = e ? e->qfs_data : NULL;
     
     gw_assert(e);
     
     if (newenv)
	  fd = qfs->fd;
     else {
	  tfname = octstr_format( 
	       "%s/%s%c%s.%d", qfs->dir, qfs->subdir,
	       MTF, qfs->name + 1, random());
	  fd = open(octstr_get_cstr(tfname),
		    O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
	  if (fd < 0 ) {
	       error(0, "mms_queueadd: Failed to open temp file %s: error = %s\n",
		     octstr_get_cstr(tfname), strerror(errno));
	       res = -1;
	       goto done;
	  } else if (mm_lockfile(fd, octstr_get_cstr(tfname), 0) != 0) { /* Lock it. */
	       error(0, "mms_queueadd: Failed lock  temp file %s: error = %s\n", 
		     octstr_get_cstr(tfname), strerror(errno));
	       res = -1;	  
	       goto done;
	  }
     }
	  
     /* Write out. */

     s = (char *)mms_message_type_to_cstr(e->msgtype);
     if (!s) {
	  error(0, "mms_queuewrite: Unknown MMS message type %d! Skipped\n", e->msgtype);
	  s = "";
     }
     _putline(fd, "T", s);
     
     if (e->msgId) 
	  _putline(fd, "I", octstr_get_cstr(e->msgId));

     if (e->src_interface[0])
	  _putline(fd, "i", e->src_interface);
     
     if (e->from)
	  _putline(fd, "F", octstr_get_cstr(e->from));

     if (e->to)
	  n = gwlist_len(e->to);
     else
	  n = 0;

     for (i = 0; i < n; i++) {
	  MmsEnvelopeTo *to = gwlist_get(e->to, i);
	  
	  if (to->process)	       
	       _putline(fd, "R", octstr_get_cstr(to->rcpt));
     }

     /* Output headers if any. */
     n = (e->hdrs) ? gwlist_len(e->hdrs) : 0;
     for (i = 0; i < n; i++) {
	  Octstr *h = NULL, *v = NULL;

	  http_header_get(e->hdrs, i, &h, &v);
	  if (h && v) {
	       Octstr *x = octstr_format("%s:%s", octstr_get_cstr(h), 
					 octstr_get_cstr(v));
	       _putline(fd, "H", octstr_get_cstr(x));
	       octstr_destroy(x);	       
	  }
	  if (h) octstr_destroy(h);
	  if (v) octstr_destroy(v);

     }

     sprintf(buf, "%ld", e->created);
     _putline(fd, "C", buf);

     if (e->lasttry) {
	  sprintf(buf, "%ld", e->lasttry);
	  _putline(fd, "L", buf);
     }

     if (e->sendt) {
	  sprintf(buf, "%ld", e->sendt);
	  _putline(fd, "D", buf);
     }

     if (e->expiryt) {
	  sprintf(buf, "%ld", e->expiryt);
	  _putline(fd, "X", buf);
     }

     if (e->attempts) {
	  sprintf(buf, "%ld", e->attempts);
	  _putline(fd, "N", buf);
     }

     if (e->lastaccess) {
	  sprintf(buf, "%ld", e->lastaccess);
	  _putline(fd, "f", buf);
     }

     sprintf(buf, "%ld", e->msize);
     _putline(fd, "S", buf);


     if (e->fromproxy) 
	  _putline(fd, "P", octstr_get_cstr(e->fromproxy));


     if (e->mdata) 
	  _putline(fd, "M", octstr_get_cstr(e->mdata));

     if (e->subject)
	  _putline(fd, "s", octstr_get_cstr(e->subject));
     

     if (e->viaproxy) 
	  _putline(fd, "p", octstr_get_cstr(e->viaproxy));

     if (e->token) 
	  _putline(fd, "t", octstr_get_cstr(e->token));
     

      if (e->vaspid) 
	  _putline(fd, "V", octstr_get_cstr(e->vaspid));
     
      if (e->vasid) 
	  _putline(fd, "v", octstr_get_cstr(e->vasid));
     
      if (e->url1) 
	  _putline(fd, "U", octstr_get_cstr(e->url1));

      if (e->url2) 
	  _putline(fd, "u", octstr_get_cstr(e->url2));

     if (e->dlr) 
	  _putline(fd, "r", "Yes");

     if (e->bill.billed) {
	  sprintf(buf, "%.3f", e->bill.amt);
	  _putline(fd,"b", buf);
     }

     _putline(fd, "", ".");

     fsync(fd); /* Sync data. */
     
     if (!newenv) { /* An update */
	  Octstr *qfname;
	 
	  qfname = octstr_format("%s/%s%s", qfs->dir, qfs->subdir, qfs->name);
	
	  if (rename(octstr_get_cstr(tfname), octstr_get_cstr(qfname)) < 0) {
	       error(0, "mms_queuewrite: Failed to rename %s to %s: error = %s\n", 
		     octstr_get_cstr(qfname), octstr_get_cstr(tfname), strerror(errno));

	       unlock_and_close(fd); /* Close new one, keep old one. */
		   res = -1;
	  } else { /* On success, new descriptor replaces old one and we close old one. */
	       unlock_and_close(qfs->fd);
	       qfs->fd = fd;
	  }
	  octstr_destroy(qfname);
     }

 done:
     octstr_destroy(tfname);
     return res;
}