Index: .hgsubstate
===================================================================
--- .hgsubstate	(revision 160)
+++ .hgsubstate	(revision 143)
@@ -1,3 +1,3 @@
 a1bd05cf1becfa567d269e68ab312ed4154d4ab2 libs/hlibpp
 3c961ba9aba9bb9031527dc9037e0132354698e8 libs/miniini
-d35893d75a45b272c73f77c7e8c61593be174c95 mediastreamer2
+b89c5dbaaf0e885c1ab465977757d60a5ad188b4 mediastreamer2
Index: phapi/phapi.c
===================================================================
--- phapi/phapi.c	(revision 158)
+++ phapi/phapi.c	(revision 161)
@@ -294,4 +294,14 @@
 #define ph_custom_lock() osip_mutex_lock(ph_custom_mutex)
 #define ph_custom_unlock() osip_mutex_unlock(ph_custom_mutex)
+static void ph_apply_header_monitor(osip_message_t* msg,  struct ph_hdr_list *hlist);
+
+
+ph_mutex_t *ph_hdrmon_mutex;
+int ph_hdrmon_idx;
+osip_list_t ph_hdrmon_list;
+
+#define ph_hdrmon_lock() osip_mutex_lock(ph_hdrmon_mutex)
+#define ph_hdrmon_unlock() osip_mutex_unlock(ph_hdrmon_mutex)
+
 
 
@@ -2695,101 +2705,4 @@
 }
 
-PHAPI_EXPORT int
-phResumeCall(int cid)
-{
-	phcall_t *ca;
-	int i;
-	osip_message_t *reinvite;
-
-	if (!phIsInitialized)
-		return -PH_NOTINIT;
-
-	ca = ph_locate_call_by_cid(cid);
-
-	if (!ca)
-		return -PH_BADCID;
-
-	if (!ca->localhold)
-		return -PH_HOLDERR;
-
-#ifndef CONF_MODE
-	if (ph_has_active_calls())
-		return -PH_NORESOURCES;
-#endif
-
-	ca->localhold = 0;
-	ca->localresume = 1;
-
-	eXosip_lock();
-	if (eXosip_call_build_request(ca->did, "INVITE", &reinvite)) {
-		eXosip_unlock();
-		return -1;
-	}
-	eXosip_unlock();
-
-	osip_message_set_subject(reinvite, "Call resuming");
-	osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
-
-	if (ca->sdpctx && ca->sdpctx->offerstr)
-		ph_req_set_body(reinvite, ca->sdpctx->offerstr, "application/sdp");
-
-	eXosip_lock();
-	i = eXosip_call_send_request(ca->did, reinvite);
-	eXosip_unlock();
-
-	return i;
-}
-
-PHAPI_EXPORT int
-phHoldCall(int cid)
-{
-	phcall_t *ca;
-	osip_message_t *reinvite;
-	int i;
-
-	DBG_SIP_NEGO("SIP_NEGO: phHoldCall\n");
-
-	if (!phIsInitialized)
-		return -PH_NOTINIT;
-
-	ca = ph_locate_call_by_cid(cid);
-
-	if (!ca)
-		return -PH_BADCID;
-
-	if (ca->localhold)
-		return -PH_HOLDERR;
-
-	ca->localhold = 1;
-
-	eXosip_lock();
-	if (eXosip_call_build_request(ca->did, "INVITE", &reinvite)) {
-		eXosip_unlock();
-		return -1;
-	}
-	eXosip_unlock();
-
-	osip_message_set_subject(reinvite, "Call on hold");
-	osip_message_set_allow(reinvite, "INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO");
-	if (ca->sdpctx && ca->sdpctx->offerstr)
-		ph_req_set_body(reinvite, ca->sdpctx->offerstr, "application/sdp");
-
-	eXosip_lock();
-	i = eXosip_call_send_request(ca->did, reinvite);
-	eXosip_unlock();
-
-	osip_mutex_lock(ph_media_stop_mutex);
-	if (!i && ph_call_hasaudio(ca))
-	{
-#ifndef MEDIA_SUSPEND
-		ph_call_media_stop(ca);
-#else
-		ph_call_media_suspend(ca, 1);
-#endif
-	}
-	osip_mutex_unlock(ph_media_stop_mutex);
-	return i;
-}
-
 
 PHAPI_EXPORT int
