diff -Naur mbuni-0.9.6/ChangeLog mbuni-0.9.7/ChangeLog
--- mbuni-0.9.6/ChangeLog	Sat Feb  5 09:23:57 2005
+++ mbuni-0.9.7/ChangeLog	Wed Mar  2 15:32:28 2005
@@ -1,2 +1,8 @@
-2005-02-05 Paul Bagyenda <bagyenda@dsmagic.com>
+Mbuni 0.9.6 - 2005-02-05
    * Initial release 0.9.6
+Mbuni 0.9.7 - 2005-02-20
+   * Added support for sending to IP addresses
+   * Fixed bug with message forwarding on MM1
+   * Fixed bug in mmsproxy when message fetched but fetch not confirmed.
+   * Added access.log
+   * various minor bug fixes
diff -Naur mbuni-0.9.6/mmlib/mms_msg.c mbuni-0.9.7/mmlib/mms_msg.c
--- mbuni-0.9.6/mmlib/mms_msg.c	Wed Feb  9 14:16:35 2005
+++ mbuni-0.9.7/mmlib/mms_msg.c	Wed Mar  2 14:01:54 2005
@@ -10,7 +10,7 @@
      int message_type; 
      Octstr *msgId;
      List *headers; /* Of type HTTPHeader. */
-
+     
      unsigned char ismultipart;
      union {
 	  List *l;
@@ -57,9 +57,9 @@
      if (octstr_search_char(s, '@', 0) > 0)
 	  return 0;
      else if (i >= 0)	
-	  if (octstr_search(s, octstr_imm("PLMN"), 0) + 4 == l ||
-	      octstr_search(s, octstr_imm("IPv4"), 0) + 4 == l ||
-	      octstr_search(s, octstr_imm("IPv6"), 0) + 4 == l)
+	  if (octstr_case_search(s, octstr_imm("PLMN"), 0) + 4 == l ||
+	      octstr_case_search(s, octstr_imm("IPv4"), 0) + 4 == l ||
+	      octstr_case_search(s, octstr_imm("IPv6"), 0) + 4 == l)
 	       return 0;
 	  else
 	       return -1;
@@ -205,7 +205,7 @@
      ret = wsp_field_value(context, &val);
 
      if (parse_error(context)) {
-	  warning(0, "Faulty header, skipping remaining headers.");
+	  warning(0, "Faulty header [code = %d], skipping remaining headers.", field_type);
 	  parse_skip_to_limit(context);
 	  return;
      }
@@ -231,7 +231,8 @@
 	  }
 
 	  if (mms_validate_address(decoded))
-	       warning(0, "Faulty receipient address format in field %s!", hname);
+	       warning(0, "Faulty address [%s] format in field %s!", 
+		       octstr_get_cstr(decoded), hname);
 	  break;
      case MMS_HEADER_SUBJECT:
      case MMS_HEADER_RESPONSE_TEXT:
@@ -363,7 +364,8 @@
 			 } else 
 			      decoded = parse_get_nul_string(context);
 			 if (mms_validate_address(decoded))
-			      warning(0, "Faulty receipient address format in field %s!", hname);			 
+			      warning(0, "Faulty address [%s] format in field %s!", 
+				      octstr_get_cstr(decoded), hname);			 
 		    } else /* Insert address. */
 			 decoded = octstr_duplicate(xfrom);
 	       }
@@ -423,7 +425,7 @@
      return;
      
  value_error:
-     warning(0, "Skipping faulty header.");
+     warning(0, "Skipping faulty header [code = %d, val=%d]!", field_type, val);
      octstr_destroy(decoded);     
 }
 
@@ -1151,14 +1153,13 @@
      MmsMsg *m;
 
 
-     if (!msg)
-	  return NULL;
-
-     if (msg->message_type == MMS_MSGTYPE_RETRIEVE_CONF)
-	  return msg; /* Unchanged. */
+     if (msg) {
+	  if (msg->message_type == MMS_MSGTYPE_RETRIEVE_CONF)
+	       return msg; /* Unchanged. XXX should we copy it instead?!! */
 	  
-     if (msg->message_type != MMS_MSGTYPE_SEND_REQ)
-	  return NULL;
+	  if (msg->message_type != MMS_MSGTYPE_SEND_REQ)
+	       return NULL;
+     }
 
      m  = gw_malloc(sizeof *m);
      m->msgId = msg ? octstr_duplicate(msg->msgId) : NULL;
diff -Naur mbuni-0.9.6/mmlib/mms_msg.h mbuni-0.9.7/mmlib/mms_msg.h
--- mbuni-0.9.6/mmlib/mms_msg.h	Sat Jan 29 16:24:04 2005
+++ mbuni-0.9.7/mmlib/mms_msg.h	Wed Mar  2 14:01:58 2005
@@ -53,4 +53,5 @@
 int mms_replace_header_value(MmsMsg *msg, char *hname, char *value);
 
 int mms_convert_readrec2readorig(MmsMsg *msg);
+
 #endif
diff -Naur mbuni-0.9.6/mmlib/mms_queue.c mbuni-0.9.7/mmlib/mms_queue.c
--- mbuni-0.9.6/mmlib/mms_queue.c	Sat Jan 29 16:22:56 2005
+++ mbuni-0.9.7/mmlib/mms_queue.c	Wed Mar  2 15:06:15 2005
@@ -697,7 +697,7 @@
 
      while ((e = list_consume(qt->l)) != NULL) {
 	  int res = qt->deliver(e); /* If it is on the queue, it has to be delivered. */
-	  	  
+	  
 	  if (res != 1) /* Then delete as it wasn't deleted. */
 	       free_envelope(e, 0);	       	  	  
      }     
@@ -753,9 +753,10 @@
 			 int j = i; /* This is the next queue to use. Checking for cycles. */
 			 do {
 			      if (tlist[i].l) {
+				   debug("queuerun", 0, "Queued to thread %d for %s/%s", 
+					 i, dir, dp->d_name);
 				   list_produce(tlist[i].l, e);
 				   queued = 1;
-				   debug("queuerun", 0, "Queued to thread %d for %s", i, dir);
 			      }
 			      i = (i+1)%num_threads;
 			 }  while (!queued && i != j);
diff -Naur mbuni-0.9.6/mmlib/mms_util.c mbuni-0.9.7/mmlib/mms_util.c
--- mbuni-0.9.6/mmlib/mms_util.c	Mon Feb 21 17:30:12 2005
+++ mbuni-0.9.7/mmlib/mms_util.c	Wed Mar  2 15:13:32 2005
@@ -17,7 +17,7 @@
      Octstr *v = cfg_get(grp, item);
 
      
-     return v ? v : octstr_imm("");
+     return v ? v : octstr_create("");
 }
 
 MmsBoxSettings *mms_load_mmsbox_settings(Cfg *cfg)
@@ -77,8 +77,7 @@
      
      user = cfg_getx(grp, octstr_imm("sendsms-username"));     
      pass = cfg_getx(grp, octstr_imm("sendsms-password"));     
-     from = cfg_getx(grp, octstr_imm("sendsms-global-sender"));     
-
+     from = cfg_get(grp, octstr_imm("sendsms-global-sender"));     
 
      if (user && octstr_len(user) > 1)
 	  octstr_url_encode(user);
@@ -86,18 +85,19 @@
 	  octstr_url_encode(pass);
      if (from && octstr_len(from) > 1) 
 	  octstr_url_encode(from);
-     
+
+       
      octstr_format_append(m->sendsms_url, 
 			  (from && octstr_len(from) > 1) ? 
 			  "?username=%S&password=%S&from=%S" : 
 			  "?username=%S&password=%S",	  
 			  user,
 			  pass,from);	
