From 201dcb6e11670a10f678644a9995c5d0275ba3aa Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Mon, 20 Aug 2012 18:11:27 -0500 Subject: [PATCH] Add rudimentary sound support --- raptorsmiface/libraptorsmiface.c | 54 ++++++++++++++++++++++++++++++-- raptorsmiface/libraptorsmiface.h | 6 +++- sesman/chansrv/chansrv.c | 3 ++ sesman/chansrv/clipboard.c | 5 +++ sesman/chansrv/sound.c | 29 ++++++++++++++++- 5 files changed, 93 insertions(+), 4 deletions(-) diff --git a/raptorsmiface/libraptorsmiface.c b/raptorsmiface/libraptorsmiface.c index 0c172f2e..bd751685 100644 --- a/raptorsmiface/libraptorsmiface.c +++ b/raptorsmiface/libraptorsmiface.c @@ -23,7 +23,8 @@ #include "libraptorsmiface.h" -char *server = "localhost"; +//char *server = "localhost"; +char *server = "freyja.starlink.edu"; char *user = "remotelab"; char *password = "rlpass123"; /* set me first */ char *database = "remotelab_sm"; @@ -349,6 +350,39 @@ char* raptor_sm_get_hostname_for_username(char* username, bool create) { } } +char* raptor_sm_get_hostname_for_display(int display) { + MYSQL_RES *res; + MYSQL_ROW row; + char* query; + + MYSQL *conn = connect_if_needed(); + if (!conn) { + return strdup("SQLERR100"); + } + + asprintf(&query, "SELECT servername FROM sessions WHERE display='%d'", display); + if (mysql_query_internal(conn, query)) { + // Server error + free(query); + mysql_close(conn); + return strdup("SQLERR101"); + } + else { + free(query); + res = mysql_store_result(conn); + while ((row = mysql_fetch_row(res)) != NULL) { + char* ret = strdup(row[0]); + mysql_free_result(res); + mysql_close(conn); + return ret; + } + // Nothing in the DB + mysql_free_result(res); + mysql_close(conn); + return strdup(""); + } +} + char* raptor_sm_get_ip_for_username(char* username, bool create) { char* hostname = raptor_sm_get_hostname_for_username(username, create); char err; @@ -523,13 +557,25 @@ pid_t raptor_sm_run_remote_server(char* username, char *const argv[], char* dbfi } char* origstr = command_string; +#ifndef RAPTOR_SM_DISABLE_PULSEAUDIO + if (display >= 0) { + asprintf(&command_string, "ssh root@%s \"su %s -c \'export DISPLAY=:%d && export PULSE_SERVER=tcp:%s:%d && pulseaudio -D --load=\\\"module-native-protocol-tcp listen=0.0.0.0 auth-ip-acl=%s port=%d\\\"\' &> /dev/null\" &", ipaddr, username, display, ipaddr, (RAPTOR_SM_BASE_PULSEAUDIO_PORT+display), RAPTOR_SM_MANAGEMENT_SERVER_IP_NETRANGE, (RAPTOR_SM_BASE_PULSEAUDIO_PORT+display)); + dprint("Running command %s...\n\r", command_string); + system(command_string); + } +#endif + if (strcmp(dbfield, RAPTOR_SM_SERVER_PID_FIELD) == 0) { asprintf(&command_string, "ssh root@%s \'%s & echo $! &\'", ipaddr, origstr); } else { +#if RAPTOR_SM_DISABLE_PULSEAUDIO asprintf(&command_string, "ssh root@%s \"su %s -c \'export DISPLAY=:%d && %s\' &> /dev/null & echo \\$!\"", ipaddr, username, display, origstr); +#else + asprintf(&command_string, "ssh root@%s \"su %s -c \'export DISPLAY=:%d && export PULSE_SERVER=tcp:%s:%d && %s\' &> /dev/null & echo \\$!\"", ipaddr, username, display, ipaddr, (RAPTOR_SM_BASE_PULSEAUDIO_PORT+display), origstr); +#endif } -dprint("Running command %s...\n\r", command_string); + dprint("Running command %s...\n\r", command_string); free(origstr); FILE *fp; @@ -807,7 +853,11 @@ char raptor_sm_set_session_state(int display, int state) { void raptor_sm_run_remote_desktop(char* username, int display, char* executable) { char* ipaddr = raptor_sm_get_ip_for_username(username, true); char* command_string; +#if RAPTOR_SM_DISABLE_PULSEAUDIO asprintf(&command_string, "ssh root@%s \"su %s -c \'export DISPLAY=:%d && %s && exit\' &> /dev/null\"", ipaddr, username, display, executable); +#else + asprintf(&command_string, "ssh root@%s \"su %s -c \'export DISPLAY=:%d && export PULSE_SERVER=tcp:%s:%d && %s && exit\' &> /dev/null\"", ipaddr, username, display, ipaddr, (RAPTOR_SM_BASE_PULSEAUDIO_PORT+display), executable); +#endif system(command_string); free(command_string); } diff --git a/raptorsmiface/libraptorsmiface.h b/raptorsmiface/libraptorsmiface.h index 232dfe33..d0a12a2c 100644 --- a/raptorsmiface/libraptorsmiface.h +++ b/raptorsmiface/libraptorsmiface.h @@ -23,6 +23,9 @@ enum raptor_sm_status { #define RAPTOR_SM_SERVER_PID_FIELD "server_pid" #define RAPTOR_SM_WM_PID_FIELD "wm_pid" +#define RAPTOR_SM_BASE_PULSEAUDIO_PORT 2000 +#define RAPTOR_SM_MANAGEMENT_SERVER_IP_NETRANGE "10.0.0.0/8" + char* raptor_sm_get_ip_for_hostname(char* hostname, char* err); char* raptor_sm_get_hostname_for_username(char* username, bool create); @@ -39,4 +42,5 @@ int raptor_sm_get_new_unique_display(int mindisplay, int maxdisplay); bool raptor_sm_sesslimit_reached(char* username); char raptor_sm_set_session_state(int display, int state); void raptor_sm_run_remote_desktop(char* username, int display, char* executable); -void raptor_sm_terminate_server(char* username); \ No newline at end of file +void raptor_sm_terminate_server(char* username); +char* raptor_sm_get_hostname_for_display(int display); \ No newline at end of file diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index 250867ec..5c7aa679 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -222,6 +222,7 @@ g_is_term(void) { return g_is_wait_obj_set(g_term_event); } +// #define ENABLE_CHANSERV_DEBUG_LOGGING #if 0 #include @@ -229,6 +230,7 @@ g_is_term(void) #include void dprint(const char *fmt, ...) { +#ifdef ENABLE_CHANSERV_DEBUG_LOGGING va_list argp; va_start(argp, fmt); char debug[1024]; @@ -240,6 +242,7 @@ void dprint(const char *fmt, ...) fclose(fp); } va_end(argp); +#endif } #undef LOG #define LOG(_a, _params) \ diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index 6d52da85..7620c62d 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -369,6 +369,11 @@ clipboard_init(void) { return 0; } + if (!g_display) + { + // prevent crash in XInternAtom + return 3; + } xfuse_init(); xcommon_init(); diff --git a/sesman/chansrv/sound.c b/sesman/chansrv/sound.c index efb7ff85..5499d4bb 100644 --- a/sesman/chansrv/sound.c +++ b/sesman/chansrv/sound.c @@ -32,6 +32,8 @@ #include "defines.h" #include "fifo.h" +#include "libraptorsmiface.h" + extern int g_rdpsnd_chan_id; /* in chansrv.c */ extern int g_display_num; /* in chansrv.c */ @@ -155,6 +157,16 @@ static struct xr_wave_format_ex *g_wave_inp_formats[SND_NUM_INP_FORMATS] = static int g_client_input_format_index = 0; static int g_server_input_format_index = 0; +//#if 0 +void dprint(const char *fmt, ...); +#undef LOG +#define LOG(_a, _params) \ +{ \ + dprint _params; \ + dprint("\n"); \ +} +//#endif + /*****************************************************************************/ static int APP_CC sound_send_server_output_formats(void) @@ -1356,6 +1368,7 @@ read_raw_audio_data(void *arg) int error; struct trans *strans; char path[256]; + char paserver_string[256]; struct stream *outs; strans = trans_create(TRANS_MODE_UNIX, 8192, 8192); @@ -1388,7 +1401,21 @@ read_raw_audio_data(void *arg) for upto one minute */ for (i = 0; i < 60; i++) { - simple = pa_simple_new(NULL, "xrdp", PA_STREAM_RECORD, NULL, + // RAJA FIXME + // How can I make this work with the distributed server system!?!? + // pa_simple_new can take a server as its first argument, but each server can have multiple sessions active at any given time... + // This will involve reserving a range of ports (e.g. port 2000 and up), and setting PULSE_SERVER=tcp::<2000 + X11 display number> + // The pulseaudio server would then need to be manually started before TDE starts with something like these commands: + // pulseaudio -D --load="module-native-protocol-tcp listen=0.0.0.0 port=<2000 + X11 display number>" + // Then the first argument to pa_simple_new needs to use the same syntax; i.e. "tcp:node001.cluster90.local:2010" + char errcode; + char* remote_backend_hostname = raptor_sm_get_hostname_for_display(g_display_num); + char* ip = raptor_sm_get_ip_for_hostname(remote_backend_hostname, &errcode); + g_free(remote_backend_hostname); + g_snprintf(paserver_string, 255, "tcp:%s:%d", ip, (RAPTOR_SM_BASE_PULSEAUDIO_PORT + g_display_num)); + g_free(ip); + LOG(0, ("read_raw_audio_data: connecting to pulseaudio server with connection string %s\n", paserver_string)); + simple = pa_simple_new(paserver_string, "xrdp", PA_STREAM_RECORD, NULL, "record", &samp_spec, NULL, NULL, &error); if (simple)