@@ -4220,4 +4133,9 @@
 	osip_list_init(&ph_custom_headers);
 
+	ph_hdrmon_mutex = osip_mutex_init();
+	osip_list_init(&ph_hdrmon_list);
+
+
+
 	if (asyncmode)
 		phapithread = osip_thread_create(20000, ph_api_thread, (void*)0);
@@ -4986,7 +4904,8 @@
 		info.remoteSdp = sdp = ph_req_get_body(je->response);
 
+		ph_apply_header_monitor(je->response, &info.hlist);
 
 		phcb->callProgress(ca->cid, &info);
-		done:
+done:
 		if (remoteUri)
 			osip_free(remoteUri);
@@ -4997,4 +4916,8 @@
 		if (sdp)
 			osip_free(sdp);
+
+		if (info.hlist.elems)
+			osip_free(info.hlist.elems);
+
 	}
 }
@@ -5069,5 +4992,4 @@
 	int rdid;
 	char *from = 0, *to = 0, *sdp = 0;
-	osip_message_t *ack;
 
 	DBG_SIP_NEGO("SIP NEGO: ph_call_answered\n");
@@ -5086,10 +5008,8 @@
 	{
 		const int mflags =  -1 & ~(PH_STREAM_MCSEND|PH_STREAM_MCRECV);
+		osip_message_t *ack;
 
 		if (sdp)
-		{	
-			if (ca->remote_sdp) {
-				sdp_message_free(ca->remote_sdp);	
-			}
+		{
 			sdp_message_init(&ca->remote_sdp);
 			sdp_message_parse(ca->remote_sdp, sdp);
@@ -5098,4 +5018,5 @@
 			ph_call_retrieve_payloads(ca, -1);
 
+
 			if (!ph_call_media_start(ca, je, mflags, ca->localresume))
 			{
@@ -5103,4 +5024,7 @@
 			}
 		}
+
+		eXosip_call_build_ack(ca->did, &ack);
+		eXosip_call_send_ack(ca->did, ack);
 	}
 
@@ -5119,9 +5043,4 @@
 		info.event = phCALLOK;
 	}
-
-	eXosip_lock();
-	eXosip_call_build_ack(ca->did, &ack);
-	eXosip_call_send_ack(ca->did, ack);
-	eXosip_unlock();
 
 	info.remoteUri = to = ph_req_get_to(je->response);
@@ -5145,4 +5064,5 @@
 		 * the local var
 		 */
+		ph_apply_header_monitor(je->response, &info.hlist);
 		phcb->callProgress(ca->cid, &info);
 	}
@@ -5161,4 +5081,7 @@
 	if (from)
 		osip_free(from);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 
 }
@@ -5195,4 +5118,5 @@
 		info.streams = ca->nego_mflags;
 
+		ph_apply_header_monitor(je->response, &info.hlist);
 		phcb->callProgress(ca->cid, &info);
 	}
@@ -5205,4 +5129,8 @@
 	if (to)
 		free(to);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
+
 
 }
@@ -5235,4 +5163,6 @@
 	if (from)
 		osip_free(from);
+
+
 }
 
@@ -5354,4 +5284,5 @@
 	info.streams = ca->nego_mflags;
 
+	ph_apply_header_monitor(je->response, &info.hlist);
 
 	phcb->callProgress(je->cid, &info);
@@ -5366,4 +5297,7 @@
 	if (from)
 		osip_free(from);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5412,4 +5346,5 @@
 	}
 
+	ph_apply_header_monitor(je->response, &info.hlist);
 
 	phcb->callProgress(je->cid, &info);
@@ -5423,4 +5358,7 @@
 	if (from)
 		osip_free(from);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5453,4 +5391,6 @@
 	info.errorCode = s;
 
