Skip to content
Snippets Groups Projects
chan_ooh323.c 148 KiB
Newer Older
  • Learn to ignore specific revisions
  •       		.transfercap = 0
    
       	if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
    
    		ast_log(LOG_WARNING, "ooh323_call called on %s, neither down nor "
    
    								"reserved\n", ast_channel_name(ast));
    
    		return -1;
    	}
    	ast_mutex_lock(&p->lock);
    	ast_set_flag(p, H323_OUTGOING);
    
    	if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
    
    		ast_free(p->callerid_num);
    		p->callerid_num = ast_strdup(ast_channel_connected(ast)->id.number.str);
    
    	if (ast_channel_connected(ast)->id.name.valid && ast_channel_connected(ast)->id.name.str) {
    
    		ast_free(p->callerid_name);
    		p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.name.str);
    
    	} else if (ast_channel_connected(ast)->id.number.valid && ast_channel_connected(ast)->id.number.str) {
    
    		ast_free(p->callerid_name);
    		p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.number.str);
    
    		ast_channel_connected(ast)->id.name.valid = 1;
    
    		ast_free(ast_channel_connected(ast)->id.name.str);
    		ast_channel_connected(ast)->id.name.str = ast_strdup(gCallerID);
    		ast_free(p->callerid_name);
    		p->callerid_name = ast_strdup(ast_channel_connected(ast)->id.name.str);
    
    	}
    
    	/* Retrieve vars */
    
    
    	if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323ID"))) {
    		ast_copy_string(p->caller_h323id, val, sizeof(p->caller_h323id));
    	}
    
    	if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323DIALEDDIGITS"))) {
    		ast_copy_string(p->caller_dialedDigits, val, sizeof(p->caller_dialedDigits));
    
          		if(!p->callerid_num)
    
    			p->callerid_num = ast_strdup(val);
    
    	}
    
    	if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323EMAIL"))) {
    		ast_copy_string(p->caller_email, val, sizeof(p->caller_email));
    	}
    
    	if ((val = pbx_builtin_getvar_helper(ast, "CALLER_H323URL"))) {
    		ast_copy_string(p->caller_url, val, sizeof(p->caller_url));
    	}
    
    	if (p->host && p->port != 0)
    		snprintf(destination, sizeof(destination), "%s:%d", p->host, p->port);
    	else if (p->host)
    		snprintf(destination, sizeof(destination), "%s", p->host);
    	else
    		ast_copy_string(destination, dest, sizeof(destination));
    
    
    	destination[sizeof(destination)-1]='\0';
    
    	opts.transfercap = ast_channel_transfercapability(ast);
    
    	opts.fastStart = p->faststart;
    	opts.tunneling = p->h245tunneling;
    
    	for (i=0;i<480 && !isRunning(p->callToken);i++) usleep(12000);
    
    	if(OO_TESTFLAG(p->flags, H323_DISABLEGK)) {
    		res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, &opts);
    	} else {
    		res = ooRunCall(destination, p->callToken, AST_MAX_EXTENSION, NULL);
     	}
    
    
    	ast_mutex_unlock(&p->lock);
    	if (res != OO_OK) {
    		ast_log(LOG_ERROR, "Failed to make call\n");
    
          		return -1; /* ToDO: cleanup */
    
    
      return 0;
    }
    
    static int ooh323_hangup(struct ast_channel *ast)
    {
    
    	struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
    
       	int q931cause = AST_CAUSE_NORMAL_CLEARING;
    
            if (ast_channel_hangupcause(ast)) {
                    q931cause = ast_channel_hangupcause(ast);
    
            } else {
                    const char *cause = pbx_builtin_getvar_helper(ast, "DIALSTATUS");
                    if (cause) {
                            if (!strcmp(cause, "CONGESTION")) {
                                    q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
                            } else if (!strcmp(cause, "BUSY")) {
                                    q931cause = AST_CAUSE_USER_BUSY;
                            } else if (!strcmp(cause, "CHANISUNVAIL")) {
                                    q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL;
                            } else if (!strcmp(cause, "NOANSWER")) {
                                    q931cause = AST_CAUSE_NO_ANSWER;
                            } else if (!strcmp(cause, "CANCEL")) {
                                    q931cause = AST_CAUSE_CALL_REJECTED;
                            }
                    }
            }
    
    
    
    
    			ast_verb(0, "    hanging %s with cause: %d\n", p->username, q931cause);
    
    		ast_channel_tech_pvt_set(ast, NULL);
    
    		if (!ast_test_flag(p, H323_ALREADYGONE)) {
    
             		ooHangCall(p->callToken,
    
    				ooh323_convert_hangupcause_asteriskToH323(q931cause), q931cause);
    
    			ast_set_flag(p, H323_ALREADYGONE);
    			/* ast_mutex_unlock(&p->lock); */
    
    			ast_set_flag(p, H323_NEEDDESTROY);
    		/* detach channel here */
    		if (p->owner) {
    
    			ast_channel_tech_pvt_set(p->owner, NULL);
    
    			ast_module_unref(myself);
    
    		}
    
    		ast_mutex_unlock(&p->lock);
    		ast_mutex_lock(&usecnt_lock);
    		usecnt--;
    		ast_mutex_unlock(&usecnt_lock);
    
    		/* Notify the module monitors that use count for resource has changed */
    		ast_update_use_count();
    
    		ast_debug(1, "No call to hangup\n" );
    
    
      return 0;
    }
    
    static int ooh323_answer(struct ast_channel *ast)
    {
    
    	struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
    
    	char *callToken = (char *)NULL;
    
    	if (p) {
    
    		ast_mutex_lock(&p->lock);
    
    		callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
    
    		if (ast_channel_state(ast) != AST_STATE_UP) {
    
    			ast_channel_lock(ast);
    
    			if (!p->alertsent) {
    	    			if (gH323Debug) {
    
    					ast_debug(1, "Sending forced ringback for %s, res = %u\n",
    
    						callToken, ooManualRingback(callToken));
    				} else {
    	    				ooManualRingback(callToken);
    				}
    				p->alertsent = 1;
    			}
    
    			ast_setstate(ast, AST_STATE_UP);
    
    			ast_debug(1, "ooh323_answer(%s)\n", ast_channel_name(ast));
    
    			ast_channel_unlock(ast);
    			ooAnswerCall(p->callToken);
    		}
    
    		ast_mutex_unlock(&p->lock);
    
    
      return 0;
    }
    
    static struct ast_frame *ooh323_read(struct ast_channel *ast)
    {
    	struct ast_frame *fr;
    	static struct ast_frame null_frame = { AST_FRAME_NULL, };
    
    	struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
    
    	if (!p) return &null_frame;
    
    
    	ast_mutex_lock(&p->lock);
    	if (p->rtp)
    		fr = ooh323_rtp_read(ast, p);
    	else
    		fr = &null_frame;
    	/* time(&p->lastrtprx); */
    	ast_mutex_unlock(&p->lock);
    	return fr;
    }
    
    static int ooh323_write(struct ast_channel *ast, struct ast_frame *f)
    {
    
    	struct ooh323_pvt *p = ast_channel_tech_pvt(ast);
    
    	if (p) {
    		ast_mutex_lock(&p->lock);
    
    
    		if (f->frametype == AST_FRAME_MODEM) {
    
    			ast_debug(1, "Send UDPTL %u/%d len %d for %s\n",
    
    				f->frametype, f->subclass.integer, f->datalen, ast_channel_name(ast));
    
    			if (p->udptl)
    				res = ast_udptl_write(p->udptl, f);
    			ast_mutex_unlock(&p->lock);
    			return res;
    		}
    
    
    		if (f->frametype == AST_FRAME_VOICE) {
    /* sending progress for first */
    			if (!ast_test_flag(p, H323_OUTGOING) && !p->progsent &&
    
    			 		p->callToken) {
    
    				ooManualProgress(p->callToken);
    				p->progsent = 1;
    			}
    
    
    
    			if (ast_format_cap_iscompatible_format(ast_channel_nativeformats(ast), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
    				if (ast_format_cap_count(ast_channel_nativeformats(ast))) {
    
    					struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
    
    					ast_log(LOG_WARNING,
    							"Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
    
    							ast_format_get_name(f->subclass.format),
    							ast_format_cap_get_names(ast_channel_nativeformats(ast), &codec_buf),
    							ast_format_get_name(ast_channel_readformat(ast)),
    							ast_format_get_name(ast_channel_writeformat(ast)));
    
    					ast_set_write_format(ast, f->subclass.format);
    
    				} else {
    					/* ast_set_write_format(ast, f->subclass);
    					ast->nativeformats = f->subclass; */
    				}
    			ast_mutex_unlock(&p->lock);
    
    			}
    
    		if (p->rtp)
    			res = ast_rtp_instance_write(p->rtp, f);
    
    		ast_mutex_unlock(&p->lock);
    
    		} else if (f->frametype == AST_FRAME_IMAGE) {
    
    			return 0;
    		} else {
    
    			ast_log(LOG_WARNING, "Can't send %u type frames with OOH323 write\n",
    
    			ast_mutex_unlock(&p->lock);
    			return 0;
    		}
    
    
    	}
    
    	return res;
    }
    
    static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
    {
    
    
    	struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast);
    
    	char *callToken = (char *)NULL;
    
    	if (!p) return -1;
    
    
    	callToken = (p->callToken ? ast_strdup(p->callToken) : NULL);
    
    	ast_mutex_unlock(&p->lock);
    
    	if (!callToken) {
    		if (gH323Debug)
    
    			ast_verb(0, "	ooh323_indicate - No callToken\n");
    
    	if (!ast_sockaddr_isnull(&p->redirip)) {
    		res = 0;
    	}
    
    	if (gH323Debug) {
    
    		ast_verb(0, "----- ooh323_indicate %d on call %s\n", condition, callToken);
    
       	ast_mutex_lock(&p->lock);
    
    	case AST_CONTROL_INCOMPLETE:
    		/* While h323 does support overlapped dialing, this channel driver does not
    		 * at this time.  Treat a response of Incomplete as if it were congestion.
    		 */
    
    	case AST_CONTROL_CONGESTION:
    		if (!ast_test_flag(p, H323_ALREADYGONE)) {
    
    			ooHangCall(callToken, OO_REASON_LOCAL_CONGESTED, AST_CAUSE_SWITCH_CONGESTION);
    
    		}
    		break;
    	case AST_CONTROL_BUSY:
    		if (!ast_test_flag(p, H323_ALREADYGONE)) {
    
    			ooHangCall(callToken, OO_REASON_LOCAL_BUSY, AST_CAUSE_USER_BUSY);
    
    		ast_moh_start(ast, data, NULL);
    
    		break;
    	case AST_CONTROL_UNHOLD:
    		ast_moh_stop(ast);
    		break;
    	case AST_CONTROL_PROGRESS:
    
    		if (ast_channel_state(ast) != AST_STATE_UP) {
    
    	    		if (!p->progsent) {
    
    	     			if (gH323Debug) {
    
    					ast_debug(1, "Sending manual progress for %s, res = %u\n", callToken, rres);
    
    	     			p->progsent = 1;
    	    		}
    
    		}
    	    break;
          case AST_CONTROL_RINGING:
    
    		if (ast_channel_state(ast) == AST_STATE_RING || ast_channel_state(ast) == AST_STATE_RINGING) {
    
    			if (!p->alertsent) {
    
    				if (gH323Debug) {
    
    					ast_debug(1, "Sending manual ringback for %s, res = %u\n", callToken, rres);
    
    				}
    				p->alertsent = 1;
    
    	case AST_CONTROL_SRCUPDATE:
    
    		if (p->rtp) {
    			ast_rtp_instance_update_source(p->rtp);
    		}
    
    		break;
    	case AST_CONTROL_SRCCHANGE:
    
    		if (p->rtp) {
    			ast_rtp_instance_change_source(p->rtp);
    		}
    
    	case AST_CONTROL_CONNECTED_LINE:
    
    		if (!ast_channel_connected(ast)->id.name.valid
    			|| ast_strlen_zero(ast_channel_connected(ast)->id.name.str)) {
    
    			break;
    
    		if (gH323Debug) {
    			ast_debug(1, "Sending connected line info for %s (%s)\n",
    
    				callToken, ast_channel_connected(ast)->id.name.str);
    
    		ooSetANI(callToken, ast_channel_connected(ast)->id.name.str);
    
          case AST_CONTROL_T38_PARAMETERS:
    		if (p->t38support != T38_ENABLED) {
    			struct ast_control_t38_parameters parameters = { .request_response = 0 };
    			parameters.request_response = AST_T38_REFUSED;
    			ast_queue_control_data(ast, AST_CONTROL_T38_PARAMETERS,
    						 &parameters, sizeof(parameters));
    			break;
    		}
    		if (datalen != sizeof(struct ast_control_t38_parameters)) {
    			ast_log(LOG_ERROR, "Invalid datalen for AST_CONTROL_T38. "
    					   "Expected %d, got %d\n",
    				(int)sizeof(enum ast_control_t38), (int)datalen);
    		} else {
    			const struct ast_control_t38_parameters *parameters = data;
    
    			struct ast_control_t38_parameters our_parameters;
    
    			enum ast_control_t38 message = parameters->request_response;
    			switch (message) {
    
    
    			case AST_T38_NEGOTIATED:
    				if (p->faxmode) {
    					res = 0;
    					break;
    				}
    
    			case AST_T38_REQUEST_NEGOTIATE:
    
    
    				if (p->faxmode) {
    					/* T.38 already negotiated */
    					our_parameters.request_response = AST_T38_NEGOTIATED;
    					our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
    					our_parameters.rate = AST_T38_RATE_14400;
    					ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
    				} else if (!p->chmodepend) {
    
    					p->chmodepend = 1;
    
    					ooRequestChangeMode(p->callToken, 1);
    
    				}
    				break;
    
    			case AST_T38_REQUEST_TERMINATE:
    
    
    				if (!p->faxmode) {
    					/* T.38 already terminated */
    					our_parameters.request_response = AST_T38_TERMINATED;
    					ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
    				} else if (!p->chmodepend) {
    
    					p->chmodepend = 1;
    
    					ooRequestChangeMode(p->callToken, 0);
    
    			case AST_T38_REQUEST_PARMS:
    				our_parameters.request_response = AST_T38_REQUEST_PARMS;
    				our_parameters.max_ifp = ast_udptl_get_far_max_ifp(p->udptl);
    				our_parameters.rate = AST_T38_RATE_14400;
    				ast_queue_control_data(p->owner, AST_CONTROL_T38_PARAMETERS, &our_parameters, sizeof(our_parameters));
    				res = AST_T38_REQUEST_PARMS;
    				break;
    
    	case AST_CONTROL_PROCEEDING:
    	case AST_CONTROL_PVT_CAUSE_CODE:
    
    	case AST_CONTROL_MASQUERADE_NOTIFY:
    
    	case -1:
    		break;
    	default:
    		ast_log(LOG_WARNING, "Don't know how to indicate condition %d on %s\n",
    									condition, callToken);
    	}
    
    
       	ast_mutex_unlock(&p->lock);
    
    
    	if (gH323Debug) {
    		ast_verb(0, "++++  ooh323_indicate %d on %s is %d\n", condition, callToken, res);
    	}
    
    static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
    {
    
    
    	struct ooh323_pvt *p = (struct ooh323_pvt *) ast_channel_tech_pvt(ast);
    
    	int res = -1;
    	enum ast_t38_state state = T38_STATE_UNAVAILABLE;
    	char* cp;
    
    	if (!p) return -1;
    
    	ast_mutex_lock(&p->lock);
    
    	if (gH323Debug)
    
    		ast_verb(0, "----- ooh323_queryoption %d on channel %s\n", option, ast_channel_name(ast));
    
    	switch (option) {
    
    		case AST_OPTION_T38_STATE:
    
    			if (*datalen != sizeof(enum ast_t38_state)) {
    
    				ast_log(LOG_ERROR, "Invalid datalen for AST_OPTION_T38_STATE option."
    
    				" Expected %d, got %d\n", (int)sizeof(enum ast_t38_state), *datalen);
    				break;
    			}
    
    
    			if (p->t38support != T38_DISABLED) {
    				if (p->faxmode) {
    					state = (p->chmodepend) ? T38_STATE_NEGOTIATING : T38_STATE_NEGOTIATED;
    				} else {
    					state = T38_STATE_UNKNOWN;
    				}
    			}
    
    
    			*((enum ast_t38_state *) data) = state;
    			res = 0;
    			break;
    
    
    		case AST_OPTION_DIGIT_DETECT:
    
    			cp = (char *) data;
    			*cp = p->vad ? 1 : 0;
    			ast_debug(1, "Reporting digit detection %sabled on %s\n",
    
    							 *cp ? "en" : "dis", ast_channel_name(ast));
    
    		ast_verb(0, "+++++ ooh323_queryoption %d on channel %s\n", option, ast_channel_name(ast));
    
       	ast_mutex_unlock(&p->lock);
    
    static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
    {
    
    	struct ooh323_pvt *p = ast_channel_tech_pvt(newchan);
    
    	if (!p) return -1;
    
    
    
    	ast_mutex_lock(&p->lock);
    	if (p->owner != oldchan) {
    		ast_log(LOG_WARNING, "Old channel wasn't %p but was %p\n", oldchan, p->owner);
    		ast_mutex_unlock(&p->lock);
    		return -1;
    	}
    
    	if (p->owner == oldchan) {
    		p->owner = newchan;
    	} else {
    		p->owner = oldchan;
    	}
    
    	ast_mutex_unlock(&p->lock);
    
    	if (gH323Debug)
    
    void ooh323_set_write_format(ooCallData *call, struct ast_format *fmt, int txframes)
    
    		ast_verb(0, "---   ooh323_update_writeformat %s/%d\n",
    
    	p = find_call(call);
    	if (!p) {
    		ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
    		return;
    	}
    
    	ast_mutex_lock(&p->lock);
    
    
    		struct ast_format_cap *caps;
    
    		caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
    		if (!caps) {
    			ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
    			return;
    		}
    
    
    		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");
    
    			struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
    
    			ast_verb(0, "Writeformat before update %s/%s\n",
    
    			  ast_format_get_name(ast_channel_writeformat(p->owner)),
    			  ast_format_cap_get_names(ast_channel_nativeformats(p->owner), &codec_buf));
    		}
    
    
    		if (p->dtmfmode & H323_DTMF_RFC2833 && p->dtmfcodec) {
    			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_codecs_payloads_set_rtpmap_type(ast_rtp_instance_get_codecs(p->rtp),
    				 p->rtp, p->dtmfcodec, "audio", "cisco-telephone-event", 0);
    		}
    
    
    		if (txframes) {
    			ast_format_cap_set_framing(caps, txframes);
    		}
    		ast_format_cap_append(caps, fmt, 0);
    		ast_channel_nativeformats_set(p->owner, caps);
    		ao2_ref(caps, -1);
    
    	  	ast_set_write_format(p->owner, ast_channel_writeformat(p->owner));
    	  	ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
    
    		ast_channel_unlock(p->owner);
       	} else
    		ast_log(LOG_ERROR, "No owner found\n");
    
    	ast_mutex_unlock(&p->lock);
    
    	if (gH323Debug)
    
    void ooh323_set_read_format(ooCallData *call, struct ast_format *fmt)
    
    	if (gH323Debug)
    
    		ast_verb(0, "---   ooh323_update_readformat %s\n",
    
    	p = find_call(call);
    	if (!p) {
    		ast_log(LOG_ERROR, "No matching call found for %s\n", call->callToken);
    		return;
    	}
    
    	ast_mutex_lock(&p->lock);
    
    		struct ast_format_cap *caps;
    
    		caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
    		if (!caps) {
    			ast_log(LOG_ERROR, "Could not allocate capabilities structure\n");
    			return;
    		}
    
    
    		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");
    
    			ast_verb(0, "Readformat before update %s\n",
    
    			  ast_format_get_name(ast_channel_readformat(p->owner)));
    		}
    		ast_format_cap_append(caps, fmt, 0);
    		ast_channel_nativeformats_set(p->owner, caps);
    		ao2_ref(caps, -1);
    		ast_set_read_format(p->owner, ast_channel_readformat(p->owner));
    
    		ast_channel_unlock(p->owner);
    
    		ast_log(LOG_ERROR, "No owner found\n");
    
    
    int onAlerting(ooCallData *call)
    {
    	struct ooh323_pvt *p = NULL;
    	struct ast_channel *c = NULL;
    
    	if (gH323Debug)
    
    		ast_verb(0, "--- onAlerting %s\n", call->callToken);
    
       	p = find_call(call);
    
       	if(!p) {
    
    		ast_log(LOG_ERROR, "No matching call found\n");
    		return -1;
    
    	if (!p->owner) {
    
    		ast_debug(1, "Channel has no owner\n");
    
    		return 0;
    	}
    	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_log(LOG_ERROR, "Channel has no owner\n");
    		return 0;
    
    	c = p->owner;
    
    
    	if (call->remoteDisplayName) {
    		struct ast_party_connected_line connected;
    
    		struct ast_set_party_connected_line update_connected;
    
    		memset(&update_connected, 0, sizeof(update_connected));
    		update_connected.id.name = 1;
    
    		ast_party_connected_line_init(&connected);
    
    		connected.id.name.valid = 1;
    		connected.id.name.str = (char *) call->remoteDisplayName;
    
    		connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
    
    		ast_channel_queue_connected_line_update(c, &connected, &update_connected);
    
    	if (ast_channel_state(c) != AST_STATE_UP)
    
    		ast_setstate(c, AST_STATE_RINGING);
    
    	ast_queue_control(c, AST_CONTROL_RINGING);
          	ast_channel_unlock(c);
          	ast_mutex_unlock(&p->lock);
    
    		ast_verb(0, "+++ onAlerting %s\n", call->callToken);
    
    int onProgress(ooCallData *call)
    {
    	struct ooh323_pvt *p = NULL;
    	struct ast_channel *c = NULL;
    
    	if (gH323Debug)
    
    		ast_verb(0, "--- onProgress %s\n", call->callToken);
    
       	p = find_call(call);
    
       	if(!p) {
    
    		ast_log(LOG_ERROR, "No matching call found\n");
    		return -1;
    
    	ast_mutex_lock(&p->lock);
    	if (!p->owner) {
    		ast_mutex_unlock(&p->lock);
    		ast_log(LOG_ERROR, "Channel has no owner\n");
    		return 0;
    	}
    	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;
    	}
    	c = p->owner;
    
    
    	if (call->remoteDisplayName) {
    		struct ast_party_connected_line connected;
    
    		struct ast_set_party_connected_line update_connected;
    
    		memset(&update_connected, 0, sizeof(update_connected));
    		update_connected.id.name = 1;
    
    		ast_party_connected_line_init(&connected);
    
    		connected.id.name.valid = 1;
    		connected.id.name.str = (char *) call->remoteDisplayName;
    
    		connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
    
    		ast_channel_queue_connected_line_update(c, &connected, &update_connected);
    
    	if (ast_channel_state(c) != AST_STATE_UP)
    
    		ast_setstate(c, AST_STATE_RINGING);
    
    	ast_queue_control(c, AST_CONTROL_PROGRESS);
    
          	ast_channel_unlock(c);
          	ast_mutex_unlock(&p->lock);
    
    		ast_verb(0, "+++ onProgress %s\n", call->callToken);
    
    /**
      * Callback for sending digits from H.323 up to asterisk
      *
      */
    int ooh323_onReceivedDigit(OOH323CallData *call, const char *digit)
    {
    	struct ooh323_pvt *p = NULL;
    	struct ast_frame f;
    	int res;
    
    	ast_debug(1, "Received Digit: %c\n", digit[0]);
    	p = find_call(call);
    	if (!p) {
    		ast_log(LOG_ERROR, "Failed to find a matching call.\n");
    		return -1;
    	}
    	if (!p->owner) {
    		ast_log(LOG_ERROR, "Channel has no owner\n");
    		return -1;
    	}
    	ast_mutex_lock(&p->lock);
    	memset(&f, 0, sizeof(f));
    	f.frametype = AST_FRAME_DTMF;
    
    	f.datalen = 0;
    	f.samples = 800;
    	f.offset = 0;
    	f.data.ptr = NULL;
    	f.mallocd = 0;
    	f.src = "SEND_DIGIT";
    
    
    	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;
    	}
    
    	res = ast_queue_frame(p->owner, &f);
    
       	ast_channel_unlock(p->owner);
       	ast_mutex_unlock(&p->lock);
    
    	return res;
    }
    
    int ooh323_onReceivedSetup(ooCallData *call, Q931Message *pmsg)
    {
    	struct ooh323_pvt *p = NULL;
    	struct ooh323_user *user = NULL;
    
       	struct ast_channel *c = NULL;
    
    	ooAliases *alias = NULL;
    	char *at = NULL;
    	char number [OO_MAX_NUMBER_LENGTH];
    
    	if (gH323Debug)
    
    		ast_verb(0, "---   ooh323_onReceivedSetup %s\n", call->callToken);
    
    
    
    	if (!(p = ooh323_alloc(call->callReference, call->callToken))) {
    		ast_log(LOG_ERROR, "Failed to create a new call.\n");
    		return -1;
    	}
    	ast_mutex_lock(&p->lock);
    	ast_clear_flag(p, H323_OUTGOING);
    
    		p->callerid_name = ast_strdup(call->remoteDisplayName);
    
    	}
    
    	if (ooCallGetCallingPartyNumber(call, number, OO_MAX_NUMBER_LENGTH) == OO_OK) {
    
    		p->callerid_num = ast_strdup(number);
    
    	}
    
    	if (call->remoteAliases) {
    		for (alias = call->remoteAliases; alias; alias = alias->next) {
    			if (alias->type == T_H225AliasAddress_h323_ID) {
    				if (!p->callerid_name) {
    
    					p->callerid_name = ast_strdup(alias->value);
    
    				}
    				ast_copy_string(p->caller_h323id, alias->value, sizeof(p->caller_h323id));
    				}
    
             else if(alias->type == T_H225AliasAddress_dialedDigits)
             {
                if(!p->callerid_num)
    
                   p->callerid_num = ast_strdup(alias->value);
    
    				ast_copy_string(p->caller_dialedDigits, alias->value,
    
    															sizeof(p->caller_dialedDigits));
    
             }
             else if(alias->type == T_H225AliasAddress_email_ID)
             {
    
    				ast_copy_string(p->caller_email, alias->value, sizeof(p->caller_email));
    
             }
             else if(alias->type == T_H225AliasAddress_url_ID)
             {
    
    				ast_copy_string(p->caller_url, alias->value, sizeof(p->caller_url));
    			}
    		}
    	}
    
    	number[0] = '\0';
    
       	if(ooCallGetCalledPartyNumber(call, number, OO_MAX_NUMBER_LENGTH)== OO_OK) {
    
          		ast_copy_string(p->exten, number, sizeof(p->exten));
    
    		update_our_aliases(call, p);
    		if (!ast_strlen_zero(p->callee_dialedDigits)) {
    
             		ast_copy_string(p->exten, p->callee_dialedDigits, sizeof(p->exten));
          		} else if(!ast_strlen_zero(p->callee_h323id)) {
    
    			ast_copy_string(p->exten, p->callee_h323id, sizeof(p->exten));
    
          		} else if(!ast_strlen_zero(p->callee_email)) {
    
    			ast_copy_string(p->exten, p->callee_email, sizeof(p->exten));
    			if ((at = strchr(p->exten, '@'))) {
    				*at = '\0';
    			}
    		}
    	}
    
    	/* if no extension found, set to default 's' */
    	if (ast_strlen_zero(p->exten)) {
    
          		p->exten[0]='s';
          		p->exten[1]='\0';
    
          	user = find_user(p->callerid_name, call->remoteIP);
          	if(user && (user->incominglimit == 0 || user->inUse < user->incominglimit)) {
    		ast_mutex_lock(&user->lock);
    
    		p->username = ast_strdup(user->name);
    
     		p->neighbor.user = user->mUseIP ? ast_strdup(user->mIP) :
    						  ast_strdup(user->name);
    		ast_copy_string(p->context, user->context, sizeof(p->context));
    		ast_copy_string(p->accountcode, user->accountcode, sizeof(p->accountcode));
    		p->amaflags = user->amaflags;
    
    		ast_format_cap_append_from_cap(p->cap, user->cap, AST_MEDIA_TYPE_UNKNOWN);
    
    		p->g729onlyA = user->g729onlyA;
    
    		p->dtmfmode |= user->dtmfmode;
    		p->dtmfcodec = user->dtmfcodec;
    
    		p->faxdetect = user->faxdetect;
    
    		p->t38support = user->t38support;
    		p->rtptimeout = user->rtptimeout;
    
    		p->h245tunneling = user->h245tunneling;
    		p->faststart = user->faststart;
    
    		p->directrtp = user->directrtp;
    		p->earlydirect = user->earlydirect;
    
    
    		if (p->faststart)
             		OO_SETFLAG(call->flags, OO_M_FASTSTART);
    		else
    			OO_CLRFLAG(call->flags, OO_M_FASTSTART);
    
    		/* if we disable h245tun for this user then we clear flag */
    		/* in any other case we don't must touch this */
    		/* ie if we receive setup without h245tun but enabled
    		   				we can't enable it per call */
    		if (!p->h245tunneling)
    
    			OO_CLRFLAG(call->flags, OO_M_TUNNELING);
    
    
    		if (user->rtpmask && user->rtpmaskstr[0]) {
    			p->rtpmask = user->rtpmask;
    
    			ast_copy_string(p->rtpmaskstr, user->rtpmaskstr,
    
    							 sizeof(p->rtpmaskstr));
    
    		if (user->rtdrcount > 0 && user->rtdrinterval > 0) {
    			p->rtdrcount = user->rtdrcount;
    			p->rtdrinterval = user->rtdrinterval;
    		}
    
    	 	if (user->incominglimit) user->inUse++;
    		ast_mutex_unlock(&user->lock);
    	} else {
    	 if (!OO_TESTFLAG(p->flags,H323_DISABLEGK)) {
    
    		p->username = ast_strdup(call->remoteIP);
    
    		p->directrtp = gDirectRTP;
    		p->earlydirect = gEarlyDirect;
    
    	} else {
    	  ast_mutex_unlock(&p->lock);
    	  ast_log(LOG_ERROR, "Unacceptable ip %s\n", call->remoteIP);
    
    	  if (!user) {
    
    	   ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_CALL_REJECTED), AST_CAUSE_CALL_REJECTED);
    
    	   call->callEndReason = OO_REASON_REMOTE_REJECTED;
    	  }
    	  else {
    
    	   ooHangCall(call->callToken, ooh323_convert_hangupcause_asteriskToH323(AST_CAUSE_NORMAL_CIRCUIT_CONGESTION), AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
    
    	   call->callEndReason = OO_REASON_REMOTE_REJECTED;
    	  }
    
    	  ast_set_flag(p, H323_NEEDDESTROY);
    	  return -1;
    	 }
    
    	ooh323c_set_capability_for_call(call, p->cap, p->dtmfmode, p->dtmfcodec,
    
    					 p->t38support, p->g729onlyA);
    
    /* Incoming call */
    
      	c = ooh323_new(p, AST_STATE_RING, p->username, 0, NULL, NULL);
    
      	if(!c) {
       	ast_mutex_unlock(&p->lock);
       	ast_log(LOG_ERROR, "Could not create ast_channel\n");
             return -1;
    
    	if (!configure_local_rtp(p, call)) {
    		ast_mutex_unlock(&p->lock);