}
}
break;
+ case ZAP_CHAN_TYPE_B:
+ {
+ if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) {
+ zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP);
+ }
+ }
+ break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled type for channel %s\n", switch_channel_get_name(channel));
static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg)
{
- return SWITCH_STATUS_FALSE;
+ switch_channel_t *channel;
+ private_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = (private_t *) switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
+ zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_UP);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_receive_message_fxo(switch_core_session_t *session, switch_core_session_message_t *msg)
return status;
}
-static ZIO_SIGNAL_CB_FUNCTION(on_zap_signal)
+static ZIO_SIGNAL_CB_FUNCTION(on_isdn_signal)
+{
+ switch_core_session_t *session = NULL;
+ switch_channel_t *channel = NULL;
+ zap_status_t status;
+
+ zap_log(ZAP_LOG_DEBUG, "got ISDN sig [%s]\n", zap_signal_event2str(sigmsg->event_id));
+
+ switch(sigmsg->event_id) {
+ case ZAP_SIGEVENT_START:
+ {
+ return zap_channel_from_event(sigmsg, &session);
+ }
+ break;
+ case ZAP_SIGEVENT_STOP:
+ {
+ while((session = zap_channel_get_session(sigmsg->channel, 0))) {
+ zap_channel_clear_token(sigmsg->channel, 0);
+ channel = switch_core_session_get_channel(session);
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ switch_core_session_rwunlock(session);
+ }
+ }
+ break;
+ case ZAP_SIGEVENT_UP:
+ {
+ if ((session = zap_channel_get_session(sigmsg->channel, 0))) {
+ channel = switch_core_session_get_channel(session);
+ switch_channel_mark_answered(channel);
+ switch_core_session_rwunlock(session);
+ }
+ }
+ break;
+ }
+
+ return ZAP_SUCCESS;
+}
+
+
+static ZIO_SIGNAL_CB_FUNCTION(on_analog_signal)
{
switch (sigmsg->channel->type) {
case ZAP_CHAN_TYPE_FXO:
continue;
}
- if (zap_analog_configure_span(span, tonegroup, to, max, on_zap_signal) != ZAP_SUCCESS) {
+ if (zap_analog_configure_span(span, tonegroup, to, max, on_analog_signal) != ZAP_SUCCESS) {
zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %d\n", span_id);
continue;
}
}
}
+ if ((spans = switch_xml_child(cfg, "pri_spans"))) {
+ for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
+ char *id = (char *) switch_xml_attr_soft(myspan, "id");
+ char *context = "default";
+ char *dialplan = "XML";
+ Q921NetUser_t mode = Q931_TE;
+ Q931Dialect_t dialect = Q931_Dialect_National;
+ uint32_t span_id = 0;
+ zap_span_t *span = NULL;
+ char *tonegroup = NULL;
+
+ for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+
+ if (!strcasecmp(var, "tonegroup")) {
+ tonegroup = val;
+ } else if (!strcasecmp(var, "mode")) {
+ mode = strcasecmp(val, "net") ? Q931_TE : Q931_NT;
+ } else if (!strcasecmp(var, "dialect")) {
+ dialect = q931_str2Q931Diaelct_type(val);
+ if (dialect == Q931_Dialect_Count) {
+ dialect = Q931_Dialect_National;
+ }
+ } else if (!strcasecmp(var, "context")) {
+ context = val;
+ } else if (!strcasecmp(var, "dialplan")) {
+ dialplan = val;
+ }
+ }
+
+ if (!id) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
+ }
+
+ span_id = atoi(id);
+
+ if (!tonegroup) {
+ tonegroup = "us";
+ }
+
+ if (zap_span_find(span_id, &span) != ZAP_SUCCESS) {
+ zap_log(ZAP_LOG_ERROR, "Error finding OpenZAP span %d\n", span_id);
+ continue;
+ }
+
+ if (zap_isdn_configure_span(span, mode, dialect, on_isdn_signal) != ZAP_SUCCESS) {
+ zap_log(ZAP_LOG_ERROR, "Error starting OpenZAP span %d mode: %d dialect: %d error: %s\n", span_id, mode, dialect, span->last_error);
+ continue;
+ }
+
+ SPAN_CONFIG[span->span_id].span = span;
+ switch_copy_string(SPAN_CONFIG[span->span_id].context, context, sizeof(SPAN_CONFIG[span->span_id].context));
+ switch_copy_string(SPAN_CONFIG[span->span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span->span_id].dialplan));
+
+ zap_isdn_start(span);
+ }
+ }
+
switch_xml_free(xml);
char aniII[25];
char dnis[25];
char rdnis[25];
+ int CRV;
+ uint8_t raw_data[1024];
+ uint32_t raw_data_len;
};
struct zap_channel {
memset(inframe, 0, MAX_BYTES);
memset(outframe, 0, MAX_BYTES);
- if (zap_channel_open("wanpipe", spri->span, channo, &chan) != ZAP_SUCCESS) {
+ if (zap_channel_open(spri->span, channo, &chan) != ZAP_SUCCESS) {
printf("DEBUG cant open fd!\n");
}
#endif
#if 1
- if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_TONE_DETECT, &tt) != ZAP_SUCCESS) {
+ if (zap_channel_command(chan, ZAP_COMMAND_ENABLE_DTMF_DETECT, &tt) != ZAP_SUCCESS) {
printf("Critical Error: Failed to set dtmf detect!\n");
zap_channel_close(&chan);
exit(-1);
if (lead) {
continue;
}
- zap_channel_write(chan, outframe, &len);
+ zap_channel_write(chan, outframe, sizeof(outframe), &len);
} else {
printf("BREAK");
break;
printf("OpenZAP loaded\n");
-
+ debug = PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE;
+
if (sangoma_init_pri(&spri,
1, // span
24, // dchan
memset(&((unsigned char*)buf)[res],0,2);
res+=2;
- print_bits(buf, res-2, bb, sizeof(bb), 1);
- zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", res-2, LINE, bb);
+ //print_bits(buf, res-2, bb, sizeof(bb), 1, 0);
+ //zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", res-2, LINE, bb);
return res;
}
zap_size_t len = buflen -2;
char bb[4096] = "";
- if (zap_channel_write(spri->zdchan, buf, &len) != ZAP_SUCCESS) {
+ if (zap_channel_write(spri->zdchan, buf, buflen, &len) != ZAP_SUCCESS) {
printf("D-WRITE FAIL! [%s]\n", spri->zdchan->last_error);
return 0;
}
- print_bits(buf, (int)buflen-2, bb, sizeof(bb), 1);
- zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)buflen-2, LINE, bb);
+ //print_bits(buf, (int)buflen-2, bb, sizeof(bb), 1, 0);
+ //zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)buflen-2, LINE, bb);
return (int) buflen;
}
memset(spri, 0, sizeof(struct sangoma_pri));
- if (zap_channel_open("wanpipe", span, dchan, &spri->zdchan) != ZAP_SUCCESS) {
+ if (zap_channel_open(span, dchan, &spri->zdchan) != ZAP_SUCCESS) {
fprintf(stderr, "Unable to open DCHAN %d for span %d (%s)\n", dchan, span, strerror(errno));
} else {
if ((spri->pri = pri_new_cb(spri->zdchan->sockfd, node, swtype, __pri_sangoma_read, __pri_sangoma_write, spri))){
printf("OpenZAP loaded\n");
- if (zap_span_find("wanpipe", 1, &span) != ZAP_SUCCESS) {
+ if (zap_span_find(1, &span) != ZAP_SUCCESS) {
fprintf(stderr, "Error finding OpenZAP span\n");
goto done;
}
assert(zchan != NULL);
check = *zchan;
- assert(check != NULL);
*zchan = NULL;
+ if (!check) {
+ return ZAP_FAIL;
+ }
+
zap_mutex_lock(check->mutex);
if (zap_test_flag(check, ZAP_CHANNEL_OPEN)) {
status = check->zio->close(check);
if (blen < (bl * 10) + 2) {
return;
}
-
+
zap_bitstream_init(&bs, b, bl, e, ss);
last = bs.byte_index;
while((bit = zap_bitstream_get_bit(&bs)) > -1) {
assert(data != NULL);
zap_log(ZAP_LOG_DEBUG, "Yay I got an event! Type:[%d] Size:[%d]\n", gen->MesType, gen->Size);
+ switch(gen->MesType) {
+ case Q931mes_SETUP:
+ {
+ Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf);
+ Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf);
+ Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
+ int chan_id = chanid->ChanSlot;
+ zap_channel_t *zchan;
+ zap_status_t status;
+ zap_sigmsg_t sig;
+ zap_isdn_data_t *data;
+ int fail = 1;
+ uint32_t cplen = mlen;
+
+ if ((status = zap_channel_open(span->span_id, chan_id, &zchan) == ZAP_SUCCESS)) {
+ zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING);
+ sig.chan_id = zchan->chan_id;
+ sig.span_id = zchan->span_id;
+ sig.channel = zchan;
+ sig.event_id = ZAP_SIGEVENT_START;
+ data = zchan->span->isdn_data;
+
+ memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
+
+ zap_copy_string(zchan->caller_data.cid_num, callingnum->Digit, callingnum->Size - 3);
+ zap_copy_string(zchan->caller_data.cid_name, callingnum->Digit, callingnum->Size - 3);
+ zap_copy_string(zchan->caller_data.ani, callingnum->Digit, callingnum->Size - 3);
+ zap_copy_string(zchan->caller_data.dnis, callednum->Digit, callednum->Size - 3);
+
+ zchan->caller_data.CRV = gen->CRV;
+ if (cplen > sizeof(zchan->caller_data.raw_data)) {
+ cplen = sizeof(zchan->caller_data.raw_data);
+ }
+ memcpy(zchan->caller_data.raw_data, msg, cplen);
+ zchan->caller_data.raw_data_len = cplen;
+ if ((status = data->sig_cb(&sig) == ZAP_SUCCESS)) {
+ fail = 0;
+ }
+ }
+
+ if (fail) {
+ // add me
+ }
+
+ }
+ break;
+ default:
+ break;
+ }
return 0;
}
zap_size_t len = (zap_size_t) mlen;
#ifdef IODEBUG
char bb[4096] = "";
- print_bits(msg, (int)len, bb, sizeof(bb), 1, 0);
+ print_bits(msg, (int)len, bb, sizeof(bb), ZAP_ENDIAN_LITTLE, 0);
zap_log(ZAP_LOG_DEBUG, "WRITE %d\n%s\n%s\n\n", (int)len, LINE, bb);
#endif
return zap_channel_write(span->isdn_data->dchan, msg, len, &len) == ZAP_SUCCESS ? 0 : -1;
}
+static void state_advance(zap_channel_t *zchan)
+{
+ Q931mes_Generic *gen = (Q931mes_Generic *) zchan->caller_data.raw_data;
+ zap_isdn_data_t *data = zchan->span->isdn_data;
+
+ zap_log(ZAP_LOG_ERROR, "%d:%d STATE [%s]\n",
+ zchan->span_id, zchan->chan_id, zap_channel_state2str(zchan->state));
+
+
+ switch (zchan->state) {
+ case ZAP_CHANNEL_STATE_UP:
+ {
+ printf("XXXXXXXXXXXXXXXX answer %d\n", zchan->caller_data.raw_data_len);
+ gen->MesType = Q931mes_CONNECT;
+ gen->BearerCap = 0;
+ gen->CRVFlag = 1;//!(gen->CRVFlag);
+ Q931Rx43(&data->q931, (void *)gen, zchan->caller_data.raw_data_len);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static void check_state(zap_span_t *span)
+{
+ uint32_t j;
+
+ for(j = 1; j <= span->chan_count; j++) {
+ if (zap_test_flag((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE)) {
+ state_advance(&span->channels[j]);
+ zap_clear_flag_locked((&span->channels[j]), ZAP_CHANNEL_STATE_CHANGE);
+ }
+ }
+}
+
static void *zap_isdn_run(zap_thread_t *me, void *obj)
{
zap_span_t *span = (zap_span_t *) obj;
zap_isdn_data_t *data = span->isdn_data;
unsigned char buf[1024];
zap_size_t len = sizeof(buf);
+ int errs = 0;
#ifdef WIN32
timeBeginPeriod(1);
zap_status_t status = zap_channel_wait(data->dchan, &flags, 100);
Q921TimerTick(&data->q921);
-
+ check_state(span);
+
switch(status) {
case ZAP_FAIL:
{
zap_log(ZAP_LOG_ERROR, "D-Chan Read Error!\n");
snprintf(span->last_error, sizeof(span->last_error), "D-Chan Read Error!");
- goto done;
+ if (++errs == 10) {
+ goto done;
+ }
}
break;
case ZAP_TIMEOUT:
{
/*zap_log(ZAP_LOG_DEBUG, "Timeout!\n");*/
/*Q931TimeTick(data->q931, L3ULONG ms);*/
+ errs = 0;
}
break;
default:
{
+ errs = 0;
if (flags & ZAP_READ) {
len = sizeof(buf);
if (zap_channel_read(data->dchan, buf, &len) == ZAP_SUCCESS) {
#ifdef IODEBUG
char bb[4096] = "";
- print_bits(buf, (int)len, bb, sizeof(bb), 1, 0);
+ print_bits(buf, (int)len, bb, sizeof(bb), ZAP_ENDIAN_LITTLE, 0);
zap_log(ZAP_LOG_DEBUG, "READ %d\n%s\n%s\n\n", (int)len, LINE, bb);
#endif
zap_channel_t *dchans[2] = {0};
if (span->signal_type) {
- snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling.");
+ snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d].", span->signal_type);
return ZAP_FAIL;
}
span->isdn_data->q931.autoRestartAck = 1;
+
span->signal_type = ZAP_SIGTYPE_ISDN;
return ZAP_SUCCESS;