mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	support call duration limits on inbound OSP calls (issue #5346)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@6721 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										25
									
								
								channel.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								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) | ||||
| { | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
							
								
								
									
										127
									
								
								res/res_osp.c
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								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); | ||||
| 							} | ||||
| 							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; | ||||
| 									} | ||||
| 								} | ||||
| 							} else { | ||||
| 								ast_log(LOG_DEBUG, "Missing destination protocol\n"); | ||||
| 								break; | ||||
| 							} | ||||
| 						} while(!res && result->numresults); | ||||
| 		/* 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 (!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); | ||||
| 				} | ||||
| 				 | ||||
| 			} | ||||
| 			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)) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user