+	ph_apply_header_monitor(je->response, &info.hlist);
+
 	phcb->callProgress(je->cid, &info);
 
@@ -5464,4 +5404,7 @@
 	if (from)
 		osip_free(from);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5499,4 +5442,6 @@
 	}
 
+	ph_apply_header_monitor(je->request, &info.hlist);
+
 	phcb->callProgress(je->cid, &info);
 
@@ -5510,4 +5455,7 @@
 	if (from)
 		osip_free(from);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5538,4 +5486,6 @@
 	//	info.localUri = from = ph_req_get_to(je->response);
 
+	ph_apply_header_monitor(je->request, &info.hlist);
+
 	phcb->callProgress(je->cid, &info);
 
@@ -5549,4 +5499,7 @@
 	if (from)
 		osip_free(from);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5576,4 +5529,6 @@
 		info.event = phCALLCLOSED;
 		info.errorCode = 0;
+
+		ph_apply_header_monitor(je->request, &info.hlist);
 		phcb->callProgress(je->cid, &info);
 	}
@@ -5583,4 +5538,7 @@
 		ph_refer_notify(rca->rdid, ph_req_get_status(je->response), "Closed", 1);
 	}
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5680,4 +5638,6 @@
 			DBG_SIP_NEGO("Retrying reg=%d for vlid=%d i=%d t=%d\n", je->rid, vlid, i, newtimeout);
 		}
+
+
 		phcb->regProgress(vlid, mask | (status ? status : 500) );
 
@@ -5741,4 +5701,6 @@
 		info.event = phMsgNew;
 		info.content = body = ph_req_get_body(je->request);
+		ph_apply_header_monitor(je->request, &info.hlist);
+
 		if (ctt)
 		{
@@ -5759,4 +5721,6 @@
 		info.to = to = ph_req_get_to(je->response);
 		info.from = from = ph_req_get_from(je->response);
+		ph_apply_header_monitor(je->response, &info.hlist);
+
 		if (phcb->msgProgress != NULL)
 			phcb->msgProgress(je->tid, &info);
@@ -5769,8 +5733,11 @@
 		if (je->response)
 		{
+			ph_apply_header_monitor(je->response, &info.hlist);
+
 			info.to = to = ph_req_get_to(je->response);
 			info.from = from = ph_req_get_from(je->response);
 		} else if (je->request)
 		{
+			ph_apply_header_monitor(je->request, &info.hlist);
 			info.to = to = ph_req_get_to(je->request);
 			info.from = from = ph_req_get_from(je->request);
@@ -5792,4 +5759,7 @@
 	if (body)
 		osip_free(body);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems);
 }
 
@@ -5861,4 +5831,6 @@
 		osip_uri_to_str(je->response->req_uri, &info.to);
 
+		ph_apply_header_monitor(je->response, &info.hlist);
+
 		if (phcb->subscriptionProgress != NULL)
 			phcb->subscriptionProgress (je->sid, &info);
@@ -5874,4 +5846,7 @@
 		else
 		{
+
+			ph_apply_header_monitor(je->response, &info.hlist);
+
 			if (je->response->status_code == 404) {
 				info.event = phSubscriptionErrNotFound;
@@ -5884,4 +5859,13 @@
 		}
 	}
+
+	if (info.from)
+		osip_free(info.from);
+
+	if (info.to)
+		osip_free(info.to);
+
+	if (info.hlist.elems)
+		osip_free(info.hlist.elems)
 }
 
@@ -6397,16 +6381,6 @@
     if (!osip_strcasecmp(h, "Expires"))
       osip_message_replace_header(req, "Expires", v);
-    else if (!osip_strcasecmp(h, "Allow"))
-        osip_message_set_allow(req, v);
-    else if (!osip_strcasecmp(h, "Accept"))
-        osip_message_set_accept(req, v);
-    else if (!osip_strcasecmp(h, "Content-Type"))
-        osip_message_set_content_type(req, v);
-    else if (!osip_strcasecmp(h, "Content-Encoding"))
-        osip_message_set_content_encoding(req, v);
-    else if (!osip_strcasecmp(h, "Accept-Language"))
-        osip_message_set_accept_language(req, v);
     else