-     
+   
      m->system_user = octstr_format("system-user@%S", 
 				    m->hostname);	  
-     if (user) octstr_destroy(user);
-     if (pass) octstr_destroy(pass);
+     octstr_destroy(user);
+     octstr_destroy(pass);
      if (from) octstr_destroy(from);
      
      cfg_get_integer(&port, grp, octstr_imm("mms-port"));
@@ -212,19 +212,33 @@
 }
 
 
-Octstr *mms_find_sender_msisdn(Octstr *send_url, List *request_hdrs, Octstr *msisdn_header)
+Octstr *mms_find_sender_msisdn(Octstr **send_url, List *request_hdrs, Octstr *msisdn_header)
 {
      /* Either we have a WAP gateway header as defined, or we look for 
       * last part of url as our number.
       */
+     Octstr *xsend_url = *send_url;
+     
      Octstr *phonenum = http_header_value(request_hdrs, 
 					  msisdn_header);
      
      if (!phonenum || octstr_len(phonenum) == 0) {
-	  List *l  = octstr_split(send_url, octstr_imm("/"));
+	  List *l  = octstr_split(xsend_url, octstr_imm("/"));
 
-	  if (l && list_len(l) > 1)
+	  if (l && list_len(l) > 1) {
+	       int i, n = list_len(l);
+	       Octstr *s;
 	       phonenum = octstr_duplicate(list_get(l, list_len(l) - 1));
+
+	       /* After getting it, remove it from the end... */
+	       for (i = 0, s = octstr_create(""); i < n-1; i++) {
+		    Octstr *p = list_get(l, i);
+		    if (octstr_len(p) > 0)
+			 octstr_format_append(s, "/%S", p);
+	       }
+	       octstr_destroy(xsend_url);
+	       *send_url = s;
+	  }
 	  if (l)
 	       list_destroy(l, (list_item_destructor_t *)octstr_destroy);
      }
@@ -235,18 +249,39 @@
 int mms_decodefetchurl(Octstr *fetch_url,  
 		       Octstr **qf, Octstr **token)
 {
+     Octstr *xfurl = octstr_duplicate(fetch_url);
      int i, j, n;
-          
+     char *s, *p;
+     
+     for (i = 0, n = 0, s = octstr_get_cstr(xfurl); 
+	  i < octstr_len(xfurl); i++)
+	  if (s[i] == '/')
+	       n++;
+     if (n < 2) /* We need at least two slashes. */
+	  octstr_append_char(xfurl, '/');
+     
      i = 0;
-     n = octstr_len(fetch_url);
+     n = octstr_len(xfurl);
+     s = octstr_get_cstr(xfurl);
+     
+     p = strrchr(s, '/'); /* Find last slash. */
+     if (p)
+	  i = (p - s) - 1;
+     else
+	  i = n-1;
+     
+     if (i < 0)
+	  i = 0;
+     
+     while (i>0 && s[i] != '/')
+	  i--; /* Go back, find first slash */
+     if (i>=0 && s[i] == '/')
+	  i++;
      
-     while (i<n && octstr_get_char(fetch_url, i) == '/')
-	  i++; /* Skip slashes. */
-
      /* Now we have qf, find its end. */
      
      j = i;     
-     while (j<n && octstr_get_char(fetch_url, j) != '/')
+     while (j<n && s[j] != '/')
 	  j++; /* Skip to next slash. */
      
      *qf = octstr_copy(fetch_url, i, j-i);
@@ -255,6 +290,7 @@
 	  *token = octstr_copy(fetch_url, j + 1, n - (j+1));
      else
 	  *token = octstr_create("");
+     octstr_destroy(xfurl);
      return 0;
 }
 
@@ -776,4 +812,51 @@
      mime_entity_destroy(m);
 
      return ret;
+}
+
+void mms_log2(char *logmsg, Octstr *from, Octstr *to, 
+	      int msize, Octstr *msgid,
+	      Octstr *acct,
+	      Octstr *viaproxy,
+	      char *interface, Octstr *ua)
+{
+     List *l;
+     if (to) {
+	  l = list_create();
+	  list_append(l, to);
+     } else
+	  l = NULL;
+     
+     mms_log(logmsg, from,l,msize,msgid,acct,viaproxy,interface,ua);
+     
+     if (l) 
+	  list_destroy(l, NULL);
+}
+
+void mms_log(char *logmsg, Octstr *from, List *to, 
+	     int msize, Octstr *msgid,
+	     Octstr *acct,
+	     Octstr *viaproxy,
+	     char *interface, Octstr *ua)
+{
+     Octstr *xto = octstr_create("");
+     int i, n = to ? list_len(to) : 0;
+
+     for (i = 0; i < n; i++)
+	  octstr_format_append(xto, 
+			       "%s%S",
+			       (i == 0) ? "" : ", ",
+			       list_get(to,i));
+       
+     alog("%s MMS [INT:%s] [ACT:%s] [MMSC:%s] [from:%s] [to:%s] [msgid:%s] [size=%d] [UA:%s]", 
+	  logmsg, interface, 
+	  acct ? octstr_get_cstr(acct) : "",
+	  viaproxy ? octstr_get_cstr(viaproxy) : "",
+	  from ? octstr_get_cstr(from) : "",
+	  octstr_get_cstr(xto),
+	  msgid ? octstr_get_cstr(msgid) : "",
+	  msize,
+	  ua ? octstr_get_cstr(ua) : "");
+
+     octstr_destroy(xto);
 }
diff -Naur mbuni-0.9.6/mmlib/mms_util.h mbuni-0.9.7/mmlib/mms_util.h
--- mbuni-0.9.6/mmlib/mms_util.h	Mon Feb  7 17:32:02 2005
+++ mbuni-0.9.7/mmlib/mms_util.h	Wed Mar  2 14:45:43 2005
@@ -98,7 +98,7 @@
 extern int mms_decodefetchurl(Octstr *fetch_url, 
 			      Octstr **qf, Octstr **token);
 
-Octstr *mms_find_sender_msisdn(Octstr *send_url, List *request_hdrs, Octstr *msisdn_header);
+Octstr *mms_find_sender_msisdn(Octstr **send_url, List *request_hdrs, Octstr *msisdn_header);
 
 extern Octstr *mms_isodate(time_t t);
 void mms_lib_init(void);
@@ -134,4 +134,16 @@
 		    int trans_msg,
 		    int trans_smil, char *txt, char *html, int append_hostname);
 
+/* log to access log. */
+void mms_log(char *logmsg, Octstr *from, List *to, 
+	     int msize, Octstr *msgid,
+	     Octstr *acct,
+	     Octstr *viaproxy,
+	     char *interface, Octstr *ua);
+
+void mms_log2(char *logmsg, Octstr *from, Octstr *to, 
+	      int msize, Octstr *msgid,
+	      Octstr *acct,
+	      Octstr *viaproxy,
+	      char *interface, Octstr *ua);
 #endif
diff -Naur mbuni-0.9.6/mmsc/mmsfromemail.c mbuni-0.9.7/mmsc/mmsfromemail.c
--- mbuni-0.9.6/mmsc/mmsfromemail.c	Fri Jan 28 16:30:04 2005
+++ mbuni-0.9.7/mmsc/mmsfromemail.c	Wed Mar  2 15:29:12 2005
@@ -27,7 +27,7 @@
      int cfidx;
      Octstr *fname;
      CfgGroup *grp;
-     Octstr *log;
+     Octstr *log, *alog;
      long loglevel;
      MIMEEntity *mm;
      MmsMsg *msg;
@@ -64,6 +64,14 @@
 	  octstr_destroy(log);
      }
      
