diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2008-12-10 17:08:56 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2008-12-10 17:08:56 +0100 |
commit | 20a1360bd87c9be583fd9fc540a8097ff2022781 (patch) | |
tree | ec6bea712338ab17a286f03c3334f1cd67aef6d5 /src/plugins/relay | |
parent | 09fdd1ace3a888a13fb0f11d839c9bbbb09463e0 (diff) | |
download | weechat-20a1360bd87c9be583fd9fc540a8097ff2022781.zip |
Add new plugin "relay", new function "string_format_size" in plugin API
Diffstat (limited to 'src/plugins/relay')
-rw-r--r-- | src/plugins/relay/CMakeLists.txt | 30 | ||||
-rw-r--r-- | src/plugins/relay/Makefile.am | 41 | ||||
-rw-r--r-- | src/plugins/relay/relay-buffer.c | 227 | ||||
-rw-r--r-- | src/plugins/relay/relay-buffer.h | 32 | ||||
-rw-r--r-- | src/plugins/relay/relay-client.c | 506 | ||||
-rw-r--r-- | src/plugins/relay/relay-client.h | 75 | ||||
-rw-r--r-- | src/plugins/relay/relay-command.c | 154 | ||||
-rw-r--r-- | src/plugins/relay/relay-command.h | 25 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.c | 211 | ||||
-rw-r--r-- | src/plugins/relay/relay-config.h | 40 | ||||
-rw-r--r-- | src/plugins/relay/relay-info.c | 96 | ||||
-rw-r--r-- | src/plugins/relay/relay-info.h | 25 | ||||
-rw-r--r-- | src/plugins/relay/relay-network.c | 227 | ||||
-rw-r--r-- | src/plugins/relay/relay-network.h | 26 | ||||
-rw-r--r-- | src/plugins/relay/relay-upgrade.c | 121 | ||||
-rw-r--r-- | src/plugins/relay/relay-upgrade.h | 35 | ||||
-rw-r--r-- | src/plugins/relay/relay.c | 144 | ||||
-rw-r--r-- | src/plugins/relay/relay.h | 28 |
18 files changed, 2043 insertions, 0 deletions
diff --git a/src/plugins/relay/CMakeLists.txt b/src/plugins/relay/CMakeLists.txt new file mode 100644 index 000000000..4ad5fbce6 --- /dev/null +++ b/src/plugins/relay/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (c) 2003-2008 FlashCode <flashcode@flashtux.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +ADD_LIBRARY(relay MODULE +relay.c relay.h +relay-buffer.c relay-buffer.h +relay-client.c relay-client.h +relay-command.c relay-command.h +relay-config.c relay-config.h +relay-info.c relay-info.h +relay-network.c relay-network.h +relay-upgrade.c relay-upgrade.h) +SET_TARGET_PROPERTIES(relay PROPERTIES PREFIX "") + +TARGET_LINK_LIBRARIES(relay) + +INSTALL(TARGETS relay LIBRARY DESTINATION lib/${PROJECT_NAME}/plugins) diff --git a/src/plugins/relay/Makefile.am b/src/plugins/relay/Makefile.am new file mode 100644 index 000000000..c2cf6e165 --- /dev/null +++ b/src/plugins/relay/Makefile.am @@ -0,0 +1,41 @@ +# Copyright (c) 2003-2008 FlashCode <flashcode@flashtux.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +INCLUDES = -DLOCALEDIR=\"$(datadir)/locale\" + +libdir = ${weechat_libdir}/plugins + +lib_LTLIBRARIES = relay.la + +relay_la_SOURCES = relay.c \ + relay.h \ + relay-buffer.c \ + relay-buffer.h \ + relay-client.c \ + relay-client.h \ + relay-command.c \ + relay-command.h \ + relay-config.c \ + relay-config.h \ + relay-info.c \ + relay-info.h \ + relay-network.c \ + relay-network.h \ + relay-upgrade.c \ + relay-upgrade.h + +relau_la_LDFLAGS = -module +relay_la_LIBADD = $(RELAY_LFLAGS) diff --git a/src/plugins/relay/relay-buffer.c b/src/plugins/relay/relay-buffer.c new file mode 100644 index 000000000..36b30bc1f --- /dev/null +++ b/src/plugins/relay/relay-buffer.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-buffer.c: display clients list on relay buffer */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-client.h" +#include "relay-config.h" + + +struct t_gui_buffer *relay_buffer = NULL; +int relay_buffer_selected_line = 0; + + +/* + * relay_buffer_refresh: update a client in buffer and update hotlist for + * relay buffer + */ + +void +relay_buffer_refresh (const char *hotlist) +{ + struct t_relay_client *ptr_client, *client_selected; + char str_color[256], status[64], date_start[128]; + char *str_recv, *str_sent; + int i, length, line; + struct tm *date_tmp; + + if (relay_buffer) + { + weechat_buffer_clear (relay_buffer); + line = 0; + client_selected = relay_client_search_by_number (relay_buffer_selected_line); + if (client_selected) + { + weechat_printf_y (relay_buffer, 0, + "%s%s%s%s%s%s%s", + weechat_color("green"), + _("Actions (letter+enter):"), + weechat_color("lightgreen"), + /* disconnect */ + (RELAY_CLIENT_HAS_ENDED(client_selected->status)) ? + "" : _(" [D] Disconnect"), + /* remove */ + (RELAY_CLIENT_HAS_ENDED(client_selected->status)) ? + _(" [R] Remove") : "", + /* purge old */ + _(" [P] Purge finished"), + /* quit */ + _(" [Q] Close this buffer")); + } + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + snprintf (str_color, sizeof (str_color), + "%s,%s", + (line == relay_buffer_selected_line) ? + weechat_config_string (relay_config_color_text_selected) : + weechat_config_string (relay_config_color_text), + weechat_config_string (relay_config_color_text_bg)); + + snprintf (status, sizeof (status), + "%s", _(relay_client_status_string[ptr_client->status])); + length = weechat_utf8_strlen_screen (status); + if (length < 20) + { + for (i = 0; i < 20 - length; i++) + { + strcat (status, " "); + } + } + + date_tmp = localtime (&(ptr_client->start_time)); + strftime (date_start, sizeof (date_start), + "%a, %d %b %Y %H:%M:%S", date_tmp); + + /* first line with status and start time */ + weechat_printf_y (relay_buffer, (line * 2) + 2, + _("%s%s[%s%s%s%s] %s (started on: %s)"), + weechat_color(str_color), + (line == relay_buffer_selected_line) ? + "*** " : " ", + weechat_color(weechat_config_string (relay_config_color_status[ptr_client->status])), + status, + weechat_color ("reset"), + weechat_color (str_color), + ptr_client->address, + date_start); + + /* second line with bytes recv/sent */ + str_recv = weechat_string_format_size (ptr_client->bytes_recv); + str_sent = weechat_string_format_size (ptr_client->bytes_sent); + weechat_printf_y (relay_buffer, (line * 2) + 3, + _("%s%-26s received: %s, sent: %s"), + weechat_color(str_color), + " ", + (str_recv) ? str_recv : "?", + (str_sent) ? str_sent : "?"); + if (str_recv) + free (str_recv); + if (str_sent) + free (str_sent); + + line++; + } + if (hotlist) + weechat_buffer_set (relay_buffer, "hotlist", hotlist); + } +} + +/* + * relay_buffer_input_cb: callback called when user send data to client list + * buffer + */ + +int +relay_buffer_input_cb (void *data, struct t_gui_buffer *buffer, + const char *input_data) +{ + struct t_relay_client *client, *ptr_client, *next_client; + + /* make C compiler happy */ + (void) data; + + client = relay_client_search_by_number (relay_buffer_selected_line); + + /* disconnect client */ + if (weechat_strcasecmp (input_data, "d") == 0) + { + if (client && !RELAY_CLIENT_HAS_ENDED(client->status)) + { + relay_client_disconnect (client); + relay_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); + } + } + /* purge old clients */ + else if (weechat_strcasecmp (input_data, "p") == 0) + { + ptr_client = relay_clients; + while (ptr_client) + { + next_client = ptr_client->next_client; + if (RELAY_CLIENT_HAS_ENDED(ptr_client->status)) + relay_client_free (ptr_client); + ptr_client = next_client; + } + relay_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); + } + /* quit relay buffer (close it) */ + else if (weechat_strcasecmp (input_data, "q") == 0) + { + weechat_buffer_close (buffer); + } + /* remove client */ + else if (weechat_strcasecmp (input_data, "r") == 0) + { + if (client && RELAY_CLIENT_HAS_ENDED(client->status)) + { + relay_client_free (client); + relay_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); + } + } + + return WEECHAT_RC_OK; +} + +/* + * relay_buffer_close_cb: callback called when relay buffer is closed + */ + +int +relay_buffer_close_cb (void *data, struct t_gui_buffer *buffer) +{ + /* make C compiler happy */ + (void) data; + (void) buffer; + + relay_buffer = NULL; + + return WEECHAT_RC_OK; +} + +/* + * relay_buffer_open: open relay buffer (to display list of clients) + */ + +void +relay_buffer_open () +{ + if (!relay_buffer) + { + relay_buffer = weechat_buffer_new ("relay.list", + &relay_buffer_input_cb, NULL, + &relay_buffer_close_cb, NULL); + + /* failed to create buffer ? then exit */ + if (!relay_buffer) + return; + + weechat_buffer_set (relay_buffer, "type", "free"); + weechat_buffer_set (relay_buffer, "title", _("List of clients for relay")); + weechat_buffer_set (relay_buffer, "key_bind_meta2-A", "/relay up"); + weechat_buffer_set (relay_buffer, "key_bind_meta2-B", "/relay down"); + } +} diff --git a/src/plugins/relay/relay-buffer.h b/src/plugins/relay/relay-buffer.h new file mode 100644 index 000000000..1702e0b91 --- /dev/null +++ b/src/plugins/relay/relay-buffer.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_DISPLAY_H +#define __WEECHAT_RELAY_DISPLAY_H 1 + +extern struct t_gui_buffer *relay_buffer; +extern int relay_buffer_selected_line; + +extern void relay_buffer_refresh (const char *hotlist); +extern int relay_buffer_input_cb (void *data, struct t_gui_buffer *buffer, + const char *input_data); +extern int relay_buffer_close_cb (void *data, struct t_gui_buffer *buffer); +extern void relay_buffer_open (); + +#endif /* relay-buffer.h */ diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c new file mode 100644 index 000000000..02a7e53fd --- /dev/null +++ b/src/plugins/relay/relay-client.c @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-client.c: client functions for relay plugin */ + + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <time.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-client.h" +#include "relay-config.h" +#include "relay-buffer.h" + + +char *relay_client_status_string[] = /* strings for status */ +{ N_("connecting"), N_("waiting auth"), + N_("connected"), N_("auth failed"), N_("disconnected") +}; + +struct t_relay_client *relay_clients = NULL; +struct t_relay_client *last_relay_client = NULL; +int relay_client_count = 0; /* number of clients */ + + +/* + * relay_client_valid: check if a client pointer exists + * return 1 if client exists + * 0 if client is not found + */ + +int +relay_client_valid (struct t_relay_client *client) +{ + struct t_relay_client *ptr_client; + + if (!client) + return 0; + + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + if (ptr_client == client) + return 1; + } + + /* client not found */ + return 0; +} + +/* + * relay_client_search_by_number: search a client by number (first client is 0) + */ + +struct t_relay_client * +relay_client_search_by_number (int number) +{ + struct t_relay_client *ptr_client; + int i; + + i = 0; + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + if (i == number) + return ptr_client; + i++; + } + + /* client not found */ + return NULL; +} + +/* + * relay_client_sendf: send formatted data to client + */ + +int +relay_client_sendf (struct t_relay_client *client, const char *format, ...) +{ + va_list args; + static char buffer[4096]; + char str_length[8]; + int length, num_sent; + + if (!client) + return 0; + + va_start (args, format); + vsnprintf (buffer + 7, sizeof (buffer) - 7 - 1, format, args); + va_end (args); + + length = strlen (buffer + 7); + snprintf (str_length, sizeof (str_length), "%07d", length); + memcpy (buffer, str_length, 7); + + num_sent = send (client->sock, buffer, length + 7, 0); + + client->bytes_sent += length + 7; + + if (num_sent < 0) + { + weechat_printf (NULL, + _("%s%s: error sending data to client %s"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME, + strerror (errno)); + } + + return num_sent; +} + +/* + * relay_client_send_infolist: send infolist to client + */ + +void +relay_client_send_infolist (struct t_relay_client *client, + const char *name, + struct t_infolist *infolist) +{ + const char *fields; + char **argv; + int i, argc, size; + + relay_client_sendf (client, "name %s", name); + + while (weechat_infolist_next (infolist)) + { + fields = weechat_infolist_fields (infolist); + if (fields) + { + argv = weechat_string_explode (fields, ",", 0, 0, &argc); + if (argv && (argc > 0)) + { + for (i = 0; i < argc; i++) + { + switch (argv[i][0]) + { + case 'i': + relay_client_sendf (client, "%s %c %d", + argv[i] + 2, argv[i][0], + weechat_infolist_integer (infolist, + argv[i] + 2)); + break; + case 's': + relay_client_sendf (client, "%s %c %s", + argv[i] + 2, argv[i][0], + weechat_infolist_string (infolist, + argv[i] + 2)); + break; + case 'p': + relay_client_sendf (client, "%s %c %lx", + argv[i] + 2, argv[i][0], + (long unsigned int)weechat_infolist_pointer (infolist, + argv[i] + 2)); + break; + case 'b': + relay_client_sendf (client, "%s %c %lx", + argv[i] + 2, argv[i][0], + (long unsigned int)weechat_infolist_buffer (infolist, + argv[i] + 2, + &size)); + break; + case 't': + relay_client_sendf (client, "%s %c %ld", + argv[i] + 2, argv[i][0], + weechat_infolist_time (infolist, argv[i] + 2)); + break; + } + } + } + if (argv) + weechat_string_free_exploded (argv); + } + } +} + +/* + * relay_client_recv_cb: read data from a client + */ + +int +relay_client_recv_cb (void *arg_client) +{ + struct t_relay_client *client; + static char buffer[4096 + 2]; + struct t_infolist *infolist; + int num_read; + + client = (struct t_relay_client *)arg_client; + + num_read = recv (client->sock, buffer, sizeof (buffer) - 1, 0); + if (num_read > 0) + { + client->bytes_recv += num_read; + buffer[num_read] = '\0'; + if (buffer[num_read - 1] == '\n') + buffer[--num_read] = '\0'; + if (buffer[num_read - 1] == '\r') + buffer[--num_read] = '\0'; + if (weechat_relay_plugin->debug) + { + weechat_printf (NULL, "%s: data received from %s: \"%s\"", + RELAY_PLUGIN_NAME, client->address, buffer); + } + if (weechat_strcasecmp (buffer, "quit") == 0) + relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); + else + { + infolist = weechat_infolist_get (buffer, NULL, NULL); + if (infolist) + { + relay_client_send_infolist (client, buffer, infolist); + weechat_infolist_free (infolist); + } + } + relay_buffer_refresh (NULL); + } + else + { + relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); + } + + return WEECHAT_RC_OK; +} + +/* + * relay_client_new: create a new client + */ + +struct t_relay_client * +relay_client_new (int sock, char *address) +{ + struct t_relay_client *new_client; + + new_client = malloc (sizeof (*new_client)); + if (new_client) + { + new_client->sock = sock; + new_client->address = strdup ((address) ? address : "?"); + new_client->status = RELAY_STATUS_CONNECTED; + new_client->start_time = time (NULL); + new_client->hook_fd = NULL; + new_client->hook_timer = NULL; + new_client->last_activity = new_client->start_time; + new_client->bytes_recv = 0; + new_client->bytes_sent = 0; + + new_client->prev_client = NULL; + new_client->next_client = relay_clients; + if (relay_clients) + relay_clients->prev_client = new_client; + else + last_relay_client = new_client; + relay_clients = new_client; + + weechat_printf (NULL, + _("%s: new client @ %s"), + RELAY_PLUGIN_NAME, + new_client->address); + + new_client->hook_fd = weechat_hook_fd (new_client->sock, + 1, 0, 0, + &relay_client_recv_cb, + new_client); + + relay_client_count++; + + if (!relay_buffer + && weechat_config_boolean (relay_config_look_auto_open_buffer)) + { + relay_buffer_open (); + } + + relay_buffer_refresh (WEECHAT_HOTLIST_PRIVATE); + } + else + { + weechat_printf (NULL, + _("%s%s: not enough memory for new client"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + } + + return new_client; +} + +/* + * relay_client_set_status: set status for a client + */ + +void +relay_client_set_status (struct t_relay_client *client, + enum t_relay_status status) +{ + client->status = status; + + if (RELAY_CLIENT_HAS_ENDED(client->status)) + { + if (client->hook_fd) + { + weechat_unhook (client->hook_fd); + client->hook_fd = NULL; + } + if (client->hook_timer) + { + weechat_unhook (client->hook_timer); + client->hook_timer = NULL; + } + switch (client->status) + { + case RELAY_STATUS_AUTH_FAILED: + weechat_printf (NULL, + _("%s%s: authentication failed with client @ %s"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME, + client->address); + break; + case RELAY_STATUS_DISCONNECTED: + weechat_printf (NULL, + _("%s: disconnected from client @ %s"), + RELAY_PLUGIN_NAME, client->address); + break; + default: + break; + } + + if (client->sock >= 0) + { + close (client->sock); + client->sock = -1; + } + } + + relay_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); +} + +/* + * relay_client_free: remove a client + */ + +void +relay_client_free (struct t_relay_client *client) +{ + struct t_relay_client *new_relay_clients; + + if (!client) + return; + + /* remove client from list */ + if (last_relay_client == client) + last_relay_client = client->prev_client; + if (client->prev_client) + { + (client->prev_client)->next_client = client->next_client; + new_relay_clients = relay_clients; + } + else + new_relay_clients = client->next_client; + if (client->next_client) + (client->next_client)->prev_client = client->prev_client; + + /* free data */ + if (client->address) + free (client->address); + if (client->hook_fd) + weechat_unhook (client->hook_fd); + if (client->hook_timer) + weechat_unhook (client->hook_timer); + + free (client); + + relay_clients = new_relay_clients; + + relay_client_count--; + if (relay_buffer_selected_line >= relay_client_count) + { + relay_buffer_selected_line = (relay_client_count == 0) ? + 0 : relay_client_count - 1; + } +} + +/* + * relay_client_disconnect: disconnect one client + */ + +void +relay_client_disconnect (struct t_relay_client *client) +{ + if (client->sock >= 0) + { + relay_client_set_status (client, RELAY_STATUS_DISCONNECTED); + } +} + +/* + * relay_client_disconnect_all: disconnect from all clients + */ + +void +relay_client_disconnect_all () +{ + struct t_relay_client *ptr_client; + + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + relay_client_disconnect (ptr_client); + } +} + +/* + * relay_client_add_to_infolist: add a client in an infolist + * return 1 if ok, 0 if error + */ + +int +relay_client_add_to_infolist (struct t_infolist *infolist, + struct t_relay_client *client) +{ + struct t_infolist_item *ptr_item; + char value[128]; + + if (!infolist || !client) + return 0; + + ptr_item = weechat_infolist_new_item (infolist); + if (!ptr_item) + return 0; + + if (!weechat_infolist_new_var_integer (ptr_item, "sock", client->sock)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "address", client->address)) + return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "status", client->status)) + return 0; + if (!weechat_infolist_new_var_string (ptr_item, "status_string", relay_client_status_string[client->status])) + return 0; + if (!weechat_infolist_new_var_time (ptr_item, "start_time", client->start_time)) + return 0; + if (!weechat_infolist_new_var_pointer (ptr_item, "hook_fd", client->hook_fd)) + return 0; + if (!weechat_infolist_new_var_pointer (ptr_item, "hook_timer", client->hook_timer)) + return 0; + if (!weechat_infolist_new_var_time (ptr_item, "last_activity", client->last_activity)) + return 0; + snprintf (value, sizeof (value), "%lu", client->bytes_recv); + if (!weechat_infolist_new_var_string (ptr_item, "bytes_recv", value)) + return 0; + snprintf (value, sizeof (value), "%lu", client->bytes_sent); + if (!weechat_infolist_new_var_string (ptr_item, "bytes_sent", value)) + return 0; + + return 1; +} + +/* + * relay_client_print_log: print client infos in log (usually for crash dump) + */ + +void +relay_client_print_log () +{ + struct t_relay_client *ptr_client; + + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + weechat_log_printf (""); + weechat_log_printf ("[relay client (addr:0x%lx)]", ptr_client); + weechat_log_printf (" sock. . . . . . . . : %d", ptr_client->sock); + weechat_log_printf (" address . . . . . . : '%s'", ptr_client->address); + weechat_log_printf (" status. . . . . . . : %d (%s)", + ptr_client->status, + relay_client_status_string[ptr_client->status]); + weechat_log_printf (" start_time. . . . . : %ld", ptr_client->start_time); + weechat_log_printf (" hook_fd . . . . . . : 0x%lx", ptr_client->hook_fd); + weechat_log_printf (" hook_timer. . . . . : 0x%lx", ptr_client->hook_timer); + weechat_log_printf (" last_activity . . . : %ld", ptr_client->last_activity); + weechat_log_printf (" bytes_recv. . . . . : %lu", ptr_client->bytes_recv); + weechat_log_printf (" bytes_sent. . . . . : %lu", ptr_client->bytes_sent); + weechat_log_printf (" prev_client . . . . : 0x%lx", ptr_client->prev_client); + weechat_log_printf (" next_client . . . . : 0x%lx", ptr_client->next_client); + } +} diff --git a/src/plugins/relay/relay-client.h b/src/plugins/relay/relay-client.h new file mode 100644 index 000000000..4f06e6c0e --- /dev/null +++ b/src/plugins/relay/relay-client.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_CLIENT_H +#define __WEECHAT_RELAY_CLIENT_H 1 + +/* relay status */ + +enum t_relay_status +{ + RELAY_STATUS_CONNECTING = 0, /* connecting to client */ + RELAY_STATUS_WAITING_AUTH, /* waiting AUTH from client */ + RELAY_STATUS_CONNECTED, /* connected to client */ + RELAY_STATUS_AUTH_FAILED, /* AUTH failed with client */ + RELAY_STATUS_DISCONNECTED, /* disconnected from client */ + /* number of relay status */ + RELAY_NUM_STATUS, +}; + +/* macros for status */ + +#define RELAY_CLIENT_HAS_ENDED(status) ((status == RELAY_STATUS_AUTH_FAILED) || \ + (status == RELAY_STATUS_DISCONNECTED)) + +/* relay client */ + +struct t_relay_client +{ + int sock; /* socket for connection */ + char *address; /* string with IP address */ + enum t_relay_status status; /* status (connecting, active,..) */ + time_t start_time; /* time of client connection */ + struct t_hook *hook_fd; /* hook for socket or child pipe */ + struct t_hook *hook_timer; /* timeout for recever accept */ + time_t last_activity; /* time of last byte received/sent */ + unsigned long bytes_recv; /* bytes received from client */ + unsigned long bytes_sent; /* bytes sent to client */ + struct t_relay_client *prev_client;/* link to previous client */ + struct t_relay_client *next_client;/* link to next client */ +}; + +extern char *relay_client_status_string[]; +extern struct t_relay_client *relay_clients; +extern struct t_relay_client *last_relay_client; +extern int relay_client_count; + +extern int relay_client_valid (struct t_relay_client *client); +extern struct t_relay_client *relay_client_search_by_number (int number); +extern struct t_relay_client *relay_client_new (int sock, char *address); +extern void relay_client_set_status (struct t_relay_client *client, + enum t_relay_status status); +extern void relay_client_free (struct t_relay_client *client); +extern void relay_client_disconnect (struct t_relay_client *client); +extern void relay_client_disconnect_all (); +extern int relay_client_add_to_infolist (struct t_infolist *infolist, + struct t_relay_client *client); +extern void relay_client_print_log (); + +#endif /* relay-client.h */ diff --git a/src/plugins/relay/relay-command.c b/src/plugins/relay/relay-command.c new file mode 100644 index 000000000..839a02286 --- /dev/null +++ b/src/plugins/relay/relay-command.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-command.c: relay command */ + + +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-buffer.h" +#include "relay-client.h" +#include "relay-config.h" + + +/* + * relay_command_client_list: list clients + */ + +void +relay_command_client_list (int full) +{ + struct t_relay_client *ptr_client; + int i; + char date_start[128], date_activity[128]; + struct tm *date_tmp; + + if (relay_clients) + { + weechat_printf (NULL, ""); + weechat_printf (NULL, _("Clients for relay:")); + i = 1; + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + date_tmp = localtime (&(ptr_client->start_time)); + strftime (date_start, sizeof (date_start), + "%a, %d %b %Y %H:%M:%S", date_tmp); + + date_tmp = localtime (&(ptr_client->last_activity)); + strftime (date_activity, sizeof (date_activity), + "%a, %d %b %Y %H:%M:%S", date_tmp); + + if (full) + { + weechat_printf (NULL, + _("%3d. %s, started on: %s, last activity: %s, " + "bytes: %lu recv, %lu sent"), + i, + ptr_client->address, + date_start, + date_activity, + ptr_client->bytes_recv, + ptr_client->bytes_sent); + } + else + { + weechat_printf (NULL, + _("%3d. %s, started on: %s"), + i, + ptr_client->address); + } + i++; + } + } + else + weechat_printf (NULL, _("No client for relay")); +} + +/* + * relay_command_relay: command /relay + */ + +int +relay_command_relay (void *data, struct t_gui_buffer *buffer, int argc, + char **argv, char **argv_eol) +{ + /* make C compiler happy */ + (void) data; + (void) buffer; + (void) argv_eol; + + if ((argc > 1) && (weechat_strcasecmp (argv[1], "list") == 0)) + { + relay_command_client_list (0); + return WEECHAT_RC_OK; + } + + if ((argc > 1) && (weechat_strcasecmp (argv[1], "listfull") == 0)) + { + relay_command_client_list (1); + return WEECHAT_RC_OK; + } + + if (!relay_buffer) + relay_buffer_open (); + + if (relay_buffer) + { + weechat_buffer_set (relay_buffer, "display", "1"); + + if (argc > 1) + { + if (strcmp (argv[1], "up") == 0) + { + if (relay_buffer_selected_line > 0) + relay_buffer_selected_line--; + } + else if (strcmp (argv[1], "down") == 0) + { + if (relay_buffer_selected_line < relay_client_count - 1) + relay_buffer_selected_line++; + } + } + } + + relay_buffer_refresh (NULL); + + return WEECHAT_RC_OK; +} + +/* + * relay_command_init: add /relay command + */ + +void +relay_command_init () +{ + weechat_hook_command ("relay", + N_("relay control"), + "[list | listfull]", + N_(" list: list relay clients\n" + "listfull: list relay clients (verbose)\n\n" + "Without argument, this command opens buffer " + "with list of relay clients."), + "list|listfull", &relay_command_relay, NULL); +} diff --git a/src/plugins/relay/relay-command.h b/src/plugins/relay/relay-command.h new file mode 100644 index 000000000..8236768f5 --- /dev/null +++ b/src/plugins/relay/relay-command.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_COMMAND_H +#define __WEECHAT_RELAY_COMMAND_H 1 + +extern void relay_command_init (); + +#endif /* relay-command.h */ diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c new file mode 100644 index 000000000..a8cd965a6 --- /dev/null +++ b/src/plugins/relay/relay-config.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-config.c: relay configuration options */ + + +#include <stdlib.h> +#include <limits.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-config.h" +#include "relay-client.h" +#include "relay-buffer.h" + + +struct t_config_file *relay_config_file = NULL; + +/* relay config, look section */ + +struct t_config_option *relay_config_look_auto_open_buffer; + +/* relay config, color section */ + +struct t_config_option *relay_config_color_text; +struct t_config_option *relay_config_color_text_bg; +struct t_config_option *relay_config_color_text_selected; +struct t_config_option *relay_config_color_status[RELAY_NUM_STATUS]; + +/* relay config, network section */ + +struct t_config_option *relay_config_network_listen_port_range; + + +/* + * relay_config_refresh_cb: callback called when user changes relay option that + * needs a refresh of relay list + */ + +void +relay_config_refresh_cb (void *data, struct t_config_option *option) +{ + /* make C compiler happy */ + (void) data; + (void) option; + + if (relay_buffer) + relay_buffer_refresh (NULL); +} + +/* + * relay_config_reload: reload relay configuration file + */ + +int +relay_config_reload (void *data, struct t_config_file *config_file) +{ + /* make C compiler happy */ + (void) data; + + return weechat_config_reload (config_file); +} + +/* + * relay_config_init: init relay configuration file + * return: 1 if ok, 0 if error + */ + +int +relay_config_init () +{ + struct t_config_section *ptr_section; + + relay_config_file = weechat_config_new (RELAY_CONFIG_NAME, + &relay_config_reload, NULL); + if (!relay_config_file) + return 0; + + ptr_section = weechat_config_new_section (relay_config_file, "look", + 0, 0, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL); + if (!ptr_section) + { + weechat_config_free (relay_config_file); + return 0; + } + + relay_config_look_auto_open_buffer = weechat_config_new_option ( + relay_config_file, ptr_section, + "auto_open_buffer", "boolean", + N_("auto open relay buffer when a new client is connecting"), + NULL, 0, 0, "on", NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + ptr_section = weechat_config_new_section (relay_config_file, "color", + 0, 0, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL); + if (!ptr_section) + { + weechat_config_free (relay_config_file); + return 0; + } + + relay_config_color_text = weechat_config_new_option ( + relay_config_file, ptr_section, + "text", "color", + N_("text color"), + NULL, 0, 0, "default", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_text_bg = weechat_config_new_option ( + relay_config_file, ptr_section, + "text_bg", "color", + N_("background color"), + NULL, 0, 0, "default", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_text_selected = weechat_config_new_option ( + relay_config_file, ptr_section, + "text_selected", "color", + N_("text color of selected client line"), + NULL, 0, 0, "white", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_status[RELAY_STATUS_CONNECTING] = weechat_config_new_option ( + relay_config_file, ptr_section, + "status_connecting", "color", + N_("text color for \"connecting\" status"), + NULL, 0, 0, "yellow", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_status[RELAY_STATUS_WAITING_AUTH] = weechat_config_new_option ( + relay_config_file, ptr_section, + "status_waiting_auth", "color", + N_("text color for \"waiting authentication\" status"), + NULL, 0, 0, "brown", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_status[RELAY_STATUS_CONNECTED] = weechat_config_new_option ( + relay_config_file, ptr_section, + "status_active", "color", + N_("text color for \"connected\" status"), + NULL, 0, 0, "lightblue", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_status[RELAY_STATUS_AUTH_FAILED] = weechat_config_new_option ( + relay_config_file, ptr_section, + "status_auth_failed", "color", + N_("text color for \"authentication failed\" status"), + NULL, 0, 0, "lightred", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + relay_config_color_status[RELAY_STATUS_DISCONNECTED] = weechat_config_new_option ( + relay_config_file, ptr_section, + "status_disconnected", "color", + N_("text color for \"disconnected\" status"), + NULL, 0, 0, "lightred", NULL, + NULL, NULL, &relay_config_refresh_cb, NULL, NULL, NULL); + + ptr_section = weechat_config_new_section (relay_config_file, "network", + 0, 0, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL); + if (!ptr_section) + { + weechat_config_free (relay_config_file); + return 0; + } + + relay_config_network_listen_port_range = weechat_config_new_option ( + relay_config_file, ptr_section, + "listen_port_range", "string", + N_("port number (or range of ports) that relay plugin listens on " + "(syntax: a single port, ie. 5000 or a port " + "range, ie. 5000-5015)"), + NULL, 0, 0, "22373-22400", NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + return 1; +} + +/* + * relay_config_read: read relay configuration file + */ + +int +relay_config_read () +{ + return weechat_config_read (relay_config_file); +} + +/* + * relay_config_write: write relay configuration file + */ + +int +relay_config_write () +{ + return weechat_config_write (relay_config_file); +} diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h new file mode 100644 index 000000000..0c35f2ff1 --- /dev/null +++ b/src/plugins/relay/relay-config.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_CONFIG_H +#define __WEECHAT_RELAY_CONFIG_H 1 + +#define RELAY_CONFIG_NAME "relay" + +extern struct t_config_file *relay_config; + +extern struct t_config_option *relay_config_look_auto_open_buffer; + +extern struct t_config_option *relay_config_color_text; +extern struct t_config_option *relay_config_color_text_bg; +extern struct t_config_option *relay_config_color_text_selected; +extern struct t_config_option *relay_config_color_status[]; + +extern struct t_config_option *relay_config_network_listen_port_range; + +extern int relay_config_init (); +extern int relay_config_read (); +extern int relay_config_write (); + +#endif /* relay-config.h */ diff --git a/src/plugins/relay/relay-info.c b/src/plugins/relay/relay-info.c new file mode 100644 index 000000000..100e366cb --- /dev/null +++ b/src/plugins/relay/relay-info.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-info.c: info and infolist hooks for relay plugin */ + + +#include <stdlib.h> +#include <stdio.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-client.h" + + +/* + * relay_info_get_infolist_cb: callback called when relay infolist is asked + */ + +struct t_infolist * +relay_info_get_infolist_cb (void *data, const char *infolist_name, + void *pointer, const char *arguments) +{ + struct t_infolist *ptr_infolist; + struct t_relay_client *ptr_client; + + /* make C compiler happy */ + (void) data; + (void) arguments; + + if (!infolist_name || !infolist_name[0]) + return NULL; + + if (weechat_strcasecmp (infolist_name, "relay") == 0) + { + if (pointer && !relay_client_valid (pointer)) + return NULL; + + ptr_infolist = weechat_infolist_new (); + if (ptr_infolist) + { + if (pointer) + { + /* build list with only one relay */ + if (!relay_client_add_to_infolist (ptr_infolist, pointer)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + return ptr_infolist; + } + else + { + /* build list with all relays */ + for (ptr_client = relay_clients; ptr_client; + ptr_client = ptr_client->next_client) + { + if (!relay_client_add_to_infolist (ptr_infolist, ptr_client)) + { + weechat_infolist_free (ptr_infolist); + return NULL; + } + } + return ptr_infolist; + } + } + } + + return NULL; +} + +/* + * relay_info_init: initialize info and infolist hooks for relay plugin + */ + +void +relay_info_init () +{ + /* relay infolist hooks */ + weechat_hook_infolist ("relay", N_("list of relay clients"), + &relay_info_get_infolist_cb, NULL); +} diff --git a/src/plugins/relay/relay-info.h b/src/plugins/relay/relay-info.h new file mode 100644 index 000000000..87aaabf96 --- /dev/null +++ b/src/plugins/relay/relay-info.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_INFO_H +#define __WEECHAT_RELAY_INFO_H 1 + +extern void relay_info_init (); + +#endif /* relay-info.h */ diff --git a/src/plugins/relay/relay-network.c b/src/plugins/relay/relay-network.c new file mode 100644 index 000000000..d93ac4387 --- /dev/null +++ b/src/plugins/relay/relay-network.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-network.c: network functions for relay plugin */ + + +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-buffer.h" +#include "relay-client.h" +#include "relay-config.h" + + +int relay_network_sock = -1; /* socket used for listening and */ + /* waiting for clients */ +struct t_hook *relay_network_hook_fd = NULL; +int relay_network_listen_port = -1; /* listening port */ + + +/* + * relay_network_close_socket: close socket + */ + +void +relay_network_close_socket () +{ + if (relay_network_hook_fd) + { + weechat_unhook (relay_network_hook_fd); + relay_network_hook_fd = NULL; + } + if (relay_network_sock >= 0) + { + close (relay_network_sock); + relay_network_sock = -1; + } +} + +/* + * relay_network_sock_cb: read data from a client which is connecting on socket + */ + +int +relay_network_sock_cb (void *data) +{ + struct sockaddr_in client_addr; + unsigned int client_length; + int client_fd; + char ipv4_address[INET_ADDRSTRLEN + 1], *ptr_address; + + /* make C compiler happy */ + (void) data; + + client_length = sizeof (client_addr); + memset (&client_addr, 0, client_length); + + client_fd = accept (relay_network_sock, (struct sockaddr *) &client_addr, + &client_length); + if (client_fd < 0) + { + weechat_printf (NULL, + _("%s%s: cannot accept client"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + return WEECHAT_RC_OK; + } + + ptr_address = NULL; + if (inet_ntop (AF_INET, + &(client_addr.sin_addr), + ipv4_address, + INET_ADDRSTRLEN)) + { + ptr_address = ipv4_address; + } + + relay_client_new (client_fd, ptr_address); + + return WEECHAT_RC_OK; +} + +/* + * relay_network_init: init socket and listen on port + * return 1 if ok, 0 if error + */ + +int +relay_network_init () +{ + int set, args, port, port_start, port_end; + struct sockaddr_in server_addr; + const char *port_range; + + relay_network_close_socket (); + + port_range = weechat_config_string (relay_config_network_listen_port_range); + if (!port_range || !port_range[0]) + { + weechat_printf (NULL, + _("%s%s: option \"listen_port_range\" is not defined"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + return 0; + } + + relay_network_sock = socket (AF_INET, SOCK_STREAM, 0); + if (relay_network_sock < 0) + { + weechat_printf (NULL, + _("%s%s: cannot create socket"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + return 0; + } + + set = 1; + if (setsockopt (relay_network_sock, SOL_SOCKET, SO_REUSEADDR, + (void *) &set, sizeof (set)) < 0) + { + weechat_printf (NULL, + _("%s%s: cannot set socket option " + "\"SO_REUSEADDR\""), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + close (relay_network_sock); + relay_network_sock = -1; + return 0; + } + + set = 1; + if (setsockopt (relay_network_sock, SOL_SOCKET, SO_KEEPALIVE, + (void *) &set, sizeof (set)) < 0) + { + weechat_printf (NULL, + _("%s%s: cannot set socket option " + "\"SO_KEEPALIVE\""), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + close (relay_network_sock); + relay_network_sock = -1; + return 0; + } + + memset(&server_addr, 0, sizeof(struct sockaddr_in)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + + port = -1; + + /* find a free port in the specified range */ + args = sscanf (weechat_config_string (relay_config_network_listen_port_range), + "%d-%d", &port_start, &port_end); + if (args > 0) + { + port = port_start; + if (args == 1) + port_end = port_start; + + /* loop through the entire allowed port range */ + while (port <= port_end) + { + /* attempt to bind to the free port */ + server_addr.sin_port = htons (port); + if (bind (relay_network_sock, (struct sockaddr *) &server_addr, + sizeof (server_addr)) == 0) + break; + port++; + } + + if (port > port_end) + port = -1; + } + + if (port < 0) + { + weechat_printf (NULL, + _("%s%s: cannot find available port for listening"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + close (relay_network_sock); + relay_network_sock = -1; + return 0; + } + + relay_network_listen_port = port; + + listen (relay_network_sock, 5); + + weechat_printf (NULL, + _("%s: listening on port %d"), + RELAY_PLUGIN_NAME, relay_network_listen_port); + + relay_network_hook_fd = weechat_hook_fd (relay_network_sock, + 1, 0, 0, + &relay_network_sock_cb, + NULL); + + return 1; +} + +/* + * relay_network_end: close main socket + */ + +void +relay_network_end () +{ + relay_network_close_socket (); +} diff --git a/src/plugins/relay/relay-network.h b/src/plugins/relay/relay-network.h new file mode 100644 index 000000000..a090276d3 --- /dev/null +++ b/src/plugins/relay/relay-network.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_NETWORK_H +#define __WEECHAT_RELAY_NETWORK_H 1 + +extern int relay_network_init (); +extern void relay_network_end (); + +#endif /* relay-network.h */ diff --git a/src/plugins/relay/relay-upgrade.c b/src/plugins/relay/relay-upgrade.c new file mode 100644 index 000000000..907122583 --- /dev/null +++ b/src/plugins/relay/relay-upgrade.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay-upgrade.c: save/restore relay plugin data */ + + +#include <stdlib.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-upgrade.h" +#include "relay-buffer.h" + + +/* + * relay_upgrade_save_clients: save clients info to upgrade file + */ + +int +relay_upgrade_save_clients (struct t_upgrade_file *upgrade_file) +{ + /* TODO: save relay data */ + (void) upgrade_file; + return 1; +} + +/* + * relay_upgrade_save: save upgrade file + * return 1 if ok, 0 if error + */ + +int +relay_upgrade_save () +{ + int rc; + struct t_upgrade_file *upgrade_file; + + upgrade_file = weechat_upgrade_create (RELAY_UPGRADE_FILENAME, 1); + if (!upgrade_file) + return 0; + + rc = relay_upgrade_save_clients (upgrade_file); + + weechat_upgrade_close (upgrade_file); + + return rc; +} + +/* + * relay_upgrade_set_buffer_callbacks: restore buffers callbacks (input and + * close) for buffers created by relay plugin + */ + +void +relay_upgrade_set_buffer_callbacks () +{ + struct t_infolist *infolist; + struct t_gui_buffer *ptr_buffer; + + infolist = weechat_infolist_get ("buffer", NULL, NULL); + if (infolist) + { + while (weechat_infolist_next (infolist)) + { + if (weechat_infolist_pointer (infolist, "plugin") == weechat_relay_plugin) + { + ptr_buffer = weechat_infolist_pointer (infolist, "pointer"); + weechat_buffer_set_pointer (ptr_buffer, "close_callback", &relay_buffer_close_cb); + weechat_buffer_set_pointer (ptr_buffer, "input_callback", &relay_buffer_input_cb); + } + } + } +} + +/* + * relay_upgrade_read_cb: read callback for relay upgrade file + */ + +int +relay_upgrade_read_cb (int object_id, + struct t_infolist *infolist) +{ + /* TODO: write relay read cb */ + (void) object_id; + (void) infolist; + return WEECHAT_RC_OK; +} + +/* + * relay_upgrade_load: load upgrade file + * return 1 if ok, 0 if error + */ + +int +relay_upgrade_load () +{ + int rc; + struct t_upgrade_file *upgrade_file; + + relay_upgrade_set_buffer_callbacks (); + + upgrade_file = weechat_upgrade_create (RELAY_UPGRADE_FILENAME, 0); + rc = weechat_upgrade_read (upgrade_file, &relay_upgrade_read_cb); + + return rc; +} diff --git a/src/plugins/relay/relay-upgrade.h b/src/plugins/relay/relay-upgrade.h new file mode 100644 index 000000000..855c1026e --- /dev/null +++ b/src/plugins/relay/relay-upgrade.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_UPGRADE_H +#define __WEECHAT_RELAY_UPGRADE_H 1 + +#define RELAY_UPGRADE_FILENAME "relay" + +/* For developers: please add new values ONLY AT THE END of enums */ + +enum t_relay_upgrade_type +{ + RELAY_UPGRADE_TYPE_RELAY = 0, +}; + +extern int relay_upgrade_save (); +extern int relay_upgrade_load (); + +#endif /* relay-upgrade.h */ diff --git a/src/plugins/relay/relay.c b/src/plugins/relay/relay.c new file mode 100644 index 000000000..252d91590 --- /dev/null +++ b/src/plugins/relay/relay.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* relay.c: network communication between WeeChat and remote application */ + + +#include <stdlib.h> + +#include "../weechat-plugin.h" +#include "relay.h" +#include "relay-client.h" +#include "relay-command.h" +#include "relay-config.h" +#include "relay-info.h" +#include "relay-network.h" +#include "relay-upgrade.h" + + +WEECHAT_PLUGIN_NAME(RELAY_PLUGIN_NAME); +WEECHAT_PLUGIN_DESCRIPTION("Network communication between WeeChat and " + "remote application"); +WEECHAT_PLUGIN_AUTHOR("FlashCode <flashcode@flashtux.org>"); +WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION); +WEECHAT_PLUGIN_WEECHAT_VERSION(WEECHAT_VERSION); +WEECHAT_PLUGIN_LICENSE("GPL3"); + +struct t_weechat_plugin *weechat_relay_plugin = NULL; + +int relay_signal_upgrade_received = 0; /* signal "upgrade" received ? */ + + +/* + * relay_signal_upgrade_cb: callback for "upgrade" signal + */ + +int +relay_signal_upgrade_cb (void *data, const char *signal, const char *type_data, + void *signal_data) +{ + /* make C compiler happy */ + (void) data; + (void) signal; + (void) type_data; + (void) signal_data; + + relay_signal_upgrade_received = 1; + + return WEECHAT_RC_OK; +} + +/* + * relay_debug_dump_cb: callback for "debug_dump" signal + */ + +int +relay_debug_dump_cb (void *data, const char *signal, const char *type_data, + void *signal_data) +{ + /* make C compiler happy */ + (void) data; + (void) signal; + (void) type_data; + (void) signal_data; + + weechat_log_printf (""); + weechat_log_printf ("***** \"%s\" plugin dump *****", + weechat_plugin->name); + + relay_client_print_log (); + + weechat_log_printf (""); + weechat_log_printf ("***** End of \"%s\" plugin dump *****", + weechat_plugin->name); + + return WEECHAT_RC_OK; +} + +/* + * weechat_plugin_init: initialize relay plugin + */ + +int +weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[]) +{ + /* make C compiler happy */ + (void) argc; + (void) argv; + + weechat_plugin = plugin; + + if (!relay_config_init ()) + return WEECHAT_RC_ERROR; + + if (relay_config_read () < 0) + return WEECHAT_RC_ERROR; + + relay_command_init (); + + weechat_hook_signal ("upgrade", &relay_signal_upgrade_cb, NULL); + weechat_hook_signal ("debug_dump", &relay_debug_dump_cb, NULL); + + relay_info_init (); + + relay_network_init (); + + return WEECHAT_RC_OK; +} + +/* + * weechat_plugin_end: end relay plugin + */ + +int +weechat_plugin_end (struct t_weechat_plugin *plugin) +{ + /* make C compiler happy */ + (void) plugin; + + relay_config_write (); + + relay_network_end (); + + if (relay_signal_upgrade_received) + relay_upgrade_save (); + else + relay_client_disconnect_all (); + + return WEECHAT_RC_OK; +} diff --git a/src/plugins/relay/relay.h b/src/plugins/relay/relay.h new file mode 100644 index 000000000..18e81c471 --- /dev/null +++ b/src/plugins/relay/relay.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2003-2008 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_RELAY_H +#define __WEECHAT_RELAY_H 1 + +#define weechat_plugin weechat_relay_plugin +#define RELAY_PLUGIN_NAME "relay" + +extern struct t_weechat_plugin *weechat_relay_plugin; + +#endif /* relay.h */ |