relay: add UNIX socket support (closes #733)

This commit is contained in:
Ryan Farley 2019-05-12 18:51:13 +02:00 committed by Sébastien Helleu
parent 5f87112ec5
commit ffefd1b785
7 changed files with 312 additions and 74 deletions

View File

@ -3194,6 +3194,27 @@ websocket = new WebSocket("ws://server.com:9000/weechat");
The port (9000 in example) is the port defined in Relay plugin.
The URI must always end with "/weechat" (for _irc_ and _weechat_ protocols).
[[relay_unixsocket]]
==== UNIX domain sockets
Using the protocol option "unix" with the "/relay add" command, you can
listen using any protocol on a UNIX domain socket at a given path. For exmaple:
----
/relay add unix.weechat /tmp/weesock
----
will allow clients to connect using the WeeChat protocol to /tmp/weesock. This
is particularly useful to allow SSH forwarding for relay clients, when other
ports cannot be opened. Using OpenSSH:
----
$ ssh -L9000:/tmp/weesock foo_host
----
will then allow for local relay clients to connect on port 9000 to a WeeChat
instance running on "foo_host".
[[relay_commands]]
==== Commands

View File

@ -1355,9 +1355,9 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server)
relay_clients = new_client;
weechat_printf_date_tags (NULL, 0, "relay_client",
_("%s: new client on port %d: %s%s%s"),
_("%s: new client on port/path %s: %s%s%s"),
RELAY_PLUGIN_NAME,
server->port,
server->path,
RELAY_COLOR_CHAT_CLIENT,
new_client->desc,
RELAY_COLOR_CHAT);

View File