+     
+     /* Get access log and open it. */
+     alog = cfg_get(grp, octstr_imm("access-log"));
+     if (alog) {
+	  alog_open(octstr_get_cstr(alog), 1, 1);
+	  octstr_destroy(alog);
+     }
+
      /* Load proxy relays. */
      
      proxyrelays = mms_proxy_relays(cfg);
@@ -179,6 +187,11 @@
 		    mms_destroy(mresp);
 		    octstr_destroy(qf);
 	       }
+
+	       mms_log("Received", xfrom, lto, 
+		       -1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL);
+	       
+
 	       octstr_destroy(transid);
 	       octstr_destroy(msgid);
 	       if (dreport) 
diff -Naur mbuni-0.9.6/mmsc/mmsglobalsender.c mbuni-0.9.7/mmsc/mmsglobalsender.c
--- mbuni-0.9.6/mmsc/mmsglobalsender.c	Fri Jan 28 16:30:04 2005
+++ mbuni-0.9.7/mmsc/mmsglobalsender.c	Wed Mar  2 14:09:44 2005
@@ -138,29 +138,39 @@
 	  }
 
 	  /* first check if it is an email address */	  
-	  if (octstr_search_char(to->rcpt, '@', 0) > 0) 
+	  if (octstr_search_char(to->rcpt, '@', 0) > 0) {
 	       res = mms_sendtoemail(e->from, to->rcpt, 
 				     e->subject, 
 				     e->msgId, msg, e->dlr, &err, sendmail_cmd,
 				     settings->hostname, 1, 1, octstr_get_cstr(settings->mms_email_txt), 
 				     octstr_get_cstr(settings->mms_email_html), 1);
-	   else if (e->viaproxy && octstr_len(e->viaproxy) > 0) /* If proxy to send through is already set, use it. */
+	       mms_log2("Sent", e->from, to->rcpt, 
+			-1, e->msgId, NULL, NULL, "MM3", NULL);
+
+	 }  else if (e->viaproxy && octstr_len(e->viaproxy) > 0) /* If proxy to send through is already set, use it. */
 	       res =  mms_sendtoproxy(e->from, 
 				      to->rcpt, e->subject, e->viaproxy, 
 				      e->msgId, e->expiryt, msg, e->dlr, &err);	  
 	  else {
 	       int j = octstr_case_search(to->rcpt, octstr_imm("/TYPE=PLMN"), 0);
+	       int k = octstr_case_search(to->rcpt, octstr_imm("/TYPE=IPv"), 0);
 	       int len = octstr_len(to->rcpt);
 	       Octstr *phonenum = NULL;
 	       int sent = 0;
 	       
 	       if (j > 0 && j - 1 +  sizeof "/TYPE=PLMN" == len) /* A proper number. */
 		    phonenum = octstr_copy(to->rcpt, 0, j);
-	       else {
+	       else if (k > 0 && k + sizeof "/TYPE=IPv" == len) {
+		    res = mms_sendtomobile(e->from, 
+					   to->rcpt, e->subject, e->fromproxy, 
+					   e->msgId, e->expiryt, msg, e->dlr, &err);    
+		    sent = 1;
+		    goto done;
+	       } else {
 		    /* We don't handle other types for now. */
 		    err = octstr_format("MMSC error: Unsupported recipient type %S", to->rcpt);
 		    res = MMS_SEND_ERROR_FATAL;
-
+		    
 		    goto done;
 	       }
 	       
@@ -282,7 +292,7 @@
      int cfidx;
      Octstr *fname;
      CfgGroup *grp;
-     Octstr *log;
+     Octstr *log, *alog;
      long loglevel;
 
      mms_lib_init();
@@ -315,6 +325,13 @@
 	  octstr_destroy(log);
      }
      
+     /* Get access log and open it. */
+     alog = cfg_get(grp, octstr_imm("access-log"));
+     if (alog) {
+	  alog_open(octstr_get_cstr(alog), 1, 1);
+	  octstr_destroy(alog);
+     }
+
      /* Load proxy relays. */
      
      proxyrelays = mms_proxy_relays(cfg);
@@ -452,6 +469,10 @@
      x = mms_sendtoemail(from, pto, subject, msgid,  msg, 0, 
 			 error, sendmail_cmd,
 			 settings->hostname, 0, 0,NULL,NULL,0);
+
+     mms_log2("Sent", from, to, 
+	      -1, msgid, NULL, proxy, "MM4", NULL);
+     
      octstr_destroy(pto);
 
      return x;
diff -Naur mbuni-0.9.6/mmsc/mmsmobilesender.c mbuni-0.9.7/mmsc/mmsmobilesender.c
--- mbuni-0.9.6/mmsc/mmsmobilesender.c	Wed Feb  9 14:20:12 2005
+++ mbuni-0.9.7/mmsc/mmsmobilesender.c	Wed Mar  2 15:24:43 2005
@@ -10,32 +10,63 @@
 #include "mms_uaprof.h"
 #include "mms_util.h"
 
+#define WAPPUSH_PORT 2948
+
 static MmsBoxSettings *settings;
 static HTTPCaller *httpcaller; 
 static int rstop = 0;
 static MmsEnvelope edummy;
 
-static void start_push(Octstr *phonenum, MmsEnvelope *e, MmsMsg *msg)
+
+static MmsEnvelope *update_env_success(MmsEnvelope *env, MmsEnvelopeTo *xto)
+{
+     time_t tnow = time(NULL);
+     
+     if (xto && env->msgtype != MMS_MSGTYPE_SEND_REQ)
+	  xto->process = 0; /* No more processing. */
+     else {
+	  env->lasttry = tnow;
+	  env->attempts++;     
+	  env->sendt = env->lasttry + settings->send_back_off * env->attempts;
+     }
+     
+     if (mms_queue_update(env) == 1)
+	  env = NULL;     
+     return env;
+} 
+
+static MmsEnvelope *update_env_failed(MmsEnvelope *env)
+{
+     time_t tnow = time(NULL);
+     if (env && env != &edummy) {
+	  env->sendt = tnow + settings->send_back_off;
+	  env->lasttry = tnow;
+	  
+	  if (mms_queue_update(env) == 1)
+	       env = NULL;
+     }
+     return env;
+}
+
+static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg)
 {
      List *pheaders;
      static unsigned char ct; /* Transaction counter -- do we need it? */
-     Octstr *to;
-
+     Octstr *to = NULL;
+     
      Octstr *pduhdr = octstr_create("");
      
-     Octstr *s = mms_tobinary(msg), *url;
-
+     Octstr *s = NULL;
+     
 
-     info(0, "mms2mobile.startpush: notification\n");
+     info(0, "mms2mobile.startpush: notification to %s\n", octstr_get_cstr(rcpt_to));
      
-     if (!phonenum) {
+     if (!rcpt_to) {
 	  error(0, "mobilesender: Queue entry %s has no recipient address!", e->qf.name);
 	  goto done;
      } else
-	  to = octstr_duplicate(phonenum);
+	  to = octstr_duplicate(rcpt_to);
      
-     octstr_url_encode(to);
-     octstr_url_encode(s);
 
      ct++;    
      octstr_append_char(pduhdr, ct);
@@ -54,25 +85,53 @@
      octstr_append_char(pduhdr, 0xaf); /* charset. */
      octstr_append_char(pduhdr, 0x84); /* ... */
 
-     octstr_url_encode(pduhdr);
-     
-     url = octstr_format("%S&text=%S%S&to=%S&udh=%%06%%05%%04%%0B%%84%%23%%F0",	
-			 settings->sendsms_url, pduhdr, s, to);     
-
-     pheaders = http_create_empty_headers();
-     http_header_add(pheaders, "Connection", "close");
-     http_header_add(pheaders, "User-Agent", MM_NAME "/" GW_VERSION);	       
+     s = mms_tobinary(msg);
 
-     http_start_request(httpcaller, HTTP_METHOD_GET, url, 
-			pheaders, NULL, 0, e, NULL);
-     
-     
-     http_destroy_headers(pheaders);
-     octstr_destroy(to);
-     octstr_destroy(url);
-     octstr_destroy(pduhdr);
+     if (isphonenum) {
+	  Octstr *url;
+	  
+	  octstr_url_encode(to);
+	  octstr_url_encode(s);
+	  
+	  octstr_url_encode(pduhdr);
+	  
+	  url = octstr_format("%S&text=%S%S&to=%S&udh=%%06%%05%%04%%0B%%84%%23%%F0",	
+			      settings->sendsms_url, pduhdr, s, to);     
+	  
+	  pheaders = http_create_empty_headers();
+	  http_header_add(pheaders, "Connection", "close");
+	  http_header_add(pheaders, "User-Agent", MM_NAME "/" GW_VERSION);	       
+	  
+	  http_start_request(httpcaller, HTTP_METHOD_GET, url, 
+			     pheaders, NULL, 0, e, NULL);
+	  	  
+	  http_destroy_headers(pheaders);
+	  octstr_destroy(url);
+     } else { /* An IP Address: Send packet, forget. */
+	  Octstr *addr = udp_create_address(to, WAPPUSH_PORT);
+	  int sock = udp_client_socket();
+	  
+	  if (sock > 0) {
+	       MmsEnvelopeTo *xto = list_get(e->to,0);
+	       octstr_append(pduhdr, s);
+	       udp_sendto(sock, pduhdr, addr);
+	       close(sock); /* ?? */      
+	       mms_log2("Notify", octstr_imm("system"), to, 
+			-1, e ? e->msgId : NULL, 
+			NULL, NULL, "MM1", NULL);
+	       e = update_env_success(e, xto);
+	  } else {
+	       e = update_env_failed(e);
+	       error(0, "push to %s:%d failed, no reason found", octstr_get_cstr(to), WAPPUSH_PORT);
+	  }
+	  octstr_destroy(addr);
+	  if (e) 
+	       mms_queue_free_env(e);
+     }
  done:
-     octstr_destroy(s);
+     if (to) octstr_destroy(to);
+     if (pduhdr) octstr_destroy(pduhdr);
+     if (s) octstr_destroy(s);
 }
 
 
@@ -89,9 +148,8 @@
      
      while ((env = http_receive_result(caller, &http_status, &final_url, &reply_headers,
 				       &reply_body)) != NULL) {
-	  time_t tnow = time(NULL);
 	  MmsEnvelopeTo *xto;
-	  Octstr *to;
+	  Octstr *to = NULL;
 	  	  
 	  if (http_status == -1 || final_url == NULL) {
 	       error(0, "push failed, no reason found");
@@ -129,32 +187,20 @@
 
 	  debug("mobilesender.push", 0, "Push reply headers were");
 	  http_header_dump(reply_headers);
+	  
+	  mms_log2("Notify", octstr_imm("system"), to, 
+		   -1, env ? env->msgId : NULL, NULL, NULL, "MM1", NULL);
 
-	  if (xto && env->msgtype != MMS_MSGTYPE_SEND_REQ)
-	       xto->process = 0; /* No more processing. */
-	  else {
-	       env->lasttry = tnow;
-	       env->attempts++;     
-	       env->sendt = env->lasttry + settings->send_back_off * env->attempts;
-	  }
-
-	  if (mms_queue_update(env) == 1)
-	       env = NULL;
-	  else
+	  if (update_env_success(env, xto) != NULL)
 	       goto push_free_env;
+
 	  /* Fall through. */
      push_failed:    
 	  octstr_destroy(final_url);    
 	  octstr_destroy(reply_body);
 	  http_destroy_headers(reply_headers);
 	  
-	  if (env && env != &edummy) {
-	       env->sendt = tnow + settings->send_back_off;
-	       env->lasttry = tnow;
-	       
-	       if (mms_queue_update(env) == 1)
-		    env = NULL;
-	  }
+	  env = update_env_failed(env);
      push_free_env:
 	  if (env && env != &edummy) 
 	       mms_queue_free_env(env);
@@ -170,17 +216,19 @@
      MmsEnvelopeTo *xto = list_get(e->to, 0);
      Octstr *err = NULL;
      time_t tnow = time(NULL);
-     int j, len;
-     Octstr *phonenum = NULL, *msgId, *from, *fromproxy;
+     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. */
-	  return 0;
+          
+     if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */
+	  e->sendt = e->expiryt + 3600*24*30*12;	  
+	  return mms_queue_update(e);
+     }
 
      if (!xto) {
 	  error(0, "mobilesender: Queue entry %s with no recipients!", 
@@ -215,10 +263,14 @@
      }
      
      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. */
+     if (j > 0 && j - 1 +  sizeof "/TYPE=PLMN" == len) { /* A proper number. */
 	  phonenum = octstr_copy(to, 0, j);
+	  normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
+     }     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));	  
@@ -226,119 +278,121 @@
 	  goto done;
      }
      