-        osip_message_set_header(req, h, v);
+    	osip_message_set_multiple_header(req, h, v);
 
 }
@@ -6482,2 +6456,104 @@
 
 
+int
+phMonitorHeader(const char *reqnames, const char *hdrname)
+{
+    struct ph_custom_hdr *hdr;
+    int idx;
+
+    hdr = (struct ph_custom_hdr*) osip_malloc(sizeof(struct ph_custom_hdr));
+
+    if (!hdr)
+        return -1;
+
+    memset(hdr, 0, sizeof(*hdr));
+
+    hdr->matchrequests = osip_strdup(reqnames);
+    hdr->hdrname = osip_strdup(hdrname);
+    hdr->enabled = 1;
+
+    ph_hdrmon_lock();
+    idx = hdr->idx = ++ph_hdrmon_idx;
+    osip_list_add(&ph_hdrmon_list, hdr, -1);
+    ph_hdrmon_unlock();
+
+    return idx;
+
+}
+
+int phEnableMonitor(int idx, int enable)
+{
+    struct ph_custom_hdr *hdr;
+    int i = 0;
+
+
+
+	ph_hdrmon_lock();
+    do
+    {
+        hdr = (struct ph_custom_hdr *) osip_list_get(&ph_hdrmon_list, i++);
+    } while(hdr);
+
+    if (hdr)
+    	hdr->enabled = enable;
+
+    ph_hdrmon_unlock();
+    return hdr == 0;
+}
+
+
+void phResetMonitoring()
+{
+		ph_hdrmon_lock();
+        osip_list_special_free(&ph_hdrmon_list, custom_hdr_free);
+        ph_hdrmon_idx = 0;
+        ph_hdrmon_unlock();
+}
+
+static
+void ph_apply_header_monitor(osip_message_t* msg,  struct ph_hdr_list *hlist)
+{
+	const char* reqname;
+	int i;
+	const int NHDRS = 64;
+	struct ph_hdr_val tmpval[NHDRS];
+	struct ph_hdr_list tmphlist = { 0, tmpval };
+
+	if (MSG_IS_REQUEST(msg))
+		reqname = msg->sip_method;
+	else
+		reqname = msg->cseq->method;
+
+
+	for(i = 0;  ; i++) {
+		struct ph_custom_hdr *chdr = (struct ph_custom_hdr *) osip_list_get(&ph_hdrmon_list, i);
+		if (!chdr)
+			break;
+
+		if (!strcmp(chdr->matchrequests, "*") || (0 !=  strstr(reqname, chdr->matchrequests))) {
+			int h = 0;
+			osip_header_t*  hv;
+
+			while ((h = osip_message_header_get_byname(msg, chdr->hdrname, h, &hv))) {
+				struct ph_hdr_val *phhv = &tmphlist.elems[tmphlist.count++];
+				phhv->hdr = hv->hname;
+				phhv->val = hv->hvalue;
+			}
+		}
+	}
+
+	if (tmphlist.count) {
+		if (!hlist->elems) {
+			hlist->elems = osip_malloc(sizeof(struct ph_hdr_val)*tmphlist.count);
+			if (!hlist->elems) {
+				return;
+			}
+		}
+		memcpy(&hlist->elems[hlist->count], tmphlist.elems, tmphlist.count*sizeof(struct ph_hdr_val));
+		hlist->count += tmphlist.count;
+	}
+
+}
+
+
+
Index: phapi/phapi.h
===================================================================
--- phapi/phapi.h	(revision 158)
+++ phapi/phapi.h	(revision 161)
@@ -379,21 +379,4 @@
 PHAPI_EXPORT int phTransferCall(int cid, int targetCid);
 
