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:
@@ -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"),
|
||||
"",
|
||||
|
||||
@@ -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 "")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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 ();
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user