Skip to content
Snippets Groups Projects
chan_ooh323.c 148 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	int reloading;
    	struct ooh323_pvt *h323 = NULL;
    	time_t t;
    
    	for (;;) {
    		struct ooh323_pvt *h323_next;
    		/* Check for a reload request */
    		ast_mutex_lock(&h323_reload_lock);
    		reloading = h323_reloading;
    		h323_reloading = 0;
    		ast_mutex_unlock(&h323_reload_lock);
    		if (reloading) {
    			ast_verb(1, "Reloading H.323\n");
    			ooh323_do_reload();
    		}
    
    		if (gH323ep.gkClient && gH323ep.gkClient->state == GkClientStopped) {
    			ooGkClientDestroy();
    			ast_verb(0, "Restart stopped gatekeeper client\n");
    
    			ooGkClientInit(gRasGkMode, (gRasGkMode == RasUseSpecificGatekeeper) ?
    
    									gGatekeeper : 0, gRASIP, 0);
    
    			ooGkClientStart(gH323ep.gkClient);
    		}
    
    		/* Check for interfaces needing to be killed */
    		ast_mutex_lock(&iflock);
    		time(&t);
    		h323 = iflist;
    		while (h323) {
    			h323_next = h323->next;
    
    
    			if (h323->rtp && h323->rtptimeout && h323->lastrtptx &&
    				h323->lastrtptx + h323->rtptimeout < t) {
    				ast_rtp_instance_sendcng(h323->rtp, 0);
    				h323->lastrtptx = time(NULL);
    			}
    
    			if (h323->rtp && h323->owner && h323->rtptimeout &&
    
    				h323->lastrtprx && ast_sockaddr_isnull(&h323->redirip) &&
    
    				h323->lastrtprx + h323->rtptimeout < t) {
    				if (!ast_channel_trylock(h323->owner)) {
    					ast_softhangup_nolock(h323->owner, AST_SOFTHANGUP_DEV);
    
    					ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", ast_channel_name(h323->owner), (long) (t - h323->lastrtprx));
    
    					ast_channel_unlock(h323->owner);
    				}
    
    			if (ast_test_flag(h323, H323_NEEDDESTROY)) {
    				ooh323_destroy (h323);
    
             } /* else if (ast_test_flag(h323, H323_NEEDSTART) && h323->owner) {
    	  ast_channel_lock(h323->owner);
              if (ast_pbx_start(h323->owner)) {
                ast_log(LOG_WARNING, "Unable to start PBX on %s\n", h323->owner->name);
                ast_channel_unlock(h323->owner);
                ast_hangup(h323->owner);
              }
              ast_channel_unlock(h323->owner);
    	  ast_clear_flag(h323, H323_NEEDSTART);
    	 } */
    
    			h323 = h323_next;
    		}
    		ast_mutex_unlock(&iflock);
    		pthread_testcancel();
    
    		/* Wait for sched or io */
    		res = ast_sched_wait(sched);
    		if ((res < 0) || (res > 1000)) {
    			res = 1000;
    		}
    		res = ast_io_wait(io, res);
    		pthread_testcancel();
    		ast_mutex_lock(&monlock);
    		if (res >= 0) {
    			ast_sched_runq(sched);
    		}
    		ast_mutex_unlock(&monlock);
    	}
    	/* Never reached */
    	return NULL;
    }
    
    int restart_monitor(void)
    {
    	pthread_attr_t attr;
    
    	/* If we're supposed to be stopped -- stay stopped */
    	if (monitor_thread == AST_PTHREADT_STOP)
    		return 0;
    	if (ast_mutex_lock(&monlock)) {
    		ast_log(LOG_WARNING, "Unable to lock monitor\n");
    		return -1;
    	}
    	if (monitor_thread == pthread_self()) {
    		ast_mutex_unlock(&monlock);
    		ast_log(LOG_WARNING, "Cannot kill myself\n");
    		return -1;
    	}
    	if (monitor_thread != AST_PTHREADT_NULL) {
    		/* Wake up the thread */
    		pthread_kill(monitor_thread, SIGURG);
    	} else {
    		pthread_attr_init(&attr);
    		pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    		/* Start a new monitor */
    		if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
    			ast_mutex_unlock(&monlock);
    			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
    			return -1;
    		}
    	}
    	ast_mutex_unlock(&monlock);
    	return 0;
    }
    
    
    
    int ooh323_destroy(struct ooh323_pvt *p)
    {
    	/* NOTE: Assumes iflock already acquired */
    	struct ooh323_pvt *prev = NULL, *cur = NULL;
    
    	struct ooh323_user *user = NULL;
    
    	}
    
    	cur = iflist;
    	while (cur) {
    		if (cur == p) { break; }
    		prev = cur;
    		cur = cur->next;
    	}
    
    	if (cur) {
    		ast_mutex_lock(&cur->lock);
    		if (prev)
    			prev->next = cur->next;
    		else
    			iflist = cur->next;
    
    		if (cur->callToken) {
    
    				ast_verb(0, " Destroying %s\n", cur->callToken);
    
    			ast_free(cur->callToken);
    
    			ast_free(cur->callerid_name);
    
    			ast_free(cur->callerid_num);
    
    			ast_rtp_instance_stop(cur->rtp);
    
    			ast_rtp_instance_destroy(cur->rtp);
    			cur->rtp = NULL;
    		}
    
    		if (cur->udptl) {
    			ast_udptl_destroy(cur->udptl);
    			cur->udptl = NULL;
    
    		/* Unlink us from the owner if we have one */
    		if (cur->owner) {
    
             		while(ast_channel_trylock(cur->owner)) {
                			ast_debug(1, "Failed to grab lock, trying again\n");
    
    				DEADLOCK_AVOIDANCE(&cur->lock);
    
    			ast_debug(1, "Detaching from %s\n", ast_channel_name(cur->owner));
    
    			ast_channel_tech_pvt_set(cur->owner, NULL);
    
    			ast_channel_unlock(cur->owner);
    			cur->owner = NULL;
    
    			ast_module_unref(myself);
    
    		if (cur->vad) {
    			ast_dsp_free(cur->vad);
    			cur->vad = NULL;
    		}
    
    
    /* decrement user/peer count */
    
          if(!ast_test_flag(cur, H323_OUTGOING)) {
    	 if (cur->neighbor.user) {
    	  user = find_user(p->callerid_name, cur->neighbor.user);
    	  if(user && user->inUse > 0) {
    	  	ast_mutex_lock(&user->lock);
    	  	user->inUse--;
    	  	ast_mutex_unlock(&user->lock);
    	  }
    
    	  ast_free(cur->neighbor.user);
    
    	 }
          } else {
    /* outgoing limit decrement here !!! */
          }
    
    
    		ast_mutex_unlock(&cur->lock);
    		ast_mutex_destroy(&cur->lock);
    
    		ao2_cleanup(cur->writeformat);
    		ao2_cleanup(cur->readformat);
    		ao2_cleanup(cur->cap);
    
    		ast_free(cur);
    
    
    	return 0;
    }
    
    int delete_peers()
    {
    	struct ooh323_peer *cur = NULL, *prev = NULL;
    	ast_mutex_lock(&peerl.lock);
    	cur = peerl.peers;
    	while (cur) {
    		prev = cur;
    		cur = cur->next;
    
    		ast_mutex_destroy(&prev->lock);
    
    		ast_free(prev->h323id);
    		ast_free(prev->email);
    		ast_free(prev->url);
    		ast_free(prev->e164);
    
          if(prev->rtpmask) {
    		ast_mutex_lock(&prev->rtpmask->lock);
    		prev->rtpmask->inuse--;
    		ast_mutex_unlock(&prev->rtpmask->lock);
    	 	if (prev->rtpmask->inuse == 0) {
    	  		regfree(&prev->rtpmask->regex);
    			ast_mutex_destroy(&prev->rtpmask->lock);
    
    
    		if (cur == peerl.peers) {
    			break;
    		}
    	}
    	peerl.peers = NULL;
    	ast_mutex_unlock(&peerl.lock);
    	return 0;
    }
    
    int delete_users()
    {
    	struct ooh323_user *cur = NULL, *prev = NULL;
    	ast_mutex_lock(&userl.lock);
    	cur = userl.users;
    	while (cur) {
    		prev = cur;
    		cur = cur->next;
    		ast_mutex_destroy(&prev->lock);
    
    
          		if(prev->rtpmask) {
    			ast_mutex_lock(&prev->rtpmask->lock);
    			prev->rtpmask->inuse--;
    			ast_mutex_unlock(&prev->rtpmask->lock);
    	 		if (prev->rtpmask->inuse == 0) {
    	  			regfree(&prev->rtpmask->regex);
    				ast_mutex_destroy(&prev->rtpmask->lock);
    
    		if (cur == userl.users) {
    			break;
    		}
    	}
    	userl.users = NULL;
    	ast_mutex_unlock(&userl.lock);
    	return 0;
    }
    
    static int unload_module(void)
    {
    	struct ooh323_pvt *p;
    	struct ooAliases *cur = NULL, *prev = NULL;
    
    	if (gH323Debug) {
    
    	}
    	/* First, take us out of the channel loop */
    	ast_cli_unregister_multiple(cli_ooh323, sizeof(cli_ooh323) / sizeof(struct ast_cli_entry));
    
    	ast_rtp_glue_unregister(&ooh323_rtp);
    
    	ast_channel_unregister(&ooh323_tech);
    #if 0
    	ast_unregister_atexit(&ast_ooh323c_exit);
    #endif
    
    	if (gH323Debug) {
    
    		ast_verb(0, "  unload_module - hanging up all interfaces\n");
    
    	}
    	if (!ast_mutex_lock(&iflock)) {
    		/* Hangup all interfaces if they have an owner */
    		p = iflist;
    		while (p) {
    			if (p->owner) {
    				ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
    			}
    			p = p->next;
    		}
    		iflist = NULL;
    		ast_mutex_unlock(&iflock);
    	} else {
    		ast_log(LOG_WARNING, "Unable to lock the interface list\n");
    		return -1;
    	}
    
    
    	if (gH323Debug) {
    
    		ast_verb(0, "  unload_module - stopping monitor thread\n");
    
    	if (monitor_thread != AST_PTHREADT_NULL) {
    		if (!ast_mutex_lock(&monlock)) {
    			if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
    				pthread_cancel(monitor_thread);
    				pthread_kill(monitor_thread, SIGURG);
    				pthread_join(monitor_thread, NULL);
    			}
    			monitor_thread = AST_PTHREADT_STOP;
    			ast_mutex_unlock(&monlock);
    		} else {
    			ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    			return -1;
    		}
    	}
    
    
    	if (gH323Debug) {
    
    		ast_verb(0, "   unload_module - stopping stack thread\n");
    
    		ast_verb(0, "   unload_module - freeing up memory used by interfaces\n");
    
    	}
    	if (!ast_mutex_lock(&iflock)) {
    		struct ooh323_pvt *pl;
    
    		/* Destroy all the interfaces and free their memory */
    		p = iflist;
    		while (p) {
    			pl = p;
    			p = p->next;
    			/* Free associated memory */
    			ooh323_destroy(pl);
    		}
    		iflist = NULL;
    		ast_mutex_unlock(&iflock);
    	} else {
    		ast_log(LOG_WARNING, "Unable to lock the interface list\n");
    		return -1;
    	}
    
    		ast_verb(0, "  unload_module - deleting users\n");
    
    		ast_verb(0, "  unload_module - deleting peers\n");
    
    		ast_verb(0, "  unload_module - Freeing up alias list\n");
    
    	}
    	cur = gAliasList;
    	while (cur) {
    	  prev = cur;
    	  cur = cur->next;
    
    	  ast_free(prev->value);
    	  ast_free(prev);
    
    		ast_verb(0, "	unload_module- destroying OOH323 endpoint \n");
    
    	ao2_ref(gCap, -1);
    	gCap = NULL;
    	ao2_ref(ooh323_tech.capabilities, -1);
    	ooh323_tech.capabilities = NULL;
    
    static void ooh323_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
    {
    	struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
    	if (gH323Debug) {
    		ast_verb(0, "+++ ooh323  get_codec, %s\n", ast_channel_name(chan));
    	}
    
    	if (p) {
    
    		if (ast_format_cap_count(ast_channel_nativeformats(chan))) {
    			ast_format_cap_append_from_cap(result, ast_channel_nativeformats(chan), AST_MEDIA_TYPE_UNKNOWN);
    		} else if (ast_format_cap_count(p->cap)) {
    			ast_format_cap_append_from_cap(result, p->cap, AST_MEDIA_TYPE_UNKNOWN);
    		}
    
    	}
    
    	if (gH323Debug) {
    		ast_verb(0, "--- ooh323  get_codec, %s\n", ast_channel_name(chan));
    	}
    }
    
    
    static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
    
    	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
    
    	struct ast_sockaddr tmp;
    
    	if (gH323Debug) {
    		ast_verb(0, "+++ ooh323  get_rtp_peer \n");
    	}
    
    	if (!(p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan)))
    
    		return AST_RTP_GLUE_RESULT_FORBID;
    
    		return AST_RTP_GLUE_RESULT_FORBID;
    
    
    	*rtp = p->rtp ? ao2_ref(p->rtp, +1), p->rtp : NULL;
    
    
    	/* there must be checking of directmedia setting */
    
    	if ((ast_channel_state(chan) != AST_STATE_UP && !p->earlydirect) || !p->directrtp) {
    		res = AST_RTP_GLUE_RESULT_LOCAL;
    	} else {
    		res = AST_RTP_GLUE_RESULT_REMOTE;
    	}
    
    	if (ast_test_flag(&global_jbconf, AST_JB_FORCED)) {
    		res = AST_RTP_GLUE_RESULT_FORBID;
    	}
    
    
    	ast_rtp_instance_get_remote_address(*rtp, &tmp);
    	if (gH323Debug) {
    
    		ast_verb(0, "ooh323_get_rtp_peer  %s -> %s:%d, %u\n", ast_channel_name(chan), ast_sockaddr_stringify_addr(&tmp),
    
    						ast_sockaddr_port(&tmp), res);
    	}
    	if (gH323Debug) {
    		ast_verb(0, "--- ooh323  get_rtp_peer, res = %d\n", (int) res);
    	}
    
    
    static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
    
    	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_LOCAL;
    
    	if (!(p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan)))
    
    		return AST_RTP_GLUE_RESULT_FORBID;
    
    		return AST_RTP_GLUE_RESULT_FORBID;
    
    
    	*rtp = p->vrtp ? ao2_ref(p->vrtp, +1), p->vrtp : NULL;
    
    
    	/* there must check of supporting video per call */
    
    	res = AST_RTP_GLUE_RESULT_FORBID;
    
    int ooh323_convertAsteriskCapToH323Cap(struct ast_format *format)
    
    	if (ast_format_cmp(format, ast_format_ulaw) == AST_FORMAT_CMP_EQUAL) {
    
    	} else if (ast_format_cmp(format, ast_format_alaw) == AST_FORMAT_CMP_EQUAL) {
    
    	} else if (ast_format_cmp(format, ast_format_gsm) == AST_FORMAT_CMP_EQUAL) {
    
    	} else if (ast_format_cmp(format, ast_format_speex) == AST_FORMAT_CMP_EQUAL) {
    
    		return OO_SPEEX;
    
    	} else if (ast_format_cmp(format, ast_format_g729) == AST_FORMAT_CMP_EQUAL) {
    
    	} else if (ast_format_cmp(format, ast_format_g726) == AST_FORMAT_CMP_EQUAL) {
    
    		return OO_G726;
    
    	} else if (ast_format_cmp(format, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
    
    		return OO_G726AAL2;
    
    	} else if (ast_format_cmp(format, ast_format_g723) == AST_FORMAT_CMP_EQUAL) {
    
    	} else if (ast_format_cmp(format, ast_format_h263) == AST_FORMAT_CMP_EQUAL) {
    
    	} else {
    		ast_log(LOG_NOTICE, "Don't know how to deal with mode %s\n", ast_format_get_name(format));
    
    static int ooh323_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp,
    
    	 struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *cap, int nat_active)
    
    {
    	/* XXX Deal with Video */
    	struct ooh323_pvt *p;
    
    	int changed = 0;
    	char *callToken = NULL;
    
    		ast_verb(0, "---   ooh323_set_peer - %s\n", ast_channel_name(chan));
    
    	if (ooh323_convertAsteriskCapToH323Cap(ast_channel_writeformat(chan)) < 0) {
    
    		ast_log(LOG_WARNING, "Unknown format.\n");
    		return -1;
    	}
    
    	p = (struct ooh323_pvt *) ast_channel_tech_pvt(chan);
    
    	if (!p) {
    		ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
    		return -1;
    	}
    
    	ast_mutex_lock(&p->lock);
    
    	if (rtp) {
    		changed |= ast_rtp_instance_get_and_cmp_remote_address(rtp, &p->redirip);
    	} else if (!ast_sockaddr_isnull(&p->redirip)) {
    		changed = 1;
    		memset(&p->redirip, 0, sizeof(p->redirip));
    	}
    
    
    	callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
    
    
    	if (!callToken) {
    		if (gH323Debug) {
    			ast_verb(0, "	set_rtp_peer - No callToken\n");
    		}
    		ast_mutex_unlock(&p->lock);
    		return -1;
    	}
    
    	if (changed) {
    		if (!ast_sockaddr_isnull(&p->redirip)) {
    			if (gH323Debug) {
    				ast_verb(0, "ooh323_set_rtp_peer  %s -> %s:%d\n", ast_channel_name(chan), ast_sockaddr_stringify_addr(&p->redirip),
    							ast_sockaddr_port(&p->redirip));
    			}
    			ooUpdateLogChannels(callToken, ast_sockaddr_stringify_addr(&p->redirip),
    							ast_sockaddr_port(&p->redirip));
    		} else {
    			if (gH323Debug) {
    				ast_verb(0, "ooh323_set_rtp_peer  return back to local\n");
    			}
    			ooUpdateLogChannels(callToken, "0.0.0.0" , 0);
    		}
    	}
    
    	ast_mutex_unlock(&p->lock);
    
    }
    
    
    
    
    int configure_local_rtp(struct ooh323_pvt *p, ooCallData *call)
    {
    
    	char lhost[INET6_ADDRSTRLEN];
    	unsigned lport = 0;
    
    Mark Michelson's avatar
    Mark Michelson committed
    	struct ast_sockaddr tmp;
    
    	memset(&mediaInfo, 0, sizeof(mediaInfo));
    
    	if (ast_parse_arg(call->localIP, PARSE_ADDR, &tmp)) {
    		ast_sockaddr_copy(&tmp, &bindaddr);
    	}
    	if (!(p->rtp = ast_rtp_instance_new("asterisk", sched, &tmp, NULL))) {
    		ast_log(LOG_WARNING, "Unable to create RTP session: %s\n",
    			strerror(errno));
    		return 0;
    	}
    
    	ast_rtp_instance_set_qos(p->rtp, gTOS, 0, "ooh323-rtp");
    
    	if (!(p->udptl = ast_udptl_new_with_bindaddr(sched, io, 0, &tmp))) {
    		ast_log(LOG_WARNING, "Unable to create UDPTL session: %s\n",
    			strerror(errno));
    		return 0;
    	}
    
    	ast_udptl_set_far_max_datagram(p->udptl, 144);
    
    
    	if (p->owner) {
    		while (p->owner && ast_channel_trylock(p->owner)) {
    			ast_debug(1,"Failed to grab lock, trying again\n");
    			DEADLOCK_AVOIDANCE(&p->lock);
    		}
    		if (!p->owner) {
    			ast_mutex_unlock(&p->lock);
    			ast_log(LOG_ERROR, "Channel has no owner\n");
    			return 0;
    		}
    	} else {
    		ast_log(LOG_ERROR, "Channel has no owner\n");
    		return 0;
    	}
    
    	ast_channel_set_fd(p->owner, 0, ast_rtp_instance_fd(p->rtp, 0));
    	ast_channel_set_fd(p->owner, 1, ast_rtp_instance_fd(p->rtp, 1));
    	ast_channel_set_fd(p->owner, 5, ast_udptl_fd(p->udptl));
    
    	ast_channel_unlock(p->owner);
    
    
    		if (p->cap) {
    			ast_rtp_codecs_set_framing(ast_rtp_instance_get_codecs(p->rtp),
    				ast_format_cap_get_framing(p->cap));
    		}
    
    		if (p->nat) {
    			ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_NAT, 1);
    		}
    
    		if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
    			ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
    			ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
    				 p->rtp, p->dtmfcodec, "audio", "telephone-event", 0);
    		}
    		if (p->dtmfmode & H323_DTMF_CISCO && p->dtmfcodec) {
    			ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_DTMF, 1);
    			ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
    				 p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
    		}
    		/* figure out our local RTP port and tell the H.323 stack about it*/
    
    Mark Michelson's avatar
    Mark Michelson committed
    		ast_rtp_instance_get_local_address(p->rtp, &tmp);
    
    		ast_copy_string(lhost, ast_sockaddr_stringify_addr(&tmp), sizeof(lhost));
    
    		lport = ast_sockaddr_port(&tmp);
    
    
    		if (p->rtptimeout) {
    			ast_rtp_instance_set_timeout(p->rtp, p->rtptimeout);
    		}
    		ast_rtp_instance_set_prop(p->rtp, AST_RTP_PROPERTY_RTCP, 1);
    
    	if (p->rtdrcount) {
    		if (gH323Debug)
    
    			ast_verb(0, "Setup RTDR info: %d, %d\n", p->rtdrinterval, p->rtdrcount);
    
    		call->rtdrInterval = p->rtdrinterval;
    		call->rtdrCount = p->rtdrcount;
    	}
    
    
    	ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
    
    	mediaInfo.lMediaPort = lport;
    	mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort + 1;
    
    	for (x = 0; x < ast_format_cap_count(p->cap); x++) {
    		struct ast_format *format = ast_format_cap_get_format(p->cap, x);
    
    
    		strcpy(mediaInfo.dir, "transmit");
    
    		mediaInfo.cap = ooh323_convertAsteriskCapToH323Cap(format);
    
    		ooAddMediaInfo(call, mediaInfo);
    		strcpy(mediaInfo.dir, "receive");
    		ooAddMediaInfo(call, mediaInfo);
    		if (mediaInfo.cap == OO_G729A) {
    			strcpy(mediaInfo.dir, "transmit");
    			mediaInfo.cap = OO_G729;
    			ooAddMediaInfo(call, mediaInfo);
    			strcpy(mediaInfo.dir, "receive");
    			ooAddMediaInfo(call, mediaInfo);
    
    
    			strcpy(mediaInfo.dir, "transmit");
    			mediaInfo.cap = OO_G729B;
    			ooAddMediaInfo(call, mediaInfo);
    			strcpy(mediaInfo.dir, "receive");
    			ooAddMediaInfo(call, mediaInfo);
    
    	if (p->udptl) {
    
    		ast_udptl_get_us(p->udptl, &tmp);
    
    		ast_copy_string(lhost, ast_sockaddr_stringify_addr(&tmp), sizeof(lhost));
    
    		lport = ast_sockaddr_port(&tmp);
    
    		ast_copy_string(mediaInfo.lMediaIP, lhost, sizeof(mediaInfo.lMediaIP));
    
    		mediaInfo.lMediaPort = lport;
    
    		mediaInfo.lMediaCntrlPort = mediaInfo.lMediaPort +1;
    		mediaInfo.cap = OO_T38;
    		strcpy(mediaInfo.dir, "transmit");
    		ooAddMediaInfo(call, mediaInfo);
    		strcpy(mediaInfo.dir, "receive");
    		ooAddMediaInfo(call, mediaInfo);
    
    void setup_rtp_remote(ooCallData *call, const char *remoteIp, int remotePort)
    {
    	struct ooh323_pvt *p = NULL;
    	struct ast_sockaddr tmp;
    
    	if (gH323Debug) {
    		ast_verb(0, "---   setup_rtp_remote %s:%d\n", remoteIp, remotePort);
    	}
    	if (!remoteIp || !remoteIp[0] || !remotePort) {
    		if (gH323Debug) {
    			ast_verb(0, "+++ setup_rtp_remote no data\n");
    		}
    		return;
    	}
    
    	/* Find the call or allocate a private structure if call not found */
    	p = find_call(call);
    
    	if (!p || !p->rtp) {
    		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
    		return;
    	}
    
    	ast_mutex_lock(&p->lock);
    
    	ast_parse_arg(remoteIp, PARSE_ADDR, &tmp);
    	ast_sockaddr_set_port(&tmp, remotePort);
    	ast_rtp_instance_set_remote_address(p->rtp, &tmp);
    
    	ast_mutex_unlock(&p->lock);
    
    	if (gH323Debug) {
    		ast_verb(0, "+++   setup_rtp_remote\n");
    	}
    
    	return;
    }
    
    
    void setup_rtp_connection(ooCallData *call, const char *remoteIp, int remotePort)
    
    Mark Michelson's avatar
    Mark Michelson committed
    	struct ast_sockaddr tmp;
    
    		ast_verb(0, "---   setup_rtp_connection %s:%d\n", remoteIp, remotePort);
    
    
    	/* Find the call or allocate a private structure if call not found */
    
    		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
    		return;
    	}
    
    
    	ast_parse_arg(remoteIp, PARSE_ADDR, &tmp);
    	ast_sockaddr_set_port(&tmp, remotePort);
    
    Mark Michelson's avatar
    Mark Michelson committed
    	ast_rtp_instance_set_remote_address(p->rtp, &tmp);
    
    	if (ast_format_cmp(p->writeformat, ast_format_g726_aal2) == AST_FORMAT_CMP_EQUAL) {
    
                    ast_rtp_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp), p->rtp, 2,
    							"audio", "G726-32", AST_RTP_OPT_G726_NONSTANDARD);
    
    
    	return;
    }
    
    void close_rtp_connection(ooCallData *call)
    {
    	struct ooh323_pvt *p = NULL;
    
    
       if(gH323Debug)
    
          ast_log(LOG_ERROR, "Couldn't find matching call to close rtp "
                             "connection\n");
    
    		return;
    	}
    	ast_mutex_lock(&p->lock);
    	if (p->rtp) {
    
    		ast_rtp_instance_stop(p->rtp);
    
       if(gH323Debug)
    
    void setup_udptl_connection(ooCallData *call, const char *remoteIp,
    
    								  int remotePort)
    {
    	struct ooh323_pvt *p = NULL;
    
    	struct ast_sockaddr them;
    
    
    	/* Find the call or allocate a private structure if call not found */
    
    	p = find_call(call);
    
    
    	if (!p) {
    		ast_log(LOG_ERROR, "Something is wrong: rtp\n");
    		return;
    	}
    
    	ast_mutex_lock(&p->lock);
    	if (p->owner) {
    		while (p->owner && ast_channel_trylock(p->owner)) {
    
    			ast_debug(1, "Failed to grab lock, trying again\n");
    
    			DEADLOCK_AVOIDANCE(&p->lock);
    		}
    		if (!p->owner) {
    			ast_mutex_unlock(&p->lock);
    			ast_log(LOG_ERROR, "Channel has no owner\n");
    			return;
    		}
    	} else {
    		ast_mutex_unlock(&p->lock);
    		ast_log(LOG_ERROR, "Channel has no owner\n");
    		return;
    	}
    
    
    	ast_parse_arg(remoteIp, PARSE_ADDR, &them);
    	ast_sockaddr_set_port(&them, remotePort);
    
    	ast_udptl_set_peer(p->udptl, &them);
    
    	ast_udptl_set_tag(p->udptl, "%s", ast_channel_name(p->owner));
    
    	p->t38_tx_enable = 1;
    	p->lastTxT38 = time(NULL);
    	if (p->t38support == T38_ENABLED) {
    		struct ast_control_t38_parameters parameters = { .request_response = 0 };
    		parameters.request_response = AST_T38_NEGOTIATED;
    
    		parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
    		parameters.rate = AST_T38_RATE_14400;
    
    		ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
    	}
    
    	if (gH323Debug) {
    		ast_debug(1, "Receiving UDPTL  %s:%d\n", ast_sockaddr_stringify_host(&them),
    							ast_sockaddr_port(&them));
    	}
    
    
    	ast_channel_unlock(p->owner);
    	ast_mutex_unlock(&p->lock);
    
    	if(gH323Debug)
    
    
    	return;
    }
    
    void close_udptl_connection(ooCallData *call)
    {
    	struct ooh323_pvt *p = NULL;
    
    
       	if(gH323Debug)
    
    
    	p = find_call(call);
    	if (!p) {
    
          		ast_log(LOG_ERROR, "Couldn't find matching call to close udptl "
    
                             "connection\n");
    		return;
    	}
    	ast_mutex_lock(&p->lock);
    	if (p->owner) {
    		while (p->owner && ast_channel_trylock(p->owner)) {
    
    			ast_debug(1, "Failed to grab lock, trying again\n");
    
    			DEADLOCK_AVOIDANCE(&p->lock);
    		}
    		if (!p->owner) {
    			ast_mutex_unlock(&p->lock);
    			ast_log(LOG_ERROR, "Channel has no owner\n");
    			return;
    		}
    	} else {
    		ast_mutex_unlock(&p->lock);
    		ast_log(LOG_ERROR, "Channel has no owner\n");
    		return;
    	}
    
    	p->t38_tx_enable = 0;
    	if (p->t38support == T38_ENABLED) {
    		struct ast_control_t38_parameters parameters = { .request_response = 0 };
    		parameters.request_response = AST_T38_TERMINATED;
    		ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &parameters, sizeof(parameters));
    
    	ast_channel_unlock(p->owner);
    	ast_mutex_unlock(&p->lock);
    
       	if(gH323Debug)
    
    /* end of udptl handling */
    
    
    int update_our_aliases(ooCallData *call, struct ooh323_pvt *p)
    {
    	int updated = -1;
    	ooAliases *psAlias = NULL;
    
    	if (!call->ourAliases)
    		return updated;
    	for (psAlias = call->ourAliases; psAlias; psAlias = psAlias->next) {
    		if (psAlias->type == T_H225AliasAddress_h323_ID) {
    			ast_copy_string(p->callee_h323id, psAlias->value, sizeof(p->callee_h323id));
    			updated = 1;
    		}
    		if (psAlias->type == T_H225AliasAddress_dialedDigits) {
    
             ast_copy_string(p->callee_dialedDigits, psAlias->value,
    
                                            sizeof(p->callee_dialedDigits));
    
    			updated = 1;
    		}
    		if (psAlias->type == T_H225AliasAddress_url_ID) {
    			ast_copy_string(p->callee_url, psAlias->value, sizeof(p->callee_url));
    			updated = 1;
    		}
    		if (psAlias->type == T_H225AliasAddress_email_ID) {
    			ast_copy_string(p->callee_email, psAlias->value, sizeof(p->callee_email));
    			updated = 1;
    		}
    	}
    	return updated;
    }
    
    struct ast_frame *ooh323_rtp_read(struct ast_channel *ast, struct ooh323_pvt *p)
    {
    	/* Retrieve audio/etc from channel.  Assumes p->lock is already held. */
    	struct ast_frame *f;
    
    	struct ast_frame *dfr = NULL;
    
    	static struct ast_frame null_frame = { AST_FRAME_NULL, };
    
    	switch (ast_channel_fdno(ast)) {
    
    		f = ast_rtp_instance_read(p->rtp, 0);	/* RTP Audio */
    
    		p->lastrtprx = time(NULL);
    
    		f = ast_rtp_instance_read(p->rtp, 1);	/* RTCP Control Channel */
    
    		f = ast_rtp_instance_read(p->vrtp, 0);	/* RTP Video */
    
    		p->lastrtprx = time(NULL);
    
    		f = ast_rtp_instance_read(p->vrtp, 1);	/* RTCP Control Channel for video */
    		break;
    	case 5:
    		f = ast_udptl_read(p->udptl);		/* UDPTL t.38 data */