Compare commits

...

25 Commits
0.3.2 ... 0.4.0

Author SHA1 Message Date
Kevin P. Fleming
0cbc6379e9 remove extraneous svn:executable properties
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/0.4.0@266 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-29 18:39:18 +00:00
Kevin P. Fleming
6faf34f986 automatic tag renames
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/0.4.0@263 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2005-11-27 04:17:23 +00:00
Admin Commit
dfdbe4f290 This commit was manufactured by cvs2svn to create tag 'v0-4-0'.
git-svn-id: https://origsvn.digium.com/svn/libpri/tags/v0-4-0@59 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-09-09 23:49:10 +00:00
Martin Pycko
4e6c9e0410 Fix q931_hangup for (call received, call delivered)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@58 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-09-09 23:49:10 +00:00
Martin Pycko
88656d9497 Don't reset peercallstate when we receive the STATUS message
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@57 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-09-09 23:40:16 +00:00
Martin Pycko
fe0eba8175 Fix the displaying of the information about the ANI/callerid
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@56 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-13 03:08:22 +00:00
Martin Pycko
24b85a379b Add pri_destroycall
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@55 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-12 20:16:55 +00:00
Martin Pycko
ec99ad86dd Regarding the new pri hangup: rewrite a little bit and introduce the PRI_EVENT_HANGUP_REQ
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@54 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-07 00:45:04 +00:00
Martin Pycko
ee9ef9ef3c One last thing fixed so that libpri would compile on 'other' systems
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@53 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-06 16:53:40 +00:00
Martin Pycko
f6966bc35b Fix the compilation errors on some systems due to -Werror flag
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@52 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-06 15:20:49 +00:00
Martin Pycko
45efb97ebd Update q931_hangup routine
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@51 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-05 20:37:32 +00:00
Martin Pycko
110062aef6 Allow to send the CAUSE IE along with RELEASE_COMPLETE message
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@50 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-05 19:26:07 +00:00
Martin Pycko
de24dd76a6 Send RELEASE COMPLETE if the cause is UNALLOCATED NUMBER (1) instead of sending DISCONNECT (although that should be ok too)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@49 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-05 18:42:55 +00:00
Martin Pycko
e09654f0ed Allow the use of pri_release and pri_disconnect to have backwards compatibility for those who don't use asterisk with libpri
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@48 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-05 01:20:25 +00:00
Martin Pycko
86fe59eacc Make dependencies between asterisk and libpri using the flag PRI_HANGUP
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@47 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-05 01:08:06 +00:00
Martin Pycko
2809056303 Fix and improve (based on callstates) the hangup routines
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@46 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-08-05 01:00:45 +00:00
Mark Spencer
f8d3569b56 Handle sendingcomplete properly
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@45 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-07-26 15:14:44 +00:00
Martin Pycko
5f1aba027a Add posibility of choosing a diffrent form of ALERTING messages that has to be changed to work e.g. with Mitel switches.
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@44 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-07-07 23:37:18 +00:00
Mark Spencer
a85d2c508b Handle sending complete
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@43 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-07-01 20:25:34 +00:00
Martin Pycko
34f700b584 Change the way we store the callednum from INFORMATION messages
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@42 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-06-05 21:15:56 +00:00
Mark Spencer
5137d733f9 Add National ISDN 1 switchtype
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@41 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-05-28 22:34:59 +00:00
Martin Pycko
5478d68b2a Pass the info about SETUP_ACKNOWLEDGE outside libpri
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@40 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-05-15 22:15:38 +00:00
Martin Pycko
6e8e051464 Don't send IE field 'Sending Complete' when we want to do overlap dialing (sending)
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@39 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-05-15 19:35:05 +00:00
Mark Spencer
80355d96c5 Don't automatically send release
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@38 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-05-12 16:59:12 +00:00
Martin Pycko
e4d3ca388b Add PRI_EVENT_PROCEEDING when we get CALL_PROCEEDING or PROGRESS
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@37 2fbb986a-6c06-0410-b554-c9c1f0a7f128
2003-04-18 15:56:38 +00:00
14 changed files with 276 additions and 59 deletions

