1
0
mirror of https://github.com/weechat/weechat.git synced 2026-07-03 16:23:14 +02:00

Add partial irc-proxy feature to relay plugin

This commit is contained in:
Sebastien Helleu
2009-10-29 17:23:25 +01:00
parent 5a8c35f6b0
commit 999de8bfc1
40 changed files with 4263 additions and 1784 deletions
+1 -1
View File
@@ -388,7 +388,7 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
weechat_plugin = plugin;
weechat_hook_command ("demo_printf",
N_("print some messages on current ubffer"),
N_("print some messages on current buffer"),
N_("[text]"),
N_("text: write this text"),
"",
+4 -1
View File
@@ -19,9 +19,12 @@ relay.c relay.h
relay-buffer.c relay-buffer.h
relay-client.c relay-client.h
relay-command.c relay-command.h
relay-completion.c relay-completion.h
relay-config.c relay-config.h
relay-info.c relay-info.h
relay-network.c relay-network.h
relay-protocol-irc.c relay-protocol-irc.h
relay-protocol-weechat.c relay-protocol-weechat.h
relay-server.c relay-server.h
relay-upgrade.c relay-upgrade.h)
SET_TARGET_PROPERTIES(relay PROPERTIES PREFIX "")
+8 -2
View File
@@ -28,12 +28,18 @@ relay_la_SOURCES = relay.c \
relay-client.h \
relay-command.c \
relay-command.h \
relay-completion.c \
relay-completion.h \
relay-config.c \
relay-config.h \
relay-info.c \
relay-info.h \
relay-network.c \
relay-network.h \
relay-protocol-irc.c \
relay-protocol-irc.h \
relay-protocol-weechat.c \
relay-protocol-weechat.h \
relay-server.c \
relay-server.h \
relay-upgrade.c \
relay-upgrade.h
+16 -5
View File
@@ -43,7 +43,7 @@ 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_color[256], status[64], date_start[128], date_end[128];
char *str_recv, *str_sent;
int i, length, line;
struct tm *date_tmp;
@@ -95,10 +95,17 @@ relay_buffer_refresh (const char *hotlist)
date_tmp = localtime (&(ptr_client->start_time));
strftime (date_start, sizeof (date_start),
"%a, %d %b %Y %H:%M:%S", date_tmp);
date_end[0] = '\0';
if (ptr_client->end_time > 0)
{
date_tmp = localtime (&(ptr_client->end_time));
strftime (date_end, sizeof (date_end),
"%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)"),
_("%s%s[%s%s%s%s] %s (started on: %s%s%s%s)"),
weechat_color(str_color),
(line == relay_buffer_selected_line) ?
"*** " : " ",
@@ -107,15 +114,19 @@ relay_buffer_refresh (const char *hotlist)
weechat_color ("reset"),
weechat_color (str_color),
ptr_client->address,
date_start);
date_start,
(ptr_client->end_time > 0) ? ", " : "",
(ptr_client->end_time > 0) ? _("ended on: ") : "",
(ptr_client->end_time > 0) ? date_end : "");
/* second line with bytes recv/sent */
/* second line with protocol and 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"),
_("%s%-26s protocol: %s, received: %s, sent: %s"),
weechat_color(str_color),
" ",
relay_protocol_string[ptr_client->protocol],
(str_recv) ? str_recv : "?",
(str_sent) ? str_sent : "?");
if (str_recv)
+102 -132
View File
@@ -34,6 +34,9 @@
#include "relay-client.h"
#include "relay-config.h"
#include "relay-buffer.h"
#include "relay-protocol-irc.h"
#include "relay-protocol-weechat.h"
#include "relay-server.h"
char *relay_client_status_string[] = /* strings for status */
@@ -94,110 +97,6 @@ relay_client_search_by_number (int number)
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_split (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_split (argv);
}
}
}
/*
* relay_client_recv_cb: read data from a client
*/
@@ -207,7 +106,6 @@ relay_client_recv_cb (void *arg_client, int fd)
{
struct t_relay_client *client;
static char buffer[4096 + 2];
struct t_infolist *infolist;
int num_read;
/* make C compiler happy */
@@ -220,25 +118,16 @@ relay_client_recv_cb (void *arg_client, int fd)
{
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)
switch (client->protocol)
{
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);
}
case RELAY_PROTOCOL_WEECHAT:
relay_protocol_weechat_recv (client, buffer);
break;
case RELAY_PROTOCOL_IRC:
relay_protocol_irc_recv (client, buffer);
break;
case RELAY_NUM_PROTOCOLS:
break;
}
relay_buffer_refresh (NULL);
}
@@ -255,7 +144,7 @@ relay_client_recv_cb (void *arg_client, int fd)
*/
struct t_relay_client *
relay_client_new (int sock, char *address)
relay_client_new (int sock, char *address, struct t_relay_server *server)
{
struct t_relay_client *new_client;
@@ -265,13 +154,30 @@ relay_client_new (int sock, char *address)
new_client->sock = sock;
new_client->address = strdup ((address) ? address : "?");
new_client->status = RELAY_STATUS_CONNECTED;
new_client->protocol = server->protocol;
new_client->protocol_string = strdup (server->protocol_string);
new_client->listen_start_time = server->start_time;
new_client->start_time = time (NULL);
new_client->end_time = 0;
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->protocol_data = NULL;
switch (new_client->protocol)
{
case RELAY_PROTOCOL_WEECHAT:
relay_protocol_weechat_alloc (new_client);
break;
case RELAY_PROTOCOL_IRC:
relay_protocol_irc_alloc (new_client);
break;
case RELAY_NUM_PROTOCOLS:
break;
}
new_client->prev_client = NULL;
new_client->next_client = relay_clients;
if (relay_clients)
@@ -281,10 +187,15 @@ relay_client_new (int sock, char *address)
relay_clients = new_client;
weechat_printf (NULL,
_("%s: new client @ %s"),
_("%s: new client from %s%s%s on port %d (relaying: %s.%s)"),
RELAY_PLUGIN_NAME,
new_client->address);
RELAY_COLOR_CHAT_HOST,
new_client->address,
RELAY_COLOR_CHAT,
server->port,
relay_protocol_string[new_client->protocol],
new_client->protocol_string);
new_client->hook_fd = weechat_hook_fd (new_client->sock,
1, 0, 0,
&relay_client_recv_cb,
@@ -322,6 +233,8 @@ relay_client_set_status (struct t_relay_client *client,
if (RELAY_CLIENT_HAS_ENDED(client->status))
{
client->end_time = time (NULL);
if (client->hook_fd)
{
weechat_unhook (client->hook_fd);
@@ -336,14 +249,24 @@ relay_client_set_status (struct t_relay_client *client,
{
case RELAY_STATUS_AUTH_FAILED:
weechat_printf (NULL,
_("%s%s: authentication failed with client @ %s"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
client->address);
_("%s%s: authentication failed with client %s%s%s (%s.%s)"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME,
RELAY_COLOR_CHAT_HOST,
client->address,
RELAY_COLOR_CHAT,
relay_protocol_string[client->protocol],
client->protocol_string);
break;
case RELAY_STATUS_DISCONNECTED:
weechat_printf (NULL,
_("%s: disconnected from client @ %s"),
RELAY_PLUGIN_NAME, client->address);
_("%s: disconnected from client %s%s%s (%s.%s)"),
RELAY_PLUGIN_NAME,
RELAY_COLOR_CHAT_HOST,
client->address,
RELAY_COLOR_CHAT,
relay_protocol_string[client->protocol],
client->protocol_string);
break;
default:
break;
@@ -387,10 +310,26 @@ relay_client_free (struct t_relay_client *client)
/* free data */
if (client->address)
free (client->address);
if (client->protocol_string)
free (client->protocol_string);
if (client->hook_fd)
weechat_unhook (client->hook_fd);
if (client->hook_timer)
weechat_unhook (client->hook_timer);
if (client->protocol_data)
{
switch (client->protocol)
{
case RELAY_PROTOCOL_WEECHAT:
relay_protocol_weechat_free (client);
break;
case RELAY_PROTOCOL_IRC:
relay_protocol_irc_free (client);
break;
case RELAY_NUM_PROTOCOLS:
break;
}
}
free (client);
@@ -404,6 +343,19 @@ relay_client_free (struct t_relay_client *client)
}
}
/*
* relay_client_free_all: remove all clients
*/
void
relay_client_free_all ()
{
while (relay_clients)
{
relay_client_free (relay_clients);
}
}
/*
* relay_client_disconnect: disconnect one client
*/
@@ -497,12 +449,30 @@ relay_client_print_log ()
weechat_log_printf (" status. . . . . . . : %d (%s)",
ptr_client->status,
relay_client_status_string[ptr_client->status]);
weechat_log_printf (" protocol. . . . . . : %d (%s)",
ptr_client->protocol,
relay_protocol_string[ptr_client->protocol]);
weechat_log_printf (" protocol_string . . : '%s'", ptr_client->protocol_string);
weechat_log_printf (" listen_start_time . : %ld", ptr_client->listen_start_time);
weechat_log_printf (" start_time. . . . . : %ld", ptr_client->start_time);
weechat_log_printf (" end_time. . . . . . : %ld", ptr_client->end_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 (" protocol_data . . . : 0x%lx", ptr_client->protocol_data);
switch (ptr_client->protocol)
{
case RELAY_PROTOCOL_WEECHAT:
relay_protocol_weechat_print_log (ptr_client);
break;
case RELAY_PROTOCOL_IRC:
relay_protocol_irc_print_log (ptr_client);
break;
case RELAY_NUM_PROTOCOLS:
break;
}
weechat_log_printf (" prev_client . . . . : 0x%lx", ptr_client->prev_client);
weechat_log_printf (" next_client . . . . : 0x%lx", ptr_client->next_client);
}
+11 -1
View File
@@ -20,6 +20,8 @@
#ifndef __WEECHAT_RELAY_CLIENT_H
#define __WEECHAT_RELAY_CLIENT_H 1
struct t_relay_server;
/* relay status */
enum t_relay_status
@@ -45,12 +47,18 @@ struct t_relay_client
int sock; /* socket for connection */
char *address; /* string with IP address */
enum t_relay_status status; /* status (connecting, active,..) */
enum t_relay_protocol protocol; /* protocol (irc,..) */
char *protocol_string; /* string used for protocol */
/* example: server for irc protocol */
time_t listen_start_time; /* when listening started */
time_t start_time; /* time of client connection */
time_t end_time; /* time of client disconnection */
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 */
void *protocol_data; /* data depending on protocol used */
struct t_relay_client *prev_client;/* link to previous client */
struct t_relay_client *next_client;/* link to next client */
};
@@ -62,10 +70,12 @@ 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 struct t_relay_client *relay_client_new (int sock, char *address,
struct t_relay_server *server);
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_free_all ();
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,
+147 -19
View File
@@ -28,6 +28,7 @@
#include "relay-buffer.h"
#include "relay-client.h"
#include "relay-config.h"
#include "relay-server.h"
/*
@@ -61,10 +62,15 @@ relay_command_client_list (int full)
if (full)
{
weechat_printf (NULL,
_("%3d. %s, started on: %s, last activity: %s, "
"bytes: %lu recv, %lu sent"),
_("%3d. %s%s%s (%s%s%s), started on: %s, last "
"activity: %s, bytes: %lu recv, %lu sent"),
i,
RELAY_COLOR_CHAT_HOST,
ptr_client->address,
RELAY_COLOR_CHAT,
RELAY_COLOR_CHAT_BUFFER,
relay_client_status_string[ptr_client->status],
RELAY_COLOR_CHAT,
date_start,
date_activity,
ptr_client->bytes_recv,
@@ -72,10 +78,16 @@ relay_command_client_list (int full)
}
else
{
weechat_printf (NULL,
_("%3d. %s, started on: %s"),
i,
ptr_client->address);
if (!RELAY_CLIENT_HAS_ENDED(ptr_client->status))
{
weechat_printf (NULL,
_("%3d. %s%s%s, started on: %s"),
i,
RELAY_COLOR_CHAT_HOST,
ptr_client->address,
RELAY_COLOR_CHAT,
date_start);
}
}
i++;
}
@@ -84,6 +96,49 @@ relay_command_client_list (int full)
weechat_printf (NULL, _("No client for relay"));
}
/*
* relay_command_server_list: list servers (list of port on which we are
* listening)
*/
void
relay_command_server_list ()
{
struct t_relay_server *ptr_server;
int i;
char date_start[128];
struct tm *date_tmp;
if (relay_servers)
{
weechat_printf (NULL, "");
weechat_printf (NULL, _("Listening on ports:"));
i = 1;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
date_tmp = localtime (&(ptr_server->start_time));
strftime (date_start, sizeof (date_start),
"%a, %d %b %Y %H:%M:%S", date_tmp);
weechat_printf (NULL,
_("%3d. port %s%d%s, relay: %s%s.%s%s, started on: %s"),
i,
RELAY_COLOR_CHAT_BUFFER,
ptr_server->port,
RELAY_COLOR_CHAT,
RELAY_COLOR_CHAT_BUFFER,
relay_protocol_string[ptr_server->protocol],
ptr_server->protocol_string,
RELAY_COLOR_CHAT,
date_start);
i++;
}
}
else
weechat_printf (NULL, _("No server for relay"));
}
/*
* relay_command_relay: command /relay
*/
@@ -92,21 +147,80 @@ int
relay_command_relay (void *data, struct t_gui_buffer *buffer, int argc,
char **argv, char **argv_eol)
{
struct t_relay_server *ptr_server;
/* make C compiler happy */
(void) data;
(void) buffer;
(void) argv_eol;
if ((argc > 1) && (weechat_strcasecmp (argv[1], "list") == 0))
if (argc > 1)
{
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 (weechat_strcasecmp (argv[1], "list") == 0)
{
relay_command_client_list (0);
return WEECHAT_RC_OK;
}
if (weechat_strcasecmp (argv[1], "listfull") == 0)
{
relay_command_client_list (1);
return WEECHAT_RC_OK;
}
if (weechat_strcasecmp (argv[1], "listrelay") == 0)
{
relay_command_server_list ();
return WEECHAT_RC_OK;
}
if (weechat_strcasecmp (argv[1], "add") == 0)
{
if (argc >= 4)
{
relay_config_create_option_port (NULL,
relay_config_file,
relay_config_section_port,
argv[2],
argv_eol[3]);
}
else
{
weechat_printf (NULL,
_("%s%s: missing arguments for \"%s\" "
"command"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
"relay add");
}
return WEECHAT_RC_OK;
}
if (weechat_strcasecmp (argv[1], "del") == 0)
{
if (argc >= 3)
{
ptr_server = relay_server_search (argv_eol[2]);
if (ptr_server)
{
relay_server_free (ptr_server);
}
else
{
weechat_printf (NULL,
_("%s%s: relay \"%s\" not found"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME,
argv_eol[2]);
}
}
else
{
weechat_printf (NULL,
_("%s%s: missing arguments for \"%s\" "
"command"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
"relay add");
}
return WEECHAT_RC_OK;
}
}
if (!relay_buffer)
@@ -145,10 +259,24 @@ 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"
N_("[list | listfull | add protocol.name port | "
"del protocol.name]"),
N_(" list: list relay clients (only active "
"relays)\n"
" listfull: list relay clients (verbose, all "
"relays)\n"
" listrelay: list relays (name and port)\n"
" add: add relay for a protocol + name\n"
" del: remove relay for a protocol + name\n"
"protocol.name: protocol and name to relay\n"
" for example: irc.freenode\n"
" port: port used for relay\n\n"
"Without argument, this command opens buffer "
"with list of relay clients."),
"list|listfull", &relay_command_relay, NULL);
"list %(relay_relays)"
" || listfull %(relay_relays)"
" || listrelay"
" || add %(relay_protocol_name) %(relay_free_port)"
" || del %(relay_relays)",
&relay_command_relay, NULL);
}
+157
View File
@@ -0,0 +1,157 @@
/*
* Copyright (c) 2003-2009 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-completion.c: completion for relay command */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../weechat-plugin.h"
#include "relay.h"
#include "relay-server.h"
/*
* relay_completion_protocol_name_cb: callback for completion with protocol and
* name
*/
int
relay_completion_protocol_name_cb (void *data, const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion)
{
struct t_infolist *infolist;
char protocol_name[256];
/* make C compiler happy */
(void) data;
(void) buffer;
(void) completion_item;
infolist = weechat_infolist_get("irc_server", NULL, NULL);
if (infolist)
{
while (weechat_infolist_next (infolist))
{
snprintf (protocol_name, sizeof (protocol_name), "irc.%s",
weechat_infolist_string (infolist, "name"));
weechat_hook_completion_list_add (completion, protocol_name,
0, WEECHAT_LIST_POS_SORT);
}
weechat_infolist_free (infolist);
}
weechat_hook_completion_list_add (completion, "weechat",
0, WEECHAT_LIST_POS_SORT);
return WEECHAT_RC_OK;
}
/*
* relay_completion_relays_cb: callback for completion with protocol and name
* of current relays
*/
int
relay_completion_relays_cb (void *data, const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion)
{
struct t_relay_server *ptr_server;
char protocol_name[256];
/* make C compiler happy */
(void) data;
(void) buffer;
(void) completion_item;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
snprintf (protocol_name, sizeof (protocol_name), "%s.%s",
relay_protocol_string[ptr_server->protocol],
ptr_server->protocol_string);
weechat_hook_completion_list_add (completion, protocol_name,
0, WEECHAT_LIST_POS_SORT);
}
return WEECHAT_RC_OK;
}
/*
* relay_completion_free_port_cb: callback for completion with a free port
*/
int
relay_completion_free_port_cb (void *data, const char *completion_item,
struct t_gui_buffer *buffer,
struct t_gui_completion *completion)
{
struct t_relay_server *ptr_server;
char str_port[16];
int port_max;
/* make C compiler happy */
(void) data;
(void) buffer;
(void) completion_item;
/* default port is 8000 */
port_max = 8000 - 1;
if (ptr_server)
{
port_max = -1;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
if (ptr_server->port > port_max)
port_max = ptr_server->port;
}
if (port_max < 0)
port_max = 8000 - 1;
}
snprintf (str_port, sizeof (str_port), "%d", port_max + 1);
weechat_hook_completion_list_add (completion, str_port,
0, WEECHAT_LIST_POS_SORT);
return WEECHAT_RC_OK;
}
/*
* relay_completion_init: init completion for relay plugin
*/
void
relay_completion_init ()
{
weechat_hook_completion ("relay_protocol_name",
N_("all possible protocol.name for relay plugin"),
&relay_completion_protocol_name_cb, NULL);
weechat_hook_completion ("relay_relays",
N_("protocol.name of current relays for relay "
"plugin"),
&relay_completion_relays_cb, NULL);
weechat_hook_completion ("relay_free_port",
N_("first free port for relay plugin"),
&relay_completion_free_port_cb, NULL);
}
@@ -17,12 +17,9 @@
*/
#ifndef __WEECHAT_RELAY_NETWORK_H
#define __WEECHAT_RELAY_NETWORK_H 1
#ifndef __WEECHAT_RELAY_COMPLETION_H
#define __WEECHAT_RELAY_COMPLETION_H 1
extern int relay_network_sock;
extern void relay_completion_init ();
extern int relay_network_init ();
extern void relay_network_end ();
#endif /* relay-network.h */
#endif /* relay-completion.h */
+157 -24
View File
@@ -27,10 +27,11 @@
#include "relay-config.h"
#include "relay-client.h"
#include "relay-buffer.h"
#include "relay-network.h"
#include "relay-server.h"
struct t_config_file *relay_config_file = NULL;
struct t_config_section *relay_config_section_port = NULL;
/* relay config, look section */
@@ -45,8 +46,7 @@ struct t_config_option *relay_config_color_status[RELAY_NUM_STATUS];
/* relay config, network section */
struct t_config_option *relay_config_network_enabled;
struct t_config_option *relay_config_network_listen_port_range;
struct t_config_option *relay_config_network_max_clients;
/*
@@ -66,23 +66,149 @@ relay_config_refresh_cb (void *data, struct t_config_option *option)
}
/*
* relay_config_change_network_enabled_cb: callback called when user
* enables/disables relay
* relay_config_change_port_cb: callback called when relay port option is
* modified
*/
void
relay_config_change_network_enabled_cb (void *data,
struct t_config_option *option)
int
relay_config_check_port_cb (void *data, struct t_config_option *option,
const char *value)
{
char *error;
long port;
struct t_relay_server *ptr_server;
/* make C compiler happy */
(void) data;
(void) option;
if ((weechat_config_boolean(relay_config_network_enabled) && relay_network_sock < 0)
|| (!weechat_config_boolean(relay_config_network_enabled) && relay_network_sock >= 0))
error = NULL;
port = strtol (value, &error, 10);
ptr_server = relay_server_search_port ((int)port);
if (ptr_server)
{
relay_network_init ();
weechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, (int)port);
return 0;
}
return 1;
}
/*
* relay_config_change_port_cb: callback called when relay port option is
* modified
*/
void
relay_config_change_port_cb (void *data, struct t_config_option *option)
{
struct t_relay_server *ptr_server;
/* make C compiler happy */
(void) data;
ptr_server = relay_server_search (weechat_config_option_get_pointer (option, "name"));
if (ptr_server)
{
relay_server_update_port (ptr_server,
*((int *)weechat_config_option_get_pointer (option, "value")));
}
}
/*
* relay_config_delete_port_cb: callback called when relay port option is
* deleted
*/
void
relay_config_delete_port_cb (void *data, struct t_config_option *option)
{
struct t_relay_server *ptr_server;
/* make C compiler happy */
(void) data;
ptr_server = relay_server_search (weechat_config_option_get_pointer (option, "name"));
if (ptr_server)
relay_server_free (ptr_server);
}
/*
* relay_config_create_option_port: create a relay for a port
*/
int
relay_config_create_option_port (void *data,
struct t_config_file *config_file,
struct t_config_section *section,
const char *option_name,
const char *value)
{
int rc, protocol_number;
char *error, *protocol, *protocol_string;
long port;
struct t_relay_server *ptr_server;
/* make C compiler happy */
(void) data;
rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
relay_server_get_protocol_string (option_name,
&protocol, &protocol_string);
protocol_number = -1;
port = -1;
if (protocol && protocol_string)
protocol_number = relay_protocol_search (protocol);
if (protocol_number < 0)
{
weechat_printf (NULL, _("%s%s: error: unknown protocol \"%s\""),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, protocol);
rc = WEECHAT_CONFIG_OPTION_SET_ERROR;
}
if (rc != WEECHAT_CONFIG_OPTION_SET_ERROR)
{
error = NULL;
port = strtol (value, &error, 10);
ptr_server = relay_server_search_port ((int)port);
if (ptr_server)
{
weechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, (int)port);
rc = WEECHAT_CONFIG_OPTION_SET_ERROR;
}
}
if (rc != WEECHAT_CONFIG_OPTION_SET_ERROR)
{
/* create config option */
weechat_config_new_option (
config_file, section,
option_name, "integer", NULL,
NULL, 0, 65535, "", value, 0,
&relay_config_check_port_cb, NULL,
&relay_config_change_port_cb, NULL,
&relay_config_delete_port_cb, NULL);
relay_server_new (protocol_number, protocol_string, port);
rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
}
if (protocol)
free (protocol);
if (protocol_string)
free (protocol_string);
return rc;
}
/*
@@ -201,20 +327,27 @@ relay_config_init ()
return 0;
}
relay_config_network_enabled = weechat_config_new_option (
relay_config_network_max_clients = weechat_config_new_option (
relay_config_file, ptr_section,
"enabled", "boolean",
N_("enable relay"),
NULL, 0, 0, "off", NULL, 0, NULL, NULL,
&relay_config_change_network_enabled_cb, NULL, NULL, NULL);
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, it's recommended to use ports greater than "
"1024, because only root can use ports below 1024)"),
NULL, 0, 0, "22373-22400", NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL);
"max_clients", "integer",
N_("maximum number of clients connecting to a port"),
NULL, 1, 1024, "5", NULL, 0,
NULL, NULL, NULL, NULL, NULL, NULL);
ptr_section = weechat_config_new_section (relay_config_file, "port",
1, 1,
NULL, NULL,
NULL, NULL,
NULL, NULL,
&relay_config_create_option_port, NULL,
NULL, NULL);
if (!ptr_section)
{
weechat_config_free (relay_config_file);
return 0;
}
relay_config_section_port = ptr_section;
return 1;
}
+8 -3
View File
@@ -22,7 +22,8 @@
#define RELAY_CONFIG_NAME "relay"
extern struct t_config_file *relay_config;
extern struct t_config_file *relay_config_file;
extern struct t_config_section *relay_config_section_port;
extern struct t_config_option *relay_config_look_auto_open_buffer;
@@ -31,9 +32,13 @@ 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_enabled;
extern struct t_config_option *relay_config_network_listen_port_range;
extern struct t_config_option *relay_config_network_max_clients;
extern int relay_config_create_option_port (void *data,
struct t_config_file *config_file,
struct t_config_section *section,
const char *option_name,
const char *value);
extern int relay_config_init ();
extern int relay_config_read ();
extern int relay_config_write ();
-234
View File
@@ -1,234 +0,0 @@
/*
* Copyright (c) 2003-2009 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;
weechat_printf (NULL,
_("%s: socket closed"),
RELAY_PLUGIN_NAME);
}
}
/*
* relay_network_sock_cb: read data from a client which is connecting on socket
*/
int
relay_network_sock_cb (void *data, int fd)
{
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;
(void) fd;
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 ();
if (!weechat_config_boolean (relay_config_network_enabled))
return 1;
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 ();
}
+545
View File
@@ -0,0 +1,545 @@
/*
* Copyright (c) 2003-2009 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-protocol-irc.c: IRC protocol for client
(relay acting as an IRC proxy/bouncer) */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include "../weechat-plugin.h"
#include "relay.h"
#include "relay-protocol-irc.h"
#include "relay-client.h"
/*
* relay_protocol_irc_search_buffer: search IRC buffer with server and channel
* name
*/
struct t_gui_buffer *
relay_protocol_irc_search_buffer (const char *server, const char *channel)
{
char string[256];
long unsigned int value;
const char *str_ptr_buffer;
snprintf (string, sizeof (string), "%s,%s", server, channel);
str_ptr_buffer = weechat_info_get ("irc_buffer", string);
if (str_ptr_buffer && str_ptr_buffer[0])
{
sscanf (str_ptr_buffer, "%lx", &value);
return (struct t_gui_buffer *)value;
}
return NULL;
}
/*
* relay_protocol_irc_sendf: send formatted data to client
*/
int
relay_protocol_irc_sendf (struct t_relay_client *client, const char *format, ...)
{
va_list args;
static char buffer[4096];
int length, num_sent;
if (!client)
return 0;
va_start (args, format);
vsnprintf (buffer, sizeof (buffer) - 3, format, args);
va_end (args);
if (weechat_relay_plugin->debug)
{
weechat_printf (NULL, "relay: send: %s", buffer);
}
length = strlen (buffer);
buffer[length] = '\r';
buffer[length + 1] = '\n';
buffer[length + 2] = '\0';
length += 2;
num_sent = send (client->sock, buffer, length, 0);
if (num_sent >= 0)
client->bytes_sent += num_sent;
else
{
weechat_printf (NULL,
_("%s%s: error sending data to client %s"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
strerror (errno));
}
return num_sent;
}
/*
* relay_protocol_irc_signal_irc_in2_cb: callback for "irc_in2" IRC signal
*/
int
relay_protocol_irc_signal_irc_in2_cb (void *data, const char *signal,
const char *type_data, void *signal_data)
{
struct t_relay_client *client;
const char *ptr_msg;
char *host, *pos, *pos_end_nick;
(void) signal;
(void) type_data;
client = (struct t_relay_client *)data;
ptr_msg = (const char *)signal_data;
if (weechat_relay_plugin->debug)
{
weechat_printf (NULL, "relay: irc_in2: client: %s, data: %s",
client->protocol_string,
ptr_msg);
}
if (ptr_msg[0] == ':')
{
pos = strchr (ptr_msg, ' ');
if (pos)
{
host = weechat_strndup (ptr_msg + 1, pos - ptr_msg);
if (host)
{
pos_end_nick = strchr (host, '!');
if (pos_end_nick)
pos_end_nick[0] = '\0';
else
host[0] = '\0';
pos++;
while (pos[0] == ' ')
{
pos++;
}
relay_protocol_irc_sendf (client, ":%s%s%s %s",
(host[0]) ? host : "",
(host[0]) ? "!" : "",
RELAY_IRC_DATA(client, address),
pos);
free (host);
}
return WEECHAT_RC_OK;
}
}
relay_protocol_irc_sendf (client, "%s", ptr_msg);
return WEECHAT_RC_OK;
}
/*
* relay_protocol_irc_signal_irc_out_cb: callback for "irc_out" IRC signal
*/
int
relay_protocol_irc_signal_irc_out_cb (void *data, const char *signal,
const char *type_data, void *signal_data)
{
struct t_relay_client *client;
(void) signal;
(void) type_data;
client = (struct t_relay_client *)data;
if (weechat_relay_plugin->debug)
{
weechat_printf (NULL, "relay: irc_out: client: %s, data: %s",
client->protocol_string,
(char *)signal_data);
}
return WEECHAT_RC_OK;
}
/*
* relay_protocol_irc_send_join: send join for a channel to client
*/
void
relay_protocol_irc_send_join (struct t_relay_client *client,
const char *channel)
{
char *infolist_name, *nicks;
const char *nick;
int length, length_nicks;
struct t_infolist *infolist_nicks;
length = strlen (client->protocol_string) + 1 + strlen (channel) + 1;
infolist_name = malloc (length);
if (infolist_name)
{
relay_protocol_irc_sendf (client,
":%s!%s@proxy JOIN %s",
RELAY_IRC_DATA(client, nick),
"weechat",
channel);
snprintf (infolist_name, length, "%s,%s",
client->protocol_string,
channel);
infolist_nicks = weechat_infolist_get ("irc_nick", NULL, infolist_name);
if (infolist_nicks)
{
length_nicks = 0;
nicks = NULL;
while (weechat_infolist_next (infolist_nicks))
{
nick = weechat_infolist_string (infolist_nicks, "name");
if (nick && nick[0])
{
if (length_nicks == 0)
{
length_nicks = strlen (nick) + 1;
nicks = malloc (length_nicks);
strcpy (nicks, nick);
}
else
{
length_nicks += strlen (nick) + 1;
nicks = realloc (nicks, length_nicks);
strcat (nicks, " ");
strcat (nicks, nick);
}
}
}
if (nicks)
{
relay_protocol_irc_sendf (client,
":%s 353 %s = %s :%s",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
channel, nicks);
free (nicks);
}
weechat_infolist_free (infolist_nicks);
}
relay_protocol_irc_sendf (client,
":%s 366 %s %s :End of /NAMES list.",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
channel);
free (infolist_name);
}
}
/*
* relay_protocol_irc_send_join_channels: send join for all channels of server
* to client
*/
void
relay_protocol_irc_send_join_channels (struct t_relay_client *client)
{
struct t_infolist *infolist_channels;
const char *channel;
infolist_channels = weechat_infolist_get ("irc_channel", NULL,
client->protocol_string);
if (infolist_channels)
{
while (weechat_infolist_next (infolist_channels))
{
channel = weechat_infolist_string (infolist_channels, "name");
relay_protocol_irc_send_join (client, channel);
}
weechat_infolist_free (infolist_channels);
}
}
/*
* relay_protocol_irc_recv_one_msg: read one message from client
*/
void
relay_protocol_irc_recv_one_msg (struct t_relay_client *client, char *data)
{
char *pos, str_time[128], **argv, **argv_eol, str_signal_name[128];
char *command;
int argc, length;
const char *nick;
struct t_gui_buffer *ptr_buffer;
pos = strchr (data, '\r');
if (pos)
pos[0] = '\0';
if (weechat_relay_plugin->debug)
{
weechat_printf (NULL, "relay: recv from client: \"%s\"", data);
}
argv = weechat_string_split (data, " ", 0, 0, &argc);
argv_eol = weechat_string_split (data, " ", 1, 0, &argc);
if (!RELAY_IRC_DATA(client, connected))
{
if (weechat_strncasecmp (data, "nick ", 5) == 0)
{
if (data[5])
{
if (RELAY_IRC_DATA(client, nick))
free (RELAY_IRC_DATA(client, nick));
RELAY_IRC_DATA(client, nick) = strdup (data + 5);
}
}
if (weechat_strncasecmp (data, "user ", 5) == 0)
{
if (data[5])
{
RELAY_IRC_DATA(client, user_received) = 1;
}
}
if (RELAY_IRC_DATA(client, nick) && RELAY_IRC_DATA(client, user_received))
{
RELAY_IRC_DATA(client, connected) = 1;
/* send nick to client if server nick is different of nick asked
by client with command NICK */
nick = weechat_info_get ("irc_nick", client->protocol_string);
if (nick && (strcmp (nick, RELAY_IRC_DATA(client, nick)) != 0))
{
relay_protocol_irc_sendf (client,
":%s!proxy NICK :%s",
RELAY_IRC_DATA(client, nick),
nick);
free (RELAY_IRC_DATA(client, nick));
RELAY_IRC_DATA(client, nick) = strdup (nick);
}
relay_protocol_irc_sendf (client,
":%s 001 %s :Welcome to the Internet "
"Relay Network %s!%s@proxy",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
RELAY_IRC_DATA(client, nick),
"weechat");
relay_protocol_irc_sendf (client,
":%s 002 %s :Your host is "
"weechat-relay-irc, running version %s",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
weechat_info_get("version", NULL));
snprintf (str_time, sizeof (str_time), "%s",
ctime (&client->listen_start_time));
if (str_time[0])
str_time[strlen (str_time) - 1] = '\0';
relay_protocol_irc_sendf (client,
":%s 003 %s :This server was created "
"on %s",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
str_time);
relay_protocol_irc_sendf (client,
":%s 004 %s %s %s oirw abiklmnopqstv",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
RELAY_IRC_DATA(client, address),
weechat_info_get("version", NULL));
relay_protocol_irc_sendf (client,
":%s 251 %s :There are %d users and 0 "
"invisible on 1 servers",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
relay_client_count);
relay_protocol_irc_sendf (client,
":%s 255 %s :I have %d clients, 0 "
"services and 0 servers",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick),
relay_client_count);
relay_protocol_irc_sendf (client,
":%s 422 %s :MOTD File is missing",
RELAY_IRC_DATA(client, address),
RELAY_IRC_DATA(client, nick));
/* hook signal "xxx,irc_in2_*" to catch IRC data received from
this server */
snprintf (str_signal_name, sizeof (str_signal_name),
"%s,irc_in2_*",
client->protocol_string);
RELAY_IRC_DATA(client, hook_signal_irc_in2) =
weechat_hook_signal (str_signal_name,
&relay_protocol_irc_signal_irc_in2_cb,
client);
/* hook signal "xxx,irc_out_*" to catch IRC data sent to
this server */
snprintf (str_signal_name, sizeof (str_signal_name),
"%s,irc_out_*",
client->protocol_string);
RELAY_IRC_DATA(client, hook_signal_irc_out) =
weechat_hook_signal (str_signal_name,
&relay_protocol_irc_signal_irc_out_cb,
client);
/* send JOIN for all channels on server to client */
relay_protocol_irc_send_join_channels (client);
}
}
else
{
if (argc > 0)
{
if (weechat_strcasecmp (argv[0], "privmsg") == 0)
{
ptr_buffer = relay_protocol_irc_search_buffer (client->protocol_string,
argv[1]);
if (ptr_buffer)
{
weechat_printf (NULL,
"relay: send string \"%s\" on channel %s",
(argv_eol[2][0] == ':') ? argv_eol[2] + 1 : argv_eol[2],
argv[1]);
weechat_command (ptr_buffer,
(argv_eol[2][0] == ':') ? argv_eol[2] + 1 : argv_eol[2]);
}
else
{
weechat_printf (NULL,
_("%s%s: buffer not found for IRC server "
"\"%s\", channel \"%s\""),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME,
client->protocol_string,
argv[1]);
}
}
else
{
length = 32 + strlen (client->protocol_string) + strlen (data);
command = malloc (length + 1);
if (command)
{
snprintf (command, length, "/quote -server %s %s",
client->protocol_string,
data);
weechat_command (NULL, command);
free (command);
}
}
}
}
if (argv)
weechat_string_free_split (argv);
if (argv_eol)
weechat_string_free_split (argv_eol);
}
/*
* relay_protocol_irc_recv: read data from client
*/
void
relay_protocol_irc_recv (struct t_relay_client *client, const char *data)
{
char **items;
int items_count, i;
items = weechat_string_split (data, "\n", 0, 0, &items_count);
for (i = 0; i < items_count; i++)
{
relay_protocol_irc_recv_one_msg (client, items[i]);
}
if (items)
weechat_string_free_split (items);
}
/*
* relay_protocol_irc_alloc: init relay data specific to IRC protocol
*/
void
relay_protocol_irc_alloc (struct t_relay_client *client)
{
struct t_relay_protocol_irc_data *irc_data;
client->protocol_data = malloc (sizeof (*irc_data));
if (client->protocol_data)
{
RELAY_IRC_DATA(client, address) = strdup ("weechat.relay.irc");
RELAY_IRC_DATA(client, nick) = NULL;
RELAY_IRC_DATA(client, user_received) = 0;
RELAY_IRC_DATA(client, connected) = 0;
RELAY_IRC_DATA(client, hook_signal_irc_in2) = NULL;
RELAY_IRC_DATA(client, hook_signal_irc_out) = NULL;
}
}
/*
* relay_protocol_irc_free: free relay data specific to IRC protocol
*/
void
relay_protocol_irc_free (struct t_relay_client *client)
{
if (client->protocol_data)
{
if (RELAY_IRC_DATA(client, address))
free (RELAY_IRC_DATA(client, address));
if (RELAY_IRC_DATA(client, nick))
free (RELAY_IRC_DATA(client, nick));
if (RELAY_IRC_DATA(client, hook_signal_irc_in2))
weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_in2));
if (RELAY_IRC_DATA(client, hook_signal_irc_out))
weechat_unhook (RELAY_IRC_DATA(client, hook_signal_irc_out));
free (client->protocol_data);
}
}
/*
* relay_protocol_irc_print_log: print IRC client infos in log (usually for
* crash dump)
*/
void
relay_protocol_irc_print_log (struct t_relay_client *client)
{
if (client->protocol_data)
{
weechat_log_printf (" address. . . . . . : '%s'", RELAY_IRC_DATA(client, address));
weechat_log_printf (" nick . . . . . . . : '%s'", RELAY_IRC_DATA(client, nick));
weechat_log_printf (" user_received. . . : %d", RELAY_IRC_DATA(client, user_received));
weechat_log_printf (" connected. . . . . : %d", RELAY_IRC_DATA(client, connected));
weechat_log_printf (" hook_signal_irc_in2: 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_in2));
weechat_log_printf (" hook_signal_irc_out: 0x%lx", RELAY_IRC_DATA(client, hook_signal_irc_out));
}
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2003-2009 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_PROTOCOL_IRC_H
#define __WEECHAT_RELAY_PROTOCOL_IRC_H 1
struct t_relay_client;
#define RELAY_IRC_DATA(client, var) \
(((struct t_relay_protocol_irc_data *)client->protocol_data)->var)
struct t_relay_protocol_irc_data
{
char *address; /* client address (used when sending */
/* data to client) */
char *nick; /* nick for client */
int user_received; /* command "USER" received */
int connected; /* 1 if client is connected as IRC */
/* client */
struct t_hook *hook_signal_irc_in2;/* hook signal "irc_in2" */
struct t_hook *hook_signal_irc_out;/* hook signal "irc_out" */
};
extern void relay_protocol_irc_recv (struct t_relay_client *client,
const char *data);
extern void relay_protocol_irc_alloc (struct t_relay_client *client);
extern void relay_protocol_irc_free (struct t_relay_client *client);
extern void relay_protocol_irc_print_log (struct t_relay_client *client);
#endif /* relay-protocol-irc.h */
+230
View File
@@ -0,0 +1,230 @@
/*
* Copyright (c) 2003-2009 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-protocol-weechat.c: WeeChat protocol for client */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include "../weechat-plugin.h"
#include "relay.h"
#include "relay-protocol-weechat.h"
#include "relay-client.h"
/*
* relay_protocol_weechat_sendf: send formatted data to client
*/
int
relay_protocol_weechat_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_protocol_weechat_send_infolist: send infolist to client
*/
void
relay_protocol_weechat_send_infolist (struct t_relay_client *client,
const char *name,
struct t_infolist *infolist)
{
const char *fields;
char **argv;
int i, argc, size;
relay_protocol_weechat_sendf (client, "name %s", name);
while (weechat_infolist_next (infolist))
{
fields = weechat_infolist_fields (infolist);
if (fields)
{
argv = weechat_string_split (fields, ",", 0, 0, &argc);
if (argv && (argc > 0))
{
for (i = 0; i < argc; i++)
{
switch (argv[i][0])
{
case 'i':
relay_protocol_weechat_sendf (client, "%s %c %d",
argv[i] + 2, argv[i][0],
weechat_infolist_integer (infolist,
argv[i] + 2));
break;
case 's':
relay_protocol_weechat_sendf (client, "%s %c %s",
argv[i] + 2, argv[i][0],
weechat_infolist_string (infolist,
argv[i] + 2));
break;
case 'p':
relay_protocol_weechat_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_protocol_weechat_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_protocol_weechat_sendf (client, "%s %c %ld",
argv[i] + 2, argv[i][0],
weechat_infolist_time (infolist, argv[i] + 2));
break;
}
}
}
if (argv)
weechat_string_free_split (argv);
}
}
}
/*
* relay_protocol_weechat_recv_one_msg: read one message from client
*/
void
relay_protocol_weechat_recv_one_msg (struct t_relay_client *client, char *data)
{
char *pos;
struct t_infolist *infolist;
pos = strchr (data, '\r');
if (pos)
pos[0] = '\0';
if (weechat_relay_plugin->debug)
{
weechat_printf (NULL, "relay: weechat: \"%s\"", data);
}
if (weechat_strcasecmp (data, "quit") == 0)
relay_client_set_status (client, RELAY_STATUS_DISCONNECTED);
else
{
infolist = weechat_infolist_get (data, NULL, NULL);
if (infolist)
{
relay_protocol_weechat_send_infolist (client, data, infolist);
weechat_infolist_free (infolist);
}
}
}
/*
* relay_protocol_weechat_recv: read data from client
*/
void
relay_protocol_weechat_recv (struct t_relay_client *client, const char *data)
{
char **items;
int items_count, i;
items = weechat_string_split (data, "\n", 0, 0, &items_count);
for (i = 0; i < items_count; i++)
{
relay_protocol_weechat_recv_one_msg (client, items[i]);
}
if (items)
weechat_string_free_split (items);
}
/*
* relay_protocol_weechat_alloc: init relay data specific to weechat protocol
*/
void
relay_protocol_weechat_alloc (struct t_relay_client *client)
{
struct t_relay_protocol_weechat_data *weechat_data;
client->protocol_data = malloc (sizeof (*weechat_data));
if (client->protocol_data)
{
/* ... */
}
}
/*
* relay_protocol_weechat_free: free relay data specific to weechat protocol
*/
void
relay_protocol_weechat_free (struct t_relay_client *client)
{
if (client->protocol_data)
free (client->protocol_data);
}
/*
* relay_protocol_weechat_print_log: print weechat client infos in log (usually
* for crash dump)
*/
void
relay_protocol_weechat_print_log (struct t_relay_client *client)
{
if (client->protocol_data)
{
}
}
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2003-2009 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_PROTOCOL_WEECHAT_H
#define __WEECHAT_RELAY_PROTOCOL_WEECHAT_H 1
struct t_relay_client;
#define RELAY_WEECHAT_DATA(client, var) \
(((struct t_relay_protocol_weechat_data *)client->protocol_data)->var)
struct t_relay_protocol_weechat_data
{
char *address; /* client address (used when sending */
/* data to client) */
char *nick; /* nick for client */
int user_received; /* command "USER" received */
int connected; /* 1 if client is connected as IRC */
/* client */
};
extern void relay_protocol_weechat_recv (struct t_relay_client *client,
const char *data);
extern void relay_protocol_weechat_alloc (struct t_relay_client *client);
extern void relay_protocol_weechat_free (struct t_relay_client *client);
extern void relay_protocol_weechat_print_log (struct t_relay_client *client);
#endif /* relay-protocol-weechat.h */
+426
View File
@@ -0,0 +1,426 @@
/*
* Copyright (c) 2003-2009 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-server.c: server functions for relay plugin */
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <time.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-server.h"
#include "relay-buffer.h"
#include "relay-client.h"
#include "relay-config.h"
struct t_relay_server *relay_servers = NULL;
struct t_relay_server *last_relay_server = NULL;
/*
* relay_server_get_protocol_string: get protocol and string from a string with
* format "protocol.string"
* Note: *protocol and *string must be freed
* after use
*/
void
relay_server_get_protocol_string (const char *protocol_and_string,
char **protocol, char **protocol_string)
{
char *pos;
pos = strchr (protocol_and_string, '.');
if (pos)
{
*protocol = weechat_strndup (protocol_and_string,
pos - protocol_and_string);
*protocol_string = strdup (pos + 1);
}
else
{
*protocol = strdup (protocol_and_string);
*protocol_string = strdup ("*");
}
}
/*
* relay_server_search: search server by protocol.string
*/
struct t_relay_server *
relay_server_search (const char *protocol_and_string)
{
char *protocol, *protocol_string;
struct t_relay_server *ptr_server;
relay_server_get_protocol_string (protocol_and_string,
&protocol, &protocol_string);
ptr_server = NULL;
if (protocol && protocol_string)
{
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
if ((strcmp (protocol, relay_protocol_string[ptr_server->protocol]) == 0)
&& (strcmp (protocol_string, ptr_server->protocol_string) == 0))
{
break;
}
}
}
if (protocol)
free (protocol);
if (protocol_string)
free (protocol_string);
return ptr_server;
}
/*
* relay_server_search_port: search server by port
*/
struct t_relay_server *
relay_server_search_port (int port)
{
struct t_relay_server *ptr_server;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
if (ptr_server->port == port)
return ptr_server;
}
/* server not found */
return NULL;
}
/*
* relay_server_close_socket: close socket for a relay server
*/
void
relay_server_close_socket (struct t_relay_server *server)
{
if (server->hook_fd)
{
weechat_unhook (server->hook_fd);
server->hook_fd = NULL;
}
if (server->sock >= 0)
{
close (server->sock);
server->sock = -1;
weechat_printf (NULL,
_("%s: socket closed for %s.%s (port %d)"),
RELAY_PLUGIN_NAME,
relay_protocol_string[server->protocol],
server->protocol_string,
server->port);
}
}
/*
* relay_server_sock_cb: read data from a client which is connecting on socket
*/
int
relay_server_sock_cb (void *data, int fd)
{
struct t_relay_server *server;
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) fd;
server = (struct t_relay_server *)data;
client_length = sizeof (client_addr);
memset (&client_addr, 0, client_length);
client_fd = accept (server->sock, (struct sockaddr *) &client_addr,
&client_length);
if (client_fd < 0)
{
weechat_printf (NULL,
_("%s%s: cannot accept client on port %d (%s.%s)"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME,
server->port,
relay_protocol_string[server->protocol],
server->protocol_string);
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, server);
return WEECHAT_RC_OK;
}
/*
* relay_server_create_socket: create socket and server on port
*/
int
relay_server_create_socket (struct t_relay_server *server)
{
int set, max_clients;
struct sockaddr_in server_addr;
server->sock = socket (AF_INET, SOCK_STREAM, 0);
if (server->sock < 0)
{
weechat_printf (NULL,
_("%s%s: cannot create socket"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME);
return 0;
}
set = 1;
if (setsockopt (server->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 (server->sock);
server->sock = -1;
return 0;
}
set = 1;
if (setsockopt (server->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 (server->sock);
server->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;
server_addr.sin_port = htons (server->port);
if (bind (server->sock, (struct sockaddr *) &server_addr,
sizeof (server_addr)) < 0)
{
weechat_printf (NULL,
_("%s%s: error with \"bind\" on port %d (%s.%s)"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
server->port,
relay_protocol_string[server->protocol],
server->protocol_string);
close (server->sock);
server->sock = -1;
return 0;
}
max_clients = weechat_config_integer (relay_config_network_max_clients);
listen (server->sock, max_clients);
weechat_printf (NULL,
_("%s: listening on port %d (relay: %s.%s, max %d clients)"),
RELAY_PLUGIN_NAME,
server->port,
relay_protocol_string[server->protocol],
server->protocol_string,
max_clients);
server->hook_fd = weechat_hook_fd (server->sock,
1, 0, 0,
&relay_server_sock_cb,
server);
server->start_time = time (NULL);
return 1;
}
/*
* relay_server_new: add a socket relaying on a port
*/
struct t_relay_server *
relay_server_new (enum t_relay_protocol protocol,
const char *protocol_string,
int port)
{
struct t_relay_server *new_server;
if (relay_server_search_port (port))
{
weechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, port);
return NULL;
}
new_server = malloc (sizeof (*new_server));
if (new_server)
{
new_server->protocol = protocol;
new_server->protocol_string =
(protocol_string) ? strdup (protocol_string) : strdup ("*");
new_server->port = port;
new_server->sock = -1;
new_server->hook_fd = NULL;
new_server->start_time = 0;
new_server->prev_server = NULL;
new_server->next_server = relay_servers;
if (relay_servers)
relay_servers->prev_server = new_server;
else
last_relay_server = new_server;
relay_servers = new_server;
relay_server_create_socket (new_server);
}
else
{
weechat_printf (NULL,
_("%s%s: not enough memory for listening on new port"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME);
}
return new_server;
}
/*
* relay_server_update_port: update port in a server
*/
void
relay_server_update_port (struct t_relay_server *server, int port)
{
if (port != server->port)
{
relay_server_close_socket (server);
server->port = port;
relay_server_create_socket (server);
}
}
/*
* relay_server_free: remove a server
*/
void
relay_server_free (struct t_relay_server *server)
{
struct t_relay_server *new_relay_servers;
if (!server)
return;
/* remove server from list */
if (last_relay_server == server)
last_relay_server = server->prev_server;
if (server->prev_server)
{
(server->prev_server)->next_server = server->next_server;
new_relay_servers = relay_servers;
}
else
new_relay_servers = server->next_server;
if (server->next_server)
(server->next_server)->prev_server = server->prev_server;
/* free data */
relay_server_close_socket (server);
if (server->protocol_string)
free (server->protocol_string);
free (server);
relay_servers = new_relay_servers;
}
/*
* relay_server_free_all: remove all servers
*/
void
relay_server_free_all ()
{
while (relay_servers)
{
relay_server_free (relay_servers);
}
}
/*
* relay_server_print_log: print server infos in log (usually for crash dump)
*/
void
relay_server_print_log ()
{
struct t_relay_server *ptr_server;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
weechat_log_printf ("");
weechat_log_printf ("[relay server (addr:0x%lx)]", ptr_server);
weechat_log_printf (" protocol. . . . . . : %d (%s)",
ptr_server->protocol,
relay_protocol_string[ptr_server->protocol]);
weechat_log_printf (" protocol_string . . : '%s'", ptr_server->protocol_string);
weechat_log_printf (" port. . . . . . . . : %d", ptr_server->port);
weechat_log_printf (" sock. . . . . . . . : %d", ptr_server->sock);
weechat_log_printf (" hook_fd . . . . . . : 0x%lx", ptr_server->hook_fd);
weechat_log_printf (" start_time. . . . . : %ld", ptr_server->start_time);
weechat_log_printf (" prev_server . . . . : 0x%lx", ptr_server->prev_server);
weechat_log_printf (" next_server . . . . : 0x%lx", ptr_server->next_server);
}
}
+52
View File
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2003-2009 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_SERVER_H
#define __WEECHAT_RELAY_SERVER_H 1
struct t_relay_server
{
enum t_relay_protocol protocol; /* protocol (irc,..) */
char *protocol_string; /* string used for protocol */
/* example: server for irc protocol */
int port; /* listening on this port */
int sock; /* socket for connection */
struct t_hook *hook_fd; /* hook for socket */
time_t start_time; /* start time */
struct t_relay_server *prev_server;/* link to previous server */
struct t_relay_server *next_server;/* link to next server */
};
extern struct t_relay_server *relay_servers;
extern struct t_relay_server *last_relay_server;
extern void relay_server_get_protocol_string (const char *protocol_and_string,
char **protocol,
char **protocol_string);
extern struct t_relay_server *relay_server_search (const char *protocol_and_string);
extern struct t_relay_server *relay_server_search_port (int port);
extern struct t_relay_server *relay_server_new (enum t_relay_protocol protocol,
const char *protocol_string,
int port);
extern void relay_server_update_port (struct t_relay_server *server, int port);
extern void relay_server_free (struct t_relay_server *server);
extern void relay_server_free_all ();
extern void relay_server_print_log ();
#endif /* relay-server.h */
+40 -5
View File
@@ -23,11 +23,13 @@
#include "../weechat-plugin.h"
#include "relay.h"
#include "relay-buffer.h"
#include "relay-client.h"
#include "relay-command.h"
#include "relay-completion.h"
#include "relay-config.h"
#include "relay-info.h"
#include "relay-network.h"
#include "relay-server.h"
#include "relay-upgrade.h"
@@ -42,6 +44,30 @@ struct t_weechat_plugin *weechat_relay_plugin = NULL;
int relay_signal_upgrade_received = 0; /* signal "upgrade" received ? */
char *relay_protocol_string[] = /* strings for protocols */
{ "weechat", "irc" };
/*
* relay_protocol_search: search a protocol by name
*/
int
relay_protocol_search (const char *name)
{
int i;
for (i = 0; i < RELAY_NUM_PROTOCOLS; i++)
{
if (weechat_strcasecmp (relay_protocol_string[i], name) == 0)
{
return i;
}
}
/* protocol not found */
return -1;
}
/*
* relay_signal_upgrade_cb: callback for "upgrade" signal
@@ -80,6 +106,7 @@ relay_debug_dump_cb (void *data, const char *signal, const char *type_data,
weechat_log_printf ("***** \"%s\" plugin dump *****",
weechat_plugin->name);
relay_server_print_log ();
relay_client_print_log ();
weechat_log_printf ("");
@@ -110,13 +137,14 @@ weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
relay_command_init ();
/* hook completions */
relay_completion_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;
}
@@ -132,12 +160,19 @@ weechat_plugin_end (struct t_weechat_plugin *plugin)
relay_config_write ();
relay_network_end ();
if (relay_signal_upgrade_received)
relay_upgrade_save ();
else
{
/* remove all servers */
relay_server_free_all ();
/* remove all clients */
relay_client_disconnect_all ();
if (relay_buffer)
weechat_buffer_close (relay_buffer);
relay_client_free_all ();
}
return WEECHAT_RC_OK;
}
+18
View File
@@ -25,4 +25,22 @@
extern struct t_weechat_plugin *weechat_relay_plugin;
/* relay protocol */
enum t_relay_protocol
{
RELAY_PROTOCOL_WEECHAT = 0, /* WeeChat protocol */
RELAY_PROTOCOL_IRC, /* IRC protocol (IRC proxy) */
/* number of relay protocols */
RELAY_NUM_PROTOCOLS,
};
#define RELAY_COLOR_CHAT weechat_color("chat")
#define RELAY_COLOR_CHAT_HOST weechat_color("chat_host")
#define RELAY_COLOR_CHAT_BUFFER weechat_color("chat_buffer")
extern char *relay_protocol_string[];
extern int relay_protocol_search (const char *name);
#endif /* relay.h */