source: mediastreamer2/linphone/console/commands.c @ 244:341831610f7f

Last change on this file since 244:341831610f7f was 244:341831610f7f, checked in by smorlat <smorlat@…>, 4 years ago

new linphonec commands.

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

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