0
ChangeLog Executable file → Normal file
View File

6
Makefile Executable file → Normal file
View File

@@ -20,12 +20,16 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
#
# Uncomment if you want libpri not send PROGRESS_INDICATOR w/ALERTING
#ALERTING=-DALERTING_NO_PROGRESS
TOBJS=testpri.o
STATIC_LIBRARY=libpri.a
DYNAMIC_LIBRARY=libpri.so.1.0
STATIC_OBJS=pri.o q921.o prisched.o q931.o
DYNAMIC_OBJS=pri.lo q921.lo prisched.lo q931.lo
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g
CFLAGS=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes -g $(ALERTING)
INSTALL_PREFIX=
all: $(STATIC_LIBRARY) $(DYNAMIC_LIBRARY)

0
README Executable file → Normal file
View File

0
TODO Executable file → Normal file
View File

43
libpri.h Executable file → Normal file
View File

@@ -48,6 +48,7 @@
#define PRI_SWITCH_ATT4ESS 4 /* AT&T 4ESS */
#define PRI_SWITCH_EUROISDN_E1 5 /* Standard EuroISDN (CTR4, ETSI 300-102) */
#define PRI_SWITCH_EUROISDN_T1 6 /* T1 EuroISDN variant (ETSI 300-102) */
#define PRI_SWITCH_NI1 7 /* National ISDN 1 */
/* PRI D-Channel Events */
#define PRI_EVENT_DCHAN_UP 1 /* D-channel is up */
@@ -62,6 +63,9 @@
#define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel */
#define PRI_EVENT_FACNAME 11 /* Caller*ID Name received on Facility */
#define PRI_EVENT_INFO_RECEIVED 12 /* Additional info (keypad) received */
#define PRI_EVENT_PROCEEDING 13 /* When we get CALL_PROCEEDING or PROGRESS */
#define PRI_EVENT_SETUP_ACK 14 /* When we get SETUP_ACKNOWLEDGE */
#define PRI_EVENT_HANGUP_REQ 15 /* Requesting the higher layer to hangup */
/* Simple states */
#define PRI_STATE_DOWN 0
@@ -176,6 +180,8 @@
#define PRI_LAYER_1_V120_RATE_ADAPT 0x28
#define PRI_LAYER_1_X31_RATE_ADAPT 0x29
#define PRI_COPY_DIGITS_CALLED_NUMBER
typedef struct q931_call q931_call;
typedef struct pri_event_generic {
@@ -231,6 +237,7 @@ typedef struct pri_event_ring {
int cref; /* Call Reference Number */
int ctype; /* Call type (see PRI_TRANS_CAP_* */
int layer1; /* User layer 1 */
int complete; /* Have we seen "Complete" i.e. no more number? */
q931_call *call; /* Opaque call pointer */
} pri_event_ring;
@@ -247,6 +254,16 @@ typedef struct pri_event_restart_ack {
int channel;
} pri_event_restart_ack;
typedef struct pri_event_proceeding {
int e;
int channel;
} pri_event_proceeding;
typedef struct pri_event_setup_ack {
int e;
int channel;
} pri_event_setup_ack;
typedef union {
int e;
pri_event_generic gen; /* Generic view */
@@ -258,6 +275,8 @@ typedef union {
pri_event_ringing ringing; /* Ringing */
pri_event_ringing answer; /* Answer */
pri_event_restart_ack restartack; /* Restart Acknowledge */
pri_event_proceeding proceeding; /* Call proceeding & Progress */
pri_event_setup_ack setup_ack; /* SETUP_ACKNOWLEDGE structure */
} pri_event;
struct pri;
@@ -319,11 +338,31 @@ extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
#if 0
/* deprecated routines, use pri_hangup */
/* Release/Reject a call */
extern int pri_release(struct pri *pri, q931_call *call, int cause);
/* Hangup / Disconnect a call */
extern int pri_disconnect(struct pri *pri, q931_call *call, int cause);
#endif
#undef pri_release
#undef pri_disconnect
/* backwards compatibility for those who don't use asterisk with libpri */
#define pri_release(a,b,c) \
pri_hangup(a,b,c)
#define pri_disconnect(a,b,c) \
pri_hangup(a,b,c)
/* Hangup a call */
#define PRI_HANGUP
extern int pri_hangup(struct pri *pri, q931_call *call, int cause);
#define PRI_DESTROYCALL
extern void pri_destroycall(struct pri *pri, q931_call *call);
extern int pri_reset(struct pri *pri, int channel);
@@ -343,4 +382,8 @@ extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
/* Override message and error stuff */
extern void pri_set_message(void (*__pri_error)(char *));
extern void pri_set_error(void (*__pri_error)(char *));
/* Set overlap mode */
#define PRI_SET_OVERLAPDIAL
extern void pri_set_overlapdial(struct pri *pri,int state);
#endif

28
pri.c Executable file → Normal file
View File

@@ -49,6 +49,8 @@ char *pri_switch2str(int sw)
return "Lucent 5E";
case PRI_SWITCH_ATT4ESS:
return "AT&T 4ESS";
case PRI_SWITCH_NI1:
return "National ISDN 1";
default:
return "Unknown switchtype";
}
@@ -188,6 +190,13 @@ int pri_information(struct pri *pri, q931_call *call, char digit)
return q931_information(pri, call, digit);
}
void pri_destroycall(struct pri *pri, q931_call *call)
{
if (pri && call)
__q931_destroycall(pri, call);
return;
}
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn)
{
if (!pri || !call)
@@ -202,6 +211,8 @@ int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
return q931_connect(pri, call, channel, nonisdn);
}
#if 0
/* deprecated routines, use pri_hangup */
int pri_release(struct pri *pri, q931_call *call, int cause)
{
if (!pri || !call)
@@ -215,6 +226,17 @@ int pri_disconnect(struct pri *pri, q931_call *call, int cause)
return -1;
return q931_disconnect(pri, call, cause);
}
#endif
int pri_hangup(struct pri *pri, q931_call *call, int cause)
{
if (!pri || !call)
return -1;
if (cause == -1)
/* normal clear cause */
cause = 16;
return q931_hangup(pri, call, cause);
}
int pri_reset(struct pri *pri, int channel)
{
@@ -304,3 +326,9 @@ void pri_error(char *fmt, ...)
else
fprintf(stderr, tmp);
}
/* Set overlap mode */
void pri_set_overlapdial(struct pri *pri,int state)
{
pri->overlapdial = state;
}

