mirror of
https://github.com/irssi/irssi.git
synced 2024-11-03 04:27:19 -05:00
Merge pull request #425 from mauke/irssiproxy-multiplex
irssi proxy: allow multiplexing multiple networks over a single port
This commit is contained in:
commit
f83a29b764
@ -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:
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -48,7 +48,7 @@ static void remove_client(CLIENT_REC *rec)
|
|||||||
|
|
||||||
signal_emit("proxy client disconnected", 1, rec);
|
signal_emit("proxy client disconnected", 1, rec);
|
||||||
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
printtext(rec->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||||
"Proxy: Client %s:%d disconnected", rec->host, rec->port);
|
"Proxy: Client %s:%d disconnected", rec->host, rec->port);
|
||||||
|
|
||||||
g_free(rec->proxy_address);
|
g_free(rec->proxy_address);
|
||||||
net_sendbuffer_destroy(rec->handle, TRUE);
|
net_sendbuffer_destroy(rec->handle, TRUE);
|
||||||
@ -59,7 +59,7 @@ static void remove_client(CLIENT_REC *rec)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void proxy_redirect_event(CLIENT_REC *client, const char *command,
|
static void proxy_redirect_event(CLIENT_REC *client, const char *command,
|
||||||
int count, const char *arg, int remote)
|
int count, const char *arg, int remote)
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ static void proxy_redirect_event(CLIENT_REC *client, const char *command,
|
|||||||
|
|
||||||
str = g_strdup_printf("proxy %p", client);
|
str = g_strdup_printf("proxy %p", client);
|
||||||
server_redirect_event(client->server, command, count,
|
server_redirect_event(client->server, command, count,
|
||||||
arg, remote, NULL, "", str, NULL);
|
arg, remote, NULL, "", str, NULL);
|
||||||
g_free(str);
|
g_free(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,28 +94,58 @@ static void grab_who(CLIENT_REC *client, const char *channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
proxy_redirect_event(client, "who",
|
proxy_redirect_event(client, "who",
|
||||||
client->server->one_endofwho ? 1 : count,
|
client->server->one_endofwho ? 1 : count,
|
||||||
arg->str, -1);
|
arg->str, -1);
|
||||||
|
|
||||||
g_strfreev(list);
|
g_strfreev(list);
|
||||||
g_string_free(arg, TRUE);
|
g_string_free(arg, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_client_connect_cmd(CLIENT_REC *client,
|
static void handle_client_connect_cmd(CLIENT_REC *client,
|
||||||
const char *cmd, const char *args)
|
const char *cmd, const char *args)
|
||||||
{
|
{
|
||||||
const char *password;
|
const char *password;
|
||||||
|
|
||||||
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,14 +154,14 @@ 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 {
|
||||||
signal_emit("proxy client connected", 1, client);
|
signal_emit("proxy client connected", 1, client);
|
||||||
printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
printtext(client->server, NULL, MSGLEVEL_CLIENTNOTICE,
|
||||||
"Proxy: Client %s:%d connected",
|
"Proxy: Client %s:%d connected",
|
||||||
client->host, client->port);
|
client->host, client->port);
|
||||||
client->connected = TRUE;
|
client->connected = TRUE;
|
||||||
proxy_dump_data(client);
|
proxy_dump_data(client);
|
||||||
}
|
}
|
||||||
@ -139,7 +169,7 @@ static void handle_client_connect_cmd(CLIENT_REC *client,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
||||||
const char *data)
|
const char *data)
|
||||||
{
|
{
|
||||||
GSList *tmp;
|
GSList *tmp;
|
||||||
if (!client->connected) {
|
if (!client->connected) {
|
||||||
@ -162,8 +192,8 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
|||||||
g_ascii_strcasecmp(target, client->proxy_address) == 0 ||
|
g_ascii_strcasecmp(target, client->proxy_address) == 0 ||
|
||||||
g_ascii_strcasecmp(target, client->nick) == 0) {
|
g_ascii_strcasecmp(target, client->nick) == 0) {
|
||||||
proxy_outdata(client, ":%s PONG %s :%s\r\n",
|
proxy_outdata(client, ":%s PONG %s :%s\r\n",
|
||||||
client->proxy_address,
|
client->proxy_address,
|
||||||
client->proxy_address, origin);
|
client->proxy_address, origin);
|
||||||
g_free(params);
|
g_free(params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -174,25 +204,25 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
|||||||
if (g_ascii_strcasecmp(args, "CTCP ON") == 0) {
|
if (g_ascii_strcasecmp(args, "CTCP ON") == 0) {
|
||||||
/* client wants all ctcps */
|
/* client wants all ctcps */
|
||||||
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);
|
||||||
rec->want_ctcp = 0;
|
rec->want_ctcp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n",
|
proxy_outdata(client, ":%s NOTICE %s :You're now receiving CTCPs sent to %s\r\n",
|
||||||
client->proxy_address, client->nick,client->listen->ircnet);
|
client->proxy_address, client->nick, client->listen->ircnet);
|
||||||
} else if (g_ascii_strcasecmp(args, "CTCP OFF") == 0) {
|
} else if (g_ascii_strcasecmp(args, "CTCP OFF") == 0) {
|
||||||
/* client wants proxy to handle all ctcps */
|
/* client wants proxy to handle all ctcps */
|
||||||
client->want_ctcp = 0;
|
client->want_ctcp = 0;
|
||||||
proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\r\n",
|
proxy_outdata(client, ":%s NOTICE %s :Proxy is now handling itself CTCPs sent to %s\r\n",
|
||||||
client->proxy_address, client->nick, client->listen->ircnet);
|
client->proxy_address, client->nick, client->listen->ircnet);
|
||||||
} else {
|
} else {
|
||||||
signal_emit("proxy client command", 3, client, args, data);
|
signal_emit("proxy client command", 3, client, args, data);
|
||||||
}
|
}
|
||||||
@ -201,11 +231,11 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
|||||||
|
|
||||||
if (client->server == NULL || !client->server->connected) {
|
if (client->server == NULL || !client->server->connected) {
|
||||||
proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n",
|
proxy_outdata(client, ":%s NOTICE %s :Not connected to server\r\n",
|
||||||
client->proxy_address, client->nick);
|
client->proxy_address, client->nick);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if the command could be redirected */
|
/* check if the command could be redirected */
|
||||||
if (g_strcmp0(cmd, "WHO") == 0)
|
if (g_strcmp0(cmd, "WHO") == 0)
|
||||||
grab_who(client, args);
|
grab_who(client, args);
|
||||||
else if (g_strcmp0(cmd, "WHOWAS") == 0)
|
else if (g_strcmp0(cmd, "WHOWAS") == 0)
|
||||||
@ -263,29 +293,29 @@ static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args,
|
|||||||
char *params, *target, *msg;
|
char *params, *target, *msg;
|
||||||
|
|
||||||
params = event_get_params(args, 2 | PARAM_FLAG_GETREST,
|
params = event_get_params(args, 2 | PARAM_FLAG_GETREST,
|
||||||
&target, &msg);
|
&target, &msg);
|
||||||
proxy_outserver_all_except(client, "PRIVMSG %s", args);
|
proxy_outserver_all_except(client, "PRIVMSG %s", args);
|
||||||
|
|
||||||
ignore_next = TRUE;
|
ignore_next = TRUE;
|
||||||
if (*msg != '\001' || msg[strlen(msg)-1] != '\001') {
|
if (*msg != '\001' || msg[strlen(msg)-1] != '\001') {
|
||||||
signal_emit(server_ischannel(SERVER(client->server), target) ?
|
signal_emit(server_ischannel(SERVER(client->server), target) ?
|
||||||
"message own_public" : "message own_private", 4,
|
"message own_public" : "message own_private", 4,
|
||||||
client->server, msg, target, target);
|
client->server, msg, target, target);
|
||||||
} else if (strncmp(msg+1, "ACTION ", 7) == 0) {
|
} else if (strncmp(msg+1, "ACTION ", 7) == 0) {
|
||||||
/* action */
|
/* action */
|
||||||
msg[strlen(msg)-1] = '\0';
|
msg[strlen(msg)-1] = '\0';
|
||||||
signal_emit("message irc own_action", 3,
|
signal_emit("message irc own_action", 3,
|
||||||
client->server, msg+8, target);
|
client->server, msg+8, target);
|
||||||
} else {
|
} else {
|
||||||
/* CTCP */
|
/* CTCP */
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
msg[strlen(msg)-1] = '\0';
|
msg[strlen(msg)-1] = '\0';
|
||||||
p = strchr(msg, ' ');
|
p = strchr(msg, ' ');
|
||||||
if (p != NULL) *p++ = '\0'; else p = "";
|
if (p != NULL) *p++ = '\0'; else p = "";
|
||||||
|
|
||||||
signal_emit("message irc own_ctcp", 4,
|
signal_emit("message irc own_ctcp", 4,
|
||||||
client->server, msg+1, p, target);
|
client->server, msg+1, p, target);
|
||||||
}
|
}
|
||||||
ignore_next = FALSE;
|
ignore_next = FALSE;
|
||||||
g_free(params);
|
g_free(params);
|
||||||
@ -337,7 +367,7 @@ static void sig_listen(LISTEN_REC *listen)
|
|||||||
CLIENT_REC *rec;
|
CLIENT_REC *rec;
|
||||||
IPADDR ip;
|
IPADDR ip;
|
||||||
NET_SENDBUF_REC *sendbuf;
|
NET_SENDBUF_REC *sendbuf;
|
||||||
GIOChannel *handle;
|
GIOChannel *handle;
|
||||||
char host[MAX_IP_LEN];
|
char host[MAX_IP_LEN];
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
@ -352,9 +382,13 @@ static void sig_listen(LISTEN_REC *listen)
|
|||||||
rec = g_new0(CLIENT_REC, 1);
|
rec = g_new0(CLIENT_REC, 1);
|
||||||
rec->listen = listen;
|
rec->listen = 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 {
|
||||||
@ -363,15 +397,15 @@ static void sig_listen(LISTEN_REC *listen)
|
|||||||
IRC_SERVER(server_find_chatnet(listen->ircnet));
|
IRC_SERVER(server_find_chatnet(listen->ircnet));
|
||||||
}
|
}
|
||||||
rec->recv_tag = g_input_add(handle, G_INPUT_READ,
|
rec->recv_tag = g_input_add(handle, G_INPUT_READ,
|
||||||
(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,
|
||||||
"Proxy: New client %s:%d on port %d (%s)",
|
"Proxy: New client %s:%d on port %d (%s)",
|
||||||
rec->host, rec->port, listen->port, listen->ircnet);
|
rec->host, rec->port, listen->port, listen->ircnet);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
|
static void sig_incoming(IRC_SERVER_REC *server, const char *line)
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user