📄 q931.c
字号:
case Q931_PROG_CALLER_RETURNED_TO_ISDN: call->progressmask |= PRI_PROG_CALLER_RETURNED_TO_ISDN; break; case Q931_PROG_INBAND_AVAILABLE: call->progressmask |= PRI_PROG_INBAND_AVAILABLE; break; case Q931_PROG_DELAY_AT_INTERF: call->progressmask |= PRI_PROG_DELAY_AT_INTERF; break; case Q931_PROG_INTERWORKING_WITH_PUBLIC: call->progressmask |= PRI_PROG_INTERWORKING_WITH_PUBLIC; break; case Q931_PROG_INTERWORKING_NO_RELEASE: call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE; break; case Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER: call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER; break; case Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER: call->progressmask |= PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER; break; default: pri_error(pri, "XXX Invalid Progress indicator value received: %02x\n",(ie->data[1] & 0x7f)); break; } return 0;}static FUNC_SEND(transmit_facility){ struct apdu_event *tmp; int i = 0; for (tmp = call->apdus; tmp; tmp = tmp->next) { if ((tmp->message == msgtype) && !tmp->sent) break; } if (!tmp) /* No APDU found */ return 0; if (tmp->apdu_len > 235) { /* TODO: find out how much space we can use */ pri_message(pri, "Requested APDU (%d bytes) is too long\n", tmp->apdu_len); return 0; } memcpy(&ie->data[i], tmp->apdu, tmp->apdu_len); i += tmp->apdu_len; tmp->sent = 1; return i + 2;}static FUNC_RECV(receive_facility){ int i = 0; int protocol, next_protocol; struct rose_component *comp = NULL; enum { Q932_STATE_NFE, /* Network facility extension */ Q932_STATE_NPP, /* Network protocol profile */ Q932_STATE_INTERPRETATION, /* Interpretation component */ Q932_STATE_SERVICE /* Service component(s) */ } state = Q932_STATE_SERVICE;#define Q932_HANDLE_PROC(component, my_state, name, handler) \ case component: \ if(state > my_state) { \ pri_error(pri, "!! %s component received in wrong place\n"); \ break; \ } \ state = my_state; \ if (pri->debug) \ pri_message(pri, "Handle Q.932 %s component\n", name); \ (handler)(pri, call, ie, comp->data, comp->len); \ break;#define Q932_HANDLE_NULL(component, my_state, name, handle) \ case component: \ if(state > my_state) { \ pri_error(pri, "!! %s component received in wrong place\n"); \ break; \ } \ state = my_state; \ if (pri->debug & PRI_DEBUG_APDU) \ pri_message(pri, "Q.932 %s component is not handled\n", name); \ break; if (ie->len < 1) return -1; switch(next_protocol = protocol = (ie->data[i] & 0x1f)) { case Q932_PROTOCOL_CMIP: case Q932_PROTOCOL_ACSE: if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "!! Don't know how to handle Q.932 Protocol Profile of type 0x%X\n", protocol); return -1; case Q932_PROTOCOL_EXTENSIONS: state = Q932_STATE_NFE; next_protocol = Q932_PROTOCOL_ROSE; break; case Q932_PROTOCOL_ROSE: break; default: pri_error(pri, "!! Invalid Q.932 Protocol Profile of type 0x%X received\n", protocol); return -1; } /* Service indicator octet - Just ignore for now */ if (!(ie->data[i] & 0x80)) i++; i++; if (ie->len < 3) return -1; while ((i+1 < ie->len) && (&ie->data[i])) { comp = (struct rose_component*)&ie->data[i]; if (comp->type) { if (protocol == Q932_PROTOCOL_EXTENSIONS) { switch (comp->type) { Q932_HANDLE_NULL(COMP_TYPE_INTERPRETATION, Q932_STATE_INTERPRETATION, "Interpretation", NULL); Q932_HANDLE_NULL(COMP_TYPE_NFE, Q932_STATE_NFE, "Network facility extensions", NULL); Q932_HANDLE_NULL(COMP_TYPE_NETWORK_PROTOCOL_PROFILE, Q932_STATE_NPP, "Network protocol profile", NULL); default: protocol = next_protocol; break; } } switch (protocol) { case Q932_PROTOCOL_ROSE: switch (comp->type) { Q932_HANDLE_PROC(COMP_TYPE_INVOKE, Q932_STATE_SERVICE, "ROSE Invoke", rose_invoke_decode); Q932_HANDLE_PROC(COMP_TYPE_RETURN_RESULT, Q932_STATE_SERVICE, "ROSE return result", rose_return_result_decode); Q932_HANDLE_PROC(COMP_TYPE_RETURN_ERROR, Q932_STATE_SERVICE, "ROSE return error", rose_return_error_decode); Q932_HANDLE_PROC(COMP_TYPE_REJECT, Q932_STATE_SERVICE, "ROSE reject", rose_reject_decode); default: if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Don't know how to handle ROSE component of type 0x%X\n", comp->type); break; } break; case Q932_PROTOCOL_CMIP: switch (comp->type) { default: if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Don't know how to handle CMIP component of type 0x%X\n", comp->type); break; } break; case Q932_PROTOCOL_ACSE: switch (comp->type) { default: if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Don't know how to handle ACSE component of type 0x%X\n", comp->type); break; } break; } } i += (comp->len + 2); }#undef Q932_HANDLE return 0;}static FUNC_SEND(transmit_progress_indicator){ int code, mask; /* Can't send progress indicator on GR-303 -- EVER! */ if (pri->subchannel && !pri->bri) return 0; if (call->progressmask > 0) { if (call->progressmask & (mask = PRI_PROG_CALL_NOT_E2E_ISDN)) code = Q931_PROG_CALL_NOT_E2E_ISDN; else if (call->progressmask & (mask = PRI_PROG_CALLED_NOT_ISDN)) code = Q931_PROG_CALLED_NOT_ISDN; else if (call->progressmask & (mask = PRI_PROG_CALLER_NOT_ISDN)) code = Q931_PROG_CALLER_NOT_ISDN; else if (call->progressmask & (mask = PRI_PROG_INBAND_AVAILABLE)) code = Q931_PROG_INBAND_AVAILABLE; else if (call->progressmask & (mask = PRI_PROG_DELAY_AT_INTERF)) code = Q931_PROG_DELAY_AT_INTERF; else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_WITH_PUBLIC)) code = Q931_PROG_INTERWORKING_WITH_PUBLIC; else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_NO_RELEASE)) code = Q931_PROG_INTERWORKING_NO_RELEASE; else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER)) code = Q931_PROG_INTERWORKING_NO_RELEASE_PRE_ANSWER; else if (call->progressmask & (mask = PRI_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER)) code = Q931_PROG_INTERWORKING_NO_RELEASE_POST_ANSWER; else { code = 0; pri_error(pri, "XXX Undefined progress bit: %x\n", call->progressmask); } if (code) { ie->data[0] = 0x80 | (call->progcode << 5) | (call->progloc); ie->data[1] = 0x80 | code; call->progressmask &= ~mask; return 4; } } /* Leave off */ return 0;}static FUNC_SEND(transmit_call_state){ if (call->ourcallstate > -1 ) { ie->data[0] = call->ourcallstate; return 3; } return 0;}static FUNC_RECV(receive_call_state){ call->sugcallstate = ie->data[0] & 0x3f; return 0;}static char *callstate2str(int callstate){ static struct msgtype callstates[] = { { 0, "Null" }, { 1, "Call Initiated" }, { 2, "Overlap sending" }, { 3, "Outgoing call Proceeding" }, { 4, "Call Delivered" }, { 6, "Call Present" }, { 7, "Call Received" }, { 8, "Connect Request" }, { 9, "Incoming Call Proceeding" }, { 10, "Active" }, { 11, "Disconnect Request" }, { 12, "Disconnect Indication" }, { 15, "Suspend Request" }, { 17, "Resume Request" }, { 19, "Release Request" }, { 22, "Call Abort" }, { 25, "Overlap Receiving" }, { 61, "Restart Request" }, { 62, "Restart" }, }; return code2str(callstate, callstates, sizeof(callstates) / sizeof(callstates[0]));}static FUNC_DUMP(dump_call_state){ pri_message(pri, "%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n", prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0xC0) >> 6), (ie->data[0] & 0xC0) >> 6, callstate2str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);}static FUNC_DUMP(dump_call_identity){ int x; pri_message(pri, "%c Call Identity (len=%2d) [ ", prefix, len); for (x=0;x<ie->len;x++) pri_message(pri, "0x%02X ", ie->data[x]); pri_message(pri, " ]\n");}static FUNC_DUMP(dump_time_date){ pri_message(pri, "%c Time Date (len=%2d) [ ", prefix, len); if (ie->len > 0) pri_message(pri, "%02d", ie->data[0]); if (ie->len > 1) pri_message(pri, "-%02d", ie->data[1]); if (ie->len > 2) pri_message(pri, "-%02d", ie->data[2]); if (ie->len > 3) pri_message(pri, " %02d", ie->data[3]); if (ie->len > 4) pri_message(pri, ":%02d", ie->data[4]); if (ie->len > 5) pri_message(pri, ":%02d", ie->data[5]); pri_message(pri, " ]\n");}static FUNC_DUMP(dump_keypad_facility){ char tmp[64]; if (ie->len == 0 || ie->len > sizeof(tmp)) return; memcpy(tmp, ie->data, ie->len); tmp[ie->len] = '\0'; pri_message(pri, "%c Keypad Facility (len=%2d) [ %s ]\n", prefix, ie->len, tmp );}static FUNC_RECV(receive_keypad_facility){ int mylen; if (ie->len == 0) return -1; if (ie->len > (sizeof(call->keypad_digits) - 1)) mylen = (sizeof(call->keypad_digits) - 1); else mylen = ie->len; memcpy(call->keypad_digits, ie->data, mylen); call->keypad_digits[mylen] = 0; return 0;}static FUNC_SEND(transmit_keypad_facility){ int sublen; sublen = strlen(call->keypad_digits); if (sublen > 32) { sublen = 32; call->keypad_digits[32] = '\0'; } if (sublen) { libpri_copy_string((char *)ie->data, (char *)call->keypad_digits, sizeof(call->keypad_digits)); /* Make sure we clear the field */ call->keypad_digits[0] = '\0'; return sublen + 2; } else return 0;}static FUNC_DUMP(dump_display){ int x, y; char *buf = malloc(len + 1); char tmp[80] = ""; if (buf) { x=y=0; if ((x < ie->len) && (ie->data[x] & 0x80)) { sprintf(tmp, "Charset: %02x ", ie->data[x] & 0x7f); ++x; } for (y=x; x<ie->len; x++) buf[x] = ie->data[x] & 0x7f; buf[x] = '\0'; pri_message(pri, "%c Display (len=%2d) %s[ %s ]\n", prefix, ie->len, tmp, &buf[y]); free(buf); }}#define CHECK_OVERFLOW(limit) \ if (tmpptr - tmp + limit >= sizeof(tmp)) { \ *tmpptr = '\0'; \ pri_message(pri, "%s", tmpptr = tmp); \ }static void dump_ie_data(struct pri *pri, unsigned char *c, int len){ static char hexs[16] = "0123456789ABCDEF"; char tmp[1024], *tmpptr; int lastascii = 0; tmpptr = tmp; for (; len; --len, ++c) { CHECK_OVERFLOW(7); if (isprint(*c)) { if (!lastascii) { if (tmpptr != tmp) { *tmpptr++ = ','; *tmpptr++ = ' '; } *tmpptr++ = '\''; lastascii = 1; } *tmpptr++ = *c; } else { if (lastascii) { *tmpptr++ = '\''; lastascii = 0; } if (tmpptr != tmp) { *tmpptr++ = ','; *tmpptr++ = ' '; } *tmpptr++ = '0'; *tmpptr++ = 'x'; *tmpptr++ = hexs[(*c >> 4) & 0x0f]; *tmpptr++ = hexs[(*c) & 0x0f]; } } if (lastascii) *tmpptr++ = '\''; *tmpptr = '\0'; pri_message(pri, "%s", tmp);}static FUNC_DUMP(dump_facility){ int dataat = (ie->data[0] & 0x80) ? 1 : 2; pri_message(pri, "%c Facility (len=%2d, codeset=%d) [ ", prefix, len, Q931_IE_CODESET(full_ie)); dump_ie_data(pri, ie->data, ie->len); pri_message(NULL, " ]\n"); if (ie->len > 1) { pri_message(pri, "PROTOCOL %02X\n", ie->data[0] & ASN1_TYPE_MASK); asn1_dump(pri, &ie->data[dataat], ie->len - dataat); }}static FUNC_DUMP(dump_network_spec_fac){ pri_message(pri, "%c Network-Specific Facilities (len=%2d) [ ", prefix, ie->len); if (ie->data[0] == 0x00) { pri_message(pri, "%s", code2str(ie->data[1], facilities, sizeof(facilities) / sizeof(facilities[0]))); } else dump_ie_data(pri, ie->data, ie->len); pri_message(pri, " ]\n");}static FUNC_RECV(receive_network_spec_fac){ return 0;}static FUNC_SEND(transmit_network_spec_fac){ /* We are ready to transmit single IE only */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -