mer feb 12 14:56:57 CET 2003
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@29 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
64f6535c65
commit
c0ce1c85ed
25
libpri.h
25
libpri.h
@ -60,6 +60,8 @@
|
|||||||
#define PRI_EVENT_ANSWER 8 /* Call has been answered */
|
#define PRI_EVENT_ANSWER 8 /* Call has been answered */
|
||||||
#define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
|
#define PRI_EVENT_HANGUP_ACK 9 /* Call hangup has been acknowledged */
|
||||||
#define PRI_EVENT_RESTART_ACK 10 /* Restart complete on a given channel */
|
#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 */
|
||||||
|
|
||||||
/* Simple states */
|
/* Simple states */
|
||||||
#define PRI_STATE_DOWN 0
|
#define PRI_STATE_DOWN 0
|
||||||
@ -205,14 +207,26 @@ typedef struct pri_event_answer {
|
|||||||
q931_call *call;
|
q931_call *call;
|
||||||
} pri_event_answer;
|
} pri_event_answer;
|
||||||
|
|
||||||
|
typedef struct pri_event_facname {
|
||||||
|
int e;
|
||||||
|
char callingname[256];
|
||||||
|
char callingnum[256];
|
||||||
|
int channel;
|
||||||
|
int cref;
|
||||||
|
q931_call *call;
|
||||||
|
} pri_event_facname;
|
||||||
|
|
||||||
typedef struct pri_event_ring {
|
typedef struct pri_event_ring {
|
||||||
int e;
|
int e;
|
||||||
int channel; /* Channel requested */
|
int channel; /* Channel requested */
|
||||||
int callingpres; /* Presentation of Calling CallerID */
|
int callingpres; /* Presentation of Calling CallerID */
|
||||||
int callingplan; /* Dialing plan of Calling entity */
|
int callingplan; /* Dialing plan of Calling entity */
|
||||||
char callingnum[256]; /* Calling number */
|
char callingnum[256]; /* Calling number */
|
||||||
|
char callingname[256]; /* Calling name (if provided) */
|
||||||
int calledplan; /* Dialing plan of Called number */
|
int calledplan; /* Dialing plan of Called number */
|
||||||
char callednum[256]; /* Called number */
|
char callednum[256]; /* Called number */
|
||||||
|
char redirectingnum[256]; /* Redirecting number */
|
||||||
|
char useruserinfo[256]; /* User->User info */
|
||||||
int flexible; /* Are we flexible with our channel selection? */
|
int flexible; /* Are we flexible with our channel selection? */
|
||||||
int cref; /* Call Reference Number */
|
int cref; /* Call Reference Number */
|
||||||
int ctype; /* Call type (see PRI_TRANS_CAP_* */
|
int ctype; /* Call type (see PRI_TRANS_CAP_* */
|
||||||
@ -238,6 +252,7 @@ typedef union {
|
|||||||
pri_event_generic gen; /* Generic view */
|
pri_event_generic gen; /* Generic view */
|
||||||
pri_event_restart restart; /* Restart view */
|
pri_event_restart restart; /* Restart view */
|
||||||
pri_event_error err; /* Error view */
|
pri_event_error err; /* Error view */
|
||||||
|
pri_event_facname facname; /* Caller*ID Name on Facility */
|
||||||
pri_event_ring ring; /* Ring */
|
pri_event_ring ring; /* Ring */
|
||||||
pri_event_hangup hangup; /* Hang up */
|
pri_event_hangup hangup; /* Hang up */
|
||||||
pri_event_ringing ringing; /* Ringing */
|
pri_event_ringing ringing; /* Ringing */
|
||||||
@ -293,6 +308,10 @@ extern char *pri_cause2str(int cause);
|
|||||||
is in-band data available on the channel */
|
is in-band data available on the channel */
|
||||||
extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
|
extern int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info);
|
||||||
|
|
||||||
|
/* Answer the incomplete(call without called number) call on the given channel.
|
||||||
|
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
|
||||||
|
extern int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||||
|
|
||||||
/* Answer the call on the given channel (ignored if you called acknowledge already).
|
/* Answer the call on the given channel (ignored if you called acknowledge already).
|
||||||
Set non-isdn to non-zero if you are not connecting to ISDN equipment */
|
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);
|
extern int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||||
@ -315,6 +334,10 @@ extern struct timeval *pri_schedule_next(struct pri *pri);
|
|||||||
extern pri_event *pri_schedule_run(struct pri *pri);
|
extern pri_event *pri_schedule_run(struct pri *pri);
|
||||||
|
|
||||||
extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
|
extern int pri_call(struct pri *pri, q931_call *c, int transmode, int channel,
|
||||||
int exclusive, int nonisdn, char *caller, int callerplan, int callerpres,
|
int exclusive, int nonisdn, char *caller, int callerplan, char *callername, int callerpres,
|
||||||
char *called,int calledplan, int ulayer1);
|
char *called,int calledplan, int ulayer1);
|
||||||
|
|
||||||
|
/* Override message and error stuff */
|
||||||
|
extern void pri_set_message(void (*__pri_error)(char *));
|
||||||
|
extern void pri_set_error(void (*__pri_error)(char *));
|
||||||
#endif
|
#endif
|
||||||
|
73
pri.c
73
pri.c
@ -18,6 +18,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include "libpri.h"
|
#include "libpri.h"
|
||||||
#include "pri_internal.h"
|
#include "pri_internal.h"
|
||||||
#include "pri_q921.h"
|
#include "pri_q921.h"
|
||||||
@ -64,7 +65,7 @@ struct pri *pri_new(int fd, int node, int switchtype)
|
|||||||
p->switchtype = switchtype;
|
p->switchtype = switchtype;
|
||||||
p->cref = 1;
|
p->cref = 1;
|
||||||
/* Start Q.921 layer */
|
/* Start Q.921 layer */
|
||||||
q921_start(p);
|
q921_start(p, 1);
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@ -95,9 +96,11 @@ pri_event *pri_check_event(struct pri *pri)
|
|||||||
res = read(pri->fd, buf, sizeof(buf));
|
res = read(pri->fd, buf, sizeof(buf));
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
fprintf(stderr, "Read on %d failed: %s\n", pri->fd, strerror(errno));
|
pri_error("Read on %d failed: %s\n", pri->fd, strerror(errno));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (!res)
|
||||||
|
return NULL;
|
||||||
/* Receive the q921 packet */
|
/* Receive the q921 packet */
|
||||||
e = q921_receive(pri, (q921_h *)buf, res);
|
e = q921_receive(pri, (q921_h *)buf, res);
|
||||||
return e;
|
return e;
|
||||||
@ -178,6 +181,13 @@ int pri_acknowledge(struct pri *pri, q931_call *call, int channel, int info)
|
|||||||
return q931_alerting(pri, call, channel, info);
|
return q931_alerting(pri, call, channel, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int pri_need_more_info(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||||
|
{
|
||||||
|
if (!pri || !call)
|
||||||
|
return -1;
|
||||||
|
return q931_setup_ack(pri, call, channel, nonisdn);
|
||||||
|
}
|
||||||
|
|
||||||
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
int pri_answer(struct pri *pri, q931_call *call, int channel, int nonisdn)
|
||||||
{
|
{
|
||||||
if (!pri || !call)
|
if (!pri || !call)
|
||||||
@ -217,34 +227,73 @@ void pri_dump_event(struct pri *pri, pri_event *e)
|
|||||||
{
|
{
|
||||||
if (!pri || !e)
|
if (!pri || !e)
|
||||||
return;
|
return;
|
||||||
printf("Event type: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
|
pri_message("Event type: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
|
||||||
switch(e->gen.e) {
|
switch(e->gen.e) {
|
||||||
case PRI_EVENT_DCHAN_UP:
|
case PRI_EVENT_DCHAN_UP:
|
||||||
case PRI_EVENT_DCHAN_DOWN:
|
case PRI_EVENT_DCHAN_DOWN:
|
||||||
break;
|
break;
|
||||||
case PRI_EVENT_CONFIG_ERR:
|
case PRI_EVENT_CONFIG_ERR:
|
||||||
printf("Error: %s", e->err.err);
|
pri_message("Error: %s", e->err.err);
|
||||||
break;
|
break;
|
||||||
case PRI_EVENT_RESTART:
|
case PRI_EVENT_RESTART:
|
||||||
printf("Restart on channel %d\n", e->restart.channel);
|
pri_message("Restart on channel %d\n", e->restart.channel);
|
||||||
case PRI_EVENT_RING:
|
case PRI_EVENT_RING:
|
||||||
printf("Calling number: %s (%s, %s)\n", e->ring.callingnum, pri_plan2str(e->ring.callingplan), pri_pres2str(e->ring.callingpres));
|
pri_message("Calling number: %s (%s, %s)\n", e->ring.callingnum, pri_plan2str(e->ring.callingplan), pri_pres2str(e->ring.callingpres));
|
||||||
printf("Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan));
|
pri_message("Called number: %s (%s)\n", e->ring.callednum, pri_plan2str(e->ring.calledplan));
|
||||||
printf("Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref);
|
pri_message("Channel: %d (%s) Reference number: %d\n", e->ring.channel, e->ring.flexible ? "Flexible" : "Not Flexible", e->ring.cref);
|
||||||
break;
|
break;
|
||||||
case PRI_EVENT_HANGUP:
|
case PRI_EVENT_HANGUP:
|
||||||
printf("Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause));
|
pri_message("Hangup, reference number: %d, reason: %s\n", e->hangup.cref, pri_cause2str(e->hangup.cause));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("Don't know how to dump events of type %d\n", e->gen.e);
|
pri_message("Don't know how to dump events of type %d\n", e->gen.e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
int pri_call(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
||||||
int nonisdn, char *caller, int callerplan, int callerpres, char *called,
|
int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
|
||||||
int calledplan,int ulayer1)
|
int calledplan,int ulayer1)
|
||||||
{
|
{
|
||||||
if (!pri || !c)
|
if (!pri || !c)
|
||||||
return -1;
|
return -1;
|
||||||
return q931_setup(pri, c, transmode, channel, exclusive, nonisdn, caller, callerplan, callerpres, called, calledplan, ulayer1);
|
return q931_setup(pri, c, transmode, channel, exclusive, nonisdn, caller, callerplan, callername, callerpres, called, calledplan, ulayer1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (*__pri_error)(char *stuff);
|
||||||
|
static void (*__pri_message)(char *stuff);
|
||||||
|
|
||||||
|
void pri_set_message(void (*func)(char *stuff))
|
||||||
|
{
|
||||||
|
__pri_message = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pri_set_error(void (*func)(char *stuff))
|
||||||
|
{
|
||||||
|
__pri_error = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pri_message(char *fmt, ...)
|
||||||
|
{
|
||||||
|
char tmp[1024];
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (__pri_message)
|
||||||
|
__pri_message(tmp);
|
||||||
|
else
|
||||||
|
fprintf(stdout, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pri_error(char *fmt, ...)
|
||||||
|
{
|
||||||
|
char tmp[1024];
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(tmp, sizeof(tmp), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (__pri_error)
|
||||||
|
__pri_error(tmp);
|
||||||
|
else
|
||||||
|
fprintf(stderr, tmp);
|
||||||
}
|
}
|
||||||
|
@ -88,4 +88,8 @@ extern void pri_schedule_del(struct pri *pri, int ev);
|
|||||||
|
|
||||||
extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
|
extern pri_event *pri_mkerror(struct pri *pri, char *errstr);
|
||||||
|
|
||||||
|
extern void pri_message(char *fmt, ...);
|
||||||
|
|
||||||
|
extern void pri_error(char *fmt, ...);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,7 +137,7 @@ typedef struct q921_frame {
|
|||||||
q921_i h;
|
q921_i h;
|
||||||
} q921_frame;
|
} q921_frame;
|
||||||
|
|
||||||
#define Q921_INC(j) (j) = ((j) + 1) % 128
|
#define Q921_INC(j) (j) = (((j) + 1) % 128)
|
||||||
|
|
||||||
typedef enum q921_state {
|
typedef enum q921_state {
|
||||||
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
|
Q921_LINK_CONNECTION_RELEASED, /* Also known as TEI_ASSIGNED */
|
||||||
@ -150,7 +150,7 @@ typedef enum q921_state {
|
|||||||
extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
|
extern void q921_dump(q921_h *h, int len, int showraw, int txrx);
|
||||||
|
|
||||||
/* Bring up the D-channel */
|
/* Bring up the D-channel */
|
||||||
extern void q921_start(struct pri *pri);
|
extern void q921_start(struct pri *pri, int now);
|
||||||
|
|
||||||
extern void q921_reset(struct pri *pri);
|
extern void q921_reset(struct pri *pri);
|
||||||
|
|
||||||
|
@ -190,6 +190,7 @@ typedef struct q931_ie {
|
|||||||
#define Q931_LOW_LAYER_COMPAT 0x7c
|
#define Q931_LOW_LAYER_COMPAT 0x7c
|
||||||
#define Q931_HIGH_LAYER_COMPAT 0x7d
|
#define Q931_HIGH_LAYER_COMPAT 0x7d
|
||||||
|
|
||||||
|
#define Q931_DISPLAY 0x28
|
||||||
#define Q931_IE_SEGMENTED_MSG 0x00
|
#define Q931_IE_SEGMENTED_MSG 0x00
|
||||||
#define Q931_IE_CHANGE_STATUS 0x01
|
#define Q931_IE_CHANGE_STATUS 0x01
|
||||||
#define Q931_IE_CONNECTED_NUM 0x0C
|
#define Q931_IE_CONNECTED_NUM 0x0C
|
||||||
@ -197,7 +198,6 @@ typedef struct q931_ie {
|
|||||||
#define Q931_IE_FACILITY 0x1c
|
#define Q931_IE_FACILITY 0x1c
|
||||||
#define Q931_IE_ENDPOINT_ID 0x26
|
#define Q931_IE_ENDPOINT_ID 0x26
|
||||||
#define Q931_IE_NOTIFY_IND 0x27
|
#define Q931_IE_NOTIFY_IND 0x27
|
||||||
#define Q931_IE_DISPLAY 0x28
|
|
||||||
#define Q931_IE_TIME_DATE 0x29
|
#define Q931_IE_TIME_DATE 0x29
|
||||||
#define Q931_IE_KEYPAD_FACILITY 0x2c
|
#define Q931_IE_KEYPAD_FACILITY 0x2c
|
||||||
#define Q931_IE_CALL_STATUS 0x2d
|
#define Q931_IE_CALL_STATUS 0x2d
|
||||||
@ -223,6 +223,8 @@ extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info
|
|||||||
|
|
||||||
extern int q931_call_proceeding(struct pri *pri, q931_call *call);
|
extern int q931_call_proceeding(struct pri *pri, q931_call *call);
|
||||||
|
|
||||||
|
extern int q931_setup_ack(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||||
|
|
||||||
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
extern int q931_connect(struct pri *pri, q931_call *call, int channel, int nonisdn);
|
||||||
|
|
||||||
extern int q931_release(struct pri *pri, q931_call *call, int cause);
|
extern int q931_release(struct pri *pri, q931_call *call, int cause);
|
||||||
@ -234,7 +236,7 @@ extern int q931_restart(struct pri *pri, int channel);
|
|||||||
extern q931_call *q931_new_call(struct pri *pri);
|
extern q931_call *q931_new_call(struct pri *pri);
|
||||||
|
|
||||||
extern int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
extern int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
||||||
int nonisdn, char *caller, int callerplan, int callerpres, char *called,
|
int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
|
||||||
int calledplan, int ulay1);
|
int calledplan, int ulay1);
|
||||||
extern void q931_dump(q931_h *h, int len, int txrx);
|
extern void q931_dump(q931_h *h, int len, int txrx);
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,7 +38,7 @@ int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), vo
|
|||||||
if (!pri->pri_sched[x].callback)
|
if (!pri->pri_sched[x].callback)
|
||||||
break;
|
break;
|
||||||
if (x == MAX_SCHED) {
|
if (x == MAX_SCHED) {
|
||||||
fprintf(stderr, "No more room in scheduler\n");
|
pri_error("No more room in scheduler\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (x > maxsched)
|
if (x > maxsched)
|
||||||
@ -98,6 +98,6 @@ pri_event *pri_schedule_run(struct pri *pri)
|
|||||||
void pri_schedule_del(struct pri *pri,int id)
|
void pri_schedule_del(struct pri *pri,int id)
|
||||||
{
|
{
|
||||||
if ((id >= MAX_SCHED) || (id < 0))
|
if ((id >= MAX_SCHED) || (id < 0))
|
||||||
fprintf(stderr, "Asked to delete sched id %d???\n", id);
|
pri_error("Asked to delete sched id %d???\n", id);
|
||||||
pri->pri_sched[id].callback = NULL;
|
pri->pri_sched[id].callback = NULL;
|
||||||
}
|
}
|
||||||
|
54
pritest.c
54
pritest.c
@ -48,6 +48,8 @@
|
|||||||
#define PRI_DEF_SWITCHTYPE PRI_SWITCH_NI2
|
#define PRI_DEF_SWITCHTYPE PRI_SWITCH_NI2
|
||||||
|
|
||||||
#define MAX_CHAN 32
|
#define MAX_CHAN 32
|
||||||
|
#define DCHANNEL_TIMESLOT 16
|
||||||
|
|
||||||
|
|
||||||
static int offset = 0;
|
static int offset = 0;
|
||||||
|
|
||||||
@ -162,10 +164,50 @@ static void launch_channel(int channo)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_free_channel(int channo)
|
||||||
|
{
|
||||||
|
channo--;
|
||||||
|
if((channo>MAX_CHAN)||(channo<0)) {
|
||||||
|
fprintf(stderr, "Invalid Bchannel RANGE <%d", channo);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
while(chans[channo].pid) {
|
||||||
|
channo--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return channo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* place here criteria for completion of destination number */
|
||||||
|
static int number_incommplete(char *number)
|
||||||
|
{
|
||||||
|
return strlen(number) < 3;
|
||||||
|
}
|
||||||
|
|
||||||
static void start_channel(struct pri *pri, pri_event *e)
|
static void start_channel(struct pri *pri, pri_event *e)
|
||||||
{
|
{
|
||||||
int channo = e->ring.channel;
|
int channo = e->ring.channel;
|
||||||
|
int flag = 1;
|
||||||
|
pri_event_ring *ring = &e->ring;
|
||||||
|
|
||||||
|
if(channo == -1) {
|
||||||
|
channo = e->ring.channel = get_free_channel(MAX_CHAN);
|
||||||
|
|
||||||
|
if(channo == DCHANNEL_TIMESLOT)
|
||||||
|
channo = e->ring.channel = get_free_channel(MAX_CHAN);
|
||||||
|
|
||||||
|
|
||||||
|
fprintf(stdout, "Any channel selected: %d\n", channo);
|
||||||
|
|
||||||
|
if(!channo) {
|
||||||
|
pri_release(pri, ring->call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
|
||||||
|
fprintf(stdout, "Abort call due to no avl B channels\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = 0;
|
||||||
|
}
|
||||||
/* Make sure it's a valid number */
|
/* Make sure it's a valid number */
|
||||||
if ((channo >= MAX_CHAN) || (channo < 0)) {
|
if ((channo >= MAX_CHAN) || (channo < 0)) {
|
||||||
fprintf(stderr, "--!! Channel %d is out of range\n", channo);
|
fprintf(stderr, "--!! Channel %d is out of range\n", channo);
|
||||||
@ -185,7 +227,11 @@ static void start_channel(struct pri *pri, pri_event *e)
|
|||||||
chans[channo].call = e->ring.call;
|
chans[channo].call = e->ring.call;
|
||||||
|
|
||||||
/* Answer the line */
|
/* Answer the line */
|
||||||
|
if(flag) {
|
||||||
pri_answer(pri, chans[channo].call, channo, 1);
|
pri_answer(pri, chans[channo].call, channo, 1);
|
||||||
|
} else {
|
||||||
|
pri_need_more_info(pri, chans[channo].call, channo, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Launch a process to handle it */
|
/* Launch a process to handle it */
|
||||||
launch_channel(channo);
|
launch_channel(channo);
|
||||||
@ -222,6 +268,14 @@ static void handle_pri_event(struct pri *pri, pri_event *e)
|
|||||||
break;
|
break;
|
||||||
case PRI_EVENT_HANGUP_ACK:
|
case PRI_EVENT_HANGUP_ACK:
|
||||||
/* Ignore */
|
/* Ignore */
|
||||||
|
break;
|
||||||
|
case PRI_EVENT_INFO_RECEIVED:
|
||||||
|
fprintf(stdout, "number is: %s\n", e->ring.callednum);
|
||||||
|
if(!number_incommplete(e->ring.callednum)) {
|
||||||
|
fprintf(stdout, "final number is: %s\n", e->ring.callednum);
|
||||||
|
pri_answer(pri, e->ring.call, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
|
fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
|
||||||
|
179
q921.c
179
q921.c
@ -42,6 +42,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define Q921_INIT(hf) do { \
|
#define Q921_INIT(hf) do { \
|
||||||
|
memset(&(hf),0,sizeof(hf)); \
|
||||||
(hf).h.sapi = 0; \
|
(hf).h.sapi = 0; \
|
||||||
(hf).h.ea1 = 0; \
|
(hf).h.ea1 = 0; \
|
||||||
(hf).h.ea2 = 1; \
|
(hf).h.ea2 = 1; \
|
||||||
@ -65,7 +66,7 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len) {
|
|||||||
int res;
|
int res;
|
||||||
#ifdef RANDOM_DROPS
|
#ifdef RANDOM_DROPS
|
||||||
if (!(random() % 3)) {
|
if (!(random() % 3)) {
|
||||||
printf(" === Dropping Packet ===\n");
|
pri_message(" === Dropping Packet ===\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -76,7 +77,7 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len) {
|
|||||||
/* Write an extra two bytes for the FCS */
|
/* Write an extra two bytes for the FCS */
|
||||||
res = write(pri->fd, h, len + 2);
|
res = write(pri->fd, h, len + 2);
|
||||||
if (res != (len + 2)) {
|
if (res != (len + 2)) {
|
||||||
fprintf(stderr, "Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
|
pri_error("Short write: %d/%d (%s)\n", res, len + 2, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -98,21 +99,25 @@ static void q921_send_ua(struct pri *pri, int pfbit)
|
|||||||
h.h.c_r = 1;
|
h.h.c_r = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Don't know how to U/A on a type %d node\n", pri->localtype);
|
pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("Sending Unnumbered Acknowledgement\n");
|
pri_message("Sending Unnumbered Acknowledgement\n");
|
||||||
q921_transmit(pri, &h, 3);
|
q921_transmit(pri, &h, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void q921_send_sabme(void *vpri)
|
static void q921_send_sabme_now(void *vpri);
|
||||||
|
|
||||||
|
static void q921_send_sabme(void *vpri, int now)
|
||||||
{
|
{
|
||||||
struct pri *pri = vpri;
|
struct pri *pri = vpri;
|
||||||
q921_h h;
|
q921_h h;
|
||||||
pri_schedule_del(pri, pri->sabme_timer);
|
pri_schedule_del(pri, pri->sabme_timer);
|
||||||
pri->sabme_timer = 0;
|
pri->sabme_timer = 0;
|
||||||
pri->sabme_timer = pri_schedule_event(pri, T_200, q921_send_sabme, pri);
|
pri->sabme_timer = pri_schedule_event(pri, T_200, q921_send_sabme_now, pri);
|
||||||
|
if (!now)
|
||||||
|
return;
|
||||||
Q921_INIT(h);
|
Q921_INIT(h);
|
||||||
h.u.m3 = 3; /* M3 = 3 */
|
h.u.m3 = 3; /* M3 = 3 */
|
||||||
h.u.m2 = 3; /* M2 = 3 */
|
h.u.m2 = 3; /* M2 = 3 */
|
||||||
@ -126,31 +131,42 @@ static void q921_send_sabme(void *vpri)
|
|||||||
h.h.c_r = 0;
|
h.h.c_r = 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Don't know how to U/A on a type %d node\n", pri->localtype);
|
pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("Sending Set Asynchronous Balanced Mode Extended\n");
|
pri_message("Sending Set Asynchronous Balanced Mode Extended\n");
|
||||||
q921_transmit(pri, &h, 3);
|
q921_transmit(pri, &h, 3);
|
||||||
pri->q921_state = Q921_AWAITING_ESTABLISH;
|
pri->q921_state = Q921_AWAITING_ESTABLISH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void q921_send_sabme_now(void *vpri)
|
||||||
|
{
|
||||||
|
q921_send_sabme(vpri, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static int q921_ack_packet(struct pri *pri, int num)
|
static int q921_ack_packet(struct pri *pri, int num)
|
||||||
{
|
{
|
||||||
struct q921_frame *f, *prev = NULL;
|
struct q921_frame *f, *prev = NULL;
|
||||||
f = pri->txqueue;
|
f = pri->txqueue;
|
||||||
while(f) {
|
while(f) {
|
||||||
if (f->h.n_s == num) {
|
if (f->h.n_s == num) {
|
||||||
|
/* Cancel each packet as necessary */
|
||||||
/* That's our packet */
|
/* That's our packet */
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->next = f->next;
|
prev->next = f->next;
|
||||||
else
|
else
|
||||||
pri->txqueue = f->next;
|
pri->txqueue = f->next;
|
||||||
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
|
pri_message("-- ACKing packet %d, new txqueue is %d (-1 means empty)\n", f->h.n_s, pri->txqueue ? pri->txqueue->h.n_s : -1);
|
||||||
|
/* Update v_a */
|
||||||
|
pri->v_a = num;
|
||||||
free(f);
|
free(f);
|
||||||
/* Reset retransmission counter if we actually acked something */
|
/* Reset retransmission counter if we actually acked something */
|
||||||
pri->retrans = 0;
|
pri->retrans = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
prev = f;
|
||||||
f = f->next;
|
f = f->next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -167,34 +183,36 @@ static void q921_ack_rx(struct pri *pri, int ack)
|
|||||||
for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
|
for (x=pri->v_a; (x != pri->v_s) && (x != ack); Q921_INC(x));
|
||||||
if (x != ack) {
|
if (x != ack) {
|
||||||
/* ACK was outside of our window --- ignore */
|
/* ACK was outside of our window --- ignore */
|
||||||
fprintf(stderr, "ACK received outside of window, ignoring\n");
|
pri_error("ACK received outside of window, ignoring\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Cancel each packet as necessary */
|
/* Cancel each packet as necessary */
|
||||||
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
|
pri_message("-- ACKing all packets from %d to (but not including) %d\n", pri->v_a, ack);
|
||||||
for (x=pri->v_a; x != ack; Q921_INC(x))
|
for (x=pri->v_a; x != ack; Q921_INC(x))
|
||||||
cnt += q921_ack_packet(pri, x);
|
cnt += q921_ack_packet(pri, x);
|
||||||
if (!pri->txqueue) {
|
if (!pri->txqueue) {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Since there was nothing left, stopping T200 counter\n");
|
pri_message("-- Since there was nothing left, stopping T200 counter\n");
|
||||||
/* Something was ACK'd. Stop T200 counter */
|
/* Something was ACK'd. Stop T200 counter */
|
||||||
pri_schedule_del(pri, pri->t200_timer);
|
pri_schedule_del(pri, pri->t200_timer);
|
||||||
pri->t200_timer = 0;
|
pri->t200_timer = 0;
|
||||||
}
|
}
|
||||||
if (pri->t203_timer) {
|
if (pri->t203_timer) {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Stopping T203 counter since we got an ACK\n");
|
pri_message("-- Stopping T203 counter since we got an ACK\n");
|
||||||
pri_schedule_del(pri, pri->t203_timer);
|
pri_schedule_del(pri, pri->t203_timer);
|
||||||
pri->t203_timer = 0;
|
pri->t203_timer = 0;
|
||||||
}
|
}
|
||||||
if (pri->txqueue) {
|
if (pri->txqueue) {
|
||||||
/* Something left to transmit, Start the T200 counter again if we stopped it */
|
/* Something left to transmit, Start the T200 counter again if we stopped it */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Something left to transmit, restarting T200 counter\n");
|
pri_message("-- Something left to transmit (%d), restarting T200 counter\n", pri->txqueue->h.n_s);
|
||||||
if (!pri->t200_timer)
|
if (!pri->t200_timer)
|
||||||
pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
|
pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
|
||||||
} else {
|
} else {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Nothing left, starting T203 counter\n");
|
pri_message("-- Nothing left, starting T203 counter\n");
|
||||||
/* Nothing to transmit, start the T203 counter instead */
|
/* Nothing to transmit, start the T203 counter instead */
|
||||||
pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
|
pri->t203_timer = pri_schedule_event(pri, T_203, t203_expire, pri);
|
||||||
}
|
}
|
||||||
@ -217,11 +235,11 @@ static void q921_reject(struct pri *pri)
|
|||||||
h.h.c_r = 1;
|
h.h.c_r = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Don't know how to U/A on a type %d node\n", pri->localtype);
|
pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("Sending Reject (%d)\n", pri->v_r);
|
pri_message("Sending Reject (%d)\n", pri->v_r);
|
||||||
q921_transmit(pri, &h, 4);
|
q921_transmit(pri, &h, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,12 +259,12 @@ static void q921_rr(struct pri *pri, int pbit) {
|
|||||||
h.h.c_r = 1;
|
h.h.c_r = 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Don't know how to U/A on a type %d node\n", pri->localtype);
|
pri_error("Don't know how to U/A on a type %d node\n", pri->localtype);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pri->v_na = pri->v_r; /* Make a note that we've already acked this */
|
pri->v_na = pri->v_r; /* Make a note that we've already acked this */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("Sending Receiver Ready (%d)\n", pri->v_r);
|
pri_message("Sending Receiver Ready (%d)\n", pri->v_r);
|
||||||
q921_transmit(pri, &h, 4);
|
q921_transmit(pri, &h, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +276,7 @@ static void t200_expire(void *vpri)
|
|||||||
if (pri->txqueue) {
|
if (pri->txqueue) {
|
||||||
/* Retransmit first packet in the queue, setting the poll bit */
|
/* Retransmit first packet in the queue, setting the poll bit */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- T200 counter expired, What to do...\n");
|
pri_message("-- T200 counter expired, What to do...\n");
|
||||||
/* Force Poll bit */
|
/* Force Poll bit */
|
||||||
pri->txqueue->h.p_f = 1;
|
pri->txqueue->h.p_f = 1;
|
||||||
/* Update nr */
|
/* Update nr */
|
||||||
@ -270,22 +288,22 @@ static void t200_expire(void *vpri)
|
|||||||
if (pri->retrans < N_200) {
|
if (pri->retrans < N_200) {
|
||||||
/* Reschedule t200_timer */
|
/* Reschedule t200_timer */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Retransmitting %d bytes\n", pri->txqueue->len);
|
pri_message("-- Retransmitting %d bytes\n", pri->txqueue->len);
|
||||||
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
|
q921_transmit(pri, (q921_h *)&pri->txqueue->h, pri->txqueue->len);
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Rescheduling retransmission (%d)\n", pri->retrans);
|
pri_message("-- Rescheduling retransmission (%d)\n", pri->retrans);
|
||||||
pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
|
pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
|
||||||
} else {
|
} else {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Timeout occured, restarting PRI\n");
|
pri_message("-- Timeout occured, restarting PRI\n");
|
||||||
pri->state = Q921_LINK_CONNECTION_RELEASED;
|
pri->state = Q921_LINK_CONNECTION_RELEASED;
|
||||||
pri->t200_timer = 0;
|
pri->t200_timer = 0;
|
||||||
q921_dchannel_down(pri);
|
q921_dchannel_down(pri);
|
||||||
q921_start(pri);
|
q921_start(pri, 1);
|
||||||
pri->schedev = 1;
|
pri->schedev = 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "T200 counter expired, nothing to send...\n");
|
pri_error("T200 counter expired, nothing to send...\n");
|
||||||
pri->t200_timer = 0;
|
pri->t200_timer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,6 +313,7 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
|
|||||||
q921_frame *f, *prev=NULL;
|
q921_frame *f, *prev=NULL;
|
||||||
for (f=pri->txqueue; f; f = f->next) prev = f;
|
for (f=pri->txqueue; f; f = f->next) prev = f;
|
||||||
f = malloc(sizeof(q921_frame) + len + 2);
|
f = malloc(sizeof(q921_frame) + len + 2);
|
||||||
|
memset(f,0,sizeof(q921_frame) + len + 2);
|
||||||
if (f) {
|
if (f) {
|
||||||
Q921_INIT(f->h);
|
Q921_INIT(f->h);
|
||||||
switch(pri->localtype) {
|
switch(pri->localtype) {
|
||||||
@ -329,20 +348,20 @@ int q921_transmit_iframe(struct pri *pri, void *buf, int len, int cr)
|
|||||||
q921_transmit(pri, (q921_h *)(&f->h), f->len);
|
q921_transmit(pri, (q921_h *)(&f->h), f->len);
|
||||||
if (pri->t203_timer) {
|
if (pri->t203_timer) {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("Stopping T_203 timer\n");
|
pri_message("Stopping T_203 timer\n");
|
||||||
pri_schedule_del(pri, pri->t203_timer);
|
pri_schedule_del(pri, pri->t203_timer);
|
||||||
pri->t203_timer = 0;
|
pri->t203_timer = 0;
|
||||||
}
|
}
|
||||||
if (!pri->t200_timer) {
|
if (!pri->t200_timer) {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("Starting T_200 timer\n");
|
pri_message("Starting T_200 timer\n");
|
||||||
pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
|
pri->t200_timer = pri_schedule_event(pri, T_200, t200_expire, pri);
|
||||||
} else
|
} else
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("T_200 timer already going (%d)\n", pri->t200_timer);
|
pri_message("T_200 timer already going (%d)\n", pri->t200_timer);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "!! Out of memory for Q.921 transmit\n");
|
pri_error("!! Out of memory for Q.921 transmit\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -352,7 +371,7 @@ static void t203_expire(void *vpri)
|
|||||||
{
|
{
|
||||||
struct pri *pri = vpri;
|
struct pri *pri = vpri;
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("T203 counter expired, sending RR and scheduling T203 again\n");
|
pri_message("T203 counter expired, sending RR and scheduling T203 again\n");
|
||||||
/* Solicit an F-bit in the other's RR */
|
/* Solicit an F-bit in the other's RR */
|
||||||
pri->solicitfbit = 1;
|
pri->solicitfbit = 1;
|
||||||
q921_rr(pri, 1);
|
q921_rr(pri, 1);
|
||||||
@ -404,26 +423,26 @@ void q921_dump(q921_h *h, int len, int showraw, int txrx)
|
|||||||
|
|
||||||
direction_tag = txrx ? '>' : '<';
|
direction_tag = txrx ? '>' : '<';
|
||||||
if (showraw) {
|
if (showraw) {
|
||||||
printf("\n%c [", direction_tag);
|
pri_message("\n%c [", direction_tag);
|
||||||
for (x=0;x<len;x++)
|
for (x=0;x<len;x++)
|
||||||
printf("%02x ",h->raw[x]);
|
pri_message("%02x ",h->raw[x]);
|
||||||
printf("]");
|
pri_message("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (h->h.data[0] & Q921_FRAMETYPE_MASK) {
|
switch (h->h.data[0] & Q921_FRAMETYPE_MASK) {
|
||||||
case 0:
|
case 0:
|
||||||
case 2:
|
case 2:
|
||||||
printf("\n%c Informational frame:\n", direction_tag);
|
pri_message("\n%c Informational frame:\n", direction_tag);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
printf("\n%c Supervisory frame:\n", direction_tag);
|
pri_message("\n%c Supervisory frame:\n", direction_tag);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
printf("\n%c Unnumbered frame:\n", direction_tag);
|
pri_message("\n%c Unnumbered frame:\n", direction_tag);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(
|
pri_message(
|
||||||
"%c SAPI: %02d C/R: %d EA: %d\n"
|
"%c SAPI: %02d C/R: %d EA: %d\n"
|
||||||
"%c TEI: %03d EA: %d\n",
|
"%c TEI: %03d EA: %d\n",
|
||||||
direction_tag,
|
direction_tag,
|
||||||
@ -437,7 +456,7 @@ void q921_dump(q921_h *h, int len, int showraw, int txrx)
|
|||||||
case 0:
|
case 0:
|
||||||
case 2:
|
case 2:
|
||||||
/* Informational frame */
|
/* Informational frame */
|
||||||
printf(
|
pri_message(
|
||||||
"%c N(S): %03d 0: %d\n"
|
"%c N(S): %03d 0: %d\n"
|
||||||
"%c N(R): %03d P: %d\n"
|
"%c N(R): %03d P: %d\n"
|
||||||
"%c %d bytes of data\n",
|
"%c %d bytes of data\n",
|
||||||
@ -464,7 +483,7 @@ void q921_dump(q921_h *h, int len, int showraw, int txrx)
|
|||||||
type = "REJ (reject)";
|
type = "REJ (reject)";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
printf(
|
pri_message(
|
||||||
"%c Zero: %d S: %d 01: %d [ %s ]\n"
|
"%c Zero: %d S: %d 01: %d [ %s ]\n"
|
||||||
"%c N(R): %03d P/F: %d\n"
|
"%c N(R): %03d P/F: %d\n"
|
||||||
"%c %d bytes of data\n",
|
"%c %d bytes of data\n",
|
||||||
@ -510,7 +529,7 @@ void q921_dump(q921_h *h, int len, int showraw, int txrx)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(
|
pri_message(
|
||||||
"%c M3: %d P/F: %d M2: %d 11: %d [ %s ]\n"
|
"%c M3: %d P/F: %d M2: %d 11: %d [ %s ]\n"
|
||||||
"%c %d bytes of data\n",
|
"%c %d bytes of data\n",
|
||||||
direction_tag,
|
direction_tag,
|
||||||
@ -580,6 +599,7 @@ void q921_reset(struct pri *pri)
|
|||||||
pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
||||||
{
|
{
|
||||||
q921_frame *f;
|
q921_frame *f;
|
||||||
|
int sendnow;
|
||||||
/* Discard FCS */
|
/* Discard FCS */
|
||||||
len -= 2;
|
len -= 2;
|
||||||
|
|
||||||
@ -602,23 +622,23 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
case 0:
|
case 0:
|
||||||
case 2:
|
case 2:
|
||||||
if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
|
if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
|
||||||
fprintf(stderr, "!! Got I-frame while link state %d\n", pri->q921_state);
|
pri_error("!! Got I-frame while link state %d\n", pri->q921_state);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Informational frame */
|
/* Informational frame */
|
||||||
if (len < 4) {
|
if (len < 4) {
|
||||||
fprintf(stderr, "!! Received short I-frame\n");
|
pri_error("!! Received short I-frame (expected 4, got %d)\n", len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return q921_handle_iframe(pri, &h->i, len);
|
return q921_handle_iframe(pri, &h->i, len);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
|
if (pri->q921_state != Q921_LINK_CONNECTION_ESTABLISHED) {
|
||||||
fprintf(stderr, "!! Got S-frame while link down\n");
|
pri_error("!! Got S-frame while link down\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (len < 4) {
|
if (len < 4) {
|
||||||
fprintf(stderr, "!! Received short S-frame\n");
|
pri_error("!! Received short S-frame (expected 4, got %d)\n", len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch(h->s.ss) {
|
switch(h->s.ss) {
|
||||||
@ -631,10 +651,10 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
/* If it's a p/f one then send back a RR in return with the p/f bit set */
|
/* If it's a p/f one then send back a RR in return with the p/f bit set */
|
||||||
if (pri->solicitfbit) {
|
if (pri->solicitfbit) {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Got RR response to our frame\n");
|
pri_message("-- Got RR response to our frame\n");
|
||||||
} else {
|
} else {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Unsolicited RR with P/F bit, responding\n");
|
pri_message("-- Unsolicited RR with P/F bit, responding\n");
|
||||||
q921_rr(pri, 1);
|
q921_rr(pri, 1);
|
||||||
}
|
}
|
||||||
pri->solicitfbit = 0;
|
pri->solicitfbit = 0;
|
||||||
@ -644,36 +664,38 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
case 1:
|
case 1:
|
||||||
/* Receiver not ready */
|
/* Receiver not ready */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Got receiver not ready\n");
|
pri_message("-- Got receiver not ready\n");
|
||||||
pri->busy = 1;
|
pri->busy = 1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case 2:
|
case 2:
|
||||||
/* Just retransmit */
|
/* Just retransmit */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
|
pri_message("-- Got reject requesting packet %d... Retransmitting.\n", h->s.n_r);
|
||||||
if (h->s.p_f) {
|
if (h->s.p_f) {
|
||||||
/* If it has the poll bit set, send an appropriate supervisory response */
|
/* If it has the poll bit set, send an appropriate supervisory response */
|
||||||
q921_rr(pri, 1);
|
q921_rr(pri, 1);
|
||||||
}
|
}
|
||||||
|
sendnow = 0;
|
||||||
/* Resend the proper I-frame */
|
/* Resend the proper I-frame */
|
||||||
for(f=pri->txqueue;f;f=f->next) {
|
for(f=pri->txqueue;f;f=f->next) {
|
||||||
if (f->h.n_s == h->s.n_r) {
|
if (sendnow || (f->h.n_s == h->s.n_r)) {
|
||||||
/* Matches the request */
|
/* Matches the request, or follows in our window */
|
||||||
break;
|
sendnow = 1;
|
||||||
}
|
pri_error("!! Got reject for frame %d, retransmitting frame %d now, updating n_r!\n", h->s.n_r, f->h.n_s);
|
||||||
}
|
f->h.n_r = pri->v_r;
|
||||||
if (f) {
|
|
||||||
/* Retransmit the requested frame */
|
|
||||||
q921_transmit(pri, (q921_h *)(&f->h), f->len);
|
q921_transmit(pri, (q921_h *)(&f->h), f->len);
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
if (!sendnow) {
|
||||||
if (pri->txqueue) {
|
if (pri->txqueue) {
|
||||||
/* This should never happen */
|
/* This should never happen */
|
||||||
if (!h->s.p_f || h->s.n_r) {
|
if (!h->s.p_f || h->s.n_r) {
|
||||||
fprintf(stderr, "!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
|
pri_error("!! Got reject for frame %d, but we only have others!\n", h->s.n_r);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
|
/* Hrm, we have nothing to send, but have been REJ'd. Reset v_a, v_s, etc */
|
||||||
|
pri_error("!! Got reject for frame %d, but we have nothing -- resetting!\n", h->s.n_r);
|
||||||
pri->v_a = h->s.n_r;
|
pri->v_a = h->s.n_r;
|
||||||
pri->v_s = h->s.n_r;
|
pri->v_s = h->s.n_r;
|
||||||
/* Reset t200 timer if it was somehow going */
|
/* Reset t200 timer if it was somehow going */
|
||||||
@ -689,38 +711,45 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
|
pri_error("!! XXX Unknown Supervisory frame ss=0x%02x,pf=%02xnr=%02x vs=%02x, va=%02x XXX\n", h->s.ss, h->s.p_f, h->s.n_r,
|
||||||
pri->v_s, pri->v_a);
|
pri->v_s, pri->v_a);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
if (len < 3) {
|
if (len < 3) {
|
||||||
fprintf(stderr, "!! Received short unnumbered frame\n");
|
pri_error("!! Received short unnumbered frame\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch(h->u.m3) {
|
switch(h->u.m3) {
|
||||||
case 0:
|
case 0:
|
||||||
if (h->u.m2 == 3) {
|
if (h->u.m2 == 3) {
|
||||||
if (h->u.p_f) {
|
if (h->u.p_f) {
|
||||||
|
/* Section 5.7.1 says we should restart on receiving a DM response with the f-bit set to
|
||||||
|
one, but we wait T200 first */
|
||||||
|
pri_event *ev = NULL;
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Got Unconnected Mode from peer.\n");
|
pri_message("-- Got DM Mode from peer.\n");
|
||||||
/* Disconnected mode */
|
/* Disconnected mode, try again after T200 */
|
||||||
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED)
|
ev = q921_dchannel_down(pri);
|
||||||
return q921_dchannel_down(pri);
|
q921_start(pri, 0);
|
||||||
|
return ev;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- DM requesting SABME, starting.\n");
|
pri_message("-- Ignoring unsolicited DM with p/f set to 0\n");
|
||||||
|
#if 0
|
||||||
/* Requesting that we start */
|
/* Requesting that we start */
|
||||||
q921_start(pri);
|
q921_start(pri, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else if (!h->u.m2) {
|
} else if (!h->u.m2) {
|
||||||
printf("XXX Unnumbered Information not implemented XXX\n");
|
pri_message("XXX Unnumbered Information not implemented XXX\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
if (pri->debug & PRI_DEBUG_Q921_STATE)
|
||||||
printf("-- Got Disconnect from peer.\n");
|
pri_message("-- Got Disconnect from peer.\n");
|
||||||
/* Acknowledge */
|
/* Acknowledge */
|
||||||
q921_send_ua(pri, h->u.p_f);
|
q921_send_ua(pri, h->u.p_f);
|
||||||
return q921_dchannel_down(pri);
|
return q921_dchannel_down(pri);
|
||||||
@ -728,7 +757,7 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
if (h->u.m2 == 3) {
|
if (h->u.m2 == 3) {
|
||||||
/* SABME */
|
/* SABME */
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE) {
|
if (pri->debug & PRI_DEBUG_Q921_STATE) {
|
||||||
printf("-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe");
|
pri_message("-- Got SABME from %s peer.\n", h->h.c_r ? "network" : "cpe");
|
||||||
}
|
}
|
||||||
if (h->h.c_r) {
|
if (h->h.c_r) {
|
||||||
pri->remotetype = PRI_NETWORK;
|
pri->remotetype = PRI_NETWORK;
|
||||||
@ -750,22 +779,22 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
/* It's a UA */
|
/* It's a UA */
|
||||||
if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
|
if (pri->q921_state == Q921_AWAITING_ESTABLISH) {
|
||||||
if (pri->debug & PRI_DEBUG_Q921_STATE) {
|
if (pri->debug & PRI_DEBUG_Q921_STATE) {
|
||||||
printf("-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network");
|
pri_message("-- Got UA from %s peer Link up.\n", h->h.c_r ? "cpe" : "network");
|
||||||
}
|
}
|
||||||
return q921_dchannel_up(pri);
|
return q921_dchannel_up(pri);
|
||||||
} else
|
} else
|
||||||
fprintf(stderr, "!! Got a UA, but i'm in state %d\n", pri->q921_state);
|
pri_error("!! Got a UA, but i'm in state %d\n", pri->q921_state);
|
||||||
} else
|
} else
|
||||||
fprintf(stderr, "!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
|
pri_error("!! Weird frame received (m3=3, m2 = %d)\n", h->u.m2);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
fprintf(stderr, "!! Frame got rejected!\n");
|
pri_error("!! Frame got rejected!\n");
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
fprintf(stderr, "!! XID frames not supported\n");
|
pri_error("!! XID frames not supported\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "!! Don't know what to do with M3=%d u-frames\n", h->u.m3);
|
pri_error("!! Don't know what to do with M3=%d u-frames\n", h->u.m3);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -773,14 +802,14 @@ pri_event *q921_receive(struct pri *pri, q921_h *h, int len)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void q921_start(struct pri *pri)
|
void q921_start(struct pri *pri, int now)
|
||||||
{
|
{
|
||||||
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
|
if (pri->q921_state != Q921_LINK_CONNECTION_RELEASED) {
|
||||||
fprintf(stderr, "!! q921_start: Not in 'Link Connection Released' state\n");
|
pri_error("!! q921_start: Not in 'Link Connection Released' state\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Reset our interface */
|
/* Reset our interface */
|
||||||
q921_reset(pri);
|
q921_reset(pri);
|
||||||
/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
|
/* Do the SABME XXX Maybe we should implement T_WAIT? XXX */
|
||||||
q921_send_sabme(pri);
|
q921_send_sabme(pri, now);
|
||||||
}
|
}
|
||||||
|
381
q931.c
381
q931.c
@ -61,7 +61,7 @@ struct msgtype msgs[] = {
|
|||||||
{ Q931_SEGMENT, "SEGMENT" },
|
{ Q931_SEGMENT, "SEGMENT" },
|
||||||
{ Q931_CONGESTION_CONTROL, "CONGESTION CONTROL" },
|
{ Q931_CONGESTION_CONTROL, "CONGESTION CONTROL" },
|
||||||
{ Q931_INFORMATION, "INFORMATION" },
|
{ Q931_INFORMATION, "INFORMATION" },
|
||||||
{ Q931_FACILITY, "FACLITY" },
|
{ Q931_FACILITY, "FACILITY" },
|
||||||
{ Q931_NOTIFY, "NOTIFY" },
|
{ Q931_NOTIFY, "NOTIFY" },
|
||||||
|
|
||||||
/* Call Management */
|
/* Call Management */
|
||||||
@ -193,6 +193,7 @@ struct q931_call {
|
|||||||
int chanflags;
|
int chanflags;
|
||||||
|
|
||||||
int alive; /* Whether or not the call is alive */
|
int alive; /* Whether or not the call is alive */
|
||||||
|
int acked; /* Whether setup has been acked or not */
|
||||||
int sendhangupack; /* Whether or not to send a hangup ack */
|
int sendhangupack; /* Whether or not to send a hangup ack */
|
||||||
int proc; /* Whether we've sent a call proceeding / alerting */
|
int proc; /* Whether we've sent a call proceeding / alerting */
|
||||||
|
|
||||||
@ -222,10 +223,19 @@ struct q931_call {
|
|||||||
int callerplan;
|
int callerplan;
|
||||||
int callerpres; /* Caller presentation */
|
int callerpres; /* Caller presentation */
|
||||||
char callernum[256]; /* Caller */
|
char callernum[256]; /* Caller */
|
||||||
|
char callername[256];
|
||||||
|
|
||||||
int calledplan;
|
int calledplan;
|
||||||
int nonisdn;
|
int nonisdn;
|
||||||
char callednum[256]; /* Called Number */
|
char callednum[256]; /* Called Number */
|
||||||
|
|
||||||
|
int redirectingplan;
|
||||||
|
int redirectingpres;
|
||||||
|
int redirectingreason;
|
||||||
|
char redirectingnum[256];
|
||||||
|
|
||||||
|
int useruserprotocoldisc;
|
||||||
|
char useruserinfo[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ie {
|
struct ie {
|
||||||
@ -278,14 +288,18 @@ static int receive_channel_id(struct pri *pri, q931_call *call, int msgtype, q93
|
|||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
int pos=0;
|
int pos=0;
|
||||||
|
#ifdef NO_BRI_SUPPORT
|
||||||
if (!ie->data[0] & 0x20) {
|
if (!ie->data[0] & 0x20) {
|
||||||
fprintf(stderr, "!! Not PRI type!?\n");
|
pri_error("!! Not PRI type!?\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef NOAUTO_CHANNEL_SELECTION_SUPPORT
|
||||||
if ((ie->data[0] & 3) != 1) {
|
if ((ie->data[0] & 3) != 1) {
|
||||||
fprintf(stderr, "!! Unexpected Channel selection %d\n", ie->data[0] & 3);
|
pri_error("!! Unexpected Channel selection %d\n", ie->data[0] & 3);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (ie->data[0] & 0x08)
|
if (ie->data[0] & 0x08)
|
||||||
call->chanflags = FLAG_EXCLUSIVE;
|
call->chanflags = FLAG_EXCLUSIVE;
|
||||||
else
|
else
|
||||||
@ -296,14 +310,14 @@ static int receive_channel_id(struct pri *pri, q931_call *call, int msgtype, q93
|
|||||||
call->ds1no = ie->data[1] & 0x7f;
|
call->ds1no = ie->data[1] & 0x7f;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
if (pos < len) {
|
if (pos+2 < len) {
|
||||||
/* More coming */
|
/* More coming */
|
||||||
if ((ie->data[pos] & 0x0f) != 3) {
|
if ((ie->data[pos] & 0x0f) != 3) {
|
||||||
fprintf(stderr, "!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
|
pri_error("!! Unexpected Channel Type %d\n", ie->data[1] & 0x0f);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((ie->data[pos] & 0x60) != 0) {
|
if ((ie->data[pos] & 0x60) != 0) {
|
||||||
fprintf(stderr, "!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
|
pri_error("!! Invalid CCITT coding %d\n", (ie->data[1] & 0x60) >> 5);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ie->data[pos] & 0x10) {
|
if (ie->data[pos] & 0x10) {
|
||||||
@ -367,7 +381,7 @@ static int transmit_channel_id(struct pri *pri, q931_call *call, int msgtype, q9
|
|||||||
/* We're done */
|
/* We're done */
|
||||||
return pos + 2;
|
return pos + 2;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
|
pri_error("!! No channel map, no channel, and no ds1? What am I supposed to identify?\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,30 +390,36 @@ static void dump_channel_id(q931_ie *ie, int len, char prefix)
|
|||||||
int pos=0;
|
int pos=0;
|
||||||
int x;
|
int x;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
printf("%c Channel ID (len=%2d) [ Ext: %d IntID: %s, %s Spare: %d, %s Dchan: %d, ChanSel: %d \n",
|
static const char* msg_chan_sel[] = {
|
||||||
|
"No channel selected", "B1 channel", "B2 channel","Any channel selected"
|
||||||
|
"No channel selected", "As indicated in following octets", "Reserved","Any channel selected"
|
||||||
|
};
|
||||||
|
|
||||||
|
pri_message("%c Channel ID (len=%2d) [ Ext: %d IntID: %s, %s Spare: %d, %s Dchan: %d\n",
|
||||||
prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
|
prefix, len, (ie->data[0] & 0x80) ? 1 : 0, (ie->data[0] & 0x40) ? "Explicit" : "Implicit",
|
||||||
(ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
|
(ie->data[0] & 0x20) ? "PRI" : "Other", (ie->data[0] & 0x10) ? 1 : 0,
|
||||||
(ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0,
|
(ie->data[0] & 0x08) ? "Exclusive" : "Preferred", (ie->data[0] & 0x04) ? 1 : 0);
|
||||||
ie->data[0] & 0x3);
|
pri_message("%c ChanSel: %s\n",
|
||||||
|
prefix, msg_chan_sel[(ie->data[0] & 0x3) + ((ie->data[0]>>3) & 0x4)]);
|
||||||
pos++;
|
pos++;
|
||||||
len--;
|
len--;
|
||||||
if (ie->data[0] & 0x40) {
|
if (ie->data[0] & 0x40) {
|
||||||
/* Explicitly defined DS1 */
|
/* Explicitly defined DS1 */
|
||||||
printf("%c Ext: %d DS1 Identifier: %d \n", prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
|
pri_message("%c Ext: %d DS1 Identifier: %d \n", prefix, (ie->data[pos] & 0x80) >> 7, ie->data[pos] & 0x7f);
|
||||||
pos++;
|
pos++;
|
||||||
len--;
|
len--;
|
||||||
} else {
|
} else {
|
||||||
/* Implicitly defined DS1 */
|
/* Implicitly defined DS1 */
|
||||||
}
|
}
|
||||||
if (pos < len) {
|
if (pos+2 < len) {
|
||||||
/* Still more information here */
|
/* Still more information here */
|
||||||
printf("%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
|
pri_message("%c Ext: %d Coding: %d %s Specified Channel Type: %d\n",
|
||||||
prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
|
prefix, (ie->data[pos] & 0x80) >> 7, (ie->data[pos] & 60) >> 5,
|
||||||
(ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
|
(ie->data[pos] & 0x10) ? "Slot Map" : "Number", ie->data[pos] & 0x0f);
|
||||||
if (!(ie->data[pos] & 0x10)) {
|
if (!(ie->data[pos] & 0x10)) {
|
||||||
/* Number specified */
|
/* Number specified */
|
||||||
pos++;
|
pos++;
|
||||||
printf("%c Ext: %d Channel: %d ]\n", prefix, (ie->data[pos] & 0x80) >> 7,
|
pri_message("%c Ext: %d Channel: %d ]\n", prefix, (ie->data[pos] & 0x80) >> 7,
|
||||||
(ie->data[pos]) & 0x7f);
|
(ie->data[pos]) & 0x7f);
|
||||||
} else {
|
} else {
|
||||||
pos++;
|
pos++;
|
||||||
@ -408,9 +428,9 @@ static void dump_channel_id(q931_ie *ie, int len, char prefix)
|
|||||||
res <<= 8;
|
res <<= 8;
|
||||||
res |= ie->data[pos++];
|
res |= ie->data[pos++];
|
||||||
}
|
}
|
||||||
printf("%c Map: %s ]\n", prefix, binary(res, 24));
|
pri_message("%c Map: %s ]\n", prefix, binary(res, 24));
|
||||||
}
|
}
|
||||||
} else printf(" ]\n");
|
} else pri_message(" ]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ri2str(int ri)
|
static char *ri2str(int ri)
|
||||||
@ -425,7 +445,7 @@ static char *ri2str(int ri)
|
|||||||
|
|
||||||
static void dump_restart_indicator(q931_ie *ie, int len, char prefix)
|
static void dump_restart_indicator(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
printf("%c Restart Indentifier: [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
|
pri_message("%c Restart Indentifier: [ Ext: %d Spare: %d Resetting %s (%d) ]\n",
|
||||||
prefix, (ie->data[0] & 0x80) >> 7, (ie->data[0] & 0x78) >> 3, ri2str(ie->data[0] & 0x7), ie->data[0] & 0x7);
|
prefix, (ie->data[0] & 0x80) >> 7, (ie->data[0] & 0x78) >> 3, ri2str(ie->data[0] & 0x7), ie->data[0] & 0x7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,7 +470,7 @@ static int transmit_restart_indicator(struct pri *pri, q931_call *call, int msgt
|
|||||||
ie->data[0] = 0xA0 | (call->ri & 0x7);
|
ie->data[0] = 0xA0 | (call->ri & 0x7);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "!! Invalid restart indicator value %d\n", call->ri);
|
pri_error("!! Invalid restart indicator value %d\n", call->ri);
|
||||||
return-1;
|
return-1;
|
||||||
}
|
}
|
||||||
return 3;
|
return 3;
|
||||||
@ -541,11 +561,11 @@ static char *l32str(int proto)
|
|||||||
static void dump_bearer_capability(q931_ie *ie, int len, char prefix)
|
static void dump_bearer_capability(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
int pos=2;
|
int pos=2;
|
||||||
printf("%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
|
pri_message("%c Bearer Capability (len=%2d) [ Ext: %d Q.931 Std: %d Info transfer capability: %s (%d)\n",
|
||||||
prefix, ie->len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
|
prefix, ie->len, (ie->data[0] & 0x80 ) >> 7, (ie->data[0] & 0x60) >> 5, cap2str(ie->data[0] & 0x1f), (ie->data[0] & 0x1f));
|
||||||
printf("%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
pri_message("%c Ext: %d Trans mode/rate: %s (%d)\n", prefix, (ie->data[1] & 0x80) >> 7, mode2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
||||||
if ((ie->data[1] & 0x7f) == 0x18) {
|
if ((ie->data[1] & 0x7f) == 0x18) {
|
||||||
printf("%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
|
pri_message("%c Ext: %d Transfer rate multiplier: %d x 64\n", prefix, (ie->data[2] & 0x80) >> 7, ie->data[2] & 0x7f);
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
/* Stop here if no more */
|
/* Stop here if no more */
|
||||||
@ -553,15 +573,15 @@ static void dump_bearer_capability(q931_ie *ie, int len, char prefix)
|
|||||||
return;
|
return;
|
||||||
if ((ie->data[1] & 0x7f) != TRANS_MODE_PACKET) {
|
if ((ie->data[1] & 0x7f) != TRANS_MODE_PACKET) {
|
||||||
/* Look for octets 5 and 5.a if present */
|
/* Look for octets 5 and 5.a if present */
|
||||||
printf("%c Ext: %d User information layer 1: %s (%d)\n", prefix, (ie->data[pos] >> 7), l12str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
pri_message("%c Ext: %d User information layer 1: %s (%d)\n", prefix, (ie->data[pos] >> 7), l12str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
||||||
if ((ie->data[pos] & 0x7f) == PRI_LAYER_1_ITU_RATE_ADAPT)
|
if ((ie->data[pos] & 0x7f) == PRI_LAYER_1_ITU_RATE_ADAPT)
|
||||||
printf("%c Ext: %d Rate adaptatation: %s (%d)\n", prefix, ie->data[pos] >> 7, ra2str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
pri_message("%c Ext: %d Rate adaptatation: %s (%d)\n", prefix, ie->data[pos] >> 7, ra2str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
||||||
pos++;
|
pos++;
|
||||||
} else {
|
} else {
|
||||||
/* Look for octets 6 and 7 but not 5 and 5.a */
|
/* Look for octets 6 and 7 but not 5 and 5.a */
|
||||||
printf("%c Ext: %d User information layer 2: %s (%d)\n", prefix, ie->data[pos] >> 7, l22str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
pri_message("%c Ext: %d User information layer 2: %s (%d)\n", prefix, ie->data[pos] >> 7, l22str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
||||||
pos++;
|
pos++;
|
||||||
printf("%c Ext: %d User information layer 3: %s (%d)\n", prefix, ie->data[pos] >> 7, l32str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
pri_message("%c Ext: %d User information layer 3: %s (%d)\n", prefix, ie->data[pos] >> 7, l32str(ie->data[pos] & 0x7f), ie->data[pos] & 0x7f);
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,7 +590,7 @@ static int receive_bearer_capability(struct pri* pri, q931_call *call, int msgty
|
|||||||
{
|
{
|
||||||
int pos=2;
|
int pos=2;
|
||||||
if (ie->data[0] & 0x60) {
|
if (ie->data[0] & 0x60) {
|
||||||
fprintf(stderr, "!! non-standard Q.931 standard field\n");
|
pri_error("!! non-standard Q.931 standard field\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
call->transcapability = ie->data[0] & 0x1f;
|
call->transcapability = ie->data[0] & 0x1f;
|
||||||
@ -698,7 +718,7 @@ static void dump_called_party_number(q931_ie *ie, int len, char prefix)
|
|||||||
char cnum[256];
|
char cnum[256];
|
||||||
|
|
||||||
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
||||||
printf("%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\n",
|
pri_message("%c Called Number (len=%2d) [ Ext: %d TON: %s (%d) NPI: %s (%d) '%s' ]\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, cnum);
|
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, cnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,7 +726,7 @@ static void dump_called_party_subaddr(q931_ie *ie, int len, char prefix)
|
|||||||
{
|
{
|
||||||
char cnum[256];
|
char cnum[256];
|
||||||
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
q931_get_number(cnum, sizeof(cnum), ie->data + 1, len - 3);
|
||||||
printf("%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
pri_message("%c Called Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||||
prefix, len, ie->data[0] >> 7,
|
prefix, len, ie->data[0] >> 7,
|
||||||
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
||||||
(ie->data[0] & 0x08) >> 3, cnum);
|
(ie->data[0] & 0x08) >> 3, cnum);
|
||||||
@ -717,15 +737,15 @@ static void dump_calling_party_number(q931_ie *ie, int len, char prefix)
|
|||||||
char cnum[256];
|
char cnum[256];
|
||||||
|
|
||||||
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
||||||
printf("%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 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);
|
||||||
printf("%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]), ie->data[1] & 0x7f, cnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_calling_party_subaddr(q931_ie *ie, int len, char prefix)
|
static void dump_calling_party_subaddr(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
char cnum[256];
|
char cnum[256];
|
||||||
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
||||||
printf("%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
pri_message("%c Calling Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||||
prefix, len, ie->data[0] >> 7,
|
prefix, len, ie->data[0] >> 7,
|
||||||
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
||||||
(ie->data[0] & 0x08) >> 3, cnum);
|
(ie->data[0] & 0x08) >> 3, cnum);
|
||||||
@ -735,15 +755,27 @@ static void dump_redirecting_number(q931_ie *ie, int len, char prefix)
|
|||||||
{
|
{
|
||||||
char cnum[256];
|
char cnum[256];
|
||||||
q931_get_number(cnum, sizeof(cnum), ie->data + 3, len - 5);
|
q931_get_number(cnum, sizeof(cnum), ie->data + 3, len - 5);
|
||||||
printf("%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 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);
|
||||||
printf("%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]), ie->data[1] & 0x7f, redirection_reason2str(ie->data[2]), ie->data[2], cnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int receive_redirecting_number(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
|
{
|
||||||
|
call->redirectingplan = ie->data[0] & 0x7f;
|
||||||
|
call->redirectingpres = ie->data[1] & 0x7f;
|
||||||
|
call->redirectingreason = ie->data[2] & 0x0f;
|
||||||
|
|
||||||
|
q931_get_number(call->redirectingnum, sizeof(call->redirectingnum), ie->data + 3, len - 5);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dump_redirecting_subaddr(q931_ie *ie, int len, char prefix)
|
static void dump_redirecting_subaddr(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
char cnum[256];
|
char cnum[256];
|
||||||
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
q931_get_number(cnum, sizeof(cnum), ie->data + 2, len - 4);
|
||||||
printf("%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
pri_message("%c Redirecting Sub-Address (len=%2d) [ Ext: %d Type: %s (%d) O: %d '%s' ]\n",
|
||||||
prefix, len, ie->data[0] >> 7,
|
prefix, len, ie->data[0] >> 7,
|
||||||
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
subaddrtype2str((ie->data[0] & 0x70) >> 4), (ie->data[0] & 0x70) >> 4,
|
||||||
(ie->data[0] & 0x08) >> 3, cnum);
|
(ie->data[0] & 0x08) >> 3, cnum);
|
||||||
@ -751,7 +783,13 @@ 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)
|
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);
|
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;
|
call->calledplan = ie->data[0] & 0x7f;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -766,9 +804,19 @@ static int transmit_called_party_number(struct pri *pri, q931_call *call, int ms
|
|||||||
|
|
||||||
static int receive_calling_party_number(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
static int receive_calling_party_number(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
{
|
{
|
||||||
q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
|
int extbit;
|
||||||
|
|
||||||
call->callerplan = ie->data[0] & 0x7f;
|
call->callerplan = ie->data[0] & 0x7f;
|
||||||
|
extbit = (ie->data[0] >> 7) & 0x01;
|
||||||
|
|
||||||
|
if (extbit) {
|
||||||
|
q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 1, len - 3);
|
||||||
|
call->callerpres = 0; /* PI presentation allowed
|
||||||
|
SI user-provided, not screened */
|
||||||
|
} else {
|
||||||
|
q931_get_number(call->callernum, sizeof(call->callernum), ie->data + 2, len - 4);
|
||||||
call->callerpres = ie->data[1] & 0x7f;
|
call->callerpres = ie->data[1] & 0x7f;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -781,6 +829,20 @@ static int transmit_calling_party_number(struct pri *pri, q931_call *call, int m
|
|||||||
return strlen(call->callernum) + 4;
|
return strlen(call->callernum) + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dump_user_user(q931_ie *ie, int len, char prefix)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int receive_user_user(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
|
{
|
||||||
|
call->useruserprotocoldisc = ie->data[0] & 0xff;
|
||||||
|
if (call->useruserprotocoldisc == 4) /* IA5 */
|
||||||
|
q931_get_number(call->useruserinfo, sizeof(call->useruserinfo), ie->data + 1, len - 3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static char *prog2str(int prog)
|
static char *prog2str(int prog)
|
||||||
{
|
{
|
||||||
static struct msgtype progs[] = {
|
static struct msgtype progs[] = {
|
||||||
@ -825,13 +887,33 @@ static char *loc2str(int loc)
|
|||||||
|
|
||||||
static void dump_progress_indicator(q931_ie *ie, int len, char prefix)
|
static void dump_progress_indicator(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
printf("%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
pri_message("%c Progress Indicator (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
||||||
prefix, ie->len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
|
prefix, ie->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);
|
(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
|
||||||
printf("%c Ext: %d Progress Description: %s (%d) ]\n",
|
pri_message("%c Ext: %d Progress Description: %s (%d) ]\n",
|
||||||
prefix, ie->data[1] >> 7, prog2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
prefix, ie->data[1] >> 7, prog2str(ie->data[1] & 0x7f), ie->data[1] & 0x7f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int receive_display(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
|
{
|
||||||
|
unsigned char *data;
|
||||||
|
data = ie->data;
|
||||||
|
if (data[0] & 0x80) {
|
||||||
|
/* Skip over character set */
|
||||||
|
data++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
q931_get_number(call->callername, sizeof(call->callername), data, len - 2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
static int receive_progress_indicator(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
static int receive_progress_indicator(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
{
|
{
|
||||||
call->progloc = ie->data[0] & 0xf;
|
call->progloc = ie->data[0] & 0xf;
|
||||||
@ -840,6 +922,18 @@ static int receive_progress_indicator(struct pri *pri, q931_call *call, int msgt
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int receive_facility(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
|
{
|
||||||
|
if (ie->len < 14) {
|
||||||
|
pri_error("!! Facility message shorter than 14 bytes\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ie->data[13] + 14 == ie->len) {
|
||||||
|
q931_get_number(call->callername, sizeof(call->callername) - 1, ie->data + 14, ie->len - 14);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int transmit_progress_indicator(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
static int transmit_progress_indicator(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
{
|
{
|
||||||
if (call->progress > 0) {
|
if (call->progress > 0) {
|
||||||
@ -880,7 +974,7 @@ static char *callstate2str(int callstate)
|
|||||||
|
|
||||||
static void dump_call_state(q931_ie *ie, int len, char prefix)
|
static void dump_call_state(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
printf("%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
|
pri_message("%c Call State (len=%2d) [ Ext: %d Coding: %s (%d) Call state: %s (%d)\n",
|
||||||
prefix, ie->len, ie->data[0] >> 7, coding2str((ie->data[0] & 0xC0) >> 6), (ie->data[0] & 0xC0) >> 6,
|
prefix, ie->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);
|
callstate2str(ie->data[0] & 0x3f), ie->data[0] & 0x3f);
|
||||||
}
|
}
|
||||||
@ -888,37 +982,82 @@ static void dump_call_state(q931_ie *ie, int len, char prefix)
|
|||||||
static void dump_call_identity(q931_ie *ie, int len, char prefix)
|
static void dump_call_identity(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
printf("%c Call Identity (len=%2d) [ ", prefix, ie->len);
|
pri_message("%c Call Identity (len=%2d) [ ", prefix, ie->len);
|
||||||
for (x=0;x<ie->len;x++)
|
for (x=0;x<ie->len;x++)
|
||||||
printf("0x%02X ", ie->data[x]);
|
pri_message("0x%02X ", ie->data[x]);
|
||||||
printf(" ]\n");
|
pri_message(" ]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_time_date(q931_ie *ie, int len, char prefix)
|
static void dump_time_date(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
printf("%c Time Date (len=%2d) [ ", prefix, ie->len);
|
pri_message("%c Time Date (len=%2d) [ ", prefix, ie->len);
|
||||||
if (ie->len > 0)
|
if (ie->len > 0)
|
||||||
printf("%02d", ie->data[0]);
|
pri_message("%02d", ie->data[0]);
|
||||||
if (ie->len > 1)
|
if (ie->len > 1)
|
||||||
printf("-%02d", ie->data[1]);
|
pri_message("-%02d", ie->data[1]);
|
||||||
if (ie->len > 2)
|
if (ie->len > 2)
|
||||||
printf("-%02d", ie->data[2]);
|
pri_message("-%02d", ie->data[2]);
|
||||||
if (ie->len > 3)
|
if (ie->len > 3)
|
||||||
printf(" %02d", ie->data[3]);
|
pri_message(" %02d", ie->data[3]);
|
||||||
if (ie->len > 4)
|
if (ie->len > 4)
|
||||||
printf(":%02d", ie->data[4]);
|
pri_message(":%02d", ie->data[4]);
|
||||||
if (ie->len > 5)
|
if (ie->len > 5)
|
||||||
printf(":%02d", ie->data[5]);
|
pri_message(":%02d", ie->data[5]);
|
||||||
printf(" ]\n");
|
pri_message(" ]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_display(q931_ie *ie, int len, char prefix)
|
static void dump_display(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
printf("%c Call Identity (len=%2d) [ ", prefix, ie->len);
|
pri_message("%c Display (len=%2d) [ ", prefix, ie->len);
|
||||||
for (x=0;x<ie->len;x++)
|
for (x=0;x<ie->len;x++)
|
||||||
printf("%c", ie->data[x] & 0x7f);
|
pri_message("%c", ie->data[x] & 0x7f);
|
||||||
printf(" ]\n");
|
pri_message(" ]\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_ie_data(unsigned char *c, int len)
|
||||||
|
{
|
||||||
|
char tmp[1024] = "";
|
||||||
|
int x=0;
|
||||||
|
int lastascii = 0;
|
||||||
|
while(len) {
|
||||||
|
if (((*c >= 'A') && (*c <= 'Z')) ||
|
||||||
|
((*c >= 'a') && (*c <= 'z')) ||
|
||||||
|
((*c >= '0') && (*c <= '9'))) {
|
||||||
|
if (!lastascii) {
|
||||||
|
if (strlen(tmp)) {
|
||||||
|
tmp[x++] = ',';
|
||||||
|
tmp[x++] = ' ';
|
||||||
|
}
|
||||||
|
tmp[x++] = '\'';
|
||||||
|
}
|
||||||
|
tmp[x++] = *c;
|
||||||
|
lastascii = 1;
|
||||||
|
} else {
|
||||||
|
if (lastascii) {
|
||||||
|
tmp[x++] = '\'';
|
||||||
|
}
|
||||||
|
if (strlen(tmp)) {
|
||||||
|
tmp[x++] = ',';
|
||||||
|
tmp[x++] = ' ';
|
||||||
|
}
|
||||||
|
sprintf (tmp + x, "0x%02x", *c);
|
||||||
|
x += 4;
|
||||||
|
lastascii = 0;
|
||||||
|
}
|
||||||
|
c++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
if (lastascii)
|
||||||
|
tmp[x++] = '\'';
|
||||||
|
pri_message(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_facility(q931_ie *ie, int len, char prefix)
|
||||||
|
{
|
||||||
|
pri_message("%c Facility (len=%2d) [ ", prefix, ie->len);
|
||||||
|
dump_ie_data(ie->data, ie->len);
|
||||||
|
pri_message(" ]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
char *pri_cause2str(int cause)
|
char *pri_cause2str(int cause)
|
||||||
@ -944,14 +1083,14 @@ static char *pri_causeclass2str(int cause)
|
|||||||
static void dump_cause(q931_ie *ie, int len, char prefix)
|
static void dump_cause(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
printf("%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
pri_message("%c Cause (len=%2d) [ Ext: %d Coding: %s (%d) 0: %d Location: %s (%d)\n",
|
||||||
prefix, ie->len, ie->data[0] >> 7, coding2str((ie->data[0] & 0x60) >> 5), (ie->data[0] & 0x60) >> 5,
|
prefix, ie->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);
|
(ie->data[0] & 0x10) >> 4, loc2str(ie->data[0] & 0xf), ie->data[0] & 0xf);
|
||||||
printf("%c Ext: %d Cause: %s (%d), class = %s (%d) ]\n",
|
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,
|
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);
|
pri_causeclass2str((ie->data[1] & 0x7f) >> 4), (ie->data[1] & 0x7f) >> 4);
|
||||||
for (x=4;x<len;x++)
|
for (x=4;x<len;x++)
|
||||||
printf("%c Cause data %d: %02x (%d)\n", prefix, x-4, ie->data[x], ie->data[x]);
|
pri_message("%c Cause data %d: %02x (%d)\n", prefix, x-4, ie->data[x], ie->data[x]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int receive_cause(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
static int receive_cause(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
@ -976,7 +1115,7 @@ static int transmit_cause(struct pri *pri, q931_call *call, int msgtype, q931_ie
|
|||||||
|
|
||||||
static void dump_sending_complete(q931_ie *ie, int len, char prefix)
|
static void dump_sending_complete(q931_ie *ie, int len, char prefix)
|
||||||
{
|
{
|
||||||
printf("%c Sending Complete (len=%2d)\n", prefix, ie->len);
|
pri_message("%c Sending Complete (len=%2d)\n", prefix, ie->len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int receive_sending_complete(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
static int receive_sending_complete(struct pri *pri, q931_call *call, int msgtype, q931_ie *ie, int len)
|
||||||
@ -1015,14 +1154,14 @@ struct ie ies[] = {
|
|||||||
{ Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_calling_party_subaddr },
|
{ Q931_CALLING_PARTY_SUBADDR, "Calling Party Subaddress", dump_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_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_CALLED_PARTY_SUBADDR, "Called Party Subaddress", dump_called_party_subaddr },
|
||||||
{ Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number },
|
{ Q931_REDIRECTING_NUMBER, "Redirecting Number", dump_redirecting_number, receive_redirecting_number },
|
||||||
{ Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
|
{ Q931_REDIRECTING_SUBADDR, "Redirecting Subaddress", dump_redirecting_subaddr },
|
||||||
{ Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
|
{ Q931_TRANSIT_NET_SELECT, "Transit Network Selection" },
|
||||||
{ Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator },
|
{ Q931_RESTART_INDICATOR, "Restart Indicator", dump_restart_indicator, receive_restart_indicator, transmit_restart_indicator },
|
||||||
{ Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
|
{ Q931_LOW_LAYER_COMPAT, "Low-layer Compatibility" },
|
||||||
{ Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
|
{ Q931_HIGH_LAYER_COMPAT, "High-layer Compatibility" },
|
||||||
{ Q931_PACKET_SIZE, "Packet Size" },
|
{ Q931_PACKET_SIZE, "Packet Size" },
|
||||||
{ Q931_IE_FACILITY, "Facility" },
|
{ Q931_IE_FACILITY, "Facility" , dump_facility, receive_facility },
|
||||||
{ Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
|
{ Q931_IE_REDIRECTION_NUMBER, "Redirection Number" },
|
||||||
{ Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
|
{ Q931_IE_REDIRECTION_SUBADDR, "Redirection Subaddress" },
|
||||||
{ Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
{ Q931_IE_FEATURE_ACTIVATE, "Feature Activation" },
|
||||||
@ -1032,12 +1171,12 @@ struct ie ies[] = {
|
|||||||
{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
|
{ Q931_IE_CALL_IDENTITY, "Call Identity", dump_call_identity },
|
||||||
{ Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
|
{ Q931_IE_ENDPOINT_ID, "Endpoint Identification" },
|
||||||
{ Q931_IE_NOTIFY_IND, "Notification Indicator" },
|
{ Q931_IE_NOTIFY_IND, "Notification Indicator" },
|
||||||
{ Q931_IE_DISPLAY, "Display", dump_display },
|
{ Q931_DISPLAY, "Display", dump_display, receive_display, transmit_display },
|
||||||
{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
|
{ Q931_IE_TIME_DATE, "Date/Time", dump_time_date },
|
||||||
{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
|
{ Q931_IE_KEYPAD_FACILITY, "Keypad Facility" },
|
||||||
{ Q931_IE_SIGNAL, "Signal" },
|
{ Q931_IE_SIGNAL, "Signal" },
|
||||||
{ Q931_IE_SWITCHHOOK, "Switch-hook" },
|
{ Q931_IE_SWITCHHOOK, "Switch-hook" },
|
||||||
{ Q931_IE_USER_USER, "User-User" },
|
{ Q931_IE_USER_USER, "User-User", dump_user_user, receive_user_user },
|
||||||
{ Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
|
{ Q931_IE_ESCAPE_FOR_EXT, "Escape for Extension" },
|
||||||
{ Q931_IE_CALL_STATUS, "Call Status" },
|
{ Q931_IE_CALL_STATUS, "Call Status" },
|
||||||
{ Q931_IE_CHANGE_STATUS, "Change Status" },
|
{ Q931_IE_CHANGE_STATUS, "Change Status" },
|
||||||
@ -1079,7 +1218,7 @@ static inline int q931_cr(q931_h *h)
|
|||||||
int cr = 0;
|
int cr = 0;
|
||||||
int x;
|
int x;
|
||||||
if (h->crlen > 3) {
|
if (h->crlen > 3) {
|
||||||
fprintf(stderr, "Call Reference Length Too long: %d\n", h->crlen);
|
pri_error("Call Reference Length Too long: %d\n", h->crlen);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
for (x=0;x<h->crlen;x++) {
|
for (x=0;x<h->crlen;x++) {
|
||||||
@ -1097,11 +1236,11 @@ static inline void q931_dumpie(q931_ie *ie, char prefix)
|
|||||||
if (ies[x].dump)
|
if (ies[x].dump)
|
||||||
ies[x].dump(ie, ielen(ie), prefix);
|
ies[x].dump(ie, ielen(ie), prefix);
|
||||||
else
|
else
|
||||||
printf("%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie));
|
pri_message("%c IE: %s (len = %d)\n", prefix, ies[x].name, ielen(ie));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stderr, "!! %c Unknown IE %d (len = %d)\n", prefix, ie->ie, ielen(ie));
|
pri_error("!! %c Unknown IE %d (len = %d)\n", prefix, ie->ie, ielen(ie));
|
||||||
}
|
}
|
||||||
|
|
||||||
static q931_call *q931_getcall(struct pri *pri, int cr)
|
static q931_call *q931_getcall(struct pri *pri, int cr)
|
||||||
@ -1117,7 +1256,7 @@ static q931_call *q931_getcall(struct pri *pri, int cr)
|
|||||||
}
|
}
|
||||||
/* No call exists, make a new one */
|
/* No call exists, make a new one */
|
||||||
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
||||||
printf("-- Making new call for cr %d\n", cr);
|
pri_message("-- Making new call for cr %d\n", cr);
|
||||||
cur = malloc(sizeof(struct q931_call));
|
cur = malloc(sizeof(struct q931_call));
|
||||||
if (cur) {
|
if (cur) {
|
||||||
call_init(cur);
|
call_init(cur);
|
||||||
@ -1166,7 +1305,7 @@ static void q931_destroycall(struct pri *pri, int cr)
|
|||||||
prev = cur;
|
prev = cur;
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
fprintf(stderr, "Can't destroy call %d!\n", cr);
|
pri_error("Can't destroy call %d!\n", cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen)
|
static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie *iet, int maxlen)
|
||||||
@ -1186,12 +1325,12 @@ static int add_ie(struct pri *pri, q931_call *call, int msgtype, int ie, q931_ie
|
|||||||
iet->len = res - 2;
|
iet->len = res - 2;
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
|
pri_error("!! Don't know how to add an IE %s (%d)\n", ie2str(ie), ie);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fprintf(stderr, "!! Unknown IE %d (%s)\n", ie, ie2str(ie));
|
pri_error("!! Unknown IE %d (%s)\n", ie, ie2str(ie));
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
@ -1212,11 +1351,11 @@ void q931_dump(q931_h *h, int len, int txrx)
|
|||||||
char c;
|
char c;
|
||||||
int x=0, r;
|
int x=0, r;
|
||||||
c = txrx ? '>' : '<';
|
c = txrx ? '>' : '<';
|
||||||
printf("%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
|
pri_message("%c Protocol Discriminator: %s (%d) len=%d\n", c, disc2str(h->pd), h->pd, len);
|
||||||
printf("%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h), q931_cr(h), (h->crv[0] & 0x80) ? "Terminator" : "Originator");
|
pri_message("%c Call Ref: len=%2d (reference %d/0x%X) (%s)\n", c, h->crlen, q931_cr(h), q931_cr(h), (h->crv[0] & 0x80) ? "Terminator" : "Originator");
|
||||||
/* Message header begins at the end of the call reference number */
|
/* Message header begins at the end of the call reference number */
|
||||||
mh = (q931_mh *)(h->contents + h->crlen);
|
mh = (q931_mh *)(h->contents + h->crlen);
|
||||||
printf("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
|
pri_message("%c Message type: %s (%d)\n", c, msg2str(mh->msg), mh->msg);
|
||||||
/* Drop length of header, including call reference */
|
/* Drop length of header, including call reference */
|
||||||
len -= (h->crlen + 3);
|
len -= (h->crlen + 3);
|
||||||
while(x < len) {
|
while(x < len) {
|
||||||
@ -1225,26 +1364,26 @@ void q931_dump(q931_h *h, int len, int txrx)
|
|||||||
x += r;
|
x += r;
|
||||||
}
|
}
|
||||||
if (x > len)
|
if (x > len)
|
||||||
fprintf(stderr, "XXX Message longer than it should be?? XXX\n");
|
pri_error("XXX Message longer than it should be?? XXX\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int q931_handle_ie(struct pri *pri, q931_call *c, int msg, q931_ie *ie)
|
static int q931_handle_ie(struct pri *pri, q931_call *c, int msg, q931_ie *ie)
|
||||||
{
|
{
|
||||||
int x;
|
int x;
|
||||||
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
||||||
printf("-- Processing IE %d (%s)\n", ie->ie, ie2str(ie->ie));
|
pri_message("-- Processing IE %d (%s)\n", ie->ie, ie2str(ie->ie));
|
||||||
for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
|
for (x=0;x<sizeof(ies) / sizeof(ies[0]);x++) {
|
||||||
if (ie->ie == ies[x].ie) {
|
if (ie->ie == ies[x].ie) {
|
||||||
if (ies[x].receive)
|
if (ies[x].receive)
|
||||||
return ies[x].receive(pri, c, msg, ie, ielen(ie));
|
return ies[x].receive(pri, c, msg, ie, ielen(ie));
|
||||||
else {
|
else {
|
||||||
if (pri->debug & PRI_DEBUG_Q931_ANOMALY)
|
if (pri->debug & PRI_DEBUG_Q931_ANOMALY)
|
||||||
fprintf(stderr, "!! No handler for IE %d (%s)\n", ie->ie, ie2str(ie->ie));
|
pri_error("!! No handler for IE %d (%s)\n", ie->ie, ie2str(ie->ie));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("!! Unknown IE %d (%s)\n", ie->ie, ie2str(ie->ie));
|
pri_message("!! Unknown IE %d (%s)\n", ie->ie, ie2str(ie->ie));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1299,7 +1438,7 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
|
|||||||
while(ies[x] > -1) {
|
while(ies[x] > -1) {
|
||||||
res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len);
|
res = add_ie(pri, c, mh->msg, ies[x], (q931_ie *)(mh->data + offset), len);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
fprintf(stderr, "!! Unable to add IE '%s'\n", ie2str(ies[x]));
|
pri_error("!! Unable to add IE '%s'\n", ie2str(ies[x]));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
offset += res;
|
offset += res;
|
||||||
@ -1309,6 +1448,7 @@ static int send_message(struct pri *pri, q931_call *c, int msgtype, int ies[])
|
|||||||
/* Invert the logic */
|
/* Invert the logic */
|
||||||
len = sizeof(buf) - len;
|
len = sizeof(buf) - len;
|
||||||
q931_xmit(pri, h, len, 1);
|
q931_xmit(pri, h, len, 1);
|
||||||
|
c->acked = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1348,6 +1488,22 @@ int q931_alerting(struct pri *pri, q931_call *c, int channel, int info)
|
|||||||
|
|
||||||
static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
|
static int connect_ies[] = { Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR, -1 };
|
||||||
|
|
||||||
|
int q931_setup_ack(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
||||||
|
{
|
||||||
|
if (channel)
|
||||||
|
c->channelno = channel;
|
||||||
|
c->chanflags &= ~FLAG_PREFERRED;
|
||||||
|
c->chanflags |= FLAG_EXCLUSIVE;
|
||||||
|
if (nonisdn && (pri->switchtype != PRI_SWITCH_DMS100)) {
|
||||||
|
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||||
|
c->progcode = CODE_CCITT;
|
||||||
|
c->progress = Q931_PROG_CALLED_NOT_ISDN;
|
||||||
|
} else
|
||||||
|
c->progress = -1;
|
||||||
|
|
||||||
|
return send_message(pri, c, Q931_SETUP_ACKNOWLEDGE, connect_ies);
|
||||||
|
}
|
||||||
|
|
||||||
int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
int q931_connect(struct pri *pri, q931_call *c, int channel, int nonisdn)
|
||||||
{
|
{
|
||||||
if (channel)
|
if (channel)
|
||||||
@ -1372,7 +1528,10 @@ int q931_release(struct pri *pri, q931_call *c, int cause)
|
|||||||
c->cause = cause;
|
c->cause = cause;
|
||||||
c->causecode = CODE_CCITT;
|
c->causecode = CODE_CCITT;
|
||||||
c->causeloc = LOC_PRIV_NET_LOCAL_USER;
|
c->causeloc = LOC_PRIV_NET_LOCAL_USER;
|
||||||
|
if (c->acked)
|
||||||
return send_message(pri, c, Q931_RELEASE, release_ies);
|
return send_message(pri, c, Q931_RELEASE, release_ies);
|
||||||
|
else
|
||||||
|
return send_message(pri, c, Q931_RELEASE_COMPLETE, release_ies); /* Yes, release_ies, not release_complete_ies */
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1409,11 +1568,11 @@ int q931_disconnect(struct pri *pri, q931_call *c, int cause)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_PROGRESS_INDICATOR,
|
static int setup_ies[] = { Q931_BEARER_CAPABILITY, Q931_CHANNEL_IDENT, Q931_DISPLAY, Q931_PROGRESS_INDICATOR,
|
||||||
Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
|
Q931_CALLING_PARTY_NUMBER, Q931_CALLED_PARTY_NUMBER, Q931_SENDING_COMPLETE, -1 };
|
||||||
|
|
||||||
int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int exclusive,
|
||||||
int nonisdn, char *caller, int callerplan, int callerpres, char *called,
|
int nonisdn, char *caller, int callerplan, char *callername, int callerpres, char *called,
|
||||||
int calledplan, int userl1)
|
int calledplan, int userl1)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
@ -1438,6 +1597,10 @@ int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int ex
|
|||||||
if (caller) {
|
if (caller) {
|
||||||
strncpy(c->callernum, caller, sizeof(c->callernum) - 1);
|
strncpy(c->callernum, caller, sizeof(c->callernum) - 1);
|
||||||
c->callerplan = callerplan;
|
c->callerplan = callerplan;
|
||||||
|
if (callername)
|
||||||
|
strncpy(c->callername, callername, sizeof(c->callername) - 1);
|
||||||
|
else
|
||||||
|
strcpy(c->callername, "");
|
||||||
if ((pri->switchtype == PRI_SWITCH_DMS100) ||
|
if ((pri->switchtype == PRI_SWITCH_DMS100) ||
|
||||||
(pri->switchtype == PRI_SWITCH_ATT4ESS)) {
|
(pri->switchtype == PRI_SWITCH_ATT4ESS)) {
|
||||||
/* Doesn't like certain presentation types */
|
/* Doesn't like certain presentation types */
|
||||||
@ -1447,6 +1610,7 @@ int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int ex
|
|||||||
c->callerpres = callerpres;
|
c->callerpres = callerpres;
|
||||||
} else {
|
} else {
|
||||||
strcpy(c->callernum, "");
|
strcpy(c->callernum, "");
|
||||||
|
strcpy(c->callername, "");
|
||||||
c->callerplan = PRI_UNKNOWN;
|
c->callerplan = PRI_UNKNOWN;
|
||||||
c->callerpres = PRES_NUMBER_NOT_AVAILABLE;
|
c->callerpres = PRES_NUMBER_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
@ -1462,8 +1626,9 @@ int q931_setup(struct pri *pri, q931_call *c, int transmode, int channel, int ex
|
|||||||
c->progress = -1;
|
c->progress = -1;
|
||||||
|
|
||||||
res = send_message(pri, c, Q931_SETUP, setup_ies);
|
res = send_message(pri, c, Q931_SETUP, setup_ies);
|
||||||
if (!res)
|
if (!res) {
|
||||||
c->alive = 1;
|
c->alive = 1;
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1504,14 +1669,14 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
}
|
}
|
||||||
c = q931_getcall(pri, q931_cr(h));
|
c = q931_getcall(pri, q931_cr(h));
|
||||||
if (!c) {
|
if (!c) {
|
||||||
fprintf(stderr, "Unable to locate call %d\n", q931_cr(h));
|
pri_error("Unable to locate call %d\n", q931_cr(h));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* Preliminary handling */
|
/* Preliminary handling */
|
||||||
switch(mh->msg) {
|
switch(mh->msg) {
|
||||||
case Q931_RESTART:
|
case Q931_RESTART:
|
||||||
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
||||||
printf("-- Processing Q.931 Restart\n");
|
pri_message("-- Processing Q.931 Restart\n");
|
||||||
/* Reset information */
|
/* Reset information */
|
||||||
c->channelno = -1;
|
c->channelno = -1;
|
||||||
c->slotmap = -1;
|
c->slotmap = -1;
|
||||||
@ -1519,9 +1684,12 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
c->ds1no = -1;
|
c->ds1no = -1;
|
||||||
c->ri = -1;
|
c->ri = -1;
|
||||||
break;
|
break;
|
||||||
|
case Q931_FACILITY:
|
||||||
|
strcpy(c->callername, "");
|
||||||
|
break;
|
||||||
case Q931_SETUP:
|
case Q931_SETUP:
|
||||||
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
if (pri->debug & PRI_DEBUG_Q931_STATE)
|
||||||
printf("-- Processing Q.931 Call Setup\n");
|
pri_message("-- Processing Q.931 Call Setup\n");
|
||||||
c->channelno = -1;
|
c->channelno = -1;
|
||||||
c->slotmap = -1;
|
c->slotmap = -1;
|
||||||
c->chanflags = 0;
|
c->chanflags = 0;
|
||||||
@ -1539,6 +1707,13 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
c->callerpres = -1;
|
c->callerpres = -1;
|
||||||
strcpy(c->callernum, "");
|
strcpy(c->callernum, "");
|
||||||
strcpy(c->callednum, "");
|
strcpy(c->callednum, "");
|
||||||
|
strcpy(c->callername, "");
|
||||||
|
c->redirectingplan = -1;
|
||||||
|
c->redirectingpres = -1;
|
||||||
|
c->redirectingreason = -1;
|
||||||
|
strcpy(c->redirectingnum, "");
|
||||||
|
c->useruserprotocoldisc = -1;
|
||||||
|
strcpy(c->useruserinfo, "");
|
||||||
break;
|
break;
|
||||||
case Q931_CONNECT:
|
case Q931_CONNECT:
|
||||||
case Q931_ALERTING:
|
case Q931_ALERTING:
|
||||||
@ -1565,13 +1740,13 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
case Q931_RESTART_ACKNOWLEDGE:
|
case Q931_RESTART_ACKNOWLEDGE:
|
||||||
c->channelno = -1;
|
c->channelno = -1;
|
||||||
break;
|
break;
|
||||||
|
case Q931_INFORMATION:
|
||||||
|
break;
|
||||||
case Q931_SETUP_ACKNOWLEDGE:
|
case Q931_SETUP_ACKNOWLEDGE:
|
||||||
case Q931_STATUS_ENQUIRY:
|
case Q931_STATUS_ENQUIRY:
|
||||||
case Q931_USER_INFORMATION:
|
case Q931_USER_INFORMATION:
|
||||||
case Q931_SEGMENT:
|
case Q931_SEGMENT:
|
||||||
case Q931_CONGESTION_CONTROL:
|
case Q931_CONGESTION_CONTROL:
|
||||||
case Q931_INFORMATION:
|
|
||||||
case Q931_FACILITY:
|
|
||||||
case Q931_NOTIFY:
|
case Q931_NOTIFY:
|
||||||
case Q931_HOLD:
|
case Q931_HOLD:
|
||||||
case Q931_HOLD_ACKNOWLEDGE:
|
case Q931_HOLD_ACKNOWLEDGE:
|
||||||
@ -1585,11 +1760,11 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
case Q931_SUSPEND:
|
case Q931_SUSPEND:
|
||||||
case Q931_SUSPEND_ACKNOWLEDGE:
|
case Q931_SUSPEND_ACKNOWLEDGE:
|
||||||
case Q931_SUSPEND_REJECT:
|
case Q931_SUSPEND_REJECT:
|
||||||
fprintf(stderr, "!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
pri_error("!! Not yet handling pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
pri_error("!! Don't know how to pre-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
x = 0;
|
x = 0;
|
||||||
@ -1599,7 +1774,7 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
ie = (q931_ie *)(mh->data + x);
|
ie = (q931_ie *)(mh->data + x);
|
||||||
r = ielen(ie);
|
r = ielen(ie);
|
||||||
if (r > len) {
|
if (r > len) {
|
||||||
fprintf(stderr, "XXX Message longer than it should be?? XXX\n");
|
pri_error("XXX Message longer than it should be?? XXX\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
q931_handle_ie(pri, c, mh->msg, ie);
|
q931_handle_ie(pri, c, mh->msg, ie);
|
||||||
@ -1623,8 +1798,11 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
pri->ev.ring.callingpres = c->callerpres;
|
pri->ev.ring.callingpres = c->callerpres;
|
||||||
pri->ev.ring.callingplan = c->callerplan;
|
pri->ev.ring.callingplan = c->callerplan;
|
||||||
strncpy(pri->ev.ring.callingnum, c->callernum, sizeof(pri->ev.ring.callingnum) - 1);
|
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;
|
pri->ev.ring.calledplan = c->calledplan;
|
||||||
strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 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.flexible = ! (c->chanflags & FLAG_EXCLUSIVE);
|
||||||
pri->ev.ring.cref = c->cr;
|
pri->ev.ring.cref = c->cr;
|
||||||
pri->ev.ring.call = c;
|
pri->ev.ring.call = c;
|
||||||
@ -1647,13 +1825,24 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
pri->ev.answer.call = c;
|
pri->ev.answer.call = c;
|
||||||
q931_connect_acknowledge(pri, c);
|
q931_connect_acknowledge(pri, c);
|
||||||
return Q931_RES_HAVEEVENT;
|
return Q931_RES_HAVEEVENT;
|
||||||
|
case Q931_FACILITY:
|
||||||
|
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;
|
||||||
|
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:
|
case Q931_PROGRESS:
|
||||||
case Q931_CONNECT_ACKNOWLEDGE:
|
case Q931_CONNECT_ACKNOWLEDGE:
|
||||||
case Q931_STATUS:
|
case Q931_STATUS:
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) &&
|
if ((pri->debug & PRI_DEBUG_Q931_ANOMALY) &&
|
||||||
(c->cause != PRI_CAUSE_INTERWORKING))
|
(c->cause != PRI_CAUSE_INTERWORKING))
|
||||||
fprintf(stderr, "Received unsolicited status: %s\n", pri_cause2str(c->cause));
|
pri_error("Received unsolicited status: %s\n", pri_cause2str(c->cause));
|
||||||
break;
|
break;
|
||||||
case Q931_CALL_PROCEEDING:
|
case Q931_CALL_PROCEEDING:
|
||||||
break;
|
break;
|
||||||
@ -1693,26 +1882,32 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
return res;
|
return res;
|
||||||
break;
|
break;
|
||||||
case Q931_DISCONNECT:
|
case Q931_DISCONNECT:
|
||||||
/* Send a release with no cause */
|
|
||||||
q931_release(pri, c, -1);
|
|
||||||
/* Return such an event */
|
/* Return such an event */
|
||||||
pri->ev.e = PRI_EVENT_HANGUP;
|
pri->ev.e = PRI_EVENT_HANGUP;
|
||||||
pri->ev.hangup.channel = c->channelno;
|
pri->ev.hangup.channel = c->channelno;
|
||||||
pri->ev.hangup.cref = c->cr;
|
pri->ev.hangup.cref = c->cr;
|
||||||
pri->ev.hangup.cause = c->cause;
|
pri->ev.hangup.cause = c->cause;
|
||||||
pri->ev.hangup.call = c;
|
pri->ev.hangup.call = c;
|
||||||
|
/* Send a release with no cause */
|
||||||
|
q931_release(pri, c, -1);
|
||||||
return Q931_RES_HAVEEVENT;
|
return Q931_RES_HAVEEVENT;
|
||||||
case Q931_RESTART_ACKNOWLEDGE:
|
case Q931_RESTART_ACKNOWLEDGE:
|
||||||
pri->ev.e = PRI_EVENT_RESTART_ACK;
|
pri->ev.e = PRI_EVENT_RESTART_ACK;
|
||||||
pri->ev.restartack.channel = c->channelno;
|
pri->ev.restartack.channel = c->channelno;
|
||||||
return Q931_RES_HAVEEVENT;
|
return Q931_RES_HAVEEVENT;
|
||||||
|
case Q931_INFORMATION:
|
||||||
|
pri->ev.e = PRI_EVENT_INFO_RECEIVED;
|
||||||
|
pri->ev.ring.call = c;
|
||||||
|
|
||||||
|
strncpy(pri->ev.ring.callednum, c->callednum, sizeof(pri->ev.ring.callednum) - 1);
|
||||||
|
|
||||||
|
return Q931_RES_HAVEEVENT;
|
||||||
|
|
||||||
case Q931_SETUP_ACKNOWLEDGE:
|
case Q931_SETUP_ACKNOWLEDGE:
|
||||||
case Q931_STATUS_ENQUIRY:
|
case Q931_STATUS_ENQUIRY:
|
||||||
case Q931_USER_INFORMATION:
|
case Q931_USER_INFORMATION:
|
||||||
case Q931_SEGMENT:
|
case Q931_SEGMENT:
|
||||||
case Q931_CONGESTION_CONTROL:
|
case Q931_CONGESTION_CONTROL:
|
||||||
case Q931_INFORMATION:
|
|
||||||
case Q931_FACILITY:
|
|
||||||
case Q931_NOTIFY:
|
case Q931_NOTIFY:
|
||||||
case Q931_HOLD:
|
case Q931_HOLD:
|
||||||
case Q931_HOLD_ACKNOWLEDGE:
|
case Q931_HOLD_ACKNOWLEDGE:
|
||||||
@ -1726,11 +1921,11 @@ int q931_receive(struct pri *pri, q931_h *h, int len)
|
|||||||
case Q931_SUSPEND:
|
case Q931_SUSPEND:
|
||||||
case Q931_SUSPEND_ACKNOWLEDGE:
|
case Q931_SUSPEND_ACKNOWLEDGE:
|
||||||
case Q931_SUSPEND_REJECT:
|
case Q931_SUSPEND_REJECT:
|
||||||
fprintf(stderr, "!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
pri_error("!! Not yet handling post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
pri_error("!! Don't know how to post-handle message type %s (%d)\n", msg2str(mh->msg), mh->msg);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user