forked from PsychoticNinja/irssi
Compare commits
15 Commits
master
...
orphaned/n
Author | SHA1 | Date | |
---|---|---|---|
|
510fa50c07 | ||
|
c668e1add0 | ||
|
c2505203d0 | ||
|
67d343fd3a | ||
|
17ecad8285 | ||
|
714b0241cb | ||
|
a35e5b4f9d | ||
|
f153922759 | ||
|
d5727e1648 | ||
|
9fcd69b9ef | ||
|
2e89752708 | ||
|
bb276c0b80 | ||
|
47419298ef | ||
|
3300e07f29 | ||
|
0236ee5eaa |
5
TODO
5
TODO
@ -1,3 +1,8 @@
|
||||
- New proxy code crashes if an invalid proxy_type setting is used
|
||||
- Remove old socks code
|
||||
- Lots of warnings at least when using socks5
|
||||
- Clean up coding style
|
||||
|
||||
19:36 [IRCNet] [muzzy] more bugs in irssi, apparently the new version: foo splits out,
|
||||
bar joins, bar changes his nick to foo, foo splits again ->
|
||||
Glib warning "is already in split list (how?)" .. :)
|
||||
|
@ -31,6 +31,15 @@ libcore_a_SOURCES = \
|
||||
net-sendbuffer.c \
|
||||
network.c \
|
||||
network-openssl.c \
|
||||
network-proxy.c \
|
||||
network-proxy.h \
|
||||
network-proxy-simple.c \
|
||||
network-proxy-simple.h \
|
||||
network-proxy-http.c \
|
||||
network-proxy-http.h \
|
||||
network-proxy-socks5.c \
|
||||
network-proxy-socks5.h \
|
||||
network-proxy-priv.h \
|
||||
nicklist.c \
|
||||
nickmatch-cache.c \
|
||||
pidwait.c \
|
||||
|
@ -551,12 +551,12 @@ static GIOChannel *irssi_ssl_get_iochannel(GIOChannel *handle, int port, SERVER_
|
||||
|
||||
return gchan;
|
||||
}
|
||||
|
||||
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server)
|
||||
GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char *host, int port,
|
||||
IPADDR *ip, IPADDR *my_ip, SERVER_REC *server)
|
||||
{
|
||||
GIOChannel *handle, *ssl_handle;
|
||||
|
||||
handle = net_connect_ip(ip, port, my_ip);
|
||||
handle = net_connect_proxy(proxy, host, port, ip, my_ip);
|
||||
if (handle == NULL)
|
||||
return NULL;
|
||||
ssl_handle = irssi_ssl_get_iochannel(handle, port, server);
|
||||
|
201
src/core/network-proxy-http.c
Normal file
201
src/core/network-proxy-http.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
network-proxy-http.c : irssi
|
||||
|
||||
Copyright (C) 2008 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
|
||||
|
||||
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; version 2 and/or 3 of the License.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "network-proxy-http.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "network.h"
|
||||
#include "network-proxy-priv.h"
|
||||
|
||||
static void network_proxy_http_destroy(struct network_proxy *proxy)
|
||||
{
|
||||
struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata;
|
||||
|
||||
g_free(self->password);
|
||||
|
||||
g_free(self);
|
||||
|
||||
_network_proxy_destroy(proxy);
|
||||
|
||||
g_free(proxy);
|
||||
}
|
||||
|
||||
static struct network_proxy *network_proxy_http_clone(const struct network_proxy *proxy)
|
||||
{
|
||||
struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata;
|
||||
struct network_proxy_http *priv;
|
||||
struct network_proxy *res;
|
||||
|
||||
res = g_malloc0(sizeof(struct network_proxy));
|
||||
|
||||
_network_proxy_clone(res, proxy);
|
||||
|
||||
priv = g_malloc0(sizeof(struct network_proxy_http));
|
||||
res->privdata = (void *)priv;
|
||||
|
||||
priv->password = g_strdup(self->password);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool send_connect(struct network_proxy_http *proxy, GIOChannel *ch,
|
||||
const char *address, uint16_t port)
|
||||
{
|
||||
char port_str[6];
|
||||
|
||||
(void)proxy;
|
||||
sprintf(port_str, "%u", port);
|
||||
|
||||
if (!_network_proxy_send_all(ch, "CONNECT ", -1) ||
|
||||
!_network_proxy_send_all(ch, address, -1) ||
|
||||
!_network_proxy_send_all(ch, ":", -1) ||
|
||||
!_network_proxy_send_all(ch, port_str, -1) ||
|
||||
!_network_proxy_send_all(ch, " HTTP/1.0\r\n\r\n", -1) ||
|
||||
!_network_proxy_flush(ch))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int read_response(struct network_proxy_http *proxy, GIOChannel *ch)
|
||||
{
|
||||
GIOStatus status;
|
||||
GString line = { .str = NULL };
|
||||
gsize term_pos;
|
||||
GError *err = NULL;
|
||||
int state = 0;
|
||||
int rc = 0;
|
||||
gchar *resp = NULL;
|
||||
|
||||
(void)proxy;
|
||||
for (;;) {
|
||||
/* TODO: a malicious proxy can DOS us by sending much data
|
||||
* without a line break */
|
||||
while ((status=g_io_channel_read_line_string(ch, &line, &term_pos,
|
||||
&err))==G_IO_STATUS_AGAIN)
|
||||
{
|
||||
/* noop */
|
||||
}
|
||||
|
||||
if (status!=G_IO_STATUS_NORMAL) {
|
||||
g_warning("failed to read HTTP response: %s", err->message);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (state==0) {
|
||||
if (g_str_has_prefix(line.str, "HTTP/1.0 ")) {
|
||||
resp = g_strndup(line.str+9, line.len-9-2);
|
||||
rc = g_ascii_strtoull(resp, NULL, 10);
|
||||
} else {
|
||||
g_warning("unexpected HTTP response: '%s'", line.str);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* state=1 ... read additional response headers
|
||||
* (ignored for now) */
|
||||
state=1;
|
||||
}
|
||||
|
||||
if (line.len==2) /* only the \r\n terminators */
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc!=200)
|
||||
g_warning("unexpected HTTP response code: %s", resp);
|
||||
|
||||
g_free(resp);
|
||||
g_free(line.str);
|
||||
return rc;
|
||||
|
||||
err:
|
||||
g_free(resp);
|
||||
g_free(line.str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static GIOChannel *network_proxy_http_connect(const struct network_proxy *proxy, const IPADDR *hint_ip,
|
||||
const char *address, int port)
|
||||
{
|
||||
struct network_proxy_http *self = (struct network_proxy_http *)proxy->privdata;
|
||||
GIOChannel *ch;
|
||||
GIOFlags old_flags;
|
||||
GError *err = NULL;
|
||||
const gchar *line_term;
|
||||
gint line_term_sz;
|
||||
|
||||
if (hint_ip)
|
||||
ch = net_connect_ip(hint_ip, proxy->port, NULL);
|
||||
else
|
||||
ch = net_connect(proxy->host, proxy->port, NULL);
|
||||
|
||||
if (!ch)
|
||||
return NULL;
|
||||
|
||||
/* set \r\n line delims */
|
||||
line_term = g_io_channel_get_line_term(ch, &line_term_sz);
|
||||
g_io_channel_set_line_term(ch, "\r\n", 2);
|
||||
|
||||
/* set to non-blocking */
|
||||
old_flags = g_io_channel_get_flags(ch);
|
||||
if (g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL)
|
||||
goto err;
|
||||
|
||||
if (!send_connect(self, ch, address, port) ||
|
||||
read_response(self, ch)!=200)
|
||||
goto err;
|
||||
|
||||
if (g_io_channel_set_flags(ch, old_flags, &err)!=G_IO_STATUS_NORMAL)
|
||||
goto err;
|
||||
|
||||
g_io_channel_set_line_term(ch, line_term, line_term_sz);
|
||||
return ch;
|
||||
err:
|
||||
if (err) {
|
||||
g_warning("something went wrong while preparing HTTP proxy request: %s",
|
||||
err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
|
||||
net_disconnect(ch);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct network_proxy *network_proxy_http_create(void)
|
||||
{
|
||||
struct network_proxy *res;
|
||||
struct network_proxy_http *priv;
|
||||
|
||||
res = g_malloc0(sizeof(struct network_proxy));
|
||||
|
||||
_network_proxy_create(res);
|
||||
|
||||
priv = g_malloc0(sizeof(struct network_proxy_http));
|
||||
res->privdata = (void *)priv;
|
||||
|
||||
priv->password = g_strdup(settings_get_str("proxy_password"));
|
||||
|
||||
res->destroy = network_proxy_http_destroy;
|
||||
res->connect = network_proxy_http_connect;
|
||||
res->clone = network_proxy_http_clone;
|
||||
|
||||
return res;
|
||||
}
|
12
src/core/network-proxy-http.h
Normal file
12
src/core/network-proxy-http.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef H_IRSSI_SRC_CORE_PROXY_HTTP_H
|
||||
#define H_IRSSI_SRC_CORE_PROXY_HTTP_H
|
||||
|
||||
#include "network-proxy.h"
|
||||
|
||||
struct network_proxy_http {
|
||||
char *password;
|
||||
};
|
||||
|
||||
struct network_proxy *network_proxy_http_create(void);
|
||||
|
||||
#endif
|
100
src/core/network-proxy-priv.h
Normal file
100
src/core/network-proxy-priv.h
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef H_IRSSI_SRC_CORE_PROXY_PRIV_H
|
||||
#define H_IRSSI_SRC_CORE_PROXY_PRIV_H
|
||||
|
||||
#include "settings.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
inline static void _network_proxy_create(struct network_proxy *dst)
|
||||
{
|
||||
// TODO: Initialize all fields, to bring the struct to a known state
|
||||
dst->privdata = NULL;
|
||||
dst->port = settings_get_int("proxy_port");
|
||||
dst->host = g_strdup(settings_get_str("proxy_address"));
|
||||
}
|
||||
|
||||
inline static void _network_proxy_clone(struct network_proxy *dst, const struct network_proxy *src)
|
||||
{
|
||||
dst->host = g_strdup(src->host);
|
||||
dst->port = src->port;
|
||||
|
||||
dst->destroy = src->destroy;
|
||||
dst->connect = src->connect;
|
||||
dst->clone = src->clone;
|
||||
}
|
||||
|
||||
inline static void _network_proxy_destroy(struct network_proxy *proxy)
|
||||
{
|
||||
g_free(proxy->host);
|
||||
}
|
||||
|
||||
inline static bool _network_proxy_send_all(GIOChannel *ch, const void *buf, ssize_t len)
|
||||
{
|
||||
GError *err = NULL;
|
||||
gsize written;
|
||||
GIOStatus status;
|
||||
|
||||
while ((status=g_io_channel_write_chars(ch, buf, len, &written,
|
||||
&err))==G_IO_STATUS_AGAIN)
|
||||
continue;
|
||||
|
||||
if (status==G_IO_STATUS_NORMAL)
|
||||
return true;
|
||||
|
||||
if (err) {
|
||||
g_warning("failed to send proxy request: %s", err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static bool _network_proxy_recv_all(GIOChannel *ch, void *buf_v, size_t len)
|
||||
{
|
||||
GError *err = NULL;
|
||||
gchar *buf = buf_v;
|
||||
|
||||
while (len>0) {
|
||||
GIOStatus status;
|
||||
gsize l;
|
||||
|
||||
status = g_io_channel_read_chars(ch, buf, len, &l, &err);
|
||||
if (status==G_IO_STATUS_AGAIN)
|
||||
continue;
|
||||
if (status!=G_IO_STATUS_NORMAL)
|
||||
break;
|
||||
|
||||
buf += l;
|
||||
len -= l;
|
||||
}
|
||||
|
||||
if (len==0)
|
||||
return true;
|
||||
|
||||
if (err) {
|
||||
g_warning("failed to send proxy request: %s", err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline static bool _network_proxy_flush(GIOChannel *ch)
|
||||
{
|
||||
GError *err = NULL;
|
||||
GIOStatus status;
|
||||
|
||||
while ((status=g_io_channel_flush(ch, &err))==G_IO_STATUS_AGAIN)
|
||||
continue;
|
||||
|
||||
if (status==G_IO_STATUS_NORMAL)
|
||||
return true;
|
||||
|
||||
if (err) {
|
||||
g_warning("failed to flush proxy channel: %s", err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
128
src/core/network-proxy-simple.c
Normal file
128
src/core/network-proxy-simple.c
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
network-proxy-simple.c : irssi
|
||||
|
||||
Copyright (C) 2008 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
|
||||
|
||||
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; version 2 and/or 3 of the License.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "network-proxy-simple.h"
|
||||
|
||||
#include "network-proxy-priv.h"
|
||||
#include "network.h"
|
||||
|
||||
static void network_proxy_simple_destroy(struct network_proxy *proxy)
|
||||
{
|
||||
struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata;
|
||||
|
||||
g_free(self->password);
|
||||
g_free(self->string_after);
|
||||
g_free(self->string);
|
||||
|
||||
g_free(self);
|
||||
|
||||
_network_proxy_destroy(proxy);
|
||||
|
||||
// We are responsible for the whole proxy struct
|
||||
g_free(proxy);
|
||||
}
|
||||
|
||||
static struct network_proxy *network_proxy_simple_clone(const struct network_proxy *proxy)
|
||||
{
|
||||
struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata;
|
||||
struct network_proxy *res;
|
||||
struct network_proxy_simple *newself;
|
||||
|
||||
// First make and set the parent struct
|
||||
res = g_malloc0(sizeof(struct network_proxy));
|
||||
_network_proxy_clone(res, proxy);
|
||||
|
||||
// Then allocate and set the private data
|
||||
newself = g_malloc0(sizeof(struct network_proxy_simple));
|
||||
res->privdata = (void *)newself;
|
||||
|
||||
newself->string = g_strdup(self->string);
|
||||
newself->string_after = g_strdup(self->string_after);
|
||||
newself->password = g_strdup(self->password);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GIOChannel *network_proxy_simple_connect(const struct network_proxy *proxy,
|
||||
const IPADDR *hint_ip, char const *address, int port)
|
||||
{
|
||||
if (hint_ip)
|
||||
return net_connect_ip(hint_ip, proxy->port, NULL);
|
||||
else
|
||||
return net_connect(proxy->host, proxy->port, NULL);
|
||||
}
|
||||
|
||||
static void network_proxy_simple_send_string(const struct network_proxy *proxy,
|
||||
const struct network_proxy_send_string_info *info)
|
||||
{
|
||||
struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata;
|
||||
char *cmd;
|
||||
|
||||
if (self->password && self->password[0]) {
|
||||
cmd = g_strdup_printf("PASS %s", self->password);
|
||||
info->func(info->obj, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
|
||||
if (self->string && self->string[0]) {
|
||||
cmd = g_strdup_printf(self->string, info->host, info->port);
|
||||
info->func(info->obj, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void network_proxy_simple_send_string_after(const struct network_proxy *proxy,
|
||||
const struct network_proxy_send_string_info *info)
|
||||
{
|
||||
struct network_proxy_simple *self = (struct network_proxy_simple *)proxy->privdata;
|
||||
char *cmd;
|
||||
|
||||
if (self->string_after && self->string_after[0]) {
|
||||
cmd = g_strdup_printf(self->string_after, info->host, info->port);
|
||||
info->func(info->obj, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
struct network_proxy *network_proxy_simple_create(void)
|
||||
{
|
||||
struct network_proxy *proxy;
|
||||
struct network_proxy_simple *self;
|
||||
|
||||
proxy = g_malloc0(sizeof(struct network_proxy));
|
||||
|
||||
// assume it could reset every variable to a known state
|
||||
_network_proxy_create(proxy);
|
||||
|
||||
self = g_malloc0(sizeof(struct network_proxy_simple));
|
||||
proxy->privdata = (void *)self;
|
||||
|
||||
self->string = g_strdup(settings_get_str("proxy_string"));
|
||||
self->string_after = g_strdup(settings_get_str("proxy_string_after"));
|
||||
self->password = g_strdup(settings_get_str("proxy_password"));
|
||||
|
||||
proxy->destroy = network_proxy_simple_destroy;
|
||||
proxy->connect = network_proxy_simple_connect;
|
||||
proxy->clone = network_proxy_simple_clone;
|
||||
|
||||
proxy->send_string = network_proxy_simple_send_string;
|
||||
proxy->send_string_after = network_proxy_simple_send_string_after;
|
||||
|
||||
return proxy;
|
||||
}
|
14
src/core/network-proxy-simple.h
Normal file
14
src/core/network-proxy-simple.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef H_IRSSI_SRC_CORE_PROXY_SIMPLE_H
|
||||
#define H_IRSSI_SRC_CORE_PROXY_SIMPLE_H
|
||||
|
||||
#include "network-proxy.h"
|
||||
|
||||
struct network_proxy_simple {
|
||||
char *string_after;
|
||||
char *string;
|
||||
char *password;
|
||||
};
|
||||
|
||||
struct network_proxy *network_proxy_simple_create(void);
|
||||
|
||||
#endif
|
343
src/core/network-proxy-socks5.c
Normal file
343
src/core/network-proxy-socks5.c
Normal file
@ -0,0 +1,343 @@
|
||||
/*
|
||||
network-proxy-socks5.c : irssi
|
||||
|
||||
Copyright (C) 2008 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
|
||||
|
||||
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; version 2 and/or 3 of the License.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "network-proxy-socks5.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "network.h"
|
||||
#include "network-proxy-priv.h"
|
||||
|
||||
/* RFC 1928 */
|
||||
struct client_greeting
|
||||
{
|
||||
uint8_t ver;
|
||||
uint8_t nmethods;
|
||||
uint8_t methods[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct server_greeting
|
||||
{
|
||||
uint8_t ver;
|
||||
uint8_t method;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct server_response_plain
|
||||
{
|
||||
uint8_t ver;
|
||||
uint8_t status;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct client_request
|
||||
{
|
||||
uint8_t ver;
|
||||
uint8_t cmd;
|
||||
uint8_t rsv;
|
||||
uint8_t atyp;
|
||||
uint8_t dst[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct server_response
|
||||
{
|
||||
uint8_t ver;
|
||||
uint8_t rep;
|
||||
uint8_t res;
|
||||
uint8_t atyp;
|
||||
uint8_t bnd[];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
static void network_proxy_socks5_destroy(struct network_proxy *proxy)
|
||||
{
|
||||
struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata;
|
||||
|
||||
g_free(self->password);
|
||||
g_free(self->username);
|
||||
g_free(self);
|
||||
_network_proxy_destroy(proxy);
|
||||
g_free(proxy);
|
||||
}
|
||||
|
||||
static struct network_proxy *network_proxy_socks5_clone(const struct network_proxy *proxy)
|
||||
{
|
||||
struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata;
|
||||
struct network_proxy_socks5 *priv;
|
||||
struct network_proxy *res;
|
||||
|
||||
res = g_malloc0(sizeof(struct network_proxy));
|
||||
_network_proxy_clone(res, proxy);
|
||||
|
||||
priv = g_malloc0(sizeof(struct network_proxy_socks5));
|
||||
res->privdata = (void *)priv;
|
||||
|
||||
priv->username = g_strdup(self->username);
|
||||
priv->password = g_strdup(self->password);
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool socks5_connect_unauthorized(GIOChannel *ch)
|
||||
{
|
||||
/* nothing to do here */
|
||||
(void)ch;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TODO: test this method! */
|
||||
static bool socks5_connect_plain(const struct network_proxy_socks5 *proxy, GIOChannel *ch)
|
||||
{
|
||||
uint8_t ver = 0x01;
|
||||
uint8_t ulen = strlen(proxy->username);
|
||||
uint8_t plen = proxy->password ? strlen(proxy->password) : 0;
|
||||
struct server_response_plain resp;
|
||||
|
||||
if (ulen==0 ||
|
||||
!_network_proxy_send_all(ch, &ver, sizeof ver) ||
|
||||
!_network_proxy_send_all(ch, &ulen, sizeof ulen) ||
|
||||
!_network_proxy_send_all(ch, proxy->username, ulen) ||
|
||||
!_network_proxy_send_all(ch, &plen, sizeof plen) ||
|
||||
(plen>0 && !_network_proxy_send_all(ch, proxy->password, plen)) ||
|
||||
!_network_proxy_flush(ch) ||
|
||||
!_network_proxy_recv_all(ch, &resp, sizeof resp))
|
||||
return false;
|
||||
|
||||
if (resp.ver!=0x01) {
|
||||
g_warning("unexpected plaintext response version %#04x", resp.ver);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (resp.status!=0x00) {
|
||||
g_warning("socks5 authentication error (%#04x)", resp.status);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool socks5_connect(const struct network_proxy_socks5 *proxy, GIOChannel *ch,
|
||||
const char *address, uint16_t port)
|
||||
{
|
||||
bool rc;
|
||||
|
||||
struct server_greeting s_greeting;
|
||||
struct server_response s_response;
|
||||
|
||||
|
||||
/* Phase 1: exchange greeting */
|
||||
{
|
||||
struct client_greeting c_greeting = {
|
||||
.ver = 0x05,
|
||||
.nmethods = proxy->username && proxy->username[0] ? 2 : 1
|
||||
};
|
||||
/* HACK: order is important because it depends upon
|
||||
* c_greeting.nmethods */
|
||||
char const methods[] = {
|
||||
0x00, /* no authentication */
|
||||
0x02 /* username/password */
|
||||
};
|
||||
if (!_network_proxy_send_all(ch, &c_greeting, sizeof c_greeting) ||
|
||||
!_network_proxy_send_all(ch, methods, c_greeting.nmethods) ||
|
||||
!_network_proxy_flush(ch) ||
|
||||
!_network_proxy_recv_all(ch, &s_greeting, sizeof s_greeting))
|
||||
goto err;
|
||||
|
||||
if (s_greeting.ver!=5) {
|
||||
g_warning("version mismatch during initial socks5 greeting; got version %#04x",
|
||||
s_greeting.ver);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Phase 2: authentication */
|
||||
{
|
||||
switch (s_greeting.method) {
|
||||
case 0x00: rc = socks5_connect_unauthorized(ch); break;
|
||||
case 0x02: rc = socks5_connect_plain(proxy, ch); break;
|
||||
default:
|
||||
g_warning("unsupported authentication method %#04x", s_greeting.method);
|
||||
rc = false;
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Phase 3: connection request */
|
||||
{
|
||||
struct client_request c_request = {
|
||||
.ver = 0x05,
|
||||
.cmd = 0x01, /* CONNECT */
|
||||
.atyp = 0x03, /* domain name */
|
||||
};
|
||||
uint8_t address_len = strlen(address);
|
||||
uint16_t dst_port = htons(port);
|
||||
uint16_t bnd_port;
|
||||
char bnd_address[257];
|
||||
|
||||
if (!_network_proxy_send_all(ch, &c_request, sizeof c_request) ||
|
||||
!_network_proxy_send_all(ch, &address_len, sizeof address_len) ||
|
||||
!_network_proxy_send_all(ch, address, address_len) ||
|
||||
!_network_proxy_send_all(ch, &dst_port, sizeof dst_port) ||
|
||||
!_network_proxy_flush(ch) ||
|
||||
!_network_proxy_recv_all(ch, &s_response, sizeof s_response))
|
||||
goto err;
|
||||
|
||||
if (s_response.ver != 0x05) {
|
||||
g_warning("version mismatch in socks5 response; got version %#04x",
|
||||
s_response.ver);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rc = false;
|
||||
switch (s_response.rep) {
|
||||
case 0x00: rc = true; break; /* succeeded */
|
||||
case 0x01: g_warning("SOCKS5: general SOCKS server failure"); break;
|
||||
case 0x02: g_warning("SOCKS5: connection not allowed by ruleset"); break;
|
||||
case 0x03: g_warning("SOCKS5: Network unreachable"); break;
|
||||
case 0x04: g_warning("SOCKS5: Host unreachable"); break;
|
||||
case 0x05: g_warning("SOCKS5: Connection refused"); break;
|
||||
case 0x06: g_warning("SOCKS5: TTL expired"); break;
|
||||
case 0x07: g_warning("SOCKS5: Command not supported"); break;
|
||||
case 0x08: g_warning("SOCKS5: Address type not supported"); break;
|
||||
default: g_warning("SOCKS5: unknown error %#04x", s_response.rep); break;
|
||||
}
|
||||
|
||||
if (!rc)
|
||||
goto err;
|
||||
|
||||
switch(s_response.atyp) {
|
||||
case 0x01: {
|
||||
struct in_addr ip;
|
||||
if (!_network_proxy_recv_all(ch, &ip, sizeof ip) ||
|
||||
!inet_ntop(AF_INET, &ip, bnd_address, sizeof bnd_address))
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x04: {
|
||||
struct in6_addr ip;
|
||||
if (!_network_proxy_recv_all(ch, &ip, sizeof ip) ||
|
||||
!inet_ntop(AF_INET6, &ip, bnd_address, sizeof bnd_address))
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x03: {
|
||||
uint8_t tmp;
|
||||
if (!_network_proxy_recv_all(ch, &tmp, sizeof tmp) ||
|
||||
tmp==0 ||
|
||||
!_network_proxy_recv_all(ch, &bnd_address, tmp))
|
||||
rc = false;
|
||||
else
|
||||
bnd_address[tmp] = '\0';
|
||||
}
|
||||
|
||||
default:
|
||||
g_warning("SOCKS5: unsupported address family in response: %#04x",
|
||||
s_response.atyp);
|
||||
rc = false;
|
||||
}
|
||||
|
||||
if (!rc ||
|
||||
!_network_proxy_recv_all(ch, &bnd_port, sizeof bnd_port))
|
||||
goto err;
|
||||
|
||||
bnd_port = ntohs(bnd_port);
|
||||
g_debug("SOCKS5: bound to %s:%u", bnd_address, bnd_port);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
err:
|
||||
g_warning("connecting through socks5 proxy failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static GIOChannel *network_proxy_socks5_connect(const struct network_proxy *proxy, const IPADDR *hint_ip,
|
||||
const char *address, int port)
|
||||
{
|
||||
struct network_proxy_socks5 *self = (struct network_proxy_socks5 *)proxy->privdata;
|
||||
GIOChannel *ch;
|
||||
|
||||
GIOFlags old_flags;
|
||||
const gchar *old_enc;
|
||||
gboolean old_buf;
|
||||
GError *err = NULL;
|
||||
|
||||
if (hint_ip)
|
||||
ch = net_connect_ip(hint_ip, proxy->port, NULL);
|
||||
else
|
||||
ch = net_connect(proxy->host, proxy->port, NULL);
|
||||
|
||||
if (!ch)
|
||||
return NULL;
|
||||
|
||||
old_enc = g_io_channel_get_encoding(ch);
|
||||
old_flags = g_io_channel_get_flags(ch);
|
||||
old_buf = g_io_channel_get_buffered(ch);
|
||||
|
||||
if (g_io_channel_set_encoding(ch, NULL, &err)!=G_IO_STATUS_NORMAL ||
|
||||
g_io_channel_set_flags(ch, old_flags & ~G_IO_FLAG_NONBLOCK, &err)!=G_IO_STATUS_NORMAL)
|
||||
goto err;
|
||||
|
||||
g_io_channel_set_buffered(ch, false);
|
||||
|
||||
if (!socks5_connect(self, ch, address, port))
|
||||
goto err;
|
||||
|
||||
g_io_channel_set_buffered(ch, old_buf);
|
||||
|
||||
if (g_io_channel_set_flags(ch, old_flags, &err) !=G_IO_STATUS_NORMAL ||
|
||||
g_io_channel_set_encoding(ch, old_enc, &err)!=G_IO_STATUS_NORMAL)
|
||||
goto err;
|
||||
|
||||
return ch;
|
||||
|
||||
err:
|
||||
if (err) {
|
||||
g_warning("something went wrong while preparing SOCKS5 proxy request: %s",
|
||||
err->message);
|
||||
g_error_free(err);
|
||||
}
|
||||
|
||||
net_disconnect(ch);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct network_proxy *network_proxy_socks5_create(void)
|
||||
{
|
||||
struct network_proxy *res;
|
||||
struct network_proxy_socks5 *priv;
|
||||
|
||||
res = g_malloc0(sizeof(struct network_proxy));
|
||||
|
||||
_network_proxy_create(res);
|
||||
|
||||
priv = g_malloc0(sizeof(struct network_proxy_socks5));
|
||||
res->privdata = (void *)priv;
|
||||
|
||||
priv->username = g_strdup(settings_get_str("proxy_username"));
|
||||
priv->password = g_strdup(settings_get_str("proxy_password"));
|
||||
|
||||
res->destroy = network_proxy_socks5_destroy;
|
||||
res->connect = network_proxy_socks5_connect;
|
||||
res->clone = network_proxy_socks5_clone;
|
||||
|
||||
return res;
|
||||
}
|
13
src/core/network-proxy-socks5.h
Normal file
13
src/core/network-proxy-socks5.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef H_IRSSI_SRC_CORE_PROXY_SOCKS5_H
|
||||
#define H_IRSSI_SRC_CORE_PROXY_SOCKS5_H
|
||||
|
||||
#include "network-proxy.h"
|
||||
|
||||
struct network_proxy_socks5 {
|
||||
char *username;
|
||||
char *password;
|
||||
};
|
||||
|
||||
struct network_proxy *network_proxy_socks5_create(void);
|
||||
|
||||
#endif
|
43
src/core/network-proxy.c
Normal file
43
src/core/network-proxy.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
network-proxy.c : irssi
|
||||
|
||||
Copyright (C) 2008 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
|
||||
|
||||
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; version 2 and/or 3 of the License.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
|
||||
#include "network-proxy.h"
|
||||
#include <string.h>
|
||||
#include "network-proxy-simple.h"
|
||||
#include "network-proxy-http.h"
|
||||
#include "network-proxy-socks5.h"
|
||||
|
||||
struct network_proxy *network_proxy_create(const char *type)
|
||||
{
|
||||
if (type==NULL)
|
||||
return NULL;
|
||||
|
||||
if (strcmp(type, "simple")==0 || type[0]=='\0')
|
||||
return network_proxy_simple_create();
|
||||
|
||||
if (strcmp(type, "http")==0)
|
||||
return network_proxy_http_create();
|
||||
|
||||
if (strcmp(type, "socks5")==0)
|
||||
return network_proxy_socks5_create();
|
||||
|
||||
g_error("unsupported proxy type '%s'", type);
|
||||
return NULL;
|
||||
}
|
65
src/core/network-proxy.h
Normal file
65
src/core/network-proxy.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef H_IRSSI_SRC_CORE_PROXY_H
|
||||
#define H_IRSSI_SRC_CORE_PROXY_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* helper structure for the send_string*() functions of the network_proxy
|
||||
* class */
|
||||
struct network_proxy_send_string_info {
|
||||
const char *host; /* hostname of the IRC server */
|
||||
uint16_t port; /* portnumber of the IRC server */
|
||||
|
||||
/* function which is used to send string; usually irc_send_cmd_now() */
|
||||
void (*func)(void *obj, const char *);
|
||||
|
||||
/* object for func */
|
||||
void *obj;
|
||||
};
|
||||
|
||||
struct network_proxy {
|
||||
/* Contains private data for the chosen proxy type */
|
||||
void *privdata;
|
||||
|
||||
/* destroys the network_proxy structure which must not be used anymore
|
||||
* after; this memberfunction is mandatory */
|
||||
void (*destroy)(struct network_proxy *);
|
||||
|
||||
/* connects through the proxy; this memberfunction is mandatory
|
||||
*
|
||||
* \arg hint_ip the asynchronously resolved ip of the proxy; when
|
||||
* NULL, method will resolve it itself
|
||||
* \arg address the hostname where proxy shall connect to
|
||||
* \arg port port address where proxy shall connect to
|
||||
*/
|
||||
GIOChannel *(*connect)(const struct network_proxy *, const IPADDR *hint_ip,
|
||||
const char *address, int port);
|
||||
|
||||
/* clones the given network_proxy object; this memberfunction is
|
||||
* mandatory */
|
||||
struct network_proxy *(*clone)(const struct network_proxy *);
|
||||
|
||||
|
||||
/* sends a string after connection has been established but before IRC
|
||||
* authentication begins; this memberfunction is optional
|
||||
*/
|
||||
void (*send_string)(const struct network_proxy *,
|
||||
const struct network_proxy_send_string_info *);
|
||||
|
||||
/* sends a string after connection IRC authentication suceeded; this
|
||||
* memberfunction is optional
|
||||
*/
|
||||
void (*send_string_after)(const struct network_proxy *,
|
||||
const struct network_proxy_send_string_info *);
|
||||
|
||||
/* hostname of proxy host */
|
||||
char *host;
|
||||
|
||||
/* portnumber of proxy */
|
||||
int port;
|
||||
};
|
||||
|
||||
/* factory method to create a proxy object based upon value of 'type' */
|
||||
struct network_proxy *network_proxy_create(const char *type);
|
||||
|
||||
#endif
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "module.h"
|
||||
#include "network.h"
|
||||
#include "network-proxy.h"
|
||||
|
||||
#include <sys/un.h>
|
||||
|
||||
@ -169,7 +170,7 @@ GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
|
||||
}
|
||||
|
||||
/* Connect to socket with ip address */
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
GIOChannel *net_connect_ip(const IPADDR *ip, int port, IPADDR *my_ip)
|
||||
{
|
||||
union sockaddr_union so;
|
||||
int handle, ret, opt = 1;
|
||||
@ -226,6 +227,16 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
return g_io_channel_new(handle);
|
||||
}
|
||||
|
||||
/* Connect to socket */
|
||||
GIOChannel *net_connect_proxy(const struct network_proxy *proxy,
|
||||
const char *host, int port, IPADDR *ip, IPADDR *my_ip)
|
||||
{
|
||||
if (proxy)
|
||||
return proxy->connect(proxy, ip, host, port);
|
||||
else
|
||||
return net_connect_ip(ip, port, my_ip);
|
||||
}
|
||||
|
||||
/* Connect to named UNIX socket */
|
||||
GIOChannel *net_connect_unix(const char *path)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@ struct _IPADDR {
|
||||
|
||||
#define IPADDR_IS_V6(ip) ((ip)->family != AF_INET)
|
||||
|
||||
struct network_proxy;
|
||||
extern IPADDR ip4_any;
|
||||
|
||||
GIOChannel *g_io_channel_new(int handle);
|
||||
@ -49,10 +50,13 @@ int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
|
||||
/* Connect to socket */
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip);
|
||||
/* Connect to socket with ip address and SSL*/
|
||||
GIOChannel *net_connect_ip_ssl(IPADDR *ip, int port, IPADDR *my_ip, SERVER_REC *server);
|
||||
GIOChannel *net_connect_proxy_ssl(const struct network_proxy *proxy, const char *host, int port,
|
||||
IPADDR *ip, IPADDR *my_ip, SERVER_REC *server);
|
||||
int irssi_ssl_handshake(GIOChannel *handle);
|
||||
/* Connect to socket with ip address */
|
||||
GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip);
|
||||
GIOChannel *net_connect_ip(const IPADDR *ip, int port, IPADDR *my_ip);
|
||||
GIOChannel *net_connect_proxy(const struct network_proxy *proxy, const char *host, int port,
|
||||
IPADDR *ip, IPADDR *my_ip);
|
||||
/* Connect to named UNIX socket */
|
||||
GIOChannel *net_connect_unix(const char *path);
|
||||
/* Disconnect socket */
|
||||
|
@ -5,10 +5,7 @@ int chat_type; /* chat_protocol_lookup(xx) */
|
||||
|
||||
int refcount;
|
||||
|
||||
/* if we're connecting via proxy, or just NULLs */
|
||||
char *proxy;
|
||||
int proxy_port;
|
||||
char *proxy_string, *proxy_string_after, *proxy_password;
|
||||
struct network_proxy *proxy;
|
||||
|
||||
unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */
|
||||
char *tag; /* try to keep this tag when connected to server */
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "servers-reconnect.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "network-proxy.h"
|
||||
|
||||
GSList *reconnects;
|
||||
static int last_reconnect_tag;
|
||||
@ -157,11 +158,7 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
|
||||
server_connect_ref(dest);
|
||||
dest->type = module_get_uniq_id("SERVER CONNECT", 0);
|
||||
dest->reconnection = src->reconnection;
|
||||
dest->proxy = g_strdup(src->proxy);
|
||||
dest->proxy_port = src->proxy_port;
|
||||
dest->proxy_string = g_strdup(src->proxy_string);
|
||||
dest->proxy_string_after = g_strdup(src->proxy_string_after);
|
||||
dest->proxy_password = g_strdup(src->proxy_password);
|
||||
dest->proxy = src->proxy ? src->proxy->clone(src->proxy) : NULL;
|
||||
|
||||
dest->tag = g_strdup(src->tag);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "chatnets.h"
|
||||
#include "servers.h"
|
||||
#include "servers-setup.h"
|
||||
#include "network-proxy.h"
|
||||
|
||||
GSList *setupservers;
|
||||
|
||||
@ -126,15 +127,6 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn,
|
||||
conn->username = g_strdup(settings_get_str("user_name"));
|
||||
conn->realname = g_strdup(settings_get_str("real_name"));
|
||||
|
||||
/* proxy settings */
|
||||
if (settings_get_bool("use_proxy")) {
|
||||
conn->proxy = g_strdup(settings_get_str("proxy_address"));
|
||||
conn->proxy_port = settings_get_int("proxy_port");
|
||||
conn->proxy_string = g_strdup(settings_get_str("proxy_string"));
|
||||
conn->proxy_string_after = g_strdup(settings_get_str("proxy_string_after"));
|
||||
conn->proxy_password = g_strdup(settings_get_str("proxy_password"));
|
||||
}
|
||||
|
||||
/* source IP */
|
||||
if (source_host_ip4 != NULL) {
|
||||
conn->own_ip4 = g_new(IPADDR, 1);
|
||||
@ -145,6 +137,10 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn,
|
||||
memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR));
|
||||
}
|
||||
|
||||
/* proxy settings */
|
||||
if (settings_get_bool("use_proxy"))
|
||||
conn->proxy = network_proxy_create(settings_get_str("proxy_type"));
|
||||
|
||||
signal_emit("server setup fill connect", 1, conn);
|
||||
}
|
||||
|
||||
@ -545,7 +541,9 @@ void servers_setup_init(void)
|
||||
settings_add_int("proxy", "proxy_port", 6667);
|
||||
settings_add_str("proxy", "proxy_string", "CONNECT %s %d");
|
||||
settings_add_str("proxy", "proxy_string_after", "");
|
||||
settings_add_str("proxy", "proxy_username", "");
|
||||
settings_add_str("proxy", "proxy_password", "");
|
||||
settings_add_str("proxy", "proxy_type", "simple");
|
||||
|
||||
setupservers = NULL;
|
||||
source_host_ip4 = source_host_ip6 = NULL;
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "servers-setup.h"
|
||||
#include "channels.h"
|
||||
#include "queries.h"
|
||||
#include "network-proxy.h"
|
||||
|
||||
GSList *servers, *lookup_servers;
|
||||
|
||||
@ -221,10 +222,15 @@ static void server_real_connect(SERVER_REC *server, IPADDR *ip,
|
||||
own_ip = ip == NULL ? NULL :
|
||||
(IPADDR_IS_V6(ip) ? server->connrec->own_ip6 :
|
||||
server->connrec->own_ip4);
|
||||
port = server->connrec->proxy != NULL ?
|
||||
server->connrec->proxy_port : server->connrec->port;
|
||||
port = server->connrec->port;
|
||||
handle = server->connrec->use_ssl ?
|
||||
net_connect_ip_ssl(ip, port, own_ip, server) : net_connect_ip(ip, port, own_ip);
|
||||
net_connect_proxy_ssl(server->connrec->proxy,
|
||||
server->connrec->address, port,
|
||||
ip, own_ip,
|
||||
server) :
|
||||
net_connect_proxy(server->connrec->proxy,
|
||||
server->connrec->address, port,
|
||||
ip, own_ip);
|
||||
} else {
|
||||
handle = net_connect_unix(unix_socket);
|
||||
}
|
||||
@ -421,7 +427,7 @@ int server_start_connect(SERVER_REC *server)
|
||||
server->connect_pipe[1] = g_io_channel_new(fd[1]);
|
||||
|
||||
connect_address = server->connrec->proxy != NULL ?
|
||||
server->connrec->proxy : server->connrec->address;
|
||||
server->connrec->proxy->host : server->connrec->address;
|
||||
server->connect_pid =
|
||||
net_gethostbyname_nonblock(connect_address,
|
||||
server->connect_pipe[1],
|
||||
@ -616,10 +622,8 @@ void server_connect_unref(SERVER_CONNECT_REC *conn)
|
||||
if (conn->connect_handle != NULL)
|
||||
net_disconnect(conn->connect_handle);
|
||||
|
||||
g_free_not_null(conn->proxy);
|
||||
g_free_not_null(conn->proxy_string);
|
||||
g_free_not_null(conn->proxy_string_after);
|
||||
g_free_not_null(conn->proxy_password);
|
||||
if (conn->proxy)
|
||||
conn->proxy->destroy(conn->proxy);
|
||||
|
||||
g_free_not_null(conn->tag);
|
||||
g_free_not_null(conn->address);
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "servers-reconnect.h"
|
||||
#include "servers-redirect.h"
|
||||
#include "modes.h"
|
||||
#include "network-proxy.h"
|
||||
|
||||
#include "settings.h"
|
||||
#include "recode.h"
|
||||
@ -195,23 +196,19 @@ static void server_init(IRC_SERVER_REC *server)
|
||||
IRC_SERVER_CONNECT_REC *conn;
|
||||
char *address, *ptr, *username, *cmd;
|
||||
GTimeVal now;
|
||||
const struct network_proxy_send_string_info send_info = {
|
||||
.host = server->connrec->address,
|
||||
.port = server->connrec->port,
|
||||
.func = irc_send_cmd_now_wrapper,
|
||||
.obj = server
|
||||
};
|
||||
|
||||
g_return_if_fail(server != NULL);
|
||||
|
||||
conn = server->connrec;
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_password != NULL &&
|
||||
*conn->proxy_password != '\0') {
|
||||
cmd = g_strdup_printf("PASS %s", conn->proxy_password);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_string != NULL) {
|
||||
cmd = g_strdup_printf(conn->proxy_string, conn->address, conn->port);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
if (conn->proxy && conn->proxy->send_string)
|
||||
conn->proxy->send_string(conn->proxy, &send_info);
|
||||
|
||||
if (conn->password != NULL && *conn->password != '\0') {
|
||||
/* send password */
|
||||
@ -245,11 +242,8 @@ static void server_init(IRC_SERVER_REC *server)
|
||||
g_free(cmd);
|
||||
g_free(username);
|
||||
|
||||
if (conn->proxy != NULL && conn->proxy_string_after != NULL) {
|
||||
cmd = g_strdup_printf(conn->proxy_string_after, conn->address, conn->port);
|
||||
irc_send_cmd_now(server, cmd);
|
||||
g_free(cmd);
|
||||
}
|
||||
if (conn->proxy && conn->proxy->send_string_after)
|
||||
conn->proxy->send_string_after(conn->proxy, &send_info);
|
||||
|
||||
server->isupport = g_hash_table_new((GHashFunc) g_istr_hash,
|
||||
(GCompareFunc) g_istr_equal);
|
||||
@ -319,6 +313,11 @@ void irc_server_connect(SERVER_REC *server)
|
||||
}
|
||||
}
|
||||
|
||||
void irc_send_cmd_now_wrapper(void *server, const char *cmd)
|
||||
{
|
||||
return irc_send_cmd_now((IRC_SERVER_REC *)server, cmd);
|
||||
}
|
||||
|
||||
/* Returns TRUE if `command' is sent to `target' */
|
||||
static int command_has_target(const char *cmd, const char *target)
|
||||
{
|
||||
|
@ -125,6 +125,8 @@ void irc_server_send_away(IRC_SERVER_REC *server, const char *reason);
|
||||
void irc_server_send_data(IRC_SERVER_REC *server, const char *data, int len);
|
||||
void irc_server_init_isupport(IRC_SERVER_REC *server);
|
||||
|
||||
void irc_send_cmd_now_wrapper(void *server, const char *cmd);
|
||||
|
||||
void irc_servers_start_cmd_timeout(void);
|
||||
|
||||
void irc_servers_init(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user