/[svn]/projects/allstar/astsrc-1.4.23-pre/trunk/asterisk/channels/chan_voter.c
ViewVC logotype

Contents of /projects/allstar/astsrc-1.4.23-pre/trunk/asterisk/channels/chan_voter.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1528 - (show annotations) (download) (as text)
Thu May 12 17:22:21 2016 UTC (12 months, 2 weeks ago) by jdixon
File MIME type: text/x-csrc
File size: 169058 byte(s)
Added DSP stuff to chan_pi and clean up other stuff 
1 /*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2011, Digium, Inc.
5 *
6 * Copyright (C) 2011-2013
7 * Jim Dixon, WB6NIL <jim@lambdatel.com>
8 *
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
14 *
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
18 */
19
20 /*! \file
21 *
22 * \brief Radio Voter channel driver for Asterisk
23 *
24 * \author Jim Dixon, WB6NIL <jim@lambdatel.com>
25 *
26 * \ingroup channel_drivers
27 */
28
29 /*** MODULEINFO
30 ***/
31
32 /* Basic Information On How This Works
33 Each node has a number of potential "clients" associated with it. In the voter.conf file, each stanza (category)
34 is named by the node number that the clients specified within the stanza are to be associated with. Each entry
35 consists of an arbitrary (realtively meaningless, just included for easy identification putposes within this
36 channel driver, and has nothing to do with its operation) identifier equated to a unique password. This password
37 is programmed into the client. All clients must have unique passwords, as that is what is used by this channel
38 driver to identify them.
39
40 Each channel instance (as opened by app_rpt as a main radio channel, e.g. rxchannel=Voter/1999 in rpt.conf) and
41 is directly associated with the node that opened it.
42
43 Each client has a pair of circular buffers, one for mu-law audio data, and one for RSSI value. The allocated buffer
44 length in all clients is determined by the 'buflen' parameter, which is specified in the "global" stanza in the
45 voter.conf file in milliseconds, and represnted in the channel driver as number of samples (actual buffer length,
46 which is 8 * milliseconds).
47
48 Every channel instance has a index ("drainindex"), indicating the next position within the physical buffer(s) where
49 the audio will be taken from the buffers and presented to the Asterisk channel stream as VOICE frames.
50
51 Therefore, there is an abstraction of a "buffer" that exists starting at drainindex and ending (modulo) at
52 drainindex - 1, with length of buflen.
53
54 Buflen is selected so that there is enough time (delay) for any straggling packets to arrive before it is time
55 to present the data to the Asterisk channel.
56
57 The idea is that the current audio being presented to Asterisk is from some time shortly in the past. Therefore,
58 "Now" is the position in the abstratcted buffer of 'bufdelay' (generally buflen - 160) (you gotta at least leave room for
59 an entire frame) and the data is being presented from the start of the abstracted buffer. As the physical buffer
60 moves along, what was once "now" will eventually become far enough in the "past" to be presented to Asterisk (gosh,
61 doesn't this sound like a scene from "Spaceballs"??.. I too always drink coffee while watching "Mr. Radar").
62
63 During the processing of an audio frame to be presented to Asterisk, all client's buffers that are associated with
64 a channel instance (node) are examined by taking an average of the RSSI value for each sample in the associated
65 time period (the first 160 samples of the abstracted buffer (which is the physical buffer from drainindex to
66 drainindex + 159) and whichever one, if any that has the largest RSSI average greather then zero is selected
67 as the audio source for that frame. The corresponding audio buffer's contents (in the corresponding offsets)
68 are presented to Asterisk, then ALL the clients corresponding RSSI data is set to 0, ALL the clients corresponding
69 audio is set to quiet (0x7f). The overwriting of the buffers after their use/examination is done so that the
70 next time those positions in the physical buffer are examined, they will not contain any data that was not actually
71 put there, since all client's buffers are significant regardless of whether they were populated or not. This
72 allows for the true 'connectionless-ness' of this protocol implementation.
73
74
75 Voter Channel test modes:
76
77 0 - Normal voting operation
78 1 - Randomly pick which client of all that
79 are receving at the max rssi value to use.
80 > 1 - Cycle thru all the clients that are receiving
81 at the max rssi value with a cycle time of (test mode - 1)
82 frames. In other words, if you set it to 2, it will
83 change every single time. If you set it to 11, it will
84 change every 10 times. This is serious torture test.
85
86 Note on ADPCM functionality:
87 The original intent was to change this driver to use signed linear internally,
88 but after some thought, it was determined that it was prudent to continue using
89 mulaw as the "standard" internal audio format (with the understanding of the slight
90 degradation in dynamic range when using ADPCM resulting in doing so). This was
91 done becuase existing external entities (such as the recording files and the streaming
92 stuff) use mulaw as their transport, and changing all of that to signed linear would
93 be cumbersome, inefficient and undesirable.
94
95 Note on "Dynamic" client functionality:
96 DONT USE IT!!. It is intentionally *NOT* documented to encourage non-use of this
97 feature. It is for demo purposes *ONLY*. The chan_voter driver will *NOT* properly
98 perform reliably in a production environment if this option is used.
99
100
101 Redundant "Proxy" Mode:
102
103 A "Redundant" (backup) server may be set up, so that if the "primary" server fails,
104 clients can detect this failure, and connect to the designated "backup" (or "secondary")
105 server.
106
107 Needless to say, since Internet connectivity is not by any means guaranteed to be consistent,
108 it is possible for some clients to have working connectivity to the "primary" server and not
109 others, even though the "primary" server is functional.
110
111 If this was to occur, actual voting and/or simulcast clients would have a "broken" system
112 (being that all the clients need to be on the same server for any sort of functional operation).
113
114 To eliminate this possibility, functionality has been added so that a "secondary" server
115 will "proxy" (forward) all of its VOTER packets to the "primary" (if the "primary" is
116 on line), and the "primary" will generate all of the outbound VOTER packets, which (for clients
117 "connected" to the "secondary" server) get sent to the "secondary" server to distribution to
118 its clients.
119
120 This allows for a "unity" of all of the clients on a network, even though they may be connected
121 to different servers.
122
123 In addition, it is assumed that "permanent linking" (at least of some sort) will be provided between
124 the channel side of the chan_voter instances (presumably through a "perma-link" provided by app_rpt).
125 When the "secondary" is "proxying" (to the "primary") it does not provide direct connectivity to/from
126 its locally-connected clients, thus allowing them to "connect" via the "primary" server instead. In
127 "normal" mode, it works "normally".
128
129 The operation is performed by more-or-less "encapsulating" the VOTER packets received by the "secondary"
130 server, and forwarding them on to the "primary" server, where they are "un-encapsulated" and appear to
131 that serer to be coming from clients connected directly to it (and keeps track of which ones are connected
132 in this manner, etc). When it needs to send VOTER packets to a client connected through the "secondary",
133 it "encapsulates" them, and sends them to the "secondary", where they get "un-enacpsulated" and sent
134 to their associated connected clients, based upon information in the "encapsulation".
135
136 If the "secondary" server loses (or does not make) connection to the "primary", it operates as normal, until
137 such time as it can make the connection.
138
139 The server redundancy feature is local to each chan_voter instance.
140
141 For each chan_voter instance served by both the "primary" and "secondary" servers, the client
142 list (parameters, etc) *MUST* be identical.
143
144 In addition, the following things must be added uniquely on each server:
145
146 In the "primary" server, there needs to be a "primary connectivity" client specified for each
147 "secondary" server for which it is "primary". Basicaly, this is a client that does NOTHING other
148 then providing a means by which the "secondary" can determine whether the "primary" is on line.
149 It is a stanard chan_voter client, with nothing else specified other then its password. Again,
150 although it is a "legitmate" client (technically), its only purpose *MUST* be to allow the secondary
151 server to connect to it.
152
153
154 The "primary" server also needs to have the following in all of its instances that require redundancy:
155
156 isprimary = y
157
158 The "secondary" server needs to have the following in all of its instances that require redundancy:
159
160 primary = 12.34.56.78:667,mypswd
161
162 (where 12.34.56.78:667 is the IPADDDR:PORT of the "primary" server, and mypswd is the password of the
163 "primary connectivity" client)
164
165 Note: Master timing sources *MUST* be local to their associated server, and therefore, can not be operated
166 in a redundant configuration. If a radio needs server redundancy, it CAN NOT be connected to a master timing
167 source. Also, the master timing source MUST be associated with a chan_voter instance that DOES NOT have
168 redundancy configured for it, even if a separate instance needs to be created just for this purpose.
169
170 Also, if Non-GPS-based operation is all that is needed, just the use of redundancy within the clients is
171 sufficient, and does not require any use of the server redundancy features.
172
173 "hostdeemp" (app_rpt duplex=3) mode:
174
175 As of Voter board firmware 1.19 (7/19/2013), there is a set of options in both the firmware ("Offline Menu item
176 #12, "DUPLEX3 support"), and the "hostdeemp" option (instance-wide) in the voter.conf file on the host.
177
178 Duplex mode 3 in app_rpt allows for "in-cabinet" repeat audio (where the actual radio hardware supplies the repeated
179 audio directly itself, and app_rpt simply "adds" all of the other audio as appropriate.
180
181 The Voter board (RTCM) now has an option to do the same functionality itself, for a case where local repeat audio
182 is desired without the "network audio delay" normally associated with Voter board (RTCM) operation, and for a radio
183 that doesnt have the option of providing "in cabinet" repeat audio (along with externally provided audio) itself.
184
185 Because of limitations with the Voter board (RTCM) hardware (being that there is only 1 audio path into the processor,
186 and it either has de-emphasis in its "hardware path" of not), it is necessary if you:
187
188 1) Wish to have the "duplex=3" functionality in app_rpt
189 2) Have the "DUPLEX3" support enabled in the Voter (RTCM) board
190 3) Have a transmitter that you are "modulating directly" (with flat audio)
191
192 If all of the above is true, then you need to use the "hostdeemp" option in chan voter, which basically "forces" the
193 RTCM *NOT* to do de-emphasis in hardware (it will send the non-de-emphasized audio to the host), and have the host
194 "do" the de-emphasis (in software) instead.
195
196 This will allow the Voter (RTCM) board to be able to "pass" the non-de-emphaszed audio back into the "direct modulation
197 audio" stream, since that is what will be "presented" to the processor in the Voter (RTCM) board, as the hardware de-emphasis
198 is disabled in this mode.
199
200 If you have a transmitter that you are "feeding" line-level (mic) audio, then this mode is not necessary, as the Voter (RTCM)
201 board is fully capable of providing the functionality all by itself.
202
203 Obviously, it is not valid to use *ANY* of the duplex=3 modes in a voted and/or simulcasted system.
204
205 */
206
207
208 #include "asterisk.h"
209 #include "../astver.h"
210
211 #include <stdio.h>
212 #include <string.h>
213 #include <sys/socket.h>
214 #include <sys/time.h>
215 #include <errno.h>
216 #include <unistd.h>
217 #include <stdlib.h>
218 #include <arpa/inet.h>
219 #include <fcntl.h>
220 #include <sys/ioctl.h>
221 #include <sys/timex.h>
222 #include <ctype.h>
223 #include <search.h>
224 #include <arpa/inet.h>
225 #include <netinet/in.h>
226 #include <netdb.h>
227 #include <pthread.h>
228 #include <signal.h>
229 #include <fnmatch.h>
230 #include <math.h>
231
232 #include "asterisk/lock.h"
233 #include "asterisk/channel.h"
234 #include "asterisk/config.h"
235 #include "asterisk/logger.h"
236 #include "asterisk/module.h"
237 #include "asterisk/pbx.h"
238 #include "asterisk/options.h"
239 #include "asterisk/utils.h"
240 #include "asterisk/app.h"
241 #include "asterisk/translate.h"
242 #include "asterisk/astdb.h"
243 #include "asterisk/cli.h"
244 #include "asterisk/ulaw.h"
245 #include "asterisk/dsp.h"
246 #include "asterisk/manager.h"
247
248
249 #include "pocsag.c"
250
251 /* Un-comment this if you wish Digital milliwatt output rather then real audio
252 when transmitting (for debugging only) */
253 /* #define DMWDIAG */
254
255 #ifdef NEW_ASTERISK
256 struct ast_flags zeroflag = { 0 };
257 #endif
258
259 #define XPMR_VOTER
260 #include "xpmr/xpmr.h"
261
262 #ifdef OLD_ASTERISK
263 #define AST_MODULE_LOAD_DECLINE -1
264 #endif
265
266 #define VOTER_CHALLENGE_LEN 10
267 #define VOTER_PASSWORD_LEN 30
268 #define VOTER_NAME_LEN 50
269
270 #define RX_TIMEOUT_MS 200
271 #define CLIENT_TIMEOUT_MS 3000
272 #define MASTER_TIMEOUT_MS 100
273 #define TX_KEEPALIVE_MS 1000
274 #define PING_TIME_MS 250
275 #define PING_TIMEOUT_MS 3000
276
277 #define DEFAULT_LINGER 6
278 #define DEFAULT_GTXGAIN "0.0"
279
280 #define DEFAULT_DYNTIME 30000
281
282 #define MAX_MASTER_COUNT 3
283
284 #define CLIENT_WARN_SECS 60
285
286 #define DELIMCHR ','
287 #define QUOTECHR 34
288
289 #define MAXSTREAMS 50
290 #define MAXTHRESHOLDS 20
291
292 #define GPS_WORK_FILE "/tmp/gps%s.tmp"
293 #define GPS_DATA_FILE "/tmp/gps%s.dat"
294
295 #define NTAPS_PL 6
296 #define NTAPS_4K 6
297
298 #ifdef DMWDIAG
299 unsigned char ulaw_digital_milliwatt[8] = { 0x1e, 0x0b, 0x0b, 0x1e, 0x9e, 0x8b, 0x8b, 0x9e };
300 unsigned char mwp;
301 #endif
302
303 #define IS_CLIENT_PROXY(x) (x->proxy_sin.sin_family == AF_INET)
304 #define SEND_PRIMARY(x) (x->primary.sin_family == AF_INET)
305
306 #define PAGER_SRC "PAGER"
307 #define ENDPAGE_STR "ENDPAGE"
308 #define AMPVAL 30000
309 #define SAMPRATE 8000 // (Sample Rate)
310 #define DIVLCM 192000 // (Least Common Mult of 512,1200,2400,8000)
311 #define PREAMBLE_BITS 576
312 #define MESSAGE_BITS 544 // (17 * 32), 1 longword SYNC plus 16 longwords data
313 // Apparently we have to send "inverted".. probably because of inverting AMP in Voter board
314 #define ONEVAL AMPVAL
315 #define ZEROVAL -AMPVAL
316 #define DIVSAMP (DIVLCM / SAMPRATE)
317
318 static const char vdesc[] = "radio Voter channel driver";
319 static char type[] = "voter";
320
321 int run_forever = 1;
322 static int nullfd = -1;
323
324 AST_MUTEX_DEFINE_STATIC(voter_lock);
325
326 int16_t listen_port = 667; /* port to listen to UDP packets on */
327 int udp_socket = -1;
328
329 int voter_timing_fd = -1;
330 int voter_timing_count = 0;
331 int last_master_count = 0;
332 int dyntime = DEFAULT_DYNTIME;
333
334 int check_client_sanity = 1;
335
336 char challenge[VOTER_CHALLENGE_LEN];
337 char password[VOTER_PASSWORD_LEN];
338 char context[100];
339
340 double dnsec;
341
342 static pthread_t voter_reader_thread = 0;
343 static pthread_t voter_timer_thread = 0;
344
345 int maxpvtorder = 0;
346
347 #define FRAME_SIZE 160
348 #define ADPCM_FRAME_SIZE 163
349
350 #define DEFAULT_BUFLEN 480 /* 480ms default buffer len */
351
352 #define BUFDELAY(p) (p->buflen - (FRAME_SIZE * 2))
353
354 #pragma pack(push)
355 #pragma pack(1)
356 typedef struct {
357 uint32_t vtime_sec;
358 uint32_t vtime_nsec;
359 } VTIME;
360
361 typedef struct {
362 VTIME curtime;
363 uint8_t challenge[10];
364 uint32_t digest;
365 uint16_t payload_type;
366 } VOTER_PACKET_HEADER;
367
368 typedef struct {
369 char lat[9];
370 char lon[10];
371 char elev[7];
372 } VOTER_GPS;
373
374 typedef struct {
375 char name[32];
376 uint8_t audio[FRAME_SIZE];
377 uint8_t rssi;
378 } VOTER_REC;
379
380 typedef struct {
381 VTIME curtime;
382 uint8_t audio[FRAME_SIZE];
383 char str[152];
384 } VOTER_STREAM;
385
386 typedef struct {
387 uint32_t ipaddr;
388 uint16_t port;
389 uint16_t payload_type;
390 uint8_t flags;
391 char challenge[VOTER_CHALLENGE_LEN];
392 } VOTER_PROXY_HEADER;
393
394 #pragma pack(pop)
395
396 #define VOTER_PAYLOAD_NONE 0
397 #define VOTER_PAYLOAD_ULAW 1
398 #define VOTER_PAYLOAD_GPS 2
399 #define VOTER_PAYLOAD_ADPCM 3
400 #define VOTER_PAYLOAD_NULAW 4
401 #define VOTER_PAYLOAD_PING 5
402 #define VOTER_PAYLOAD_PROXY 0xf000
403
404 struct voter_client {
405 uint32_t nodenum;
406 uint32_t digest;
407 char name[VOTER_NAME_LEN];
408 char pswd[VOTER_NAME_LEN];
409 uint8_t *audio;
410 uint8_t *rssi;
411 uint32_t respdigest;
412 struct sockaddr_in sin;
413 int drainindex;
414 int drainindex_40ms;
415 int buflen;
416 char heardfrom;
417 char totransmit;
418 char ismaster;
419 char curmaster;
420 char doadpcm;
421 char donulaw;
422 char mix;
423 char nodeemp;
424 char noplfilter;
425 char dynamic;
426 char txlockout;
427 struct voter_client *next;
428 uint8_t lastrssi;
429 int txseqno;
430 int txseqno_rxkeyed;
431 int rxseqno;
432 int rxseqno_40ms;
433 char rxseq40ms;
434 char drain40ms;
435 time_t warntime;
436 char *gpsid;
437 int reload;
438 int old_buflen;
439 struct timeval lastheardtime;
440 struct timeval lastdyntime;
441 struct timeval lastsenttime;
442 int prio;
443 int prio_override;
444 VTIME lastgpstime;
445 VTIME lastmastergpstime;
446 struct sockaddr_in proxy_sin;
447 char saved_challenge[VOTER_CHALLENGE_LEN];
448 short lastaudio[FRAME_SIZE];
449 struct timeval ping_txtime;
450 struct timeval ping_last_rxtime;
451 unsigned int ping_last_seqno;
452 int pings_requested;
453 int pings_sent;
454 int pings_received;
455 int pings_oos;
456 int pings_worst;
457 int pings_best;
458 unsigned int ping_seqno;
459 int pings_total_ms;
460 char ping_abort;
461 } ;
462
463 struct voter_pvt {
464 struct ast_channel *owner;
465 unsigned int nodenum; /* node # associated with instance */
466 struct voter_pvt *next;
467 struct ast_frame fr;
468 char buf[FRAME_SIZE + AST_FRIENDLY_OFFSET];
469 char txkey;
470 char rxkey;
471 struct ast_module_user *u;
472 struct timeval lastrxtime;
473 char drained_once;
474 int testcycle;
475 int testindex;
476 struct voter_client *lastwon;
477 char *streams[MAXSTREAMS];
478 int nstreams;
479 float hpx[NTAPS_PL + 1];
480 float hpy[NTAPS_PL + 1];
481 float rlpx[NTAPS_4K + 1];
482 float rlpy[NTAPS_4K + 1];
483 float tlpx[NTAPS_4K + 1];
484 float tlpy[NTAPS_4K + 1];
485 int32_t hdx;
486 char plfilter;
487 char hostdeemp;
488 int linger;
489 uint8_t rssi_thresh[MAXTHRESHOLDS];
490 uint16_t count_thresh[MAXTHRESHOLDS];
491 uint16_t linger_thresh[MAXTHRESHOLDS];
492 int nthresholds;
493 int threshold;
494 struct voter_client *winner;
495 uint16_t threshcount;
496 uint16_t lingercount;
497 struct ast_dsp *dsp;
498 struct ast_trans_pvt *adpcmin;
499 struct ast_trans_pvt *adpcmout;
500 struct ast_trans_pvt *nuin;
501 struct ast_trans_pvt *nuout;
502 struct ast_trans_pvt *toast;
503 struct ast_trans_pvt *toast1;
504 struct ast_trans_pvt *fromast;
505 t_pmr_chan *pmrChan;
506 char txctcssfreq[32];
507 int txctcsslevel;
508 int txctcsslevelset;
509 int txtoctype;
510 char duplex;
511 struct ast_frame *adpcmf1;
512 struct ast_frame *nulawf1;
513 ast_mutex_t xmit_lock;
514 ast_cond_t xmit_cond;
515 pthread_t xmit_thread;
516 int voter_test;
517 char usedtmf;
518 char isprimary;
519 char priconn;
520 struct sockaddr_in primary;
521 char primary_pswd[VOTER_NAME_LEN];
522 char primary_challenge[VOTER_CHALLENGE_LEN];
523 FILE *recfp;
524 short lastaudio[FRAME_SIZE];
525 char mixminus;
526 int order;
527 char waspager;
528 float gtxgain;
529
530 #ifdef OLD_ASTERISK
531 AST_LIST_HEAD(, ast_frame) txq;
532 #else
533 AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
534 #endif
535 #ifdef OLD_ASTERISK
536 AST_LIST_HEAD(, ast_frame) pagerq;
537 #else
538 AST_LIST_HEAD_NOLOCK(, ast_frame) pagerq;
539 #endif
540 ast_mutex_t txqlock;
541 ast_mutex_t pagerqlock;
542 };
543
544 #ifdef OLD_ASTERISK
545 int reload();
546 #else
547 static int reload(void);
548 #endif
549
550 #ifdef OLD_ASTERISK
551 static int usecnt;
552 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
553 #endif
554
555 int debug = 0;
556 int hasmaster = 0;
557
558 /* This is just a horrendous KLUDGE!! Some Garmin LVC-18 GPS "pucks"
559 *sometimes* get EXACTLY 1 second off!! Some dont do it at all.
560 Some do it constantly. Some just do it once in a while. In an attempt
561 to be at least somewhat tolerant of such swine poo-poo, the "puckit"
562 configuration flag may be set, which makes an attempt to deal with
563 this problem by keeping a "time differential" for each client (compared
564 with the "master") and applying it to time information within the protocol.
565 Obviously, this SHOULD NEVER HAVE TO BE DONE. */
566
567 int puckit = 0;
568
569 static char *config = "voter.conf";
570
571 struct voter_pvt *pvts = NULL;
572
573 struct voter_client *clients = NULL;
574
575 struct voter_client *dyn_clients = NULL;
576
577 FILE *fp;
578
579 VTIME master_time = {0,0};
580 VTIME mastergps_time = {0,0};
581
582 #ifdef OLD_ASTERISK
583 #define ast_free free
584 #define ast_malloc malloc
585 #endif
586
587 static struct ast_channel *voter_request(const char *type, int format, void *data, int *cause);
588 static int voter_call(struct ast_channel *ast, char *dest, int timeout);
589 static int voter_hangup(struct ast_channel *ast);
590 static struct ast_frame *voter_read(struct ast_channel *ast);
591 static int voter_write(struct ast_channel *ast, struct ast_frame *frame);
592 #ifdef OLD_ASTERISK
593 static int voter_indicate(struct ast_channel *ast, int cond);
594 static int voter_digit_end(struct ast_channel *c, char digit);
595 #else
596 static int voter_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen);
597 static int voter_digit_begin(struct ast_channel *c, char digit);
598 static int voter_digit_end(struct ast_channel *c, char digit, unsigned int duratiion);
599 #endif
600 static int voter_text(struct ast_channel *c, const char *text);
601 static int voter_setoption(struct ast_channel *chan, int option, void *data, int datalen);
602
603 static const struct ast_channel_tech voter_tech = {
604 .type = type,
605 .description = vdesc,
606 .capabilities = AST_FORMAT_SLINEAR,
607 .requester = voter_request,
608 .call = voter_call,
609 .hangup = voter_hangup,
610 .read = voter_read,
611 .write = voter_write,
612 .indicate = voter_indicate,
613 .send_text = voter_text,
614 #ifdef OLD_ASTERISK
615 .send_digit = voter_digit_end,
616 #else
617 .send_digit_begin = voter_digit_begin,
618 .send_digit_end = voter_digit_end,
619 .setoption = voter_setoption,
620
621 #endif
622 };
623
624 /*
625 * CLI extensions
626 */
627
628 /* Debug mode */
629 static int voter_do_debug(int fd, int argc, char *argv[]);
630
631 static char debug_usage[] =
632 "Usage: voter debug level {0-7}\n"
633 " Enables debug messages in chan_voter\n";
634
635
636 /* Test */
637 static int voter_do_test(int fd, int argc, char *argv[]);
638
639 static char test_usage[] =
640 "Usage: voter test instance_id [test value]\n"
641 " Specifies/Queries test mode for voter instance\n";
642
643
644 /* Prio */
645 static int voter_do_prio(int fd, int argc, char *argv[]);
646
647 static char prio_usage[] =
648 "Usage: voter prio instance_id [client_id] [priority value]\n"
649 " Specifies/Queries priority value for voter client\n";
650
651
652 /* Record */
653 static int voter_do_record(int fd, int argc, char *argv[]);
654
655 static char record_usage[] =
656 "Usage: voter record instance_id [record filename]\n"
657 " Enables/Specifies (or disables) recording file for chan_voter\n";
658
659 /* Tone */
660 static int voter_do_tone(int fd, int argc, char *argv[]);
661
662 static char tone_usage[] =
663 "Usage: voter tone instance_id [new_tone_level(0-250)]\n"
664 " Sets/Queries Tx CTCSS level for specified chan_voter instance\n";
665
666 /* Reload */
667 static int voter_do_reload(int fd, int argc, char *argv[]);
668
669 static char reload_usage[] =
670 "Usage: voter reload\n"
671 " Reload chan_voter parameters\n";
672
673 /* Display */
674 static int voter_do_display(int fd, int argc, char *argv[]);
675
676 static char display_usage[] =
677 "Usage: voter display [instance]\n"
678 " Display voter instance clients\n";
679
680 /* Txlockout */
681 static int voter_do_txlockout(int fd, int argc, char *argv[]);
682
683 static char txlockout_usage[] =
684 "Usage: voter txlockout [instance] <client_list>\n"
685 " Set Tx Lockout for voter instance clients\n";
686
687 /* Ping client */
688 static int voter_do_ping(int fd, int argc, char *argv[]);
689
690 static char ping_usage[] =
691 "Usage: voter ping [client] <# pings, 0 to abort>\n"
692 " Ping (check connectivity) to client\n";
693
694 #ifndef NEW_ASTERISK
695
696 static struct ast_cli_entry cli_debug =
697 { { "voter", "debug", "level" }, voter_do_debug,
698 "Enable voter debugging", debug_usage };
699 static struct ast_cli_entry cli_test =
700 { { "voter", "test" }, voter_do_test,
701 "Specify/Query voter instance test mode", test_usage };
702 static struct ast_cli_entry cli_prio =
703 { { "voter", "prio" }, voter_do_prio,
704 "Specify/Query voter client priority value", prio_usage };
705 static struct ast_cli_entry cli_record =
706 { { "voter", "record" }, voter_do_record,
707 "Enables/Specifies (or disables) voter recording file", record_usage };
708 static struct ast_cli_entry cli_tone =
709 { { "voter", "tone" }, voter_do_tone,
710 "Sets/Queries Tx CTCSS level for specified chan_voter instance", tone_usage };
711 static struct ast_cli_entry cli_reload =
712 { { "voter", "reload" }, voter_do_reload,
713 "Reloads chan_voter parameters", reload_usage };
714 static struct ast_cli_entry cli_display =
715 { { "voter", "display" }, voter_do_display,
716 "Display voter (instance) clients", display_usage };
717 static struct ast_cli_entry cli_txlockout =
718 { { "voter", "txlockout" }, voter_do_txlockout,
719 "Set Tx Lockout status for voter (instance) clients", txlockout_usage };
720 static struct ast_cli_entry cli_ping =
721 { { "voter", "ping" }, voter_do_ping,
722 "Ping (check connectivity) to client", ping_usage };
723 #endif
724
725 static uint32_t crc_32_tab[] = { /* CRC polynomial 0xedb88320 */
726 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
727 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
728 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
729 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
730 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
731 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
732 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
733 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
734 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
735 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
736 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
737 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
738 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
739 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
740 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
741 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
742 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
743 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
744 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
745 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
746 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
747 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
748 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
749 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
750 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
751 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
752 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
753 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
754 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
755 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
756 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
757 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
758 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
759 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
760 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
761 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
762 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
763 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
764 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
765 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
766 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
767 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
768 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
769 };
770
771 static int32_t crc32_bufs(char *buf, char *buf1)
772 {
773 int32_t oldcrc32;
774
775 oldcrc32 = 0xFFFFFFFF;
776 while(buf && *buf)
777 {
778 oldcrc32 = crc_32_tab[(oldcrc32 ^ *buf++) & 0xff] ^ ((uint32_t)oldcrc32 >> 8);
779 }
780 while(buf1 && *buf1)
781 {
782 oldcrc32 = crc_32_tab[(oldcrc32 ^ *buf1++) & 0xff] ^ ((uint32_t)oldcrc32 >> 8);
783 }
784 return ~oldcrc32;
785 }
786
787 /* IIR 6 pole High pass filter, 300 Hz corner with 0.5 db ripple */
788
789 #define GAIN1 1.745882764e+00
790
791 static int16_t hpass6(int16_t input,float *xv,float *yv)
792 {
793 xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6];
794 xv[6] = ((float)input) / GAIN1;
795 yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6];
796 yv[6] = (xv[0] + xv[6]) - 6 * (xv[1] + xv[5]) + 15 * (xv[2] + xv[4])
797 - 20 * xv[3]
798 + ( -0.3491861578 * yv[0]) + ( 2.3932556573 * yv[1])
799 + ( -6.9905126572 * yv[2]) + ( 11.0685981760 * yv[3])
800 + ( -9.9896695552 * yv[4]) + ( 4.8664511065 * yv[5]);
801 return((int)yv[6]);
802 }
803
804 /* IIR 6 pole Low pass filter, 1900 Hz corner with 0.5 db ripple */
805
806 #define GAIN2 1.080715413e+02
807
808 static int16_t lpass4(int16_t input,float *xv,float *yv)
809 {
810 xv[0] = xv[1]; xv[1] = xv[2]; xv[2] = xv[3]; xv[3] = xv[4]; xv[4] = xv[5]; xv[5] = xv[6];
811 xv[6] = ((float)input) / GAIN2;
812 yv[0] = yv[1]; yv[1] = yv[2]; yv[2] = yv[3]; yv[3] = yv[4]; yv[4] = yv[5]; yv[5] = yv[6];
813 yv[6] = (xv[0] + xv[6]) + 6 * (xv[1] + xv[5]) + 15 * (xv[2] + xv[4])
814 + 20 * xv[3]
815 + ( -0.1802140297 * yv[0]) + ( 0.7084527003 * yv[1])
816 + ( -1.5847014566 * yv[2]) + ( 2.3188475168 * yv[3])
817 + ( -2.5392334760 * yv[4]) + ( 1.6846484378 * yv[5]);
818 return((int)yv[6]);
819 }
820
821 /* FIR integrator providing de-emphasis @ 8000 samples/sec */
822
823 static int16_t deemp1(int16_t input, int32_t *state0)
824 {
825
826 int32_t accum;
827 int16_t output;
828
829 accum = input;
830 *state0 = accum + (*state0 * 25889) / M_Q15;
831 accum = (*state0 * 6878) / (M_Q15 / 4);
832 output = accum;
833 return(output);
834 }
835
836
837 /*
838 * Break up a delimited string into a table of substrings
839 *
840 * str - delimited string ( will be modified )
841 * strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
842 * limit- maximum number of substrings to process
843 */
844
845 static int finddelim(char *str, char *strp[], int limit)
846 {
847 int i,l,inquo;
848
849 inquo = 0;
850 i = 0;
851 strp[i++] = str;
852 if (!*str)
853 {
854 strp[0] = 0;
855 return(0);
856 }
857 for(l = 0; *str && (l < limit) ; str++)
858 {
859 if (*str == QUOTECHR)
860 {
861 if (inquo)
862 {
863 *str = 0;
864 inquo = 0;
865 }
866 else
867 {
868 strp[i - 1] = str + 1;
869 inquo = 1;
870 }
871 }
872 if ((*str == DELIMCHR) && (!inquo))
873 {
874 *str = 0;
875 l++;
876 strp[i++] = str + 1;
877 }
878 }
879 strp[i] = 0;
880 return(i);
881
882 }
883
884 static unsigned int voter_tvdiff_ms(struct timeval x, struct timeval y)
885 {
886 int i;
887
888 i = ast_tvdiff_ms(x,y);
889 if (i < 0) i = INT32_MAX;
890 return(i);
891 }
892
893
894 /* return offsetted time */
895 static long long puckoffset(struct voter_client *client)
896 {
897 long long btime,ptime,difftime;
898
899 if (!puckit) return 0;
900 btime = ((long long)client->lastmastergpstime.vtime_sec * 1000000000LL) + client->lastmastergpstime.vtime_nsec;
901 ptime = ((long long)client->lastgpstime.vtime_sec * 1000000000LL) + client->lastgpstime.vtime_nsec;
902 difftime = ptime - btime;
903 return difftime;
904 }
905
906 static void mkpucked(struct voter_client *client,VTIME *dst)
907 {
908 long long btime;
909
910 btime = ((long long)master_time.vtime_sec * 1000000000LL) + master_time.vtime_nsec;
911 btime += puckoffset(client);
912 dst->vtime_nsec = htonl((long)(btime % 1000000000LL));
913 dst->vtime_sec = htonl((long)(btime / 1000000000LL));
914 return;
915 }
916
917 /* must be called with voter_lock locked */
918 static void incr_drainindex(struct voter_pvt *p)
919 {
920 struct voter_client *client;
921
922 if (p == NULL) return;
923 for(client = clients; client; client = client->next)
924 {
925 if (client->nodenum != p->nodenum) continue;
926 if (!client->drain40ms)
927 {
928 client->drainindex_40ms = client->drainindex;
929 client->rxseqno_40ms = client->rxseqno;
930 }
931 client->drainindex += FRAME_SIZE;
932 if (client->drainindex >= client->buflen) client->drainindex -= client->buflen;
933 client->drain40ms = !client->drain40ms;
934 }
935 }
936
937 static int voter_call(struct ast_channel *ast, char *dest, int timeout)
938 {
939 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
940 ast_log(LOG_WARNING, "voter_call called on %s, neither down nor reserved\n", ast->name);
941 return -1;
942 }
943 /* When we call, it just works, really, there's no destination... Just
944 ring the phone and wait for someone to answer */
945 if (option_debug)
946 ast_log(LOG_DEBUG, "Calling %s on %s\n", dest, ast->name);
947 ast_setstate(ast,AST_STATE_UP);
948 return 0;
949 }
950
951 static int voter_hangup(struct ast_channel *ast)
952 {
953 struct voter_pvt *p = ast->tech_pvt,*q;
954
955 if (option_debug)
956 ast_log(LOG_DEBUG, "voter_hangup(%s)\n", ast->name);
957 if (!ast->tech_pvt) {
958 ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
959 return 0;
960 }
961 if (p->dsp) ast_dsp_free(p->dsp);
962 if (p->adpcmin) ast_translator_free_path(p->adpcmin);
963 if (p->adpcmout) ast_translator_free_path(p->adpcmout);
964 if (p->toast) ast_translator_free_path(p->toast);
965 if (p->toast) ast_translator_free_path(p->toast1);
966 if (p->fromast) ast_translator_free_path(p->fromast);
967 if (p->nuin) ast_translator_free_path(p->nuin);
968 if (p->nuout) ast_translator_free_path(p->nuout);
969 ast_mutex_lock(&voter_lock);
970 for(q = pvts; q->next; q = q->next)
971 {
972 if (q->next == p) break;
973 }
974 if (q->next) q->next = p->next;
975 if (pvts == p) pvts = p->next;
976 ast_mutex_unlock(&voter_lock);
977 ast_free(p);
978 ast->tech_pvt = NULL;
979 ast_setstate(ast, AST_STATE_DOWN);
980 return 0;
981 }
982
983 #ifdef OLD_ASTERISK
984 static int voter_indicate(struct ast_channel *ast, int cond)
985 #else
986 static int voter_indicate(struct ast_channel *ast, int cond, const void *data, size_t datalen)
987 #endif
988 {
989 struct voter_pvt *p = ast->tech_pvt;
990
991 switch (cond) {
992 case AST_CONTROL_RADIO_KEY:
993 p->txkey = 1;
994 break;
995 case AST_CONTROL_RADIO_UNKEY:
996 p->txkey = 0;
997 break;
998 case AST_CONTROL_HANGUP:
999 return -1;
1000 default:
1001 return 0;
1002 }
1003
1004 return 0;
1005 }
1006
1007 #ifndef OLD_ASTERISK
1008
1009 static int voter_digit_begin(struct ast_channel *ast, char digit)
1010 {
1011 return -1;
1012 }
1013
1014 #endif
1015
1016 #ifdef OLD_ASTERISK
1017 static int voter_digit_end(struct ast_channel *ast, char digit)
1018 #else
1019 static int voter_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
1020 #endif
1021 {
1022 return(0);
1023 }
1024
1025 static int voter_setoption(struct ast_channel *chan, int option, void *data, int datalen)
1026 {
1027 char *cp;
1028 struct voter_pvt *o = chan->tech_pvt;
1029
1030 /* all supported options require data */
1031 if (!data || (datalen < 1)) {
1032 errno = EINVAL;
1033 return -1;
1034 }
1035
1036 switch (option) {
1037 case AST_OPTION_TONE_VERIFY:
1038 cp = (char *) data;
1039 switch (*cp) {
1040 case 1:
1041 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
1042 o->usedtmf = 1;
1043 break;
1044 case 2:
1045 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
1046 o->usedtmf = 1;
1047 break;
1048 case 3:
1049 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: DISABLE DETECT(3) on %s\n",chan->name);
1050 o->usedtmf = 0;
1051 break;
1052 default:
1053 ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
1054 o->usedtmf = 1;
1055 break;
1056 }
1057 break;
1058 }
1059 errno = 0;
1060 return 0;
1061 }
1062
1063 static void mkpsamples(short *audio,uint32_t x, int *audio_ptr, int *divcnt, int divdiv)
1064 {
1065 int i;
1066
1067 for(i = 31; i >= 0; i--)
1068 {
1069 while(*divcnt < divdiv)
1070 {
1071 audio[(*audio_ptr)++] = (x & (1 << i)) ? ONEVAL : ZEROVAL;
1072 *divcnt += DIVSAMP;
1073 }
1074 if (*divcnt >= divdiv) *divcnt -= divdiv;
1075 }
1076 }
1077
1078 static int voter_text(struct ast_channel *ast, const char *text)
1079 {
1080 struct voter_pvt *o = ast->tech_pvt;
1081 int cnt,i,j,audio_samples,divcnt,divdiv,audio_ptr,baud;
1082 struct pocsag_batch *batch,*b;
1083 short *audio;
1084 char *cmd,audio1[AST_FRIENDLY_OFFSET + (FRAME_SIZE * sizeof(short))];
1085 struct ast_frame wf,*f1;
1086
1087 cmd = alloca(strlen(text) + 10);
1088
1089 /* print received messages */
1090 if (debug > 3) ast_verbose(" << Console Received simpleusb text %s >> \n", text);
1091
1092 if (!strncmp(text,"PAGE",4))
1093 {
1094 if (!o->pmrChan)
1095 {
1096 ast_log(LOG_WARNING,"Attempt to page on a non-flat-audio Voter config (%s)\n",ast->name);
1097 return 0;
1098 }
1099 cnt = sscanf(text,"%s %d %d %n",cmd,&baud,&i,&j);
1100 if (cnt < 3) return 0;
1101 if (strlen(text + j) < 1) return 0;
1102 switch(text[j])
1103 {
1104 case 'T': /* Tone only */
1105 if (option_verbose > 2)
1106 ast_verbose(VERBOSE_PREFIX_3 "POCSAG page (%d baud, capcode=%d) TONE ONLY\n",baud,i);
1107 batch = make_pocsag_batch(i, NULL, 0, TONE, 0);
1108 break;
1109 case 'N': /* Numeric */
1110 if (!text[j + 1]) return 0;
1111 if (option_verbose > 2)
1112 ast_verbose(VERBOSE_PREFIX_3 "POCSAG page (%d baud, capcode=%d) NUMERIC (%s)\n",baud,i,text + j + 1);
1113 batch = make_pocsag_batch(i, (char *)text + j + 1, strlen(text + j + 1), NUMERIC, 0);
1114 break;
1115 case 'A': /* Alpha */
1116 if (!text[j + 1]) return 0;
1117 if (option_verbose > 2)
1118 ast_verbose(VERBOSE_PREFIX_3 "POCSAG page (%d baud, capcode=%d) ALPHA (%s)\n",baud,i,text + j + 1);
1119 batch = make_pocsag_batch(i, (char *)text + j + 1, strlen(text + j + 1), ALPHA, 0);
1120 break;
1121 case '?': /* Query Page Status */
1122 i = 0;
1123 ast_mutex_lock(&o->txqlock);
1124 AST_LIST_TRAVERSE(&o->txq, f1,frame_list) if (f1->src && (!strcmp(f1->src,PAGER_SRC))) i++;
1125 ast_mutex_unlock(&o->txqlock);
1126 cmd = (i) ? "PAGES" : "NOPAGES" ;
1127 memset(&wf,0,sizeof(wf));
1128 wf.frametype = AST_FRAME_TEXT;
1129 wf.datalen = strlen(cmd);
1130 AST_FRAME_DATA(wf) = cmd;
1131 ast_queue_frame(o->owner, &wf);
1132 return 0;
1133 default:
1134 return 0;
1135 }
1136 if (!batch)
1137 {
1138 ast_log(LOG_ERROR,"Error creating POCSAG page!!\n");
1139 return 0;
1140 }
1141 b = batch;
1142 for(i = 0; b; b = b->next) i++;
1143 /* get number of samples to alloc for audio */
1144 audio_samples = (SAMPRATE * (PREAMBLE_BITS + (MESSAGE_BITS * i))) / baud;
1145 /* pad end with 250ms of silence on each side */
1146 audio_samples += SAMPRATE / 2;
1147 /* also pad up to FRAME_SIZE */
1148 audio_samples += audio_samples % FRAME_SIZE;
1149 audio = malloc((audio_samples * sizeof(short)) + 10);
1150 if (!audio)
1151 {
1152 free_batch(batch);
1153 ast_log(LOG_ERROR,"Cant malloc() for audio buffer!!\n");
1154 return 0;
1155 }
1156 memset(audio,0,audio_samples * sizeof(short));
1157 divdiv = DIVLCM / baud;
1158 divcnt = 0;
1159 audio_ptr = SAMPRATE / 4;
1160 for(i = 0; i < (PREAMBLE_BITS / 32); i++)
1161 mkpsamples(audio,0xaaaaaaaa,&audio_ptr,&divcnt,divdiv);
1162 b = batch;
1163 while (b)
1164 {
1165 mkpsamples(audio,b->sc,&audio_ptr,&divcnt,divdiv);
1166 for(j = 0; j < 8; j++)
1167 {
1168 for(i = 0; i < 2; i++)
1169 {
1170 mkpsamples(audio,b->frame[j][i],&audio_ptr,&divcnt,divdiv);
1171 }
1172 }
1173 b = b->next;
1174 }
1175 free_batch(batch);
1176 memset(audio1,0,sizeof(audio1));
1177 for(i = 0; i < audio_samples; i += FRAME_SIZE)
1178 {
1179 memset(&wf,0,sizeof(wf));
1180 wf.frametype = AST_FRAME_VOICE;
1181 wf.subclass = AST_FORMAT_SLINEAR;
1182 wf.samples = FRAME_SIZE;
1183 wf.datalen = FRAME_SIZE * 2;
1184 wf.offset = AST_FRIENDLY_OFFSET;
1185 AST_FRAME_DATA(wf) = audio1 + AST_FRIENDLY_OFFSET;
1186 wf.src = PAGER_SRC;
1187 memcpy(AST_FRAME_DATA(wf),(char *)(audio + i),FRAME_SIZE * 2);
1188 f1 = ast_frdup(&wf);
1189 memset(&f1->frame_list,0,sizeof(f1->frame_list));
1190 ast_mutex_lock(&o->pagerqlock);
1191 AST_LIST_INSERT_TAIL(&o->pagerq,f1,frame_list);
1192 ast_mutex_unlock(&o->pagerqlock);
1193 }
1194 free(audio);
1195 return 0;
1196 }
1197
1198 return 0;
1199 }
1200
1201
1202 static struct ast_frame *voter_read(struct ast_channel *ast)
1203 {
1204 struct voter_pvt *p = ast->tech_pvt;
1205
1206 memset(&p->fr,0,sizeof(struct ast_frame));
1207 p->fr.frametype = AST_FRAME_NULL;
1208 return &p->fr;
1209 }
1210
1211 static int voter_write(struct ast_channel *ast, struct ast_frame *frame)
1212 {
1213 struct voter_pvt *p = ast->tech_pvt;
1214 struct ast_frame *f1;
1215
1216 if (frame->frametype != AST_FRAME_VOICE) return 0;
1217
1218 if (!p->txkey) return 0;
1219
1220 if (hasmaster && (!master_time.vtime_sec))
1221 {
1222 ast_mutex_lock(&p->txqlock);
1223 while((f1 = AST_LIST_REMOVE_HEAD(&p->txq,frame_list)) != NULL) ast_frfree(f1);
1224 ast_mutex_unlock(&p->txqlock);
1225 return 0;
1226 }
1227
1228 if (fp != NULL) fwrite(AST_FRAME_DATAP(frame),1,frame->datalen,fp);
1229 f1 = ast_frdup(frame);
1230 if (p->gtxgain != 1.0)
1231 {
1232 int x1;
1233 short *sp;
1234 float fsamp;
1235
1236 sp = (short *) AST_FRAME_DATAP(f1);
1237 for(x1 = 0; x1 < f1->datalen / 2; x1++)
1238 {
1239 fsamp = (float) sp[x1] * p->gtxgain;
1240 if (fsamp > 32765.0) fsamp = 32765.0;
1241 if (fsamp < -32765.0) fsamp = -32765.0;
1242 sp[x1] = (int) fsamp;
1243 }
1244 }
1245 memset(&f1->frame_list,0,sizeof(f1->frame_list));
1246 ast_mutex_lock(&p->txqlock);
1247 AST_LIST_INSERT_TAIL(&p->txq,f1,frame_list);
1248 ast_mutex_unlock(&p->txqlock);
1249
1250 return 0;
1251 }
1252
1253 static struct ast_frame *ast_frcat(struct ast_frame *f1, struct ast_frame *f2)
1254 {
1255
1256 struct ast_frame *f;
1257 char *cp;
1258 int len;
1259
1260 if ((f1->subclass != f2->subclass) || (f1->frametype != f2->frametype))
1261 {
1262 ast_log(LOG_ERROR,"ast_frcat() called with non-matching frame types!!\n");
1263 return NULL;
1264 }
1265 f = (struct ast_frame *)ast_malloc(sizeof(struct ast_frame));
1266 if (!f)
1267 {
1268 ast_log(LOG_ERROR,"Cant malloc()\n");
1269 return NULL;
1270 }
1271 memset(f,0,sizeof(struct ast_frame));
1272 len = f1->datalen + f2->datalen + AST_FRIENDLY_OFFSET;
1273 cp = malloc(len);
1274 if (!cp)
1275 {
1276 ast_log(LOG_ERROR,"Cant malloc()\n");
1277 return NULL;
1278 }
1279 memcpy(cp + AST_FRIENDLY_OFFSET,AST_FRAME_DATAP(f1),f1->datalen);
1280 memcpy(cp + AST_FRIENDLY_OFFSET + f1->datalen,AST_FRAME_DATAP(f2),f2->datalen);
1281 f->frametype = f1->frametype;
1282 f->subclass = f1->subclass;
1283 f->datalen = f1->datalen + f2->datalen;
1284 f->samples = f1->samples + f2->samples;
1285 AST_FRAME_DATAP(f) = cp + AST_FRIENDLY_OFFSET;;
1286 f->mallocd = AST_MALLOCD_HDR | AST_MALLOCD_DATA;
1287 f->src = "ast_frcat";
1288 f->offset = AST_FRIENDLY_OFFSET;
1289 return(f);
1290 }
1291
1292
1293 /* must be called with voter_lock locked */
1294 static int voter_mix_and_send(struct voter_pvt *p, struct voter_client *maxclient, int maxrssi)
1295 {
1296
1297 int i,j,k,x,maxprio,haslastaudio;
1298 struct ast_frame fr,*f1,*f2;
1299 struct voter_client *client;
1300 short silbuf[FRAME_SIZE];
1301
1302
1303 haslastaudio = 0;
1304 memset(&fr,0,sizeof(struct ast_frame));
1305 fr.frametype = AST_FRAME_VOICE;
1306 fr.subclass = AST_FORMAT_ULAW;
1307 fr.datalen = FRAME_SIZE;
1308 fr.samples = FRAME_SIZE;
1309 AST_FRAME_DATA(fr) = p->buf + AST_FRIENDLY_OFFSET;
1310 fr.src = type;
1311 fr.offset = AST_FRIENDLY_OFFSET;
1312 fr.mallocd = 0;
1313 fr.delivery.tv_sec = 0;
1314 fr.delivery.tv_usec = 0;
1315 f1 = ast_translate(p->toast,&fr,0);
1316 if (!f1)
1317 {
1318 ast_log(LOG_ERROR,"Can not translate frame to send to Asterisk\n");
1319 return(0);
1320 }
1321 maxprio = 0;
1322 for(client = clients; client; client = client->next)
1323 {
1324 if (client->nodenum != p->nodenum) continue;
1325 if (!client->mix) continue;
1326 if (client->prio_override == -1) continue;
1327 if (client->prio_override > -2)
1328 i = client->prio_override;
1329 else
1330 i = client->prio;
1331 if (i > maxprio) maxprio = i;
1332 }
1333 /* f1 now contains the voted-upon audio in slinear */
1334 for(client = clients; client; client = client->next)
1335 {
1336 short *sp1,*sp2;
1337 if (client->nodenum != p->nodenum) continue;
1338 if (!client->mix) continue;
1339 if (client->prio_override == -1) continue;
1340 if (maxprio)
1341 {
1342 if (client->prio_override > -2)
1343 i = client->prio_override;
1344 else
1345 i = client->prio;
1346 if (i < maxprio) continue;
1347 }
1348 i = (int)client->buflen - ((int)client->drainindex + FRAME_SIZE);
1349 if (i >= 0)
1350 {
1351 memcpy(p->buf + AST_FRIENDLY_OFFSET,client->audio + client->drainindex,FRAME_SIZE);
1352 }
1353 else
1354 {
1355 memcpy(p->buf + AST_FRIENDLY_OFFSET,client->audio + client->drainindex,FRAME_SIZE + i);
1356 memcpy(p->buf + AST_FRIENDLY_OFFSET + (client->buflen - i),client->audio,-i);
1357 }
1358 if (i >= 0)
1359 {
1360 memset(client->audio + client->drainindex,0xff,FRAME_SIZE);
1361 }
1362 else
1363 {
1364 memset(client->audio + client->drainindex,0xff,FRAME_SIZE + i);
1365 memset(client->audio,0xff,-i);
1366 }
1367 k = 0;
1368 if (i >= 0)
1369 {
1370 for(j = client->drainindex; j < client->drainindex + FRAME_SIZE; j++)
1371 {
1372 k += client->rssi[j];
1373 client->rssi[j] = 0;
1374 }
1375 }
1376 else
1377 {
1378 for(j = client->drainindex; j < client->drainindex + (FRAME_SIZE + i); j++)
1379 {
1380 k += client->rssi[j];
1381 client->rssi[j] = 0;
1382 }
1383 for(j = 0; j < -i; j++)
1384 {
1385 k += client->rssi[j];
1386 client->rssi[j] = 0;
1387 }
1388 }
1389 client->lastrssi = k / FRAME_SIZE;
1390 if (client->lastrssi > maxrssi)
1391 {
1392 maxrssi = client->lastrssi;
1393 maxclient = client;
1394 }
1395 memset(&fr,0,sizeof(struct ast_frame));
1396 fr.frametype = AST_FRAME_VOICE;
1397 fr.subclass = AST_FORMAT_ULAW;
1398 fr.datalen = FRAME_SIZE;
1399 fr.samples = FRAME_SIZE;
1400 AST_FRAME_DATA(fr) = p->buf + AST_FRIENDLY_OFFSET;
1401 fr.src = type;
1402 fr.offset = AST_FRIENDLY_OFFSET;
1403 fr.mallocd = 0;
1404 fr.delivery.tv_sec = 0;
1405 fr.delivery.tv_usec = 0;
1406 f2 = ast_translate(p->toast1,&fr,0);
1407 if (!f2)
1408 {
1409 ast_log(LOG_ERROR,"Can not translate frame to send to Asterisk\n");
1410 return(0);
1411 }
1412 sp1 = AST_FRAME_DATAP(f1);
1413 sp2 = AST_FRAME_DATAP(f2);
1414 if (!haslastaudio)
1415 {
1416 memcpy(p->lastaudio,sp1,FRAME_SIZE * 2);
1417 haslastaudio = 1;
1418 }
1419 memcpy(client->lastaudio,sp2,FRAME_SIZE * 2);
1420 for(i = 0; i < FRAME_SIZE; i++)
1421 {
1422 if (maxprio && client->lastrssi)
1423 j = sp2[i];
1424 else
1425 j = sp1[i] + sp2[i];
1426 if (j > 32767) j = 32767;
1427 if (j < -32767) j = -32767;
1428 sp1[i] = j;
1429 }
1430 ast_frfree(f2);
1431 }
1432 if (p->priconn) maxclient = NULL;
1433 if (!maxclient) /* if nothing there */
1434 {
1435 if (p->rxkey && p->dsp && p->usedtmf)
1436 {
1437 memset(silbuf,0,sizeof(silbuf));
1438 memset(&fr,0,sizeof(struct ast_frame));
1439 fr.frametype = AST_FRAME_VOICE;
1440 fr.subclass = AST_FORMAT_SLINEAR;
1441 fr.datalen = FRAME_SIZE * 2;
1442 fr.samples = FRAME_SIZE;
1443 AST_FRAME_DATA(fr) = silbuf;
1444 fr.src = type;
1445 fr.offset = 0;
1446 fr.mallocd = 0;
1447 fr.delivery.tv_sec = 0;
1448 fr.delivery.tv_usec = 0;
1449 f2 = ast_dsp_process(NULL,p->dsp,&fr);
1450 #ifdef OLD_ASTERISK
1451 if (f2->frametype == AST_FRAME_DTMF)
1452 #else
1453 if ((f2->frametype == AST_FRAME_DTMF_END) ||
1454 (f2->frametype == AST_FRAME_DTMF_BEGIN))
1455 #endif
1456 {
1457 if ((f2->subclass != 'm') && (f2->subclass != 'u'))
1458 {
1459 #ifndef OLD_ASTERISK
1460 if (f2->frametype == AST_FRAME_DTMF_END)
1461 #endif
1462 ast_log(LOG_NOTICE,"Voter %d Got DTMF char %c\n",p->nodenum,f2->subclass);
1463 }
1464 else
1465 {
1466 f2->frametype = AST_FRAME_NULL;
1467 f2->subclass = 0;
1468 }
1469 ast_queue_frame(p->owner,f2);
1470 gettimeofday(&p->lastrxtime,NULL);
1471 }
1472 }
1473 memset(silbuf,0,sizeof(silbuf));
1474 memset(&fr,0,sizeof(struct ast_frame));
1475 fr.frametype = AST_FRAME_VOICE;
1476 fr.subclass = AST_FORMAT_SLINEAR;
1477 fr.datalen = FRAME_SIZE * 2;
1478 fr.samples = FRAME_SIZE;
1479 AST_FRAME_DATA(fr) = silbuf;
1480 fr.src = type;
1481 fr.offset = 0;
1482 fr.mallocd = 0;
1483 fr.delivery.tv_sec = 0;
1484 fr.delivery.tv_usec = 0;
1485 p->threshold = 0;
1486 p->threshcount = 0;
1487 p->lingercount = 0;
1488 p->winner = 0;
1489 incr_drainindex(p);
1490 ast_queue_frame(p->owner,&fr);
1491 return(0);
1492 }
1493 p->winner = maxclient;
1494 incr_drainindex(p);
1495 gettimeofday(&p->lastrxtime,NULL);
1496 if (!p->rxkey)
1497 {
1498 memset(&fr,0,sizeof(fr));
1499 fr.datalen = 0;
1500 fr.samples = 0;
1501 fr.frametype = AST_FRAME_CONTROL;
1502 fr.subclass = AST_CONTROL_RADIO_KEY;
1503 AST_FRAME_DATA(fr) = 0;
1504 fr.src = type;
1505 fr.offset = 0;
1506 fr.mallocd=0;
1507 fr.delivery.tv_sec = 0;
1508 fr.delivery.tv_usec = 0;
1509 ast_queue_frame(p->owner,&fr);
1510 }
1511 p->rxkey = 1;
1512 x = 0;
1513 if (p->dsp && p->usedtmf)
1514 {
1515 f2 = ast_dsp_process(NULL,p->dsp,f1);
1516 #ifdef OLD_ASTERISK
1517 if (f2->frametype == AST_FRAME_DTMF)
1518 #else
1519 if ((f2->frametype == AST_FRAME_DTMF_END) ||
1520 (f2->frametype == AST_FRAME_DTMF_BEGIN))
1521 #endif
1522 {
1523 if ((f2->subclass != 'm') && (f2->subclass != 'u'))
1524 {
1525 #ifndef OLD_ASTERISK
1526 if (f2->frametype == AST_FRAME_DTMF_END)
1527 #endif
1528 ast_log(LOG_NOTICE,"Voter %d Got DTMF char %c\n",p->nodenum,f2->subclass);
1529 }
1530 else
1531 {
1532 f2->frametype = AST_FRAME_NULL;
1533 f2->subclass = 0;
1534 }
1535 ast_queue_frame(p->owner,f2);
1536 x = 1;
1537 }
1538 }
1539 if (!x) ast_queue_frame(p->owner,f1);
1540 else
1541 {
1542 memset(silbuf,0,sizeof(silbuf));
1543 memset(&fr,0,sizeof(struct ast_frame));
1544 fr.frametype = AST_FRAME_VOICE;
1545 fr.subclass = AST_FORMAT_SLINEAR;
1546 fr.datalen = FRAME_SIZE * 2;
1547 fr.samples = FRAME_SIZE;
1548 AST_FRAME_DATA(fr) = silbuf;
1549 fr.src = type;
1550 fr.offset = 0;
1551 fr.mallocd = 0;
1552 fr.delivery.tv_sec = 0;
1553 fr.delivery.tv_usec = 0;
1554 ast_queue_frame(p->owner,&fr);
1555 }
1556 return(1);
1557 }
1558
1559 /* voter primary client thread */
1560 static void *voter_primary_client(void *data)
1561 {
1562 struct voter_pvt *p = (struct voter_pvt *)data;
1563 int i,pri_socket,ms;
1564 char buf[4096];
1565 struct sockaddr_in sin;
1566 socklen_t fromlen;
1567 ssize_t recvlen;
1568 struct voter_client *client;
1569 struct timeval tv,lasttx,lastrx;
1570 VOTER_PACKET_HEADER *vph;
1571 uint32_t resp_digest,digest,mydigest;
1572 #pragma pack(push)
1573 #pragma pack(1)
1574 struct {
1575 VOTER_PACKET_HEADER vp;
1576 char flags;
1577 } authpacket;
1578 #pragma pack(pop)
1579
1580
1581
1582 if (debug >= 3) ast_verbose("pri thread started on instance %d\n",p->nodenum);
1583 if ((pri_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
1584 {
1585 ast_log(LOG_ERROR,"Unable to create new socket for voter primary connection for instance %d\n",p->nodenum);
1586 pthread_exit(NULL);
1587 return (NULL);
1588 }
1589 resp_digest = 0;
1590 digest = 0;
1591 memset(&lasttx,0,sizeof(lasttx));
1592 memset(&lastrx,0,sizeof(lasttx));
1593 ast_mutex_lock(&voter_lock);
1594 p->primary_challenge[0] = 0;
1595 while(run_forever && (!ast_shutting_down()))
1596 {
1597 ast_mutex_unlock(&voter_lock);
1598 ms = 100;
1599 i = ast_waitfor_n_fd(&pri_socket, 1, &ms,NULL);
1600 ast_mutex_lock(&voter_lock);
1601 if (i == -1)
1602 {
1603 ast_mutex_unlock(&voter_lock);
1604 ast_log(LOG_ERROR,"Error in select()\n");
1605 pthread_exit(NULL);
1606 }
1607 gettimeofday(&tv,NULL);
1608 memset(&authpacket,0,sizeof(authpacket));
1609 if ((!p->priconn) && (ast_tvzero(lasttx) || (voter_tvdiff_ms(tv,lasttx) >= 500)))
1610 {
1611 authpacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
1612 authpacket.vp.curtime.vtime_nsec = htonl(voter_timing_count);
1613 strcpy((char *)authpacket.vp.challenge,challenge);
1614 authpacket.vp.digest = htonl(resp_digest);
1615 authpacket.flags = 32;
1616 if (debug >= 3) ast_verbose("Sent pri auth to %s:%d\n",ast_inet_ntoa(p->primary.sin_addr),ntohs(p->primary.sin_port));
1617 sendto(pri_socket, &authpacket, sizeof(authpacket),0,(struct sockaddr *)&p->primary,sizeof(p->primary));
1618 lasttx = tv;
1619 }
1620 if (p->priconn && (ast_tvzero(lasttx) || (voter_tvdiff_ms(tv,lasttx) >= 1000)))
1621 {
1622 authpacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
1623 authpacket.vp.curtime.vtime_nsec = htonl(voter_timing_count);
1624 strcpy((char *)authpacket.vp.challenge,challenge);
1625 authpacket.vp.digest = htonl(resp_digest);
1626 authpacket.vp.payload_type = htons(VOTER_PAYLOAD_GPS);
1627 if (debug >= 3) ast_verbose("Sent pri GPS Keepalive to %s:%d\n",ast_inet_ntoa(p->primary.sin_addr),ntohs(p->primary.sin_port));
1628 sendto(pri_socket, &authpacket, sizeof(authpacket) - 1,0,(struct sockaddr *)&p->primary,sizeof(p->primary));
1629 lasttx = tv;
1630 }
1631 if (p->priconn && (ast_tvzero(lastrx) || (voter_tvdiff_ms(tv,lastrx) >= 2000)))
1632 {
1633 p->priconn = 0;
1634 digest = 0;
1635 p->primary_challenge[0] = 0;
1636 if (option_verbose >= 3) ast_verbose(VERBOSE_PREFIX_3 "Primary client for %d Lost connection!!!\n",p->nodenum);
1637 for(client = clients; client; client = client->next)
1638 {
1639 if (client->nodenum != p->nodenum) continue;
1640 if (!IS_CLIENT_PROXY(client)) continue;
1641 client->respdigest = 0;
1642 client->heardfrom = 0;
1643 }
1644 }
1645 if (i < 0) continue;
1646 if (i == pri_socket)
1647 {
1648 fromlen = sizeof(struct sockaddr_in);
1649 recvlen = recvfrom(pri_socket,buf,sizeof(buf) - 1,0,
1650 (struct sockaddr *)&sin,&fromlen);
1651
1652 if (recvlen >= sizeof(VOTER_PACKET_HEADER)) /* if set got something worthwile */
1653 {
1654 vph = (VOTER_PACKET_HEADER *)buf;
1655 if (debug > 3) ast_verbose("Got pri rx packet, len %d payload %d challenge %s digest %08x\n",(int)recvlen,ntohs(vph->payload_type),vph->challenge,ntohl(vph->digest));
1656 /* if this is a new session */
1657 if (strcmp((char *)vph->challenge,p->primary_challenge))
1658 {
1659 resp_digest = crc32_bufs((char *)vph->challenge,p->primary_pswd);
1660 strcpy(p->primary_challenge,(char *)vph->challenge);
1661 p->priconn = 0;
1662 }
1663 else
1664 {
1665 if ((!digest) || (!vph->digest) || (digest != ntohl(vph->digest)) ||
1666 (ntohs(vph->payload_type) == 0) || (ntohs(vph->payload_type) == VOTER_PAYLOAD_GPS))
1667 {
1668 mydigest = crc32_bufs(challenge,password);
1669 if (mydigest == ntohl(vph->digest))
1670 {
1671 digest = mydigest;
1672 if ((!p->priconn) && (option_verbose >= 3))
1673 ast_verbose(VERBOSE_PREFIX_3 "Primary client for %d connected (with challenge=%s)\n",
1674 p->nodenum,p->primary_challenge);
1675 p->priconn = 1;
1676 lastrx = tv;
1677 }
1678 else
1679 {
1680 p->priconn = 0;
1681 digest = 0;
1682 }
1683 }
1684 }
1685 }
1686 }
1687 }
1688 pthread_exit(NULL);
1689 return (NULL);
1690 }
1691
1692 static void check_ping_done(struct voter_client *client)
1693 {
1694 float p,q;
1695
1696 if (!client->pings_requested) return;
1697 if (!client->ping_abort)
1698 {
1699 if (client->pings_sent < client->pings_requested) return;
1700 if (voter_tvdiff_ms(ast_tvnow(),
1701 (ast_tvzero(client->ping_last_rxtime)) ? client->ping_txtime : client->ping_last_rxtime) > PING_TIMEOUT_MS)
1702 {
1703 ast_verbose("\nPING (%s): RESPONSE TIMEOUT!!\n",client->name);
1704 }
1705 else
1706 {
1707 if (client->pings_received < client->pings_requested) return;
1708 }
1709 }
1710 else
1711 {
1712 ast_verbose("\nPING (%s): ABORTED!!\n",client->name);
1713 client->ping_abort = 0;
1714 }
1715 if (client->pings_sent)
1716 p = 100.0 * (float) (client->pings_received - client->pings_oos) / (float) client->pings_sent;
1717 else
1718 p = 0.0;
1719 if (client->pings_received)
1720 q = (float)client->pings_total_ms / (float) client->pings_received;
1721 else
1722 q = 0;
1723 ast_verbose("\nPING (%s): Packets tx: %d, rx: %d, oos: %d, Avg.: %0.3f ms\n",client-> name,client->pings_sent,
1724 client->pings_received,client->pings_oos,q);
1725 ast_verbose("PING (%s): Worst: %d ms, Best: %d ms, %0.1f%% Packets successfully received (%0.1f%% loss)\n",client->name,
1726 client->pings_worst,client->pings_best,p, 100.0 - p);
1727 client->pings_requested = 0;
1728 }
1729
1730
1731
1732 /* voter xmit thread */
1733 static void *voter_xmit(void *data)
1734 {
1735
1736 struct voter_pvt *p = (struct voter_pvt *)data;
1737 int i,n,x,mx;
1738 i16 dummybuf1[FRAME_SIZE * 12],xmtbuf1[FRAME_SIZE * 12];
1739 i16 xmtbuf[FRAME_SIZE],dummybuf2[FRAME_SIZE],xmtbuf2[FRAME_SIZE];
1740 i32 l;
1741 struct ast_frame fr,*f1,*f2,*f3,wf1;
1742 struct voter_client *client,*client1;
1743 struct timeval tv;
1744
1745 #pragma pack(push)
1746 #pragma pack(1)
1747 struct {
1748 VOTER_PACKET_HEADER vp;
1749 char rssi;
1750 char audio[FRAME_SIZE + 3];
1751 } audiopacket;
1752 struct {
1753 VOTER_PACKET_HEADER vp;
1754 VOTER_PROXY_HEADER vprox;
1755 char rssi;
1756 char audio[FRAME_SIZE + 3];
1757 } proxy_audiopacket;
1758 struct {
1759 VOTER_PACKET_HEADER vp;
1760 unsigned int seqno;
1761 struct timeval txtime;
1762 struct timeval starttime;
1763 char filler[128];
1764 } pingpacket;
1765 #pragma pack(pop)
1766
1767 while(run_forever && (!ast_shutting_down()))
1768 {
1769 ast_mutex_lock(&p->xmit_lock);
1770 ast_cond_wait(&p->xmit_cond, &p->xmit_lock);
1771 ast_mutex_unlock(&p->xmit_lock);
1772 if (!p->drained_once)
1773 {
1774 p->drained_once = 1;
1775 continue;
1776 }
1777 n = x = 0;
1778 f2 = 0;
1779 ast_mutex_lock(&p->txqlock);
1780 AST_LIST_TRAVERSE(&p->txq, f1,frame_list) n++;
1781 ast_mutex_unlock(&p->txqlock);
1782 if (n && ((n > 3) || (!p->txkey)))
1783 {
1784 x = 1;
1785 ast_mutex_lock(&p->txqlock);
1786 f2 = AST_LIST_REMOVE_HEAD(&p->txq,frame_list);
1787 ast_mutex_unlock(&p->txqlock);
1788 if (p->pmrChan)
1789 {
1790 p->pmrChan->txPttIn = 1;
1791 PmrTx(p->pmrChan,(i16*) AST_FRAME_DATAP(f2));
1792 ast_frfree(f2);
1793 }
1794 }
1795 f1 = NULL;
1796 // x will be set here is there was actual transmit activity
1797 if ((!x) && (p->pmrChan)) p->pmrChan->txPttIn = 0;
1798 if (x && (!p->pmrChan))
1799 {
1800 memcpy(xmtbuf,AST_FRAME_DATAP(f2),sizeof(xmtbuf));
1801 f1 = ast_translate(p->fromast,f2,1);
1802 if (!f1)
1803 {
1804 ast_log(LOG_ERROR,"Can not translate frame to recv from Asterisk\n");
1805 continue;
1806 }
1807 }
1808 if (p->pmrChan)
1809 {
1810 if (p->pmrChan->txPttOut && (!x))
1811 {
1812 memset(xmtbuf,0,sizeof(xmtbuf));
1813 if (p->pmrChan) PmrTx(p->pmrChan,xmtbuf);
1814 }
1815 PmrRx(p->pmrChan,dummybuf1,dummybuf2,xmtbuf1);
1816 n = 0;
1817 ast_mutex_lock(&p->pagerqlock);
1818 AST_LIST_TRAVERSE(&p->pagerq, f1,frame_list) n++;
1819 ast_mutex_unlock(&p->pagerqlock);
1820 if (p->waspager && (n < 1))
1821 {
1822 memset(&wf1,0,sizeof(wf1));
1823 wf1.frametype = AST_FRAME_TEXT;
1824 wf1.datalen = strlen(ENDPAGE_STR) + 1;
1825 AST_FRAME_DATA(wf1) = ENDPAGE_STR;
1826 ast_queue_frame(p->owner, &wf1);
1827 p->waspager = 0;
1828 }
1829 if (n)
1830 {
1831 ast_mutex_lock(&p->pagerqlock);
1832 f3 = AST_LIST_REMOVE_HEAD(&p->pagerq,frame_list);
1833 f1 = ast_translate(p->fromast,f3,0);
1834 if (!f1)
1835 {
1836 ast_log(LOG_ERROR,"Can not translate frame to recv from Asterisk\n");
1837 continue;
1838 }
1839 ast_frfree(f3);
1840 ast_mutex_unlock(&p->pagerqlock);
1841 x = 1;
1842 p->waspager = 1;
1843 }
1844 else
1845 {
1846 x = p->pmrChan->txPttOut;
1847 for(i = 0; i < FRAME_SIZE; i++)
1848 {
1849 xmtbuf[i] = xmtbuf1[i * 2];
1850 if (xmtbuf[i] > 28000) xmtbuf[i] = 28000;
1851 else if (xmtbuf[i] < -28000) xmtbuf[i] = -28000;
1852 }
1853 memset(&fr,0,sizeof(struct ast_frame));
1854 fr.frametype = AST_FRAME_VOICE;
1855 fr.subclass = AST_FORMAT_SLINEAR;
1856 fr.datalen = FRAME_SIZE;
1857 fr.samples = FRAME_SIZE;
1858 AST_FRAME_DATA(fr) = xmtbuf;
1859 fr.src = type;
1860 fr.offset = 0;
1861 fr.mallocd = 0;
1862 fr.delivery.tv_sec = 0;
1863 fr.delivery.tv_usec = 0;
1864 f1 = ast_translate(p->fromast,&fr,0);
1865 if (!f1)
1866 {
1867 ast_log(LOG_ERROR,"Can not translate frame to recv from Asterisk\n");
1868 continue;
1869 }
1870 }
1871 }
1872 mx = 0;
1873 if (p->mixminus)
1874 {
1875 for(client = clients; client; client = client->next)
1876 {
1877 if (client->nodenum != p->nodenum) continue;
1878 if (!client->heardfrom) continue;
1879 if (!client->respdigest) continue;
1880 if (!client->mix) continue;
1881 if (client->doadpcm) continue;
1882 if (client->donulaw) continue;
1883 if (client->lastrssi) mx = 1;
1884 }
1885 }
1886 // x will now be set if we are to generate TX output
1887 if (x || mx)
1888 {
1889 memset(&audiopacket,0,sizeof(audiopacket) - sizeof(audiopacket.audio));
1890 memset(&audiopacket.audio,0xff,sizeof(audiopacket.audio));
1891 strcpy((char *)audiopacket.vp.challenge,challenge);
1892 audiopacket.vp.payload_type = htons(1);
1893 audiopacket.rssi = 0;
1894 if (f1) memcpy(audiopacket.audio,AST_FRAME_DATAP(f1),FRAME_SIZE);
1895 #ifdef DMWDIAG
1896 for(i = 0; i < FRAME_SIZE; i++)
1897 {
1898 audiopacket.audio[i] = ulaw_digital_milliwatt[mwp++];
1899 if (mwp > 7) mwp = 0;
1900 }
1901 #endif
1902 audiopacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
1903 audiopacket.vp.curtime.vtime_nsec = htonl(master_time.vtime_nsec);
1904 for(client = clients; client; client = client->next)
1905 {
1906 if (client->nodenum != p->nodenum) continue;
1907 if (p->priconn && (!client->dynamic) && (!client->mix)) continue;
1908 if ((!client->respdigest) && (!IS_CLIENT_PROXY(client))) continue;
1909 if (!client->heardfrom) continue;
1910 if (client->doadpcm) continue;
1911 if (client->donulaw) continue;
1912 if (p->mixminus)
1913 {
1914 memcpy(xmtbuf2,xmtbuf,sizeof(xmtbuf2));
1915 i = 0;
1916 for(client1 = clients; client1; client1 = client1->next)
1917 {
1918 if (client1 == client) continue;
1919 if (client1->nodenum != p->nodenum) continue;
1920 if (!client1->heardfrom) continue;
1921 if (!client1->respdigest) continue;
1922 if (!client1->mix) continue;
1923 if (client1->doadpcm) continue;
1924 if (client1->donulaw) continue;
1925 if (!client1->lastrssi) continue;
1926 for(i = 0; i < FRAME_SIZE; i++)
1927 {
1928 l = xmtbuf2[i] + client1->lastaudio[i];
1929 if (l > 32767) l = 32767;
1930 if (l < -32767) l = -32767;
1931 xmtbuf2[i] = l;
1932 }
1933 }
1934 if ((!x) && (!i)) continue;
1935 memset(&fr,0,sizeof(struct ast_frame));
1936 fr.frametype = AST_FRAME_VOICE;
1937 fr.subclass = AST_FORMAT_SLINEAR;
1938 fr.datalen = FRAME_SIZE;
1939 fr.samples = FRAME_SIZE;
1940 AST_FRAME_DATA(fr) = xmtbuf2;
1941 fr.src = type;
1942 fr.offset = 0;
1943 fr.mallocd = 0;
1944 fr.delivery.tv_sec = 0;
1945 fr.delivery.tv_usec = 0;
1946 if (f1) ast_frfree(f1);
1947 f1 = ast_translate(p->fromast,&fr,0);
1948 if (!f1)
1949 {
1950 ast_log(LOG_ERROR,"Can not translate frame to recv from Asterisk\n");
1951 continue;
1952 }
1953 memcpy(audiopacket.audio,AST_FRAME_DATAP(f1),FRAME_SIZE);
1954 }
1955 mkpucked(client,&audiopacket.vp.curtime);
1956 audiopacket.vp.digest = htonl(client->respdigest);
1957 audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
1958 if (client->totransmit && (!client->txlockout))
1959 {
1960 if (IS_CLIENT_PROXY(client))
1961 {
1962 memset(&proxy_audiopacket,0,sizeof(proxy_audiopacket));
1963 proxy_audiopacket.vp = audiopacket.vp;
1964 proxy_audiopacket.rssi = audiopacket.rssi;
1965 memcpy(proxy_audiopacket.audio,audiopacket.audio,sizeof(audiopacket.audio));
1966 proxy_audiopacket.vprox.ipaddr = client->proxy_sin.sin_addr.s_addr;
1967 proxy_audiopacket.vprox.port = client->proxy_sin.sin_port;
1968 proxy_audiopacket.vprox.payload_type = proxy_audiopacket.vp.payload_type;
1969 proxy_audiopacket.vp.payload_type = htons(VOTER_PAYLOAD_PROXY);
1970 proxy_audiopacket.vp.digest = htonl(crc32_bufs(client->saved_challenge,client->pswd));
1971 proxy_audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
1972 if (debug > 1) ast_verbose("sending (proxied) audio packet to client %s digest %08x\n",client->name,proxy_audiopacket.vp.digest);
1973 sendto(udp_socket, &proxy_audiopacket, sizeof(proxy_audiopacket) - 3,0,(struct sockaddr *)&client->sin,sizeof(client->sin));
1974 }
1975 else
1976 {
1977 if (debug > 1) ast_verbose("sending audio packet to client %s digest %08x\n",client->name,client->respdigest);
1978 sendto(udp_socket, &audiopacket, sizeof(audiopacket) - 3,0,(struct sockaddr *)&client->sin,sizeof(client->sin));
1979 }
1980 gettimeofday(&client->lastsenttime,NULL);
1981 }
1982 }
1983 }
1984 if (x || p->adpcmf1)
1985 {
1986 if (p->adpcmf1 == NULL) p->adpcmf1 = ast_frdup(f1);
1987 else
1988 {
1989 memset(xmtbuf,0xff,sizeof(xmtbuf));
1990 memset(&fr,0,sizeof(struct ast_frame));
1991 fr.frametype = AST_FRAME_VOICE;
1992 fr.subclass = AST_FORMAT_ULAW;
1993 fr.datalen = FRAME_SIZE;
1994 fr.samples = FRAME_SIZE;
1995 AST_FRAME_DATA(fr) = xmtbuf;
1996 fr.src = type;
1997 fr.offset = 0;
1998 fr.mallocd = 0;
1999 fr.delivery.tv_sec = 0;
2000 fr.delivery.tv_usec = 0;
2001 if (x) f3 = ast_frcat(p->adpcmf1,f1); else f3 = ast_frcat(p->adpcmf1,&fr);
2002 ast_frfree(p->adpcmf1);
2003 p->adpcmf1 = NULL;
2004 f2 = ast_translate(p->adpcmout,f3,1);
2005 memcpy(audiopacket.audio,AST_FRAME_DATAP(f2),f2->datalen);
2006 audiopacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
2007 audiopacket.vp.payload_type = htons(3);
2008 for(client = clients; client; client = client->next)
2009 {
2010 if (client->nodenum != p->nodenum) continue;
2011 if (p->priconn && (!client->dynamic) && (!client->mix)) continue;
2012 if ((!client->respdigest) && (!IS_CLIENT_PROXY(client))) continue;
2013 if (!client->heardfrom) continue;
2014 if (!client->doadpcm) continue;
2015 mkpucked(client,&audiopacket.vp.curtime);
2016 audiopacket.vp.digest = htonl(client->respdigest);
2017 audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2018 #ifndef ADPCM_LOOPBACK
2019 if (client->totransmit && (!client->txlockout))
2020 {
2021 if (IS_CLIENT_PROXY(client))
2022 {
2023 memset(&proxy_audiopacket,0,sizeof(proxy_audiopacket));
2024 proxy_audiopacket.vp = audiopacket.vp;
2025 proxy_audiopacket.rssi = audiopacket.rssi;
2026 memcpy(proxy_audiopacket.audio,audiopacket.audio,sizeof(audiopacket.audio));
2027 proxy_audiopacket.vprox.ipaddr = client->proxy_sin.sin_addr.s_addr;
2028 proxy_audiopacket.vprox.port = client->proxy_sin.sin_port;
2029 proxy_audiopacket.vprox.payload_type = proxy_audiopacket.vp.payload_type;
2030 proxy_audiopacket.vp.payload_type = htons(VOTER_PAYLOAD_PROXY);
2031 proxy_audiopacket.vp.digest = htonl(crc32_bufs(client->saved_challenge,client->pswd));
2032 proxy_audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2033 if (debug > 1) ast_verbose("sending (proxied) audio packet to client %s digest %08x\n",client->name,proxy_audiopacket.vp.digest);
2034 sendto(udp_socket, &proxy_audiopacket, sizeof(proxy_audiopacket),0,(struct sockaddr *)&client->sin,sizeof(client->sin));
2035 }
2036 else
2037 {
2038 if (debug > 1) ast_verbose("sending audio packet to client %s digest %08x\n",client->name,client->respdigest);
2039 sendto(udp_socket, &audiopacket, sizeof(audiopacket),0,(struct sockaddr *)&client->sin,sizeof(client->sin));
2040 }
2041 gettimeofday(&client->lastsenttime,NULL);
2042
2043 }
2044 #endif
2045 }
2046 ast_frfree(f2);
2047 }
2048 }
2049 if (x || p->nulawf1)
2050 {
2051 short *sap,s;
2052 unsigned char nubuf[FRAME_SIZE];
2053
2054 if (p->nulawf1 == NULL) p->nulawf1 = ast_frdup(f1);
2055 else
2056 {
2057 memset(xmtbuf,0xff,sizeof(xmtbuf));
2058 memset(&fr,0,sizeof(struct ast_frame));
2059 fr.frametype = AST_FRAME_VOICE;
2060 fr.subclass = AST_FORMAT_ULAW;
2061 fr.datalen = FRAME_SIZE;
2062 fr.samples = FRAME_SIZE;
2063 AST_FRAME_DATA(fr) = xmtbuf;
2064 fr.src = type;
2065 fr.offset = 0;
2066 fr.mallocd = 0;
2067 fr.delivery.tv_sec = 0;
2068 fr.delivery.tv_usec = 0;
2069 if (x) f3 = ast_frcat(p->nulawf1,f1); else f3 = ast_frcat(p->nulawf1,&fr);
2070 ast_frfree(p->nulawf1);
2071 p->nulawf1 = NULL;
2072 f2 = ast_translate(p->nuout,f3,1);
2073 sap = (short *)AST_FRAME_DATAP(f2);
2074 for(i = 0; i < f2->samples / 2; i++)
2075 {
2076 s = *sap++;
2077 if (s > 14000) s = 14000;
2078 if (s < -14000) s = -14000;
2079 lpass4(s,p->tlpx,p->tlpy);
2080 s = *sap++;
2081 if (s > 14000) s = 14000;
2082 if (s < -14000) s = -14000;
2083 nubuf[i] = AST_LIN2MU(lpass4(s,p->tlpx,p->tlpy));
2084 }
2085 memcpy(audiopacket.audio,nubuf,sizeof(nubuf));
2086 audiopacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
2087 audiopacket.vp.payload_type = htons(4);
2088 for(client = clients; client; client = client->next)
2089 {
2090 if (client->nodenum != p->nodenum) continue;
2091 if (p->priconn && (!client->dynamic) && (!client->mix)) continue;
2092 if ((!client->respdigest) && (!IS_CLIENT_PROXY(client))) continue;
2093 if (!client->heardfrom) continue;
2094 if (!client->donulaw) continue;
2095 mkpucked(client,&audiopacket.vp.curtime);
2096 audiopacket.vp.digest = htonl(client->respdigest);
2097 audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2098 #ifndef NULAW_LOOPBACK
2099 if (client->totransmit && (!client->txlockout))
2100 {
2101 if (IS_CLIENT_PROXY(client))
2102 {
2103 memset(&proxy_audiopacket,0,sizeof(proxy_audiopacket));
2104 proxy_audiopacket.vp = audiopacket.vp;
2105 proxy_audiopacket.rssi = audiopacket.rssi;
2106 memcpy(proxy_audiopacket.audio,audiopacket.audio,sizeof(audiopacket.audio));
2107 proxy_audiopacket.vprox.ipaddr = client->proxy_sin.sin_addr.s_addr;
2108 proxy_audiopacket.vprox.port = client->proxy_sin.sin_port;
2109 proxy_audiopacket.vprox.payload_type = proxy_audiopacket.vp.payload_type;
2110 proxy_audiopacket.vp.payload_type = htons(VOTER_PAYLOAD_PROXY);
2111 proxy_audiopacket.vp.digest = htonl(crc32_bufs(client->saved_challenge,client->pswd));
2112 proxy_audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2113 if (debug > 1) ast_verbose("sending (proxied) audio packet to client %s digest %08x\n",client->name,proxy_audiopacket.vp.digest);
2114 sendto(udp_socket, &proxy_audiopacket, sizeof(proxy_audiopacket) - 3,0,
2115 (struct sockaddr *)&client->sin,sizeof(client->sin));
2116 }
2117 else
2118 {
2119 if (debug > 1) ast_verbose("sending audio packet to client %s digest %08x\n",client->name,client->respdigest);
2120 sendto(udp_socket, &audiopacket, sizeof(audiopacket) - 3,0,(struct sockaddr *)&client->sin,sizeof(client->sin));
2121 }
2122 gettimeofday(&client->lastsenttime,NULL);
2123 }
2124 #endif
2125 }
2126 ast_frfree(f2);
2127 }
2128 }
2129 if (f1) ast_frfree(f1);
2130 gettimeofday(&tv,NULL);
2131 for(client = clients; client; client = client->next)
2132 {
2133 if (client->nodenum != p->nodenum) continue;
2134 if (!client->respdigest) continue;
2135 if (!client->heardfrom) continue;
2136 if (IS_CLIENT_PROXY(client)) continue;
2137 check_ping_done(client);
2138 if (!client->pings_requested) continue;
2139 if (client->pings_sent >= client->pings_requested) continue;
2140 if (voter_tvdiff_ms(tv,client->ping_txtime) >= (PING_TIME_MS * client->pings_sent))
2141 {
2142 if (!client->pings_sent)
2143 {
2144 client->ping_txtime = ast_tvnow();
2145 memset(&client->ping_last_rxtime,0,sizeof(client->ping_last_rxtime));
2146 }
2147 client->pings_sent++;
2148 memset(&pingpacket,0,sizeof(pingpacket));
2149 pingpacket.seqno = ++client->ping_seqno;
2150 for(i = 0; i < sizeof(pingpacket.filler); i++)
2151 pingpacket.filler[i] = (pingpacket.seqno & 0xff) + i;
2152 pingpacket.txtime = tv;
2153 pingpacket.starttime = client->ping_txtime;
2154 strcpy((char *)pingpacket.vp.challenge,challenge);
2155 pingpacket.vp.payload_type = htons(VOTER_PAYLOAD_PING);
2156 pingpacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
2157 pingpacket.vp.curtime.vtime_nsec = htonl(master_time.vtime_nsec);
2158 mkpucked(client,&pingpacket.vp.curtime);
2159 pingpacket.vp.digest = htonl(client->respdigest);
2160 pingpacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2161 if (debug > 1) ast_verbose("sending ping packet to client %s digest %08x\n",client->name,client->respdigest);
2162 sendto(udp_socket, &pingpacket, sizeof(pingpacket),0,(struct sockaddr *)&client->sin,sizeof(client->sin));
2163 }
2164 }
2165 for(client = clients; client; client = client->next)
2166 {
2167 if (client->nodenum != p->nodenum) continue;
2168 if ((!client->respdigest) && (!IS_CLIENT_PROXY(client))) continue;
2169 if (p->priconn && (!client->dynamic) && (!client->mix) && (!IS_CLIENT_PROXY(client))) continue;
2170 if (!client->heardfrom) continue;
2171 if (ast_tvzero(client->lastsenttime) || (voter_tvdiff_ms(tv,client->lastsenttime) >= TX_KEEPALIVE_MS))
2172 {
2173 memset(&audiopacket,0,sizeof(audiopacket));
2174 strcpy((char *)audiopacket.vp.challenge,challenge);
2175 audiopacket.vp.curtime.vtime_sec = htonl(master_time.vtime_sec);
2176 audiopacket.vp.payload_type = htons(2);
2177 audiopacket.vp.digest = htonl(client->respdigest);
2178 audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2179 if (IS_CLIENT_PROXY(client))
2180 {
2181 memset(&proxy_audiopacket,0,sizeof(proxy_audiopacket));
2182 proxy_audiopacket.vp = audiopacket.vp;
2183 proxy_audiopacket.rssi = audiopacket.rssi;
2184 memcpy(proxy_audiopacket.audio,audiopacket.audio,sizeof(audiopacket.audio));
2185 proxy_audiopacket.vprox.ipaddr = client->proxy_sin.sin_addr.s_addr;
2186 proxy_audiopacket.vprox.port = client->proxy_sin.sin_port;
2187 proxy_audiopacket.vprox.payload_type = proxy_audiopacket.vp.payload_type;
2188 proxy_audiopacket.vp.payload_type = htons(VOTER_PAYLOAD_PROXY);
2189 proxy_audiopacket.vp.digest = htonl(crc32_bufs(client->saved_challenge,client->pswd));
2190 proxy_audiopacket.vp.curtime.vtime_nsec = (client->mix) ? htonl(client->txseqno) : htonl(master_time.vtime_nsec);
2191 if (debug > 1) ast_verbose("sending (proxied) GPS/Keepalive packet to client %s digest %08x\n",client->name,proxy_audiopacket.vp.digest);
2192 sendto(udp_socket, &proxy_audiopacket, sizeof(VOTER_PACKET_HEADER) + sizeof(VOTER_PROXY_HEADER),
2193 0,(struct sockaddr *)&client->sin,sizeof(client->sin));
2194 }
2195 else
2196 {
2197 if (debug > 1) ast_verbose("sending KEEPALIVE (GPS) packet to client %s digest %08x\n",client->name,client->respdigest);
2198 sendto(udp_socket, &audiopacket, sizeof(VOTER_PACKET_HEADER),0,(struct sockaddr *)&client->sin,sizeof(client->sin));
2199 }
2200 gettimeofday(&client->lastsenttime,NULL);
2201 }
2202 }
2203 }
2204 pthread_exit(NULL);
2205 }
2206
2207 static struct ast_channel *voter_request(const char *type, int format, void *data, int *cause)
2208 {
2209 int oldformat,i,j;
2210 struct voter_pvt *p,*p1;
2211 struct ast_channel *tmp = NULL;
2212 char *val,*cp,*cp1,*cp2,*strs[MAXTHRESHOLDS],*ctg;
2213 struct ast_config *cfg = NULL;
2214 pthread_attr_t attr;
2215
2216 oldformat = format;
2217 format &= AST_FORMAT_SLINEAR;
2218 if (!format) {
2219 ast_log(LOG_ERROR, "Asked to get a channel of unsupported format '%d'\n", oldformat);
2220 return NULL;
2221 }
2222 p = ast_malloc(sizeof(struct voter_pvt));
2223 if (!p)
2224 {
2225 ast_log(LOG_ERROR,"Cant malloc() for voter structure!\n");
2226 return NULL;
2227 }
2228 memset(p, 0, sizeof(struct voter_pvt));
2229 p->nodenum = strtoul((char *)data,NULL,0);
2230 ast_mutex_init(&p->txqlock);
2231 ast_mutex_init(&p->pagerqlock);
2232 ast_mutex_init(&p->xmit_lock);
2233 ast_cond_init(&p->xmit_cond,NULL);
2234 p->dsp = ast_dsp_new();
2235 if (!p->dsp)
2236 {
2237 ast_log(LOG_ERROR,"Cannot get DSP!!\n");
2238 ast_free(p);
2239 return NULL;
2240 }
2241 #ifdef NEW_ASTERISK
2242 ast_dsp_set_features(p->dsp,DSP_FEATURE_DIGIT_DETECT);
2243 ast_dsp_set_digitmode(p->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
2244 #else
2245 ast_dsp_set_features(p->dsp,DSP_FEATURE_DTMF_DETECT);
2246 ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_RELAXDTMF);
2247 #endif
2248 p->usedtmf = 1;
2249 p->adpcmin = ast_translator_build_path(AST_FORMAT_ULAW,AST_FORMAT_ADPCM);
2250 if (!p->adpcmin)
2251 {
2252 ast_log(LOG_ERROR,"Cannot get translator from adpcm to ulaw!!\n");
2253 ast_dsp_free(p->dsp);
2254 ast_free(p);
2255 return NULL;
2256 }
2257 p->adpcmout = ast_translator_build_path(AST_FORMAT_ADPCM,AST_FORMAT_ULAW);
2258 if (!p->adpcmout)
2259 {
2260 ast_log(LOG_ERROR,"Cannot get translator from ulaw to adpcm!!\n");
2261 ast_dsp_free(p->dsp);
2262 ast_free(p);
2263 return NULL;
2264 }
2265 p->toast = ast_translator_build_path(AST_FORMAT_SLINEAR,AST_FORMAT_ULAW);
2266 if (!p->toast)
2267 {
2268 ast_log(LOG_ERROR,"Cannot get translator from ulaw to slinear!!\n");
2269 ast_dsp_free(p->dsp);
2270 ast_free(p);
2271 return NULL;
2272 }
2273 p->toast1 = ast_translator_build_path(AST_FORMAT_SLINEAR,AST_FORMAT_ULAW);
2274 if (!p->toast1)
2275 {
2276 ast_log(LOG_ERROR,"Cannot get translator from ulaw to slinear!!\n");
2277 ast_dsp_free(p->dsp);
2278 ast_free(p);
2279 return NULL;
2280 }
2281 p->fromast = ast_translator_build_path(AST_FORMAT_ULAW,AST_FORMAT_SLINEAR);
2282 if (!p->fromast)
2283 {
2284 ast_log(LOG_ERROR,"Cannot get translator from slinear to ulaw!!\n");
2285 ast_dsp_free(p->dsp);
2286 ast_free(p);
2287 return NULL;
2288 }
2289 p->nuin = ast_translator_build_path(AST_FORMAT_ULAW,AST_FORMAT_SLINEAR);
2290 if (!p->nuin)
2291 {
2292 ast_log(LOG_ERROR,"Cannot get translator from slinear to ulaw!!\n");
2293 ast_dsp_free(p->dsp);
2294 ast_free(p);
2295 return NULL;
2296 }
2297 p->nuout = ast_translator_build_path(AST_FORMAT_SLINEAR,AST_FORMAT_ULAW);
2298 if (!p->nuout)
2299 {
2300 ast_log(LOG_ERROR,"Cannot get translator from ulaw to slinear!!\n");
2301 ast_dsp_free(p->dsp);
2302 ast_free(p);
2303 return NULL;
2304 }
2305 #ifdef OLD_ASTERISK
2306 tmp = ast_channel_alloc(1);
2307 if (!tmp)
2308 {
2309 ast_log(LOG_ERROR,"Cant alloc new asterisk channel\n");
2310 ast_free(p);
2311 return NULL;
2312 }
2313 ast_setstate(tmp,AST_STATE_DOWN);
2314 ast_copy_string(tmp->context, context, sizeof(tmp->context));
2315 ast_copy_string(tmp->exten, (char *)data, sizeof(tmp->exten));
2316 snprintf(tmp->name, sizeof(tmp->name), "voter/%s", (char *)data);
2317 #else
2318 tmp = ast_channel_alloc(1, AST_STATE_DOWN, 0, 0, "", (char *)data, context, 0, "voter/%s", (char *)data);
2319 if (!tmp)
2320 {
2321 ast_log(LOG_ERROR,"Cant alloc new asterisk channel\n");
2322 ast_free(p);
2323 return NULL;
2324 }
2325 #endif
2326 ast_mutex_lock(&voter_lock);
2327 if (pvts != NULL) p->next = pvts;
2328 pvts = p;
2329 ast_mutex_unlock(&voter_lock);
2330 tmp->tech = &voter_tech;
2331 tmp->rawwriteformat = AST_FORMAT_SLINEAR;
2332 tmp->writeformat = AST_FORMAT_SLINEAR;
2333 tmp->rawreadformat = AST_FORMAT_SLINEAR;
2334 tmp->readformat = AST_FORMAT_SLINEAR;
2335 tmp->nativeformats = AST_FORMAT_SLINEAR;
2336 // if (state == AST_STATE_RING) tmp->rings = 1;
2337 tmp->tech_pvt = p;
2338 #ifdef OLD_ASTERISK
2339 ast_copy_string(tmp->language, "", sizeof(tmp->language));
2340 #else
2341 ast_string_field_set(tmp, language, "");
2342 #endif
2343 p->owner = tmp;
2344 #ifdef OLD_ASTERISK
2345 ast_mutex_lock(&usecnt_lock);
2346 usecnt++;
2347 ast_mutex_unlock(&usecnt_lock);
2348 ast_update_use_count();
2349 #else
2350 p->u = ast_module_user_add(tmp);
2351 #endif
2352 #ifdef NEW_ASTERISK
2353 if (!(cfg = ast_config_load(config,zeroflag))) {
2354 #else
2355 if (!(cfg = ast_config_load(config))) {
2356 #endif
2357 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
2358 } else {
2359 val = (char *) ast_variable_retrieve(cfg,(char *)data,"linger");
2360 if (val) p->linger = atoi(val); else p->linger = DEFAULT_LINGER;
2361 val = (char *) ast_variable_retrieve(cfg,(char *)data,"plfilter");
2362 if (val) p->plfilter = ast_true(val);
2363 val = (char *) ast_variable_retrieve(cfg,(char *)data,"hostdeemp");
2364 if (val) p->hostdeemp = ast_true(val);
2365 val = (char *) ast_variable_retrieve(cfg,(char *)data,"duplex");
2366 if (val) p->duplex = ast_true(val); else p->duplex = 1;
2367 val = (char *) ast_variable_retrieve(cfg,(char *)data,"mixminus");
2368 if (val) p->mixminus = ast_true(val);