-     normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
      mtype = mms_messagetype(msg);     
-
-     /* Getting here means the message can be delivered. So: 
+     
+     /* 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)
       * - Send to MMBox if not yet done. 
       * - 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;
-	  int send_ind = mms_ind_send(settings->prov_getstatus, phonenum);
 	  
-	  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 (phonenum) {
+	       int send_ind = mms_ind_send(settings->prov_getstatus, phonenum);
 	       
-	       if (mms_queue_update(e) == 1) 
-		    e = NULL; /* Queue entry gone. */	
-	       else 	  
-		    mms_queue_free_env(e);		    
-  
-	       goto done;
-	  } else if (e->mdata == NULL) { /* That is, not yet sent to MMBox etc, but provisioned. */
-
-	       int x;
-	       if (settings->mmbox_host && 
-		   octstr_len(settings->mmbox_host) > 0) { /* Only if mmbox is configured. */
-		    Octstr *mto = octstr_format("%S@%S", phonenum, settings->mmbox_host); 		    
-		    x = mms_sendtoemail(from, mto, e->subject, e->msgId, msg, 0, &err, 
-					octstr_get_cstr(settings->sendmail), settings->hostname, 1,
-					1, octstr_get_cstr(settings->mms_email_txt), 
-					octstr_get_cstr(settings->mms_email_html), 1);
-		    octstr_destroy(mto);
-	       } else 
-		    x = 0;
-	       
-	       if (x != 0) { /* Failed to send to MMBox...*/
+	       if (send_ind < 0) { /* That is, recipient is not (yet) provisioned. */
 		    res = MMS_SEND_ERROR_TRANSIENT;
-		    err = octstr_format("Failed to send to MMBox %d", x);
-		    e->attempts++;
+		    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 * e->attempts;
-
+		    e->sendt = e->lasttry + settings->send_back_off * (1 + e->attempts);
+		    
 		    if (mms_queue_update(e) == 1) 
 			 e = NULL; /* Queue entry gone. */	
 		    else 	  
 			 mms_queue_free_env(e);		    
-		    goto done;
-	       }
-	       
-	       /* else Send to MMBox succeeded or non-provisioned.
-		* But if phone cannot handle MMS-Ind, then send it sms.
-		*/
-	       if (send_ind == 0) { 
-		    Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt), from);
-		    List *pheaders;			
 		    
-		    Octstr *xto = octstr_duplicate(phonenum);
-
-		    octstr_url_encode(s);
-		    octstr_url_encode(xto);
-
-		    url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, xto);
-		    pheaders = http_create_empty_headers();
-		    http_header_add(pheaders, "Connection", "close");
-		    http_header_add(pheaders, "User-Agent", MM_NAME "/" GW_VERSION);	       
-		    
-		    http_start_request(httpcaller, HTTP_METHOD_GET, url, 
-				       pheaders, NULL, 0, &edummy, NULL);
+		    goto done;
+	       } else if (e->mdata == NULL) { /* Not yet sent to MMBox etc, but provisioned. */
 		    
+		    int x;
+		    if (settings->mmbox_host && 
+			octstr_len(settings->mmbox_host) > 0) { /* Only if mmbox is configured. */
+			 Octstr *mto = octstr_format("%S@%S", phonenum, settings->mmbox_host); 		    
+			 x = mms_sendtoemail(from, mto, e->subject, e->msgId, msg, 0, &err, 
+					     octstr_get_cstr(settings->sendmail), settings->hostname, 1,
+					     1, octstr_get_cstr(settings->mms_email_txt), 
+					     octstr_get_cstr(settings->mms_email_html), 1);
+			 octstr_destroy(mto);
+		    } else 
+			 x = 0;
 		    
-		    http_destroy_headers(pheaders);
-		    octstr_destroy(url);
-		    octstr_destroy(s);	
-		    octstr_destroy(xto);		   		 
+		    if (x != 0) { /* Failed to send to MMBox...*/
+			 res = MMS_SEND_ERROR_TRANSIENT;
+			 err = octstr_format("Failed to send to MMBox %d", x);
+			 e->attempts++;
+			 e->lasttry = tnow;		    
+			 e->sendt = e->lasttry + settings->send_back_off * e->attempts;
+			 
+			 if (mms_queue_update(e) == 1) 
+			      e = NULL; /* Queue entry gone. */	
+			 else 	  
+			      mms_queue_free_env(e);		    
+			 goto done;
+		    }
 		    
+		    /* else Send to MMBox succeeded or non-provisioned.
+		     * But if phone cannot handle MMS-Ind, then send it sms.
+		     */
+		    if (send_ind == 0) { 
+			 Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt),
+						   from);
+			 List *pheaders;			
+			 
+			 Octstr *xto = octstr_duplicate(phonenum);
+			 
+			 octstr_url_encode(s);
+			 octstr_url_encode(xto);
+			 
+			 url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, xto);
+			 pheaders = http_create_empty_headers();
+			 http_header_add(pheaders, "Connection", "close");
+			 http_header_add(pheaders, "User-Agent", MM_NAME "/" GW_VERSION);      
+			 
+			 http_start_request(httpcaller, HTTP_METHOD_GET, url, 
+					    pheaders, NULL, 0, &edummy, NULL);
+			 
+			 
+			 http_destroy_headers(pheaders);
+			 octstr_destroy(url);
+			 octstr_destroy(s);	
+			 octstr_destroy(xto);		   		 
+			 
+		    }
+		    e->mdata = octstr_imm("MMSent");	/* Mark as sent to MMBox. */
+		    if (mms_queue_update(e) == 1) {
+			 e = NULL;
+			 goto done;
+		    }		    		    
 	       }
