diff --git a/libs/openzap/mod_openzap/mod_openzap.c b/libs/openzap/mod_openzap/mod_openzap.c index e4793fe807..639fc18f6f 100644 --- a/libs/openzap/mod_openzap/mod_openzap.c +++ b/libs/openzap/mod_openzap/mod_openzap.c @@ -319,6 +319,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) case ZAP_CHAN_TYPE_B: { if (tech_pvt->zchan->state != ZAP_CHANNEL_STATE_DOWN) { + tech_pvt->zchan->caller_data.hangup_cause = switch_channel_get_cause(channel); zap_set_state_locked(tech_pvt->zchan, ZAP_CHANNEL_STATE_HANGUP); } } @@ -638,7 +639,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s } } -static const switch_state_handler_table_t channel_event_handlers = { +static switch_state_handler_table_t channel_event_handlers = { /*.on_init */ channel_on_init, /*.on_ring */ channel_on_ring, /*.on_execute */ channel_on_execute, @@ -647,7 +648,7 @@ static const switch_state_handler_table_t channel_event_handlers = { /*.on_transmit */ channel_on_transmit }; -static const switch_io_routines_t channel_io_routines = { +static switch_io_routines_t channel_io_routines = { /*.outgoing_channel */ channel_outgoing_channel, /*.read_frame */ channel_read_frame, /*.write_frame */ channel_write_frame, @@ -658,7 +659,7 @@ static const switch_io_routines_t channel_io_routines = { /*.receive_message*/ channel_receive_message }; -static const switch_endpoint_interface_t channel_endpoint_interface = { +static switch_endpoint_interface_t channel_endpoint_interface = { /*.interface_name */ "openzap", /*.io_routines */ &channel_io_routines, /*.event_handlers */ &channel_event_handlers, @@ -666,7 +667,7 @@ static const switch_endpoint_interface_t channel_endpoint_interface = { /*.next */ NULL }; -static const switch_loadable_module_interface_t channel_module_interface = { +static switch_loadable_module_interface_t channel_module_interface = { /*.module_name */ modname, /*.endpoint_interface */ &channel_endpoint_interface, /*.timer_interface */ NULL, diff --git a/libs/openzap/src/include/openzap.h b/libs/openzap/src/include/openzap.h index a13ae80814..316b4d3af4 100644 --- a/libs/openzap/src/include/openzap.h +++ b/libs/openzap/src/include/openzap.h @@ -195,7 +195,7 @@ #define zap_set_state_locked(obj, s) if ( obj->state == s ) { \ zap_log(ZAP_LOG_WARNING, "Why bother changing state from %s to %s\n", zap_channel_state2str(obj->state), zap_channel_state2str(s)); \ - } else { \ + } else if (zap_test_flag(obj, ZAP_CHANNEL_READY)) { \ int st = obj->state; \ zap_channel_set_state(obj, s); \ if (obj->state == s) zap_log(ZAP_LOG_DEBUG, "Changing state from %s to %s\n", zap_channel_state2str(st), zap_channel_state2str(s)); \ @@ -297,6 +297,7 @@ struct zap_caller_data { char dnis[25]; char rdnis[25]; int CRV; + int hangup_cause; uint8_t raw_data[1024]; uint32_t raw_data_len; }; diff --git a/libs/openzap/src/include/zap_types.h b/libs/openzap/src/include/zap_types.h index c6ae837986..b81f5338c1 100644 --- a/libs/openzap/src/include/zap_types.h +++ b/libs/openzap/src/include/zap_types.h @@ -224,7 +224,8 @@ typedef enum { typedef enum { ZAP_SPAN_CONFIGURED = (1 << 0), - ZAP_SPAN_READY = (1 << 1) + ZAP_SPAN_READY = (1 << 1), + ZAP_SPAN_STATE_CHANGE = (1 << 2) } zap_span_flag_t; typedef enum { @@ -258,10 +259,13 @@ typedef enum { ZAP_CHANNEL_STATE_DIALING, ZAP_CHANNEL_STATE_GET_CALLERID, ZAP_CHANNEL_STATE_CALLWAITING, + ZAP_CHANNEL_STATE_TERMINATING, + ZAP_CHANNEL_STATE_RESTART, ZAP_CHANNEL_STATE_INVALID } zap_channel_state_t; #define CHANNEL_STATE_STRINGS "DOWN", "UP", "HANGUP", "HOLD", "DIALTONE", "COLLECT", \ - "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", "INVALID" + "RING", "BUSY", "ATTN", "IDLE", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \ + "TERMINATING", "RESTART", "INVALID" ZAP_STR2ENUM_P(zap_str2zap_channel_state, zap_channel_state2str, zap_channel_state_t) typedef enum { @@ -285,7 +289,6 @@ typedef enum { ZAP_CHANNEL_CALLERID_DETECT = (1 << 17) } zap_channel_flag_t; - typedef struct zap_channel zap_channel_t; typedef struct zap_event zap_event_t; typedef struct zap_sigmsg zap_sigmsg_t; diff --git a/libs/openzap/src/isdn/Q931api.c b/libs/openzap/src/isdn/Q931api.c index 1ac2a56b96..2e4e0063a6 100644 --- a/libs/openzap/src/isdn/Q931api.c +++ b/libs/openzap/src/isdn/Q931api.c @@ -518,8 +518,8 @@ L3INT Q931Disconnect(Q931_TrunkInfo_t *pTrunk, L3INT iTo, L3INT iCRV, L3INT iCau L3INT Q931ReleaseComplete(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) { Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_RESTART_ACKNOWLEDGE; - + ptr->MesType = Q931mes_RELEASE_COMPLETE; + ptr->CRVFlag = !(ptr->CRVFlag); return Q931Tx32(pTrunk,buf,ptr->Size); } @@ -528,7 +528,10 @@ L3INT Q931AckRestart(Q931_TrunkInfo_t *pTrunk, L3UCHAR *buf) L3INT RetCode; Q931mes_Header *ptr = (Q931mes_Header*)&buf[Q931L4HeaderSpace]; - ptr->MesType = Q931mes_RELEASE_COMPLETE; + ptr->MesType = Q931mes_RESTART_ACKNOWLEDGE; + if (ptr->CRV) { + ptr->CRVFlag = !(ptr->CRVFlag); + } RetCode = Q931Proc[pTrunk->Dialect][ptr->MesType](pTrunk, buf, 4); diff --git a/libs/openzap/src/isdn/Q931ie.c b/libs/openzap/src/isdn/Q931ie.c index 9e2f687206..0ea4251dbf 100644 --- a/libs/openzap/src/isdn/Q931ie.c +++ b/libs/openzap/src/isdn/Q931ie.c @@ -715,19 +715,22 @@ L3INT Q931Uie_CalledNum(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHAR pie->TypNum = (IBuf[Octet+Off] >> 4) & 0x07; pie->NumPlanID = IBuf[Octet+Off] & 0x0f; Octet ++; - + /* Octet 4*/ - for (x = 0; x < IESize - 1; x++) - { + x=0; + do{ pie->Digit[x] = IBuf[Octet+Off] & 0x7f; Off++; - } + x++; + } while((IBuf[Octet+Off]&0x80) == 0 && Q931MoreIE()); + + pie->Digit[x] = '\0'; Q931SetIE(*pIE, *OOff); *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CalledNum) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CalledNum) + x - 1); + *OOff = (*OOff) + sizeof(Q931ie_CalledNum) + x; + pie->Size = (L3UCHAR)(sizeof(Q931ie_CalledNum) + x); return Q931E_NO_ERROR; } @@ -824,15 +827,17 @@ L3INT Q931Uie_CallingNum(Q931_TrunkInfo_t *pTrunk, Q931mes_Generic *pMsg, L3UCHA pie->Digit[x] = IBuf[Octet+Off] & 0x7f; Off++; x++; - }while((IBuf[Octet+Off]&0x80) == 0 && Q931MoreIE()); + } while((IBuf[Octet+Off]&0x80) == 0 && Q931MoreIE()); + + pie->Digit[x] = '\0'; Q931IESizeTest(Q931E_CALLINGNUM); Q931SetIE(*pIE, *OOff); *IOff = (*IOff) + Octet + Off; - *OOff = (*OOff) + sizeof(Q931ie_CallingNum) + x - 1; - pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingNum) + x - 1); + *OOff = (*OOff) + sizeof(Q931ie_CallingNum) + x; + pie->Size = (L3UCHAR)(sizeof(Q931ie_CallingNum) + x); return Q931E_NO_ERROR; } diff --git a/libs/openzap/src/priserver.c b/libs/openzap/src/priserver.c index 57c29146c2..6bb5e02965 100644 --- a/libs/openzap/src/priserver.c +++ b/libs/openzap/src/priserver.c @@ -180,7 +180,7 @@ static void launch_channel(struct sangoma_pri *spri, int channo) close(file); //close(ifd); - + pri_hangup(spri->pri, channo, 16); if (zap_channel_close(&chan) != ZAP_SUCCESS) { printf("Critical Error: Failed to close channel [%s]\n", chan->last_error); } diff --git a/libs/openzap/src/zap_analog.c b/libs/openzap/src/zap_analog.c index 7bca77d10a..0ad28c92bd 100644 --- a/libs/openzap/src/zap_analog.c +++ b/libs/openzap/src/zap_analog.c @@ -307,6 +307,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) if (done) { zap_set_state_locked(chan, ZAP_CHANNEL_STATE_UP); zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE); + zap_clear_flag_locked(chan->span, ZAP_SPAN_STATE_CHANGE); chan->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0; } } @@ -328,6 +329,7 @@ static void *zap_analog_channel_run(zap_thread_t *me, void *obj) } } else { zap_clear_flag_locked(chan, ZAP_CHANNEL_STATE_CHANGE); + zap_clear_flag_locked(chan->span, ZAP_SPAN_STATE_CHANGE); indicate = 0; state_counter = 0; zap_log(ZAP_LOG_DEBUG, "Executing state handler for %s\n", zap_channel_state2str(chan->state)); @@ -631,6 +633,7 @@ static zap_status_t process_event(zap_span_t *span, zap_event_t *event) if (event->channel->state == ZAP_CHANNEL_STATE_CALLWAITING) { zap_set_state_locked(event->channel, ZAP_CHANNEL_STATE_UP); zap_clear_flag_locked(event->channel, ZAP_CHANNEL_STATE_CHANGE); + zap_clear_flag_locked(event->channel->span, ZAP_SPAN_STATE_CHANGE); event->channel->detected_tones[ZAP_TONEMAP_CALLWAITING_ACK] = 0; } diff --git a/libs/openzap/src/zap_io.c b/libs/openzap/src/zap_io.c index 82d6706134..8f5e0d08f6 100644 --- a/libs/openzap/src/zap_io.c +++ b/libs/openzap/src/zap_io.c @@ -511,26 +511,35 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta zap_mutex_lock(zchan->mutex); - if (zchan->state == ZAP_CHANNEL_STATE_DOWN) { - - switch(state) { - case ZAP_CHANNEL_STATE_BUSY: - ok = 0; - break; - default: - break; - } + if (!zap_test_flag(zchan, ZAP_CHANNEL_READY)) { + return ZAP_FAIL; } - if (zchan->state == ZAP_CHANNEL_STATE_BUSY) { - - switch(state) { - case ZAP_CHANNEL_STATE_UP: - ok = 0; - break; - default: - break; + switch(zchan->state) { + case ZAP_CHANNEL_STATE_DOWN: + { + switch(state) { + case ZAP_CHANNEL_STATE_BUSY: + case ZAP_CHANNEL_STATE_HANGUP: + case ZAP_CHANNEL_STATE_TERMINATING: + ok = 0; + break; + default: + break; + } } + case ZAP_CHANNEL_STATE_BUSY: + { + switch(state) { + case ZAP_CHANNEL_STATE_UP: + ok = 0; + break; + default: + break; + } + } + default: + break; } if (state == zchan->state) { @@ -539,6 +548,7 @@ zap_status_t zap_channel_set_state(zap_channel_t *zchan, zap_channel_state_t sta if (ok) { zap_set_flag(zchan, ZAP_CHANNEL_STATE_CHANGE); + zap_set_flag(zchan->span, ZAP_SPAN_STATE_CHANGE); zchan->last_state = zchan->state; zchan->state = state; } diff --git a/libs/openzap/src/zap_isdn.c b/libs/openzap/src/zap_isdn.c index 35b828c387..d114be55d0 100644 --- a/libs/openzap/src/zap_isdn.c +++ b/libs/openzap/src/zap_isdn.c @@ -66,52 +66,74 @@ static L3INT zap_isdn_931_34(void *pvt, L2UCHAR *msg, L2INT mlen) zap_span_t *span = (zap_span_t *) pvt; zap_isdn_data_t *data = span->isdn_data; Q931mes_Generic *gen = (Q931mes_Generic *) msg; - + Q931ie_ChanID *chanid = Q931GetIEPtr(gen->ChanID, gen->buf); + int chan_id = chanid->ChanSlot; + zap_channel_t *zchan = NULL; + assert(span != NULL); assert(data != NULL); + + if (chan_id) { + zchan = &span->channels[chan_id]; + } - zap_log(ZAP_LOG_DEBUG, "Yay I got an event! Type:[%d] Size:[%d]\n", gen->MesType, gen->Size); + zap_log(ZAP_LOG_DEBUG, "Yay I got an event! Type:[%02x] Size:[%d]\n", gen->MesType, gen->Size); switch(gen->MesType) { + case Q931mes_RESTART: + { + if (zchan) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RESTART); + } else { + uint32_t i; + for (i = 0; i < span->chan_count; i++) { + zap_set_state_locked((&span->channels[i]), ZAP_CHANNEL_STATE_RESTART); + } + } + } + break; + case Q931mes_RELEASE_COMPLETE: + { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + } + break; + case Q931mes_DISCONNECT: + { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_TERMINATING); + } + break; 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)); + if (zchan->state == ZAP_CHANNEL_STATE_DOWN) { + memset(&zchan->caller_data, 0, sizeof(zchan->caller_data)); - zap_copy_string(zchan->caller_data.cid_num, (char *)callingnum->Digit, callingnum->Size - 3); - zap_copy_string(zchan->caller_data.cid_name, (char *)callingnum->Digit, callingnum->Size - 3); - zap_copy_string(zchan->caller_data.ani, (char *)callingnum->Digit, callingnum->Size - 3); - zap_copy_string(zchan->caller_data.dnis, (char *)callednum->Digit, callednum->Size - 3); + zap_set_string(zchan->caller_data.cid_num, callingnum->Digit); + zap_set_string(zchan->caller_data.cid_name, callingnum->Digit); + zap_set_string(zchan->caller_data.ani, callingnum->Digit); + zap_set_string(zchan->caller_data.dnis, callednum->Digit); - 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)) { + zchan->caller_data.CRV = gen->CRV; + if (cplen > sizeof(zchan->caller_data.raw_data)) { + cplen = sizeof(zchan->caller_data.raw_data); + } + gen->CRVFlag = !(gen->CRVFlag); + memcpy(zchan->caller_data.raw_data, msg, cplen); + zchan->caller_data.raw_data_len = cplen; + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_RING); fail = 0; - } + } } if (fail) { + zap_log(ZAP_LOG_CRIT, "FIX ME!\n"); // add me } @@ -147,39 +169,80 @@ 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) +static __inline__ 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_sigmsg_t sig; + zap_status_t status; zap_log(ZAP_LOG_ERROR, "%d:%d STATE [%s]\n", zchan->span_id, zchan->chan_id, zap_channel_state2str(zchan->state)); + memset(&sig, 0, sizeof(sig)); + sig.chan_id = zchan->chan_id; + sig.span_id = zchan->span_id; + sig.channel = zchan; switch (zchan->state) { + case ZAP_CHANNEL_STATE_RING: + { + sig.event_id = ZAP_SIGEVENT_START; + if ((status = data->sig_cb(&sig) != ZAP_SUCCESS)) { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_HANGUP); + } + + } + break; + case ZAP_CHANNEL_STATE_RESTART: + { + zap_set_state_locked(zchan, ZAP_CHANNEL_STATE_DOWN); + zap_channel_close(&zchan); + } + break; 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; + case ZAP_CHANNEL_STATE_HANGUP: + { + Q931ie_Cause cause; + gen->MesType = Q931mes_DISCONNECT; + cause.IEId = Q931ie_CAUSE; + cause.Size = sizeof(Q931ie_Cause); + cause.CodStand = 0; + cause.Location = 1; + cause.Recom = 1; + cause.Value = zchan->caller_data.hangup_cause; + *cause.Diag = '\0'; + gen->Cause = Q931AppendIE((L3UCHAR *) gen, (L3UCHAR *) &cause); + Q931Rx43(&data->q931, (L3UCHAR *) gen, gen->Size); + } + break; + case ZAP_CHANNEL_STATE_TERMINATING: + { + gen->MesType = Q931mes_RELEASE; + Q931Rx43(&data->q931, (void *)gen, gen->Size); + } default: break; } } -static void check_state(zap_span_t *span) +static __inline__ 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); + if (zap_test_flag(span, ZAP_SPAN_STATE_CHANGE)) { + 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); + } } + zap_clear_flag_locked(span, ZAP_SPAN_STATE_CHANGE); } }