-/**
- * Resume previously held call
- *
- * @param cid          call id of call.
- * @return             0 in case of success
- */
-PHAPI_EXPORT int phResumeCall(int cid);
-
-/**
- * Put a call on hold
- *
- * @param cid          call id of call.
- * @return             0 in case of success
- */
-PHAPI_EXPORT int phHoldCall(int cid);
-
-
 PHAPI_EXPORT int phCallStartMedia(int cid, int streamFlags);
 PHAPI_EXPORT int phCallGetMediaInfo(int cid, struct ph_confirmed_media_info *mi);
@@ -606,5 +589,5 @@
 /**
   * Add customization rule for given header, for given request types
-  * the customization can be later disabled and re-anabled by using phEnableCustomization...
+  * the customization can be later disabled and re-enabled by using phEnableCustomization...
   *
   * @param reqnames  comma separated list of SIP REQUEST NAMES in capital letters  to which this rule apply ("*" means all requests)
@@ -618,5 +601,5 @@
  * Enable or Disable a given customization
  *
- * @param custID   the customization id (value returnde by phAddCustomHeader)
+ * @param custID   the customization id (value returned by phAddCustomHeader)
  * @param enable   if zero the customization is disabled else enable
  * @return 0 in case of success, -1 if custID specifies non-existent
@@ -625,5 +608,27 @@
 
 
-
+/**
+  * Add monitoring rule for given header, for given request/response types
+  * the rule can be later disabled and re-enabled by using phEnableCustomization...
+  *
+  * @param reqnames  comma separated list of SIP REQUEST NAMES in capital letters  to which this rule apply ("*" means all requests)
+  * @param hdrname   the header name to add
+  * @param hdrval 	header value to add
+  * @return	-1 in case of failure (no memory) or positive index to use in phEnableMonitor...
+  */
+
+PHAPI_EXPORT int phMonitorHeader(const char *reqnames, const char *hdrname);
+
+/*
+ * Enable or Disable a given montor rule
+ *
+ * @param ruleID   the rule id (value returned by phMonitorHeader)
+ * @param enable   if zero the rule is disabled else enable
+ * @return 0 in case of success, -1 if custID specifies non-existent
+ */
+
+PHAPI_EXPORT int phEnableMonitor(int ruleID, int enable);
+
+PHAPI_EXPORT void phResetMonitoring();
 
 /********************CONFERENCING*********************/
@@ -802,4 +807,17 @@
 
 /********************STRUCTS*********************/
+
+struct ph_hdr_val {
+	const char *hdr;
+	const char *val;
+};
+typedef struct ph_hdr_val ph_hdr_val_t;
+
+struct ph_hdr_list {
+	int count;
+	struct ph_hdr_val *elems;
+};
+
+typedef struct ph_hdr_list ph_hdr_list_t;
 
 /**
@@ -832,4 +850,5 @@
   int   dtmfDigit;           /*!< valid for DTMF */
   const char *remoteSdp;
+  struct ph_hdr_list hlist;
 };
 typedef struct phCallStateInfo phCallStateInfo_t;
@@ -855,4 +874,5 @@
   const char *rawctt;
   int   cid;     /*!<  when non-zero this is message inside a dialog corresponding to call 'cid' */
+  struct ph_hdr_list hlist;
 };
 typedef struct phMsgStateInfo  phMsgStateInfo_t;
@@ -873,4 +893,5 @@
 	char *from;
 	char *to;
+	struct ph_hdr_list hlist;
 };
 typedef struct phSubscriptionStateInfo  phSubscriptionStateInfo_t;
