summaryrefslogtreecommitdiff
path: root/src/irc/proxy
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2000-11-06 02:29:01 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2000-11-06 02:29:01 +0000
commita8c139d5e2f11b5f37bdffa83fbcef0d927bae9d (patch)
tree5aac2532b76b8551a0166fe914deb9f1db6a8a71 /src/irc/proxy
parent2fc8c5b83fd9f077433a4740df2f30cd67d899a2 (diff)
downloadirssi-a8c139d5e2f11b5f37bdffa83fbcef0d927bae9d.zip
Proxy plugin fixes and cleanups. Supports now multiple servers, doesn't
let clients see CTCP requests and if one client writes message, other clients will see it as well. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@810 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/irc/proxy')
-rw-r--r--src/irc/proxy/Makefile.am1
-rw-r--r--src/irc/proxy/dump.c257
-rw-r--r--src/irc/proxy/listen.c696
-rw-r--r--src/irc/proxy/module.h36
-rw-r--r--src/irc/proxy/proxy.c127
-rw-r--r--src/irc/proxy/proxy.h55
6 files changed, 648 insertions, 524 deletions
diff --git a/src/irc/proxy/Makefile.am b/src/irc/proxy/Makefile.am
index e4fd73b6..a8259c7f 100644
--- a/src/irc/proxy/Makefile.am
+++ b/src/irc/proxy/Makefile.am
@@ -12,5 +12,4 @@ libproxy_la_SOURCES = \
listen.c
noinst_HEADERS = \
- proxy.h \
module.h
diff --git a/src/irc/proxy/dump.c b/src/irc/proxy/dump.c
index eb222956..1b848974 100644
--- a/src/irc/proxy/dump.c
+++ b/src/irc/proxy/dump.c
@@ -18,107 +18,198 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "common.h"
+#include "module.h"
#include "network.h"
-#include "servers.h"
+#include "settings.h"
+
#include "irc-servers.h"
-#include "channels.h"
+#include "irc-channels.h"
+#include "irc-nicklist.h"
#include "modes.h"
-#include "nicklist.h"
-#include "settings.h"
-#include "proxy.h"
-static void outdata(gint handle, gchar *data, ...)
+void proxy_outdata(CLIENT_REC *client, const char *data, ...)
{
- va_list args;
- gchar *str;
+ va_list args;
+ char *str;
- va_start(args, data);
+ g_return_if_fail(client != NULL);
+ g_return_if_fail(data != NULL);
- str = g_strdup_vprintf(data, args);
- net_transmit(handle, str, strlen(str));
- g_free(str);
+ va_start(args, data);
- va_end(args);
+ str = g_strdup_vprintf(data, args);
+ net_transmit(client->handle, str, strlen(str));
+ g_free(str);
+
+ va_end(args);
}
-static void outserver(gint handle, SERVER_REC *server, gchar *data, ...)
+void proxy_outdata_all(IRC_SERVER_REC *server, const char *data, ...)
{
- va_list args;
- gchar *str;
+ va_list args;
+ GSList *tmp;
+ char *str;
+ int len;
+
+ g_return_if_fail(server != NULL);
+ g_return_if_fail(data != NULL);
- va_start(args, data);
+ va_start(args, data);
- str = g_strdup_vprintf(data, args);
- outdata(handle, ":%s!%s@proxy %s\n", server->nick, settings_get_str("user_name"), str);
- g_free(str);
+ str = g_strdup_vprintf(data, args);
+ len = strlen(str);
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
- va_end(args);
+ if (rec->connected && rec->server == server)
+ net_transmit(rec->handle, str, len);
+ }
+ g_free(str);
+
+ va_end(args);
}
-void plugin_proxy_dump_data(CLIENT_REC *client)
+void proxy_outserver(CLIENT_REC *client, const char *data, ...)
+{
+ va_list args;
+ char *str;
+
+ g_return_if_fail(client != NULL);
+ g_return_if_fail(data != NULL);
+
+ va_start(args, data);
+
+ str = g_strdup_vprintf(data, args);
+ proxy_outdata(client, ":%s!%s@proxy %s\n", client->nick,
+ settings_get_str("user_name"), str);
+ g_free(str);
+
+ va_end(args);
+}
+
+/*void proxy_outserver_all(IRC_SERVER_REC *server, const char *data, ...)
+{
+ va_list args;
+ GSList *tmp;
+ char *str;
+
+ g_return_if_fail(server != NULL);
+ g_return_if_fail(data != NULL);
+
+ va_start(args, data);
+
+ str = g_strdup_vprintf(data, args);
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
+
+ if (rec->connected && rec->server == server) {
+ proxy_outdata(rec, ":%s!%s@proxy %s\n", rec->nick,
+ settings_get_str("user_name"), str);
+ }
+ }
+ g_free(str);
+
+ va_end(args);
+}*/
+
+void proxy_outserver_all_except(CLIENT_REC *client, const char *data, ...)
+{
+ va_list args;
+ GSList *tmp;
+ char *str;
+
+ g_return_if_fail(client != NULL);
+ g_return_if_fail(data != NULL);
+
+ va_start(args, data);
+
+ str = g_strdup_vprintf(data, args);
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
+
+ if (rec->connected && rec != client &&
+ rec->server == client->server) {
+ proxy_outdata(rec, ":%s!%s@proxy %s\n", rec->nick,
+ settings_get_str("user_name"), str);
+ }
+ }
+ g_free(str);
+
+ va_end(args);
+}
+
+static void dump_join(IRC_CHANNEL_REC *channel, CLIENT_REC *client)
{
- SERVER_REC *server;
- GSList *tmp, *tmp2, *nicks;
- gint handle;
-
- handle = client->handle;
- server = servers->data;
- if (strcmp(server->nick, client->nick) != 0)
- {
- /* change nick first so that clients won't try to eg. set their own
- user mode with wrong nick.. hopefully works with all clients. */
- outdata(handle, ":%s!proxy NICK :%s\n", client->nick, server->nick);
- g_free(client->nick);
- client->nick = g_strdup(server->nick);
- }
- outdata(handle, ":proxy 001 %s :Welcome to the Internet Relay Network\n", client->nick);
- outdata(handle, ":proxy 002 %s :Your host is irssi-proxy, running version %s\n", client->nick, VERSION);
- outdata(handle, ":proxy 003 %s :This server was created ...\n", client->nick);
- if (!IRC_SERVER(server)->emode_known)
- outdata(handle, ":proxy 004 %s proxy %s oirw abiklmnopqstv\n", client->nick, VERSION);
- else
- outdata(handle, ":proxy 004 %s proxy %s oirw abeIiklmnopqstv\n", client->nick, VERSION);
- outdata(handle, ":proxy 251 %s :There are 0 users and 0 invisible on 1 servers\n", client->nick);
- outdata(handle, ":proxy 255 %s :I have 0 clients, 0 services and 0 servers\n", client->nick);
- outdata(handle, ":proxy 422 %s :MOTD File is missing\n", client->nick);
-
- /* nick / mode */
- outserver(handle, server, "MODE %s :+%s", server->nick, IRC_SERVER(server)->usermode);
-
- if (server->usermode_away)
- outdata(handle, ":proxy 306 %s :You have been marked as being away\n", server->nick);
-
- /* Send channel joins */
- for (tmp = server->channels; tmp != NULL; tmp = tmp->next)
- {
- CHANNEL_REC *rec = tmp->data;
-
- outserver(handle, rec->server, "JOIN %s", rec->name);
- outdata(handle, ":proxy 353 %s %c %s :", rec->server->nick,
- channel_mode_is_set(IRC_CHANNEL(rec), 'p') ? '*' :
- channel_mode_is_set(IRC_CHANNEL(rec), 's') ? '@' : '=',
- rec->name);
-
- nicks = nicklist_getnicks(rec);
- for (tmp2 = nicks; tmp2 != NULL; tmp2 = tmp2->next)
- {
- NICK_REC *nick = tmp2->data;
-
- if (tmp2 != nicks)
- net_transmit(handle, " ", 1);
-
- if (nick->op)
- net_transmit(handle, "@", 1);
- else if (nick->voice)
- net_transmit(handle, "+", 1);
- net_transmit(handle, nick->nick, strlen(nick->nick));
+ GSList *tmp, *nicks;
+ GString *str;
+
+ proxy_outserver(client, "JOIN %s", channel->name);
+ proxy_outdata(client, ":proxy 353 %s %c %s :", client->nick,
+ channel_mode_is_set(channel, 'p') ? '*' :
+ channel_mode_is_set(channel, 's') ? '@' : '=',
+ channel->name);
+
+ str = g_string_new(NULL);
+
+ nicks = nicklist_getnicks(CHANNEL(channel));
+ for (tmp = nicks; tmp != NULL; tmp = tmp->next) {
+ NICK_REC *nick = tmp->data;
+
+ if (tmp != nicks)
+ g_string_append_c(str, ' ');
+
+ if (nick->op)
+ g_string_append_c(str, '@');
+ else if (nick->halfop)
+ g_string_append_c(str, '%');
+ else if (nick->voice)
+ g_string_append_c(str, '+');
+ g_string_append(str, nick->nick);
}
g_slist_free(nicks);
- net_transmit(handle, "\n", 1);
- outdata(handle, ":proxy 366 %s %s :End of /NAMES list.\n", rec->server->nick, rec->name);
- if (rec->topic != NULL)
- outdata(handle, ":proxy 332 %s %s :%s\n", rec->server->nick, rec->name, rec->topic);
- }
+ g_string_append_c(str, '\n');
+ proxy_outdata(client, str->str);
+ g_string_free(str, TRUE);
+
+ proxy_outdata(client, ":proxy 366 %s %s :End of /NAMES list.\n",
+ client->nick, channel->name);
+ if (channel->topic != NULL) {
+ proxy_outdata(client, ":proxy 332 %s %s :%s\n",
+ client->nick, channel->name, channel->topic);
+ }
+}
+
+void plugin_proxy_dump_data(CLIENT_REC *client)
+{
+ if (strcmp(client->server->nick, client->nick) != 0) {
+ /* change nick first so that clients won't try to eg. set
+ their own user mode with wrong nick.. hopefully works
+ with all clients. */
+ proxy_outdata(client, ":%s!proxy NICK :%s\n",
+ client->nick, client->server->nick);
+ g_free(client->nick);
+ client->nick = g_strdup(client->server->nick);
+ }
+
+ /* welcome info */
+ proxy_outdata(client, ":proxy 001 %s :Welcome to the Internet Relay Network\n", client->nick);
+ proxy_outdata(client, ":proxy 002 %s :Your host is irssi-proxy, running version %s\n", client->nick, VERSION);
+ proxy_outdata(client, ":proxy 003 %s :This server was created ...\n", client->nick);
+ if (!client->server->emode_known)
+ proxy_outdata(client, ":proxy 004 %s proxy %s oirw abiklmnopqstv\n", client->nick, VERSION);
+ else
+ proxy_outdata(client, ":proxy 004 %s proxy %s oirw abeIiklmnopqstv\n", client->nick, VERSION);
+ proxy_outdata(client, ":proxy 251 %s :There are 0 users and 0 invisible on 1 servers\n", client->nick);
+ proxy_outdata(client, ":proxy 255 %s :I have 0 clients, 0 services and 0 servers\n", client->nick);
+ proxy_outdata(client, ":proxy 422 %s :MOTD File is missing\n", client->nick);
+
+ /* user mode / away status */
+ proxy_outserver(client, "MODE %s :+%s", client->server->nick,
+ client->server->usermode);
+ if (client->server->usermode_away)
+ proxy_outdata(client, ":proxy 306 %s :You have been marked as being away\n", client->nick);
+
+ /* Send channel joins */
+ g_slist_foreach(client->server->channels, (GFunc) dump_join, client);
}
diff --git a/src/irc/proxy/listen.c b/src/irc/proxy/listen.c
index c5453442..ac8c0f67 100644
--- a/src/irc/proxy/listen.c
+++ b/src/irc/proxy/listen.c
@@ -19,154 +19,148 @@
*/
#include "module.h"
-#include "proxy.h"
+#include "signals.h"
#include "net-sendbuffer.h"
-#include "fe-common/core/printtext.h"
+#include "servers-redirect.h"
#include "levels.h"
+#include "settings.h"
+
+#include "irc.h"
+#include "irc-channels.h"
+
+#include "fe-common/core/printtext.h"
+
+GSList *proxy_listens;
+GSList *proxy_clients;
-static PLUGIN_DATA *proxy_data;
static GString *next_line;
-void remove_client(PLUGIN_DATA *data, CLIENT_REC *rec)
+static void remove_client(CLIENT_REC *rec)
{
- data->clients = g_slist_remove(data->clients, rec);
+ g_return_if_fail(rec != NULL);
+
+ proxy_clients = g_slist_remove(proxy_clients, rec);
- net_disconnect(rec->handle);
- g_source_remove(rec->tag);
- line_split_free(rec->buffer);
- g_free(rec);
+ net_disconnect(rec->handle);
+ g_source_remove(rec->tag);
+ line_split_free(rec->buffer);
+ g_free_not_null(rec->nick);
+ g_free(rec);
}
-static void proxy_redirect_event(CLIENT_REC *client, gchar *args, gint last, ...)
+static void proxy_redirect_event(CLIENT_REC *client,
+ const char *args, int last, ...)
{
- va_list vargs;
- gchar *event;
- gint argpos, group;
- GString *str;
-
- g_return_if_fail(client != NULL);
-
- va_start(vargs, last);
-
- str = g_string_new(NULL);
- group = 0;
- while ((event = va_arg(vargs, gchar *)) != NULL)
- {
- argpos = va_arg(vargs, gint);
- g_string_sprintf(str, "proxy %d", client->handle);
- group = server_redirect_single_event(client->server, args, last > 0, group, event, str->str, argpos);
- last--;
- }
- g_string_free(str, TRUE);
-
- va_end(vargs);
+ va_list vargs;
+ GString *str;
+ char *event;
+ int argpos, group;
+
+ g_return_if_fail(client != NULL);
+
+ va_start(vargs, last);
+
+ str = g_string_new(NULL);
+ group = 0;
+ while ((event = va_arg(vargs, char *)) != NULL) {
+ argpos = va_arg(vargs, int);
+ g_string_sprintf(str, "proxy %d", client->handle);
+ group = server_redirect_single_event(SERVER(client->server), args, last > 0,
+ group, event, str->str, argpos);
+ last--;
+ }
+ g_string_free(str, TRUE);
+
+ va_end(vargs);
}
-static void grab_who(CLIENT_REC *client, gchar *channel)
+static void grab_who(CLIENT_REC *client, const char *channel)
{
- gchar *chlist;
- gchar **list, **tmp;
-
- /* /WHO a,b,c may respond with either one "a,b,c End of WHO" message or
- three different "a End of WHO", "b End of WHO", .. messages */
- chlist = g_strdup(channel);
- list = g_strsplit(channel, ",", -1);
-
- for (tmp = list; *tmp != NULL; tmp++)
- {
- if (strcmp(*tmp, "0") == 0)
- {
- /* /who 0 displays everyone */
- **tmp = '*';
- }
+ char *chlist, *chanevent;
+ char **list, **tmp;
+
+ /* /WHO a,b,c may respond with either one "a,b,c End of WHO" message
+ or three different "a End of WHO", "b End of WHO", .. messages */
+ chlist = g_strdup(channel);
+ list = g_strsplit(channel, ",", -1);
+
+ for (tmp = list; *tmp != NULL; tmp++) {
+ if (strcmp(*tmp, "0") == 0) {
+ /* /who 0 displays everyone */
+ **tmp = '*';
+ }
- channel = g_strdup_printf("%s %s", chlist, *tmp);
- proxy_redirect_event(client, channel, 2,
- "event 401", 1, "event 315", 1,
- "event 352", -1, NULL);
- g_free(channel);
- }
- g_strfreev(list);
- g_free(chlist);
+ chanevent = g_strdup_printf("%s %s", chlist, *tmp);
+ proxy_redirect_event(client, chanevent, 2,
+ "event 401", 1, "event 315", 1,
+ "event 352", -1, NULL);
+ g_free(chanevent);
+ }
+ g_strfreev(list);
+ g_free(chlist);
}
-static void sig_listen_client(CLIENT_REC *client, gint handle)
+static void handle_client_connect_cmd(CLIENT_REC *client,
+ const char *cmd, const char *args)
{
- char tmpbuf[1024], *str, *cmd, *args, *p;
- int ret, recvlen;
-
- g_return_if_fail(client != NULL);
-
- for (;;)
- {
- recvlen = net_receive(handle, tmpbuf, sizeof(tmpbuf));
- ret = line_split(tmpbuf, recvlen, &str, &client->buffer);
- if (ret == -1)
- {
- /* connection lost */
- remove_client(proxy_data, client);
- break;
- }
- if (ret == 0) break;
-
- if (client->server == NULL)
- continue;
-
- cmd = g_strdup(str);
- args = strchr(cmd, ' ');
- if (args != NULL) *args++ = '\0'; else args = "";
- if (*args == ':') args++;
- g_strup(cmd);
-
- if (!client->connected)
- {
- if (proxy_data->password != NULL && strcmp(cmd, "PASS") == 0)
- {
- if (strcmp(proxy_data->password, args) != 0)
- {
- /* wrong password! */
- remove_client(proxy_data, client);
- break;
+ const char *password;
+
+ password = settings_get_str("irssiproxy_password");
+
+ if (password != NULL && strcmp(cmd, "PASS") == 0) {
+ if (strcmp(password, args) == 0)
+ client->pass_sent = TRUE;
+ else {
+ /* wrong password! */
+ remove_client(client);
}
- client->pass_sent = TRUE;
- }
- else if (strcmp(cmd, "NICK") == 0)
+ } else if (strcmp(cmd, "NICK") == 0) {
+ g_free_not_null(client->nick);
client->nick = g_strdup(args);
- else if (strcmp(cmd, "USER") == 0)
- {
- if (client->nick == NULL || (proxy_data->password != NULL && !client->pass_sent))
- {
- /* stupid client didn't send us NICK/PASS or, kill it */
- remove_client(proxy_data, client);
- break;
+ } else if (strcmp(cmd, "USER") == 0) {
+ if (client->nick == NULL ||
+ (*password != '\0' && !client->pass_sent)) {
+ /* stupid client didn't send us NICK/PASS, kill it */
+ remove_client(client);
+ } else {
+ client->connected = TRUE;
+ plugin_proxy_dump_data(client);
}
- client->connected = TRUE;
- plugin_proxy_dump_data(client);
- }
}
- else if (strcmp(cmd, "QUIT") == 0)
- {
- remove_client(proxy_data, client);
- break;
- }
- else if (strcmp(cmd, "PING") == 0)
- {
- net_transmit(handle, "PONG proxy :nick\n", 17);
+}
+
+static void handle_client_cmd(CLIENT_REC *client, char *cmd, char *args)
+{
+ int server_handle;
+
+ if (!client->connected) {
+ handle_client_connect_cmd(client, cmd, args);
+ return;
+ }
+
+ if (strcmp(cmd, "QUIT") == 0) {
+ remove_client(client);
+ return;
+ }
+ if (strcmp(cmd, "PING") == 0) {
+ proxy_outdata(client, "PONG proxy :%s\n", args);
+ return;
}
- else
- {
- net_transmit(net_sendbuffer_handle(client->server->handle), str, strlen(str));
- net_transmit(net_sendbuffer_handle(client->server->handle), "\n", 1);
- if (strcmp(cmd, "WHO") == 0)
- {
+ server_handle = net_sendbuffer_handle(client->server->handle);
+ net_transmit(server_handle, cmd, strlen(cmd));
+ net_transmit(server_handle, " ", 1);
+ net_transmit(server_handle, args, strlen(args));
+ net_transmit(server_handle, "\n", 1);
+
+ if (strcmp(cmd, "WHO") == 0)
grab_who(client, args);
- }
- else if (strcmp(cmd, "WHOIS") == 0)
- {
+ else if (strcmp(cmd, "WHOIS") == 0) {
+ char *p;
+
/* convert dots to spaces */
for (p = args; *p != '\0'; p++)
- if (*p == ',') *p = ' ';
+ if (*p == ',') *p = ' ';
proxy_redirect_event(client, args, 2,
"event 318", -1, "event 402", -1,
@@ -174,20 +168,14 @@ static void sig_listen_client(CLIENT_REC *client, gint handle)
"event 301", 1, "event 312", 1,
"event 313", 1, "event 317", 1,
"event 319", 1, NULL);
- }
- else if (strcmp(cmd, "ISON") == 0)
- {
+ } else if (strcmp(cmd, "ISON") == 0)
proxy_redirect_event(client, NULL, 1, "event 303", -1, NULL);
- }
- else if (strcmp(cmd, "USERHOST") == 0)
- {
+ else if (strcmp(cmd, "USERHOST") == 0)
proxy_redirect_event(client, args, 1, "event 302", -1, "event 401", 1, NULL);
- }
- else if (strcmp(cmd, "MODE") == 0)
- {
+ else if (strcmp(cmd, "MODE") == 0) {
/* convert dots to spaces */
- gchar *slist, *str, mode;
- gint argc;
+ char *slist, *str, mode, *p;
+ int argc;
p = strchr(args, ' ');
if (p != NULL) *p++ = '\0';
@@ -195,205 +183,355 @@ static void sig_listen_client(CLIENT_REC *client, gint handle)
slist = g_strdup(args);
argc = 1;
- for (p = slist; *p != '\0'; p++)
- {
- if (*p == ',')
- {
- *p = ' ';
- argc++;
- }
+ for (p = slist; *p != '\0'; p++) {
+ if (*p == ',') {
+ *p = ' ';
+ argc++;
+ }
}
/* get channel mode / bans / exception / invite list */
str = g_strdup_printf("%s %s", args, slist);
- switch (mode)
- {
- case '\0':
- while (argc-- > 0)
- proxy_redirect_event(client, str, 3, "event 403", 1,
- "event 443", 1, "event 324", 1, NULL);
+ switch (mode) {
+ case '\0':
+ while (argc-- > 0)
+ proxy_redirect_event(client, str, 3, "event 403", 1,
+ "event 443", 1, "event 324", 1, NULL);
break;
- case 'b':
- while (argc-- > 0)
- proxy_redirect_event(client, str, 2, "event 403", 1,
- "event 368", 1, "event 367", 1, NULL);
+ case 'b':
+ while (argc-- > 0)
+ proxy_redirect_event(client, str, 2, "event 403", 1,
+ "event 368", 1, "event 367", 1, NULL);
break;
- case 'e':
+ case 'e':
while (argc-- > 0)
- proxy_redirect_event(client, str, 4, "event 403", 1,
- "event 482", 1, "event 472", -1,
- "event 349", 1, "event 348", 1, NULL);
+ proxy_redirect_event(client, str, 4, "event 403", 1,
+ "event 482", 1, "event 472", -1,
+ "event 349", 1, "event 348", 1, NULL);
break;
- case 'I':
- while (argc-- > 0)
- proxy_redirect_event(client, str, 4, "event 403", 1,
- "event 482", 1, "event 472", -1,
- "event 347", 1, "event 346", 1, NULL);
+ case 'I':
+ while (argc-- > 0)
+ proxy_redirect_event(client, str, 4, "event 403", 1,
+ "event 482", 1, "event 472", -1,
+ "event 347", 1, "event 346", 1, NULL);
break;
}
g_free(str);
g_free(slist);
- }
+ } else if (strcmp(cmd, "PRIVMSG") == 0) {
+ /* send the message to other clients as well */
+ char *params, *target, *msg;
+
+ params = event_get_params(args, 2 | PARAM_FLAG_GETREST,
+ &target, &msg);
+ proxy_outserver_all_except(client, "PRIVMSG %s", args);
+ signal_emit("message public", 5, client->server, msg,
+ client->nick, "proxy", target);
+ g_free(params);
}
- g_free(cmd);
- }
}
-static void sig_listen(PLUGIN_DATA *data, gint handle)
+static void sig_listen_client(CLIENT_REC *client)
{
- CLIENT_REC *rec;
- IPADDR ip;
- gint port;
+ char tmpbuf[1024], *str, *cmd, *args;
+ int ret, recvlen;
- g_return_if_fail(data != NULL);
- if (servers == NULL) return;
+ g_return_if_fail(client != NULL);
- /* accept connection */
- handle = net_accept(handle, &ip, &port);
- if (handle == -1)
- return;
+ while (g_slist_find(proxy_clients, client) != NULL) {
+ recvlen = net_receive(client->handle, tmpbuf, sizeof(tmpbuf));
+ ret = line_split(tmpbuf, recvlen, &str, &client->buffer);
+ if (ret == -1) {
+ /* connection lost */
+ remove_client(client);
+ break;
+ }
+
+ if (ret == 0) break;
+
+ if (client->server == NULL)
+ continue;
- rec = g_new0(CLIENT_REC, 1);
- rec->handle = handle;
- rec->server = servers == NULL ? NULL : servers->data;
- rec->tag = g_input_add(handle, G_INPUT_READ, (GInputFunction) sig_listen_client, rec);
+ cmd = g_strdup(str);
+ args = strchr(cmd, ' ');
+ if (args != NULL) *args++ = '\0'; else args = "";
+ if (*args == ':') args++;
+ g_strup(cmd);
- data->clients = g_slist_append(data->clients, rec);
+ handle_client_cmd(client, cmd, args);
+
+ g_free(cmd);
+ }
}
-static gboolean sig_incoming(SERVER_REC *server, gchar *line)
+static void sig_listen(LISTEN_REC *listen)
{
- g_return_val_if_fail(line != NULL, FALSE);
+ CLIENT_REC *rec;
+ IPADDR ip;
+ char host[MAX_IP_LEN];
+ int port, handle;
+
+ g_return_if_fail(listen != NULL);
+
+ /* accept connection */
+ handle = net_accept(listen->handle, &ip, &port);
+ if (handle == -1)
+ return;
+ net_ip2host(&ip, host);
+
+ rec = g_new0(CLIENT_REC, 1);
+ rec->listen = listen;
+ rec->handle = handle;
+ rec->server = IRC_SERVER(server_find_chatnet(listen->ircnet));
+ rec->tag = g_input_add(handle, G_INPUT_READ,
+ (GInputFunction) sig_listen_client, rec);
+
+ proxy_clients = g_slist_append(proxy_clients, rec);
+ printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Proxy: Client connected from %s", host);
+}
+
+static void sig_incoming(IRC_SERVER_REC *server, const char *line)
+{
+ g_return_if_fail(line != NULL);
- /* send server event to all clients */
- g_string_sprintf(next_line, "%s\n", line);
- return TRUE;
+ /* send server event to all clients */
+ g_string_sprintf(next_line, "%s\n", line);
}
-static gboolean sig_server_event(gchar *line, SERVER_REC *server, gchar *nick, gchar *address)
+static void sig_server_event(const char *line, IRC_SERVER_REC *server,
+ const char *nick, const char *address)
{
- GSList *tmp, *list;
- gchar *event, *args;
-
- g_return_val_if_fail(line != NULL, FALSE);
-
- /* get command.. */
- event = g_strconcat("event ", line, NULL);
- args = strchr(event+6, ' ');
- if (args != NULL) *args++ = '\0'; else args = "";
- while (*args == ' ') args++;
-
- list = server_redirect_getqueue(server, event, args);
-
- if (list != NULL)
- {
- /* we want to send this to one client (or proxy itself) only */
- REDIRECT_REC *rec;
- gint handle;
-
- rec = list->data;
- if (g_strncasecmp(rec->name, "proxy ", 6) != 0)
- {
- /* proxy only */
- g_free(event);
- return TRUE;
+ GSList *list;
+ char *event, *args;
+
+ g_return_if_fail(line != NULL);
+ if (!IS_IRC_SERVER(server))
+ return;
+
+ /* get command.. */
+ event = g_strconcat("event ", line, NULL);
+ args = strchr(event+6, ' ');
+ if (args != NULL) *args++ = '\0'; else args = "";
+ while (*args == ' ') args++;
+
+ list = server_redirect_getqueue(SERVER(server), event, args);
+
+ if (list != NULL) {
+ /* we want to send this to one client (or proxy itself) only */
+ REDIRECT_REC *rec;
+ int handle;
+
+ rec = list->data;
+ if (g_strncasecmp(rec->name, "proxy ", 6) != 0) {
+ /* proxy only */
+ g_free(event);
+ return;
+ }
+
+ if (sscanf(rec->name+6, "%d", &handle) == 1) {
+ /* send it to specific client only */
+ server_redirect_remove_next(SERVER(server), event, list);
+ net_transmit(handle, next_line->str, next_line->len);
+ g_free(event);
+ signal_stop();
+ return;
+ }
}
- if (sscanf(rec->name+6, "%d", &handle) == 1)
- {
- /* send it to specific client only */
- server_redirect_remove_next(server, event, list);
- net_transmit(handle, next_line->str, next_line->len);
- g_free(event);
- return FALSE;
+ if (g_strcasecmp(event, "event ping") == 0 ||
+ (g_strcasecmp(event, "event privmsg") == 0 &&
+ strstr(args, " :\001") != NULL)) {
+ /* We want to answer ourself to PINGs and CTCPs */
+ g_free(event);
+ return;
}
- }
- if (g_strcasecmp(event, "event ping") == 0)
- {
- /* We want to answer ourself to PINGs.. */
+ /* send the data to clients.. */
+ proxy_outdata_all(server, next_line->str);
+
g_free(event);
- return TRUE;
- }
+}
+
+static void sig_server_connected(IRC_SERVER_REC *server)
+{
+ GSList *tmp;
+
+ if (!IS_IRC_SERVER(server) || server->connrec->chatnet == NULL)
+ return;
+
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
+
+ if (rec->connected && rec->server == NULL &&
+ g_strcasecmp(server->connrec->chatnet, rec->listen->ircnet) == 0) {
+ proxy_outserver(rec, "NOTICE %s :Connected to server", rec->nick);
+ rec->server = server;
+ }
+ }
+}
+
+static void proxy_server_disconnected(CLIENT_REC *client,
+ IRC_SERVER_REC *server)
+{
+ GSList *tmp;
+
+ proxy_outdata(client, ":proxy NOTICE %s :Connection lost to server %s\n",
+ client->nick, server->connrec->address);
+
+ for (tmp = server->channels; tmp != NULL; tmp = tmp->next) {
+ IRC_CHANNEL_REC *rec = tmp->data;
+
+ proxy_outserver(client, "PART %s :Connection lost to server",
+ rec->name);
+ }
+}
+
+static void sig_server_disconnected(IRC_SERVER_REC *server)
+{
+ GSList *tmp;
- /* send the data to clients.. */
- for (tmp = proxy_data->clients; tmp != NULL; tmp = tmp->next)
- {
- CLIENT_REC *rec = tmp->data;
+ if (!IS_IRC_SERVER(server))
+ return;
- if (rec->server == server)
- net_transmit(rec->handle, next_line->str, next_line->len);
- }
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
- g_free(event);
- return TRUE;
+ if (rec->connected && rec->server == server) {
+ proxy_server_disconnected(rec, server);
+ rec->server = NULL;
+ }
+ }
}
-static gboolean sig_server_connected(SERVER_REC *server)
+static void event_nick(const char *data, IRC_SERVER_REC *server)
{
- GSList *tmp;
+ GSList *tmp;
- g_return_val_if_fail(server != NULL, FALSE);
+ if (*data == ':') data++;
+ for (tmp = proxy_clients; tmp != NULL; tmp = tmp->next) {
+ CLIENT_REC *rec = tmp->data;
- for (tmp = proxy_data->clients; tmp != NULL; tmp = tmp->next)
- {
- CLIENT_REC *rec = tmp->data;
+ if (rec->connected && rec->server == server) {
+ g_free(rec->nick);
+ rec->nick = g_strdup(data);
+ }
+ }
+}
- if (rec->server == NULL)
- rec->server = server;
- }
- return TRUE;
+static LISTEN_REC *find_listen(const char *ircnet, int port)
+{
+ GSList *tmp;
+
+ for (tmp = proxy_listens; tmp != NULL; tmp = tmp->next) {
+ LISTEN_REC *rec = tmp->data;
+
+ if (rec->port == port &&
+ g_strcasecmp(rec->ircnet, ircnet) == 0)
+ return rec;
+ }
+
+ return NULL;
}
-static gboolean sig_server_disconnected(SERVER_REC *server)
+static void add_listen(const char *ircnet, int port)
{
- GSList *tmp;
+ LISTEN_REC *rec;
- g_return_val_if_fail(server != NULL, FALSE);
+ if (port <= 0 || *ircnet == '\0') return;
- for (tmp = proxy_data->clients; tmp != NULL; tmp = tmp->next)
- {
- CLIENT_REC *rec = tmp->data;
+ rec = g_new0(LISTEN_REC, 1);
+ rec->ircnet = g_strdup(ircnet);
+ rec->port = port;
- if (rec->server == server)
- rec->server = NULL;
- }
- return TRUE;
+ /* start listening */
+ rec->handle = net_listen(NULL, &rec->port);
+ if (rec->handle == -1) {
+ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR,
+ "Proxy: Listen in port %d failed: %s",
+ rec->port, g_strerror(errno));
+ return;
+ }
+
+ rec->tag = g_input_add(rec->handle, G_INPUT_READ,
+ (GInputFunction) sig_listen, rec);
+
+ proxy_listens = g_slist_append(proxy_listens, rec);
}
-void plugin_proxy_listen_init(PLUGIN_DATA *data)
+static void remove_listen(LISTEN_REC *rec)
{
- proxy_data = data;
- g_return_if_fail(proxy_data != NULL);
-
- next_line = g_string_new(NULL);
-
- /* start listening */
- proxy_data->listen_handle = net_listen(&proxy_data->ip, &proxy_data->port);
- if (proxy_data->listen_handle == -1)
- {
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "Listen failed");
- return;
- }
-
- proxy_data->clients = NULL;
- proxy_data->listen_tag = g_input_add(proxy_data->listen_handle, G_INPUT_READ,
- (GInputFunction) sig_listen, proxy_data);
-
- signal_add("server incoming", (SIGNAL_FUNC) sig_incoming);
- signal_add("server event", (SIGNAL_FUNC) sig_server_event);
- signal_add("server connected", (SIGNAL_FUNC) sig_server_connected);
- signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
+ proxy_listens = g_slist_remove(proxy_listens, rec);
+
+ net_disconnect(rec->handle);
+ g_source_remove(rec->tag);
+ g_free(rec->ircnet);
+ g_free(rec);
}
-void plugin_proxy_listen_deinit(PLUGIN_DATA *data)
+static void read_settings(void)
{
- g_return_if_fail(data != NULL);
+ LISTEN_REC *rec;
+ GSList *remove_listens;
+ char **ports, **tmp, *ircnet, *port;
+ int portnum;
+
+ remove_listens = g_slist_copy(proxy_listens);
+
+ ports = g_strsplit(settings_get_str("irssiproxy_ports"), " ", -1);
+ for (tmp = ports; *tmp != NULL; tmp++) {
+ ircnet = *tmp;
+ port = strchr(ircnet, '=');
+ if (port == NULL)
+ continue;
+
+ *port++ = '\0';
+ portnum = atoi(port);
+ if (portnum <= 0)
+ continue;
+
+ rec = find_listen(ircnet, portnum);
+ if (rec == NULL)
+ add_listen(ircnet, portnum);
+ else
+ remove_listens = g_slist_remove(remove_listens, rec);
+ }
+ g_strfreev(ports);
+
+ while (remove_listens != NULL) {
+ remove_listen(remove_listens->data);
+ g_slist_remove(remove_listens, remove_listens->data);
+ }
+}
- g_string_free(next_line, TRUE);
- while (data->clients != NULL)
- remove_client(data, data->clients->data);
+void plugin_proxy_listen_init(void)
+{
+ next_line = g_string_new(NULL);
+
+ proxy_clients = NULL;
+ proxy_listens = NULL;
+ read_settings();
+
+ signal_add("server incoming", (SIGNAL_FUNC) sig_incoming);
+ signal_add("server event", (SIGNAL_FUNC) sig_server_event);
+ signal_add("server connected", (SIGNAL_FUNC) sig_server_connected);
+ signal_add("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
+ signal_add("event nick", (SIGNAL_FUNC) event_nick);
+ signal_add("setup changed", (SIGNAL_FUNC) read_settings);
+}
- net_disconnect(data->listen_handle);
- g_source_remove(data->listen_tag);
+void plugin_proxy_listen_deinit(void)
+{
+ while (proxy_clients != NULL)
+ remove_client(proxy_clients->data);
+ while (proxy_listens != NULL)
+ remove_listen(proxy_listens->data);
+ g_string_free(next_line, TRUE);
+
+ signal_remove("server incoming", (SIGNAL_FUNC) sig_incoming);
+ signal_remove("server event", (SIGNAL_FUNC) sig_server_event);
+ signal_remove("server connected", (SIGNAL_FUNC) sig_server_connected);
+ signal_remove("server disconnected", (SIGNAL_FUNC) sig_server_disconnected);
+ signal_remove("event nick", (SIGNAL_FUNC) event_nick);
+ signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
}
diff --git a/src/irc/proxy/module.h b/src/irc/proxy/module.h
index 809c2c51..e0ccf856 100644
--- a/src/irc/proxy/module.h
+++ b/src/irc/proxy/module.h
@@ -2,10 +2,46 @@
#define MODULE_NAME "proxy"
+#include "network.h"
+#include "line-split.h"
+#include "irc-servers.h"
+typedef struct {
+ int port;
+ char *ircnet;
+ int tag;
+ int handle;
+} LISTEN_REC;
+typedef struct {
+ LINEBUF_REC *buffer;
+ char *nick;
+ int handle;
+ int tag;
+ LISTEN_REC *listen;
+ IRC_SERVER_REC *server;
+ int pass_sent:1;
+ int connected:1;
+} CLIENT_REC;
+extern GSList *proxy_listens;
+extern GSList *proxy_clients;
+void plugin_proxy_setup_init(void);
+void plugin_proxy_setup_deinit(void);
+
+void plugin_proxy_listen_init(void);
+void plugin_proxy_listen_deinit(void);
+
+void proxy_settings_init(void);
+
+void plugin_proxy_dump_data(CLIENT_REC *client);
+
+void proxy_outdata(CLIENT_REC *client, const char *data, ...);
+void proxy_outdata_all(IRC_SERVER_REC *server, const char *data, ...);
+void proxy_outserver(CLIENT_REC *client, const char *data, ...);
+/*void proxy_outserver_all(const char *data, ...);*/
+void proxy_outserver_all_except(CLIENT_REC *client, const char *data, ...);
diff --git a/src/irc/proxy/proxy.c b/src/irc/proxy/proxy.c
index 879d3205..ab7ef4cc 100644
--- a/src/irc/proxy/proxy.c
+++ b/src/irc/proxy/proxy.c
@@ -18,119 +18,34 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "proxy.h"
+#include "module.h"
+#include "settings.h"
#include "levels.h"
#include "fe-common/core/printtext.h"
-#include "servers.h"
-#include "net-sendbuffer.h"
-
-#include "lib-config/iconfig.h"
-#include "settings.h"
-
-PLUGIN_DATA *proxy_data;
-MODULE_REC *plug;
-
-
-gchar *plugin_description(void)
+void proxy_deinit(void)
{
- return "IRC proxy plugin";
+ plugin_proxy_listen_deinit();
}
-/*gint plugin_version(void)
+void proxy_init(void)
{
- return PLUGIN_LAYER_VERSION;
-}
-*/
-
-void proxy_settings_init(void)
-{
- settings_add_str("proxy", "proxy_listen_addr", "localhost");
- settings_add_int("proxy", "proxy_listen_port", 2777);
- settings_add_str("proxy", "proxy_listen_password", "");
-}
-
-
-
-/* If we call plugin_deinit() in this code, it doesn't necessarily point to
- _THIS_ module's plugin_deinit() but instead some other module's.. So,
- we create static deinit() function which should be used.. */
-static void deinit(/*MODULE_REC *plugin*/)
-{
- plugin_proxy_listen_deinit(proxy_data);
-}
-
-
-void proxy_deinit(/*MODULE_REC *plugin*/)
-{
- deinit(/*plugin*/);
-}
-
-gboolean proxy_init(void)
-{
-
- gchar ipaddr[MAX_IP_LEN];
-
- const char *password;
- const char *addr;
- int port;
-
- proxy_settings_init();
-
- proxy_data = g_new0(PLUGIN_DATA, 1);
- password = settings_get_str("proxy_listen_password");
- addr = settings_get_str("proxy_listen_addr");
- port = settings_get_int("proxy_listen_port");
-
- plug = module_find("proxy");
- proxy_data->plugin = plug;
-
- if (*password != '\0')
- {
- /* args = password */
- proxy_data->password = g_strdup(password);
- }
- if (*addr != '\0')
- {
- /* specify ip address to listen */
- net_host2ip(addr, &proxy_data->ip);
- }
- if (port != 0)
- {
- /* specify port to use */
- proxy_data->port = port;
- }
-
- if (proxy_data->password == NULL)
- {
- /* no password - bad idea! */
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Warning!! Password not specified, everyone can use this proxy! Use /set proxy_listen_password <password> to set it");
- }
-
- if (servers == NULL)
- {
- /* FIXME: not good */
- printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "You need to specify IP address to listen with /set proxy_listen_addr <address>");
- deinit();
- return FALSE;
- }
- else
- {
- SERVER_REC *server;
-
- server = servers->data;
- if (net_getsockname(net_sendbuffer_handle(server->handle), &proxy_data->ip, NULL))
- {
- deinit();
- return FALSE;
+ settings_add_str("irssiproxy", "irssiproxy_ports", "");
+ settings_add_str("irssiproxy", "irssiproxy_password", "");
+
+ if (*settings_get_str("irssiproxy_password") == '\0') {
+ /* no password - bad idea! */
+ printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ "Warning!! Password not specified, everyone can "
+ "use this proxy! Use /set irssiproxy_password "
+ "<password> to set it");
+ }
+ if (*settings_get_str("irssiproxy_ports") == '\0') {
+ printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE,
+ "No proxy ports specified. Use /SET "
+ "irssiproxy_ports <ircnet>=<port> <ircnet2>=<port2> "
+ "... to set them.");
}
- }
-
- net_ip2host(&proxy_data->ip, ipaddr);
- printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Proxy plugin loaded - listening in interface %s port %d", ipaddr, proxy_data->port);
-
- plugin_proxy_listen_init(proxy_data);
- proxy_data->loaded = TRUE;
- return TRUE;
+ plugin_proxy_listen_init();
}
diff --git a/src/irc/proxy/proxy.h b/src/irc/proxy/proxy.h
deleted file mode 100644
index dadc044d..00000000
--- a/src/irc/proxy/proxy.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef __PROXY_H
-#define __PROXY_H
-
-
-#include "module.h"
-#include "../../core/modules.h"
-
-#include "network.h"
-#include <core/line-split.h>
-#include <core/servers-redirect.h>
-#include "commands.h"
-
-typedef struct
-{
- MODULE_REC *plugin;
- gboolean loaded;
-
- IPADDR ip;
- gint port;
- gchar *password;
-
- gint listen_tag;
- gint listen_handle;
-
- GSList *clients;
-}
-PLUGIN_DATA;
-
-typedef struct
-{
- LINEBUF_REC *buffer;
-
- gchar *nick;
- gint handle;
- gint tag;
-
- SERVER_REC *server;
- gboolean pass_sent;
- gboolean connected;
-}
-CLIENT_REC;
-
-void plugin_proxy_setup_init(MODULE_REC *plugin);
-void plugin_proxy_setup_deinit(MODULE_REC *plugin);
-
-void plugin_proxy_listen_init();
-void plugin_proxy_listen_deinit();
-
-void proxy_settings_init(void);
-
-void plugin_proxy_dump_data(CLIENT_REC *client);
-
-/* #define MODULE_NAME "proxy" */
-
-#endif