Merge pull request #425 from mauke/irssiproxy-multiplex

irssi proxy: allow multiplexing multiple networks over a single port
This commit is contained in:
ailin-nemui 2016-02-24 16:14:43 +01:00
commit f83a29b764
5 changed files with 112 additions and 47 deletions

View file

@ -30,6 +30,18 @@ There we have 3 different irc networks answering in 3 ports. Note that
you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to you'll have to make the correct /IRCNET ADD and /SERVER ADD commands to
make it work properly. make it work properly.
The special network name "?" allows the client to select the network
dynamically on connect:
/SET irssiproxy_ports ?=2777
Now the client can send <network>:<password> as the server password, e.g.
/CONNECT ... 2777 efnet:secret
to connect to efnet. If there is no irssiproxy_password set, you can
omit the ":" and just send the network name as the password.
By default, the proxy binds to all available interfaces. To make it By default, the proxy binds to all available interfaces. To make it
only listen on (for example) the loopback address: only listen on (for example) the loopback address:

View file

@ -735,6 +735,13 @@ reason, and you only use one server connection, you may simply set:</p>
/SET irssiproxy_ports *=2777 /SET irssiproxy_ports *=2777
</pre> </pre>
<p>The special network name <code>?</code> allows the client to select the
network dynamically on connect (see below):</p>
<pre>
/SET irssiproxy_ports ?=2777
</pre>
<p>Usage in client side:</p> <p>Usage in client side:</p>
<p>Just connect to the irssi proxy like it is a normal server with password <p>Just connect to the irssi proxy like it is a normal server with password
@ -745,6 +752,16 @@ specified in <code>/SET irssiproxy_password</code>. For example:</p>
/SERVER ADD -network efnet my.irssi-proxy.org 2778 secret /SERVER ADD -network efnet my.irssi-proxy.org 2778 secret
</pre> </pre>
<p>Or, if you used <code>?</code> in <code>irssiproxy_ports</code>:</p>
<pre>
/SERVER ADD -network IRCnet my.irssi-proxy.org 2777 IRCnet:secret
/SERVER ADD -network efnet my.irssi-proxy.org 2777 efnet:secret
</pre>
<p>I.e. the network to connect to is specified as part of the password,
separated by <code>:</code> from the actual proxy password.</p>
<p>Irssi proxy works fine with other IRC clients as well.</p> <p>Irssi proxy works fine with other IRC clients as well.</p>
<p><strong>SOCKS</strong></p> <p><strong>SOCKS</strong></p>

View file

