diff --git a/Makefile b/Makefile index a82f9e2..4720a9f 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ daemon_sourcefiles := $(shell find src/impl/daemon/ -name *.c) refreshpeers_sourcefiles := $(shell find src/impl/refresh-peers/ -name *.c) shared_sourcefiles := $(shell find src/impl/shared/ -name *.c) libshared := "src/intf/" - +hidedep := "-Wno-deprecated-declarations" proj_version := $(shell cat project.json | jq .Version -r) @@ -21,15 +21,15 @@ all: build-shared: mkdir -p dist/ && \ mkdir -p dist/libmelonvpnshared-obj/ && \ - ./scripts/gcc_multiwrap.sh -I ${libshared} -- dist/libmelonvpnshared.a dist/libmelonvpnshared-obj/ ${shared_sourcefiles} + ./scripts/gcc_multiwrap.sh ${hidedep} -I ${libshared} -- dist/libmelonvpnshared.a dist/libmelonvpnshared-obj/ ${shared_sourcefiles} build-daemon: mkdir -p dist/ && \ - gcc -o dist/melonvpndaemon -I ${libshared} ${daemon_sourcefiles} dist/libmelonvpnshared.a -pthread + gcc -o dist/melonvpndaemon ${hidedep} -I ${libshared} ${daemon_sourcefiles} dist/libmelonvpnshared.a -pthread build-refreshpeers: mkdir -p dist/ && \ - gcc -o dist/melonvpnrefreshpeers -I ${libshared} ${refreshpeers_sourcefiles} dist/libmelonvpnshared.a obj/mjson.o + gcc -o dist/melonvpnrefreshpeers ${hidedep} -I ${libshared} ${refreshpeers_sourcefiles} dist/libmelonvpnshared.a obj/mjson.o build-user: mkdir -p dist/ && \ @@ -38,11 +38,11 @@ build-user: build-cli: mkdir -p dist/ && \ - gcc -rdynamic -o dist/melonvpn -I ${libshared} ${cli_sourcefiles} dist/libmelonvpnshared.a -DPROJ_VERSION=\"${proj_version}\" -ldl -pthread + gcc -g -O0 -rdynamic -o dist/melonvpn ${hidedep} -I ${libshared} ${cli_sourcefiles} dist/libmelonvpnshared.a -DPROJ_VERSION=\"${proj_version}\" -ldl -pthread build-gui: mkdir -p dist/ && \ - gcc `pkg-config --cflags gtk+-3.0 appindicator3-0.1` -shared -fPIC -o dist/libmelonvpngui.so -I ${libshared} ${gui_sourcefiles} dist/libmelonvpnshared.a `pkg-config --libs gtk+-3.0 appindicator3-0.1` + gcc ${hidedep} `pkg-config --cflags gtk+-3.0 appindicator3-0.1` -shared -fPIC -o dist/libmelonvpngui.so -I ${libshared} ${gui_sourcefiles} dist/libmelonvpnshared.a `pkg-config --libs gtk+-3.0 appindicator3-0.1` build-logo: mkdir -p dist/ && \ diff --git a/src/impl/cli/main.c b/src/impl/cli/main.c index 40e93ab..7f9bd74 100644 --- a/src/impl/cli/main.c +++ b/src/impl/cli/main.c @@ -11,6 +11,7 @@ #include "unix_sockets.h" #include "melon_vpn_sock.h" #include "melon_vpn_about.h" +#include "is_arg.h" #ifndef PROJ_VERSION #define PROJ_VERSION "unknown" @@ -71,18 +72,6 @@ bool incoming_isrestart(char *isrestart) { return true; } -int is_arg(int ac, char **argv, char *arg) { - if (ac < 2) { - return 0; - } - for(int x=1; x < ac; x++) { - if (0 == strcmp(argv[x], arg)) { - return x; // return position of arg - } - } - return 0; // arg not present -} - void display_version() { if(is_debug) printf("v%s-beta\n", version); else printf("v%s\n", version); @@ -200,11 +189,14 @@ int start_client_server() { char buf[BUF_SIZE]; int total = 0; + memset(msg,0,MAX_PEERS_LEN); + memset(buf,0,BUF_SIZE); + for(;;) { int cfd = accept(sfd, NULL, NULL); - strcpy(msg, ""); - strcpy(buf, ""); + memset(msg,0,MAX_PEERS_LEN); + memset(buf,0,BUF_SIZE); total = 0; while ((numRead = read(cfd, buf, BUF_SIZE)) > 0) { @@ -212,22 +204,26 @@ int start_client_server() { total+=numRead; strcat(msg, buf); msg[MAX_PEERS_LEN-1]=0; + memset(buf,0,BUF_SIZE); } - if(is_debug) fprintf(stderr, "Incoming request: %s\n",msg); + // Don't bother checking an empty incoming message + if(total!=0) { + if(is_debug) 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; + 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; + } } } } diff --git a/src/impl/daemon/main.c b/src/impl/daemon/main.c index 52e75ff..8c68216 100644 --- a/src/impl/daemon/main.c +++ b/src/impl/daemon/main.c @@ -34,6 +34,9 @@ void send_to_client(char*, ssize_t); int start_vpn_process(); void stop_vpn_process(); +void send_vpn_status(); +void send_is_restart_status(); + thrd_t daemonthr; thrd_t peersthr; @@ -110,7 +113,21 @@ void incoming_request(char *request) { void incoming_peers(char *peers) { storedpeers = peers; - send_to_client(peers, strlen(peers)); + + fprintf(stderr,peers); + + char *prefix = "client\1peers\1"; + int prel = strlen(prefix); + int l = strlen(peers); + + int t = prel+l+1; + char *msg = malloc(t); + memset(msg,0,t); + strcpy(msg,prefix); + strcat(msg,peers); + + send_to_client(msg, t); + free(msg); } void send_vpn_status() { @@ -190,7 +207,7 @@ void write_daemon_config() { int start_vpn_process() { fprintf(stderr, "ready to start: %d\n", vpn_process); - if(vpn_process != -1) return; + if(vpn_process != -1) return 1; // Command line arguments for simple-vpn char* const command[] = {"simple-vpn", "client", vpnconfig, NULL}; @@ -257,7 +274,7 @@ int start_peers_server(void *thr_data) { int sfd = unix_socket_server_start(SV_RPEERS_SOCK_PATH); - ssize_t numRead; + ssize_t numRead = 0; int MAX_PEERS_LEN = 1000; char msg[MAX_PEERS_LEN]; char buf[BUF_SIZE]; @@ -266,8 +283,8 @@ int start_peers_server(void *thr_data) { for(;;) { int cfd = accept(sfd, NULL, NULL); - strcpy(msg, ""); - strcpy(buf, ""); + memset(msg,0,MAX_PEERS_LEN); + memset(buf,0,BUF_SIZE); total = 0; while ((numRead = read(cfd, buf, BUF_SIZE)) > 0) { @@ -277,6 +294,9 @@ int start_peers_server(void *thr_data) { msg[MAX_PEERS_LEN-1]=0; } + // Don't bother checking an empty incoming message + if(total==0) continue; + incoming_peers(msg); } @@ -289,6 +309,8 @@ void send_to_client(char *buf, ssize_t n) { return; } + fprintf(stderr, "send to client: %s\n", buf); + write(sfd, buf, n); close(sfd); diff --git a/src/impl/gui/main.c b/src/impl/gui/main.c index 1d62362..3bbc2dc 100644 --- a/src/impl/gui/main.c +++ b/src/impl/gui/main.c @@ -3,13 +3,15 @@ #include #include #include - #include #include "states.h" #include "statusicon.h" #include "magic_code.h" #include "melon_vpn_about.h" +#include "peersview.h" + +#define MAX_CURRENT_PEERS 5000 GtkApplication *app; GdkPixbuf *appicon; @@ -28,6 +30,7 @@ GtkWidget *button2; GtkWidget *button3; GtkWidget *button4; GtkWidget *statustxt; +GtkWidget *peerstreeview; // Callback functions for the code in the CLI int (*cli_start_vpn)(); @@ -92,10 +95,15 @@ gboolean on_window_deleted(GtkWidget *widget, GdkEvent *event, gpointer data) { void activate(GtkApplication* app) { window = gtk_application_window_new(app); + + // Setup window position and properties gtk_window_set_title(GTK_WINDOW(window),"Melon VPN"); gtk_window_set_default_size(GTK_WINDOW(window),300,300); gtk_window_set_resizable(GTK_WINDOW(window),false); gtk_window_set_type_hint(GTK_WINDOW(window),GDK_WINDOW_TYPE_HINT_DIALOG); + //gtk_window_set_gravity(GTK_WINDOW(window),GDK_GRAVITY_CENTER); + //gtk_window_move(GTK_WINDOW(window),0,0); + gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER_ALWAYS); g_signal_connect(G_OBJECT(window),"delete-event",G_CALLBACK(on_window_deleted),NULL); // Setup status icon now window is available @@ -135,6 +143,10 @@ void activate(GtkApplication* app) { statustxt = gtk_label_new(""); gtk_widget_modify_font(GTK_WIDGET(statustxt), font); + // Create treeview for peers + peerstreeview = gtk_tree_view_new(); + peersview_new(peerstreeview); + // Fixed box used to position the widgets box = gtk_fixed_new(); @@ -144,6 +156,9 @@ void activate(GtkApplication* app) { 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_fixed_put(GTK_FIXED(box),peerstreeview,10,80); + + gtk_widget_set_size_request(GTK_WIDGET(peerstreeview),280,220); gtk_widget_show_all(window); @@ -165,6 +180,8 @@ int run_gui(int argc, char **argv, bool is_debug, int (*start_vpn)(), int (*stop cli_refresh_vpn = refresh_vpn; cli_restart_conf_vpn = restart_conf_vpn; + currentpeers = malloc(MAX_CURRENT_PEERS); + statusiconoff = ""; statusiconon = ""; @@ -249,7 +266,9 @@ void mod_trigger_state(States state) { } void mod_trigger_peers(char *peers) { + memset(currentpeers,0,MAX_CURRENT_PEERS); strcpy(currentpeers, peers); + peersview_update(currentpeers); } void mod_trigger_isrestart(bool isrestart) { diff --git a/src/impl/gui/peersview.c b/src/impl/gui/peersview.c new file mode 100644 index 0000000..6427cdc --- /dev/null +++ b/src/impl/gui/peersview.c @@ -0,0 +1,82 @@ +#include +#include +#include + +#include "peers.h" +#include "ip_utils.h" +#include "peersview.h" + +GtkWidget *peersview; +GtkListStore *list_store; + +int peersview_sort(const void *v1, const void *v2); +gboolean peersview_setup_list_store(gpointer a); + +struct peersview_list_store_and_peer { + GtkListStore *list_store; + struct peer_t *peer; + int length; +}; + +void peersview_new(GtkWidget *treeview) { + peersview = GTK_WIDGET(treeview); + list_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); + + GtkTreeViewColumn *c1; + GtkCellRenderer *r1 = gtk_cell_renderer_text_new(); + c1 = gtk_tree_view_column_new_with_attributes("Name", r1, NULL); + + GtkTreeViewColumn *c2; + GtkCellRenderer *r2 = gtk_cell_renderer_text_new(); + c2 = gtk_tree_view_column_new_with_attributes("IP", r2, NULL); + + gtk_tree_view_append_column(GTK_TREE_VIEW(peersview),c1); + gtk_tree_view_append_column(GTK_TREE_VIEW(peersview),c2); + + gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(peersview)), GTK_SELECTION_NONE); + gtk_tree_view_set_model(GTK_TREE_VIEW(peersview), GTK_TREE_MODEL(list_store)); +} + +void peersview_update(char *peers) { + struct peersview_list_store_and_peer *a = g_slice_new(struct peersview_list_store_and_peer); + a->list_store = list_store; + + a->length = string_to_peers(peers, a->peer); + qsort(a->peer, a->length, sizeof(struct peer_t), peersview_sort); + + g_idle_add(&peersview_setup_list_store, (gpointer)a); + + fprintf(stderr, "Finished adding list store items\n"); +} + +gboolean peersview_setup_list_store(gpointer a) { + // TODO: fix the segmentation fault here + struct peersview_list_store_and_peer *b = (struct peersview_list_store_and_peer *)a; + + GtkListStore *list_store = b->list_store; + struct peer_t *devs = b->peer; + int l = b->length; + + gtk_list_store_clear(GTK_LIST_STORE(list_store)); + + GtkTreeIter iter; + for(int i=0; ipeer); + g_slice_free(struct peersview_list_store_and_peer, b); +} + +int peersview_sort(const void *v1, const void *v2) { + struct peer_t *p1 = (struct peer_t*)v1; + struct peer_t *p2 = (struct peer_t*)v2; + + int i1 = numericalIp(p1->ip); + int i2 = numericalIp(p2->ip); + + if(i1 < i2) return -1; + else if(i1 > i2) return +1; + else return 0; +} diff --git a/src/impl/refresh-peers/main.c b/src/impl/refresh-peers/main.c index c2f5aeb..df25027 100644 --- a/src/impl/refresh-peers/main.c +++ b/src/impl/refresh-peers/main.c @@ -8,28 +8,21 @@ #include "mjson.h" #include "unix_sockets.h" #include "melon_vpn_sock.h" +#include "peers.h" #define JBUF_SIZE 5000 -#define NAME_MAX 25 -#define IP_MAX 15 -#define DEV_MAX 25 - -struct dev_t { - char name[NAME_MAX]; - char ip[IP_MAX]; -}; struct devlist_t { int ndevices; - struct dev_t list[DEV_MAX]; + struct peer_t list[PEER_DEV_MAX]; }; static struct devlist_t devicelist; static int json_devicelist_read(const char *buf) { const struct json_attr_t json_attrs_subdevice[] = { - {"Name",t_string,STRUCTOBJECT(struct dev_t,name),.len=NAME_MAX}, - {"IP",t_string,STRUCTOBJECT(struct dev_t,ip),.len=IP_MAX}, + {"Name",t_string,STRUCTOBJECT(struct peer_t,name),.len=PEER_NAME_MAX}, + {"IP",t_string,STRUCTOBJECT(struct peer_t,ip),.len=PEER_IP_MAX}, {NULL}, }; const struct json_attr_t json_attrs_devices[] = { @@ -56,37 +49,24 @@ int main(int argc, char *argv[]) { strcat(jbuf, ibuf); strcat(jbuf, "}"); + fprintf(stderr,ibuf); + int status = json_devicelist_read(jbuf); if (status != 0) { puts(json_error_string(status)); } else { - ssize_t l=0; char obuf[JBUF_SIZE]; - obuf[JBUF_SIZE-1]=0; - strcpy(obuf, ""); - - for (int i = 0; i < devicelist.ndevices; i++) { - l += strlen(devicelist.list[i].name)+strlen(devicelist.list[i].ip)+2; - strcat(obuf, devicelist.list[i].name); - strcat(obuf, "\t"); - strcat(obuf, devicelist.list[i].ip); - strcat(obuf, "\n"); - obuf[l]=0; - fprintf(stderr, "l: %d\nobuf: %d\n",l,strlen(obuf)); - } - + int l=peers_to_string(devicelist.list,devicelist.ndevices,obuf); send_to_daemon(obuf,l); } } void send_to_daemon(char *buf, ssize_t n) { int sfd = unix_socket_client_start(SV_RPEERS_SOCK_PATH); - if(sfd==-1) { - return; - } + if(sfd==-1) return; write(sfd, buf, n); close(sfd); - fprintf(stderr, "Closed connection to socket"); + fprintf(stderr, "Closed connection to socket\n"); } diff --git a/src/impl/shared/ip_utils.c b/src/impl/shared/ip_utils.c new file mode 100644 index 0000000..dd91ca6 --- /dev/null +++ b/src/impl/shared/ip_utils.c @@ -0,0 +1,21 @@ +#include "ip_utils.h" + +unsigned long numericalIp(char *p) { + int parsedArray[IP_SEGMENTS]; + int nb = 0; + + while (nb < sizeof(parsedArray) && *p && nb < IP_SEGMENTS) { + parsedArray[nb++] = strtol(p, &p, 10); + if (*p != '.') break; + p++; + } + + if(nb==4) { + unsigned long a=parsedArray[3]; + a+=parsedArray[2]*(1<<8); + a+=parsedArray[1]*(1<<16); + a+=parsedArray[0]*(1<<24); + return a; + } + return 0; +} diff --git a/src/impl/shared/peers.c b/src/impl/shared/peers.c new file mode 100644 index 0000000..cf71eec --- /dev/null +++ b/src/impl/shared/peers.c @@ -0,0 +1,57 @@ +#include +#include + +#include "peers.h" + +int peers_to_string(struct peer_t *peers, int n, char *obuf) { + int l=0; + int total = PEER_DEV_MAX * (PEER_NAME_MAX + PEER_IP_MAX + 2) + 2; + memset(obuf, 0, total); + + for (int i = 0; i < n; i++) { + l += strlen(peers[i].name) + strlen(peers[i].ip) + 2; + strcat(obuf, peers[i].name); + strcat(obuf, "\t"); + strcat(obuf, peers[i].ip); + strcat(obuf, "\n"); + obuf[l]=0; + } + + return l; +} + +int string_to_peers(char *input, struct peer_t* output) { + char *list[PEER_DEV_MAX]; + char *name; + char *ip; + + int size = sizeof(struct peer_t) * (PEER_DEV_MAX+1); + output = malloc(size); + memset(output, 0, size); + + struct peet_t *peer; + int count = 0; + char *full; + + full = strtok(input,"\n"); + while(full != NULL) { + list[count++] = full; + full = strtok(NULL, "\n"); + } + + for(int i=0; i +#include #include "states.h" diff --git a/src/intf/ip_utils.h b/src/intf/ip_utils.h new file mode 100644 index 0000000..c84a41e --- /dev/null +++ b/src/intf/ip_utils.h @@ -0,0 +1,5 @@ +#include + +#define IP_SEGMENTS 4 + +unsigned long numericalIp(char *p); \ No newline at end of file diff --git a/src/intf/is_arg.h b/src/intf/is_arg.h new file mode 100644 index 0000000..4e408d9 --- /dev/null +++ b/src/intf/is_arg.h @@ -0,0 +1,9 @@ +#include + +int is_arg(int ac, char **argv, char *arg) { + if (ac < 2) return 0; + for (int x = 1; x < ac; x++) + if (0 == strcmp(argv[x], arg)) + return x; // return position of arg + return 0; // arg not present +} diff --git a/src/intf/peers.h b/src/intf/peers.h new file mode 100644 index 0000000..7ce2571 --- /dev/null +++ b/src/intf/peers.h @@ -0,0 +1,11 @@ +#define PEER_NAME_MAX 25 +#define PEER_IP_MAX 15 +#define PEER_DEV_MAX 25 + +struct peer_t { + char name[PEER_NAME_MAX]; + char ip[PEER_IP_MAX]; +}; + +int peers_to_string(struct peer_t *peers, int n, char *obuf); +int string_to_peers(char *input, struct peer_t *output); diff --git a/src/intf/peersview.h b/src/intf/peersview.h new file mode 100644 index 0000000..d10ecd6 --- /dev/null +++ b/src/intf/peersview.h @@ -0,0 +1,4 @@ +#include + +void peersview_new(GtkWidget *treeview); +void peersview_update(char *peers); diff --git a/src/intf/statusicon.h b/src/intf/statusicon.h index 838a095..a4d4ffc 100644 --- a/src/intf/statusicon.h +++ b/src/intf/statusicon.h @@ -6,5 +6,7 @@ void status_icon_create(GtkWidget *window, char *off, char *on); void status_icon_set_state(AppIndicatorStatus state); + +void status_icon_set_quit_callback(int (*func)()); void status_icon_set_connect_callback(int (*func)()); void status_icon_set_disconnect_callback(int (*func)());