@ -134,7 +134,7 @@ relay_command_server_list ()
if (relay_servers)
{
weechat_printf (NULL, "");
weechat_printf (NULL, _("Listening on ports:"));
weechat_printf (NULL, _("Listening on:"));
i = 1;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
@ -143,14 +143,15 @@ relay_command_server_list ()
{
weechat_printf (
NULL,
_(" port %s%d%s, relay: %s%s%s, %s (not started)"),
_(" %s %s%s%s, relay: %s%s%s, %s (not started)"),
RELAY_COLOR_CHAT_BUFFER,
ptr_server->port,
ptr_server->un ? _("path") : _("port"),
ptr_server->path,
RELAY_COLOR_CHAT,
RELAY_COLOR_CHAT_BUFFER,
ptr_server->protocol_string,
RELAY_COLOR_CHAT,
((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : "IPv4")));
((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : ((ptr_server->ipv4) ? "IPv4" : "UNIX"))));
}
else
{
@ -164,15 +165,16 @@ relay_command_server_list ()
}
weechat_printf (
NULL,
_(" port %s%d%s, relay: %s%s%s, %s, started on: %s"),
_(" %s %s%s%s, relay: %s%s%s, %s, started on: %s"),
ptr_server->un ? _("path") : _("port"),
RELAY_COLOR_CHAT_BUFFER,
ptr_server->port,
ptr_server->path,
RELAY_COLOR_CHAT,
RELAY_COLOR_CHAT_BUFFER,
ptr_server->protocol_string,
RELAY_COLOR_CHAT,
((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : "IPv4")),
date_start);
((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : ((ptr_server->ipv4) ? "IPv4" : "UNIX"))),
date_start);
}
i++;
}
@ -192,7 +194,8 @@ relay_command_relay (const void *pointer, void *data,
{
struct t_relay_server *ptr_server;
struct t_config_option *ptr_option;
int port;
struct t_config_section *port_path_section;
char *path;
/* make C compiler happy */
(void) pointer;
@ -222,15 +225,19 @@ relay_command_relay (const void *pointer, void *data,
if (weechat_strcasecmp (argv[1], "add") == 0)
{
WEECHAT_COMMAND_MIN_ARGS(4, "add");
/* check if we're expecting a path or a port */
port_path_section = strncmp (argv[2], "unix.", 5) ?
relay_config_section_port :
relay_config_section_path;
if (relay_config_create_option_port (
NULL, NULL,
relay_config_file,
relay_config_section_port,
port_path_section,
argv[2],
argv_eol[3]) != WEECHAT_CONFIG_OPTION_SET_ERROR)
{
weechat_printf (NULL,
_("%s: relay \"%s\" (port %s) added"),
_("%s: relay \"%s\" (path/port: %s) added"),
RELAY_PLUGIN_NAME,
argv[2], argv_eol[3]);
}
@ -243,17 +250,21 @@ relay_command_relay (const void *pointer, void *data,
ptr_server = relay_server_search (argv_eol[2]);
if (ptr_server)
{
port = ptr_server->port;
path = strdup (ptr_server->path);
relay_server_free (ptr_server);
ptr_option = weechat_config_search_option (relay_config_file,
relay_config_section_port,
ptr_server->un ?
relay_config_section_path :
relay_config_section_port,
argv_eol[2]);
if (ptr_option)
weechat_config_option_free (ptr_option);
weechat_printf (NULL,
_("%s: relay \"%s\" (port %d) removed"),
_("%s: relay \"%s\" (%s %s) removed"),
RELAY_PLUGIN_NAME,
argv[2], port);
argv[2], ptr_server->un ? _("path") : _("port"),
path);
free (path);
}
else
{
@ -391,7 +402,7 @@ relay_command_init ()
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 a relay (listen on a port)\n"
" add: add a relay (listen on a port/path)\n"
" del: remove a relay (clients remain connected)\n"
" start: listen on port\n"
" restart: close the server socket and listen again on port "
@ -407,6 +418,7 @@ relay_command_init ()
" ipv4: force use of IPv4\n"
" ipv6: force use of IPv6\n"
" ssl: enable SSL\n"
" unix: use UNIX domain socket\n"
"protocol.name: protocol and name to relay:\n"
" - protocol \"irc\": name is the server to share "
"(optional, if not given, the server name must be sent by client in "
@ -437,7 +449,9 @@ relay_command_init ()
" weechat protocol with SSL, using only IPv6:\n"
" /relay add ipv6.ssl.weechat 9001\n"
" weechat protocol with SSL, using IPv4 + IPv6:\n"
" /relay add ipv4.ipv6.ssl.weechat 9001"),
" /relay add ipv4.ipv6.ssl.weechat 9001\n"
" weechat protocol over UNIX domain socket:\n"
" /relay add unix.weechat /tmp/weesock\n"),
"list %(relay_relays)"
" || listfull %(relay_relays)"
" || listrelay"

View File

@ -23,6 +23,7 @@
#include <string.h>
#include <limits.h>
#include <regex.h>
#include <sys/un.h>
#include "../weechat-plugin.h"
#include "relay.h"
@ -36,6 +37,7 @@
struct t_config_file *relay_config_file = NULL;
struct t_config_section *relay_config_section_port = NULL;
struct t_config_section *relay_config_section_path = NULL;
/* relay config, look section */
@ -185,7 +187,7 @@ relay_config_change_network_ipv6_cb (const void *pointer, void *data,
{
relay_server_get_protocol_args (ptr_server->protocol_string,
&ptr_server->ipv4, &ptr_server->ipv6,
NULL, NULL, NULL);
NULL, &ptr_server->un, NULL, NULL);
relay_server_close_socket (ptr_server);
relay_server_create_socket (ptr_server);
}
@ -509,6 +511,75 @@ relay_config_check_port_cb (const void *pointer, void *data,
return 1;
}
/*
* Checks if a UNIX path is too long or empty.
*
* Returns:
* 1: path is valid
* 0: path is empty, or too long
*/
int
relay_config_check_path_len (const char *path)
{
struct sockaddr_un addr;
size_t max_path, path_len;
max_path = sizeof (addr.sun_path);
path_len = strlen (path);
if (!path_len)
{
weechat_printf (NULL, _("%s%s: error: path is empty"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME);
return 0;
}
if (path_len >= max_path)
{
weechat_printf (NULL,
_("%s%s: error: path \"%s\" too long (length: %d; max: %d)"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME, path,
path_len, max_path);
return 0;
}
return 1;
}
/*
* Checks if a path is valid.
*
* Returns:
* 1: path is valid
* 0: path is not valid
*/
int
relay_config_check_path_cb (const void *pointer, void *data,
struct t_config_option *option,
const char *value)
{
struct t_relay_server *ptr_server;
/* make C compiler happy */
(void) pointer;
(void) data;
(void) option;
if (!relay_config_check_path_len (value))
return 0;
ptr_server = relay_server_search_path (value);
if (ptr_server)
{
weechat_printf (NULL, _("%s%s: error: path \"%s\" is already used"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, value);
return 0;
}
return 1;
}
/*
* Callback for changes on options in section "port".
*/
@ -561,7 +632,7 @@ relay_config_create_option_port (const void *pointer, void *data,
const char *option_name,
const char *value)
{
int rc, protocol_number, ipv4, ipv6, ssl;
int rc, protocol_number, ipv4, ipv6, ssl, un;
char *error, *protocol, *protocol_args;
long port;
struct t_relay_server *ptr_server;
@ -575,7 +646,7 @@ relay_config_create_option_port (const void *pointer, void *data,
protocol_number = -1;
port = -1;
relay_server_get_protocol_args (option_name, &ipv4, &ipv6, &ssl,
relay_server_get_protocol_args (option_name, &ipv4, &ipv6, &ssl, &un,
&protocol, &protocol_args);
#ifndef HAVE_GNUTLS
@ -625,14 +696,23 @@ relay_config_create_option_port (const void *pointer, void *data,
if (rc != WEECHAT_CONFIG_OPTION_SET_ERROR)
{
error = NULL;
port = strtol (value, &error, 10);
ptr_server = relay_server_search_port ((int)port);
if (un)
{
ptr_server = relay_server_search_path (value);
}
else
{
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_printf (NULL, _("%s%s: error: %s \"%s\" is already used"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, (int)port);
RELAY_PLUGIN_NAME,
un ? _("path") : _("port"),
value);
rc = WEECHAT_CONFIG_OPTION_SET_ERROR;
}
}
@ -640,16 +720,29 @@ relay_config_create_option_port (const void *pointer, void *data,
if (rc != WEECHAT_CONFIG_OPTION_SET_ERROR)
{
if (relay_server_new (option_name, protocol_number, protocol_args,
port, ipv4, ipv6, ssl))
port, value, ipv4, ipv6, ssl, un))
{
/* create configuration option */
weechat_config_new_option (
if (un)
{
weechat_config_new_option (
config_file, section,
option_name, "string", NULL,
NULL, 0, 0, "", value, 0,
&relay_config_check_path_cb, NULL, NULL,
&relay_config_change_port_cb, NULL, NULL,
&relay_config_delete_port_cb, NULL, NULL);
}
else
{
weechat_config_new_option (
config_file, section,
option_name, "integer", NULL,
NULL, 0, 65535, "", value, 0,
&relay_config_check_port_cb, NULL, NULL,
&relay_config_change_port_cb, NULL, NULL,
&relay_config_delete_port_cb, NULL, NULL);
}
rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
}
else
@ -1067,6 +1160,23 @@ relay_config_init ()
relay_config_section_port = ptr_section;
/* section path */
ptr_section = weechat_config_new_section (
relay_config_file, "path",
1, 1,
NULL, NULL, NULL,
NULL, NULL, NULL,
NULL, NULL, NULL,
&relay_config_create_option_port, NULL, NULL,
NULL, NULL, NULL);
if (!ptr_section)
{
weechat_config_free (relay_config_file);
relay_config_file = NULL;
return 0;
}
relay_config_section_path = ptr_section;
return 1;
}

View File

@ -26,6 +26,7 @@
extern struct t_config_file *relay_config_file;
extern struct t_config_section *relay_config_section_port;
extern struct t_config_section *relay_config_section_path;
extern struct t_config_option *relay_config_look_auto_open_buffer;
extern struct t_config_option *relay_config_look_raw_messages;
@ -72,6 +73,7 @@ extern int relay_config_create_option_port (const void *pointer, void *data,
struct t_config_section *section,
const char *option_name,
const char *value);
extern int relay_config_check_path_len (const char *path);
extern int relay_config_init ();
extern int relay_config_read ();
extern int relay_config_write ();

View File

@ -30,6 +30,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include "../weechat-plugin.h"
#include "relay.h"
@ -49,32 +50,34 @@ struct t_relay_server *last_relay_server = NULL;
*
* Examples:
*
* string ipv4 ipv6 ssl protocol protocol_args
* string ipv4 ipv6 ssl unix protocol protocol_args
* ---------------------------------------------------------------
* irc.freenode 1 1 0 irc freenode
* ssl.irc.freenode 1 1 1 irc freenode
* ipv4.irc.freenode 1 0 0 irc freenode
* ipv6.irc.freenode 0 1 0 irc freenode
* ipv4.ipv6.irc.freenode 1 1 0 irc freenode
* ipv6.ssl.irc.freenode 0 1 1 irc freenode
* weechat 1 1 0 weechat
* ssl.weechat 1 1 1 weechat
* ipv6.ssl.weechat 0 1 1 weechat
* irc.freenode 1 1 0 0 irc freenode
* ssl.irc.freenode 1 1 1 0 irc freenode
* ipv4.irc.freenode 1 0 0 0 irc freenode
* ipv6.irc.freenode 0 1 0 0 irc freenode
* ipv4.ipv6.irc.freenode 1 1 0 0 irc freenode
* ipv6.ssl.irc.freenode 0 1 1 0 irc freenode
* weechat 1 1 0 0 weechat
* ssl.weechat 1 1 1 0 weechat
* ipv6.ssl.weechat 0 1 1 0 weechat
* unix.weechat 0 0 0 1 weechat
*
* Note: *protocol and *protocol_args must be freed after use.
*/
void
relay_server_get_protocol_args (const char *protocol_and_args,
int *ipv4, int *ipv6, int *ssl,
int *ipv4, int *ipv6, int *ssl, int *un,
char **protocol, char **protocol_args)
{
int opt_ipv4, opt_ipv6, opt_ssl;
int opt_ipv4, opt_ipv6, opt_ssl, opt_un;
char *pos;
opt_ipv4 = -1;
opt_ipv6 = -1;
opt_ssl = 0;
opt_un = -1;
while (1)
{
if (strncmp (protocol_and_args, "ipv4.", 5) == 0)
@ -92,18 +95,24 @@ relay_server_get_protocol_args (const char *protocol_and_args,
opt_ssl = 1;
protocol_and_args += 4;
}
else if (strncmp (protocol_and_args, "unix.", 5) == 0)
{
opt_un = 1;
protocol_and_args += 5;
}
else
break;
}
if ((opt_ipv4 == -1) && (opt_ipv6 == -1))
if ((opt_ipv4 == -1) && (opt_ipv6 == -1) && (opt_un == -1))
{
/*
* no IPv4/IPv6 specified, then use defaults:
* no IPv4/IPv6/UNIX specified, then use defaults:
* - IPv4 enabled
* - IPv6 enabled if option relay.network.ipv6 is on
*/
opt_ipv4 = 1;
opt_ipv6 = weechat_config_boolean (relay_config_network_ipv6);
opt_un = 0;
}
else
{
@ -111,10 +120,12 @@ relay_server_get_protocol_args (const char *protocol_and_args,
opt_ipv4 = 0;
if (opt_ipv6 == -1)
opt_ipv6 = 0;
if (opt_un == -1)
opt_un = 0;
}
if (!opt_ipv4 && !opt_ipv6)
if (!opt_ipv4 && !opt_ipv6 && !opt_un)
{
/* both IPv4/IPv6 disabled (should never occur!) */
/* IPv4/IPv6/UNIX disabled (should never occur!) */
opt_ipv4 = 1;
}
if (ipv4)
@ -123,6 +134,8 @@ relay_server_get_protocol_args (const char *protocol_and_args,
*ipv6 = opt_ipv6;
if (ssl)
*ssl = opt_ssl;
if (un)
*un = opt_un;
pos = strchr (protocol_and_args, '.');
if (pos)
@ -187,6 +200,28 @@ relay_server_search_port (int port)
return NULL;
}
/*
* Searches for a server by path. Only returns servers using a UNIX socket.
*
* Returns pointer to new server, NULL if not found.
*/
struct t_relay_server *
relay_server_search_path (const char *path)
{
struct t_relay_server *ptr_server;
for (ptr_server = relay_servers; ptr_server;
ptr_server = ptr_server->next_server)
{
/* only include UNIX socket relays, to allow for numerical paths */
if (!strcmp (path, ptr_server->path) && ptr_server->un)
return ptr_server;
}
/* server not found */
return NULL;
}
/*
* Closes socket for a relay server.
*/
@ -203,13 +238,17 @@ relay_server_close_socket (struct t_relay_server *server)
{
close (server->sock);
server->sock = -1;
if (server->un)
{
unlink (server->path);
}
if (!relay_signal_upgrade_received)
{
weechat_printf (NULL,
_("%s: socket closed for %s (port %d)"),
_("%s: socket closed for %s (%s %s)"),
RELAY_PLUGIN_NAME, server->protocol_string,
server->port);
server->un ? _("path") : _("port"),
server->path);
}
}
}
@ -224,10 +263,13 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
struct t_relay_server *server;
struct sockaddr_in client_addr;
struct sockaddr_in6 client_addr6;
struct sockaddr_un client_addr_un;
socklen_t client_addr_size;
void *ptr_addr;
int client_fd, flags, set, max_clients, num_clients_on_port;
char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1];
char un_address[sizeof (client_addr_un.sun_path)];
char *ptr_ip_address, *relay_password, *relay_totp_secret;
/* make C compiler happy */
@ -245,11 +287,16 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
ptr_addr = &client_addr6;
client_addr_size = sizeof (struct sockaddr_in6);
}
else
else if (server->ipv4)
{
ptr_addr = &client_addr;
client_addr_size = sizeof (struct sockaddr_in);
}
else if (server->un)
{
ptr_addr = &client_addr_un;
client_addr_size = sizeof (struct sockaddr_un);
}
memset (ptr_addr, 0, client_addr_size);
@ -258,9 +305,10 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
if (client_fd < 0)
{
weechat_printf (NULL,
_("%s%s: cannot accept client on port %d (%s): error %d %s"),
_("%s%s: cannot accept client on %s %s (%s): error %d %s"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
server->port, server->protocol_string,
server->un ? _("path") : _("port"),
server->path, server->protocol_string,
errno, strerror (errno));
goto error;
}
@ -345,7 +393,7 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
}
}
}
else
else if (server->ipv4)
{
if (inet_ntop (AF_INET,
&(client_addr.sin_addr),
@ -355,6 +403,11 @@ relay_server_sock_cb (const void *pointer, void *data, int fd)
ptr_ip_address = ipv4_address;
}
}
else
{
strncpy (un_address, client_addr_un.sun_path, sizeof (un_address));
ptr_ip_address = un_address;
}
/* check if IP is allowed, if not, just close socket */
if (relay_config_regex_allowed_ips
@ -422,6 +475,7 @@ relay_server_create_socket (struct t_relay_server *server)
int domain, set, max_clients, addr_size;
struct sockaddr_in server_addr;
struct sockaddr_in6 server_addr6;
struct sockaddr_un server_addr_un;
const char *bind_address;
void *ptr_addr;
@ -449,7 +503,7 @@ relay_server_create_socket (struct t_relay_server *server)
ptr_addr = &server_addr6;
addr_size = sizeof (struct sockaddr_in6);
}
else
else if (server->ipv4)
{
domain = AF_INET;
memset (&server_addr, 0, sizeof (struct sockaddr_in));
@ -471,6 +525,21 @@ relay_server_create_socket (struct t_relay_server *server)
ptr_addr = &server_addr;
addr_size = sizeof (struct sockaddr_in);
}
else
{
domain = AF_UNIX;
memset (&server_addr_un, 0, sizeof (struct sockaddr_un));
server_addr_un.sun_family = domain;
strncpy (server_addr_un.sun_path, server->path,
sizeof (server_addr_un.sun_path));
ptr_addr = &server_addr_un;
addr_size = sizeof (struct sockaddr_un);
if (!relay_config_check_path_len (server->path))
return 0;
/* just in case it already exists */
unlink (server->path);
}
/* create socket */
server->sock = socket (domain, SOCK_STREAM, 0);
@ -543,9 +612,10 @@ relay_server_create_socket (struct t_relay_server *server)
if (bind (server->sock, (struct sockaddr *)ptr_addr, addr_size) < 0)
{
weechat_printf (NULL,
_("%s%s: cannot \"bind\" on port %d (%s): error %d %s"),
_("%s%s: cannot \"bind\" on %s %s (%s): error %d %s"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
server->port, server->protocol_string,
server->un ? _("path") : _("port"),
server->path, server->protocol_string,
errno, strerror (errno));
close (server->sock);
server->sock = -1;
@ -559,9 +629,10 @@ relay_server_create_socket (struct t_relay_server *server)
#endif
{
weechat_printf (NULL,
_("%s%s: cannot \"listen\" on port %d (%s): error %d %s"),
_("%s%s: cannot \"listen\" on %s %s (%s): error %d %s"),
weechat_prefix ("error"), RELAY_PLUGIN_NAME,
server->port, server->protocol_string,
server->un ? _("path") : _("port"),
server->path, server->protocol_string,
errno, strerror (errno));
close (server->sock);
server->sock = -1;
@ -573,24 +644,26 @@ relay_server_create_socket (struct t_relay_server *server)
{
weechat_printf (
NULL,
NG_("%s: listening on port %d (relay: %s, %s, max %d client)",
"%s: listening on port %d (relay: %s, %s, max %d clients)",
NG_("%s: listening on %s %s (relay: %s, %s, max %d client)",
"%s: listening on %s %s (relay: %s, %s, max %d clients)",
max_clients),
RELAY_PLUGIN_NAME,
server->port,
server->un ? _("path") : _("port"),
server->path,
server->protocol_string,
((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : "IPv4")),
((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))),
max_clients);
}
else
{
weechat_printf (
NULL,
_("%s: listening on port %d (relay: %s, %s)"),
_("%s: listening on %s %s (relay: %s, %s)"),
RELAY_PLUGIN_NAME,
server->port,
server->un ? _("path") : _("port"),
server->path,
server->protocol_string,
((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : "IPv4")));
((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))));
}
server->hook_fd = weechat_hook_fd (server->sock,
1, 0, 0,
@ -610,17 +683,21 @@ relay_server_create_socket (struct t_relay_server *server)
struct t_relay_server *
relay_server_new (const char *protocol_string, enum t_relay_protocol protocol,
const char *protocol_args, int port, int ipv4, int ipv6,
int ssl)
const char *protocol_args, int port, const char *path,
int ipv4, int ipv6, int ssl, int un)
{
struct t_relay_server *new_server;
struct t_relay_server *new_server, *dup_server;
if (!protocol_string)
return NULL;
if (relay_server_search_port (port))
/* look for duplicate ports/paths */
dup_server = un ?
relay_server_search_path (path) : relay_server_search_port (port);
if (dup_server)
{
weechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"),
weechat_printf (NULL, _("%s%s: error: %s \"%s\" is already used"),
un ? _("path") : _("port"),
weechat_prefix ("error"),
RELAY_PLUGIN_NAME, port);
return NULL;
@ -634,9 +711,11 @@ relay_server_new (const char *protocol_string, enum t_relay_protocol protocol,
new_server->protocol_args =
(protocol_args) ? strdup (protocol_args) : NULL;
new_server->port = port;
new_server->path = strdup (path);
new_server->ipv4 = ipv4;
new_server->ipv6 = ipv6;
new_server->ssl = ssl;
new_server->un = un;
new_server->sock = -1;
new_server->hook_fd = NULL;
new_server->start_time = 0;
@ -708,7 +787,7 @@ relay_server_free (struct t_relay_server *server)
free (server->protocol_string);
if (server->protocol_args)
free (server->protocol_args);
free (server->path);
free (server);
relay_servers = new_relay_servers;
@ -756,12 +835,16 @@ relay_server_add_to_infolist (struct t_infolist *infolist,
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "port", server->port))
return 0;
if (!weechat_infolist_new_var_string (ptr_item, "path", server->path))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "ipv4", server->ipv4))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "ipv6", server->ipv6))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "ssl", server->ssl))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "un", server->un))
return 0;
if (!weechat_infolist_new_var_integer (ptr_item, "sock", server->sock))
return 0;
if (!weechat_infolist_new_var_pointer (ptr_item, "hook_fd", server->hook_fd))
@ -794,9 +877,11 @@ relay_server_print_log ()
relay_protocol_string[ptr_server->protocol]);
weechat_log_printf (" protocol_args . . . . : '%s'", ptr_server->protocol_args);
weechat_log_printf (" port. . . . . . . . . : %d", ptr_server->port);
weechat_log_printf (" path. . . . . . . . . : %s", ptr_server->path);
weechat_log_printf (" ipv4. . . . . . . . . : %d", ptr_server->ipv4);
weechat_log_printf (" ipv6. . . . . . . . . : %d", ptr_server->ipv6);
weechat_log_printf (" ssl . . . . . . . . . : %d", ptr_server->ssl);
weechat_log_printf (" unix. . . . . . . . . : %d", ptr_server->un);
weechat_log_printf (" sock. . . . . . . . . : %d", ptr_server->sock);
weechat_log_printf (" hook_fd . . . . . . . : 0x%lx", ptr_server->hook_fd);
weechat_log_printf (" start_time. . . . . . : %lld", (long long)ptr_server->start_time);

View File

@ -21,7 +21,6 @@
#define WEECHAT_PLUGIN_RELAY_SERVER_H
#include <time.h>
#ifdef HAVE_GNUTLS
#define RELAY_SERVER_GNUTLS_DH_BITS 1024
#endif /* HAVE_GNUTLS */
@ -33,9 +32,14 @@ struct t_relay_server
char *protocol_args; /* arguments used for protocol */
/* example: server for irc protocol */
int port; /* listening on this port */
/* or UNIX socket, if negative. */
char *path; /* listening on this path (UNIX) */
/* contains string representation of */
/* port if IP */
int ipv4; /* IPv4 protocol enabled */
int ipv6; /* IPv6 protocol enabled */
int ssl; /* 1 if SSL is enabled */
int un; /* 1 if UNIX socket */
int sock; /* socket for connection */
struct t_hook *hook_fd; /* hook for socket */
time_t start_time; /* start time */
@ -49,18 +53,20 @@ extern struct t_relay_server *last_relay_server;
extern void relay_server_get_protocol_args (const char *protocol_and_string,
int *ipv4, int *ipv6,
int *ssl,
int *ssl, int *un,
char **protocol,
char **protocol_args);
extern struct t_relay_server *relay_server_search (const char *protocol_and_args);
extern struct t_relay_server *relay_server_search_port (int port);
extern struct t_relay_server *relay_server_search_path (const char *path);
extern void relay_server_close_socket (struct t_relay_server *server);
extern int relay_server_create_socket (struct t_relay_server *server);
extern struct t_relay_server *relay_server_new (const char *protocol_string,
enum t_relay_protocol protocol,
const char *protocol_args,
int port, int ipv4, int ipv6,
int ssl);
int port, const char *path,
int ipv4, int ipv6,
int ssl, int un);
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 ();