1 /*
2  * libpri: An implementation of Primary Rate ISDN
3  *
4  * Written by Mark Spencer <markster@digium.com>
5  *
6  * Copyright (C) 2001-2005, Digium, Inc.
7  * All Rights Reserved.
8  */
9 
10 /*
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  * This program is free software, distributed under the terms of
18  * the GNU General Public License Version 2 as published by the
19  * Free Software Foundation. See the LICENSE file included with
20  * this program for more details.
21  *
22  * In addition, when this program is distributed with Asterisk in
23  * any form that would qualify as a 'combined work' or as a
24  * 'derivative work' (but not mere aggregation), you can redistribute
25  * and/or modify the combination under the terms of the license
26  * provided with that copy of Asterisk, instead of the license
27  * terms granted here.
28  */
29 
30 /*
31  * This program tests libpri call reception using a dahdi interface.
32  * Its state machines are setup for RECEIVING CALLS ONLY, so if you
33  * are trying to both place and receive calls you have to a bit more.
34  */
35 
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <string.h>
39 #include <errno.h>
40 #include <ctype.h>
41 #include <sys/ioctl.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <sys/signal.h>
45 #include <sys/select.h>
46 #include <sys/wait.h>
47 #include <sys/resource.h>
48 #include <sys/time.h>
49 #include <dahdi/user.h>
50 #include <dahdi/tonezone.h>
51 #include "libpri.h"
52 
53 #define PRI_DEF_NODETYPE	PRI_CPE
54 #define PRI_DEF_SWITCHTYPE	PRI_SWITCH_NI2
55 
56 #define MAX_CHAN		32
57 #define	DCHANNEL_TIMESLOT	16
58 
59 #define READ_SIZE 160
60 
61 static int offset = 0;
62 
do_channel(int fd)63 static void do_channel(int fd)
64 {
65 	/* This is the part that runs on a given channel */
66 	char buf[READ_SIZE];
67 	int res;
68 	int i=0;
69 
70 	while ((res = read(fd, buf, READ_SIZE)) > 0 && (i++ < 1000)) {
71 		if (write(fd, buf, res) == -1) {
72 			fprintf(stderr, "--!! Failed write: %d\n", errno);
73 			break;
74 		}
75 	}
76 }
77 
78 struct pri_chan {
79 	pid_t pid;
80 	int needhangup;
81 	int alreadyhungup;
82 	q931_call *call;
83 } chans[MAX_CHAN];
84 
str2node(char * node)85 static int str2node(char *node)
86 {
87 	if (!strcasecmp(node, "cpe"))
88 		return PRI_CPE;
89 	if (!strcasecmp(node, "network"))
90 		return PRI_NETWORK;
91 	return -1;
92 }
93 
chan_ended(int sig)94 static void chan_ended(int sig)
95 {
96 	int status;
97 	int x;
98 	struct rusage rusage;
99 	pid_t pid;
100 	pid = wait4(-1, &status, WNOHANG, &rusage);
101 
102 	for (x=0;x<MAX_CHAN;x++) {
103 		if (pid == chans[x].pid) {
104 			printf("-- PID %d ended, channel %d\n", pid, x);
105 			chans[x].pid = 0;
106 			if (!chans[x].alreadyhungup) {
107 				/* It died, we need to hangup now */
108 				chans[x].needhangup = 1;
109 			} else {
110 				/* We've already been hungup, just clear it */
111 				chans[x].alreadyhungup = 0;
112 				chans[x].call = NULL;
113 			}
114 			return;
115 		}
116 	}
117 
118 	if (pid > -1) {
119 		fprintf(stderr, "--!! Unknown PID %d exited\n", pid);
120 		return;
121 	}
122 }
str2switch(char * swtype)123 static int str2switch(char *swtype)
124 {
125 	if (!strcasecmp(swtype, "ni2"))
126 		return PRI_SWITCH_NI2;
127 	if (!strcasecmp(swtype, "dms100"))
128 		return PRI_SWITCH_DMS100;
129 	if (!strcasecmp(swtype, "lucent5e"))
130 		return PRI_SWITCH_LUCENT5E;
131 	if (!strcasecmp(swtype, "att4ess"))
132 		return PRI_SWITCH_ATT4ESS;
133 	if (!strcasecmp(swtype, "euroisdn"))
134 		return PRI_SWITCH_EUROISDN_E1;
135 	if (!strcasecmp(swtype, "gr303eoc"))
136 		return PRI_SWITCH_GR303_EOC;
137 	if (!strcasecmp(swtype, "gr303tmc"))
138 		return PRI_SWITCH_GR303_TMC;
139 	return -1;
140 }
141 
hangup_channel(int channo)142 static void hangup_channel(int channo)
143 {
144 	if (chans[channo].pid) {
145 
146 #if 0
147 		printf("Killing channel %d (pid = %d)\n", channo, chans[channo].pid);
148 #endif
149 		chans[channo].alreadyhungup = 1;
150 		kill(chans[channo].pid, SIGTERM);
151 	} else if (chans[channo].needhangup)
152 		chans[channo].needhangup = 0;
153 }
154 
dahdi_open(char * fn)155 static int dahdi_open(char *fn)
156 {
157 	int fd;
158 	int isnum;
159 	int chan = 0;
160 	int bs;
161 	int x;
162 
163 	fprintf(stderr, "dahdi open %s\n", fn);
164 
165 	isnum = 1;
166 	for (x = 0; x < strlen(fn); x++) {
167 		if (!isdigit(fn[x])) {
168 			isnum = 0;
169 			break;
170 		}
171 	}
172 	if (isnum) {
173 		chan = atoi(fn);
174 		if (chan < 1) {
175 			printf("Invalid channel number '%s'\n", fn);
176 			exit(1);
177 		}
178 		fn = "/dev/dahdi/channel";
179 	}
180 	fd = open(fn, O_RDWR /* | O_NONBLOCK */);
181 	if (fd < 0) {
182 		printf("Unable to open '%s': %s\n", fn, strerror(errno));
183 		exit(1);
184 	}
185 	if (chan) {
186 		if (ioctl(fd, DAHDI_SPECIFY, &chan)) {
187 			x = errno;
188 			close(fd);
189 			errno = x;
190 			printf("Unable to specify channel %d: %s\n", chan, strerror(errno));
191 			exit(1);
192 		}
193 	}
194 	bs = READ_SIZE;
195 	if (ioctl(fd, DAHDI_SET_BLOCKSIZE, &bs) == -1) {
196 		printf("Unable to set blocksize '%d': %s\n", bs,  strerror(errno));
197 		exit(1);
198 	}
199 	return fd;
200 }
201 
launch_channel(int channo)202 static void launch_channel(int channo)
203 {
204 	pid_t pid;
205 	int z;
206 	char ch[80];
207 
208 	/* Make sure hangup state is reset */
209 	chans[channo].needhangup = 0;
210 	chans[channo].alreadyhungup = 0;
211 
212 	pid = fork();
213 	if (pid < 0) {
214 		fprintf(stderr, "--!! Unable to fork\n");
215 		chans[channo].needhangup = 1;
216 	}
217 	if (pid) {
218 		printf("-- Launching process %d to handle channel %d\n", pid, channo);
219 		chans[channo].pid = pid;
220 	} else {
221 		sprintf(ch, "%d", channo + offset);
222 		z = dahdi_open(ch);
223 		if (z) {
224 			do_channel(z);
225 			exit(0);
226 		} else {
227 			fprintf(stderr, "--!! Unable to open channel %d\n", channo);
228 			exit(1);
229 		}
230 	}
231 
232 }
233 
get_free_channel(int channo)234 static int get_free_channel(int channo)
235 {
236 	channo--;
237 	if((channo>MAX_CHAN)||(channo<0)) {
238 		fprintf(stderr, "Invalid Bchannel RANGE <%d", channo);
239 		return 0;
240 	};
241 
242 	while(chans[channo].pid) {
243 		channo--;
244 	}
245 
246 	return channo;
247 }
248 
249 /* place here criteria for completion of destination number */
number_incommplete(char * number)250 static int number_incommplete(char *number)
251 {
252   return strlen(number) < 3;
253 }
254 
start_channel(struct pri * pri,pri_event * e)255 static void start_channel(struct pri *pri, pri_event *e)
256 {
257 	int channo = e->ring.channel;
258 	int		flag = 1;
259 	pri_event_ring	*ring = &e->ring;
260 
261 	if(channo == -1) {
262 		channo = e->ring.channel = get_free_channel(MAX_CHAN);
263 
264 		if(channo == DCHANNEL_TIMESLOT)
265 			channo = e->ring.channel = get_free_channel(MAX_CHAN);
266 
267 
268 		fprintf(stdout, "Any channel selected: %d\n", channo);
269 
270 		if(!channo) {
271 		  pri_release(pri, ring->call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
272 		  fprintf(stdout, "Abort call due to no avl B channels\n");
273 		  return;
274 		}
275 
276 		flag = 0;
277 	}
278 	/* Make sure it's a valid number */
279 	if ((channo >= MAX_CHAN) || (channo < 0)) {
280 		fprintf(stderr, "--!! Channel %d is out of range\n", channo);
281 		return;
282 	}
283 
284 	/* Make sure nothing is there */
285 	if (chans[channo].pid) {
286 		fprintf(stderr, "--!! Channel %d still has a call on it, ending it...\n", channo);
287 		hangup_channel(channo);
288 		/* Wait for it to die */
289 		while(chans[channo].pid)
290 			usleep(100);
291 	}
292 
293 	/* Record call number */
294 	chans[channo].call = e->ring.call;
295 
296 	/* Answer the line */
297 	if(flag) {
298 		pri_answer(pri, chans[channo].call, channo, 1);
299 	} else {
300 		pri_need_more_info(pri, chans[channo].call, channo, 1);
301 	}
302 
303 	/* Launch a process to handle it */
304 	launch_channel(channo);
305 
306 }
307 
handle_pri_event(struct pri * pri,pri_event * e)308 static void handle_pri_event(struct pri *pri, pri_event *e)
309 {
310 	switch(e->e) {
311 	case PRI_EVENT_DCHAN_UP:
312 		printf("-- D-Channel is now up!  :-)\n");
313 		break;
314 	case PRI_EVENT_DCHAN_DOWN:
315 		printf("-- D-Channel is now down! :-(\n");
316 		break;
317 	case PRI_EVENT_RESTART:
318 		printf("-- Restarting channel %d\n", e->restart.channel);
319 		hangup_channel(e->restart.channel);
320 		break;
321 	case PRI_EVENT_CONFIG_ERR:
322 		printf("-- Configuration error detected: %s\n", e->err.err);
323 		break;
324 	case PRI_EVENT_RING:
325 		printf("-- Ring on channel %d (from %s to %s), answering...\n", e->ring.channel, e->ring.callingnum, e->ring.callednum);
326 		start_channel(pri, e);
327 		break;
328 	case PRI_EVENT_HANGUP:
329 		printf("-- Hanging up channel %d\n", e->hangup.channel);
330 		hangup_channel(e->hangup.channel);
331 		break;
332 	case PRI_EVENT_RINGING:
333 	case PRI_EVENT_ANSWER:
334 		fprintf(stderr, "--!! What?  We shouldn't be making any calls...\n");
335 		break;
336 	case PRI_EVENT_HANGUP_ACK:
337 		/* Ignore */
338 		break;
339 	case PRI_EVENT_INFO_RECEIVED:
340 		fprintf(stdout, "number is: %s\n", e->ring.callednum);
341 		if(!number_incommplete(e->ring.callednum)) {
342 			fprintf(stdout, "final number is: %s\n", e->ring.callednum);
343 			pri_answer(pri, e->ring.call, 0, 1);
344 		}
345 
346 		break;
347 	default:
348 		fprintf(stderr, "--!! Unknown PRI event %d\n", e->e);
349 	}
350 }
351 
run_pri(int dfd,int swtype,int node)352 static int run_pri(int dfd, int swtype, int node)
353 {
354 	struct pri *pri;
355 	pri_event *e;
356 	struct timeval tv = {0,0}, *next;
357 	fd_set rfds, efds;
358 	int res,x;
359 
360 	pri = pri_new(dfd, node, swtype);
361 	if (!pri) {
362 		fprintf(stderr, "Unable to create PRI\n");
363 		return -1;
364 	}
365 	pri_set_debug(pri, -1);
366 	for (;;) {
367 
368 		/* Run the D-Channel */
369 		FD_ZERO(&rfds);
370 		FD_ZERO(&efds);
371 		FD_SET(dfd, &rfds);
372 		FD_SET(dfd, &efds);
373 
374 		if ((next = pri_schedule_next(pri))) {
375 			gettimeofday(&tv, NULL);
376 			tv.tv_sec = next->tv_sec - tv.tv_sec;
377 			tv.tv_usec = next->tv_usec - tv.tv_usec;
378 			if (tv.tv_usec < 0) {
379 				tv.tv_usec += 1000000;
380 				tv.tv_sec -= 1;
381 			}
382 			if (tv.tv_sec < 0) {
383 				tv.tv_sec = 0;
384 				tv.tv_usec = 0;
385 			}
386 		}
387 		res = select(dfd + 1, &rfds, NULL, &efds, next ? &tv : NULL);
388 		e = NULL;
389 
390 		if (!res) {
391 			e = pri_schedule_run(pri);
392 		} else if (res > 0) {
393 			e = pri_check_event(pri);
394 		} else if (errno == ELAST) {
395 			res = ioctl(dfd, DAHDI_GETEVENT, &x);
396 			printf("Got DAHDI event: %d\n", x);
397 		} else if (errno != EINTR)
398 			fprintf(stderr, "Error (%d) on select: %s\n", ELAST, strerror(errno));
399 
400 		if (e) {
401 			handle_pri_event(pri, e);
402 		}
403 
404 		res = ioctl(dfd, DAHDI_GETEVENT, &x);
405 
406 		if (!res && x) {
407 			fprintf(stderr, "Got event on PRI interface: %d\n", x);
408 		}
409 
410 		/* Check for lines that need hangups */
411 		for (x=0;x<MAX_CHAN;x++)
412 			if (chans[x].needhangup) {
413 				chans[x].needhangup = 0;
414 				pri_release(pri, chans[x].call, PRI_CAUSE_NORMAL_CLEARING);
415 			}
416 
417 	}
418 	return 0;
419 }
420 
main(int argc,char * argv[])421 int main(int argc, char *argv[])
422 {
423 	int dfd;
424 	int swtype = PRI_DEF_SWITCHTYPE;
425 	int node = PRI_DEF_NODETYPE;
426 	struct dahdi_params p;
427 	if (argc < 2) {
428 		fprintf(stderr, "Usage: pritest <dchannel> [swtypetype] [nodetype]\n");
429 		exit(1);
430 	}
431 	dfd = open(argv[1], O_RDWR);
432 	if (dfd < 0) {
433 		fprintf(stderr, "Failed to open dchannel '%s': %s\n", argv[1], strerror(errno));
434 		exit(1);
435 	}
436 	if (ioctl(dfd, DAHDI_GET_PARAMS, &p)) {
437 		fprintf(stderr, "Unable to get parameters on '%s': %s\n", argv[1], strerror(errno));
438 		exit(1);
439 	}
440 	if ((p.sigtype != DAHDI_SIG_HDLCRAW) && (p.sigtype != DAHDI_SIG_HDLCFCS)) {
441 		fprintf(stderr, "%s is in %d signalling, not FCS HDLC or RAW HDLC mode\n", argv[1], p.sigtype);
442 		exit(1);
443 	}
444 
445 	if (argc > 2) {
446 		swtype = str2switch(argv[2]);
447 		if (swtype < 0) {
448 			fprintf(stderr, "Valid switchtypes are: ni2, dms100, lucent5e, att4ess, and euroisdn\n");
449 			exit(1);
450 		}
451 	}
452 
453 	if (argc > 3) {
454 		node = str2node(argv[3]);
455 		if (node < 0) {
456 			fprintf(stderr, "Valid node types are: network and cpe\n");
457 			exit(1);
458 		}
459 	}
460 
461 	signal(SIGCHLD, chan_ended);
462 
463 	if (run_pri(dfd, swtype, node))
464 		exit(1);
465 	exit(0);
466 
467 	return 0;
468 }
469