Index: libpri.h =================================================================== RCS file: /usr/cvsroot/libpri/libpri.h,v retrieving revision 1.40 diff -u -r1.40 libpri.h --- libpri.h 17 Jan 2005 12:58:05 -0000 1.40 +++ libpri.h 4 Feb 2005 19:31:56 -0000 @@ -73,6 +73,8 @@ #define PRI_EVENT_HANGUP_REQ 15 /* Requesting the higher layer to hangup */ #define PRI_EVENT_NOTIFY 16 /* Notification received */ #define PRI_EVENT_PROGRESS 17 /* When we get CALL_PROCEEDING or PROGRESS */ +#define PRI_EVENT_SERVICE 18 /* ANSI T1.607 Maintenance */ +#define PRI_EVENT_SERVICE_ACK 19 /* ANSI T1.607 Maintenance */ /* Simple states */ #define PRI_STATE_DOWN 0 @@ -346,6 +348,18 @@ int info; } pri_event_notify; +typedef struct pri_event_service { + int e; + int channel; + int changestatus; +} pri_event_service; + +typedef struct pri_event_service_ack { + int e; + int channel; + int changestatus; +} pri_event_service_ack; + typedef union { int e; pri_event_generic gen; /* Generic view */ @@ -360,6 +374,8 @@ pri_event_proceeding proceeding; /* Call proceeding & Progress */ pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */ pri_event_notify notify; /* Notification */ + pri_event_service service; /* ANSI T1.607 Maintenance */ + pri_event_service_ack service_ack; /* ANSI T1.607 Maintenance */ } pri_event; struct pri; @@ -446,6 +462,9 @@ extern void pri_destroycall(struct pri *pri, q931_call *call); extern int pri_reset(struct pri *pri, int channel); + +/* Handle ANSI T1.607 maintenance messages for putting B-Channels (and eventually D-Channels) in and out of service */ +extern int pri_maintenance_service(struct pri *pri, int channel, int changestatus); /* Create a new call */ extern q931_call *pri_new_call(struct pri *pri); Index: pri.c =================================================================== RCS file: /usr/cvsroot/libpri/pri.c,v retrieving revision 1.31 diff -u -r1.31 pri.c --- pri.c 15 Dec 2004 20:15:28 -0000 1.31 +++ pri.c 4 Feb 2005 19:31:56 -0000 @@ -416,6 +416,13 @@ return q931_restart(pri, channel); } +int pri_maintenance_service(struct pri *pri, int channel, int changestatus) +{ + if (!pri) + return -1; + return t1607_maintenance_service(pri, channel, changestatus); +} + q931_call *pri_new_call(struct pri *pri) { if (!pri) Index: pri_internal.h =================================================================== RCS file: /usr/cvsroot/libpri/pri_internal.h,v retrieving revision 1.16 diff -u -r1.16 pri_internal.h --- pri_internal.h 3 Feb 2005 22:14:44 -0000 1.16 +++ pri_internal.h 4 Feb 2005 19:31:56 -0000 @@ -202,6 +202,7 @@ int useruserprotocoldisc; char useruserinfo[256]; char callingsubaddr[256]; /* Calling parties sub address */ + int changestatus; /* Maintenance service related */ }; extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data); Index: pri_q931.h =================================================================== RCS file: /usr/cvsroot/libpri/pri_q931.h,v retrieving revision 1.19 diff -u -r1.19 pri_q931.h --- pri_q931.h 5 Nov 2004 02:12:02 -0000 1.19 +++ pri_q931.h 4 Feb 2005 19:31:57 -0000 @@ -108,6 +108,8 @@ #define Q931_PROTOCOL_DISCRIMINATOR 0x08 #define GR303_PROTOCOL_DISCRIMINATOR 0x4f +#define T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR 0x3 +#define T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO 0x43 /* Q.931 / National ISDN Message Types */ @@ -151,12 +153,9 @@ #define Q931_SUSPEND_ACKNOWLEDGE 0x2d #define Q931_SUSPEND_REJECT 0x21 -/* Maintenance messages (codeset 0 only) */ -#define NATIONAL_SERVICE 0x0f -#define NATIONAL_SERVICE_ACKNOWLEDGE 0x07 - -/* Special codeset 0 IE */ -#define NATIONAL_CHANGE_STATUS 0x1 +/* Maintenance messages (codeset 0) */ +#define T1607_MAINTENANCE_SERVICE 0x0f +#define T1607_MAINTENANCE_SERVICE_ACKNOWLEDGE 0x07 /* Q.931 / National ISDN Information Elements */ #define Q931_LOCKING_SHIFT 0x90 @@ -193,7 +192,6 @@ #define Q931_DISPLAY 0x28 #define Q931_IE_SEGMENTED_MSG 0x00 -#define Q931_IE_CHANGE_STATUS 0x01 #define Q931_IE_ORIGINATING_LINE_INFO (0x01 | Q931_CODESET(6)) #define Q931_IE_CONNECTED_ADDR 0x0C #define Q931_IE_CONNECTED_NUM 0x4C @@ -218,6 +216,13 @@ #define Q931_IE_USER_USER 0x7E #define Q931_IE_ESCAPE_FOR_EXT 0x7F +/* For maintenance service */ +#define T1607_IE_CHANGE_STATUS 0x05 +#define T1607_CHANGE_STATUS_IN_SERVICE 0 +#define T1607_CHANGE_STATUS_LOOP_BACK 1 +#define T1607_CHANGE_STATUS_OUT_OF_SERVICE 2 +#define T1607_CHANGE_STATUS_REQ_CONTINUITY_CHECK 3 +#define T1607_CHANGE_STATUS_GRACEFUL_SHUTDOWN 4 /* Call state stuff */ #define Q931_CALL_STATE_NULL 0 @@ -242,6 +247,10 @@ /* EuroISDN */ #define Q931_SENDING_COMPLETE 0xa1 + +extern int t1607_maintenance_service(struct pri *pri, int channel, int changestatus); + +extern int t1607_maintenance_service_ack(struct pri *pri, q931_call *call); extern int q931_receive(struct pri *pri, q931_h *h, int len); Index: q931.c =================================================================== RCS file: /usr/cvsroot/libpri/q931.c,v retrieving revision 1.113 diff -u -r1.113 q931.c --- q931.c 3 Feb 2005 22:14:44 -0000 1.113 +++ q931.c 4 Feb 2005 19:32:00 -0000 @@ -83,10 +83,12 @@ { Q931_SUSPEND, "SUSPEND" }, { Q931_SUSPEND_ACKNOWLEDGE, "SUSPEND ACKNOWLEDGE" }, { Q931_SUSPEND_REJECT, "SUSPEND REJECT" }, +}; +struct msgtype t1607_msgs[] = { /* Maintenance */ - { NATIONAL_SERVICE, "SERVICE" }, - { NATIONAL_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" }, + { T1607_MAINTENANCE_SERVICE, "SERVICE" }, + { T1607_MAINTENANCE_SERVICE_ACKNOWLEDGE, "SERVICE ACKNOWLEDGE" }, }; struct msgtype causes[] = { @@ -929,6 +931,27 @@ return 0; } +static FUNC_DUMP(dump_change_status) +{ + int x; + pri_message("%c Change Status Information (len=%2d) [", prefix, len); + for (x=0;xlen;x++) + pri_message(" %02x", ie->data[x] & 0x7f); + pri_message(" ]\n"); +} + +static FUNC_RECV(receive_change_status) +{ + call->changestatus = ie->data[0] & 0x7f; + return 0; +} + +static FUNC_SEND(transmit_change_status) +{ + ie->data[0] = 0x80 | call->changestatus; + return 3; +} + static char *prog2str(int prog) { static struct msgtype progs[] = { @@ -1961,7 +1984,7 @@ struct ie ies[] = { /* Codeset 0 - Common */ - { 1, NATIONAL_CHANGE_STATUS, "Change Status" }, + { 1, T1607_IE_CHANGE_STATUS, "Change Status", dump_change_status, receive_change_status, transmit_change_status }, { 0, Q931_LOCKING_SHIFT, "Locking Shift", dump_shift }, { 0, Q931_BEARER_CAPABILITY, "Bearer Capability", dump_bearer_capability, receive_bearer_capability, transmit_bearer_capability }, { 0, Q931_CAUSE, "Cause", dump_cause, receive_cause, transmit_cause }, @@ -2005,7 +2028,6 @@ { 1, Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user }, { 1, Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" }, { 1, Q931_IE_CALL_STATUS, "Call Status" }, - { 1, Q931_IE_CHANGE_STATUS, "Change Status" }, { 1, Q931_IE_CONNECTED_ADDR, "Connected Number", dump_connected_number }, { 1, Q931_IE_CONNECTED_NUM, "Connected Number", dump_connected_number }, { 1, Q931_IE_ORIGINAL_CALLED_NUMBER, "Original Called Number", dump_redirecting_number, receive_redirecting_number, transmit_redirecting_number }, @@ -2017,7 +2039,7 @@ { 1, Q931_IE_FACILITY | Q931_CODESET(6), "Facility", dump_facility, receive_facility, transmit_facility }, { 1, Q931_DISPLAY | Q931_CODESET(6), "Display (CS6)", dump_display, receive_display, transmit_display }, { 0, Q931_IE_GENERIC_DIGITS, "Generic Digits", dump_generic_digits, receive_generic_digits, transmit_generic_digits }, - /* Codeset 7 */ + /* Codeset 7 - User specific */ }; static char *ie2str(int ie) @@ -2089,6 +2111,15 @@ return "Unknown Message Type"; } +static char *t1607_msg2str(int msg) +{ + unsigned int x; + for (x=0;xcrlen, q931_cr(h) & 0x7FFF, q931_cr(h) & 0x7FFF, (h->crv[0] & 0x80) ? "Terminator" : "Originator"); /* Message header begins at the end of the call reference number */ mh = (q931_mh *)(h->contents + h->crlen); - pri_message("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg); + /* Might be an ANSI T1.607 message */ + if ((h->pd == T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR) || (h->pd == T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO)) + pri_message("%c Message type: %s (%d)\n", c, t1607_msg2str(mh->msg), mh->msg); + else + pri_message("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg); /* Drop length of header, including call reference */ len -= (h->crlen + 3); codeset = cur_codeset = 0; @@ -2358,12 +2393,15 @@ return -1; } -static void init_header(struct pri *pri, q931_call *call, char *buf, q931_h **hb, q931_mh **mhb, int *len) +static void init_header(struct pri *pri, q931_call *call, char *buf, q931_h **hb, q931_mh **mhb, int *len, int protodisc) { /* Returns header and message header and modifies length in place */ q931_h *h = (q931_h *)buf; q931_mh * mh = (q931_mh *)(h->contents + 2); - h->pd = pri->protodisc; + if (protodisc) + h->pd = protodisc; + else + h->pd = pri->protodisc; h->x0 = 0; /* Reserved 0 */ h->crlen = 2; /* Two bytes of Call Reference. Invert the top bit to make it from our sense */ if (call->cr || call->forceinvert) { @@ -2411,8 +2449,8 @@ int codeset; memset(buf, 0, sizeof(buf)); len = sizeof(buf); - init_header(pri, c, buf, &h, &mh, &len); - mh->msg = msgtype; + init_header(pri, c, buf, &h, &mh, &len, (msgtype >> 8)); + mh->msg = msgtype & 0x00ff; x=0; codeset = 0; while(ies[x] > -1) { @@ -2432,6 +2470,29 @@ return 0; } +static int maintenance_service_ies[] = { T1607_IE_CHANGE_STATUS, Q931_CHANNEL_IDENT, -1 }; + +int t1607_maintenance_service_ack(struct pri *pri, q931_call *c) +{ + return send_message(pri, c, (T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR << 8) | T1607_MAINTENANCE_SERVICE_ACKNOWLEDGE, maintenance_service_ies); +} + +int t1607_maintenance_service(struct pri *pri, int channel, int changestatus) +{ + struct q931_call *c; + c = q931_getcall(pri, 0 | 0x8000); + if (!c) + return -1; + if (channel) { + c->ds1no = (channel & 0xff00) >> 8; + channel &= 0xff; + c->channelno = channel; + } + c->chanflags &= ~FLAG_PREFERRED; + c->changestatus = changestatus; + return send_message(pri, c, (T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR << 8) | T1607_MAINTENANCE_SERVICE, maintenance_service_ies); +} + static int status_ies[] = { Q931_CAUSE, Q931_CALL_STATE, -1 }; static int q931_status(struct pri *pri, q931_call *c, int cause) @@ -2967,14 +3028,7 @@ pri->q931_rxcount++; #endif mh = (q931_mh *)(h->contents + h->crlen); - if ((h->pd == 0x3) || (h->pd == 0x43)) { - /* This is the weird maintenance stuff. We majorly - KLUDGE this by changing byte 4 from a 0xf (SERVICE) - to a 0x7 (SERVICE ACKNOWLEDGE) */ - h->raw[h->crlen + 2] -= 0x8; - q931_xmit(pri, h, len, 1); - return 0; - } else if (h->pd != pri->protodisc) { + if ((h->pd != pri->protodisc) && (h->pd != T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR) && (h->pd != T1607_MAINTENANCE_PROTOCOL_DISCRIMINATOR_TOO)) { pri_error("Warning: unknown/inappropriate protocol discriminator received (%02x/%d)\n", h->pd, h->pd); return 0; } @@ -2983,116 +3037,135 @@ pri_error("Unable to locate call %d\n", q931_cr(h)); return -1; } - /* Preliminary handling */ - switch(mh->msg) { - case Q931_RESTART: - if (pri->debug & PRI_DEBUG_Q931_STATE) - pri_message("-- Processing Q.931 Restart\n"); - /* Reset information */ - c->channelno = -1; - c->slotmap = -1; - c->chanflags = 0; - c->ds1no = 0; - c->ri = -1; - break; - case Q931_FACILITY: - strcpy(c->callername, ""); - break; - case Q931_SETUP: - if (pri->debug & PRI_DEBUG_Q931_STATE) - pri_message("-- Processing Q.931 Call Setup\n"); - c->channelno = -1; - c->slotmap = -1; - c->chanflags = 0; - c->ds1no = 0; - c->ri = -1; - c->transcapability = -1; - c->transmoderate = -1; - c->transmultiple = -1; - c->userl1 = -1; - c->userl2 = -1; - c->userl3 = -1; - c->rateadaption = -1; - c->calledplan = -1; - c->callerplan = -1; - c->callerpres = -1; - strcpy(c->callernum, ""); - strcpy(c->callednum, ""); - strcpy(c->callername, ""); - c->redirectingplan = -1; - c->redirectingpres = -1; - c->redirectingreason = -1; - strcpy(c->redirectingnum, ""); - c->useruserprotocoldisc = -1; - strcpy(c->useruserinfo, ""); - c->complete = 0; - c->nonisdn = 0; - /* Fall through */ - case Q931_CONNECT: - case Q931_ALERTING: - case Q931_PROGRESS: - case Q931_CALL_PROCEEDING: - c->progress = -1; - c->progressmask = 0; - break; - case Q931_CONNECT_ACKNOWLEDGE: - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; - break; - case Q931_RELEASE: - case Q931_DISCONNECT: - c->cause = -1; - c->causecode = -1; - c->causeloc = -1; - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; - break; - case Q931_RELEASE_COMPLETE: - if (c->retranstimer) - pri_schedule_del(pri, c->retranstimer); - c->retranstimer = 0; - case Q931_STATUS: - c->cause = -1; - c->causecode = -1; - c->causeloc = -1; - c->sugcallstate = -1; - break; - case Q931_RESTART_ACKNOWLEDGE: - c->channelno = -1; - break; - case Q931_INFORMATION: - break; - case Q931_STATUS_ENQUIRY: - break; - case Q931_SETUP_ACKNOWLEDGE: - break; - case Q931_NOTIFY: - break; - case Q931_USER_INFORMATION: - case Q931_SEGMENT: - case Q931_CONGESTION_CONTROL: - case Q931_HOLD: - case Q931_HOLD_ACKNOWLEDGE: - case Q931_HOLD_REJECT: - case Q931_RETRIEVE: - case Q931_RETRIEVE_ACKNOWLEDGE: - case Q931_RETRIEVE_REJECT: - case Q931_RESUME: - case Q931_RESUME_ACKNOWLEDGE: - case Q931_RESUME_REJECT: - case Q931_SUSPEND: - case Q931_SUSPEND_ACKNOWLEDGE: - case Q931_SUSPEND_REJECT: - pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - /* Fall through */ - default: - pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); - if (c->newcall) - q931_destroycall(pri,c->cr); - return -1; + if (h->pd == pri->protodisc) { + /* Preliminary handling */ + switch(mh->msg) { + case Q931_RESTART: + if (pri->debug & PRI_DEBUG_Q931_STATE) + pri_message("-- Processing Q.931 Restart\n"); + /* Reset information */ + c->channelno = -1; + c->slotmap = -1; + c->chanflags = 0; + c->ds1no = 0; + c->ri = -1; + break; + case Q931_FACILITY: + strcpy(c->callername, ""); + break; + case Q931_SETUP: + if (pri->debug & PRI_DEBUG_Q931_STATE) + pri_message("-- Processing Q.931 Call Setup\n"); + c->channelno = -1; + c->slotmap = -1; + c->chanflags = 0; + c->ds1no = 0; + c->ri = -1; + c->transcapability = -1; + c->transmoderate = -1; + c->transmultiple = -1; + c->userl1 = -1; + c->userl2 = -1; + c->userl3 = -1; + c->rateadaption = -1; + c->calledplan = -1; + c->callerplan = -1; + c->callerpres = -1; + strcpy(c->callernum, ""); + strcpy(c->callednum, ""); + strcpy(c->callername, ""); + c->redirectingplan = -1; + c->redirectingpres = -1; + c->redirectingreason = -1; + strcpy(c->redirectingnum, ""); + c->useruserprotocoldisc = -1; + strcpy(c->useruserinfo, ""); + c->complete = 0; + c->nonisdn = 0; + /* Fall through */ + case Q931_CONNECT: + case Q931_ALERTING: + case Q931_PROGRESS: + case Q931_CALL_PROCEEDING: + c->progress = -1; + c->progressmask = 0; + break; + case Q931_CONNECT_ACKNOWLEDGE: + if (c->retranstimer) + pri_schedule_del(pri, c->retranstimer); + c->retranstimer = 0; + break; + case Q931_RELEASE: + case Q931_DISCONNECT: + c->cause = -1; + c->causecode = -1; + c->causeloc = -1; + if (c->retranstimer) + pri_schedule_del(pri, c->retranstimer); + c->retranstimer = 0; + break; + case Q931_RELEASE_COMPLETE: + if (c->retranstimer) + pri_schedule_del(pri, c->retranstimer); + c->retranstimer = 0; + case Q931_STATUS: + c->cause = -1; + c->causecode = -1; + c->causeloc = -1; + c->sugcallstate = -1; + break; + case Q931_RESTART_ACKNOWLEDGE: + c->channelno = -1; + break; + case Q931_INFORMATION: + break; + case Q931_STATUS_ENQUIRY: + break; + case Q931_SETUP_ACKNOWLEDGE: + break; + case Q931_NOTIFY: + break; + case Q931_USER_INFORMATION: + case Q931_SEGMENT: + case Q931_CONGESTION_CONTROL: + case Q931_HOLD: + case Q931_HOLD_ACKNOWLEDGE: + case Q931_HOLD_REJECT: + case Q931_RETRIEVE: + case Q931_RETRIEVE_ACKNOWLEDGE: + case Q931_RETRIEVE_REJECT: + case Q931_RESUME: + case Q931_RESUME_ACKNOWLEDGE: + case Q931_RESUME_REJECT: + case Q931_SUSPEND: + case Q931_SUSPEND_ACKNOWLEDGE: + case Q931_SUSPEND_REJECT: + pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + /* Fall through */ + default: + pri_error("!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); + if (c->newcall) + q931_destroycall(pri,c->cr); + return -1; + } + } else { + /* Do the maintenance stuff */ + switch(mh->msg) { + case T1607_MAINTENANCE_SERVICE: + case T1607_MAINTENANCE_SERVICE_ACKNOWLEDGE: + c->channelno = -1; + c->slotmap = -1; + c->chanflags = 0; + c->ds1no = 0; + c->ri = -1; + c->changestatus = -1; + break; + default: + pri_error("!! Don't know how to pre-handle maintenance message type %s (%d)\n", t1607_msg2str(mh->msg), mh->msg); + return -1; + break; + } } memset(mandies, 0, sizeof(mandies)); missingmand = 0; @@ -3159,8 +3232,9 @@ default: y = q931_handle_ie(cur_codeset, pri, c, mh->msg, ie); /* XXX Applicable to codeset 0 only? XXX */ - if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0)) + if (!cur_codeset && !(ie->ie & 0xf0) && (y < 0)) { mandies[MAX_MAND_IES - 1] = Q931_FULL_IE(cur_codeset, ie->ie); + } } /* Reset current codeset */ cur_codeset = codeset; @@ -3180,180 +3254,202 @@ } } - /* Post handling */ - switch(mh->msg) { - case Q931_RESTART: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - q931_destroycall(pri, c->cr); - break; - } - c->ourcallstate = Q931_CALL_STATE_RESTART; - c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST; - /* Send back the Restart Acknowledge */ - restart_ack(pri, c); - /* Notify user of restart event */ - pri->ev.e = PRI_EVENT_RESTART; - pri->ev.restart.channel = c->channelno | (c->ds1no << 8); - return Q931_RES_HAVEEVENT; - case Q931_SETUP: - if (missingmand) { - q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - break; - } - /* Must be new call */ - if (!c->newcall) { - break; - } - if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN) - c->nonisdn = 1; - c->newcall = 0; - c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT; - c->peercallstate = Q931_CALL_STATE_CALL_INITIATED; - /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */ - c->alive = 0; - if (c->transmoderate != TRANS_MODE_64_CIRCUIT) { - q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL); - break; - } - pri->ev.e = PRI_EVENT_RING; - pri->ev.ring.channel = c->channelno | (c->ds1no << 8); - pri->ev.ring.callingpres = c->callerpres; - pri->ev.ring.callingplan = c->callerplan; - pri->ev.ring.ani2 = c->ani2; - strncpy(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum) - 1); - strncpy(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname) - 1); - pri->ev.ring.calledplan = c->calledplan; - strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); - strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); - strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1); - strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1); - pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE); - pri->ev.ring.cref = c->cr; - pri->ev.ring.call = c; - pri->ev.ring.layer1 = c->userl1; - pri->ev.ring.complete = c->complete; - pri->ev.ring.ctype = c->transcapability; - pri->ev.ring.redirectingreason = c->redirectingreason; - pri->ev.ring.progress = c->progress; - pri->ev.ring.progressmask = c->progressmask; - return Q931_RES_HAVEEVENT; - case Q931_ALERTING: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED; - c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED; - pri->ev.e = PRI_EVENT_RINGING; - pri->ev.ringing.channel = c->channelno | (c->ds1no << 8); - pri->ev.ringing.cref = c->cr; - pri->ev.ringing.call = c; - pri->ev.ringing.progress = c->progress; - pri->ev.ringing.progressmask = c->progressmask; - return Q931_RES_HAVEEVENT; - case Q931_CONNECT: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) { - q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE); - break; - } - c->ourcallstate = Q931_CALL_STATE_ACTIVE; - c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST; - pri->ev.e = PRI_EVENT_ANSWER; - pri->ev.answer.channel = c->channelno | (c->ds1no << 8); - pri->ev.answer.cref = c->cr; - pri->ev.answer.call = c; - pri->ev.answer.progress = c->progress; - pri->ev.answer.progressmask = c->progressmask; - q931_connect_acknowledge(pri, c); - return Q931_RES_HAVEEVENT; - case Q931_FACILITY: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - pri->ev.e = PRI_EVENT_FACNAME; - strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1); - strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1); - pri->ev.facname.channel = c->channelno | (c->ds1no << 8); - pri->ev.facname.cref = c->cr; - pri->ev.facname.call = c; -#if 0 - pri_message("Sending facility event (%s/%s)\n", pri->ev.facname.callingname, pri->ev.facname.callingnum); -#endif - return Q931_RES_HAVEEVENT; - case Q931_PROGRESS: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - q931_destroycall(pri, c->cr); - break; - } - pri->ev.e = PRI_EVENT_PROGRESS; - /* Fall through */ - case Q931_CALL_PROCEEDING: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) && - (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) && - (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) && - (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) { - q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); - break; - } - pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8); - if (mh->msg == Q931_CALL_PROCEEDING) { - pri->ev.e = PRI_EVENT_PROCEEDING; - c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING; - c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING; - } - pri->ev.proceeding.progress = c->progress; - pri->ev.proceeding.progressmask = c->progressmask; - pri->ev.proceeding.cref = c->cr; - pri->ev.proceeding.call = c; - return Q931_RES_HAVEEVENT; - case Q931_CONNECT_ACKNOWLEDGE: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) { - q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); - break; - } - c->ourcallstate = Q931_CALL_STATE_ACTIVE; - c->peercallstate = Q931_CALL_STATE_ACTIVE; - break; - case Q931_STATUS: - if (missingmand) { - q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); - q931_destroycall(pri, c->cr); + if (h->pd == pri->protodisc) { + /* Post handling */ + switch(mh->msg) { + case Q931_RESTART: + if (missingmand) { + q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + q931_destroycall(pri, c->cr); + break; + } + c->ourcallstate = Q931_CALL_STATE_RESTART; + c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST; + /* Send back the Restart Acknowledge */ + restart_ack(pri, c); + /* Notify user of restart event */ + pri->ev.e = PRI_EVENT_RESTART; + pri->ev.restart.channel = c->channelno | (c->ds1no << 8); + return Q931_RES_HAVEEVENT; + case Q931_SETUP: + if (missingmand) { + q931_release_complete(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + break; + } + /* Must be new call */ + if (!c->newcall) { + break; + } + if (c->progressmask & PRI_PROG_CALLER_NOT_ISDN) + c->nonisdn = 1; + c->newcall = 0; + c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT; + c->peercallstate = Q931_CALL_STATE_CALL_INITIATED; + /* it's not yet a call since higher level can respond with RELEASE or RELEASE_COMPLETE */ + c->alive = 0; + if (c->transmoderate != TRANS_MODE_64_CIRCUIT) { + q931_release_complete(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL); + break; + } + pri->ev.e = PRI_EVENT_RING; + pri->ev.ring.channel = c->channelno | (c->ds1no << 8); + pri->ev.ring.callingpres = c->callerpres; + pri->ev.ring.callingplan = c->callerplan; + pri->ev.ring.ani2 = c->ani2; + strncpy(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum) - 1); + strncpy(pri->ev.ring.callingname, c->callername, sizeof(pri->ev.ring.callingname) - 1); + pri->ev.ring.calledplan = c->calledplan; + strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); + strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); + strncpy(pri->ev.ring.redirectingnum, c->redirectingnum, sizeof(pri->ev.ring.redirectingnum) - 1); + strncpy(pri->ev.ring.useruserinfo, c->useruserinfo, sizeof(pri->ev.ring.useruserinfo) - 1); + pri->ev.ring.flexible = ! (c->chanflags & FLAG_EXCLUSIVE); + pri->ev.ring.cref = c->cr; + pri->ev.ring.call = c; + pri->ev.ring.layer1 = c->userl1; + pri->ev.ring.complete = c->complete; + pri->ev.ring.ctype = c->transcapability; + pri->ev.ring.redirectingreason = c->redirectingreason; + pri->ev.ring.progress = c->progress; + pri->ev.ring.progressmask = c->progressmask; + return Q931_RES_HAVEEVENT; + case Q931_ALERTING: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + c->ourcallstate = Q931_CALL_STATE_CALL_DELIVERED; + c->peercallstate = Q931_CALL_STATE_CALL_RECEIVED; + pri->ev.e = PRI_EVENT_RINGING; + pri->ev.ringing.channel = c->channelno | (c->ds1no << 8); + pri->ev.ringing.cref = c->cr; + pri->ev.ringing.call = c; + pri->ev.ringing.progress = c->progress; + pri->ev.ringing.progressmask = c->progressmask; + return Q931_RES_HAVEEVENT; + case Q931_CONNECT: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if (c->ourcallstate == Q931_CALL_STATE_ACTIVE) { + q931_status(pri, c, PRI_CAUSE_WRONG_MESSAGE); + break; + } + c->ourcallstate = Q931_CALL_STATE_ACTIVE; + c->peercallstate = Q931_CALL_STATE_CONNECT_REQUEST; + pri->ev.e = PRI_EVENT_ANSWER; + pri->ev.answer.channel = c->channelno | (c->ds1no << 8); + pri->ev.answer.cref = c->cr; + pri->ev.answer.call = c; + pri->ev.answer.progress = c->progress; + pri->ev.answer.progressmask = c->progressmask; + q931_connect_acknowledge(pri, c); + return Q931_RES_HAVEEVENT; + case Q931_FACILITY: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + pri->ev.e = PRI_EVENT_FACNAME; + strncpy(pri->ev.facname.callingname, c->callername, sizeof(pri->ev.facname.callingname) - 1); + strncpy(pri->ev.facname.callingnum, c->callernum, sizeof(pri->ev.facname.callingname) - 1); + pri->ev.facname.channel = c->channelno | (c->ds1no << 8); + pri->ev.facname.cref = c->cr; + pri->ev.facname.call = c; + return Q931_RES_HAVEEVENT; + case Q931_PROGRESS: + if (missingmand) { + q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + q931_destroycall(pri, c->cr); + break; + } + pri->ev.e = PRI_EVENT_PROGRESS; + /* Fall through */ + case Q931_CALL_PROCEEDING: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if ((c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED) && + (c->ourcallstate != Q931_CALL_STATE_OVERLAP_SENDING) && + (c->ourcallstate != Q931_CALL_STATE_CALL_DELIVERED) && + (c->ourcallstate != Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING)) { + q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); + break; + } + pri->ev.proceeding.channel = c->channelno | (c->ds1no << 8); + if (mh->msg == Q931_CALL_PROCEEDING) { + pri->ev.e = PRI_EVENT_PROCEEDING; + c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING; + c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING; + } + pri->ev.proceeding.progress = c->progress; + pri->ev.proceeding.progressmask = c->progressmask; + pri->ev.proceeding.cref = c->cr; + pri->ev.proceeding.call = c; + return Q931_RES_HAVEEVENT; + case Q931_CONNECT_ACKNOWLEDGE: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if (c->ourcallstate != Q931_CALL_STATE_CONNECT_REQUEST) { + q931_status(pri,c,PRI_CAUSE_WRONG_MESSAGE); + break; + } + c->ourcallstate = Q931_CALL_STATE_ACTIVE; + c->peercallstate = Q931_CALL_STATE_ACTIVE; break; - } - if (c->newcall) { - if (c->cr & 0x7fff) - q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE); + case Q931_STATUS: + if (missingmand) { + q931_status(pri, c, PRI_CAUSE_MANDATORY_IE_MISSING); + q931_destroycall(pri, c->cr); + break; + } + if (c->newcall) { + if (c->cr & 0x7fff) + q931_release_complete(pri,c,PRI_CAUSE_WRONG_CALL_STATE); + break; + } + /* Do nothing */ + /* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */ + if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) && + (c->cause != PRI_CAUSE_INTERWORKING)) + pri_error("Received unsolicited status: %s\n", pri_cause2str(c->cause)); + /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */ + if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) { + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); + pri->ev.hangup.cref = c->cr; + pri->ev.hangup.cause = c->cause; + pri->ev.hangup.call = c; + /* Free resources */ + c->ourcallstate = Q931_CALL_STATE_NULL; + c->peercallstate = Q931_CALL_STATE_NULL; + if (c->alive) { + pri->ev.e = PRI_EVENT_HANGUP; + res = Q931_RES_HAVEEVENT; + c->alive = 0; + } else if (c->sendhangupack) { + res = Q931_RES_HAVEEVENT; + pri->ev.e = PRI_EVENT_HANGUP_ACK; + q931_hangup(pri, c, c->cause); + } else { + q931_hangup(pri, c, c->cause); + res = 0; + } + if (res) + return res; + } break; - } - /* Do nothing */ - /* Also when the STATUS asks for the call of an unexisting reference send RELEASE_COMPL */ - if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) && - (c->cause != PRI_CAUSE_INTERWORKING)) - pri_error("Received unsolicited status: %s\n", pri_cause2str(c->cause)); - /* Workaround for S-12 ver 7.3 - it responds for invalid/non-implemented IEs at SETUP with null call state */ - if (!c->sugcallstate && (c->ourcallstate != Q931_CALL_STATE_CALL_INITIATED)) { + case Q931_RELEASE_COMPLETE: + c->ourcallstate = Q931_CALL_STATE_NULL; + c->peercallstate = Q931_CALL_STATE_NULL; pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); pri->ev.hangup.cref = c->cr; pri->ev.hangup.cause = c->cause; pri->ev.hangup.call = c; /* Free resources */ - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; if (c->alive) { pri->ev.e = PRI_EVENT_HANGUP; res = Q931_RES_HAVEEVENT; @@ -3361,154 +3457,150 @@ } else if (c->sendhangupack) { res = Q931_RES_HAVEEVENT; pri->ev.e = PRI_EVENT_HANGUP_ACK; - q931_hangup(pri, c, c->cause); - } else { - q931_hangup(pri, c, c->cause); + pri_hangup(pri, c, c->cause); + } else res = 0; - } if (res) return res; - } - break; - case Q931_RELEASE_COMPLETE: - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); - pri->ev.hangup.cref = c->cr; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - /* Free resources */ - if (c->alive) { + else + q931_hangup(pri,c,c->cause); + break; + case Q931_RELEASE: + if (missingmand) { + /* Force cause to be mandatory IE missing */ + c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; + } + if (c->ourcallstate == Q931_CALL_STATE_RELEASE_REQUEST) + c->peercallstate = Q931_CALL_STATE_NULL; + else { + c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST; + } + c->ourcallstate = Q931_CALL_STATE_NULL; pri->ev.e = PRI_EVENT_HANGUP; - res = Q931_RES_HAVEEVENT; - c->alive = 0; - } else if (c->sendhangupack) { - res = Q931_RES_HAVEEVENT; - pri->ev.e = PRI_EVENT_HANGUP_ACK; - pri_hangup(pri, c, c->cause); - } else - res = 0; - if (res) - return res; - else - q931_hangup(pri,c,c->cause); - break; - case Q931_RELEASE: - if (missingmand) { - /* Force cause to be mandatory IE missing */ - c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; - } - if (c->ourcallstate == Q931_CALL_STATE_RELEASE_REQUEST) + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); + pri->ev.hangup.cref = c->cr; + pri->ev.hangup.cause = c->cause; + pri->ev.hangup.call = c; + /* Don't send release complete if they send us release + while we sent it, assume a NULL state */ + if (c->newcall) + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + else + return Q931_RES_HAVEEVENT; + break; + case Q931_DISCONNECT: + if (missingmand) { + /* Still let user call release */ + c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; + } + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + c->ourcallstate = Q931_CALL_STATE_DISCONNECT_INDICATION; + c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST; + c->sendhangupack = 1; + /* Return such an event */ + pri->ev.e = PRI_EVENT_HANGUP_REQ; + pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); + pri->ev.hangup.cref = c->cr; + pri->ev.hangup.cause = c->cause; + pri->ev.hangup.call = c; + if (c->alive) + return Q931_RES_HAVEEVENT; + else + q931_hangup(pri,c,c->cause); + break; + case Q931_RESTART_ACKNOWLEDGE: + c->ourcallstate = Q931_CALL_STATE_NULL; c->peercallstate = Q931_CALL_STATE_NULL; - else { - c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST; - } - c->ourcallstate = Q931_CALL_STATE_NULL; - pri->ev.e = PRI_EVENT_HANGUP; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); - pri->ev.hangup.cref = c->cr; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - /* Don't send release complete if they send us release - while we sent it, assume a NULL state */ - if (c->newcall) - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - else + pri->ev.e = PRI_EVENT_RESTART_ACK; + pri->ev.restartack.channel = c->channelno | (c->ds1no << 8); + return Q931_RES_HAVEEVENT; + case Q931_INFORMATION: + /* XXX We're handling only INFORMATION messages that contain + overlap dialing received digit + + the "Complete" msg which is basically an EOF on further digits + XXX */ + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + if (c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING) + break; + pri->ev.e = PRI_EVENT_INFO_RECEIVED; + pri->ev.ring.call = c; + pri->ev.ring.channel = c->channelno | (c->ds1no << 8); + strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); + strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); + pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ return Q931_RES_HAVEEVENT; - break; - case Q931_DISCONNECT: - if (missingmand) { - /* Still let user call release */ - c->cause = PRI_CAUSE_MANDATORY_IE_MISSING; - } - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); break; + case Q931_STATUS_ENQUIRY: + if (c->newcall) { + q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE); + } else + q931_status(pri,c, 0); + break; + case Q931_SETUP_ACKNOWLEDGE: + if (c->newcall) { + q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); + break; + } + c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING; + c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING; + pri->ev.e = PRI_EVENT_SETUP_ACK; + pri->ev.setup_ack.channel = c->channelno; + return Q931_RES_HAVEEVENT; + case Q931_NOTIFY: + pri->ev.e = PRI_EVENT_NOTIFY; + pri->ev.notify.channel = c->channelno; + pri->ev.notify.info = c->notify; + return Q931_RES_HAVEEVENT; + case Q931_USER_INFORMATION: + case Q931_SEGMENT: + case Q931_CONGESTION_CONTROL: + case Q931_HOLD: + case Q931_HOLD_ACKNOWLEDGE: + case Q931_HOLD_REJECT: + case Q931_RETRIEVE: + case Q931_RETRIEVE_ACKNOWLEDGE: + case Q931_RETRIEVE_REJECT: + case Q931_RESUME: + case Q931_RESUME_ACKNOWLEDGE: + case Q931_RESUME_REJECT: + case Q931_SUSPEND: + case Q931_SUSPEND_ACKNOWLEDGE: + case Q931_SUSPEND_REJECT: + pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + /* Fall through */ + default: + + pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); + q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); + if (c->newcall) + q931_destroycall(pri,c->cr); + return -1; } - c->ourcallstate = Q931_CALL_STATE_DISCONNECT_INDICATION; - c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST; - c->sendhangupack = 1; - /* Return such an event */ - pri->ev.e = PRI_EVENT_HANGUP_REQ; - pri->ev.hangup.channel = c->channelno | (c->ds1no << 8); - pri->ev.hangup.cref = c->cr; - pri->ev.hangup.cause = c->cause; - pri->ev.hangup.call = c; - if (c->alive) + } else { + /* Do the maintenance stuff */ + switch(mh->msg) { + case T1607_MAINTENANCE_SERVICE: + pri->ev.e = PRI_EVENT_SERVICE; + pri->ev.service.channel = c->channelno | (c->ds1no << 8); + pri->ev.service.changestatus = c->changestatus; + t1607_maintenance_service_ack(pri, c); return Q931_RES_HAVEEVENT; - else - q931_hangup(pri,c,c->cause); - break; - case Q931_RESTART_ACKNOWLEDGE: - c->ourcallstate = Q931_CALL_STATE_NULL; - c->peercallstate = Q931_CALL_STATE_NULL; - pri->ev.e = PRI_EVENT_RESTART_ACK; - pri->ev.restartack.channel = c->channelno | (c->ds1no << 8); - return Q931_RES_HAVEEVENT; - case Q931_INFORMATION: - /* XXX We're handling only INFORMATION messages that contain - overlap dialing received digit - + the "Complete" msg which is basically an EOF on further digits - XXX */ - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - if (c->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING) - break; - pri->ev.e = PRI_EVENT_INFO_RECEIVED; - pri->ev.ring.call = c; - pri->ev.ring.channel = c->channelno | (c->ds1no << 8); - strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1); - strncpy(pri->ev.ring.callingsubaddr, c->callingsubaddr, sizeof(pri->ev.ring.callingsubaddr) - 1); - pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */ - return Q931_RES_HAVEEVENT; - break; - case Q931_STATUS_ENQUIRY: - if (c->newcall) { - q931_release_complete(pri, c, PRI_CAUSE_INVALID_CALL_REFERENCE); - } else - q931_status(pri,c, 0); - break; - case Q931_SETUP_ACKNOWLEDGE: - if (c->newcall) { - q931_release_complete(pri,c,PRI_CAUSE_INVALID_CALL_REFERENCE); - break; - } - c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING; - c->peercallstate = Q931_CALL_STATE_OVERLAP_RECEIVING; - pri->ev.e = PRI_EVENT_SETUP_ACK; - pri->ev.setup_ack.channel = c->channelno; - return Q931_RES_HAVEEVENT; - case Q931_NOTIFY: - pri->ev.e = PRI_EVENT_NOTIFY; - pri->ev.notify.channel = c->channelno; - pri->ev.notify.info = c->notify; - return Q931_RES_HAVEEVENT; - case Q931_USER_INFORMATION: - case Q931_SEGMENT: - case Q931_CONGESTION_CONTROL: - case Q931_HOLD: - case Q931_HOLD_ACKNOWLEDGE: - case Q931_HOLD_REJECT: - case Q931_RETRIEVE: - case Q931_RETRIEVE_ACKNOWLEDGE: - case Q931_RETRIEVE_REJECT: - case Q931_RESUME: - case Q931_RESUME_ACKNOWLEDGE: - case Q931_RESUME_REJECT: - case Q931_SUSPEND: - case Q931_SUSPEND_ACKNOWLEDGE: - case Q931_SUSPEND_REJECT: - pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - /* Fall through */ - default: - - pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg); - q931_status(pri,c, PRI_CAUSE_MESSAGE_TYPE_NONEXIST); - if (c->newcall) - q931_destroycall(pri,c->cr); - return -1; + case T1607_MAINTENANCE_SERVICE_ACKNOWLEDGE: + pri->ev.e = PRI_EVENT_SERVICE_ACK; + pri->ev.service_ack.channel = c->channelno | (c->ds1no << 8); + pri->ev.service_ack.changestatus = c->changestatus; + return Q931_RES_HAVEEVENT; + default: + pri_error("!! Don't know how to post-handle maintenance message type %s (%d)\n", t1607_msg2str(mh->msg), mh->msg); + return -1; + break; + } } return 0; } Index: testprilib.c =================================================================== RCS file: /usr/cvsroot/libpri/testprilib.c,v retrieving revision 1.4 diff -u -r1.4 testprilib.c --- testprilib.c 3 Feb 2005 22:14:44 -0000 1.4 +++ testprilib.c 4 Feb 2005 19:32:00 -0000 @@ -47,9 +47,6 @@ #elif defined(__FreeBSD__) || defined(SOLARIS) #include #endif -#ifndef SOLARIS -#include -#endif #include #include #include "libpri.h"