source: mediastreamer2/linphone/console/commands.c @ 256:70ad9c490986

Last change on this file since 256:70ad9c490986 was 256:70ad9c490986, checked in by smorlat <smorlat@…>, 4 years ago

linphonecsh and linphonec use a unix socket by default, for security reasons

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@259 3f6dc0c8-ddfe-455d-9043-3cd528dc4637

File size: 35.2 KB
Line 
1/****************************************************************************
2 *
3 *  $Id: commands.c,v 1.39 2008/07/03 15:08:34 smorlat Exp $
4 *
5 *  Copyright (C) 2006  Sandro Santilli <strk@keybit.net>
6 *  Copyright (C) 2004  Simon MORLAT <simon.morlat@linphone.org>
7 *
8****************************************************************************
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 *
24 ****************************************************************************/
25
26#include <string.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <errno.h>
30#include <limits.h>
31#include <ctype.h>
32#include <unistd.h>
33#include <linphonecore.h>
34#include "linphonec.h"
35
36/***************************************************************************
37 *
38 *  Forward declarations
39 *
40 ***************************************************************************/
41
42extern char *lpc_strip_blanks(char *input);
43
44/* Command handlers */
45static int lpc_cmd_help(LinphoneCore *, char *);
46static int lpc_cmd_proxy(LinphoneCore *, char *);
47static int lpc_cmd_call(LinphoneCore *, char *);
48static int lpc_cmd_answer(LinphoneCore *, char *);
49static int lpc_cmd_autoanswer(LinphoneCore *, char *);
50static int lpc_cmd_terminate(LinphoneCore *, char *);
51static int lpc_cmd_call_logs(LinphoneCore *, char *);
52static int lpc_cmd_ipv6(LinphoneCore *, char *);
53static int lpc_cmd_refer(LinphoneCore *, char *);
54static int lpc_cmd_quit(LinphoneCore *, char *);
55static int lpc_cmd_nat(LinphoneCore *, char *);
56static int lpc_cmd_stun(LinphoneCore *, char *);
57static int lpc_cmd_firewall(LinphoneCore *, char *);
58static int lpc_cmd_friend(LinphoneCore *, char*);
59static int lpc_cmd_soundcard(LinphoneCore *, char *);
60static int lpc_cmd_play(LinphoneCore *, char *);
61static int lpc_cmd_record(LinphoneCore *, char *);
62static int lpc_cmd_register(LinphoneCore *, char *);
63static int lpc_cmd_unregister(LinphoneCore *, char *);
64static int lpc_cmd_duration(LinphoneCore *lc, char *args);
65static int lpc_cmd_status(LinphoneCore *lc, char *args);
66
67/* Command handler helpers */
68static void linphonec_proxy_add(LinphoneCore *lc);
69static void linphonec_proxy_display(LinphoneProxyConfig *lc);
70static void linphonec_proxy_list(LinphoneCore *lc);
71static void linphonec_proxy_remove(LinphoneCore *lc, int index);
72static  int linphonec_proxy_use(LinphoneCore *lc, int index);
73static void linphonec_proxy_show(LinphoneCore *lc,int index);
74static void linphonec_friend_display(LinphoneFriend *fr);
75static int linphonec_friend_list(LinphoneCore *lc, char *arg);
76static void linphonec_display_command_help(LPC_COMMAND *cmd);
77static int linphonec_friend_call(LinphoneCore *lc, unsigned int num);
78static int linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr);
79static int linphonec_friend_delete(LinphoneCore *lc, int num);
80
81
82
83/* Command table management */
84static LPC_COMMAND *lpc_find_command(const char *name);
85
86void linphonec_out(const char *fmt,...);
87
88
89
90/***************************************************************************
91 *
92 *  Global variables
93 *
94 ***************************************************************************/
95
96/*
97 * Commands table.
98 */
99LPC_COMMAND commands[] = {
100        { "help", lpc_cmd_help, "Print commands help", NULL },
101        { "call", lpc_cmd_call, "Call a SIP uri",
102                "'call <sip-url>' or 'c <sip-url>' "
103                ": initiate a call to the specified destination."
104                },
105        { "terminate", lpc_cmd_terminate, "Terminate the current call",
106                NULL },
107        { "answer", lpc_cmd_answer, "Answer a call",
108                "Accept an incoming call."
109        },
110        { "autoanswer", lpc_cmd_autoanswer, "Enable auto-answer mode",
111                "'autoanswer enable'\t: enable autoanswer mode\n"
112                "'autoanswer disable'\t: disable autoanswer mode \n"},
113        { "proxy", lpc_cmd_proxy, "Manage proxies",
114                "'proxy list' : list all proxy setups.\n"
115                "'proxy add' : add a new proxy setup.\n"
116                "'proxy remove <index>' : remove proxy setup with number index.\n"
117                "'proxy use <index>' : use proxy with number index as default proxy.\n"
118                "'proxy unuse' : don't use a default proxy."
119                "'proxy show <index>' : show configuration and status of the proxy numbered by index.\n"
120                "'proxy show default' : show configuration and status of the default proxy.\n"
121        },
122        { "soundcard", lpc_cmd_soundcard, "Manage soundcards",
123                "'soundcard list' : list all sound devices.\n"
124                "'soundcard use <index>' : select a sound device.\n"
125                "'soundcard use files' : use .wav files instead of soundcard\n"
126        },
127        { "ipv6", lpc_cmd_ipv6, "Use IPV6",
128                "'ipv6 status' : show ipv6 usage status.\n"
129                "'ipv6 enable' : enable the use of the ipv6 network.\n"
130                "'ipv6 disable' : do not use ipv6 network."
131        },
132        { "refer", lpc_cmd_refer,
133                "Refer the current call to the specified destination.",
134                "'refer <sip-url>' or 'r <sip-url>' "
135                ": refer the current call to the specified destination."
136        },
137        { "nat", lpc_cmd_nat, "Set nat address",
138                "'nat'        : show nat settings.\n"
139                "'nat <addr>' : set nat address.\n"
140        },
141        { "stun", lpc_cmd_stun, "Set stun server address",
142                "'stun'        : show stun settings.\n"
143                "'stun <addr>' : set stun address.\n"
144        },
145        { "firewall", lpc_cmd_firewall, "Set ",
146                "'firewall'        : show current firewall policy.\n"
147                "'firewall none'   : use direct connection.\n"
148                "'firewall nat'    : use nat address given with the 'nat' command.\n"
149                "'firewall stun'   : use stun server given with the 'server' command.\n"
150        },
151        { "call-logs", lpc_cmd_call_logs, "Calls history",
152                NULL },
153        { "friend", lpc_cmd_friend, "Manage friends",
154                "'friend list [<pattern>]'    : list friends.\n"
155                "'friend call <index>'        : call a friend.\n"
156                "'friend add <name> <addr>'   : add friend, <name> must be quoted to include\n"
157            "                               spaces, <addr> has \"sip:\" added if it isn't\n"
158            "                               there.  Don't use '<' '>' around <addr>.\n"
159                "'friend delete <index>'      : remove friend, 'all' removes all\n"
160        },
161        { "play", lpc_cmd_play, "play from a wav file",
162                "This feature is available only in file mode (see 'help soundcard')\n"
163                "'play <wav file>'    : play a wav file."
164        },
165        { "record", lpc_cmd_record, "record to a wav file",
166                "This feature is available only in file mode (see 'help soundcard')\n"
167                "'record <wav file>'    : record into wav file."
168        },
169        { "quit", lpc_cmd_quit, "Exit linphonec", NULL },
170        { "register", lpc_cmd_register, "Register in one line to a proxy" , "register <sip identity> <sip proxy> <password>"},
171        { "unregister", lpc_cmd_unregister, "Unregister from default proxy", NULL       },
172        { "duration", lpc_cmd_duration, "Print duration in seconds of the last call.", NULL },
173        { "status", lpc_cmd_status, "Print various status information", 
174                        "'status register' \t: print status concerning registration\n"
175                        "'status autoanswer'\t: tell whether autoanswer mode is enabled\n"
176                        "'status hook' \t: print hook status\n" },
177                                       
178        { (char *)NULL, (lpc_cmd_handler)NULL, (char *)NULL, (char *)NULL }
179};
180
181/***************************************************************************
182 *
183 *  Public interface
184 *
185 ***************************************************************************/
186
187/*
188 * Main command dispatcher.
189 * WARNING: modifies second argument!
190 *
191 * Always return 1 currently.
192 */
193int
194linphonec_parse_command_line(LinphoneCore *lc, char *cl)
195{
196        char *ptr=cl;
197        char *args=NULL;
198        LPC_COMMAND *cmd;
199
200        /* Isolate first word and args */
201        while(*ptr && !isspace(*ptr)) ++ptr;
202        if (*ptr)
203        {
204                *ptr='\0';
205                /* set args to first nonblank */
206                args=ptr+1;
207                while(*args && isspace(*args)) ++args;
208        }
209
210        /* Handle DTMF */
211        if ( isdigit(*cl) || *cl == '#' || *cl == '*' )
212        {
213                while ( isdigit(*cl) || *cl == '#' || *cl == '*' )
214                {
215                        linphone_core_send_dtmf(lc, *cl);
216                        sleep(1); // be nice
217                        ++cl;
218                }
219
220                // discard spurious trailing chars
221                return 1;
222        }
223
224        /* Handle other kind of commands */
225        cmd=lpc_find_command(cl);
226        if ( !cmd )
227        {
228                linphonec_out("'%s': Cannot understand this.\n", cl);
229                return 1;
230        }
231
232        if ( ! cmd->func(lc, args) )
233        {
234                linphonec_out("Syntax error.\n");
235                linphonec_display_command_help(cmd);
236        }
237
238        return 1;
239}
240
241/*
242 * Generator function for command completion.
243 * STATE let us know whether to start from scratch;
244 * without any state (STATE==0), then we start at the
245 * top of the list.
246 */
247char *
248linphonec_command_generator(const char *text, int state)
249{
250        static int index, len;
251        char *name;
252
253        if ( ! state )
254        {
255                index=0;
256                len=strlen(text);
257        }
258
259        /*
260         * Return the next name which partially matches
261         * from the commands list
262         */
263        while ((name=commands[index].name))
264        {
265                ++index; /* so next call get next command */
266
267                if (strncmp(name, text, len) == 0)
268                {
269                        return strdup(name);
270                }
271        }
272
273        return NULL;
274}
275
276
277/***************************************************************************
278 *
279 *  Command handlers
280 *
281 ***************************************************************************/
282
283static int
284lpc_cmd_help(LinphoneCore *lc, char *arg)
285{
286        int i=0;
287        LPC_COMMAND *cmd;
288
289        if (!arg || !*arg)
290        {
291                linphonec_out("Commands are:\n");
292                linphonec_out("---------------------------\n");
293
294                while (commands[i].help)
295                {
296                        linphonec_out("%10.10s\t%s\n", commands[i].name,
297                                commands[i].help);
298                        i++;
299                }
300               
301                linphonec_out("---------------------------\n");
302                linphonec_out("Type 'help <command>' for more details.\n");
303
304                return 1;
305        }
306
307        cmd=lpc_find_command(arg);
308        if ( !cmd )
309        {
310                linphonec_out("No such command.\n");
311                return 1;
312        }
313
314        linphonec_display_command_help(cmd);
315        return 1;
316
317}
318
319static char callee_name[256]={0};
320
321static int
322lpc_cmd_call(LinphoneCore *lc, char *args)
323{
324        if ( ! args || ! *args )
325        {
326                return 0;
327        }
328
329        if ( lc->call != NULL )
330        {
331                linphonec_out("Terminate current call first.\n");
332        }
333        else
334        {
335                if ( -1 == linphone_core_invite(lc, args) )
336                {
337                        linphonec_out("Error from linphone_core_invite.\n");
338                }
339                else
340                {
341                        snprintf(callee_name,sizeof(callee_name),"%s",args);
342                }
343        }
344        return 1;
345}
346
347static const char *linphonec_get_callee(){
348        return callee_name;
349}
350
351static int
352lpc_cmd_refer(LinphoneCore *lc, char *args)
353{
354        if (args)
355                linphone_core_refer(lc, args);
356        else{
357                linphonec_out("refer needs an argument\n");
358        }
359        return 1;
360}
361
362static int
363lpc_cmd_terminate(LinphoneCore *lc, char *args)
364{
365        if ( -1 == linphone_core_terminate_call(lc, NULL) )
366        {
367                linphonec_out("No active call.\n");
368        }
369        return 1;
370}
371
372static int
373lpc_cmd_answer(LinphoneCore *lc, char *args)
374{
375        if ( -1 == linphone_core_accept_call(lc, NULL) )
376        {
377                linphonec_out("No incoming call.\n");
378        }
379        return 1;
380}
381
382static int
383lpc_cmd_autoanswer(LinphoneCore *lc, char *args)
384{
385        if (strstr(args,"enable")){
386                linphonec_set_autoanswer(TRUE);
387        }else if (strstr(args,"disable")){
388                linphonec_set_autoanswer(FALSE);
389        }else return 0;
390        return 1;
391}
392
393static int
394lpc_cmd_quit(LinphoneCore *lc, char *args)
395{
396        linphonec_finish(EXIT_SUCCESS);
397        return 1;
398}
399
400static int
401lpc_cmd_nat(LinphoneCore *lc, char *args)
402{
403        bool_t use;
404        const char *nat;
405
406        if ( args ) args=lpc_strip_blanks(args);
407
408        if ( args && *args )
409        {
410                linphone_core_set_nat_address(lc, args);
411                /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS); */
412        }
413
414        nat = linphone_core_get_nat_address(lc);
415        use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_NAT_ADDRESS;
416        linphonec_out("Nat address: %s%s\n", nat ? nat : "unspecified" , use ? "" : " (disabled - use 'firewall nat' to enable)");
417
418        return 1;
419}
420
421static int
422lpc_cmd_stun(LinphoneCore *lc, char *args)
423{
424        bool_t use;
425        const char *stun;
426
427        if ( args ) args=lpc_strip_blanks(args);
428
429        if ( args && *args )
430        {
431                linphone_core_set_stun_server(lc, args);
432                /* linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN); */
433        }
434
435        stun = linphone_core_get_stun_server(lc);
436        use = linphone_core_get_firewall_policy(lc)==LINPHONE_POLICY_USE_STUN;
437        linphonec_out("Stun server: %s%s\n", stun ? stun : "unspecified" , use? "" : " (disabled - use 'firewall stun' to enable)");
438
439        return 1;
440}
441
442static int
443lpc_cmd_firewall(LinphoneCore *lc, char *args)
444{
445        const char* setting=NULL;
446
447        if ( args ) args=lpc_strip_blanks(args);
448
449        if ( args && *args )
450        {
451                if (strcmp(args,"none")==0)
452                {
453                        linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_NO_FIREWALL);
454                }
455                else if (strcmp(args,"stun")==0)
456                {
457                        setting = linphone_core_get_stun_server(lc);
458                        if ( ! setting )
459                        {
460                                linphonec_out("No stun server address is defined, use 'stun <address>' first");
461                                return 1;
462                        }
463                        linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_STUN);
464                }
465                else if (strcmp(args,"nat")==0)
466                {
467                        setting = linphone_core_get_nat_address(lc);
468                        if ( ! setting )
469                        {
470                                linphonec_out("No nat address is defined, use 'nat <address>' first");
471                                return 1;
472                        }
473                        linphone_core_set_firewall_policy(lc,LINPHONE_POLICY_USE_NAT_ADDRESS);
474                }
475        }
476
477        switch(linphone_core_get_firewall_policy(lc))
478        {
479                case LINPHONE_POLICY_NO_FIREWALL:
480                        linphonec_out("No firewall\n");
481                        break;
482                case LINPHONE_POLICY_USE_STUN:
483                        linphonec_out("Using stun server %s to discover firewall address\n", setting ? setting : linphone_core_get_stun_server(lc));
484                        break;
485                case LINPHONE_POLICY_USE_NAT_ADDRESS:
486                        linphonec_out("Using supplied nat address %s.\n", setting ? setting : linphone_core_get_nat_address(lc));
487                        break;
488        }
489        return 1;
490}
491
492/* Helper function for processing freind names */
493static int
494lpc_friend_name(char **args, char **name)
495{
496        /* Use space as a terminator unless quoted */
497        if (('"' == **args) || ('\'' == **args)){
498                char *end;
499                char delim = **args;
500                (*args)++;
501                end = (*args);
502                while ((delim != *end) && ('\0' != *end)) end++;
503                if ('\0' == *end) {
504                        fprintf(stderr, "Mismatched quotes\n");
505                        return 0;
506                }
507                *name = *args;
508                *end = '\0';
509                *args = ++end;
510        } else {
511                *name = strsep(args, " ");
512               
513                if (NULL == *args) { /* Means there was no separator */
514                        fprintf(stderr, "Either name or address is missing\n");
515                        return 0;
516                }
517                if (NULL == *name) return 0;
518        }
519        return 1;
520}
521
522static int
523lpc_cmd_friend(LinphoneCore *lc, char *args)
524{
525        int friend_num;
526
527        if ( args ) args=lpc_strip_blanks(args);
528
529        if ( ! args || ! *args ) return 0;
530
531        if ( !strncmp(args, "list", 4) )
532        {
533                return linphonec_friend_list(lc, args+4);
534                return 1;
535        }
536        else if ( !strncmp(args, "call", 4) )
537        {
538                args+=4;
539                if ( ! *args ) return 0;
540                friend_num = strtol(args, NULL, 10);
541                if ( errno == ERANGE ) {
542                        linphonec_out("Invalid friend number\n");
543                        return 0;
544                }
545                linphonec_friend_call(lc, friend_num);
546                return 1;
547        }
548        else if ( !strncmp(args, "delete", 6) )
549        {
550                args+=6;
551                if ( ! *args ) return 0;
552                while (*args == ' ') args++;
553                if ( ! *args ) return 0;
554                if (!strncmp(args, "all", 3))
555                {
556                        friend_num = -1;
557                } 
558                else
559                {
560                        friend_num = strtol(args, NULL, 10);
561                        if ( errno == ERANGE ) {
562                                linphonec_out("Invalid friend number\n");
563                                return 0;
564                        }
565                }
566                linphonec_friend_delete(lc, friend_num);
567                return 1;
568        }
569        else if ( !strncmp(args, "add", 3) )
570        {
571                char  *name;
572                char  addr[80];
573                char *addr_p = addr;
574                char *addr_orig;
575
576                args+=3;
577                if ( ! *args ) return 0;
578                while (*args == ' ') args++;
579                if ( ! *args ) return 0;
580                if (!lpc_friend_name(&args,  &name)) return 0;
581
582                while (*args == ' ') args++;
583                if ( ! *args ) return 0;
584                if (isdigit(*args)) {
585                        strcpy (addr, "sip:");
586                        addr_p = addr + strlen("sip:");
587                }
588                addr_orig = strsep(&args, " ");
589                if (1 >= strlen(addr_orig)) {
590                        fprintf(stderr, "A single-digit address is not valid\n");
591                        return 0;
592                }
593                strcpy(addr_p, addr_orig);
594                linphonec_friend_add(lc, name, addr);
595                return 1;
596        }
597        return 0;
598}
599
600static int lpc_cmd_play(LinphoneCore *lc, char *args){
601        if ( args ) args=lpc_strip_blanks(args);
602        if ( ! args || ! *args ) return 0;
603        linphone_core_set_play_file(lc,args);
604        return 1;
605}
606
607static int lpc_cmd_record(LinphoneCore *lc, char *args){
608        if ( args ) args=lpc_strip_blanks(args);
609        if ( ! args || ! *args ) return 0;
610        linphone_core_set_record_file(lc,args);
611        return 1;
612}
613
614/*
615 * Modified input
616 */
617static int
618lpc_cmd_proxy(LinphoneCore *lc, char *args)
619{
620        char *arg1 = args;
621        char *arg2 = NULL;
622        char *ptr = args;
623        int proxynum;
624
625        if ( ! arg1 ) return 0;
626
627        /* Isolate first and second arg */
628        while(*ptr && !isspace(*ptr)) ++ptr;
629        if ( *ptr )
630        {
631                *ptr='\0';
632                arg2=ptr+1;
633                while(*arg2 && isspace(*arg2)) ++arg2;
634        }
635
636        if (strcmp(arg1,"add")==0)
637        {
638#ifdef HAVE_READLINE
639                rl_inhibit_completion=1;
640#endif
641                linphonec_proxy_add(lc);
642#ifdef HAVE_READLINE
643                rl_inhibit_completion=0;
644#endif
645        }
646        else if (strcmp(arg1,"list")==0)
647        {
648                linphonec_proxy_list(lc);
649        }
650        else if (strcmp(arg1,"remove")==0)
651        {
652                linphonec_proxy_remove(lc,atoi(arg2));
653        }
654        else if (strcmp(arg1,"use")==0)
655        {
656                if ( arg2 && *arg2 )
657                {
658                        proxynum=atoi(arg2);
659                        if ( linphonec_proxy_use(lc, proxynum) )
660                                linphonec_out("Default proxy set to %d.\n", proxynum);
661                }
662                else
663                {
664                        proxynum=linphone_core_get_default_proxy(lc, NULL);
665                        if ( proxynum == -1 ) linphonec_out("No default proxy.\n");
666                        else linphonec_out("Current default proxy is %d.\n", proxynum);
667                }
668        }else if (strcmp(arg1, "unuse")==0){
669                linphone_core_set_default_proxy(lc, NULL);
670                linphonec_out("Use no proxy.\n");
671        }else if (strcmp(arg1,"show")==0){
672                if (arg2 && *arg2){
673                        if (strstr(arg2,"default")==0){
674                                proxynum=linphone_core_get_default_proxy(lc, NULL);
675                                linphonec_proxy_show(lc,proxynum);
676                        }else linphonec_proxy_show(lc,atoi(arg2));
677                }
678        }else
679        {
680                linphonec_out("Syntax error - see 'help proxy'\n");
681        }
682
683        return 1;
684}
685
686static int
687lpc_cmd_call_logs(LinphoneCore *lc, char *args)
688{
689        MSList *elem=linphone_core_get_call_logs(lc);
690        for (;elem!=NULL;elem=ms_list_next(elem))
691        {
692                LinphoneCallLog *cl=(LinphoneCallLog*)elem->data;
693                char *str=linphone_call_log_to_str(cl);
694                linphonec_out("%s\n",str);
695                ms_free(str);
696        }
697        return 1;
698}
699
700static int
701lpc_cmd_ipv6(LinphoneCore *lc, char *arg1)
702{
703        if ( ! arg1 )
704        {
705                linphonec_out("Syntax error - see 'help ipv6'\n");
706                return 1;
707        }
708
709        if (strcmp(arg1,"status")==0)
710        {
711                linphonec_out("ipv6 use enabled: %s\n",linphone_core_ipv6_enabled(lc) ? "true":"false");
712        }
713        else if (strcmp(arg1,"enable")==0)
714        {
715                linphone_core_enable_ipv6(lc,TRUE);
716                linphonec_out("ipv6 use enabled.\n");
717        }
718        else if (strcmp(arg1,"disable")==0)
719        {
720                linphone_core_enable_ipv6(lc,FALSE);
721                linphonec_out("ipv6 use disabled.\n");
722        }
723        else
724        {
725                linphonec_out("Syntax error - see 'help ipv6'\n");
726        }
727        return 1;
728}
729
730static int lpc_cmd_soundcard(LinphoneCore *lc, char *cmd){
731        int i;
732        if (cmd==NULL){
733                linphonec_out("Syntax error - see 'help soundcard'\n");
734                return 1;
735        }
736        if (strcmp(cmd,"list")==0){
737                const char **dev=linphone_core_get_sound_devices(lc);
738                for(i=0;dev[i]!=NULL;i++){
739                        linphonec_out("%i: %s\n",i,dev[i]);
740                }
741                return 1;
742        }else{
743                char *tmp=alloca(strlen(cmd)+1);
744                char *card=alloca(strlen(cmd)+1);
745                int index;
746                int n=sscanf(cmd,"%s %s",tmp,card);
747                if (n==2 && strcmp(tmp,"use")==0){
748                        if (strcmp(card,"files")==0) {
749                                linphonec_out("Using wav files instead of soundcard.\n");
750                                linphone_core_use_files(lc,TRUE);
751                                return 1;
752                        }else{
753                                const char **dev=linphone_core_get_sound_devices(lc);
754                                index=atoi(card);
755                                for(i=0;dev[i]!=NULL;i++){
756                                        if (i==index){
757                                                linphone_core_set_ringer_device(lc,dev[i]);
758                                                linphone_core_set_playback_device(lc,dev[i]);
759                                                linphone_core_set_capture_device(lc,dev[i]);
760                                                linphonec_out("Using sound device %s\n",dev[i]);
761                                                return 1;
762                                        }
763                                }
764                                linphonec_out("no such sound device\n");
765                                return 1;
766                        }
767                }
768                linphonec_out("Syntax error - see 'help soundcard'\n");
769        }
770        return 1;
771}
772
773/***************************************************************************
774 *
775 *  Commands helper functions
776 *
777 ***************************************************************************/
778
779
780static void
781linphonec_proxy_add(LinphoneCore *lc)
782{
783        bool_t enable_register=FALSE;
784        LinphoneProxyConfig *cfg;
785
786        linphonec_out("Adding new proxy setup. Hit ^D to abort.\n");
787
788        /*
789         * SIP Proxy address
790         */
791        while (1)
792        {
793                char *input=linphonec_readline("Enter proxy sip address: ");
794                char *clean;
795
796                if ( ! input ) {
797                        linphonec_out("Aborted.\n");
798                        return;
799                }
800
801                /* Strip blanks */
802                clean=lpc_strip_blanks(input);
803                if ( ! *clean ) {
804                        free(input);
805                        continue;
806                }
807
808                cfg=linphone_proxy_config_new();
809                if (linphone_proxy_config_set_server_addr(cfg,clean)<0)
810                {
811                        linphonec_out("Invalid sip address (sip:sip.domain.tld).\n");
812                        free(input);
813                        linphone_proxy_config_destroy(cfg);
814                        continue;
815                }
816                free(input);
817                break;
818        }
819
820        /*
821         * SIP Proxy identity
822         */
823        while (1)
824        {
825                char *input=linphonec_readline("Your identity for this proxy: ");
826                char *clean;
827
828                if ( ! input ) {
829                        linphonec_out("Aborted.\n");
830                        linphone_proxy_config_destroy(cfg);
831                        return;
832                }
833
834                /* Strip blanks */
835                clean=lpc_strip_blanks(input);
836                if ( ! *clean ) {
837                        free(input);
838                        continue;
839                }
840
841                linphone_proxy_config_set_identity(cfg, clean);
842                if ( ! cfg->reg_identity )
843                {
844                        linphonec_out("Invalid identity (sip:name@sip.domain.tld).\n");
845                        free(input);
846                        continue;
847                }
848                free(input);
849                break;
850        }
851
852        /*
853         * SIP Proxy enable register
854         */
855        while (1)
856        {
857                char *input=linphonec_readline("Do you want to register on this proxy (yes/no): ");
858                char *clean;
859
860                if ( ! input ) {
861                        linphonec_out("Aborted.\n");
862                        linphone_proxy_config_destroy(cfg);
863                        return;
864                }
865
866                /* Strip blanks */
867                clean=lpc_strip_blanks(input);
868                if ( ! *clean ) {
869                        free(input);
870                        continue;
871                }
872
873                if ( ! strcmp(clean, "yes") ) enable_register=TRUE;
874                else if ( ! strcmp(clean, "no") ) enable_register=FALSE;
875                else {
876                        linphonec_out("Please answer with 'yes' or 'no'\n");
877                        free(input);
878                        continue;
879                }
880                linphone_proxy_config_enableregister(cfg, enable_register);
881                free(input);
882                break;
883        }
884
885        /*
886         * SIP Proxy registration expiration
887         */
888        if ( enable_register==TRUE )
889        {
890                long int expires=0;
891                while (1)
892                {
893                        char *input=linphonec_readline("Specify register expiration time"
894                                " in seconds (default is 600): ");
895
896                        if ( ! input ) {
897                                linphonec_out("Aborted.\n");
898                                linphone_proxy_config_destroy(cfg);
899                                return;
900                        }
901
902                        expires=strtol(input, (char **)NULL, 10);
903                        if ( expires == LONG_MIN || expires == LONG_MAX )
904                        {
905                                linphonec_out("Invalid value: %s\n", strerror(errno));
906                                free(input);
907                                continue;
908                        }
909
910                        linphone_proxy_config_expires(cfg, expires);
911                        linphonec_out("Expiration: %d seconds\n", cfg->expires);
912
913                        free(input);
914                        break;
915                }
916        }
917
918        /*
919         * SIP proxy route
920         */
921        while (1)
922        {
923                char *input=linphonec_readline("Specify route if needed: ");
924                char *clean;
925
926                if ( ! input ) {
927                        linphonec_out("Aborted.\n");
928                        linphone_proxy_config_destroy(cfg);
929                        return;
930                }
931
932                /* Strip blanks */
933                clean=lpc_strip_blanks(input);
934                if ( ! *clean ) {
935                        free(input);
936                        linphonec_out("No route specified.\n");
937                        break;
938                }
939
940                linphone_proxy_config_set_route(cfg, clean);
941                if ( ! cfg->reg_route )
942                {
943                        linphonec_out("Invalid route.\n");
944                        free(input);
945                        continue;
946                }
947
948                free(input);
949                break;
950        }
951
952        /*
953         * Final confirmation
954         */
955        while (1)
956        {
957                char *input;
958                char *clean;
959
960                linphonec_out("--------------------------------------------\n");
961                linphonec_proxy_display(cfg);
962                linphonec_out("--------------------------------------------\n");
963                input=linphonec_readline("Accept the above proxy configuration (yes/no) ?: ");
964
965
966                if ( ! input ) {
967                        linphonec_out("Aborted.\n");
968                        linphone_proxy_config_destroy(cfg);
969                        return;
970                }
971
972                /* Strip blanks */
973                clean=lpc_strip_blanks(input);
974                if ( ! *clean ) {
975                        free(input);
976                        continue;
977                }
978
979                if ( ! strcmp(clean, "yes") ) break;
980                else if ( ! strcmp(clean, "no") )
981                {
982                        linphonec_out("Declined.\n");
983                        linphone_proxy_config_destroy(cfg);
984                        free(input);
985                        return;
986                }
987
988                linphonec_out("Please answer with 'yes' or 'no'\n");
989                free(input);
990                continue;
991        }
992
993
994        linphone_core_add_proxy_config(lc,cfg);
995
996        /* automatically set the last entered proxy as the default one */
997        linphone_core_set_default_proxy(lc,cfg);
998
999        linphonec_out("Proxy added.\n");
1000}
1001
1002static void
1003linphonec_proxy_display(LinphoneProxyConfig *cfg)
1004{
1005        linphonec_out("sip address: %s\nroute: %s\nidentity: %s\nregister: %s\nexpires: %i\nregistered: %s\n",
1006                        cfg->reg_proxy,
1007                        (cfg->reg_route!=NULL)?cfg->reg_route:"",
1008                        (cfg->reg_identity!=NULL)?cfg->reg_identity:"",
1009                        (cfg->reg_sendregister)?"yes":"no",
1010                        cfg->expires,
1011                        linphone_proxy_config_is_registered(cfg) ? "yes" : "no");
1012}
1013
1014static void linphonec_proxy_show(LinphoneCore *lc, int index){
1015        const MSList *elem;
1016        int i;
1017        for(elem=linphone_core_get_proxy_config_list(lc),i=0;elem!=NULL;elem=elem->next,++i){
1018                if (index==i){
1019                        LinphoneProxyConfig *cfg=(LinphoneProxyConfig *)elem->data;
1020                        linphonec_proxy_display(cfg);
1021                        return;
1022                }
1023        }
1024        linphonec_out("No proxy with index %i",index);
1025}
1026
1027static void
1028linphonec_proxy_list(LinphoneCore *lc)
1029{
1030        const MSList *proxies;
1031        int n;
1032        int def=linphone_core_get_default_proxy(lc,NULL);
1033       
1034        proxies=linphone_core_get_proxy_config_list(lc);
1035        for(n=0;proxies!=NULL;proxies=ms_list_next(proxies),n++){
1036                if (n==def)
1037                        linphonec_out("****** Proxy %i - this is the default one - *******\n",n);
1038                else 
1039                        linphonec_out("****** Proxy %i *******\n",n);
1040                linphonec_proxy_display((LinphoneProxyConfig*)proxies->data);
1041        }
1042}
1043
1044static void
1045linphonec_proxy_remove(LinphoneCore *lc, int index)
1046{
1047        const MSList *proxies;
1048        LinphoneProxyConfig *cfg;
1049        proxies=linphone_core_get_proxy_config_list(lc);
1050        cfg=(LinphoneProxyConfig*)ms_list_nth_data(proxies,index);
1051        if (cfg==NULL){
1052                linphonec_out("No such proxy.\n");
1053                return;
1054        }
1055        linphone_core_remove_proxy_config(lc,cfg);
1056        linphonec_out("Proxy %s removed.\n", cfg->reg_proxy);
1057        linphone_proxy_config_destroy(cfg);
1058}
1059
1060static int
1061linphonec_proxy_use(LinphoneCore *lc, int index)
1062{
1063        const MSList *proxies;
1064        LinphoneProxyConfig *cfg;
1065        proxies=linphone_core_get_proxy_config_list(lc);
1066        cfg=(LinphoneProxyConfig*)ms_list_nth_data(proxies,index);
1067        if (cfg==NULL){
1068                linphonec_out("No such proxy (try 'proxy list').");
1069                return 0;
1070        }
1071        linphone_core_set_default_proxy(lc,cfg);
1072        return 1;
1073}
1074
1075static void
1076linphonec_friend_display(LinphoneFriend *fr)
1077{
1078        char *name = linphone_friend_get_name(fr);
1079        char *addr = linphone_friend_get_addr(fr);
1080        //char *url = linphone_friend_get_url(fr);
1081
1082        linphonec_out("name: %s\n", name);
1083        linphonec_out("address: %s\n", addr);
1084}
1085
1086static int
1087linphonec_friend_list(LinphoneCore *lc, char *pat)
1088{
1089        const MSList *friend;
1090        int n;
1091
1092        if (pat) {
1093                pat=lpc_strip_blanks(pat);
1094                if (!*pat) pat = NULL;
1095        }
1096
1097        friend = linphone_core_get_friend_list(lc);
1098        for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1099        {
1100                if ( pat ) {
1101                        char *name = linphone_friend_get_name(friend->data);
1102                        if ( ! strstr(name, pat) ) continue;
1103                }
1104                linphonec_out("****** Friend %i *******\n",n);
1105                linphonec_friend_display((LinphoneFriend*)friend->data);
1106        }
1107
1108        return 1;
1109}
1110
1111static int
1112linphonec_friend_call(LinphoneCore *lc, unsigned int num)
1113{
1114        const MSList *friend = linphone_core_get_friend_list(lc);
1115        unsigned int n;
1116        char *addr;
1117
1118        for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1119        {
1120                if ( n == num )
1121                {
1122                        addr = linphone_friend_get_addr(friend->data);
1123                        return lpc_cmd_call(lc, addr);
1124                }
1125        }
1126        linphonec_out("No such friend %u\n", num);
1127        return 1;
1128}
1129
1130static int
1131linphonec_friend_add(LinphoneCore *lc, const char *name, const char *addr)
1132{
1133        LinphoneFriend *newFriend;
1134
1135        char url[PATH_MAX];
1136
1137        snprintf(url, PATH_MAX, "%s <%s>", name, addr);
1138        newFriend = linphone_friend_new_with_addr(url);
1139        linphone_core_add_friend(lc, newFriend);
1140        return 0;
1141}
1142
1143static int
1144linphonec_friend_delete(LinphoneCore *lc, int num)
1145{
1146        const MSList *friend = linphone_core_get_friend_list(lc);
1147        unsigned int n;
1148
1149        for(n=0; friend!=NULL; friend=ms_list_next(friend), ++n )
1150        {
1151                if ( n == num )
1152                {
1153                        linphone_core_remove_friend(lc, friend->data);
1154                        return 0;
1155                }
1156        }
1157
1158        if (-1 == num) 
1159        {
1160                unsigned int i;
1161                for (i = 0 ; i < n ; i++)
1162                        linphonec_friend_delete(lc, 0);
1163                return 0;
1164        }
1165
1166        linphonec_out("No such friend %u\n", num);
1167        return 1;
1168}
1169
1170static void
1171linphonec_display_command_help(LPC_COMMAND *cmd)
1172{
1173        if ( cmd->doc ) linphonec_out ("%s\n", cmd->doc);
1174        else linphonec_out("%s\n", cmd->help);
1175}
1176
1177
1178static int lpc_cmd_register(LinphoneCore *lc, char *args){
1179        char identity[512];
1180        char proxy[512];
1181        char passwd[512];
1182        LinphoneProxyConfig *cfg;
1183        const MSList *elem;
1184        passwd[0]=proxy[0]=identity[0]='\0';
1185        sscanf(args,"%s %s %s",identity,proxy,passwd);
1186        if (proxy[0]=='\0' || identity[0]=='\0'){
1187                linphonec_out("Missing parameters, see help register\n");
1188                return 1;
1189        }
1190        if (passwd[0]!='\0'){
1191                osip_from_t *from;
1192                LinphoneAuthInfo *info;
1193                osip_from_init(&from);
1194                if (osip_from_parse(from,identity)==0){
1195                        info=linphone_auth_info_new(from->url->username,NULL,passwd,NULL,NULL);
1196                        linphone_core_add_auth_info(lc,info);
1197                }
1198                osip_from_free(from);
1199        }
1200        elem=linphone_core_get_proxy_config_list(lc);
1201        if (elem) {
1202                cfg=(LinphoneProxyConfig*)elem->data;
1203                linphone_proxy_config_edit(cfg);
1204        }
1205        else cfg=linphone_proxy_config_new();
1206        linphone_proxy_config_set_identity(cfg,identity);
1207        linphone_proxy_config_set_server_addr(cfg,proxy);
1208        linphone_proxy_config_enable_register(cfg,TRUE);
1209        if (elem) linphone_proxy_config_done(cfg);
1210        else linphone_core_add_proxy_config(lc,cfg);
1211        linphone_core_set_default_proxy(lc,cfg);
1212        return 1;
1213}
1214
1215static int lpc_cmd_unregister(LinphoneCore *lc, char *args){
1216        LinphoneProxyConfig *cfg=NULL;
1217        linphone_core_get_default_proxy(lc,&cfg);
1218        if (cfg && linphone_proxy_config_is_registered(cfg)) {
1219                linphone_proxy_config_edit(cfg);
1220                linphone_proxy_config_enable_register(cfg,FALSE);
1221                linphone_proxy_config_done(cfg);
1222        }else{
1223                linphonec_out("unregistered\n");
1224        }
1225        return 1;
1226}
1227
1228static int lpc_cmd_duration(LinphoneCore *lc, char *args){
1229        LinphoneCallLog *cl;
1230        const MSList *elem=linphone_core_get_call_logs(lc);
1231        for(;elem!=NULL;elem=elem->next){
1232                if (elem->next==NULL){
1233                        cl=(LinphoneCallLog*)elem->data;
1234                        linphonec_out("%i seconds\n",cl->duration);
1235                }
1236        }
1237        return 1;
1238}
1239
1240static int lpc_cmd_status(LinphoneCore *lc, char *args){
1241        LinphoneProxyConfig *cfg;
1242        linphone_core_get_default_proxy(lc,&cfg);
1243        if (strstr(args,"register")){
1244                if (cfg){
1245                        if (linphone_proxy_config_is_registered(cfg)){
1246                                linphonec_out("registered, identity=%s duration=%i\n",
1247                                        linphone_proxy_config_get_identity(cfg),
1248                                        linphone_proxy_config_get_expires(cfg));
1249                        }else if (linphone_proxy_config_register_enabled(cfg)){
1250                                linphonec_out("registered=-1\n");
1251                        }else linphonec_out("registered=0\n");
1252                }else linphonec_out("registered=0\n");
1253        }else if (strstr(args,"autoanswer")){
1254                if (cfg && linphone_proxy_config_is_registered(cfg))
1255                        linphonec_out("autoanswer=%i\n",linphonec_get_autoanswer());
1256                else linphonec_out("unregistered\n");
1257        }else if (strstr(args,"hook")){
1258                gstate_t call_state=linphone_core_get_state(lc,GSTATE_GROUP_CALL);
1259                if (!cfg || !linphone_proxy_config_is_registered(cfg)){
1260                        linphonec_out("unregistered\n");
1261                        return 1;
1262                }
1263                switch(call_state){
1264                        case GSTATE_CALL_OUT_INVITE:
1265                                linphonec_out("hook=dialing\n");
1266                        break;
1267                        case GSTATE_CALL_IDLE:
1268                                linphonec_out("hook=offhook\n");
1269                        break;
1270                        case GSTATE_CALL_OUT_CONNECTED:
1271                                linphonec_out("Call out, hook=%s duration=%i\n", linphonec_get_callee(),
1272                                        linphone_core_get_current_call_duration(lc));
1273                        break;
1274                        case GSTATE_CALL_IN_CONNECTED:
1275                                linphonec_out("hook=answered duration=%i\n" ,
1276                                        linphone_core_get_current_call_duration(lc));
1277                        default:
1278                                break;
1279                }
1280               
1281        }else return 0;
1282        return 1;
1283}
1284
1285/***************************************************************************
1286 *
1287 *  Command table management funx
1288 *
1289 ***************************************************************************/
1290
1291/*
1292 * Find a command given its name
1293 */
1294static LPC_COMMAND *
1295lpc_find_command(const char *name)
1296{
1297        int i;
1298
1299        for (i=0; commands[i].name; ++i)
1300        {
1301                if (strcmp(name, commands[i].name) == 0)
1302                        return &commands[i];
1303        }
1304
1305        return (LPC_COMMAND *)NULL;
1306}
1307
1308
1309/****************************************************************************
1310 *
1311 * $Log: commands.c,v $
1312 * Revision 1.39  2008/07/03 15:08:34  smorlat
1313 * api cleanups, interface in progress.
1314 *
1315 * Revision 1.38  2008/06/17 20:38:59  smorlat
1316 * added missing file.
1317 *
1318 * Revision 1.37  2008/04/09 09:26:00  smorlat
1319 * merge various patches
1320 * H264 support.
1321 *
1322 * Revision 1.36  2007/08/01 14:47:53  strk
1323 *         * console/commands.c: Clean up commands 'nat', 'stun'
1324 *           and 'firewall' to be more intuitive.
1325 *
1326 * Revision 1.35  2007/06/27 09:01:25  smorlat
1327 * logging improvements.
1328 *
1329 * Revision 1.34  2007/02/20 10:17:13  smorlat
1330 * linphonec friends patch2
1331 *
1332 * Revision 1.31  2006/09/22 07:22:47  smorlat
1333 * linphonecore api changes.
1334 *
1335 * Revision 1.30  2006/09/08 15:32:57  smorlat
1336 * support for using files instead of soundcard (used by linphonec only)
1337 *
1338 * Revision 1.29  2006/08/28 14:29:07  smorlat
1339 * fix bug.
1340 *
1341 * Revision 1.28  2006/08/21 12:49:59  smorlat
1342 * merged several little patches.
1343 *
1344 * Revision 1.27  2006/07/17 18:45:00  smorlat
1345 * support for several event queues in ortp.
1346 * glib dependency removed from coreapi/ and console/
1347 *
1348 * Revision 1.26  2006/04/14 15:16:36  smorlat
1349 * soundcard use did nothing !
1350 *
1351 * Revision 1.25  2006/04/06 20:09:33  smorlat
1352 * add linphonec command to see and select sound devices.
1353 *
1354 * Revision 1.24  2006/03/04 11:17:10  smorlat
1355 * mediastreamer2 in progress.
1356 *
1357 * Revision 1.23  2006/02/20 21:14:01  strk
1358 * Handled syntax errors with 'friend' command
1359 *
1360 * Revision 1.22  2006/02/20 10:20:29  strk
1361 * Added substring-based filter support for command 'friend list'
1362 *
1363 * Revision 1.21  2006/02/02 15:39:18  strk
1364 * - Added 'friend list' and 'friend call' commands
1365 * - Allowed for multiple DTFM send in a single line
1366 * - Added status-specific callback (bare version)
1367 *
1368 * Revision 1.20  2006/01/26 11:54:34  strk
1369 * More robust 'nat' command handler (strip blanks in args)
1370 *
1371 * Revision 1.19  2006/01/26 09:48:05  strk
1372 * Added limits.h include
1373 *
1374 * Revision 1.18  2006/01/26 02:18:05  strk
1375 * Added new commands 'nat use' and 'nat unuse'.
1376 * These will required a pending patch to linphonecore.c
1377 * in order to work.
1378 *
1379 * Revision 1.17  2006/01/20 14:12:33  strk
1380 * Added linphonec_init() and linphonec_finish() functions.
1381 * Handled SIGINT and SIGTERM to invoke linphonec_finish().
1382 * Handling of auto-termination (-t) moved to linphonec_finish().
1383 * Reworked main (input read) loop to not rely on 'terminate'
1384 * and 'run' variable (dropped). configfile_name allocated on stack
1385 * using PATH_MAX limit. Changed print_usage signature to allow
1386 * for an exit_status specification.
1387 *
1388 * Revision 1.16  2006/01/18 09:25:32  strk
1389 * Command completion inhibited in proxy addition and auth request prompts.
1390 * Avoided use of linphonec_readline's internal filename completion.
1391 *
1392 * Revision 1.15  2006/01/14 13:29:32  strk
1393 * Reworked commands interface to use a table structure,
1394 * used by command line parser and help function.
1395 * Implemented first level of completion (commands).
1396 * Added notification of invalid "answer" and "terminate"
1397 * commands (no incoming call, no active call).
1398 * Forbidden "call" intialization when a call is already active.
1399 * Cleaned up all commands, adding more feedback and error checks.
1400 *
1401 * Revision 1.14  2006/01/13 13:00:29  strk
1402 * Added linphonec.h. Code layout change (added comments, forward decl,
1403 * globals on top, copyright notices and Logs). Handled out-of-memory
1404 * condition on history management. Removed assumption on sizeof(char).
1405 * Fixed bug in authentication prompt (introduced by linphonec_readline).
1406 * Added support for multiple authentication requests (up to MAX_PENDING_AUTH).
1407 *
1408 *
1409 ****************************************************************************/
Note: See TracBrowser for help on using the repository browser.