mISDNuser/i4lnet/nettst.c

321 lines
7.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include "isdn_net.h"
#include "net_l2.h"
#include "net_l3.h"
#include "net_l4.h"
#include "l3dss1.h"
#include "helper.h"
#include "bchannel.h"
#include "tone.h"
net_stack_t kern_if;
itimer_t timer1;
static void
do_cleanup(net_stack_t *nst)
{
fprintf(stderr, "%s\n", __FUNCTION__);
cleanup_Isdnl4(nst);
cleanup_Isdnl3(nst);
cleanup_Isdnl2(nst);
do_net_stack_cleanup(nst);
}
static void
term_handler(int sig)
{
pthread_t tid;
tid = pthread_self();
fprintf(stderr,"signal %d received from thread %ld\n", sig, tid);
test_and_set_bit(FLG_KIF_TERMINATION, &kern_if.flag);
sem_post(&kern_if.network);
}
static int
man_down(net_stack_t *nst, msg_t *msg)
{
msg_queue_tail(&nst->wqueue, msg);
sem_post(&nst->network);
return(0);
}
static int
do_disconnect(layer4_t *l4)
{
l4->cause_loc = CAUSE_LOC_PNET_LOCUSER;
l4->cause_val = CAUSE_NORMAL_CLEARING;
l4->progress = PROGRESS_TONE;
if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST,
l4->channel, 0, NULL, 0);
return(0);
}
static int
do_connect(layer4_t *l4)
{
if_link(l4->nst, man_down, MAN_CONNECT | REQUEST,
l4->channel, 0, NULL, 0);
return(0);
}
static int
do_alert(layer4_t *l4)
{
if_link(l4->nst, man_down, MAN_ALERT | REQUEST,
l4->channel, 0, NULL, 0);
return(0);
}
static int
clear_call(layer4_t *l4)
{
if (l4->sdata) {
layer4_t *peer = l4->sdata;
if (l4->cause_val) {
peer->cause_loc = l4->cause_loc;
peer->cause_val = l4->cause_val;
} else {
peer->cause_loc = CAUSE_LOC_PNET_LOCUSER;
peer->cause_val = CAUSE_NORMALUNSPECIFIED;
}
peer->progress = PROGRESS_TONE;
peer->sbuf = NULL;
peer->sdata = NULL;
peer->rdata = NULL;
if (peer->nst)
if_link(peer->nst, man_down, MAN_CLEAR_CALL |
REQUEST, peer->channel, 0, NULL, 0);
}
l4->sdata = NULL;
l4->rdata = NULL;
l4->sbuf = NULL;
return(0);
}
static int
alert_call(layer4_t *l4)
{
if (l4->sdata)
do_alert(l4->sdata);
return(0);
}
static int
connect_call(layer4_t *l4)
{
strcpy(l4->display,"connect ack");
if_link(l4->nst, man_down, MAN_CONNECT | RESPONSE,
l4->channel, 0, NULL, 0);
del_timer(&timer1);
if (l4->sdata)
do_connect(l4->sdata);
return(0);
}
static int
route_call(layer4_t *l4)
{
layer4_t *newl4;
fprintf(stderr, "%s: msn ", __FUNCTION__);
display_NR_IE(l4->msn);
fprintf(stderr, "%s: nr ", __FUNCTION__);
display_NR_IE(l4->nr);
if (l4->usednr->typ == NR_TYPE_INTERN) {
newl4 = get_free_channel(&kern_if, -1, NULL);
if (!newl4) {
l4->cause_loc = CAUSE_LOC_PNET_LOCUSER;
l4->cause_val = CAUSE_USER_BUSY;
l4->progress = PROGRESS_TONE;
if_link(l4->nst, man_down, MAN_CLEAR_CALL | REQUEST,
l4->channel, 0, NULL, 0);
return(0);
}
l4->sdata = newl4;
l4->rdata = newl4;
newl4->sdata = l4;
newl4->rdata = l4;
l4->sbuf = &newl4->rbuf;
newl4->sbuf = &l4->rbuf;
newl4->msn[0] = l4->usednr->len +1;
newl4->msn[1] = 0x81;
memcpy(&newl4->msn[2], l4->usednr->nr, l4->usednr->len);
if (l4->msn[0])
memcpy(newl4->nr, l4->msn, l4->msn[0] + 1);
newl4->l1_prot = ISDN_PID_L1_B_64TRANS;
if_link(newl4->nst, man_down, MAN_SETUP | REQUEST,
newl4->channel, 0, NULL, 0);
} else if (l4->usednr->typ == NR_TYPE_AUDIO) {
l4->sdata = NULL;
l4->rdata = NULL;
strcpy(l4->display,"connect to AUDIO");
do_connect(l4);
l4->display[0] = 0;
deactivate_bchannel(l4);
setup_bchannel_rawdev(l4);
activate_bchannel(l4);
} else if (l4->usednr->typ == NR_TYPE_VOIP) {
l4->sdata = NULL;
l4->rdata = NULL;
sprintf(l4->display,"calling %s", l4->usednr->name);
do_alert(l4);
sprintf(l4->display,"connect to %s", l4->usednr->name);
do_connect(l4);
l4->display[0] = 0;
deactivate_bchannel(l4);
setup_bchannel_rawdev(l4);
activate_bchannel(l4);
}
return(0);
}
static int
manager(net_stack_t *nst, msg_t *msg) {
mISDN_head_t *hh;
layer4_t *l4;
if (!msg)
return(-EINVAL);
hh = (mISDN_head_t *)msg->data;
msg_pull(msg, mISDN_HEAD_SIZE);
fprintf(stderr, "%s: prim(%x) msg->len(%d)\n", __FUNCTION__,
hh->prim, msg->len);
if (hh->dinfo == 1) {
l4 = &nst->layer4[0];
} else if (hh->dinfo == 2) {
l4 = &nst->layer4[1];
} else {
return(-EINVAL);
}
switch(hh->prim) {
case MAN_SETUP | INDICATION:
fprintf(stderr, "%s: setup id(%x)\n", __FUNCTION__,
hh->dinfo);
route_call(l4);
break;
case MAN_ALERT | INDICATION:
fprintf(stderr, "%s: connect id(%x)\n", __FUNCTION__,
hh->dinfo);
alert_call(l4);
break;
case MAN_CONNECT | INDICATION:
fprintf(stderr, "%s: connect id(%x)\n", __FUNCTION__,
hh->dinfo);
connect_call(l4);
break;
case MAN_CLEAR_CALL | INDICATION:
fprintf(stderr, "%s: clear call id(%x)\n", __FUNCTION__,
hh->dinfo);
clear_call(l4);
break;
default:
fprintf(stderr, "%s: unhandled prim(%x) msg->len(%d)\n", __FUNCTION__,
hh->prim, msg->len);
break;
}
free_msg(msg);
return(0);
}
int main(argc,argv)
int argc;
char *argv[];
{
int ret, *retp;
nr_list_t *nr1,*nr2,*nr3,*nr4,*nr5;
layer4_t *l4;
if_action_t mISDNrd,*hrd;
nr1 = malloc(sizeof(nr_list_t));
nr2 = malloc(sizeof(nr_list_t));
nr3 = malloc(sizeof(nr_list_t));
nr4 = malloc(sizeof(nr_list_t));
nr5 = malloc(sizeof(nr_list_t));
memset(nr1, 0, sizeof(nr_list_t));
memset(nr2, 0, sizeof(nr_list_t));
memset(nr3, 0, sizeof(nr_list_t));
memset(nr4, 0, sizeof(nr_list_t));
memset(nr5, 0, sizeof(nr_list_t));
nr1->len = 5;
strcpy(nr1->nr,"12345");
nr1->typ = NR_TYPE_INTERN;
nr2->len = 4;
strcpy(nr2->nr,"4566");
nr2->typ = NR_TYPE_INTERN;
nr3->len = 3;
strcpy(nr3->nr,"789");
nr3->typ = NR_TYPE_AUDIO;
nr4->len = 3;
strcpy(nr4->nr,"147");
strcpy(nr4->name, "pingi2");
nr4->typ = NR_TYPE_VOIP;
nr5->len = 3;
strcpy(nr5->nr,"258");
strcpy(nr5->name, "pingi2");
nr5->typ = NR_TYPE_VOIP;
msg_init();
ret = do_net_stack_setup(&kern_if);
if (ret) {
fprintf(stderr, "error in do_net_stack_setup %d\n", ret);
return(0);
}
APPEND_TO_LIST(nr1, kern_if.nrlist);
APPEND_TO_LIST(nr2, kern_if.nrlist);
APPEND_TO_LIST(nr3, kern_if.nrlist);
APPEND_TO_LIST(nr4, kern_if.nrlist);
APPEND_TO_LIST(nr5, kern_if.nrlist);
Isdnl2Init(&kern_if);
Isdnl3Init(&kern_if);
Isdnl4Init(&kern_if);
kern_if.l4_mgr = manager;
init_bhandler(&kern_if);
memset(&timer1, 0, sizeof(itimer_t));
signal(SIGTERM, term_handler);
signal(SIGINT, term_handler);
signal(SIGPIPE, term_handler);
if (argc>1) {
l4 = get_free_channel(&kern_if, -1, NULL);
if (l4) {
l4->msn[0] = 4;
l4->msn[1] = 0x81;
l4->msn[2] = '8';
l4->msn[3] = '8';
l4->msn[4] = '8';
l4->nr[0] = 4;
l4->nr[1] = 0x81;
l4->nr[2] = '1';
l4->nr[3] = '2';
l4->nr[4] = '3';
l4->l1_prot = ISDN_PID_L1_B_64TRANS;
if_link(l4->nst, man_down, MAN_SETUP | REQUEST,
l4->channel, 0, NULL, 0);
del_timer(&timer1);
timer1.function = (void *)do_disconnect;
timer1.data = (long)l4;
init_timer(&timer1, &kern_if);
timer1.expires = 8000;
add_timer(&timer1);
}
}
hrd = &mISDNrd;
memset(hrd, 0, sizeof(if_action_t));
hrd->nst = &kern_if;
hrd->fd = kern_if.device;
hrd->function = do_net_read;
APPEND_TO_LIST(hrd, kern_if.rd);
retp = do_netthread(&kern_if);
fprintf(stderr, "do_main_loop returns(%p)\n", retp);
do_cleanup(&kern_if);
return(0);
}