?? q931.c
字號:
static char *pri_causeclass2str(int cause){ static struct msgtype causeclasses[] = { { 0, "Normal Event" }, { 1, "Normal Event" }, { 2, "Network Congestion" }, { 3, "Service or Option not Available" }, { 4, "Service or Option not Implemented" }, { 5, "Invalid message" }, { 6, "Protocol Error" }, { 7, "Interworking" }, }; return code2str(cause, causeclasses, sizeof(causeclasses) / sizeof(causeclasses[0]));}static FUNC_DUMP(dump_cause){ int x; pri_message("%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n", prefix, len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5, (ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf); pri_message("%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n", prefix, (ie->data[1] >> 7), pri_cause2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, pri_causeclass2str((ie->data[1] & 0x7f) >> 4), (ie->data[1] & 0x7f) >> 4); for (x=2;x<ie->len;x++) pri_message("%c Cause data %d: %02x (%d)\n", prefix, x-1, ie->data[x], ie->data[x]);}static FUNC_RECV(receive_cause){ call->causeloc = ie->data[0] & 0xf; call->causecode = (ie->data[0] & 0x60) >> 5; call->cause = (ie->data[1] & 0x7f); return 0;}static FUNC_SEND(transmit_cause){ if (call->cause > 0) { ie->data[0] = 0x80 | (call->causecode << 5) | (call->causeloc); ie->data[1] = 0x80 | (call->cause); return 4; } else { /* Leave off */ return 0; }}static FUNC_DUMP(dump_sending_complete){ pri_message("%c Sending Complete (len=%2d)\n", prefix, len);}static FUNC_RECV(receive_sending_complete){ /* We've got a "Complete" message: Exect no further digits. */ call->complete = 1; return 0;}static FUNC_SEND(transmit_sending_complete){ if ((pri->overlapdial && call->complete) || /* Explicit */ (!pri->overlapdial && ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) || /* Implicit */ (pri->switchtype == PRI_SWITCH_EUROISDN_T1)))) { /* Include this single-byte IE */ return 1; } return 0;}static char *notify2str(int info){ /* ITU-T Q.763 */ static struct msgtype notifies[] = { { PRI_NOTIFY_USER_SUSPENDED, "User suspended" }, { PRI_NOTIFY_USER_RESUMED, "User resumed" }, { PRI_NOTIFY_BEARER_CHANGE, "Bearer service change (DSS1)" }, { PRI_NOTIFY_ASN1_COMPONENT, "ASN.1 encoded component (DSS1)" }, { PRI_NOTIFY_COMPLETION_DELAY, "Call completion delay" }, { PRI_NOTIFY_CONF_ESTABLISHED, "Conference established" }, { PRI_NOTIFY_CONF_DISCONNECTED, "Conference disconnected" }, { PRI_NOTIFY_CONF_PARTY_ADDED, "Other party added" }, { PRI_NOTIFY_CONF_ISOLATED, "Isolated" }, { PRI_NOTIFY_CONF_REATTACHED, "Reattached" }, { PRI_NOTIFY_CONF_OTHER_ISOLATED, "Other party isolated" }, { PRI_NOTIFY_CONF_OTHER_REATTACHED, "Other party reattached" }, { PRI_NOTIFY_CONF_OTHER_SPLIT, "Other party split" }, { PRI_NOTIFY_CONF_OTHER_DISCONNECTED, "Other party disconnected" }, { PRI_NOTIFY_CONF_FLOATING, "Conference floating" }, { PRI_NOTIFY_WAITING_CALL, "Call is waiting call" }, { PRI_NOTIFY_DIVERSION_ACTIVATED, "Diversion activated (DSS1)" }, { PRI_NOTIFY_TRANSFER_ALERTING, "Call transfer, alerting" }, { PRI_NOTIFY_TRANSFER_ACTIVE, "Call transfer, active" }, { PRI_NOTIFY_REMOTE_HOLD, "Remote hold" }, { PRI_NOTIFY_REMOTE_RETRIEVAL, "Remote retrieval" }, { PRI_NOTIFY_CALL_DIVERTING, "Call is diverting" }, }; return code2str(info, notifies, sizeof(notifies) / sizeof(notifies[0]));}static FUNC_DUMP(dump_notify){ pri_message("%c Notification indicator (len=%2d): Ext: %d %s (%d)\n", prefix, len, ie->data[0] >> 7, notify2str(ie->data[0] & 0x7f), ie->data[0] & 0x7f);}static FUNC_RECV(receive_notify){ call->notify = ie->data[0] & 0x7F; return 0;}static FUNC_SEND(transmit_notify){ if (call->notify >= 0) { ie->data[0] = 0x80 | call->notify; return 3; } return 0;}static FUNC_DUMP(dump_shift){ pri_message("%c %sLocking Shift (len=%02d): Requested codeset %d\n", prefix, (full_ie & 8) ? "Non-" : "", len, full_ie & 7);}static char *lineinfo2str(int info){ /* NAPNA ANI II digits */ static struct msgtype lineinfo[] = { { 0, "Plain Old Telephone Service (POTS)" }, { 1, "Multiparty line (more than 2)" }, { 2, "ANI failure" }, { 6, "Station Level Rating" }, { 7, "Special Operator Handling Required" }, { 20, "Automatic Identified Outward Dialing (AIOD)" }, { 23, "Coing or Non-Coin" }, { 24, "Toll free translated to POTS originated for non-pay station" }, { 25, "Toll free translated to POTS originated from pay station" }, { 27, "Pay station with coin control signalling" }, { 29, "Prison/Inmate Service" }, { 30, "Intercept (blank)" }, { 31, "Intercept (trouble)" }, { 32, "Intercept (regular)" }, { 34, "Telco Operator Handled Call" }, { 52, "Outward Wide Area Telecommunications Service (OUTWATS)" }, { 60, "TRS call from unrestricted line" }, { 61, "Cellular/Wireless PCS (Type 1)" }, { 62, "Cellular/Wireless PCS (Type 2)" }, { 63, "Cellular/Wireless PCS (Roaming)" }, { 66, "TRS call from hotel/motel" }, { 67, "TRS call from restricted line" }, { 70, "Line connected to pay station" }, { 93, "Private virtual network call" }, }; return code2str(info, lineinfo, sizeof(lineinfo) / sizeof(lineinfo[0]));}static FUNC_DUMP(dump_line_information){ pri_message("%c Originating Line Information (len=%02d): %s (%d)\n", prefix, len, lineinfo2str(ie->data[0]), ie->data[0]);}static FUNC_RECV(receive_line_information){ call->ani2 = ie->data[0]; return 0;}static FUNC_SEND(transmit_line_information){#if 0 /* XXX Is this IE possible for 4ESS? XXX */ if(pri->switchtype == PRI_SWITCH_ATT4ESS) { ie->data[0] = 0; return 3; }#endif return 0;}struct ie ies[] = { /* Codeset 0 - Common */ { NATIONAL_CHANGE_STATUS, "Change Status" }, { Q931_LOCKING_SHIFT, "Locking Shift", dump_shift }, { Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability }, { Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause }, { Q931_CALL_STATE, "Call State", dump_call_state, receive_call_state, transmit_call_state }, { Q931_CHANNEL_IDENT, "Channel Identification", dump_channel_id, receive_channel_id, transmit_channel_id }, { Q931_PROGRESS_INDICATOR, "Progress Indicator", dump_progress_indicator, receive_progress_indicator, transmit_progress_indicator }, { Q931_NETWORK_SPEC_FAC, "Network-Specific Facilities", dump_network_spec_fac, receive_network_spec_fac, transmit_network_spec_fac }, { Q931_INFORMATION_RATE, "Information Rate" }, { Q931_TRANSIT_DELAY, "End-to-End Transit Delay" }, { Q931_TRANS_DELAY_SELECT, "Transmit Delay Selection and Indication" }, { Q931_BINARY_PARAMETERS, "Packet-layer Binary Parameters" }, { Q931_WINDOW_SIZE, "Packet-layer Window Size" }, { Q931_CLOSED_USER_GROUP, "Closed User Group" }, { Q931_REVERSE_CHARGE_INDIC, "Reverse Charging Indication" }, { Q931_CALLING_PARTY_NUMBER, "Calling Party Number", dump_calling_party_number, receive_calling_party_number, transmit_calling_party_number }, { Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr, receive_calling_party_subaddr }, { Q931_CALLED_PARTY_NUMBER, "Called Party Number", dump_called_party_number, receive_called_party_number, transmit_called_party_number }, { Q931_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr }, { Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number }, { Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr }, { Q931_TRANSIT_NET_SELECT, "Transit Network Selection" }, { Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator }, { Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" }, { Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" }, { Q931_PACKET_SIZE, "Packet Size" }, { Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility }, { Q931_IE_REDIRECTION_NUMBER, "Redirection Number" }, { Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" }, { Q931_IE_FEATURE_ACTIVATE, "Feature Activation" }, { Q931_IE_INFO_REQUEST, "Feature Request" }, { Q931_IE_FEATURE_IND, "Feature Indication" }, { Q931_IE_SEGMENTED_MSG, "Segmented Message" }, { Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity }, { Q931_IE_ENDPOINT_ID, "Endpoint Identification" }, { Q931_IE_NOTIFY_IND, "Notification Indicator", dump_notify, receive_notify, transmit_notify }, { Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display }, { Q931_IE_TIME_DATE, "Date/Time", dump_time_date }, { Q931_IE_KEYPAD_FACILITY, "Keypad Facility" }, { Q931_IE_SIGNAL, "Signal" }, { Q931_IE_SWITCHHOOK, "Switch-hook" }, { Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user }, { Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" }, { Q931_IE_CALL_STATUS, "Call Status" }, { Q931_IE_CHANGE_STATUS, "Change Status" }, { Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number }, { Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number }, { Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number" }, { Q931_IE_USER_USER_FACILITY, "User-User Facility" }, { Q931_IE_UPDATE, "Update" }, { Q931_SENDING_COMPLETE, "Sending Complete", dump_sending_complete, receive_sending_complete, transmit_sending_complete }, /* Codeset 6 - Network specific */ { Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility }, { Q931_IE_ORIGINATING_LINE_INFO, "Originating Line Information", dump_line_information, receive_line_information, transmit_line_information }, /* Codeset 7 */};static char *ie2str(int ie) { unsigned int x; /* Special handling for Locking/Non-Locking Shifts */ switch (ie & 0xf8) { case Q931_LOCKING_SHIFT: switch (ie & 7) { case 0: return "!! INVALID Locking Shift To Codeset 0"; case 1: return "Locking Shift To Codeset 1"; case 2: return "Locking Shift To Codeset 2"; case 3: return "Locking Shift To Codeset 3"; case 4: return "Locking Shift To Codeset 4"; case 5: return "Locking Shift To Codeset 5"; case 6: return "Locking Shift To Codeset 6"; case 7: return "Locking Shift To Codeset 7"; } case Q931_NON_LOCKING_SHIFT: switch (ie & 7) { case 0: return "Non-Locking Shift To Codeset 0"; case 1: return "Non-Locking Shift To Codeset 1"; case 2: return "Non-Locking Shift To Codeset 2"; case 3: return "Non-Locking Shift To Codeset 3"; case 4: return "Non-Locking Shift To Codeset 4"; case 5: return "Non-Locking Shift To Codeset 5"; case 6: return "Non-Locking Shift To Codeset 6"; case 7: return "Non-Locking Shift To Codeset 7"; } default: for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++) if (ie == ies[x].ie) return ies[x].name; return "Unknown Information Element"; }} static inline unsigned int ielen(q931_ie *ie){ if ((ie->ie & 0x80) != 0) return 1; else return 2 + ie->len;}static char *msg2str(int msg){ unsigned int x; for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++) if (msgs[x].msgnum == msg) return msgs[x].name; return "Unknown Message Type";}static inline int q931_cr(q931_h *h){ int cr = 0; int x; if (h->crlen > 3) { pri_error("Call Reference Length Too long: %d\n", h->crlen); return -1; } switch (h->crlen) { case 2: for (x=0;x<h->crlen;x++) { cr <<= 8; cr |= h->crv[x]; } break; case 1: cr = h->crv[0]; if (cr & 0x80) { cr &= ~0x80; cr |= 0x8000; } break; default: pri_error("Call Reference Length not supported: %d\n", h->crlen); } return cr;}static inline void q931_dumpie(int codeset, q931_ie *ie, char prefix){ unsigned int x; int full_ie = Q931_FULL_IE(codeset, ie->ie); int base_ie; pri_message("%c [", prefix); pri_message("%02x", ie->ie); if (!(ie->ie & 0x80)) { pri_message(" %02x", ielen(ie)-2); for (x = 0; x + 2 < ielen(ie); ++x) pri_message(" %02x", ie->data[x]); } pri_message("]\n"); /* Special treatment for shifts */ if((full_ie & 0xf0) == Q931_LOCKING_SHIFT) full_ie &= 0xff; base_ie = (((full_ie & ~0x7f) == Q931_FULL_IE(0, 0x80)) && ((full_ie & 0x70) != 0x20)) ? full_ie & ~0x0f : full_ie; for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++) if (ies[x].ie == base_ie) { if (ies[x].dump) ies[x].dump(full_ie, ie, ielen(ie), prefix); else pri_message("%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie)); return; } pri_error("!! %c Unknown IE %d (len = %d)\n", prefix, base_ie, ielen(ie));}static q931_call *q931_getcall(struct pri *pri, int cr){ q931_call *cur, *prev; cur = *pri->callpool; prev = NULL; while(cur) { if (cur->cr == cr) return cur; prev = cur; cur = cur->next; } /* No call exists, make a new one */ if (pri->debug & PRI_DEBUG_Q931_STATE) pri_message("-- Making new call for cr %d\n", cr); cur = malloc(sizeof(struct q931_call)); if (cur) { call_init(cur); /* Call reference */ cur->cr = cr; cur->pri = pri; /* Append to end of list */ if (prev) prev->next = cur; else *pri->callpool = cur; } return cur;}q931_call *q931_new_call(struct pri *pri){ q931_call *cur; do { cur = *pri->callpool; pri->cref++; if (pri->cref > 32767) pri->cref = 1; while(cur) { if (cur->cr == (0x8000 | pri->cref)) break; cur = cur->next; } } while(cur); return q931_getcall(pri, pri->cref | 0x8000);}static void q931_destroy(struct pri *pri, int cr, q931_call *c){
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -