Version 0.1.0 from FTP
[asterisk/asterisk.git] / translate.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Translate via the use of pseudo channels
5  * 
6  * Copyright (C) 1999, Adtran Inc. and Linux Support Services, LLC
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <asterisk/channel.h>
15 #include <asterisk/channel_pvt.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/translate.h>
18 #include <asterisk/options.h>
19 #include <sys/socket.h>
20 #include <sys/time.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <pthread.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 static char *type = "Trans";
28
29 static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
30 static struct ast_translator *list = NULL;
31
32 struct ast_translator_dir {
33         struct ast_translator *step;    /* Next step translator */
34         int cost;                                               /* Complete cost to destination */
35 };
36
37 static struct ast_translator_dir tr_matrix[MAX_FORMAT][MAX_FORMAT];
38
39 struct ast_trans_pvt {
40         struct ast_translator *step;
41         struct ast_translator_pvt *state;
42         struct ast_trans_pvt *next;
43 };
44
45
46 static int powerof(int d)
47 {
48         int x;
49         for (x = 0; x < 32; x++)
50                 if ((1 << x) & d)
51                         return x;
52         ast_log(LOG_WARNING, "Powerof %d: No power??\n", d);
53         return -1;
54 }
55
56 struct translator_pvt {
57         /* Sockets for communication */
58         int comm[2];
59         struct ast_trans_pvt *system;
60         struct ast_trans_pvt *rsystem;
61 };
62
63 static int translator_hangup(struct ast_channel *chan)
64 {
65         ast_log(LOG_WARNING, "Explicit hangup on '%s' not recommended!  Call translator_destroy() instead.\n", chan->name);
66         chan->master->trans = NULL;
67         ast_hangup(chan->master);
68         chan->master = NULL;
69         return 0;
70 }
71
72 static int translator_send_digit(struct ast_channel *chan, char digit)
73 {
74         /* Pass digits right along */
75         if (chan->master->pvt->send_digit)
76                 return chan->master->pvt->send_digit(chan->master, digit);
77         return -1;
78 }
79
80 static int translator_call(struct ast_channel *chan, char *addr, int timeout)
81 {
82         if (chan->master->pvt->call)
83                 return chan->master->pvt->call(chan->master, addr, timeout);
84         return -1;
85 }
86
87 static int translator_answer(struct ast_channel *chan)
88 {
89         if (chan->master->pvt->answer)
90                 return chan->master->pvt->answer(chan->master);
91         return -1;
92 }
93
94 void ast_translator_free_path(struct ast_trans_pvt *p)
95 {
96         struct ast_trans_pvt *pl;
97         while(p) {
98                 pl = p;
99                 p = p->next;
100                 if (pl->state && pl->step->destroy)
101                         pl->step->destroy(pl->state);
102                 free(pl);
103         }
104 }
105
106 static void ast_translator_free(struct translator_pvt *pvt)
107 {
108         ast_translator_free_path(pvt->system);
109         ast_translator_free_path(pvt->rsystem);
110         if (pvt->comm[0] > -1)
111                 close(pvt->comm[0]);
112         if (pvt->comm[1] > -1)
113                 close(pvt->comm[1]);
114         free(pvt);
115 }
116
117 struct ast_trans_pvt *ast_translator_build_path(int source, int dest)
118 {
119         struct ast_trans_pvt *tmpr = NULL, *tmp = NULL;
120         /* One of the hardest parts:  Build a set of translators based upon
121            the given source and destination formats */
122         source = powerof(source);
123         dest = powerof(dest);
124         while(source != dest) {
125                 if (tr_matrix[source][dest].step) {
126                         if (tmp) {
127                                 tmp->next = malloc(sizeof(struct ast_trans_pvt));
128                                 tmp = tmp->next;
129                         } else
130                                 tmp = malloc(sizeof(struct ast_trans_pvt));
131
132                                 
133                         if (tmp) {
134                                 tmp->next = NULL;
135                                 tmp->step = tr_matrix[source][dest].step;
136                                 tmp->state = tmp->step->new();
137                                 if (!tmp->state) {
138                                         free(tmp);
139                                         tmp = NULL;
140                                 }
141                                 /* Set the root, if it doesn't exist yet... */
142                                 if (!tmpr)
143                                         tmpr = tmp;
144                                 /* Keep going if this isn't the final destination */
145                                 source = tmp->step->dstfmt;
146                         } else {
147                                 /* XXX This could leak XXX */
148                                 ast_log(LOG_WARNING, "Out of memory\n");
149                                 return NULL;
150                         }
151                 }
152         }
153         return tmpr;
154 }
155
156 static struct ast_frame *fd_read(int fd)
157 {
158         /* XXX Wrong: Not thread safe! XXX */
159         char buf[4096];
160         int res;
161         struct ast_frame *f = (struct ast_frame *)buf;
162         /* Read a frame directly from there.  They're always in the
163            right format. */
164         
165         if (read(fd, buf, sizeof(struct ast_frame)) 
166                                                 == sizeof(struct ast_frame)) {
167                 /* read the frame header */
168                 f->mallocd = 0;
169                 f->data = buf + sizeof(struct ast_frame) + AST_FRIENDLY_OFFSET;
170                 f->offset = AST_FRIENDLY_OFFSET;
171                 if (f->datalen > sizeof(buf) - sizeof(struct ast_frame) - AST_FRIENDLY_OFFSET) {
172                         /* Really bad read */
173                         ast_log(LOG_WARNING, "Strange read (%d bytes)\n", f->datalen);
174                         return NULL;
175                 }
176                 if (f->datalen) {
177                         if ((res = read(fd, f->data, f->datalen)) != f->datalen) {
178                                 /* Bad read */
179                                 ast_log(LOG_WARNING, "How very strange, expected %d, got %d\n", f->datalen, res);
180                                 return NULL;
181                         }
182                 }
183                 return ast_frisolate(f);
184         } else if (option_debug)
185                 ast_log(LOG_DEBUG, "NULL or invalid header\n");
186         /* Null if there was an error */
187         return NULL;
188 }
189
190 static struct ast_frame *translator_read(struct ast_channel *chan)
191 {
192         return fd_read(chan->fd);
193 }
194
195 static int fd_write(int fd, struct ast_frame *frame)
196 {
197         /* Write the frame exactly */
198         if (write(fd, frame, sizeof(struct ast_frame)) != sizeof(struct ast_frame)) {
199                 ast_log(LOG_WARNING, "Write error\n");
200                 return -1;
201         }
202         if (write(fd, frame->data, frame->datalen) != frame->datalen) {
203                 ast_log(LOG_WARNING, "Write error\n");
204                 return -1;
205         }
206         return 0;
207 }
208
209 static int translator_write(struct ast_channel *chan, struct ast_frame *frame)
210 {
211         return fd_write(chan->fd, frame);
212 }
213
214 struct ast_frame_chain *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f)
215 {
216         struct ast_trans_pvt *p;
217         struct ast_frame *out;
218         struct ast_frame_chain *outc = NULL, *prev = NULL, *cur;
219         p = path;
220         /* Feed the first frame into the first translator */
221         p->step->framein(p->state, f);
222         while(p) {
223                 /* Read all the frames from the current translator */
224                 while((out = p->step->frameout(p->state)))  {
225                         if (p->next) {
226                                 /* Feed to next layer */
227                                 p->next->step->framein(p->next->state, out);
228                         } else {
229                                 /* Last layer -- actually do something */
230                                 cur = malloc(sizeof(struct ast_frame_chain));
231                                 if (!cur) {
232                                         /* XXX Leak majorly on a problem XXX */
233                                         ast_log(LOG_WARNING, "Out of memory\n");
234                                         return NULL;
235                                 }
236                                 if (prev) 
237                                         prev->next = cur;
238                                 else
239                                         outc = cur;
240                                 cur->fr = ast_frisolate(out);
241                                 cur->next = NULL;
242                                 if (prev)
243                                         prev = prev->next;
244                                 else
245                                         prev = outc;
246                         }
247                 }
248                 p = p->next;
249         }
250         return outc;
251 }
252
253 /* XXX There's an experimentally derived fudge factor XXX */
254 #define FUDGE 4
255
256 static void translator_apply(struct ast_trans_pvt *path, struct ast_frame *f, int fd, struct ast_channel *c)
257 {
258         struct ast_trans_pvt *p;
259         struct ast_frame *out;
260         p = path;
261         /* Feed the first frame into the first translator */
262         p->step->framein(p->state, f);
263         while(p) {
264                 /* Read all the frames from the current translator */
265                 while((out = p->step->frameout(p->state)))  {
266                         if (p->next) {
267                                 /* Feed to next layer */
268                                 p->next->step->framein(p->next->state, out);
269                         } else {
270                                 if (c)
271                                         ast_write(c, out);
272                                 else
273                                         fd_write(fd, out);
274                         }
275                 }
276                 p = p->next;
277         }
278 }
279
280 static void *translator_thread(void *data)
281 {
282         struct ast_channel *real = data;
283         struct ast_frame *f;
284         int ms = -1;
285         struct translator_pvt *pvt = NULL;
286         int fd = -1;
287         int fds[2];
288         int res;
289         /* Read from the real, translate, write as necessary to the fake */
290         for(;;) {
291                 if (!real->trans) {
292                         ast_log(LOG_WARNING, "No translator anymore\n");
293                         break;
294                 }
295                 pvt = real->trans->pvt->pvt;
296                 fd = pvt->comm[1];
297                 fds[0] = fd;
298                 fds[1] = real->fd;
299                 CHECK_BLOCKING(real);
300                 res = ast_waitfor_n_fd(fds, 2, &ms);
301                 real->blocking = 0;
302                 if (res >= 0) {
303                         if (res == real->fd) {
304                                 f = ast_read(real);
305                                 if (!f) {
306                                         if (option_debug)
307                                                 ast_log(LOG_DEBUG, "Empty frame\n");
308                                         break;
309                                 }
310                                 if (f->frametype ==  AST_FRAME_VOICE) {
311                                         if (pvt->system)
312                                                 translator_apply(pvt->system, f, fd, NULL);
313                                 } else {
314                                         /* If it's not voice, just pass it along */
315                                         fd_write(fd, f);
316                                 }
317                                 ast_frfree(f);
318                         } else {
319                                 f = fd_read(res);
320                                 if (!f) {
321                                         if (option_debug)
322                                                 ast_log(LOG_DEBUG, "Empty (hangup) frame\n");
323                                         break;
324                                 }
325                                 if (f->frametype == AST_FRAME_VOICE) {
326                                         if (pvt->rsystem)
327                                                 translator_apply(pvt->rsystem, f, -1, real);
328                                 } else {
329                                         ast_write(real, f);
330                                 }
331                                 ast_frfree(f);
332                         }
333                 } else {
334                         ast_log(LOG_DEBUG, "Waitfor returned non-zero\n");
335                         break;
336                 }
337         }
338         if (pvt)
339                 pvt->comm[1] = -1;
340         if (fd > -1) {
341                 /* Write a bogus frame */
342                 write(fd, data, 1);
343                 close(fd);
344         }
345         return NULL;
346 }
347
348 struct ast_channel *ast_translator_create(struct ast_channel *real, int format, int direction)
349 {
350         struct ast_channel *tmp;
351         struct translator_pvt *pvt;
352         pthread_t t;
353         if (real->trans) {
354                 ast_log(LOG_WARNING, "Translator already exists on '%s'\n", real->name);
355                 return NULL;
356         }
357         if (!(pvt = malloc(sizeof(struct translator_pvt)))) {
358                 ast_log(LOG_WARNING, "Unable to allocate private translator on '%s'\n", real->name);
359                 return NULL;
360         }
361         pvt->comm[0] = -1;
362         pvt->comm[1] = -1;
363         if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pvt->comm)) {
364                 ast_log(LOG_WARNING, "Unable to create UNIX domain socket on '%s'\n", real->name);
365                 ast_translator_free(pvt);
366         }
367         /* In to the system */
368         if (direction & AST_DIRECTION_IN)
369                 pvt->system = ast_translator_build_path(real->format, format);
370         else
371                 pvt->system = NULL;
372         /* Out from the system */
373         if (direction & AST_DIRECTION_OUT)
374                 pvt->rsystem = ast_translator_build_path(format, real->format);
375         else
376                 pvt->rsystem = NULL;
377         if (!pvt->system && !pvt->rsystem) {
378                 ast_log(LOG_WARNING, "Unable to build a translation path for %s (%d to %d)\n", real->name, real->format, format);
379                 ast_translator_free(pvt);
380                 return NULL;
381         }
382         if (!pvt->system && (direction & AST_DIRECTION_IN)) {
383                 ast_log(LOG_WARNING, "Translation path for '%s' is one-way (reverse)\n", real->name);
384                 ast_translator_free(pvt);
385                 return NULL;
386         }
387         if (!pvt->rsystem && (direction & AST_DIRECTION_OUT)) {
388                 ast_log(LOG_WARNING, "Translation path for '%s' is one-way (forward)\n", real->name);
389                 ast_translator_free(pvt);
390                 return NULL;
391         }
392         if ((tmp = ast_channel_alloc())) {
393                 snprintf(tmp->name, sizeof(tmp->name), "%s/Translate:%d", real->name, format);
394                 tmp->type = type;
395                 tmp->fd = pvt->comm[0];
396                 tmp->format = format;
397                 tmp->state = real->state;
398                 tmp->rings = 0;
399                 tmp->pvt->pvt = pvt;
400                 tmp->master = real;
401                 tmp->pvt->send_digit = translator_send_digit;
402                 tmp->pvt->call = translator_call;
403                 tmp->pvt->hangup = translator_hangup;
404                 tmp->pvt->answer = translator_answer;
405                 tmp->pvt->read = translator_read;
406                 tmp->pvt->write = translator_write;
407                 real->trans = tmp;
408                 if (option_verbose > 2)
409                         ast_verbose(VERBOSE_PREFIX_3 "Created translator %s\n", tmp->name);
410                 if (pthread_create(&t, NULL, translator_thread, real) < 0) {
411                         ast_translator_destroy(tmp);
412                         tmp = NULL;
413                         ast_log(LOG_WARNING, "Failed to start thread\n");
414                 }
415         } else {
416                 ast_translator_free(pvt);
417                 ast_log(LOG_WARNING, "Unable to allocate channel\n");
418         }
419         return tmp;
420
421
422 static void rebuild_matrix()
423 {
424         struct ast_translator *t;
425         int changed;
426         int x,y,z;
427         if (option_debug)
428                 ast_log(LOG_DEBUG, "Reseting translation matrix\n");
429         /* Use the list of translators to build a translation matrix */
430         bzero(tr_matrix, sizeof(tr_matrix));
431         t = list;
432         while(t) {
433                 if (!tr_matrix[t->srcfmt][t->dstfmt].step ||
434                      tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) {
435                         tr_matrix[t->srcfmt][t->dstfmt].step = t;
436                         tr_matrix[t->srcfmt][t->dstfmt].cost = t->cost;
437                 }
438                 t = t->next;
439         }
440         do {
441                 changed = 0;
442                 /* Don't you just love O(N^3) operations? */
443                 for (x=0; x< MAX_FORMAT; x++)                           /* For each source format */
444                         for (y=0; y < MAX_FORMAT; y++)                  /* And each destination format */
445                                 if (x != y)                                                     /* Except ourselves, of course */
446                                         for (z=0; z < MAX_FORMAT; z++)  /* And each format it might convert to */
447                                                 if ((x!=z) && (y!=z))           /* Don't ever convert back to us */
448                                                         if (tr_matrix[x][y].step && /* We can convert from x to y */
449                                                                 tr_matrix[y][z].step && /* And from y to z and... */
450                                                                 (!tr_matrix[x][z].step ||       /* Either there isn't an x->z conversion */
451                                                                 (tr_matrix[x][y].cost + 
452                                                                  tr_matrix[y][z].cost < /* Or we're cheaper than the existing */
453                                                                  tr_matrix[x][z].cost)  /* solution */
454                                                              )) {
455                                                                                         /* We can get from x to z via y with a cost that
456                                                                                            is the sum of the transition from x to y and
457                                                                                            from y to z */
458                                                                  
459                                                                         tr_matrix[x][z].step = tr_matrix[x][y].step;
460                                                                         tr_matrix[x][z].cost = tr_matrix[x][y].cost + 
461                                                                                                                    tr_matrix[y][z].cost;
462                                                                         if (option_debug)
463                                                                                 ast_log(LOG_DEBUG, "Discovered %d cost path from %d to %d, via %d\n", tr_matrix[x][z].cost, x, z, y);
464                                                                         changed++;
465                                                                  }
466                 
467         } while (changed);
468 }
469
470 static void calc_cost(struct ast_translator *t)
471 {
472         int sofar=0;
473         struct ast_translator_pvt *pvt;
474         struct ast_frame *f, *out;
475         struct timeval start, finish;
476         int cost;
477         /* If they don't make samples, give them a terrible score */
478         if (!t->sample) {
479                 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
480                 t->cost = 99999;
481                 return;
482         }
483         pvt = t->new();
484         if (!pvt) {
485                 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
486                 t->cost = 99999;
487                 return;
488         }
489         gettimeofday(&start, NULL);
490         /* Call the encoder until we've processed one second of time */
491         while(sofar < 1000) {
492                 f = t->sample();
493                 if (!f) {
494                         ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
495                         t->destroy(pvt);
496                         t->cost = 99999;
497                         return;
498                 }
499                 t->framein(pvt, f);
500                 ast_frfree(f);
501                 while((out = t->frameout(pvt))) {
502                         sofar += out->timelen;
503                         ast_frfree(out);
504                 }
505         }
506         gettimeofday(&finish, NULL);
507         t->destroy(pvt);
508         cost = (finish.tv_sec - start.tv_sec) * 1000 + (finish.tv_usec - start.tv_usec) / 1000;
509         t->cost = cost;
510 }
511
512 int ast_register_translator(struct ast_translator *t)
513 {
514         t->srcfmt = powerof(t->srcfmt);
515         t->dstfmt = powerof(t->dstfmt);
516         if ((t->srcfmt >= MAX_FORMAT) || (t->dstfmt >= MAX_FORMAT)) {
517                 ast_log(LOG_WARNING, "Format %d is larger than MAX_FORMAT\n", t->srcfmt);
518                 return -1;
519         }
520         calc_cost(t);
521         if (option_verbose > 1)
522                 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %d to %d, cost %d\n", t->name, t->srcfmt, t->dstfmt, t->cost);
523         pthread_mutex_lock(&list_lock);
524         t->next = list;
525         list = t;
526         rebuild_matrix();
527         pthread_mutex_unlock(&list_lock);
528         return 0;
529 }
530
531 int ast_unregister_translator(struct ast_translator *t)
532 {
533         struct ast_translator *u, *ul = NULL;
534         pthread_mutex_lock(&list_lock);
535         u = list;
536         while(u) {
537                 if (u == t) {
538                         if (ul)
539                                 ul->next = u->next;
540                         else
541                                 list = u->next;
542                         break;
543                 }
544                 u = u->next;
545         }
546         rebuild_matrix();
547         pthread_mutex_unlock(&list_lock);
548         return (u ? 0 : -1);
549 }
550
551 void ast_translator_destroy(struct ast_channel *trans)
552 {
553         char dummy;
554         int ms = 1000;
555         if (!trans->master) {
556                 ast_log(LOG_WARNING, "Translator is not part of a real channel?\n");
557                 return;
558         }
559         if (trans->master->trans != trans) {
560                 ast_log(LOG_WARNING, "Translator is not the right one!?!?\n");
561                 return;
562         }
563         trans->master->trans = NULL;
564         /* Write an invalid frame to kill off the main thread, which will
565            in turn acknowledge by writing an invalid frame back to us, unless
566            they're already closed.  */
567         if (trans->fd > -1) {
568                 if (write(trans->fd, trans, 1) == 1) {
569                         /* Wait for a respnose, but no more than 1 second */
570                         if (ast_waitfor_n_fd(&trans->fd, 1, &ms) == trans->fd)
571                                 read(trans->fd, &dummy, 1);
572                 }
573         }
574         if (option_verbose > 2)
575                 ast_verbose(VERBOSE_PREFIX_3 "Destroyed translator %s\n", trans->name);
576         close(trans->fd);
577         ast_channel_free(trans);
578 }
579
580 int ast_translator_best_choice(int dst, int srcs)
581 {
582         /* Calculate our best source format, given costs, and a desired destination */
583         int x;
584         int best=-1;
585         int besttime=999999999;
586         dst = powerof(dst);
587         pthread_mutex_lock(&list_lock);
588         for (x=0;x<MAX_FORMAT;x++) {
589                 if (tr_matrix[x][dst].step &&   /* There's a step */
590                     (tr_matrix[x][dst].cost < besttime) && /* We're better than what exists now */
591                         (srcs & (1 << x)))                      /* x is a valid source format */
592                         {
593                                 best = 1 << x;
594                                 besttime = tr_matrix[x][dst].cost;
595                         }
596                                 
597         }
598         pthread_mutex_unlock(&list_lock);
599         return best;
600 }