Index: phapi/phms.c
===================================================================
--- phapi/phms.c	(revision 159)
+++ phapi/phms.c	(revision 150)
@@ -490,9 +490,5 @@
 	else
 	{
-		RtpProfile * profile = rtp_profile_clone(&av_profile); //should replace it by video1->profile
-		if (audio1->profile)
-			rtp_profile_destroy(audio1->profile);
-		
-		audio1->profile = make_profile(&av_profile, audio1);
+		RtpProfile *profile = rtp_profile_clone_full(&av_profile);
 
 #ifdef PHAPI_VIDEO_SUPPORT
@@ -522,5 +518,5 @@
 		if(stop_on_hold)
 		{
-			audio = phms_audio_stream_start(audio1->profile, audio1->localport,audio1->remoteaddr,audio1->remoteport,audio1->remotertcpport,
+			audio = phms_audio_stream_start(profile, audio1->localport,audio1->remoteaddr,audio1->remoteport,audio1->remotertcpport,
 					audio1->ipayloads[0].number, audio1->jitter, (audio1->flags)&PH_MSTREAM_FLAG_AEC,s,device,use_tr_sock);
 		}
Index: phapi/sdphandler.c
===================================================================
--- phapi/sdphandler.c	(revision 159)
+++ phapi/sdphandler.c	(revision 150)
@@ -138,13 +138,8 @@
 sdp_equal_payload(const sdp_payload_t *cur_payload, const sdp_payload_t *payload)
 {
-	int rate1=0, rate2=0, channels1=0, channels2=0, mime_len1=0, mime_len2=0;
-
-	if (cur_payload->a_rtpmap && payload->a_rtpmap) {
-		sdp_parse_rtpmap(cur_payload->a_rtpmap, &rate1, &channels1, &mime_len1);
-		sdp_parse_rtpmap(payload->a_rtpmap, &rate2, &channels2, &mime_len2);
-	} else {
-		return cur_payload->pt == payload->pt;
-	}
-
+	int rate1, rate2, channels1, channels2, mime_len1, mime_len2;
+
+	sdp_parse_rtpmap(cur_payload->a_rtpmap, &rate1, &channels1, &mime_len1);
+	sdp_parse_rtpmap(payload->a_rtpmap, &rate2, &channels2, &mime_len2);
 
 	if (mime_len1 != mime_len2)
Index: phcpp/phapipp.cpp
===================================================================
--- phcpp/phapipp.cpp	(revision 158)
+++ phcpp/phapipp.cpp	(revision 147)
@@ -123,14 +123,4 @@
 	return phCloseCall(cid);
 
-}
-
-int phapi::holdCall(int cid)
-{
-	return phHoldCall(cid);
-}
-
-int phapi::resumeCall(int cid)
-{
-	return phResumeCall(cid);
 }
 
Index: phcpp/phapipp.h
===================================================================
--- phcpp/phapipp.h	(revision 158)
+++ phcpp/phapipp.h	(revision 152)
@@ -84,7 +84,4 @@
 	virtual int ringingCall(int cid);
 	virtual int closeCall(int cid);
-	virtual int holdCall(int cid);
-	virtual int resumeCall(int cid);
-
 	virtual int messageInCall(int cid, const char *buff, const char *mime);
 	virtual int getSipCallID(int cid, char *idbuf,  int bufsize);
Index: phtest/phtests.h
===================================================================
--- phtest/phtests.h	(revision 158)
+++ phtest/phtests.h	(revision 131)
@@ -113,6 +113,4 @@
 int testSendDtmf(testConf *conf);
 int testSoftRecvVolumeGain(testConf *conf);
-int testHoldCall(testConf *conf);
-int testResumeCall(testConf *conf);
 
 static struct
@@ -134,6 +132,4 @@
 		{"sendDtmf",testSendDtmf},
 		{"softRecvVolumeGain",testSoftRecvVolumeGain},
-		{"holdCall",testHoldCall},
-		{"resumeCall",testResumeCall},
 		{0,0}
 };
Index: phtest/phtests_funcs.cpp
===================================================================
--- phtest/phtests_funcs.cpp	(revision 158)
+++ phtest/phtests_funcs.cpp	(revision 131)
@@ -213,22 +213,2 @@
 	return res >= 0;
 }
-
-int testHoldCall(testConf *conf)
-{
-	int res;
-
-	INFO_LOG("begin with cid %i", conf->cid);
-	res = testsphapi.holdCall(conf->cid);
-	INFO_LOG("end with res %i", res);
-	return res >= 0;
-}
-
-int testResumeCall(testConf *conf)
-{
-	int res;
-
-	INFO_LOG("begin with cid %i", conf->cid);
-	res = testsphapi.resumeCall(conf->cid);
-	INFO_LOG("end with res %i", res);
-	return res >= 0;
-}
