From 18ac09fb0d48f246fc3e75bf75c36f7d0a7c5957 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 13 Jun 2007 03:37:55 +0000 Subject: [PATCH] WIP git-svn-id: http://svn.openzap.org/svn/openzap/trunk@251 a93c3328-9c30-0410-af19-c9cd2b2d52af --- libs/openzap/mod_openzap/mod_openzap.c | 131 ++++++++++++++++++++++++- libs/openzap/src/include/openzap.h | 3 + libs/openzap/src/priserver.c | 9 +- libs/openzap/src/sangoma_pri.c | 12 +-- libs/openzap/src/testisdn.c | 2 +- libs/openzap/src/zap_io.c | 7 +- libs/openzap/src/zap_isdn.c | 102 ++++++++++++++++++- 7 files changed, 245 insertions(+), 21 deletions(-) diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index 070ea50e5d..e4793fe807 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -316,6 +316,13 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) } } 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)); @@ -536,7 +543,27 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc 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) @@ -913,7 +940,46 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal) 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: @@ -1027,7 +1093,7 @@ static switch_status_t load_config(void) 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; } @@ -1041,6 +1107,65 @@ static switch_status_t load_config(void) } } + 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); diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index 774f3bcd4f..a13ae80814 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -296,6 +296,9 @@ struct zap_caller_data { char aniII[25]; char dnis[25]; char rdnis[25]; + int CRV; + uint8_t raw_data[1024]; + uint32_t raw_data_len; }; struct zap_channel { diff --git a/libs/openzap/src/priserver.c b/libs/openzap/src/priserver.c index 9126a186af..57c29146c2 100644 --- a/libs/openzap/src/priserver.c +++ b/libs/openzap/src/priserver.c @@ -88,7 +88,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo) 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"); } @@ -103,7 +103,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo) #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); @@ -167,7 +167,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo) if (lead) { continue; } - zap_channel_write(chan, outframe, &len); + zap_channel_write(chan, outframe, sizeof(outframe), &len); } else { printf("BREAK"); break; @@ -289,7 +289,8 @@ int main(int argc, char *argv[]) printf("OpenZAP loaded\n"); - + debug = PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE; + if (sangoma_init_pri(&spri, 1, // span 24, // dchan diff --git a/libs/openzap/src/sangoma_pri.c b/libs/openzap/src/sangoma_pri.c index 865fe4f476..bf213699b6 100644 --- a/libs/openzap/src/sangoma_pri.c +++ b/libs/openzap/src/sangoma_pri.c @@ -105,8 +105,8 @@ static int __pri_sangoma_read(struct pri *pri, void *buf, int buflen) 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; } @@ -118,13 +118,13 @@ static int __pri_sangoma_write(struct pri *pri, void *buf, int buflen) 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; } @@ -136,7 +136,7 @@ int sangoma_init_pri(struct sangoma_pri *spri, int span, int dchan, int swtype, 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))){ diff --git a/libs/openzap/src/testisdn.c b/libs/openzap/src/testisdn.c index 93af26f752..231215a4b1 100644 --- a/libs/openzap/src/testisdn.c +++ b/libs/openzap/src/testisdn.c @@ -19,7 +19,7 @@ int main(int argc, char *argv[]) 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; } diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index 009fafef40..82d6706134 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -781,9 +781,12 @@ zap_status_t zap_channel_close(zap_channel_t **zchan) 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); @@ -1966,7 +1969,7 @@ void print_bits(uint8_t *b, int bl, char *buf, int blen, zap_endian_t e, uint8_t 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) { diff --git a/libs/openzap/src/zap_isdn.c b/libs/openzap/src/zap_isdn.c index f9577e4798..36628a6309 100644 --- a/libs/openzap/src/zap_isdn.c +++ b/libs/openzap/src/zap_isdn.c @@ -71,6 +71,55 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) 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; } @@ -89,7 +138,7 @@ static int zap_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen) 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 @@ -98,12 +147,49 @@ static int zap_isdn_921_21(void *pvt, L2UCHAR *msg, L2INT mlen) 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); @@ -118,29 +204,34 @@ static void *zap_isdn_run(zap_thread_t *me, void *obj) 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 @@ -191,7 +282,7 @@ zap_status_t zap_isdn_configure_span(zap_span_t *span, Q921NetUser_t mode, Q931D 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; } @@ -246,6 +337,7 @@ zap_status_t zap_isdn_configure_span(zap_span_t *span, Q921NetUser_t mode, Q931D span->isdn_data->q931.autoRestartAck = 1; + span->signal_type = ZAP_SIGTYPE_ISDN; return ZAP_SUCCESS;