3
pri_internal.h Executable file → Normal file
View File

@@ -78,6 +78,9 @@ struct pri {
/* Q.931 calls */
q931_call *calls;
/* do we do overlap dialing */
int overlapdial;
};
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);

0
pri_q921.h Executable file → Normal file
View File

5
pri_q931.h Executable file → Normal file
View File

@@ -255,6 +255,8 @@ extern int q931_release(struct pri *pri, q931_call *call, int cause);
extern int q931_disconnect(struct pri *pri, q931_call *call, int cause);
extern int q931_hangup(struct pri *pri, q931_call *call, int cause);
extern int q931_restart(struct pri *pri, int channel);
extern q931_call *q931_new_call(struct pri *pri);
@@ -263,4 +265,7 @@ extern int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel,
int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
int calledplan, int ulay1);
extern void q931_dump(q931_h *h, int len, int txrx);
extern void __q931_destroycall(struct pri *pri, q931_call *c);
#endif

0
pridump.c Executable file → Normal file
View File

0
prisched.c Executable file → Normal file
View File

0
pritest.c Executable file → Normal file
View File

0
q921.c Executable file → Normal file
View File

250
q931.c Executable file → Normal file
View File

@@ -218,7 +218,7 @@ struct q931_call {
int causeloc; /* Cause Location */
int cause; /* Cause of clearing */
int callstate; /* Call state of peer as reported */
int peercallstate; /* Call state of peer as reported */
int ourcallstate; /* Our call state */
int callerplan;
@@ -229,6 +229,7 @@ struct q931_call {
int calledplan;
int nonisdn;
char callednum[256]; /* Called Number */
int complete; /* no more digits coming */
int redirectingplan;
int redirectingpres;
@@ -273,6 +274,7 @@ static void call_init(struct q931_call *c)
c->next = NULL;
c->sentchannel = 0;
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL;
}
static char *binary(int b, int len) {
@@ -700,7 +702,7 @@ char *pri_pres2str(int pres)
{ PRES_PROHIB_USER_NUMBER_NOT_SCREENED, "Presentation prohibited, user number not screened" },
{ PRES_PROHIB_USER_NUMBER_PASSED_SCREEN, "Presentation prohibited, user number passed network screening" },
{ PRES_PROHIB_USER_NUMBER_FAILED_SCREEN, "Presentation prohibited, user number failed network screening" },
{ PRES_PROHIB_NETWORK_NUMBER, "Presentation prohibbited of network provided number" },
{ PRES_PROHIB_NETWORK_NUMBER, "Presentation prohibited of network provided number" },
};
return code2str(pres, press, sizeof(press) / sizeof(press[0]));
}
@@ -740,7 +742,7 @@ static void dump_calling_party_number(q931_ie *ie, int len, char prefix)
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
pri_message("%c Calling Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
pri_message("%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1]), ie->data[1] & 0x7f, cnum);
pri_message("%c Presentation: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, cnum);
}
static void dump_calling_party_subaddr(q931_ie *ie, int len, char prefix)
@@ -758,7 +760,7 @@ static void dump_redirecting_number(q931_ie *ie, int len, char prefix)
char cnum[256];
q931_get_number(cnum, sizeof(cnum), ie->data + 3, len - 5);
pri_message("%c Redirecting Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d)\n", prefix, len, ie->data[0] >> 7, ton2str((ie->data[0] >> 4) & 0x07), (ie->data[0] >> 4) & 0x07, npi2str(ie->data[0] & 0x0f), ie->data[0] & 0x0f);
pri_message("%c Presentation: %s (%d) Reason: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1]), ie->data[1] & 0x7f, redirection_reason2str(ie->data[2]), ie->data[2], cnum);
pri_message("%c Presentation: %s (%d) Reason: %s (%d) '%s' ]\n", prefix, pri_pres2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f, redirection_reason2str(ie->data[2]), ie->data[2], cnum);
}
@@ -785,13 +787,8 @@ static void dump_redirecting_subaddr(q931_ie *ie, int len, char prefix)
static int receive_called_party_number(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
{
#ifdef SKIP_OVERLAP_SUPPORT
/* copy digits to call->callednum */
q931_get_number(call->callednum, sizeof(call->callednum), ie->data + 1, len - 3);
#else
/* append new digits to call->callednum */
q931_get_number(call->callednum + strlen(call->callednum), sizeof(call->callednum) - strlen(call->callednum), ie->data + 1, len - 3);
#endif
call->calledplan = ie->data[0] & 0x7f;
return 0;
}
@@ -911,9 +908,12 @@ static int receive_display(struct pri *pri, q931_call *call, int msgtype, q931_i
static int transmit_display(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
{
ie->data[0] = 0xb1;
memcpy(ie->data + 1, call->callername, strlen(call->callername));
return 3 + strlen(call->callername);
if (pri->switchtype != PRI_SWITCH_NI1) {
ie->data[0] = 0xb1;
memcpy(ie->data + 1, call->callername, strlen(call->callername));
return 3 + strlen(call->callername);
}
return 0;
}
static int receive_progress_indicator(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
@@ -1136,13 +1136,14 @@ static void dump_sending_complete(q931_ie *ie, int len, char prefix)
static int receive_sending_complete(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
{
/* Do nothing */
/* We've got a "Complete" message: Exect no further digits. */
call->complete = 1;
return 0;
}
static int transmit_sending_complete(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
{
if ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) || (pri->switchtype == PRI_SWITCH_EUROISDN_T1)) {
if (!pri->overlapdial && ((pri->switchtype == PRI_SWITCH_EUROISDN_E1) || (pri->switchtype == PRI_SWITCH_EUROISDN_T1))) {
/* Include this single-byte IE */
ie->f = 1;
return 1;
@@ -1205,7 +1206,7 @@ struct ie ies[] = {
static char *ie2str(int ie)
{
int x;
unsigned int x;
for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++)
if (ies[x].ie == ie)
return ies[x].name;
@@ -1222,7 +1223,7 @@ static inline int ielen(q931_ie *ie)
static char *msg2str(int msg)
{
int x;
unsigned int x;
for (x=0;x<sizeof(msgs) / sizeof(msgs[0]); x++)
if (msgs[x].msgnum == msg)
return msgs[x].name;
@@ -1246,7 +1247,7 @@ static inline int q931_cr(q931_h *h)
static inline void q931_dumpie(q931_ie *ie, char prefix)
{
int x;
unsigned int x;
for (x=0;x<sizeof(ies) / sizeof(ies[0]); x++)
if (ies[x].ie == ie->ie) {
if (ies[x].dump)
@@ -1315,6 +1316,8 @@ static void q931_destroycall(struct pri *pri, int cr)
prev->next = cur->next;
else
pri->calls = cur->next;
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message("NEW_HANGUP DEBUG: Destroying the call, ourstate %s, peerstate %s\n",callstate2str(cur->ourcallstate),callstate2str(cur->peercallstate));
free(cur);
return;
}
@@ -1324,9 +1327,14 @@ static void q931_destroycall(struct pri *pri, int cr)
pri_error("Can't destroy call %d!\n", cr);
}
void __q931_destroycall(struct pri *pri, q931_call *c) {
if (pri && c)
q931_destroycall(pri,c->cr);
return;
}
static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen)
{
int x;
unsigned int x;
int res;
for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
if (ies[x].ie == ie) {
@@ -1385,7 +1393,7 @@ void q931_dump(q931_h *h, int len, int txrx)
static int q931_handle_ie(struct pri *pri, q931_call *c, int msg, q931_ie *ie)
{
int x;
unsigned int x;
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message("-- Processing IE %d (%s)\n", ie->ie, ie2str(ie->ie));
for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
@@ -1487,6 +1495,7 @@ static int q931_status(struct pri *pri, q931_call *c)
if (!cur) {
/* something went wrong, respond with "no such call" */
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL;
cur=c;
}
return send_message(pri, cur, Q931_STATUS, status_ies);
@@ -1505,7 +1514,8 @@ static int restart_ack_ies[] = { Q931_CHANNEL_IDENT, Q931_RESTART_INDICATOR, -1
static int restart_ack(struct pri *pri, q931_call *c)
{
c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL;
return send_message(pri, c, Q931_RESTART_ACKNOWLEDGE, restart_ack_ies);
}
@@ -1514,11 +1524,16 @@ static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, -1 };
int q931_call_proceeding(struct pri *pri, q931_call *c)
{
c->ourcallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
c->peercallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
c->proc = 1;
c->alive = 1;
return send_message(pri, c, Q931_CALL_PROCEEDING, call_proceeding_ies);
}
#ifndef ALERTING_NO_PROGRESS
static int alerting_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
#else
static int alerting_ies[] = { Q931_CHANNEL_IDENT, -1 };
#endif
int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
{
@@ -1535,6 +1550,8 @@ int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
if (!c->proc)
q931_call_proceeding(pri, c);
c->ourcallstate = Q931_CALL_STATE_CALL_RECEIVED;
c->peercallstate = Q931_CALL_STATE_CALL_DELIVERED;
c->alive = 1;
return send_message(pri, c, Q931_ALERTING, alerting_ies);
}
@@ -1553,6 +1570,8 @@ int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
} else
c->progress = -1;
c->ourcallstate = Q931_CALL_STATE_OVERLAP_RECEIVING;
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
c->alive = 1;
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
}
@@ -1569,6 +1588,8 @@ int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
} else
c->progress = -1;
c->ourcallstate = Q931_CALL_STATE_CONNECT_REQUEST;
c->peercallstate = Q931_CALL_STATE_ACTIVE;
c->alive = 1;
return send_message(pri, c, Q931_CONNECT, connect_ies);
}
@@ -1577,6 +1598,7 @@ static int release_ies[] = { Q931_CAUSE, -1 };
int q931_release(struct pri *pri, q931_call *c, int cause)
{
c->ourcallstate = Q931_CALL_STATE_RELEASE_REQUEST;
/* c->peercallstate stays the same */
if (c->alive) {
c->alive = 0;
c->cause = cause;
@@ -1605,6 +1627,7 @@ int q931_restart(struct pri *pri, int channel)
c->chanflags &= ~FLAG_PREFERRED;
c->chanflags |= FLAG_EXCLUSIVE;
c->ourcallstate = Q931_CALL_STATE_RESTART;
c->peercallstate = Q931_CALL_STATE_RESTART_REQUEST;
return send_message(pri, c, Q931_RESTART, restart_ies);
}
@@ -1613,6 +1636,7 @@ static int disconnect_ies[] = { Q931_CAUSE, -1 };
int q931_disconnect(struct pri *pri, q931_call *c, int cause)
{
c->ourcallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
c->peercallstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
if (c->alive) {
c->alive = 0;
c->cause = cause;
@@ -1680,11 +1704,13 @@ int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int ex
c->progress = Q931_PROG_CALLER_NOT_ISDN;
else
c->progress = -1;
c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
res = send_message(pri, c, Q931_SETUP, setup_ies);
if (!res) {
c->alive = 1;
/* make sure we call PRI_EVENT_HANGUP_ACK once we send/receive RELEASE_COMPLETE */
c->sendhangupack = 1;
c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
c->peercallstate = Q931_CALL_STATE_OVERLAP_SENDING;
}
return res;
@@ -1692,10 +1718,23 @@ int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int ex
static int release_complete_ies[] = { -1 };
static int q931_release_complete(struct pri *pri, q931_call *c)
static int q931_release_complete(struct pri *pri, q931_call *c, int cause)
{
int res = 0;
c->ourcallstate = Q931_CALL_STATE_NULL;
return send_message(pri, c, Q931_RELEASE_COMPLETE, release_complete_ies);
c->peercallstate = Q931_CALL_STATE_NULL;
if (cause > -1) {
c->cause = cause;
c->causecode = CODE_CCITT;
c->causeloc = LOC_PRIV_NET_LOCAL_USER;
/* release_ies has CAUSE in it */
res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies);
} else
res = send_message(pri, c, Q931_RELEASE_COMPLETE, release_complete_ies);
c->alive = 0;
/* release the structure */
res += q931_hangup(pri,c,cause);
return res;
}
static int connect_acknowledge_ies[] = { -1 };
@@ -1705,6 +1744,86 @@ static int q931_connect_acknowledge(struct pri *pri, q931_call *c)
return send_message(pri, c, Q931_CONNECT_ACKNOWLEDGE, connect_acknowledge_ies);
}
int q931_hangup(struct pri *pri, q931_call *c, int cause)
{
int disconnect = 1;
int release_compl = 0;
if (pri->debug & PRI_DEBUG_Q931_STATE)
pri_message("NEW_HANGUP DEBUG: Calling q931_hangup, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
if (!pri || !c)
return -1;
if (cause == 34 || cause == 44 || cause == 82 || cause == 1) {
/* We'll send RELEASE_COMPLETE with these causes */
disconnect = 0;
release_compl = 1;
}
if (cause == 6 || cause == 7 || cause == 26) {
/* We'll send RELEASE with these causes */
disconnect = 0;
}
/* All other causes we send with DISCONNECT */
switch(c->ourcallstate) {
case Q931_CALL_STATE_NULL:
if (c->peercallstate == Q931_CALL_STATE_NULL)
/* free the resources if we receive or send REL_COMPL */
q931_destroycall(pri, c->cr);
else if (c->peercallstate == Q931_CALL_STATE_RELEASE_REQUEST)
q931_release_complete(pri,c,cause);
break;
case Q931_CALL_STATE_CALL_INITIATED:
/* we sent SETUP */
case Q931_CALL_STATE_OVERLAP_SENDING:
/* received SETUP_ACKNOWLEDGE */
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
/* received CALL_PROCEEDING */
case Q931_CALL_STATE_CALL_DELIVERED:
/* received ALERTING */
case Q931_CALL_STATE_CALL_PRESENT:
/* received SETUP */
case Q931_CALL_STATE_CALL_RECEIVED:
/* sent ALERTING */
case Q931_CALL_STATE_CONNECT_REQUEST:
/* sent CONNECT */
case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
/* we sent CALL_PROCEEDING */
case Q931_CALL_STATE_ACTIVE:
/* received CONNECT */
case Q931_CALL_STATE_OVERLAP_RECEIVING:
/* received SETUP_ACKNOWLEDGE */
/* send DISCONNECT in general */
if (c->peercallstate != Q931_CALL_STATE_NULL && c->peercallstate != Q931_CALL_STATE_DISCONNECT_REQUEST && c->peercallstate != Q931_CALL_STATE_DISCONNECT_INDICATION && c->peercallstate != Q931_CALL_STATE_RELEASE_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART_REQUEST && c->peercallstate != Q931_CALL_STATE_RESTART) {
if (disconnect)
q931_disconnect(pri,c,cause);
else if (release_compl)
q931_release_complete(pri,c,cause);
else
q931_release(pri,c,cause);
} else
pri_error("Wierd, doing nothing but this shouldn't happen, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
break;
case Q931_CALL_STATE_DISCONNECT_REQUEST:
/* sent DISCONNECT */
break;
case Q931_CALL_STATE_DISCONNECT_INDICATION:
/* received DISCONNECT */
if (c->peercallstate == Q931_CALL_STATE_DISCONNECT_REQUEST)
q931_release(pri,c,cause);
case Q931_CALL_STATE_RELEASE_REQUEST:
/* sent RELEASE */
/* don't do anything, waiting for RELEASE_COMPLETE */
break;
case Q931_CALL_STATE_RESTART:
case Q931_CALL_STATE_RESTART_REQUEST:
/* sent RESTART */
pri_error("q931_hangup shouldn't be called in this state, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
break;
default:
pri_error("We're not yet handling hanging up when our state is %d, contact support@digium.com, ourstate %s, peerstate %s\n",callstate2str(c->ourcallstate),callstate2str(c->peercallstate));
return -1;
}
/* we did handle hangup properly at this point */
return 0;
}
int q931_receive(struct pri *pri, q931_h *h, int len)
{
@@ -1772,34 +1891,28 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
strcpy(c->redirectingnum, "");
c->useruserprotocoldisc = -1;
strcpy(c->useruserinfo, "");
c->ourcallstate = Q931_CALL_STATE_CALL_INITIATED;
c->complete = 0;
break;
case Q931_CONNECT:
c->ourcallstate = Q931_CALL_STATE_ACTIVE;
case Q931_ALERTING:
case Q931_PROGRESS:
c->progress = -1;
break;
case Q931_CALL_PROCEEDING:
case Q931_CONNECT_ACKNOWLEDGE:
c->ourcallstate = Q931_CALL_STATE_ACTIVE;
/* Do nothing */
break;
case Q931_RELEASE:
c->ourcallstate = Q931_CALL_STATE_NULL;
case Q931_DISCONNECT:
c->cause = -1;
c->causecode = -1;
c->causeloc = -1;
c->ourcallstate = Q931_CALL_STATE_NULL;
break;
case Q931_RELEASE_COMPLETE:
c->ourcallstate = Q931_CALL_STATE_NULL;
case Q931_STATUS:
c->cause = -1;
c->causecode = -1;
c->causeloc = -1;
c->callstate = -1;
break;
case Q931_RESTART_ACKNOWLEDGE:
c->channelno = -1;
@@ -1850,7 +1963,8 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
/* Post handling */
switch(mh->msg) {
case Q931_RESTART:
c->ourcallstate = Q931_CALL_STATE_RESTART_REQUEST;
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 */
@@ -1859,7 +1973,9 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
return Q931_RES_HAVEEVENT;
case Q931_SETUP:
c->ourcallstate = Q931_CALL_STATE_CALL_PRESENT;
c->alive = 1;
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;
pri->ev.e = PRI_EVENT_RING;
pri->ev.ring.channel = c->channelno;
pri->ev.ring.callingpres = c->callerpres;
@@ -1874,6 +1990,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.ring.cref = c->cr;
pri->ev.ring.call = c;
pri->ev.ring.layer1 = c->userl1;
pri->ev.ring.complete = c->complete;
if (c->transmoderate != TRANS_MODE_64_CIRCUIT) {
q931_release(pri, c, PRI_CAUSE_BEARERCAPABILITY_NOTIMPL);
break;
@@ -1881,6 +1998,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
return Q931_RES_HAVEEVENT;
case Q931_ALERTING:
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;
pri->ev.ringing.cref = c->cr;
@@ -1888,6 +2006,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
return Q931_RES_HAVEEVENT;
case Q931_CONNECT:
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;
pri->ev.answer.cref = c->cr;
@@ -1906,73 +2025,84 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
#endif
return Q931_RES_HAVEEVENT;
case Q931_PROGRESS:
case Q931_CALL_PROCEEDING:
pri->ev.e = PRI_EVENT_PROCEEDING;
pri->ev.proceeding.channel = c->channelno;
c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
c->peercallstate = Q931_CALL_STATE_INCOMING_CALL_PROCEEDING;
return Q931_RES_HAVEEVENT;
case Q931_CONNECT_ACKNOWLEDGE:
c->ourcallstate = Q931_CALL_STATE_ACTIVE;
c->peercallstate = Q931_CALL_STATE_ACTIVE;
break;
case Q931_STATUS:
/* Do nothing */
/* FIXME if the callstate != ourcallstate send RELEASE */
if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) &&
(c->cause != PRI_CAUSE_INTERWORKING))
pri_error("Received unsolicited status: %s\n", pri_cause2str(c->cause));
break;
case Q931_CALL_PROCEEDING:
c->ourcallstate = Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING;
break;
case Q931_RELEASE_COMPLETE:
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_NULL;
pri->ev.hangup.channel = c->channelno;
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c;
/* Free resources */
if (c->alive) {
pri->ev.e = PRI_EVENT_HANGUP;
pri->ev.hangup.channel = c->channelno;
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c;
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;
q931_destroycall(pri, c->cr);
if (res)
return res;
else
q931_hangup(pri,c,c->cause);
break;
case Q931_RELEASE:
c->ourcallstate = Q931_CALL_STATE_NULL;
c->peercallstate = Q931_CALL_STATE_RELEASE_REQUEST;
pri->ev.e = PRI_EVENT_HANGUP;
pri->ev.hangup.channel = c->channelno;
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c;
if (c->alive)
res = Q931_RES_HAVEEVENT;
else if (c->sendhangupack) {
res = Q931_RES_HAVEEVENT;
pri->ev.e = PRI_EVENT_HANGUP_ACK;
} else
res = 0;
q931_release_complete(pri, c);
/* Free resources */
q931_destroycall(pri, c->cr);
if (res)
return res;
break;
return Q931_RES_HAVEEVENT;
case Q931_DISCONNECT:
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;
pri->ev.e = PRI_EVENT_HANGUP_REQ;
pri->ev.hangup.channel = c->channelno;
pri->ev.hangup.cref = c->cr;
pri->ev.hangup.cause = c->cause;
pri->ev.hangup.call = c;
#if 0 /* Require the user app to call release */
/* Send a release with no cause */
q931_release(pri, c, -1);
return Q931_RES_HAVEEVENT;
#endif
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;
pri->ev.e = PRI_EVENT_RESTART_ACK;
pri->ev.restartack.channel = c->channelno;
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->ourcallstate!=Q931_CALL_STATE_OVERLAP_RECEIVING)
break;
@@ -1980,13 +2110,17 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
pri->ev.ring.call = c;
pri->ev.ring.channel = c->channelno;
strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1);
pri->ev.ring.complete = c->complete; /* this covers IE 33 (Sending Complete) */
return Q931_RES_HAVEEVENT;
case Q931_STATUS_ENQUIRY:
q931_status(pri,c);
break;
case Q931_SETUP_ACKNOWLEDGE:
c->ourcallstate = Q931_CALL_STATE_OVERLAP_SENDING;
break;
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_USER_INFORMATION:
case Q931_SEGMENT:
case Q931_CONGESTION_CONTROL: