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);
}
}
}
}
-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,
/*.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,
/*.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,
/*.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,
#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)); \
char dnis[25];
char rdnis[25];
int CRV;
+ int hangup_cause;
uint8_t raw_data[1024];
uint32_t raw_data_len;
};
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 {
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 {
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;
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);
}
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);
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;
}
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;
}
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);
}
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;
}
}
}
} 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));
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;
}
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) {
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;
}
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));
-
- 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);
-
- 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)) {
+ if (zchan->state == ZAP_CHANNEL_STATE_DOWN) {
+ memset(&zchan->caller_data, 0, sizeof(zchan->caller_data));
+
+ 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);
+ }
+ 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
}
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);
}
}