Commit 3f84c8d4 authored by smorlat's avatar smorlat
Browse files

use windows pipes in linphonec/linphonecsh.

git-svn-id: svn+ssh://svn.savannah.nongnu.org/linphone/trunk@485 3f6dc0c8-ddfe-455d-9043-3cd528dc4637
parent 581436ae
......@@ -58,8 +58,6 @@
#define _(something) (something)
#endif
#define DEFAULT_TCP_PORT 32333
/***************************************************************************
*
* Types
......@@ -131,19 +129,17 @@ static bool_t display_enabled=FALSE;
static bool_t preview_enabled=FALSE;
static bool_t show_general_state=FALSE;
static bool_t unix_socket=FALSE;
static int tcp_port=0; /* see --tcp: tcp port to listen for commands */
LPC_AUTH_STACK auth_stack;
static int trace_level = 0;
static char *logfile_name = NULL;
static char configfile_name[PATH_MAX];
static char *sipAddr = NULL; /* for autocall */
static ortp_socket_t client_sock=-1;
static ortp_pipe_t client_sock=ORTP_PIPE_INVALID;
char prompt[PROMPT_MAX_LEN];
char sock_unix_path[128]={0};
static ortp_thread_t net_reader_th;
static bool_t net_reader_run=FALSE;
static ortp_socket_t server_sock;
static ortp_thread_t pipe_reader_th;
static bool_t pipe_reader_run=FALSE;
static ortp_pipe_t server_sock;
LinphoneCoreVTable linphonec_vtable = {
......@@ -231,7 +227,7 @@ static void
linphonec_prompt_for_auth(LinphoneCore *lc, const char *realm, const char *username)
{
/* no prompt possible when using pipes or tcp mode*/
if (unix_socket || tcp_port){
if (unix_socket){
linphone_core_abort_authentication(lc,NULL);
}else{
LinphoneAuthInfo *pending_auth;
......@@ -380,81 +376,38 @@ static void start_prompt_reader(void){
ortp_thread_create(&th,NULL,prompt_reader_thread,NULL);
}
static ortp_socket_t create_server_socket(int port){
ortp_socket_t sock;
if (!unix_socket){
char service[12];
/*setup the server socket */
struct addrinfo *ai=NULL;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
snprintf(service,sizeof(service),"%i",port);
getaddrinfo("127.0.0.1",service,&hints,&ai);
if (ai==NULL){
fprintf(stderr,"getaddrinfo failed on port %s",service);
exit(-1);
}
sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (bind(sock,ai->ai_addr,ai->ai_addrlen)!=0){
fprintf(stderr,"Failed to bind command socket.\n");
exit(-1);
}
listen(sock,1);
}else{
static ortp_pipe_t create_server_socket(void){
char path[128];
#ifndef WIN32
struct sockaddr_un sa;
sock=socket(AF_UNIX,SOCK_STREAM,0);
sa.sun_family=AF_UNIX;
snprintf(sock_unix_path,sizeof(sock_unix_path)-1,"/tmp/linphonec-%i",getuid());
strncpy(sa.sun_path,sock_unix_path,sizeof(sa.sun_path)-1);
unlink(sock_unix_path);/*in case we didn't finished properly previous time */
fchmod(sock,S_IRUSR|S_IWUSR);
if (bind(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
fprintf(stderr,"Failed to bind command unix socket.\n");
exit(-1);
}
listen(sock,1);
printf("Listening from unix socket %s\n",sock_unix_path);
snprintf(path,sizeof(path)-1,"linphonec-%i",getuid());
#else
fprintf(stderr,"Window pipe implementation not written yet.\n");
#endif
{
char username[128];
DWORD size=sizeof(username)-1;
GetUserName(username,&size);
snprintf(path,sizeof(path)-1,"linphonec-%s",username);
}
return sock;
#endif
return ortp_server_pipe_create(path);
}
static void *net_thread(void*p){
static void *pipe_thread(void*p){
char tmp[250];
struct sockaddr_storage ss;
#ifndef WIN32
struct sockaddr_un su;
#endif
socklen_t ssize;
server_sock=create_server_socket(tcp_port);
if (server_sock==-1) return NULL;
while(net_reader_run){
while(client_sock!=-1){ /*sleep until the last command is finished*/
server_sock=create_server_socket();
if (server_sock==ORTP_PIPE_INVALID) return NULL;
while(pipe_reader_run){
while(client_sock!=ORTP_PIPE_INVALID){ /*sleep until the last command is finished*/
#ifndef WIN32
usleep(20000);
#else
Sleep(20);
#endif
}
if (!unix_socket){
ssize=sizeof(ss);
client_sock=accept(server_sock,(struct sockaddr*)&ss,&ssize);
}else{
#ifndef WIN32
ssize=sizeof(su);
client_sock=accept(server_sock,(struct sockaddr*)&su,&ssize);
#endif
}
if (client_sock!=-1){
client_sock=ortp_server_pipe_accept_client(server_sock);
if (client_sock!=ORTP_PIPE_INVALID){
int len;
/*now read from the client */
if ((len=recv(client_sock,tmp,sizeof(tmp)-1,0))>0){
if ((len=ortp_pipe_read(client_sock,tmp,sizeof(tmp)-1))>0){
ortp_mutex_lock(&prompt_mutex);
tmp[len]='\0';
strcpy(received_prompt,tmp);
......@@ -463,31 +416,29 @@ static void *net_thread(void*p){
ortp_mutex_unlock(&prompt_mutex);
}else{
printf("read nothing\n");fflush(stdout);
close_socket(client_sock);
client_sock=-1;
ortp_server_pipe_close_client(client_sock);
client_sock=ORTP_PIPE_INVALID;
}
}else{
if (net_reader_run) fprintf(stderr,"accept() failed: %s\n",getSocketError());
if (pipe_reader_run) fprintf(stderr,"accept() failed: %s\n",strerror(errno));
}
}
printf("Exiting pipe_reader_thread.");
fflush(stdout);
return NULL;
}
static void start_net_reader(void){
static void start_pipe_reader(void){
ms_mutex_init(&prompt_mutex,NULL);
net_reader_run=TRUE;
ortp_thread_create(&net_reader_th,NULL,net_thread,NULL);
pipe_reader_run=TRUE;
ortp_thread_create(&pipe_reader_th,NULL,pipe_thread,NULL);
}
static void stop_net_reader(void){
net_reader_run=FALSE;
close(server_sock);
if (sock_unix_path[0]!=0){
unlink(sock_unix_path);
}
/*ortp_thread_join(net_reader_th,NULL);*/
static void stop_pipe_reader(void){
pipe_reader_run=FALSE;
ortp_server_pipe_close(server_sock);
ortp_thread_join(pipe_reader_th,NULL);
}
#ifdef HAVE_READLINE
......@@ -497,16 +448,16 @@ static void stop_net_reader(void){
#endif
char *linphonec_readline(char *prompt){
if (tcp_port ||unix_socket || !BOOL_HAVE_READLINE ){
if (unix_socket || !BOOL_HAVE_READLINE ){
static bool_t prompt_reader_started=FALSE;
static bool_t net_reader_started=FALSE;
static bool_t pipe_reader_started=FALSE;
if (!prompt_reader_started){
start_prompt_reader();
prompt_reader_started=TRUE;
}
if ((tcp_port>0 || unix_socket) && !net_reader_started){
start_net_reader();
net_reader_started=TRUE;
if (unix_socket && !pipe_reader_started){
start_pipe_reader();
pipe_reader_started=TRUE;
}
fprintf(stdout,"%s",prompt);
fflush(stdout);
......@@ -539,19 +490,20 @@ void linphonec_out(const char *fmt,...){
va_start (args, fmt);
res=ortp_strdup_vprintf(fmt,args);
va_end (args);
printf("%s",res);fflush(stdout);
if (client_sock!=-1){
if (send(client_sock,res,strlen(res),0)==-1){
fprintf(stderr,"Fail to send output via socket: %s",getSocketError());
printf("%s",res);
fflush(stdout);
if (client_sock!=ORTP_PIPE_INVALID){
if (ortp_pipe_write(client_sock,res,strlen(res))==-1){
fprintf(stderr,"Fail to send output via pipe: %s",strerror(errno));
}
}
ortp_free(res);
}
void linphonec_command_finished(void){
if (client_sock!=-1){
close_socket(client_sock);
client_sock=-1;
if (client_sock!=ORTP_PIPE_INVALID){
ortp_server_pipe_close_client(client_sock);
client_sock=ORTP_PIPE_INVALID;
}
}
......@@ -689,8 +641,8 @@ linphonec_finish(int exit_status)
#ifdef HAVE_READLINE
linphonec_finish_readline();
#endif
if (net_reader_run)
stop_net_reader();
if (pipe_reader_run)
stop_pipe_reader();
linphone_core_uninit (&linphonec);
......@@ -1061,14 +1013,6 @@ linphonec_parse_cmdline(int argc, char **argv)
{
show_general_state = TRUE;
}
else if (strncmp ("--tcp", argv[arg_num], 5) == 0)
{
if (arg_num+1 < argc){
tcp_port = atoi(argv[arg_num+1]);
if (tcp_port!=0) arg_num++;
}
if (tcp_port==0) tcp_port=DEFAULT_TCP_PORT;
}
else if (strncmp ("--pipe", argv[arg_num], 6) == 0)
{
unix_socket=1;
......
......@@ -57,7 +57,7 @@ Includes=../oRTP/include;../mediastreamer2/include;../../linphone-deps/include;.
Libs=../oRTP/build/win32native;../mediastreamer2/build/win32native;../coreapi/;../../linphone-deps/lib
ResourceIncludes=
MakeIncludes=
Compiler=-g -02_@@_-DIN_LINPHONE_@@_-D_WIN32_WINNT=0x0501 _@@_
Compiler=-g -02_@@_-DIN_LINPHONE_@@_-D_WIN32_WINNT=0x0501 _@@_-Wall -Werror_@@_
CppCompiler=
Linker=-mwindows_@@_-Wl,--export-all-symbols_@@_-Wl,--add-stdcall-alias_@@_-llinphone_@@_-lmediastreamer2_@@_-lortp_@@_-losip2_@@_-losipparser2_@@_-leXosip2_@@_-lws2_32_@@_
PreprocDefines=
......
......@@ -39,7 +39,6 @@
#include "ortp/ortp.h"
#define DEFAULT_TCP_PORT "32333"
#define DEFAULT_REPLY_SIZE 4096
#define STATUS_REGISTERED (1<<0)
......@@ -49,11 +48,6 @@
#define STATUS_IN_CONNECTED (1<<4) /* incoming call accepted */
#define STATUS_OUT_CONNECTED (1<<5) /*outgoing call accepted */
#ifndef WIN32
static int tcp=0;
#else
static int tcp=1;
#endif
static int make_status_value(const char *status_string){
int ret=0;
......@@ -78,57 +72,37 @@ static int make_status_value(const char *status_string){
return ret;
}
static int send_command(const char *command, const char * port, char *reply, int reply_len, int print_errors){
ortp_socket_t sock;
static int send_command(const char *command, char *reply, int reply_len, int print_errors){
ortp_pipe_t pp;
int i;
int err;
if (tcp){
struct addrinfo *ai=NULL;
struct addrinfo hints;
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_INET;
hints.ai_socktype=SOCK_STREAM;
err=getaddrinfo("127.0.0.1",port,&hints,&ai);
if (err!=0){
if (print_errors) fprintf(stderr,"ERROR: getaddrinfo failed: error %i\n", err);
return -1;
}
sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if (connect(sock,ai->ai_addr,ai->ai_addrlen)!=0){
if (print_errors) fprintf(stderr,"ERROR: Failed to connect socket.\n");
freeaddrinfo(ai);
return -1;
}
freeaddrinfo(ai);
}else{
char path[128];
#ifndef WIN32
struct sockaddr_un sa;
char path[128];
sock=socket(AF_UNIX,SOCK_STREAM,0);
sa.sun_family=AF_UNIX;
snprintf(path,sizeof(path)-1,"/tmp/linphonec-%i",getuid());
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
if (connect(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
if (print_errors) fprintf(stderr,"ERROR: Failed to connect socket: %s\n",getSocketError());
return -1;
}
snprintf(path,sizeof(path)-1,"linphonec-%i",getuid());
#else
fprintf(stderr,"ERROR: windows pipes communication not yet implemented.\n");
return -1;
{
char username[128];
DWORD size=sizeof(username)-1;
GetUserName(username,&size);
snprintf(path,sizeof(path)-1,"linphonec-%s",username);
}
#endif
if ((pp=ortp_client_pipe_connect(path))==ORTP_PIPE_INVALID){
if (print_errors) fprintf(stderr,"ERROR: Failed to connect pipe: %s\n",strerror(errno));
return -1;
}
if (send(sock,command,strlen(command),0)<0){
if (ortp_pipe_write(pp,command,strlen(command))==-1){
if (print_errors) fprintf(stderr,"ERROR: Fail to send command to remote linphonec\n");
close_socket(sock);
ortp_client_pipe_close(pp);
return -1;
}
/*wait for replies */
i=0;
while ((err=recv(sock,&reply[i],reply_len-i-1,0))>0){
while ((err=ortp_pipe_read(pp,&reply[i],reply_len-i-1))>0){
i+=err;
}
reply[i]='\0';
close_socket(sock);
ortp_client_pipe_close(pp);
return 0;
}
......@@ -160,10 +134,7 @@ static void spawn_linphonec(int argc, char *argv[]){
pid_t pid;
j=0;
args[j++]="linphonec";
if (tcp){
args[j++]="--tcp";
args[j++]=DEFAULT_TCP_PORT;
}else args[j++]="--pipe";
args[j++]="--pipe";
args[j++]="-c";
args[j++]="/dev/null";
for(i=0;i<argc;++i){
......@@ -207,7 +178,7 @@ static void spawn_linphonec(int argc, char *argv[]){
ZeroMemory( &pinfo, sizeof(pinfo) );
BOOL ret=CreateProcess(NULL,"linphonec.exe --tcp " DEFAULT_TCP_PORT " -c NUL",
BOOL ret=CreateProcess(NULL,"linphonec.exe --pipe -c NUL",
NULL,
NULL,
FALSE,
......@@ -228,7 +199,7 @@ static void spawn_linphonec(int argc, char *argv[]){
static int send_generic_command(const char *command, int print_result){
char reply[DEFAULT_REPLY_SIZE];
int err;
err=send_command(command,DEFAULT_TCP_PORT,reply,sizeof(reply),print_result);
err=send_command(command,reply,sizeof(reply),print_result);
if (err==0 && print_result) {
printf("%s",reply);
fflush(stdout);
......@@ -296,7 +267,7 @@ static int status_execute(int argc, char *argv[]){
if (argc==1){
snprintf(cmd,sizeof(cmd),"status %s",argv[0]);
err=send_command(cmd,DEFAULT_TCP_PORT,reply,sizeof(reply),TRUE);
err=send_command(cmd,reply,sizeof(reply),TRUE);
if (err==0) {
printf("%s",reply);
err=make_status_value(reply);
......@@ -323,14 +294,14 @@ static int soundcard_execute(int argc, char *argv[]){
int err;
if (argc==1){
snprintf(cmd,sizeof(cmd),"soundcard %s",argv[0]);
err=send_command(cmd,DEFAULT_TCP_PORT,reply,sizeof(reply),TRUE);
err=send_command(cmd,reply,sizeof(reply),TRUE);
if (err==0) {
printf("%s",reply);
return parse_card_index(reply);
}
}else if (argc==2){/*setting a soundcard */
snprintf(cmd,sizeof(cmd),"soundcard %s %s",argv[0],argv[1]);
err=send_command(cmd,DEFAULT_TCP_PORT,reply,sizeof(reply),TRUE);
err=send_command(cmd,reply,sizeof(reply),TRUE);
if (err==0) {
printf("%s",reply);
return 0;
......@@ -349,16 +320,13 @@ int main(int argc, char *argv[]){
}
ortp_init();
for(argi=1;argi<argc;++argi){
if (strcmp(argv[argi],"--tcp")==0){
tcp=1;
}else if (strcmp(argv[argi],"init")==0){
if (strcmp(argv[argi],"init")==0){
/*check if there is running instance*/
if (send_generic_command("help",0)==0){
fprintf(stderr,"A running linphonec has been found, not spawning a second one.\n");
return 0;
}
spawn_linphonec(argc-argi-1,&argv[argi+1]);
if (tcp) fprintf(stderr,"WARNING: using --tcp is unsafe: unprivilegied users can make calls.\n");
return 0;
}else if (strcmp(argv[argi],"generic")==0){
if (argi+1<argc){
......
......@@ -33,7 +33,7 @@
#endif
#ifndef LINPHONE_VERSION
#define LINPHONE_VERSION "3.1.1"
#define LINPHONE_VERSION "3.1.2"
#endif
#ifndef LIBLINPHONE_VERSION
......
......@@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PACKAGE_DATA_DIR "./"
#ifndef LINPHONE_VERSION
#define LINPHONE_VERSION "3.1.2"
#define LINPHONE_VERSION "3.1.2-20090520"
#endif
#endif
......
......@@ -231,16 +231,29 @@ char *ortp_strdup_printf(const char *fmt,...);
char *ortp_strdup_vprintf(const char *fmt, va_list ap);
/* portable named pipes */
ortp_socket_t ortp_server_pipe_create(const char *name);
ortp_socket_t ortp_server_pipe_accept_client(ortp_socket_t server);
int ortp_server_pipe_close(ortp_socket_t spipe);
int ortp_server_pipe_close_client(ortp_socket_t client);
#ifdef WIN32
typedef HANDLE ortp_pipe_t;
#define ORTP_PIPE_INVALID INVALID_HANDLE_VALUE
#else
typedef int ortp_pipe_t;
#define ORTP_PIPE_INVALID (-1)
#endif
ortp_pipe_t ortp_server_pipe_create(const char *name);
/*
* warning: on win32 ortp_server_pipe_accept_client() might return INVALID_HANDLE_VALUE without
* any specific error, this happens when ortp_server_pipe_close() is called on another pipe.
* This pipe api is not thread-safe.
*/
ortp_pipe_t ortp_server_pipe_accept_client(ortp_pipe_t server);
int ortp_server_pipe_close(ortp_pipe_t spipe);
int ortp_server_pipe_close_client(ortp_pipe_t client);
ortp_socket_t ortp_client_pipe_connect(const char *name);
int ortp_client_pipe_close(ortp_socket_t sock);
ortp_pipe_t ortp_client_pipe_connect(const char *name);
int ortp_client_pipe_close(ortp_pipe_t sock);
int ortp_pipe_read(ortp_socket_t p, uint8_t *buf, int len);
int ortp_pipe_write(ortp_socket_t p, const uint8_t *buf, int len);
int ortp_pipe_read(ortp_pipe_t p, uint8_t *buf, int len);
int ortp_pipe_write(ortp_pipe_t p, const uint8_t *buf, int len);
#ifdef __cplusplus
......
......@@ -341,14 +341,20 @@ char * WSAAPI gai_strerror(int errnum){
#include <sys/un.h>
#include <sys/stat.h>
static char *make_pipe_name(const char *name){
return ortp_strdup_printf("/tmp/%s",name);
}
/* portable named pipes */
ortp_socket_t ortp_server_pipe_create(const char *name){
struct sockaddr_un sa;
char *pipename=make_pipe_name(name);
ortp_socket_t sock;
sock=socket(AF_UNIX,SOCK_STREAM,0);
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,name,sizeof(sa.sun_path)-1);
unlink(name);/*in case we didn't finished properly previous time */
strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
unlink(pipename);/*in case we didn't finished properly previous time */
ortp_free(pipename);
fchmod(sock,S_IRUSR|S_IWUSR);
if (bind(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
ortp_error("Failed to bind command unix socket: %s",strerror(errno));
......@@ -375,9 +381,11 @@ int ortp_server_pipe_close(ortp_socket_t spipe){
ortp_socket_t ortp_client_pipe_connect(const char *name){
struct sockaddr_un sa;
char *pipename=make_pipe_name(name);
ortp_socket_t sock=socket(AF_UNIX,SOCK_STREAM,0);
sa.sun_family=AF_UNIX;
strncpy(sa.sun_path,name,sizeof(sa.sun_path)-1);
strncpy(sa.sun_path,pipename,sizeof(sa.sun_path)-1);
ortp_free(pipename);
if (connect(sock,(struct sockaddr*)&sa,sizeof(sa))!=0){
close(sock);
return -1;
......@@ -398,13 +406,90 @@ int ortp_client_pipe_close(ortp_socket_t sock){
}
#else
static char *make_pipe_name(const char *name){
return ortp_strdup_printf("\\\\.\\pipe\\%s",name);
}
static HANDLE event=NULL;
/* portable named pipes */
ortp_socket_t ortp_server_pipe_create(const char *name);
ortp_socket_t ortp_server_pipe_accept(ortp_socket_t server);
int ortp_server_pipe_close(ortp_socket_t spipe);
ortp_pipe_t ortp_server_pipe_create(const char *name){
ortp_pipe_t h;
char *pipename=make_pipe_name(name);
h=CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED,PIPE_TYPE_MESSAGE|PIPE_WAIT,1,
32768,32768,0,NULL);
ortp_free(pipename);
if (h==INVALID_HANDLE_VALUE){
ortp_error("Fail to create named pipe %s",pipename);
}
if (event==NULL) event=CreateEvent(NULL,TRUE,FALSE,NULL);
return h;
}
/*this function is a bit complex because we need to wakeup someday
even if nobody connects to the pipe.
ortp_server_pipe_close() makes this function to exit.
*/
ortp_pipe_t ortp_server_pipe_accept_client(ortp_pipe_t server){
OVERLAPPED ol;
DWORD undef;
memset(&ol,0,sizeof(ol));
ol.hEvent=event;
ResetEvent(event);
ConnectNamedPipe(server,&ol);
WaitForSingleObject(ol.hEvent,INFINITE);
if (GetOverlappedResult(server,&ol,&undef,FALSE)){
return server;
}
return INVALID_HANDLE_VALUE;
}
ortp_socket_t ortp_call_pipe(const char *name);
int ortp_server_pipe_close_client(ortp_pipe_t server){
return DisconnectNamedPipe(server)==TRUE ? 0 : -1;
}
int ortp_server_pipe_close(ortp_pipe_t spipe){
SetEvent(event);
//CancelIoEx(spipe,NULL); /*vista only*/
return CloseHandle(spipe);
}
ortp_pipe_t ortp_client_pipe_connect(const char *name){
char *pipename=make_pipe_name(name);
ortp_pipe_t hpipe = CreateFile(
pipename, // pipe name
GENERIC_READ | // read and write access
GENERIC_WRITE,
0, // no sharing
NULL, // default security attributes
OPEN_EXISTING, // opens existing pipe
0, // default attributes
NULL); // no template file
ortp_free(pipename);
return hpipe;
}
int ortp_pipe_read(ortp_pipe_t p, uint8_t *buf, int len){
DWORD ret=0;
if (ReadFile(p,buf,len,&ret,NULL))
return ret;
/*ortp_error("Could not read from pipe: %s",strerror(GetLastError()));*/
return -1;
}
int ortp_pipe_write(ortp_pipe_t p, const uint8_t *buf, int len){