From 23a638cf66d8a1bba416d065842c371eead9f94e Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Thu, 17 Mar 2005 15:46:23 +0000 Subject: [PATCH] Allow PRI to support callback functions (Diana's patch, placed in public domain) git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@202 2fbb986a-6c06-0410-b554-c9c1f0a7f128 --- libpri.h | 12 ++++++++++ pri.c | 62 +++++++++++++++++++++++++++++++++++++++++--------- pri_internal.h | 3 +++ q921.c | 2 +- q931.c | 2 +- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/libpri.h b/libpri.h index b4c1d9b..0b2d998 100755 --- a/libpri.h +++ b/libpri.h @@ -376,6 +376,9 @@ typedef union { struct pri; struct pri_sr; +#define PRI_IO_FUNCS +/* Type declaration for callbacks to read or write a HDLC frame as below */ +typedef int (*pri_io_cb)(struct pri *pri, void *buf, int buflen); /* Create a D-channel on a given file descriptor. The file descriptor must be a channel operating in HDLC mode with FCS computed by the fd's driver. Also it @@ -383,6 +386,15 @@ struct pri_sr; must be one of PRI_NETWORK or PRI_CPE. switchtype should be PRI_SWITCH_* */ extern struct pri *pri_new(int fd, int nodetype, int switchtype); +/* Create D-channel just as above with user defined I/O callbacks and data */ +extern struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata); + +/* Retrieve the user data associated with the D channel */ +extern void *pri_get_userdata(struct pri *pri); + +/* Set the user data associated with the D channel */ +extern void pri_set_userdata(struct pri *pri, void *userdata); + /* Set Network Specific Facility for PRI */ extern void pri_set_nsf(struct pri *pri, int nsf); diff --git a/pri.c b/pri.c index 71774d5..ac1cf0b 100755 --- a/pri.c +++ b/pri.c @@ -153,13 +153,38 @@ int pri_timer2idx(char *timer) return -1; } -static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master) +static int __pri_read(struct pri *pri, void *buf, int buflen) +{ + int res = read(pri->fd, buf, buflen); + if (res < 0) { + if (errno != EAGAIN) + pri_error("Read on %d failed: %s\n", pri->fd, strerror(errno)); + return 0; + } + return res; +} + +static int __pri_write(struct pri *pri, void *buf, int buflen) +{ + int res = write(pri->fd, buf, buflen); + if (res < 0) { + if (errno != EAGAIN) + pri_error("Write to %d failed: %s\n", pri->fd, strerror(errno)); + return 0; + } + return res; +} + +static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *master, pri_io_cb rd, pri_io_cb wr, void *userdata) { struct pri *p; p = malloc(sizeof(struct pri)); if (p) { memset(p, 0, sizeof(struct pri)); p->fd = fd; + p->read_func = rd; + p->write_func = wr; + p->userdata = userdata; p->localtype = node; p->switchtype = switchtype; p->cref = 1; @@ -180,7 +205,7 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste p->protodisc = GR303_PROTOCOL_DISCRIMINATOR; p->sapi = Q921_SAPI_GR303_EOC; p->tei = Q921_TEI_GR303_EOC_OPS; - p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p); + p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_EOC_PATH, p, NULL, NULL, NULL); if (!p->subchannel) { free(p); p = NULL; @@ -189,7 +214,7 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste p->protodisc = GR303_PROTOCOL_DISCRIMINATOR; p->sapi = Q921_SAPI_GR303_TMC_CALLPROC; p->tei = Q921_TEI_GR303_TMC_CALLPROC; - p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p); + p->subchannel = __pri_new(-1, node, PRI_SWITCH_GR303_TMC_SWITCHING, p, NULL, NULL, NULL); if (!p->subchannel) { free(p); p = NULL; @@ -210,9 +235,29 @@ static struct pri *__pri_new(int fd, int node, int switchtype, struct pri *maste return p; } -struct pri *pri_new(int fd, int node, int switchtype) +struct pri *pri_new(int fd, int nodetype, int switchtype) { - return __pri_new(fd, node, switchtype, NULL); + return __pri_new(fd, nodetype, switchtype, NULL, __pri_read, __pri_write, NULL); +} + +struct pri *pri_new_cb(int fd, int nodetype, int switchtype, pri_io_cb io_read, pri_io_cb io_write, void *userdata) +{ + if (!io_read) + io_read = __pri_read; + if (!io_write) + io_write = __pri_write; + return __pri_new(fd, nodetype, switchtype, NULL, io_read, io_write, userdata); +} + +void *pri_get_userdata(struct pri *pri) +{ + return pri ? pri->userdata : NULL; +} + +void pri_set_userdata(struct pri *pri, void *userdata) +{ + if (pri) + pri->userdata = userdata; } void pri_set_nsf(struct pri *pri, int nsf) @@ -268,12 +313,7 @@ pri_event *pri_check_event(struct pri *pri) char buf[1024]; int res; pri_event *e; - res = read(pri->fd, buf, sizeof(buf)); - if (res < 0) { - if (errno != EAGAIN) - pri_error("Read on %d failed: %s\n", pri->fd, strerror(errno)); - return NULL; - } + res = pri->read_func ? pri->read_func(pri, buf, sizeof(buf)) : 0; if (!res) return NULL; /* Receive the q921 packet */ diff --git a/pri_internal.h b/pri_internal.h index 18c2b08..38acd03 100755 --- a/pri_internal.h +++ b/pri_internal.h @@ -44,6 +44,9 @@ enum q931_mode; struct pri { int fd; /* File descriptor for D-Channel */ + pri_io_cb read_func; /* Read data callback */ + pri_io_cb write_func; /* Write data callback */ + void *userdata; struct pri *subchannel; /* Sub-channel if appropriate */ struct pri *master; /* Master channel if appropriate */ struct pri_sched pri_sched[MAX_SCHED]; /* Scheduled events */ diff --git a/q921.c b/q921.c index 6c3efdd..86bd122 100755 --- a/q921.c +++ b/q921.c @@ -83,7 +83,7 @@ static int q921_transmit(struct pri *pri, q921_h *h, int len) if (pri->debug & PRI_DEBUG_Q921_DUMP) q921_dump(h, len, pri->debug & PRI_DEBUG_Q921_RAW, 1); /* Write an extra two bytes for the FCS */ - res = write(pri->fd, h, len + 2); + res = pri->write_func ? pri->write_func(pri, h, len + 2) : 0; if (res != (len + 2)) { pri_error("Short write: %d/%d (%s)\n", res, len + 2, strerror(errno)); return -1; diff --git a/q931.c b/q931.c index c9c474e..6ad5406 100755 --- a/q931.c +++ b/q931.c @@ -1929,10 +1929,10 @@ static FUNC_RECV(receive_generic_digits) } if (len == 3) /* No number information */ return 0; + value = 0; switch(type) { /* Integer value handling */ case 4: /* Info Digits */ - value = 0; for(idx = 3; idx < len; ++idx) { switch(encoding) { case 0: /* BCD even */