From baf7d64cab0961615dc97d904ad706c15a8d161f Mon Sep 17 00:00:00 2001 From: MrMelon Date: Thu, 29 Apr 2021 17:31:50 +0100 Subject: [PATCH] Finish building daemon, refresh peers, cli and gui --- .gitignore | 1 + src/impl/cli/main.c | 235 ++++++++++++++++++++++++++- src/impl/cli/open_gui.c | 67 +++++++- src/impl/daemon/main.c | 199 ++++++++++++++++++----- src/impl/daemon/popen2.c | 36 ++++ src/impl/gui/main.c | 162 ++++++++++++++---- src/impl/refresh-peers/main.c | 3 +- src/impl/shared/states.c | 24 +++ src/impl/shared/unix_socket_client.c | 4 +- src/impl/shared/unix_socket_server.c | 10 +- src/intf/melon_vpn_about.h | 8 + src/intf/melon_vpn_sock.h | 7 +- src/intf/open_gui.h | 9 +- src/intf/popen2.h | 5 + src/intf/states.h | 7 + 15 files changed, 680 insertions(+), 97 deletions(-) create mode 100644 src/impl/daemon/popen2.c create mode 100644 src/impl/shared/states.c create mode 100644 src/intf/melon_vpn_about.h create mode 100644 src/intf/popen2.h diff --git a/.gitignore b/.gitignore index 849ddff..aaea3dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ dist/ +package/ diff --git a/src/impl/cli/main.c b/src/impl/cli/main.c index 1c325a5..15d4c69 100644 --- a/src/impl/cli/main.c +++ b/src/impl/cli/main.c @@ -1,21 +1,75 @@ #include #include #include +#include +#include +#include +#include #include "states.h" #include "open_gui.h" +#include "unix_sockets.h" +#include "melon_vpn_sock.h" +#include "melon_vpn_about.h" #ifndef PROJ_VERSION #define PROJ_VERSION "unknown" #endif States currentstate; +char *currentpeers; +bool currentisrestart; char *version = PROJ_VERSION; +bool is_gui = false; +thrd_t listenthr; +atomic_bool listenserverready = false; + +int send_to_daemon(char*, ssize_t); +int refresh_vpn(); +int status_vpn(); +int peers_vpn(); +int start_vpn(); +int stop_vpn(); +int restart_conf_vpn(bool); + +int start_client_receiver(void*); +int listen_client_receiver(int); + +void start_listen_thread(); +void wait_listen_thread(); void update_state(States state) { currentstate = state; } +bool incoming_state(char *state) { + currentstate = enum_state(state); + if(is_gui) { + gui_trigger_state(currentstate); + return false; + } else { + return true; + } +} + +bool incoming_peers(char *peers) { + currentpeers = peers; + if(is_gui) { + gui_trigger_peers(peers); + return false; + } + return true; +} + +bool incoming_isrestart(char *isrestart) { + currentisrestart = strcmp(isrestart,"on")==0; + if(is_gui) { + gui_trigger_isrestart(currentisrestart); + return false; + } + return true; +} + int is_arg(int ac, char **argv, char *arg) { if (ac < 2) { return 0; @@ -34,19 +88,23 @@ void display_version(bool is_debug) { } void display_about(bool is_debug) { - printf("Melon VPN\n"); + printf("%s\n", about_name); display_version(is_debug); - printf("Copyright OnPointCoding\n"); - printf("https://software.onpointcoding.net\n"); - printf("OnPointCoding.net\n"); - printf("Author: MrMelon54\n"); - printf("Artist: MrMelon54\n"); + printf("%s\n", about_copyright); + printf("%s\n", about_url); + printf("%s\n", about_website); + printf("Author: %s\n", about_author); + printf("Artist: %s\n", about_artist); } void display_help(bool is_debug) { printf("Melon VPN Help\n"); - printf("-h, --help Display this help message\n"); - printf("--about About this program\n"); + printf("-h, --help Display this help message\n"); + printf("--about About this program\n"); + printf("connect, -c Connect to VPN\n"); + printf("disconnect, -d Disconnect from VPN\n"); + printf("restart , Enable or disable restart mode\n"); + printf(" -r \n"); } int main (int argc, char **argv) { @@ -70,10 +128,169 @@ int main (int argc, char **argv) { return 0; } + start_listen_thread(); + + struct timespec *t = malloc(sizeof t); + t->tv_nsec = 1000; + while(!listenserverready) { + thrd_sleep(t,NULL); + } + if(is_arg(argc, argv, "--gui")) { - open_gui(argc, argv, is_debug); + is_gui = true; + open_gui(argc, argv, is_debug, &start_vpn, &stop_vpn, &restart_conf_vpn, &refresh_vpn); + is_gui = false; return 0; } + if(argc==2) { + if(strcmp(argv[1],"status")==0 || strcmp(argv[1],"-s")==0) { + status_vpn(); + } else if(strcmp(argv[1],"peers")==0 || strcmp(argv[1],"-p")==0) { + peers_vpn(); + } else if(strcmp(argv[1],"connect")==0 || strcmp(argv[1],"-c")==0) { + start_vpn(); + } else if(strcmp(argv[1],"disconnect")==0 || strcmp(argv[1],"-d")==0) { + stop_vpn(); + } + } else if(argc==3) { + if(strcmp(argv[1],"restart")==0 || strcmp(argv[1],"-r")==0) { + if(strcmp(argv[2],"enable")==0 || strcmp(argv[2],"on")==0) { + restart_conf_vpn(true); + } else if(strcmp(argv[2],"disable")==0 || strcmp(argv[2],"off")==0) { + restart_conf_vpn(false); + } + } + } + return status; } + +void start_listen_thread() { + thrd_create(&listenthr, start_client_receiver, NULL); +} + +void wait_listen_thread() { + thrd_join(listenthr,NULL); +} + +int send_to_daemon(char *buf, ssize_t n) { + int sfd = unix_socket_client_start(SV_DAEMON_SOCK_PATH); + if(sfd==-1) { + fprintf(stderr, "Make sure the daemon is running before trying to use it.\n"); + return 1; + } + + write(sfd, buf, n); + close(sfd); + + fprintf(stderr, "Closed connection to socket\n"); + return 0; +} + +int start_client_server() { + int sfd = unix_socket_server_start(SV_CLIENT_SOCK_PATH); + + listenserverready = true; + + ssize_t numRead; + int MAX_PEERS_LEN = 1000; + char msg[MAX_PEERS_LEN]; + char buf[BUF_SIZE]; + int total = 0; + + for(;;) { + int cfd = accept(sfd, NULL, NULL); + + strcpy(msg, ""); + strcpy(buf, ""); + total = 0; + + while ((numRead = read(cfd, buf, BUF_SIZE)) > 0) { + if(total > MAX_PEERS_LEN-1) break; + total+=numRead; + strcat(msg, buf); + msg[MAX_PEERS_LEN-1]=0; + } + + fprintf(stderr, "Incoming request: %s\n",msg); + + char *a = strtok(msg,"\1"); + if(strcmp(a,"client")==0) { + char *b = strtok(NULL,"\1"); + if(strcmp(b,"status")==0) { + char *c = strtok(NULL,"\1"); + if(incoming_state(c)) break; + } else if(strcmp(b,"peers")==0) { + char *c = strtok(NULL,"\1"); + if(incoming_peers(c)) break; + } else if(strcmp(b,"isrestart")==0) { + char *c = strtok(NULL,"\1"); + if(incoming_isrestart(c)) break; + } + } + } + + return 0; +} + +int start_client_receiver(void *thr_data) { + (void)thr_data; + + start_client_server(); + return 0; +} + +int status_vpn() { + char *msg = "daemon\1status"; + send_to_daemon(msg, strlen(msg)); + wait_listen_thread(); + printf("Melon VPN status: %s\n", string_state(currentstate)); + return 0; +} + +int peers_vpn() { + char *msg = "daemon\1peers"; + send_to_daemon(msg, strlen(msg)); + wait_listen_thread(); + printf("Melon VPN peers:\n%s\n", currentpeers); + return 0; +} + +int start_vpn() { + char *msg = "daemon\1connect"; + return send_to_daemon(msg, strlen(msg)); +} + +int stop_vpn() { + char *msg = "daemon\1disconnect"; + return send_to_daemon(msg, strlen(msg)); +} + +int refresh_vpn() { + char *msg = "daemon\1status"; + int a=send_to_daemon(msg, strlen(msg)); + + char *msg2 = "daemon\1peers"; + int b=send_to_daemon(msg2, strlen(msg2)); + + char *msg3 = "daemon\1isrestart"; + int c=send_to_daemon(msg3, strlen(msg3)); + + return a+b+c; +} + +int restart_conf_vpn(bool enable) { + char *msgprefix = "daemon\1restart\1"; + int prefixlen = strlen(msgprefix); + int msglen = prefixlen + (enable ? 2 : 3); + + char msg[msglen+1]; + strcpy(msg, msgprefix); + msg[prefixlen] = 0; + + strcat(msg, enable ? "on" : "off"); + msg[msglen] = 0; + + return send_to_daemon(msg, msglen+1); +} diff --git a/src/impl/cli/open_gui.c b/src/impl/cli/open_gui.c index 9995a0a..1b6e4b2 100644 --- a/src/impl/cli/open_gui.c +++ b/src/impl/cli/open_gui.c @@ -4,10 +4,12 @@ #include "magic_code.h" #include "open_gui.h" -int open_gui(int argc, char **argv, bool is_debug) { - void *lib_handle; +void *lib_handle; +bool gui_trigger_safe = false; + +int open_gui(int argc, char **argv, bool is_debug, int (*start_vpn)(), int (*stop_vpn)(), int (*restart_conf_vpn)(bool), int (*refresh_vpn)()) { void (*fn)(int*, int*); - int (*gui)(int, char**); + int (*gui)(int argc, char** argv, bool is_debug, int (*start_vpn)(), int (*stop_vpn)(), int (*restart_conf_vpn)(bool), int (*refresh_vpn)()); int a = 0; int b = 0; char *error; @@ -30,6 +32,7 @@ int open_gui(int argc, char **argv, bool is_debug) { fprintf(stderr, "The function 'get_magic_code' couldn't be found\n"); fprintf(stderr, "Check the package 'melonvpngui' is installed correctly\n"); fprintf(stderr, "%s\n", error); + dlclose(lib_handle); return 1; } @@ -42,16 +45,72 @@ int open_gui(int argc, char **argv, bool is_debug) { fprintf(stderr, "The function 'run_gui' couldn't be found\n"); fprintf(stderr, "Check the package 'melonvpngui' is installed correctly\n"); fprintf(stderr, "%s\n", error); + dlclose(lib_handle); return 1; } + gui_trigger_safe = true; + int fake_argc = 1; char *fake_argv[1] = {0}; fake_argv[0] = argv[0]; - (*gui)(fake_argc,fake_argv); + (*gui)(fake_argc, fake_argv, is_debug, start_vpn, stop_vpn, restart_conf_vpn, refresh_vpn); } + gui_trigger_safe = false; + dlclose(lib_handle); return 0; } + +int gui_trigger_state(States state) { + if(!gui_trigger_safe) return 100; + + char *error; + void (*trigger)(States); + trigger = dlsym(lib_handle, "mod_trigger_state"); + + if((error = dlerror()) != NULL) { + fprintf(stderr, "Failed to run 'mod_trigger_state'\n"); + fprintf(stderr, "%s\n", error); + return 1; + } + + (*trigger)(state); + return 0; +} + +int gui_trigger_isrestart(bool isrestart) { + if(!gui_trigger_safe) return 100; + + char *error; + void (*trigger)(bool); + trigger = dlsym(lib_handle, "mod_trigger_isrestart"); + + if((error = dlerror()) != NULL) { + fprintf(stderr, "Failed to run 'mod_trigger_isrestart'\n"); + fprintf(stderr, "%s\n", error); + return 1; + } + + (*trigger)(isrestart); + return 0; +} + +int gui_trigger_peers(char *peers) { + if(!gui_trigger_safe) return 100; + + char *error; + void (*trigger)(char*); + trigger = dlsym(lib_handle, "mod_trigger_peers"); + + if((error = dlerror()) != NULL) { + fprintf(stderr, "Failed to run 'mod_trigger_peers'\n"); + fprintf(stderr, "%s\n", error); + return 1; + } + + (*trigger)(peers); + return 0; +} diff --git a/src/impl/daemon/main.c b/src/impl/daemon/main.c index e513377..52e75ff 100644 --- a/src/impl/daemon/main.c +++ b/src/impl/daemon/main.c @@ -5,13 +5,16 @@ #include #include #include -#include #include +#include +#include +#include #include "states.h" #include "unix_sockets.h" #include "melon_vpn_sock.h" #include "config_file.h" +#include "popen2.h" #define vpnconfig "/etc/melonvpn/client.cfg" #define daemonconfig "/etc/melonvpn/daemon.cfg" @@ -20,27 +23,53 @@ char *vpnserver = ""; char *devicename = "unknown"; bool restartvpn = false; +char *storedpeers; +pid_t vpn_process = -1; +States currentstate; + int start_daemon_server(void*); int start_peers_server(void*); +void send_to_client(char*, ssize_t); -static volatile int keepRunning = 1; -atomic_bool daemonthrbusy = false; -atomic_bool peersthrbusy = false; +int start_vpn_process(); +void stop_vpn_process(); thrd_t daemonthr; thrd_t peersthr; void read_vpn_config(); void read_daemon_config(); +void write_daemon_config(); int main(int argc, char **argv) { + currentstate = DISCONNECTED; + printf("Reading config files...\n"); read_vpn_config(); read_daemon_config(); printf("VPN server: %s\n", vpnserver); printf("Device name: %s\n", devicename); - printf("Restart VPN: %s\n", restartvpn?"true":"false"); + printf("Restart VPN: %s\n", restartvpn ? "true" : "false"); + + printf("Create folder for sockets\n"); + + // why check stat first its slower? + char sock_wrapper_path[100] = SV_WRAPPER_SOCK_PATH; + umask(0); + + // Try removing sockets + unlink(SV_CLIENT_SOCK_PATH); + unlink(SV_DAEMON_SOCK_PATH); + unlink(SV_RPEERS_SOCK_PATH); + + // Remove wrapping directory and make a new one + rmdir(sock_wrapper_path); + int mkdirout = mkdir(sock_wrapper_path, 0777); // user: rw, group: rw, everyone: w + if(mkdirout!=0) { + fprintf(stderr, "Failed to create directory for sockets (%d)\n",mkdirout); + return 1; + } thrd_create(&daemonthr, start_daemon_server, NULL); thrd_create(&peersthr, start_peers_server, NULL); @@ -50,18 +79,66 @@ int main(int argc, char **argv) { } void incoming_request(char *request) { - char *a; - char *b; - a=strtok(request,(char*)1); - b=strtok(NULL,""); - fprintf(stderr,a); - fprintf(stderr,b); + fprintf(stderr, "Incoming request: %s\n",request); + char *a = strtok(request, "\1"); + + if(strcmp(a,"daemon")==0) { + char *b = strtok(NULL, "\1"); + + if(strcmp(b,"status")==0) { + send_vpn_status(); + } else if(strcmp(b,"connect")==0) { + if(start_vpn_process()==0) { + currentstate = CONNECTED; + } else { + currentstate = DISCONNECTED; + } + send_vpn_status(); + } else if(strcmp(b,"disconnect")==0) { + stop_vpn_process(); + currentstate = DISCONNECTED; + send_vpn_status(); + } else if(strcmp(b,"isrestart")==0) { + send_is_restart_status(); + } else if(strcmp(b,"restart")==0) { + char *c = strtok(NULL, "\1"); + restartvpn=strcmp(c,"on")==0; + write_daemon_config(); + } + } } void incoming_peers(char *peers) { - char *a; - char *b; - fprintf(stderr,peers); + storedpeers = peers; + send_to_client(peers, strlen(peers)); +} + +void send_vpn_status() { + char *msgprefix = "client\1status\1"; + int prefixl = strlen(msgprefix); + char *msgsuffix = string_state(currentstate); + int suffixl = strlen(msgsuffix); + int total = prefixl+suffixl; + char msg[total+1]; + strcpy(msg, msgprefix); + msg[prefixl] = 0; + strcat(msg, msgsuffix); + msg[total] = 0; + send_to_client(msg, total+1); +} + +void send_is_restart_status() { + char *msgprefix = "client\1isrestart\1"; + int prefixl = strlen(msgprefix); + char *msgsuffix = restartvpn ? "on" : "off"; + int suffixl = strlen(msgsuffix); + int total = prefixl+suffixl; + char msg[total+1]; + strcpy(msg, msgprefix); + msg[prefixl]=0; + strcat(msg, msgsuffix); + msg[total]=0; + send_to_client(msg, total+1); } void read_vpn_config() { @@ -111,41 +188,65 @@ void write_daemon_config() { fclose(fp); } +int start_vpn_process() { + fprintf(stderr, "ready to start: %d\n", vpn_process); + if(vpn_process != -1) return; + + // Command line arguments for simple-vpn + char* const command[] = {"simple-vpn", "client", vpnconfig, NULL}; + + fprintf(stderr, "Attempting to start simple-vpn.\n"); + + int a; + int b; + pid_t pp = popen2(command, &a, &b); + if(pp < 0){ + fprintf(stderr, "Could not start simple-vpn.\n"); + return 1; + } + + vpn_process = pp; + return 0; +} + +void stop_vpn_process() { + if(vpn_process < 0) return; + fprintf(stderr, "Stopping simple-vpn (%d)\n", vpn_process); + + kill(vpn_process, SIGTERM); + waitpid(vpn_process,NULL,0); + vpn_process = -1; +} + int start_daemon_server(void *thr_data) { (void)thr_data; - // Just too lazy to keep all this shit here... - // functions are better int sfd = unix_socket_server_start(SV_DAEMON_SOCK_PATH); ssize_t numRead; char buf[BUF_SIZE]; + int MAX_PEERS_LEN = 1000; + int total = 0; + char msg[MAX_PEERS_LEN]; - // Client connections are handled iteratively - for (;;) { + for(;;) { int cfd = accept(sfd, NULL, NULL); - // Read at most BUF_SIZE bytes from the socket into buf. + total = 0; + strcpy(msg, ""); + strcpy(buf, ""); + while ((numRead = read(cfd, buf, BUF_SIZE)) > 0) { - // Then, write those bytes from buf into STDOUT. + if(total > MAX_PEERS_LEN-1) break; + total+=numRead; - incoming_request(buf); - - if (write(STDOUT_FILENO, buf, numRead) != numRead) { - fprintf(stderr,"Partial/failed write"); - return 0; - } + // Append buf to msg then clear buf + strcat(msg, buf); + strcpy(buf, ""); + msg[total]=0; } - if (numRead == -1) { - fprintf(stderr,"Failed to read"); - return 0; - } - - if (close(cfd) == -1) { - fprintf(stderr,"Failed to close"); - return 0; - } + incoming_request(msg); } return 0; @@ -157,25 +258,39 @@ int start_peers_server(void *thr_data) { int sfd = unix_socket_server_start(SV_RPEERS_SOCK_PATH); ssize_t numRead; + int MAX_PEERS_LEN = 1000; + char msg[MAX_PEERS_LEN]; char buf[BUF_SIZE]; + int total = 0; for(;;) { int cfd = accept(sfd, NULL, NULL); - int MAX_PEERS_LEN = 1000; - int total = 0; - char peers[MAX_PEERS_LEN]; - strcpy(peers, ""); + strcpy(msg, ""); + strcpy(buf, ""); + total = 0; while ((numRead = read(cfd, buf, BUF_SIZE)) > 0) { if(total > MAX_PEERS_LEN-1) break; total+=numRead; - strcat(peers, buf); - peers[MAX_PEERS_LEN-1]=0; + strcat(msg, buf); + msg[MAX_PEERS_LEN-1]=0; } - incoming_peers(buf); + incoming_peers(msg); } return 0; } + +void send_to_client(char *buf, ssize_t n) { + int sfd = unix_socket_client_start(SV_CLIENT_SOCK_PATH); + if(sfd==-1) { + return; + } + + write(sfd, buf, n); + close(sfd); + + fprintf(stderr, "Closed connection to socket\n"); +} diff --git a/src/impl/daemon/popen2.c b/src/impl/daemon/popen2.c new file mode 100644 index 0000000..8f18780 --- /dev/null +++ b/src/impl/daemon/popen2.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#define READ 0 +#define WRITE 1 + +// omg thanks +// https://stackoverflow.com/a/12788169/10719432 +pid_t popen2(char* const *command, int *infp, int *outfp) { + int p_stdin[2], p_stdout[2]; + pid_t pid; + + if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) return -1; + + pid = fork(); + + if (pid < 0) return pid; + else if (pid == 0) { + close(p_stdin[WRITE]); + dup2(p_stdin[READ], READ); + close(p_stdout[READ]); + dup2(p_stdout[WRITE], WRITE); + + execvp(command[0], command); + exit(1); + } + + if (infp == NULL) close(p_stdin[WRITE]); + else *infp = p_stdin[WRITE]; + + if (outfp == NULL) close(p_stdout[READ]); + else *outfp = p_stdout[READ]; + + return pid; +} diff --git a/src/impl/gui/main.c b/src/impl/gui/main.c index 094deca..e817215 100644 --- a/src/impl/gui/main.c +++ b/src/impl/gui/main.c @@ -1,16 +1,39 @@ #include #include #include +#include +#include + +#include #include "states.h" #include "statusicon.h" #include "magic_code.h" +#include "melon_vpn_about.h" GtkApplication *app; GdkPixbuf *appicon; char *statusiconoff; char *statusiconon; States currentstate; +char *currentpeers; +bool restarttoggle = false; +bool cli_is_debug = false; + +// Window shit +GtkWidget *window; +GtkWidget *box; +GtkWidget *button; +GtkWidget *button2; +GtkWidget *button3; +GtkWidget *button4; +GtkWidget *statustxt; + +// Callback functions for the code in the CLI +int (*cli_start_vpn)(); +int (*cli_stop_vpn)(); +int (*cli_refresh_vpn)(); +int (*cli_restart_conf_vpn)(bool); void update_state(States state) { currentstate = state; @@ -25,25 +48,41 @@ void update_state(States state) { void open_about(GtkApplication* app) { GtkWidget *about = gtk_about_dialog_new(); - gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),"Melon VPN"); + gtk_about_dialog_set_program_name(GTK_ABOUT_DIALOG(about),about_name); gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about),"v1.0.0"); - gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),"Copyright OnPointCoding"); + gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about),about_copyright); gtk_about_dialog_set_license_type(GTK_ABOUT_DIALOG(about),GTK_LICENSE_UNKNOWN); - gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),"https://software.onpointcoding.net"); - gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about),"OnPointCoding.net"); + gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about),about_url); + gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about),about_website); gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about),appicon); - const char *authors[2] = {"MrMelon54",NULL}; + const char *authors[2] = {about_author,NULL}; gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about),authors); - const char *artists[2] = {"MrMelon54",NULL}; + const char *artists[2] = {about_artist,NULL}; gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(about),artists); gtk_widget_show_all(about); } -void open_paint_btn(GtkButton *button) { - update_state((currentstate + 1) % 3); +void open_start_btn(GtkButton *button) { + (*cli_start_vpn)(); +} + +void open_stop_btn(GtkButton *button) { + (*cli_stop_vpn)(); +} + +void open_restart_toggle_btn(GtkButton *button) { + restarttoggle = !restarttoggle; + (*cli_restart_conf_vpn)(restarttoggle); + update_restart_toggle_btn_label(); +} + +void update_restart_toggle_btn_label() { + char restartbtnlabel[] = "Restart [ ]"; + if(restarttoggle) restartbtnlabel[9] = '#'; + gtk_button_set_label(GTK_BUTTON(button3), restartbtnlabel); } void open_about_btn(GtkButton *button) { @@ -51,14 +90,9 @@ void open_about_btn(GtkButton *button) { } void activate(GtkApplication* app) { - GtkWidget *window; - GtkWidget *box; - GtkWidget *button; - GtkWidget *button2; - window = gtk_application_window_new(app); gtk_window_set_title(GTK_WINDOW(window),"Melon VPN"); - gtk_window_set_default_size(GTK_WINDOW(window),400,400); + gtk_window_set_default_size(GTK_WINDOW(window),300,300); // Setup status icon now window is available status_icon_create(window,statusiconoff,statusiconon); @@ -66,19 +100,41 @@ void activate(GtkApplication* app) { gtk_container_set_border_width(GTK_CONTAINER(window),8); - button = gtk_button_new_with_label("Start"); - g_signal_connect(button,"clicked",G_CALLBACK(open_paint_btn),NULL); + PangoFontDescription *font = pango_font_description_new(); + pango_font_description_set_family(font,"Monospace"); - button2 = gtk_button_new_with_label("About"); - g_signal_connect(button2,"clicked",G_CALLBACK(open_about_btn),NULL); + button = gtk_button_new_with_label("Start"); + gtk_widget_modify_font(GTK_WIDGET(button), font); + g_signal_connect(button,"clicked",G_CALLBACK(open_start_btn),NULL); + + button2 = gtk_button_new_with_label("Stop"); + gtk_widget_modify_font(GTK_WIDGET(button2), font); + g_signal_connect(button2,"clicked",G_CALLBACK(open_stop_btn),NULL); + + button3 = gtk_button_new_with_label("Restart [ ]"); + gtk_widget_modify_font(GTK_WIDGET(button3), font); + g_signal_connect(button3,"clicked",G_CALLBACK(open_restart_toggle_btn),NULL); + + button4 = gtk_button_new_with_label("About"); + gtk_widget_modify_font(GTK_WIDGET(button4), font); + g_signal_connect(button4,"clicked",G_CALLBACK(open_about_btn),NULL); + + statustxt = gtk_label_new(""); + gtk_widget_modify_font(GTK_WIDGET(statustxt), font); box = gtk_fixed_new(); gtk_container_add(GTK_CONTAINER(window),box); - gtk_fixed_put(GTK_FIXED(box),button,5,5); - gtk_fixed_put(GTK_FIXED(box),button2,100,60); + gtk_fixed_put(GTK_FIXED(box),button,10,40); + gtk_fixed_put(GTK_FIXED(box),button2,100,40); + gtk_fixed_put(GTK_FIXED(box),button3,190,40); + gtk_fixed_put(GTK_FIXED(box),button4,190,5); + gtk_fixed_put(GTK_FIXED(box),statustxt,10,10); gtk_widget_show_all(window); + + // Refresh data when loading the GUI + (*cli_refresh_vpn)(); } void get_magic_code(int *a, int *b) { @@ -86,39 +142,69 @@ void get_magic_code(int *a, int *b) { *b = MAGIC_CODE_B; } -int run_gui(int argc, char **argv) { +int run_gui(int argc, char **argv, bool is_debug, int (*start_vpn)(), int (*stop_vpn)(), int (*restart_conf_vpn)(bool), int (*refresh_vpn)()) { int status; + cli_is_debug = is_debug; + cli_start_vpn = start_vpn; + cli_stop_vpn = stop_vpn; + cli_refresh_vpn = refresh_vpn; + cli_restart_conf_vpn = restart_conf_vpn; + statusiconoff = ""; statusiconon = ""; + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) == NULL) { + fprintf(stderr, "Failed to get current directory\n"); + return 1; + } + + int cwdlen = strlen(cwd); + + char officonname[] = "/statusmelonoff.png"; + int officonl = cwdlen+strlen(officonname)+1; + char officonpath[officonl]; + strcpy(officonpath, cwd); + officonpath[cwdlen] = 0; + strcat(officonpath, officonname); + officonpath[officonl-1] = 0; + + char oniconname[] = "/statusmelonon.png"; + int oniconl = cwdlen+strlen(oniconname)+1; + char oniconpath[oniconl]; + strcpy(oniconpath, cwd); + oniconpath[cwdlen] = 0; + strcat(oniconpath, oniconname); + oniconpath[oniconl-1] = 0; + if(access("melonvpn.png",R_OK) == 0) { appicon = gdk_pixbuf_new_from_file("melonvpn.png",NULL); } else if(access("/usr/lib/melonvpn/melonvpn.png",R_OK) == 0) { appicon = gdk_pixbuf_new_from_file("/usr/lib/melonvpn/melonvpn.png",NULL); } - if(access("/usr/lib/melonvpn/statusmelonoff.png",R_OK) == 0) { + if(access(officonpath,R_OK) == 0) { + statusiconoff = officonpath; + } else if(access("/usr/lib/melonvpn/statusmelonoff.png",R_OK) == 0) { statusiconoff = "/usr/lib/melonvpn/statusmelonoff.png"; - } else { - fprintf(stderr,"WARN: Unable to find statusmelonoff.png\n"); } - if(access("/usr/lib/melonvpn/statusmelonon.png",R_OK) == 0) { + if(access(oniconpath,R_OK) == 0) { + statusiconon = oniconpath; + } else if(access("/usr/lib/melonvpn/statusmelonon.png",R_OK) == 0) { statusiconon = "/usr/lib/melonvpn/statusmelonon.png"; - } else { - fprintf(stderr,"WARN: Unable to find statusmelonon.png\n"); } if(appicon == NULL) { fprintf(stderr,"ERROR: Failed to load program logo\n"); return 1; } - if(statusiconoff == NULL) { + if(strcmp(statusiconoff,"")==0) { fprintf(stderr,"ERROR: Failed to load status off icon\n"); return 1; } - if(statusiconon == NULL) { + if(strcmp(statusiconon,"")==0) { fprintf(stderr,"ERROR: Failed to load status on icon\n"); return 1; } @@ -132,3 +218,21 @@ int run_gui(int argc, char **argv) { return status; } + +void mod_trigger_state(States state) { + currentstate = state; + + char *statelbl = string_state_upper(state); + fprintf(stderr, "hi: %s\n", statelbl); + + gtk_label_set_text(GTK_LABEL(statustxt), statelbl); +} + +void mod_trigger_peers(char *peers) { + strcpy(currentpeers, peers); +} + +void mod_trigger_isrestart(bool isrestart) { + restarttoggle = isrestart; + update_restart_toggle_btn_label(); +} diff --git a/src/impl/refresh-peers/main.c b/src/impl/refresh-peers/main.c index a1eda6d..c2f5aeb 100644 --- a/src/impl/refresh-peers/main.c +++ b/src/impl/refresh-peers/main.c @@ -86,8 +86,7 @@ void send_to_daemon(char *buf, ssize_t n) { } write(sfd, buf, n); + close(sfd); - // Closes our socket; server sees EOF. - exit(EXIT_SUCCESS); fprintf(stderr, "Closed connection to socket"); } diff --git a/src/impl/shared/states.c b/src/impl/shared/states.c new file mode 100644 index 0000000..68ecab0 --- /dev/null +++ b/src/impl/shared/states.c @@ -0,0 +1,24 @@ +#include + +#include "states.h" + +char *string_state(States state) { + if(state == CONNECTED) return "connected"; + else if(state == DISCONNECTED) return "disconnected"; + else if(state == RESTARTING) return "restarting"; + else return "unknown"; +} + +char *string_state_upper(States state) { + if(state == CONNECTED) return "Connected"; + else if(state == DISCONNECTED) return "Disconnected"; + else if(state == RESTARTING) return "Restarting"; + else return "Unknown"; +} + +States enum_state(char *state) { + if(strcmp(state,"connected")==0) return CONNECTED; + else if(strcmp(state,"disconnected")==0) return DISCONNECTED; + else if(strcmp(state,"restarting")==0) return RESTARTING; + else return UNKNOWN; +} diff --git a/src/impl/shared/unix_socket_client.c b/src/impl/shared/unix_socket_client.c index fc87ead..5f76d2b 100644 --- a/src/impl/shared/unix_socket_client.c +++ b/src/impl/shared/unix_socket_client.c @@ -14,7 +14,7 @@ int unix_socket_client_start(char *sock_path) { // Make sure socket's file descriptor is legit. if (sfd == -1) { - fprintf(stderr,"ERROR: socket is not legit"); + fprintf(stderr,"ERROR: socket is not legit\n"); return -1; } @@ -28,7 +28,7 @@ int unix_socket_client_start(char *sock_path) { // Connects the active socket referred to be sfd to the listening socket // whose address is specified by addr. if (connect(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) { - fprintf(stderr,"Failed to connect"); + fprintf(stderr,"Failed to connect\n"); return -1; } diff --git a/src/impl/shared/unix_socket_server.c b/src/impl/shared/unix_socket_server.c index 2410624..371e76f 100644 --- a/src/impl/shared/unix_socket_server.c +++ b/src/impl/shared/unix_socket_server.c @@ -15,20 +15,20 @@ int unix_socket_server_start(char *sock_path) { // Make sure socket's file descriptor is legit. if (sfd == -1) { - fprintf(stderr,"ERROR: socket is not legit"); + fprintf(stderr,"ERROR: socket is not legit\n"); return -1; } // Make sure the address we're planning to use isn't too long. if (strlen(sock_path) > sizeof(addr.sun_path) - 1) { - fprintf(stderr,"Server socket path too long: %s",sock_path); + fprintf(stderr,"Server socket path too long: %s\n",sock_path); return -1; } // Delete any file that already exists at the address. Make sure the deletion // succeeds. If the error is just that the file/directory doesn't exist, it's fine. if (remove(sock_path) == -1 && errno != ENOENT) { - fprintf(stderr,"remove-%s",sock_path); + fprintf(stderr,"remove-%s\n",sock_path); return -1; } @@ -40,7 +40,7 @@ int unix_socket_server_start(char *sock_path) { // Bind the socket to the address. Note that we're binding the server socket // to a well-known address so that clients know where to connect. if (bind(sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un)) == -1) { - fprintf(stderr,"Failed to bind"); + fprintf(stderr,"Failed to bind\n"); return -1; } @@ -49,7 +49,7 @@ int unix_socket_server_start(char *sock_path) { // listen cannot be called on a connected socket (a socket on which a connect() // has been succesfully performed or a socket returned by a call to accept()). if (listen(sfd, BACKLOG) == -1) { - fprintf(stderr,"Failed to listen"); + fprintf(stderr,"Failed to listen\n"); return -1; } diff --git a/src/intf/melon_vpn_about.h b/src/intf/melon_vpn_about.h new file mode 100644 index 0000000..828bf20 --- /dev/null +++ b/src/intf/melon_vpn_about.h @@ -0,0 +1,8 @@ +#pragma once + +#define about_name "Melon VPN" +#define about_copyright "Copyright OnPointCoding" +#define about_url "https://software.onpointcoding.net/melonvpn" +#define about_website "OnPointCoding.net" +#define about_author "MrMelon54" +#define about_artist "MrMelon54" diff --git a/src/intf/melon_vpn_sock.h b/src/intf/melon_vpn_sock.h index bcc551c..1781425 100644 --- a/src/intf/melon_vpn_sock.h +++ b/src/intf/melon_vpn_sock.h @@ -1,5 +1,6 @@ #pragma once -#define SV_DAEMON_SOCK_PATH "/tmp/melonvpndaemon.sock" -#define SV_RPEERS_SOCK_PATH "/tmp/melonvpnrefreshpeers.sock" -#define SV_CLIENT_SOCK_PATH "/tmp/melonvpn.sock" +#define SV_WRAPPER_SOCK_PATH "/run/melonvpn" +#define SV_DAEMON_SOCK_PATH "/run/melonvpn/melonvpndaemon.sock" +#define SV_RPEERS_SOCK_PATH "/run/melonvpn/melonvpnrefreshpeers.sock" +#define SV_CLIENT_SOCK_PATH "/run/melonvpn/melonvpnclient.sock" diff --git a/src/intf/open_gui.h b/src/intf/open_gui.h index d395e49..6e6e77b 100644 --- a/src/intf/open_gui.h +++ b/src/intf/open_gui.h @@ -1,4 +1,11 @@ #pragma once + #include -int open_gui(int argc, char **argv, bool is_debug); +#include "states.h" + +int open_gui(int argc, char **argv, bool is_debug, int (*start_vpn)(), int (*stop_vpn)(), int (*restart_conf_vpn)(bool), int (*refresh_vpn)()); + +int gui_trigger_state(States state); +int gui_trigger_peers(char *peers); +int gui_trigger_isrestart(bool isrestart); diff --git a/src/intf/popen2.h b/src/intf/popen2.h new file mode 100644 index 0000000..e8e11ba --- /dev/null +++ b/src/intf/popen2.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +pid_t popen2(char* const *command, int *infp, int *outfp); diff --git a/src/intf/states.h b/src/intf/states.h index 629779a..8d329ce 100644 --- a/src/intf/states.h +++ b/src/intf/states.h @@ -1,7 +1,14 @@ #pragma once typedef enum { + UNKNOWN, CONNECTED, DISCONNECTED, RESTARTING } States; + +char *string_state(States state); + +char *string_state_upper(States state); + +States enum_state(char *state);