Commit cfb609f6 authored by jpbl's avatar jpbl

added back sflphone-cli

parent 7bdf5e36
......@@ -42,6 +42,9 @@
/* Define to 1 if you have the `pthread' library (-lpthread). */
#undef HAVE_LIBPTHREAD
/* Define to 1 if you have a fully functional readline library. */
#undef HAVE_LIBREADLINE
/* Define if you have libz */
#undef HAVE_LIBZ
......
......@@ -130,6 +130,7 @@ if test "x$with_speex" = "xyes" ; then
fi
AM_CONDITIONAL(USE_SPEEX, test "x$with_speex" = "xyes" )
GNUPG_CHECK_READLINE
dnl check for zeroconf (from apple)
AC_ARG_ENABLE(zeroconf,
......@@ -224,7 +225,6 @@ src/Makefile \
src/sflphone \
src/audio/Makefile \
src/audio/gsm/Makefile \
src/audio/OpenAL/Makefile \
src/audio/pacpp/Makefile \
src/audio/pacpp/include/Makefile \
src/audio/pacpp/include/portaudiocpp/Makefile \
......@@ -233,6 +233,7 @@ src/audio/pacpp/source/portaudiocpp/Makefile \
src/config/Makefile \
src/gui/Makefile \
src/gui/qt/Makefile \
src/gui/cli/Makefile \
src/gui/server/Makefile \
src/zeroconf/Makefile \
ringtones/Makefile \
......
dnl Check for readline and dependencies
dnl Copyright (C) 2004 Free Software Foundation, Inc.
dnl
dnl This file is free software, distributed under the terms of the GNU
dnl General Public License. As a special exception to the GNU General
dnl Public License, this file may be distributed as part of a program
dnl that contains a configuration script generated by Autoconf, under
dnl the same distribution terms as the rest of that program.
dnl
dnl Defines HAVE_LIBREADLINE to 1 if a working readline setup is
dnl found, and sets @LIBREADLINE@ to the necessary libraries.
AC_DEFUN([GNUPG_CHECK_READLINE],
[
AC_ARG_WITH(readline,
AC_HELP_STRING([--with-readline=DIR],
[look for the readline library in DIR]),
[_do_readline=$withval],[_do_readline=yes])
if test "$_do_readline" != "no" ; then
if test -d "$withval" ; then
CPPFLAGS="${CPPFLAGS} -I$withval/include"
LDFLAGS="${LDFLAGS} -L$withval/lib"
fi
for _termcap in "" "-ltermcap" "-lcurses" "-lncurses" ; do
_readline_save_libs=$LIBS
_combo="-lreadline${_termcap:+ $_termcap}"
LIBS="$LIBS $_combo"
AC_MSG_CHECKING([whether readline via \"$_combo\" is present and sane])
AC_LINK_IFELSE(AC_LANG_PROGRAM([
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
],[
add_history("foobar");
rl_catch_signals=0;
rl_inhibit_completion=0;
rl_attempted_completion_function=NULL;
]),_found_readline=yes,_found_readline=no)
AC_MSG_RESULT([$_found_readline])
LIBS=$_readline_save_libs
if test $_found_readline = yes ; then
AC_DEFINE(HAVE_LIBREADLINE,1,
[Define to 1 if you have a fully functional readline library.])
AC_SUBST(LIBREADLINE,$_combo)
break
fi
done
unset _termcap
unset _readline_save_libs
unset _combo
unset _found_readline
fi
])dnl
SUBDIRS = gsm pacpp OpenAL
SUBDIRS = gsm pacpp
noinst_LTLIBRARIES = libaudio.la
......@@ -28,7 +28,7 @@ audioloop.cpp ringbuffer.cpp $(SPEEX_SOURCES)
AM_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/libs -I$(srcdir)/pacpp/include/ $(libccext2_CFLAGS) $(libccrtp1_CFLAGS) $(portaudio_CFLAGS) -I$(top_srcdir)/libs/portaudio/pa_common
libaudio_la_LIBADD = gsm/libgsm.la pacpp/source/portaudiocpp/libportaudiocpp.la $(SPEEX_LIB) $(SAMPLERATE_LIB)
libaudio_la_CPPFLAGS = $(SPEEX_FLAG) $(SAMPLERATE_FLAG)
noinst_HEADERS = audioloop.h common.h ringbuffer.h alaw.h audiofile.h g711.h \
tonelist.h audiortp.h audiocodec.h audiolayer.h \
......
......@@ -6,7 +6,7 @@ serverlib = server/libsflphoneguiserver.la
#qt/sflphone-qt:
# cd qt && make
SUBDIRS = $(serverdir) qt
SUBDIRS = $(serverdir) qt cli
noinst_LTLIBRARIES = libguiframework.la
......
This diff is collapsed.
libexec_PROGRAMS = sflphone-cli
#-lncurses
AM_LDFLAGS = $(LIBREADLINE)
sflphone_cli_SOURCES = \
calls.c calls.h \
commons.h \
core.c core.h \
display.c display.h \
eventloop.c eventloop.h \
globals.c globals.h \
main.c \
net.c net.h \
requests.c requests.h \
seqs.c seqs.h \
setup.c setup.h \
sflphone.c \
sflphone-events.c sflphone-events.h \
sflphone.h \
strutils.c strutils.h \
user-input.c user-input.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "calls.h"
#include "display.h"
// malloc a new call
static struct call *new_call (char *, char *, char *);
static char *cstate2str (int);
static callobj *calls_list = NULL;
callobj *
call_push_new (char *seqid, char *callid, char *destination) {
callobj *new;
new = new_call (seqid, callid, destination);
// Add call to the list.
if (calls_list == NULL) {
calls_list = new;
} else {
new->next = calls_list;
calls_list = new;
}
return new;
}
void
call_print_list (void) {
callobj *cptr = calls_list;
if (cptr == NULL) {
display_info ("No call currently in progress !");
return;
}
display_info ("Calls in progress:");
while (cptr != NULL) {
display_info ("* (%s) [%s] %s", cstate2str (cptr->state),
cptr->cid, cptr->dest);
cptr = cptr->next;
}
}
/********************************
* PRIVATE FUNCTIONS *
********************************/
static char *
cstate2str (int state) {
switch (state) {
case TALKING:
return "Talking";
break;
case ON_HOLD:
return "On Hold";
break;
case CALLING:
default:
return "Calling";
break;
}
}
// Malloc new call descriptor
static struct call *
new_call (char *seqid, char *cid, char *destination) {
int len;
struct call *new;
new = malloc (sizeof (struct call));
if (new == NULL) {
perror ("malloc");
exit (1);
}
// Erase memory
bzero (new, sizeof (struct call));
// Put cid
len = (strlen(cid) > (CIDMAX - 1)) ? (CIDMAX - 1) : strlen(cid);
strncpy (new->cid, cid, len);
// Put seq id
len = (strlen(seqid) > (CIDMAX - 1)) ? (CIDMAX - 1) : strlen(seqid);
strncpy (new->sid, seqid, len);
// Put dest
if (destination != NULL) {
new->dest = strdup (destination);
}
return new;
}
/* EOF */
#ifndef __CALLS_H__
#define __CALLS_H__
#define CIDMAX 32
enum callstate {
CALLING = 0,
TALKING,
ON_HOLD
};
struct call {
struct call *next;
char *dest;
char cid[CIDMAX];
char sid[CIDMAX];
enum callstate state;
};
typedef struct call callobj;
void call_print_list (void);
callobj *call_push_new (char *, char *, char *);
#endif // __CALLS_H__
#ifndef __COMMONS_H__
#define __COMMONS_H__
#include <strings.h>
#define CONNECT_HOST "127.0.0.1"
#define CONNECT_PORT 3999
#define FOREVER for(;;)
#define IF_INIT if(0)
#define IF_GOT(STRING) else if (0 == strncasecmp (ibuf, STRING, strlen(STRING)))
#endif // __COMMONS_H__
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "core.h"
#include "display.h"
#define SFLPHONED_NAME "sflphoned"
static char *core_path;
static int find_core (void);
/* Runs the sflphone core daemon */
int
run_core (void) {
int ret;
if (!find_core ()) {
display_info ("Unable to find %s.", SFLPHONED_NAME);
display_info ("Point $SFLPHONE_CORE_DIR to its directory.");
exit (1);
}
if (core_path == NULL) {
return -1;
}
ret = fork ();
switch (ret) {
case 0:
/* core process */
execl (core_path, NULL, NULL);
exit (0);
break;
case -1:
/* error */
display_info ("Unable to fork(), call 911.");
exit (1);
default:
/* original process */
sleep (1); /* Wait for core to init. */
break;
}
return ret;
}
/* Find the core sflphoned and set the full path */
static int
find_core (void) {
char *envar;
envar = getenv ("SFLPHONE_CORE_DIR");
if (envar == NULL) {
return 0;
}
core_path = (char *) malloc (strlen (envar) + 3 + strlen (SFLPHONED_NAME));
if (core_path == NULL) {
return 0;
}
snprintf (core_path, strlen (envar) + 3 + strlen (SFLPHONED_NAME),
"%s/%s", envar, SFLPHONED_NAME);
return 1;
}
/* EOF */
#ifndef __CORE_H__
#define __CORE_H__
#define CORE_PATH "/opt/SFLphone/bin/sflphoned"
int run_core (void);
#endif // __CORE_H__
#include <stdio.h>
#include "display.h"
#ifdef USE_ANSI
# define PROMPT "SFLphone>"
#else
# define PROMPT "SFLphone>"
#endif
// Display the SFLphone> prompt
void
display_prompt (void) {
printf ("%s ", PROMPT);
fflush (stdout);
}
// Display incoming call info
void
display_inc_call (char *from) {
printf ("\r");
#ifdef USE_ANSI
printf ("*** Incoming Call from %s "
"***\n", from);
#else
printf ("*** Incoming Call from %s ***\n", from);
#endif
}
/* EOF */
#ifndef __DISPLAY_H__
#define __DISPLAY_H__
#ifdef DEBUG
#include <stdio.h>
# ifdef USE_ANSI
# define debug(...) fprintf (stderr, "\r[debug] " __VA_ARGS__)
# else
# define debug(...) fprintf (stderr, "\r[debug] " __VA_ARGS__)
# endif
#else
# define debug(...)
#endif
void display_prompt (void);
void display_inc_call (char *);
#ifdef USE_ANSI
# define display_info(...) printf("[Info] " __VA_ARGS__);printf("\n");
#else
#define display_info(...) printf ("[Info] " __VA_ARGS__);printf("\n");
#endif
#endif // __DISPLAY_H__
#include <sys/select.h>
#include <stdio.h>
#include "commons.h"
#include "display.h"
#include "globals.h"
#include "user-input.h"
#include "sflphone.h"
#include "sflphone-events.h"
int
event_loop (int socket) {
fd_set rfds,
wfds;
/* get socket as FILE */
fdsocket = fdopen (socket, "a+");
if (fdsocket == NULL) {
perror ("fdopen");
return -1;
}
/* Ask SFLphone's core version */
sflphone_ask_version ();
sflphone_get_events();
/* Main event loop */
FOREVER {
FD_ZERO (&rfds);
FD_ZERO (&wfds);
FD_SET (socket, &rfds); // Watch socket
FD_SET (0, &rfds); // Watch stdin
/* Wait for input, forever */
display_prompt ();
select (socket+1, &rfds, NULL, NULL, NULL);
/* React to socket input */
if (FD_ISSET (socket, &rfds)) {
if (feof (fdsocket)) {
display_info ("SFLphone core closed the link. "
"Shutting down.");
break;
} else {
handle_event ();
}
}
/* React to user input */
if (FD_ISSET (0, &rfds)) {
if (handle_input () < 0) {
/* Exit if handle_input tells to. */
break;
}
// Break on EOF
if (feof (stdin)) {
display_info ("Got EOF. Bye bye !\n");
break;
}
}
}
return 0;
}
/* EOF */
#ifndef __EVENTLOOP_H__
#define __EVENTLOOP_H__
int event_loop (int);
#endif // __EVENTLOOP_H__
#include <stdio.h>
#include "globals.h"
FILE *fdsocket = NULL;
int core_pid = 0;
/* EOF */
#ifndef __GLOBALS_H__
#define __GLOBALS_H__
#include <stdio.h>
extern FILE *fdsocket;
extern int core_pid;
#endif // __GLOBALS_H__
#include <stdio.h>
#include <unistd.h>
#include "commons.h"
#include "core.h"
#include "display.h"
#include "eventloop.h"
#include "globals.h"
#include "net.h"
#define MAX_RETRIES 5
int
main (int argc, char **argv) {
int socket;
int launched = 0;
int retry = 0;
/* Init */
/* Connect */
do {
//display_info ("Connecting to %s:%d...\n", CONNECT_HOST, CONNECT_PORT);
socket = create_socket (CONNECT_HOST, CONNECT_PORT);
if (socket < 0) {
if (!launched) {
// Attempt to launch sflphone.
launched = 1;
//display_info ("Attempting to run sflphoned.");
core_pid = run_core ();
} else {
sleep (1);
}
} else {
break;
}
retry++;
} while (retry < MAX_RETRIES);
if (retry < MAX_RETRIES) {
return event_loop (socket);
} else {
display_info ("Cannot run sflphone daemon !");
return 1;
}
}
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int global_socket;
int
create_socket (char *hostname, unsigned short portnum) {
struct hostent *hp;
struct sockaddr_in sa;
int sock;
/* Check destination */
if ((hp = gethostbyname (hostname)) == NULL) {
perror ("gethostbyname");
return (-1);
}
/* Alloc socket */
sock = socket (PF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror ("socket");
return (-1);
}
/* Setup socket */
bzero (&sa, sizeof(sa));
bcopy (hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
sa.sin_port = htons ((unsigned short)portnum);
/* Connect to sflphone */
if (connect (sock, (const struct sockaddr *) &sa, sizeof(sa)) < 0) {
close(sock);
perror ("connect");
return(-1);
}
return (sock);
}
/* EOF */
#ifndef __NET__H__
#define __NET__H__
extern int global_socket;
int create_socket (char *, unsigned short);
#endif // __NET__H__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "requests.h"
// malloc a new request
static struct request *new_request (char *, char *, void *);
static reqobj *requests_list = NULL;
// Malloc new request
static struct request *
new_request (char *rid, char *subject, void *payload) {
int len;
struct request *req;
req = malloc (sizeof (struct request));
if (req == NULL) {
perror ("malloc");
exit (1);
}
// Erase memory
bzero (req, sizeof (struct request));
// Put rid
len = (strlen(rid) > (RIDMAX-1)) ? (RIDMAX-1) : strlen(rid);
strncpy (req->rid, rid, len);
// Put subject
req->subject = strdup (subject);
// Attach payload
if (payload != NULL) {
req->payload = payload;
}
return req;
}
void
request_push (int id, char *subject, void *payload) {
reqobj *newreq;
char tmp[RIDMAX];
snprintf (tmp, RIDMAX - 1, "seq%d", id);
newreq = (reqobj *) new_request (tmp, subject, payload);
if (requests_list == NULL) {
// First item
requests_list = newreq;
} else {
// Add to the beginning of the list.
newreq->next = requests_list->next;
requests_list = newreq;
}
}
reqobj *
request_find (char *sid) {
reqobj *candidate;
if (requests_list == NULL) {
return NULL;
}
candidate = requests_list;
while (candidate != NULL) {
if (0 == strcmp (sid, candidate->rid)) {
return candidate;
}
candidate = candidate->next;
}
// Not found
return NULL;
}
reqobj *
request_pop (char *sid) {
reqobj *candidate;
reqobj *prev;
if (requests_list == NULL) {
return NULL;
}
candidate = prev = requests_list;
while (candidate != NULL) {
if (0 == strcmp (sid, candidate->rid)) {
// dequeue
if (candidate == requests_list) {
requests_list = candidate->next;
} else {
prev->next = candidate->next;
}
return candidate;
}
prev = candidate;
candidate = candidate->next;
}
// Not found
return NULL;
}
void
request_free (reqobj *item) {
if (item->subject != NULL) {
free (item->subject);
}
free (item);
}
/* EOF */
#ifndef __REQUESTS_H__
#define __REQUESTS_H__
#define RIDMAX 32
struct request {
struct request *next;
char *subject;
char rid[RIDMAX];
void *payload;
};