diff --git a/channel.c b/channel.c
index 9296ed10d1fc0c05ec72db208dd1482059e2cb39..3ffeebaeffe3685e53d501d18c78bb9270282a52 100755
--- a/channel.c
+++ b/channel.c
@@ -273,6 +273,31 @@ void ast_channel_setwhentohangup(struct ast_channel *chan, time_t offset)
 	return;
 }
 
+/*--- ast_channel_cmpwhentohangup: Compare a offset with when to hangup channel */
+int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset)
+{
+	time_t whentohangup;
+
+	if (chan->whentohangup == 0) {
+		if (offset == 0)
+			return (0);
+		else
+			return (-1);
+	} else { 
+		if (offset == 0)
+			return (1);
+		else {
+			whentohangup = offset + time (NULL);
+			if (chan->whentohangup < whentohangup)
+				return (1);
+			else if (chan->whentohangup == whentohangup)
+				return (0);
+			else
+				return (-1);
+		}
+	}
+}
+
 /*--- ast_channel_register: Register a new telephony channel in Asterisk */
 int ast_channel_register(const struct ast_channel_tech *tech)
 {
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 5505a846f8924427434af577ee4a3354e1e80f0d..2b449c5bfd2d6583f6ecf2c78e1476a64d33ea2a 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -637,6 +637,7 @@ static struct sip_pvt {
 #ifdef OSP_SUPPORT
 	int osphandle;				/* OSP Handle for call */
 	time_t ospstart;			/* OSP Start time */
+	unsigned int osptimelimit;		/* OSP call duration limit */
 #endif
 	struct sip_request initreq;		/* Initial request */
 	
@@ -2666,6 +2667,10 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
 	struct ast_channel *tmp;
 	struct ast_variable *v = NULL;
 	int fmt;
+#ifdef OSP_SUPPORT
+	char iabuf[INET_ADDRSTRLEN];
+	char peer[MAXHOSTNAMELEN];
+#endif	
 	
 	ast_mutex_unlock(&i->lock);
 	/* Don't hold a sip pvt lock while we allocate a channel */
@@ -2757,6 +2762,10 @@ static struct ast_channel *sip_new(struct sip_pvt *i, int state, char *title)
 	if (!ast_strlen_zero(i->callid)) {
 		pbx_builtin_setvar_helper(tmp, "SIPCALLID", i->callid);
 	}
+#ifdef OSP_SUPPORT
+	snprintf(peer, sizeof(peer), "[%s]:%d", ast_inet_ntoa(iabuf, sizeof(iabuf), i->sa.sin_addr), ntohs(i->sa.sin_port));
+	pbx_builtin_setvar_helper(tmp, "OSPPEER", peer);
+#endif
 	ast_setstate(tmp, state);
 	if (state != AST_STATE_DOWN) {
 		if (ast_pbx_start(tmp)) {
@@ -2975,6 +2984,7 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg
 		p->timer_t1 = 500;	/* Default SIP retransmission timer T1 (RFC 3261) */
 #ifdef OSP_SUPPORT
 	p->osphandle = -1;
+	p->osptimelimit = 0;
 #endif	
 	if (sin) {
 		memcpy(&p->sa, sin, sizeof(p->sa));
@@ -5957,6 +5967,22 @@ static void build_route(struct sip_pvt *p, struct sip_request *req, int backward
 		list_route(p->route);
 }
 
+#ifdef OSP_SUPPORT
+/*--- check_osptoken: Validate OSP token for user authrroization ---*/
+static int check_osptoken (struct sip_pvt *p, char *token)
+{
+	char tmp[80];
+
+	if (ast_osp_validate (NULL, token, &p->osphandle, &p->osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
+		return (-1);
+	} else {
+		snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
+		pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
+		return (0);
+	}
+}
+#endif
+
 /*--- check_auth: Check user authorization from peer definition ---*/
 /*      Some actions, like REGISTER and INVITEs from peers require
         authentication (if peer have secret set) */
@@ -5968,9 +5994,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
 	char *respheader = "Proxy-Authenticate";
 	char *authtoken;
 #ifdef OSP_SUPPORT
-	char tmp[80];
 	char *osptoken;
-	unsigned int osptimelimit;
 #endif
 	/* Always OK if no secret */
 	if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)
@@ -6002,14 +6026,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
 					}
 				}
 				else {
-					if (ast_osp_validate (NULL, osptoken, &p->osphandle, &osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
-						return (-1);
-					} 
-					else {
-						snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
-						pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
-						return (0);
-					}
+					return (check_osptoken (p, osptoken));
 				}
 				break;
 			case SIP_OSPAUTH_PROXY:
@@ -6017,14 +6034,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
 					return (0);
 				} 
 				else {
-					if (ast_osp_validate (NULL, osptoken, &p->osphandle, &osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
-						return (-1);
-					} 
-					else {
-						snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
-						pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
-						return (0);
-					}
+					return (check_osptoken (p, osptoken));
 				}
 				break;
 			case SIP_OSPAUTH_EXCLUSIVE:
@@ -6032,14 +6042,7 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata
 					return (-1);
 				}
 				else {
-					if (ast_osp_validate (NULL, osptoken, &p->osphandle, &osptimelimit, p->cid_num, p->sa.sin_addr, p->exten) < 1) {
-						return (-1);
-					} 
-					else {
-						snprintf (tmp, sizeof (tmp), "%d", p->osphandle);
-						pbx_builtin_setvar_helper (p->owner, "_OSPHANDLE", tmp);
-						return (0);
-					}
+					return (check_osptoken (p, osptoken));
 				}
 				break;
 			default:
@@ -10243,6 +10246,9 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, int
 	if (!ignore && p)
 		p->lastinvite = seqno;
 	if (c) {
+#ifdef OSP_SUPPORT
+		ast_channel_setwhentohangup (c, p->osptimelimit);
+#endif
 		switch(c->_state) {
 		case AST_STATE_DOWN:
 			transmit_response(p, "100 Trying", req);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 67b32b1b823c655b1997f0d513a1b62b99d952b4..0d7cb6b05fc7d48f409b6e878f1767fe52b9646b 100755
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -562,6 +562,18 @@ int ast_softhangup_nolock(struct ast_channel *chan, int cause);
  */
 int ast_check_hangup(struct ast_channel *chan);
 
+/*! Compare a offset with the settings of when to hang a channel up */
+/*! 
+ * \param chan channel on which to check for hang up
+ * \param offset offset in seconds from current time
+ * \return 1, 0, or -1
+ * This function compares a offset from current time with the absolute time 
+ * out on a channel (when to hang up). If the absolute time out on a channel
+ * is earlier than current time plus the offset, it returns 1, if the two
+ * time values are equal, it return 0, otherwise, it retturn -1.
+ */
+int ast_channel_cmpwhentohangup(struct ast_channel *chan, time_t offset);
+
 /*! Set when to hang a channel up */
 /*! 
  * \param chan channel on which to check for hang up
diff --git a/res/res_osp.c b/res/res_osp.c
index 128befbcc1f33fe4ff16358522b2d217c8d05cfd..dca948c72ca1024678e4b1e552df1ddad098c76a 100755
--- a/res/res_osp.c
+++ b/res/res_osp.c
@@ -521,7 +521,6 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
 	int tokenlen;
 	unsigned int dummy=0;
 	unsigned int timelimit;
-	char* sipcallid;
 	unsigned int callidlen;
 	char callidstr[OSPC_CALLID_MAXSIZE] = "";
 	struct osp_provider *osp;
@@ -531,9 +530,9 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
 	char destination[2048]="";
 	char token[2000];
 	char tmp[256]="", *l, *n;
-	OSPTCALLID *callid;
 	OSPE_DEST_PROT prot;
 	OSPE_DEST_OSP_ENABLED ospenabled;
+	char *devinfo = NULL;
 
 	result->handle = -1;
 	result->numresults = 0;
@@ -558,8 +557,6 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
 	callerid = l;
 
 	if (chan) {
-		sipcallid = pbx_builtin_getvar_helper (chan, "SIPCALLID");
-		ast_copy_string(callidstr, sipcallid, sizeof(callidstr));
 		cres = ast_autoservice_start(chan);
 		if (cres < 0)
 			return cres;
@@ -581,67 +578,71 @@ int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, ch
 	ast_mutex_unlock(&osplock);
 	if (res) {
 		res = 0;
-		callid = OSPPCallIdNew(strlen(callidstr), callidstr);
-		if (callid) {
-			/* No more than 10 back */
-			counts = 10;
-			dummy = 0;
-			callidlen = sizeof(callidstr);
-			if (!OSPPTransactionRequestAuthorisation(result->handle, source, "", 
-				  callerid,OSPC_E164, extension, OSPC_E164, NULL, 1, &callid, NULL, &counts, &dummy, NULL)) {
-				if (counts) {
-					tokenlen = sizeof(token);
-					result->numresults = counts - 1;
-					if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
-						sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
-						ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
-							destination, callednum, callingnum, extension, provider);
-						ast_channel_setwhentohangup (chan, timelimit);	/* Only support OSP server with only one duration limit */
-						do {
-							if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
-								result->token[0] = 0;
-							}
-							else {
-								ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
+		/* No more than 10 back */
+		counts = 10;
+		dummy = 0;
+		devinfo = pbx_builtin_getvar_helper (chan, "OSPPEER");
+		if (!devinfo) {
+			devinfo = "";
+		}
+		if (!OSPPTransactionRequestAuthorisation(result->handle, source, devinfo, 
+			  callerid,OSPC_E164, extension, OSPC_E164, NULL, 0, NULL, NULL, &counts, &dummy, NULL)) {
+			if (counts) {
+				tokenlen = sizeof(token);
+				result->numresults = counts - 1;
+				callidlen = sizeof(callidstr);
+				if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
+					sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
+					ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
+						destination, callednum, callingnum, extension, provider);
+					/* Only support OSP server with only one duration limit */
+					if (ast_channel_cmpwhentohangup (chan, timelimit) < 0) {
+						ast_channel_setwhentohangup (chan, timelimit);	
+					}
+					do {
+						if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
+							result->token[0] = 0;
+						}
+						else {
+							ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
+						}
+						if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
+							res = 1;
+							/* Strip leading and trailing brackets */
+							destination[strlen(destination) - 1] = '\0';
+							switch(prot) {
+							case OSPE_DEST_PROT_H323_SETUP:
+								ast_copy_string(result->tech, "H323", sizeof(result->tech));
+								snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+								break;
+							case OSPE_DEST_PROT_SIP:
+								ast_copy_string(result->tech, "SIP", sizeof(result->tech));
+								snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+								break;
+							case OSPE_DEST_PROT_IAX:
+								ast_copy_string(result->tech, "IAX", sizeof(result->tech));
+								snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
+								break;
+							default:
+								ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
+								res = 0;
 							}
-							if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
-								res = 1;
-								/* Strip leading and trailing brackets */
-								destination[strlen(destination) - 1] = '\0';
-								switch(prot) {
-								case OSPE_DEST_PROT_H323_SETUP:
-									ast_copy_string(result->tech, "H323", sizeof(result->tech));
-									snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
-									break;
-								case OSPE_DEST_PROT_SIP:
-									ast_copy_string(result->tech, "SIP", sizeof(result->tech));
-									snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
-									break;
-								case OSPE_DEST_PROT_IAX:
-									ast_copy_string(result->tech, "IAX", sizeof(result->tech));
-									snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
-									break;
-								default:
-									ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
-									res = 0;
-								}
-								if (!res && result->numresults) {
-									result->numresults--;
-									if (OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
-											sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
-											break;
-									}
+							if (!res && result->numresults) {
+								result->numresults--;
+								callidlen = sizeof(callidstr);
+								if (OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
+										sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
+										break;
 								}
-							} else {
-								ast_log(LOG_DEBUG, "Missing destination protocol\n");
-								break;
 							}
-						} while(!res && result->numresults);
-					}
+						} else {
+							ast_log(LOG_DEBUG, "Missing destination protocol\n");
+							break;
+						}
+					} while(!res && result->numresults);
 				}
-				
 			}
-			OSPPCallIdDelete(&callid);
+			
 		}
 		if (!res) {
 			OSPPTransactionDelete(result->handle);
@@ -680,11 +681,11 @@ int ast_osp_next(struct ast_osp_result *result, int cause)
 
 	if (result->handle > -1) {
 		dummy = 0;
-		callidlen = sizeof(callidstr);
 		if (result->numresults) {
 			tokenlen = sizeof(token);
 			while(!res && result->numresults) {
 				result->numresults--;
+				callidlen = sizeof(callidstr);
 				if (!OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
 									sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
 					if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {