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 /*
32 * This program tests libpri call reception using a zaptel interface.
33 * Its state machines are setup for RECEIVING CALLS ONLY, so if you
34 * are trying to both place and receive calls you have to a bit more.
35 */
36
37 #include <fcntl.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <errno.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 <netinet/in.h>
50 #include <sys/socket.h>
51 #include <pthread.h>
52 #include <sys/select.h>
53 #include "libpri.h"
54 #include "pri_q921.h"
55 #include "pri_q931.h"
56
57 #ifndef AF_LOCAL
58 #define AF_LOCAL AF_UNIX
59 #endif
60
61 #define DEBUG_LEVEL PRI_DEBUG_ALL
62
63 #define PRI_DEF_NODETYPE PRI_CPE
64 #define PRI_DEF_SWITCHTYPE PRI_SWITCH_NI2
65
66 static struct pri *first;
67
68 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
69
70 #define TEST_CALLS 1
71
event1(struct pri * pri,pri_event * e)72 static void event1(struct pri *pri, pri_event *e)
73 {
74 /* Network */
75 int x;
76 static q931_call *calls[TEST_CALLS];
77 char name[256], num[256], dest[256];
78 switch(e->gen.e) {
79 case PRI_EVENT_DCHAN_UP:
80 printf("Network is up. Sending blast of calls!\n");
81 for (x=0;x<TEST_CALLS;x++) {
82 sprintf(name, "Caller %d", x + 1);
83 sprintf(num, "25642860%02d", x+1);
84 sprintf(dest, "60%02d", x + 1);
85 if (!(calls[x] = pri_new_call(pri))) {
86 perror("pri_new_call");
87 continue;
88 }
89 #if 0
90 {
91 struct pri_sr *sr;
92 sr = pri_sr_new();
93 pri_sr_set_channel(sr, x+1, 0, 0);
94 pri_sr_set_bearer(sr, 0, PRI_LAYER_1_ULAW);
95 pri_sr_set_called(sr, dest, PRI_NATIONAL_ISDN, 1);
96 pri_sr_set_caller(sr, num, name, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN);
97 pri_sr_set_redirecting(sr, num, PRI_NATIONAL_ISDN, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
98 if (pri_setup(pri, calls[x], sr))
99 perror("pri_setup");
100 pri_sr_free(sr);
101 }
102 #else
103 if (pri_call(pri, calls[x], PRI_TRANS_CAP_DIGITAL, x + 1, 1, 1, num,
104 PRI_NATIONAL_ISDN, name, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN,
105 dest, PRI_NATIONAL_ISDN, PRI_LAYER_1_ULAW)) {
106 perror("pri_call");
107 }
108 #endif
109 }
110 printf("Setup %d calls!\n", TEST_CALLS);
111 break;
112 case PRI_EVENT_RINGING:
113 printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
114 q931_facility(pri, e->ringing.call);
115 pri_answer(pri, e->ringing.call, e->ringing.channel, 0);
116 break;
117 case PRI_EVENT_HANGUP_REQ:
118 printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
119 pri_hangup(pri, e->hangup.call, e->hangup.cause);
120 break;
121 default:
122 printf("PRI 1: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
123 }
124 }
125
event2(struct pri * pri,pri_event * e)126 static void event2(struct pri *pri, pri_event *e)
127 {
128 /* CPE */
129 switch(e->gen.e) {
130 case PRI_EVENT_RING:
131 printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
132 pri_proceeding(pri, e->ring.call, e->ring.channel, 0);
133 pri_acknowledge(pri, e->ring.call, e->ring.channel, 0);
134 break;
135 case PRI_EVENT_ANSWER:
136 printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
137 pri_hangup(pri, e->answer.call, PRI_CAUSE_NORMAL_UNSPECIFIED);
138 break;
139 case PRI_EVENT_HANGUP:
140 printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
141 pri_hangup(pri, e->hangup.call, e->hangup.cause);
142 break;
143 case PRI_EVENT_DCHAN_UP:
144 default:
145 printf("PRI 2: %s (%d)\n", pri_event2str(e->gen.e), e->gen.e);
146 }
147 }
148
testmsg(struct pri * pri,char * s)149 static void testmsg(struct pri *pri, char *s)
150 {
151 char *c;
152 static int keeplast = 0;
153 do {
154 c = strchr(s, '\n');
155 if (c) {
156 *c = '\0';
157 c++;
158 }
159 if (keeplast || !pri)
160 printf("%s", s);
161 else if (pri == first)
162 printf("-1 %s", s);
163 else
164 printf("-2 %s", s);
165 if (c)
166 printf("\n");
167 s = c;
168 } while(c && *c);
169 if (!c)
170 keeplast = 1;
171 else
172 keeplast = 0;
173 }
174
testerr(struct pri * pri,char * s)175 static void testerr(struct pri *pri, char *s)
176 {
177 char *c;
178 static int keeplast = 0;
179 do {
180 c = strchr(s, '\n');
181 if (c) {
182 *c = '\0';
183 c++;
184 }
185 if (keeplast || !pri)
186 printf("%s", s);
187 else if (pri == first)
188 printf("=1 %s", s);
189 else
190 printf("=2 %s", s);
191 if (c)
192 printf("\n");
193 s = c;
194 } while(c && *c);
195 if (!c)
196 keeplast = 1;
197 else
198 keeplast = 0;
199 }
200
201
dchan(void * data)202 static void *dchan(void *data)
203 {
204 /* Joint D-channel */
205 struct pri *pri = data;
206 struct timeval *next, tv;
207 pri_event *e = NULL;
208 fd_set fds;
209 int res;
210 for(;;) {
211 if ((next = pri_schedule_next(pri))) {
212 gettimeofday(&tv, NULL);
213 tv.tv_sec = next->tv_sec - tv.tv_sec;
214 tv.tv_usec = next->tv_usec - tv.tv_usec;
215 if (tv.tv_usec < 0) {
216 tv.tv_usec += 1000000;
217 tv.tv_sec -= 1;
218 }
219 if (tv.tv_sec < 0) {
220 tv.tv_sec = 0;
221 tv.tv_usec = 0;
222 }
223 }
224 FD_ZERO(&fds);
225 FD_SET(pri_fd(pri), &fds);
226 res = select(pri_fd(pri) + 1, &fds, NULL, NULL, next ? &tv : NULL);
227 pthread_mutex_lock(&lock);
228 if (res < 0) {
229 perror("select");
230 } else if (!res) {
231 e = pri_schedule_run(pri);
232 } else {
233 e = pri_check_event(pri);
234 }
235 if (e) {
236 if (first == pri) {
237 event1(pri, e);
238 } else {
239 event2(pri, e);
240 }
241 }
242 pthread_mutex_unlock(&lock);
243 }
244 return NULL;
245 }
246
247
main(int argc,char * argv[])248 int main(int argc, char *argv[])
249 {
250 int pair[2];
251 pthread_t tmp;
252 struct pri *pri;
253 pri_set_message(testmsg);
254 pri_set_error(testerr);
255 if (socketpair(AF_LOCAL, SOCK_DGRAM, 0, pair)) {
256 perror("socketpair");
257 exit(1);
258 }
259 if (!(pri = pri_new_bri(pair[0], 0, PRI_NETWORK, PRI_DEF_SWITCHTYPE))) {
260 perror("pri(0)");
261 exit(1);
262 }
263 first = pri;
264 pri_set_debug(pri, DEBUG_LEVEL);
265 pri_facility_enable(pri);
266 if (pthread_create(&tmp, NULL, dchan, pri)) {
267 perror("thread(0)");
268 exit(1);
269 }
270 if (!(pri = pri_new_bri(pair[1], 0, PRI_CPE, PRI_DEF_SWITCHTYPE))) {
271 perror("pri(1)");
272 exit(1);
273 }
274 pri_set_debug(pri, DEBUG_LEVEL);
275 pri_facility_enable(pri);
276 if (pthread_create(&tmp, NULL, dchan, pri)) {
277 perror("thread(1)");
278 exit(1);
279 }
280 /* Wait for things to run */
281 sleep(5);
282 exit(0);
283 }
284
285