@ -108,14 +108,44 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
password = settings_get_str("irssiproxy_password"); password = settings_get_str("irssiproxy_password");
if (password != NULL && g_strcmp0(cmd, "PASS") == 0) { if (g_strcmp0(cmd, "PASS") == 0) {
if (g_strcmp0(password, args) == 0) const char *args_pass;
client->pass_sent = TRUE;
else { if (!client->multiplex) {
args_pass = args;
} else {
IRC_SERVER_REC *server;
char *tag;
const char *tag_end;
if ((tag_end = strchr(args, ':')) != NULL) {
args_pass = tag_end + 1;
} else {
tag_end = args + strlen(args);
args_pass = "";
}
tag = g_strndup(args, tag_end - args);
server = IRC_SERVER(server_find_chatnet(tag));
g_free(tag);
if (!server) {
/* an invalid network was specified */
remove_client(client);
return;
}
client->server = server;
g_free(client->proxy_address);
client->proxy_address = g_strdup_printf("%*s.proxy", (int)(tag_end - args), args);
}
if (g_strcmp0(password, args_pass) != 0) {
/* wrong password! */ /* wrong password! */
remove_client(client); remove_client(client);
return; return;
} }
client->pass_sent = TRUE;
} else if (g_strcmp0(cmd, "NICK") == 0) { } else if (g_strcmp0(cmd, "NICK") == 0) {
g_free_not_null(client->nick); g_free_not_null(client->nick);
client->nick = g_strdup(args); client->nick = g_strdup(args);
@ -124,7 +154,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
} }
if (client->nick != NULL && client->user_sent) { if (client->nick != NULL && client->user_sent) {
if (*password != '\0' && !client->pass_sent) { if ((*password != '\0' || client->multiplex) && !client->pass_sent) {
/* client didn't send us PASS, kill it */ /* client didn't send us PASS, kill it */
remove_client(client); remove_client(client);
} else { } else {
@ -176,9 +206,9 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
client->want_ctcp = 1; client->want_ctcp = 1;
for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) { for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
CLIENT_REC *rec = tmp->data; CLIENT_REC *rec = tmp->data;
if ((g_ascii_strcasecmp(client->listen->ircnet,rec->listen->ircnet) == 0) && if (g_ascii_strcasecmp(client->listen->ircnet, rec->listen->ircnet) == 0 &&
/* kludgy way to check if the clients aren't the same */ /* kludgy way to check if the clients aren't the same */
(client->recv_tag != rec->recv_tag)) { client->recv_tag != rec->recv_tag) {
if (rec->want_ctcp == 1) if (rec->want_ctcp == 1)
proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n", proxy_outdata(rec, ":%s NOTICE %s :Another client is now receiving CTCPs sent to %s\r\n",
rec->proxy_address, rec->nick, rec->listen->ircnet); rec->proxy_address, rec->nick, rec->listen->ircnet);
@ -354,7 +384,11 @@ static void sig_listen(LISTEN_REC *listen)
rec->handle = sendbuf; rec->handle = sendbuf;
rec->host = g_strdup(host); rec->host = g_strdup(host);
rec->port = port; rec->port = port;
if (g_strcmp0(listen->ircnet, "*") == 0) { if (g_strcmp0(listen->ircnet, "?") == 0) {
rec->multiplex = TRUE;
rec->proxy_address = g_strdup("multiplex.proxy");
rec->server = NULL;
} else if (g_strcmp0(listen->ircnet, "*") == 0) {
rec->proxy_address = g_strdup("irc.proxy"); rec->proxy_address = g_strdup("irc.proxy");
rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data); rec->server = servers == NULL ? NULL : IRC_SERVER(servers->data);
} else { } else {
@ -366,7 +400,7 @@ static void sig_listen(LISTEN_REC *listen)
(GInputFunction) sig_listen_client, rec); (GInputFunction) sig_listen_client, rec);
proxy_clients = g_slist_prepend(proxy_clients, rec); proxy_clients = g_slist_prepend(proxy_clients, rec);
rec->listen->clients = g_slist_prepend(rec->listen->clients, rec); listen->clients = g_slist_prepend(listen->clients, rec);
signal_emit("proxy client connecting", 1, rec); signal_emit("proxy client connecting", 1, rec);
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE, printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,

View file

@ -29,6 +29,7 @@ typedef struct {
unsigned int user_sent:1; unsigned int user_sent:1;
unsigned int connected:1; unsigned int connected:1;
unsigned int want_ctcp:1; unsigned int want_ctcp:1;
unsigned int multiplex:1;
} CLIENT_REC; } CLIENT_REC;
#endif #endif

View file

@ -157,6 +157,7 @@ static void perl_client_fill_hash(HV *hv, CLIENT_REC *client)
(void) hv_store(hv, "user_sent", 9, newSViv(client->user_sent), 0); (void) hv_store(hv, "user_sent", 9, newSViv(client->user_sent), 0);
(void) hv_store(hv, "connected", 9, newSViv(client->connected), 0); (void) hv_store(hv, "connected", 9, newSViv(client->connected), 0);
(void) hv_store(hv, "want_ctcp", 9, newSViv(client->want_ctcp), 0); (void) hv_store(hv, "want_ctcp", 9, newSViv(client->want_ctcp), 0);
(void) hv_store(hv, "multiplex", 9, newSViv(client->multiplex), 0);
(void) hv_store(hv, "ircnet", 6, new_pv(client->listen->ircnet), 0); (void) hv_store(hv, "ircnet", 6, new_pv(client->listen->ircnet), 0);
} }