-	       e->mdata = octstr_imm("MMSent");	/* Mark as sent to MMBox. */
-	       if (mms_queue_update(e) == 1) {
-		    e = NULL;
-		    goto done;
-	       }		    		    
-	       
 	       
-	  }
-	  
-	  if (send_ind == 0) { /* No MMS Ind, go away but first update queue entry. */
-	       res = MMS_SEND_OK;
-	       err = octstr_imm("No MMS Ind support, sent SMS instead");
-	       
-	       xto->process = 0; /* No more processing. */
-	       if (mms_queue_update(e) == 1) 
-		    e = NULL; 
-	       else 	  
-		    mms_queue_free_env(e);		    
-	       goto done;
+	       if (send_ind == 0) { /* No MMS Ind, go away but first update queue entry. */
+		    res = MMS_SEND_OK;
+		    err = octstr_imm("No MMS Ind support, sent SMS instead");
+		    
+		    xto->process = 0; /* No more processing. */
+		    if (mms_queue_update(e) == 1) 
+			 e = NULL; 
+		    else 	  
+			 mms_queue_free_env(e);		    
+		    goto done;
+	       }
 	  }
 	  
 	  /* To get here means we can send Ind. */
 	  url = mms_makefetchurl(e->qf.name, e->token, 
 				 settings);
 	  transid = mms_maketransid(e->qf.name, settings->host_alias);	  
-
+	  
 	  smsg = mms_notification(msg, e->msize, url, transid, 
 				  e->expiryt ? e->expiryt :
 				  tnow + settings->default_msgexpiry);
@@ -353,12 +407,14 @@
 	  res = MMS_SEND_ERROR_FATAL;
 	  goto done;
      }
-
+     
      if (smsg)
-	  start_push(phonenum, e, smsg); /* Send the message. 
-					  * Don't touch 'e' after this point!
-					  * It may be freed by receive thread. 
-					  */
+	  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);
@@ -371,7 +427,8 @@
 	  
 	  if (dlr) {	       
 	       MmsMsg *m = mms_deliveryreport(msgId, to, tnow, 
-					      rtype ? octstr_imm(rtype) : octstr_imm("Indeterminate"));
+					      rtype ? octstr_imm(rtype) : 
+					      octstr_imm("Indeterminate"));
 	       
 	       List *l = list_create();
 	       Octstr *res;
@@ -390,7 +447,7 @@
      }
      
      /* Write to log */
-     info(0, "%s Mobile Queue MMS Send: From %s, to %s, msgsize=%d, reason=%s", 
+     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) : "");
@@ -414,6 +471,8 @@
      if (msg) mms_destroy(msg);       
      if (phonenum) 
 	  octstr_destroy(phonenum);
+     if (rcpt_ip)
+	  octstr_destroy(rcpt_ip);
      octstr_destroy(to);
      if (msgId) octstr_destroy(msgId);
      if (fromproxy) octstr_destroy(fromproxy);
@@ -435,7 +494,7 @@
      int cfidx;
      Octstr *fname;
      CfgGroup *grp;
-     Octstr *log;
+     Octstr *log, *alog;
      long loglevel;
 
      mms_lib_init();
@@ -467,6 +526,13 @@
 	  octstr_destroy(log);
      }
      
+     /* Get access log and open it. */
+     alog = cfg_get(grp, octstr_imm("access-log"));
+     if (alog) {
+	  alog_open(octstr_get_cstr(alog), 1, 1);
+	  octstr_destroy(alog);
+     }
+
      /* Load proxy relays. */
      
      proxyrelays = mms_proxy_relays(cfg);
diff -Naur mbuni-0.9.6/mmsc/mmsproxy.c mbuni-0.9.7/mmsc/mmsproxy.c
--- mbuni-0.9.6/mmsc/mmsproxy.c	Fri Feb 11 09:29:31 2005
+++ mbuni-0.9.7/mmsc/mmsproxy.c	Wed Mar  2 15:13:50 2005
@@ -27,12 +27,15 @@
 
 typedef struct MmsHTTPClientInfo {
      HTTPClient *client;
+     Octstr *ua;
      Octstr *ip;
      List *headers;
      Octstr *url;
      Octstr *body;
      List *cgivars;
      MmsUaProfile *prof;
+     Octstr *base_client_addr;
+     Octstr *client_addr;
 } MmsHTTPClientInfo;
 
 static void fetchmms_proxy(MmsHTTPClientInfo *h);
@@ -43,7 +46,7 @@
      int cfidx;
      Octstr *fname;
      CfgGroup *grp;
-     Octstr *log;
+     Octstr *log, *alog;
      long loglevel;
 
      MmsHTTPClientInfo h;
@@ -77,6 +80,12 @@
 	  octstr_destroy(log);
      }
      
+     /* Get access log and open it. */
+     alog = cfg_get(grp, octstr_imm("access-log"));
+     if (alog) {
+	  alog_open(octstr_get_cstr(alog), 1, 1);
+	  octstr_destroy(alog);
+     }
      /* Load proxy relays. */
      
      proxyrelays = mms_proxy_relays(cfg);
@@ -108,7 +117,8 @@
 	  if (is_allowed_ip(settings->deny_ip, settings->allow_ip, h.ip)) {
 	       MmsHTTPClientInfo *hx = gw_malloc(sizeof *hx);
 	       Octstr *profile_url;
-
+	       
+	       h.ua = http_header_value(h.headers, octstr_imm("User-Agent"));
 
 	       /* Get the profile URL and store it. Has effect of fetching if missing. */
 	       if ((profile_url = http_header_value(h.headers, 
@@ -123,6 +133,17 @@
 
 		    h.prof = mms_make_ua_profile(h.headers);
 
+	       /* Get the sender address. */
+
+	       h.base_client_addr = mms_find_sender_msisdn(&h.url, h.headers, settings->wap_gw_msisdn_header);  
+	       
+	       if (!h.base_client_addr) /* Set to IP sender... XXXX assumes ipv4 only for now*/
+		    h.client_addr = octstr_format("%S/TYPE=IPv4", h.ip);
+	       else {
+		    normalize_number(octstr_get_cstr(settings->unified_prefix), &h.base_client_addr);
+		    h.client_addr = octstr_format("%S/TYPE=PLMN", h.base_client_addr);	  
+	       }
+
 	       /* Dump headers, url etc. */
 #if 0
 	       http_header_dump(h.headers);
@@ -143,6 +164,10 @@
 	  } else {	  
 	       octstr_destroy(h.ip);
 	       octstr_destroy(h.url);
+	       if (h.ua) octstr_destroy(h.ua);
+	       if (h.base_client_addr)
+		    octstr_destroy(h.base_client_addr);
+	       octstr_destroy(h.client_addr);
 	       octstr_destroy(h.body);
 	       http_destroy_headers(h.headers);
 	       http_destroy_headers(h.cgivars);
@@ -261,7 +286,8 @@
 
 
 
-     e->lastaccess = time(NULL);
+     e->lastaccess = time(NULL); /* No more notifications requests. */
+     e->sendt = e->expiryt + 3600*24*30*12;
      mms_queue_update(e);
 
 
@@ -277,9 +303,12 @@
 	  mms_msgdump(mr,1);
 #endif
 
-     goto free_stuff;
-
-
+     /* Send to access log with success. */
+     mms_log2("Fetched", e ? e->from : NULL, h->client_addr, 
+	     e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua);
+     
+     goto free_stuff; /* Skip to end. */
+     
  failed:          
 #if 1
      debug("proxy.fetchinterface", 0, 
@@ -290,6 +319,10 @@
 	  mms_msgdump(mr,1);
 #endif
      
+     /* Send to access log on failure?? */
+     mms_log2("Failed Fetch", e ? e->from : NULL, h->client_addr, 
+	     e ? e->msize : 0, e ? e->msgId : NULL, NULL, NULL, "MM1", h->ua);
+
      if (!s) {
 	  http_header_add(rh, "Content-Type", "text/plain");
 	  http_send_reply(h->client, HTTP_NOT_FOUND, rh, octstr_imm("Not found"));
@@ -312,8 +345,14 @@
      if (transid) octstr_destroy(transid);
 
      octstr_destroy(h->ip);
-     octstr_destroy(h->url);     
+     octstr_destroy(h->url);    
+     if (h->ua) octstr_destroy(h->ua); 
      if (h->body) octstr_destroy(h->body);
+
+     if (h->base_client_addr)
+	  octstr_destroy(h->base_client_addr);
+     octstr_destroy(h->client_addr);
+
      http_destroy_cgiargs(h->cgivars);
      http_destroy_headers(h->headers);
 
@@ -401,7 +440,6 @@
 
 static void sendmms_proxy(MmsHTTPClientInfo *h)
 {
-     Octstr *phonenum, *base_phonenum;
      List *rh = http_create_empty_headers();
      MmsMsg *m, *mresp = NULL;
      Octstr *reply_body = NULL;
@@ -409,21 +447,16 @@
      int mtype = 0;
      int hstatus = HTTP_OK;
      char *notify_cmd = NULL;
+     int msize = h->body ? octstr_len(h->body) : 0;
 
-     debug("proxy.sendinterface", 0, " --> Enterred sendmms interface, blen=%ld <--- ", h->body ? octstr_len(h->body) : 0);
+     debug("proxy.sendinterface", 0, 
+	   " --> Enterred sendmms interface, blen=%d <--- ", 
+	   msize);
      
      http_header_add(rh, "Pragma", "no-cache");
      http_header_add(rh, "Cache-Control", "no-cache");
 
 
-     base_phonenum = mms_find_sender_msisdn(h->url, h->headers, settings->wap_gw_msisdn_header);  
-
-     if (!base_phonenum)
-	  phonenum = octstr_format("unknown@%S", settings->hostname);
-     else {
-	  normalize_number(octstr_get_cstr(settings->unified_prefix), &base_phonenum);
-	  phonenum = octstr_format("%S/TYPE=PLMN", base_phonenum);	  
-     }
 
      if (!h->body) { /* A body is required. */
 	  http_header_add(rh, "Content-Type", "text/plain"); 
@@ -434,7 +467,7 @@
 	  goto done;
      }      
 	  
-     m = mms_frombinary(h->body, phonenum);
+     m = mms_frombinary(h->body, h->client_addr);
 
      if (!m) {
 	  http_header_add(rh, "Content-Type", "text/plain"); 
@@ -489,74 +522,97 @@
 			     NULL, NULL, deliveryt, expiryt, m, NULL, dlr,
 			     octstr_get_cstr(settings->global_queuedir));
 	  
-	  if (value) 
-	       octstr_destroy(value);
-	  octstr_destroy(from);
-	  octstr_destroy(subject);
-	  http_destroy_headers(mh);
-	  list_destroy(to, (list_item_destructor_t *)octstr_destroy);
-
 	  if (!qf) 
 	       mresp = mms_sendconf("Error-transient-failure", "None", octstr_get_cstr(otransid),0);
 	  else {
 	       Octstr *transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias);
 	       mresp = mms_sendconf("Ok", octstr_get_cstr(transid), octstr_get_cstr(otransid),0);
-	       octstr_destroy(transid);
-	       
+
+	       /* Log to access log */
+	       mms_log("Received", from, to, msize, transid, NULL, NULL, "MM1", h->ua);
+
+	       octstr_destroy(transid);	       
 	       octstr_destroy(qf);
 	  }
-	  if (otransid) octstr_destroy(otransid);
+	  
+	  if (otransid) 
+	       octstr_destroy(otransid);
+	  if (value) 
+	       octstr_destroy(value);
+	  octstr_destroy(from);
+	  octstr_destroy(subject);
+	  http_destroy_headers(mh);
+	  list_destroy(to, (list_item_destructor_t *)octstr_destroy);
+
 	  notify_cmd = "sent";
 	  reply_body = mms_tobinary(mresp);
      }	  
      break;
      case MMS_MSGTYPE_FORWARD_REQ:
      {
-	  Octstr *qf;
+	  Octstr *qf = NULL, *token = NULL;
 	  List *mh = mms_message_headers(m);
 	  Octstr *from;
 	  List *to = list_create();
 	  Octstr  *subject;
 	  time_t expiryt, deliveryt;
-	  MmsMsg *mfwd;
-	  
+	  MmsMsg *mfwd = NULL;
+	  MmsEnvelope *e = NULL;
+	       
 	  Octstr *otransid;
 	  Octstr *url = http_header_value(mh, octstr_imm("X-Mms-Content-Location"));
 	  Octstr *read_report = http_header_value(mh, octstr_imm("X-Mms-Read-Report"));
-	  Octstr *delivery_report = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"));
-	  Octstr *allow_report = http_header_value(mh, octstr_imm("X-Mms-Report-Allowed"));
-	  
-	  HTTPCaller *caller = http_caller_create();
-	  List *request_hdrs = http_create_empty_headers();
-	  List *reply_headers;
-	  int status;
-	  Octstr *final_url, *rbody;
+	  Octstr *delivery_report = http_header_value(mh, 
+						      octstr_imm("X-Mms-Delivery-Report"));
+	  Octstr *allow_report = http_header_value(mh, 
+						   octstr_imm("X-Mms-Report-Allowed"));
 	  int dlr;
 	  
 	  collect_senddata(mh, &to, &from, &subject, &otransid, &expiryt, &deliveryt);
 	  
-	  http_header_add(request_hdrs, "User-Agent", MM_NAME "/" GW_VERSION);	       
-	  http_start_request(caller,HTTP_METHOD_GET, url, request_hdrs, NULL, 1, NULL, NULL);
-	  
-	  if (http_receive_result(caller, &status, &final_url, &reply_headers, &rbody) == NULL ||
-	      status != HTTP_OK ||
-	      (mfwd = mms_frombinary(rbody, octstr_imm(""))) == NULL) {
-	       mresp = mms_sendconf("Error-permanent-message-not-found", "None", octstr_get_cstr(otransid),1);	    
-	  } else {
+	  if (mms_decodefetchurl(url, &qf, &token) != 0) {
+	       error(0, "MMS Send interface: failed to decode forward url (%s) from %s!", 
+		     octstr_get_cstr(url), 
+		     octstr_get_cstr(h->ip));
+	       mresp = mms_sendconf("Error-permanent-message-not-found", "None", 
+				    octstr_get_cstr(otransid),1);	    
+	       goto forward_done;
+	  }
+
+	  e = mms_queue_readenvelope(octstr_get_cstr(qf), 
+				     octstr_get_cstr(settings->mm1_queuedir), 1);
+
+	  if (!e ||
+	      (mfwd = mms_queue_getdata(e)) == NULL) {
+	       error(0, 
+		     "MMS Send interface: failed to find envelope/data %s for forward url "
+		     "(%s) from %s (e=%s)!", 
+		     octstr_get_cstr(qf), octstr_get_cstr(url), octstr_get_cstr(h->ip),
+		     (e) ? "found" : "not found");  
+
+	       mresp = mms_sendconf("Error-permanent-message-not-found", "None", 
+				    octstr_get_cstr(otransid),1);	    
+	       goto forward_done;
+	  } else { /* Found it, etc. */
+
 	       Octstr *transid;
 	       Octstr *pfrom = mms_get_header_value(mfwd, octstr_imm("From"));		    
 	       Octstr *pdate = mms_get_header_value(mfwd, octstr_imm("Date"));
-	       Octstr *pdelivery_report = mms_get_header_value(mfwd, octstr_imm("X-Mms-Delivery-Report"));
+	       Octstr *pdelivery_report = mms_get_header_value(mfwd, 
+							       octstr_imm("X-Mms-Delivery-Report"));
 	       Octstr *pmsgid = mms_get_header_value(mfwd, octstr_imm("Message-ID"));
 	       Octstr *s;
+	       Octstr *qf2;
 	       int n = 0;
 	       
+
 	       /* Modify the message before sending on as per spec. */
 	       mms_replace_header_value(mfwd, "From", octstr_get_cstr(from));
 	       
 	       mms_remove_headers(mfwd, "X-Mms-Read-Report");
 	       if (read_report)
-		    mms_replace_header_value(mfwd, "X-Mms-Read-Report", octstr_get_cstr(read_report));
+		    mms_replace_header_value(mfwd, "X-Mms-Read-Report", 
+					     octstr_get_cstr(read_report));
 	       
 	       mms_remove_headers(mfwd, "X-Mms-Delivery-Report");
 	       if (delivery_report)
@@ -571,16 +627,17 @@
 	       s = octstr_format("%d %S", n+1, pfrom);			 
 	       mms_replace_header_value(mfwd, "X-Mms-Previously-Sent-By",  octstr_get_cstr(s));
 	       
-	       n = 0;
 	       
-	       if ((s = mms_get_header_value(mfwd, octstr_imm("X-Mms-Previously-Sent-Date"))) != NULL) {
+	       if ((s = mms_get_header_value(mfwd, 
+					     octstr_imm("X-Mms-Previously-Sent-Date"))) 
+		   != NULL) {
 		    sscanf(octstr_get_cstr(s), "%d", &n);
 		    octstr_destroy(s);
 	       }
 	       s = octstr_format("%d %S", n+1, pdate);			 
-	       mms_replace_header_value(mfwd, "X-Mms-Previously-Sent-Date",  octstr_get_cstr(s));
-	       
-	       
+	       mms_replace_header_value(mfwd, 
+					"X-Mms-Previously-Sent-Date",  
+					octstr_get_cstr(s));
 	       octstr_destroy(pdate);
 
 	       if (delivery_report &&
@@ -589,22 +646,26 @@
 	       else 
 		    dlr = 0;
 	       /* Message to forward is now ready, write it to queue. */
-	       qf = mms_queue_add(from, to, NULL, subject, 
+	       qf2 = mms_queue_add(from, to, NULL, subject, 
 				  NULL, NULL, deliveryt, expiryt, mfwd, NULL,
 				  dlr,
 				  octstr_get_cstr(settings->global_queuedir));
 	       
-	       octstr_destroy(from);
-	       octstr_destroy(subject);
-	       http_destroy_headers(mh);
 	       
-	       if (!qf) 
-		    mresp = mms_sendconf("Error-transient-failure", "None", octstr_get_cstr(otransid),1);
+	       if (!qf2) 
+		    mresp = mms_sendconf("Error-transient-failure", 
+					 "None", octstr_get_cstr(otransid),1);
 	       else {
 		    transid = mms_maketransid(octstr_get_cstr(qf), settings->host_alias);
-		    mresp = mms_sendconf("Ok", octstr_get_cstr(transid), octstr_get_cstr(otransid),0);
+		    mresp = mms_sendconf("Ok", 
+					 octstr_get_cstr(transid), 
+					 octstr_get_cstr(otransid),1);
+		    
+		    /* Log to access log */
+		    mms_log("Forwarded", h->client_addr, to, msize, transid, NULL, NULL, "MM1", h->ua);
+		    
 		    octstr_destroy(transid);
-		    octstr_destroy(qf);
+		    octstr_destroy(qf2);
 	       }
 	       
 	       /* You have queued it, now check if the original sender asked for a delivery notify. 
@@ -616,7 +677,7 @@
 		   (pdelivery_report && octstr_case_compare(pdelivery_report, 
 							    octstr_imm("Yes")))) {
 		    
-		    MmsMsg *mrep = mms_deliveryreport(pmsgid, phonenum, time(NULL), octstr_imm("Forwarded"));
+		    MmsMsg *mrep = mms_deliveryreport(pmsgid, h->client_addr, time(NULL), octstr_imm("Forwarded"));
 		    Octstr *x;
 		    List *l = list_create();
 		    list_append(l, pfrom);
@@ -626,7 +687,7 @@
 				      mrep, NULL,0,
 				      octstr_get_cstr(settings->global_queuedir));
 		    octstr_destroy(x);
-
+		    
 		    list_destroy(l, (list_item_destructor_t *)octstr_destroy);
 		    mms_destroy(mrep);
 	       }
@@ -634,22 +695,46 @@
 	       octstr_destroy(pdelivery_report);
 	       octstr_destroy(pmsgid);
 	       
-	       mms_destroy(mfwd);
 	  }  
 	  
-	  http_caller_destroy(caller);
-	  octstr_destroy(final_url);
-	  octstr_destroy(url);
-	  octstr_destroy(rbody);
-	  octstr_destroy(read_report);
-	  octstr_destroy(allow_report);
-	  octstr_destroy(delivery_report);
-	  http_destroy_headers(reply_headers);
-	  http_destroy_headers(request_hdrs);
+     forward_done:
 	  
-	  reply_body = mms_tobinary(mresp);
-	  notify_cmd = "fetched";
+	  if (mfwd) 
+	       mms_destroy(mfwd);
+	  
+	  if (e) { /* Update the message queue and go. */
+	       e->lastaccess = time(NULL);
+	       if (mms_queue_update(e) != 1) /* Should be freed. */	       
+		    mms_queue_free_env(e);
+	       e = NULL;
+	  } 
+	  
+	  if (qf)
+	       octstr_destroy(qf);
+	  if (token)
+	       octstr_destroy(token);
+	  if (from) 
+	       octstr_destroy(from);
+	  if (subject) 
+		octstr_destroy(subject);
+	  if (mh) 
+	       http_destroy_headers(mh);
+	  if (to)
+	       list_destroy(to, (list_item_destructor_t *)octstr_destroy);
+	  if (otransid) 
+	       octstr_destroy(otransid);
+	  if (url) 
+	       octstr_destroy(url);
+	  
+	  if (read_report) 
+	       octstr_destroy(read_report);
+	  if (allow_report) 
+	       octstr_destroy(allow_report);
+	  if (delivery_report)
+	       octstr_destroy(delivery_report);
 	  
+	  reply_body = mms_tobinary(mresp);
+	  notify_cmd = "fetched";	  
      }
      break;
      case MMS_MSGTYPE_NOTIFYRESP:
@@ -692,7 +777,7 @@
 	       Octstr *x;
 	       List *l = list_create();
 
-	       mrpt = mms_deliveryreport(e->msgId, phonenum, time(NULL), status);
+	       mrpt = mms_deliveryreport(e->msgId, h->client_addr, time(NULL), status);
 	       list_append(l, octstr_duplicate(e->from));
 	       
 	       x = mms_queue_add(settings->system_user, l, NULL, NULL, NULL, NULL, 0, 
@@ -703,10 +788,16 @@
 	       list_destroy(l, (list_item_destructor_t *)octstr_destroy);
 	       mms_destroy(mrpt);
 	  }	       
-	  if (mms_queue_update(e) != 1) /* Should be freed. */	       
-	       mms_queue_free_env(e);
 	  
      mdone:
+
+	  /* Log to access log */
+	  mms_log2("NotifyResp", h->client_addr, NULL, msize, transid, NULL, NULL, "MM1", h->ua);
+
+	  if (e && 
+	      mms_queue_update(e) != 1) /* Should be freed. */	       
+	       mms_queue_free_env(e);
+
 	  octstr_destroy(qf);
 	  octstr_destroy(transid);
 	  octstr_destroy(allow_report);
@@ -735,6 +826,9 @@
 			    NULL, time(NULL),  time(NULL) + settings->default_msgexpiry, 
 			    m, NULL, 0, octstr_get_cstr(settings->global_queuedir));
 	  
+	  /* Log to access log */
+	  mms_log("ReadReport", h->client_addr, NULL, msize, NULL, NULL, NULL, "MM1", h->ua);
+	  
 	  octstr_destroy(x);
 	  octstr_destroy(from);
 	  http_destroy_headers(mh);
@@ -759,14 +853,11 @@
 
      if (notify_cmd) /* Inform provisioning server */	  
 	  notify_prov_server(octstr_get_cstr(settings->prov_notify), 
-			     base_phonenum ? octstr_get_cstr(base_phonenum) : "unknown", 
+			     h->base_client_addr ? octstr_get_cstr(h->base_client_addr) : "unknown", 
 			     notify_cmd, 
 			     octstr_get_cstr(settings->prov_notify_arg));
 
      mms_destroy(m);
-     octstr_destroy(phonenum);     
-     if (base_phonenum)
-	  octstr_destroy(base_phonenum);
      /* Send reply. */
 
  done:
@@ -782,6 +873,12 @@
 
      octstr_destroy(h->ip);
      octstr_destroy(h->url);     
+
+     if (h->base_client_addr)
+	  octstr_destroy(h->base_client_addr);
+     octstr_destroy(h->client_addr);
+
+     if (h->ua) octstr_destroy(h->ua);
      if (h->body) octstr_destroy(h->body);
      http_destroy_cgiargs(h->cgivars);
      http_destroy_headers(h->headers);
diff -Naur mbuni-0.9.6/mmsc/mmssend.c mbuni-0.9.7/mmsc/mmssend.c
--- mbuni-0.9.6/mmsc/mmssend.c	Fri Feb  4 12:07:06 2005
+++ mbuni-0.9.7/mmsc/mmssend.c	Wed Mar  2 15:43:06 2005
@@ -51,8 +51,9 @@
      
      int cfidx;
      CfgGroup *grp;
-     Octstr *log;
+     Octstr *log, *alog;
      long loglevel;
+     int msize;
      
      if (argc < 2)
 	  return -1;
@@ -87,6 +88,13 @@
 	  octstr_destroy(log);
      }
      
+     /* Get access log and open it. */
+     alog = cfg_get(grp, octstr_imm("access-log"));
+     if (alog) {
+	  alog_open(octstr_get_cstr(alog), 1, 1);
+	  octstr_destroy(alog);
+     }
+
      /* Load proxy relays. */
      
      proxyrelays = mms_proxy_relays(cfg);
@@ -97,20 +105,31 @@
      if (!settings) 
 	  panic(0, "No global MMSC configuration!");
 
+     if (from == NULL ||
+	 to == NULL) {
+	  error(0, "Sender and recipient addresses required!\n");
+	  exit(-1);
+     }
+
      mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
 
      if (data) {
 	  m = mms_frombinary(data, from ? from : octstr_imm("anon@anon"));
 	  if (m) 
-	       mms_msgdump(m,0);       
-
-     }
+		  mms_msgdump(m,0);       
+	  msize = octstr_len(data);
+     } else
+	     msize = 0;
      if (!m)
-	  panic(0, "No Message supplied, or failed to decode binary data!");
+	     panic(0, "No Message supplied, or failed to decode binary data!");
      
      s = mms_queue_add(from, to, NULL, NULL, NULL, NULL, time(NULL), 
 		       time(NULL) + settings->default_msgexpiry, m,
 		       NULL, 0, octstr_get_cstr(settings->global_queuedir));
+     
+     mms_log("Received", from, to, msize, s, NULL, NULL, "mmssend",NULL);
+     
      printf("Queued: %s\n", octstr_get_cstr(s));
+     octstr_destroy(s);
   return 0;
 }
