Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/majn/tgl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVysheng <mail@vysheng.ru>2015-01-12 16:58:17 +0300
committerVysheng <mail@vysheng.ru>2015-01-12 16:58:17 +0300
commit354f2064fcb1dd9de1e1abdb091daf532d735b4a (patch)
treeacb1fbb4dd8f740eea07e14a8214561d970be333
parent7f370266688aed5329ea576e9795bb27e74b2bfe (diff)
ipv6 support
-rw-r--r--mtproto-client.c46
-rw-r--r--tgl-net.c144
-rw-r--r--tgl.c4
-rw-r--r--tgl.h13
4 files changed, 111 insertions, 96 deletions
diff --git a/mtproto-client.c b/mtproto-client.c
index b876834..312d5c7 100644
--- a/mtproto-client.c
+++ b/mtproto-client.c
@@ -985,11 +985,52 @@ static int rpc_execute_answer (struct tgl_state *TLS, struct connection *c, long
static struct mtproto_methods mtproto_methods;
void tgls_free_session (struct tgl_state *TLS, struct tgl_session *S);
+
+static char *get_ipv6 (struct tgl_state *TLS, int num) {
+ static char res[1<< 10];
+ if (TLS->test_mode) {
+ switch (num) {
+ case 1:
+ strcpy (res, TG_SERVER_TEST_IPV6_1);
+ break;
+ case 2:
+ strcpy (res, TG_SERVER_TEST_IPV6_2);
+ break;
+ case 3:
+ strcpy (res, TG_SERVER_TEST_IPV6_3);
+ break;
+ default:
+ assert (0);
+ }
+ } else {
+ switch (num) {
+ case 1:
+ strcpy (res, TG_SERVER_IPV6_1);
+ break;
+ case 2:
+ strcpy (res, TG_SERVER_IPV6_2);
+ break;
+ case 3:
+ strcpy (res, TG_SERVER_IPV6_3);
+ break;
+ case 4:
+ strcpy (res, TG_SERVER_IPV6_4);
+ break;
+ case 5:
+ strcpy (res, TG_SERVER_IPV6_5);
+ break;
+ default:
+ assert (0);
+ }
+ }
+ return res;
+}
+
static void fail_connection (struct tgl_state *TLS, struct connection *c) {
struct tgl_session *S = TLS->net_methods->get_session (c);
struct tgl_dc *DC = TLS->net_methods->get_dc (c);
TLS->net_methods->free (c);
- S->c = TLS->net_methods->create_connection (TLS, DC->ip, DC->port, S, DC, &mtproto_methods);
+ S->c = TLS->net_methods->create_connection (TLS, TLS->ipv6_enabled ? get_ipv6 (TLS, DC->id) : DC->ip, DC->port, S, DC, &mtproto_methods);
}
static void fail_session (struct tgl_state *TLS, struct tgl_session *S) {
@@ -1322,7 +1363,8 @@ void tglmp_dc_create_session (struct tgl_state *TLS, struct tgl_dc *DC) {
struct tgl_session *S = talloc0 (sizeof (*S));
assert (RAND_pseudo_bytes ((unsigned char *) &S->session_id, 8) >= 0);
S->dc = DC;
- S->c = TLS->net_methods->create_connection (TLS, DC->ip, DC->port, S, DC, &mtproto_methods);
+ //S->c = TLS->net_methods->create_connection (TLS, DC->ip, DC->port, S, DC, &mtproto_methods);
+ S->c = TLS->net_methods->create_connection (TLS, TLS->ipv6_enabled ? get_ipv6 (TLS, DC->id) : DC->ip, DC->port, S, DC, &mtproto_methods);
if (!S->c) {
vlogprintf (E_DEBUG, "Can not create connection to DC. Is network down?\n");
exit (1);
diff --git a/tgl-net.c b/tgl-net.c
index b8c340f..39c6a0d 100644
--- a/tgl-net.c
+++ b/tgl-net.c
@@ -260,14 +260,15 @@ static void conn_try_write (evutil_socket_t fd, short what, void *arg) {
event_add (c->write_ev, 0);
}
}
-
-struct connection *tgln_create_connection (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods) {
- struct connection *c = talloc0 (sizeof (*c));
- c->TLS = TLS;
- int fd = socket (AF_INET, SOCK_STREAM, 0);
- if (fd == -1) {
+
+static int my_connect (struct connection *c, const char *host) {
+ struct tgl_state *TLS = c->TLS;
+ int v6 = TLS->ipv6_enabled;
+ int fd = socket (v6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0);
+ if (fd < 0) {
vlogprintf (E_ERROR, "Can not create socket: %m\n");
- exit (1);
+ start_fail_timer (c);
+ return -1;
}
assert (fd >= 0 && fd < MAX_CONNECTIONS);
if (fd > max_connection_fd) {
@@ -279,29 +280,55 @@ struct connection *tgln_create_connection (struct tgl_state *TLS, const char *ho
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof (flags));
struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons (port);
- addr.sin_addr.s_addr = inet_addr (host);
-
+ struct sockaddr_in6 addr6;
+ memset (&addr, 0, sizeof (addr));
+ memset (&addr6, 0, sizeof (addr6));
+ if (v6) {
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = htons (c->port);
+ if (inet_pton (AF_INET6, host, &addr6.sin6_addr.s6_addr) != 1) {
+ vlogprintf (E_ERROR, "Bad ipv6 %s\n", host);
+ close (fd);
+ return -1;
+ }
+ } else {
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons (c->port);
+ if (inet_pton (AF_INET, host, &addr.sin_addr.s_addr) != 1) {
+ vlogprintf (E_ERROR, "Bad ipv4 %s\n", host);
+ close (fd);
+ return -1;
+ }
+ }
fcntl (fd, F_SETFL, O_NONBLOCK);
- if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
- //vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port);
+ if (connect (fd, (struct sockaddr *) (v6 ? (void *)&addr6 : (void *)&addr), v6 ? sizeof (addr6) : sizeof (addr)) == -1) {
if (errno != EINPROGRESS) {
- vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port);
close (fd);
- tfree (c, sizeof (*c));
- return 0;
+ return -1;
}
}
+ return fd;
+}
+
+struct connection *tgln_create_connection (struct tgl_state *TLS, const char *host, int port, struct tgl_session *session, struct tgl_dc *dc, struct mtproto_methods *methods) {
+ struct connection *c = talloc0 (sizeof (*c));
+ c->TLS = TLS;
+ c->ip = tstrdup (host);
+ c->port = port;
+
+ int fd = my_connect (c, c->ip);
+ if (fd < 0) {
+ vlogprintf (E_ERROR, "Can not connect to %s:%d %m\n", host, port);
+ tfree (c, sizeof (*c));
+ return 0;
+ }
c->fd = fd;
c->state = conn_connecting;
c->last_receive_time = tglt_get_double_time ();
- c->ip = tstrdup (host);
c->flags = 0;
- c->port = port;
assert (!Connections[fd]);
Connections[fd] = c;
@@ -333,40 +360,16 @@ static void restart_connection (struct connection *c) {
return;
}
- c->last_connect_time = time (0);
- int fd = socket (AF_INET, SOCK_STREAM, 0);
- if (fd == -1) {
- vlogprintf (E_ERROR, "Can not create socket: %m\n");
- exit (1);
- }
- assert (fd >= 0 && fd < MAX_CONNECTIONS);
- if (fd > max_connection_fd) {
- max_connection_fd = fd;
- }
- int flags = -1;
- setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof (flags));
- setsockopt (fd, SOL_SOCKET, SO_KEEPALIVE, &flags, sizeof (flags));
- setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &flags, sizeof (flags));
-
- struct sockaddr_in addr;
- addr.sin_family = AF_INET;
- addr.sin_port = htons (c->port);
if (strcmp (c->ip, c->dc->ip)) {
tfree_str (c->ip);
c->ip = tstrdup (c->dc->ip);
}
- addr.sin_addr.s_addr = inet_addr (c->ip);
-
-
- fcntl (fd, F_SETFL, O_NONBLOCK);
-
- if (connect (fd, (struct sockaddr *) &addr, sizeof (addr)) == -1) {
- if (errno != EINPROGRESS) {
- vlogprintf (E_WARNING, "Can not connect to %s:%d %m\n", c->ip, c->port);
- start_fail_timer (c);
- close (fd);
- return;
- }
+ c->last_connect_time = time (0);
+ int fd = my_connect (c, c->ip);
+ if (fd < 0) {
+ vlogprintf (E_WARNING, "Can not connect to %s:%d %m\n", c->ip, c->port);
+ start_fail_timer (c);
+ return;
}
c->fd = fd;
@@ -530,51 +533,6 @@ static void try_read (struct connection *c) {
try_rpc_read (c);
}
}
-/*
-int tgl_connections_make_poll_array (struct pollfd *fds, int max) {
- int _max = max;
- int i;
- for (i = 0; i <= max_connection_fd; i++) {
- if (Connections[i] && Connections[i]->state == conn_failed) {
- restart_connection (Connections[i]);
- }
- if (Connections[i] && Connections[i]->state != conn_failed) {
- assert (max > 0);
- struct connection *c = Connections[i];
- fds[0].fd = c->fd;
- fds[0].events = POLLERR | POLLHUP | POLLRDHUP | POLLIN;
- if (c->out_bytes || c->state == conn_connecting) {
- fds[0].events |= POLLOUT;
- }
- fds ++;
- max --;
- }
- }
- return _max - max;
-}
-
-void tgl_connections_poll_result (struct pollfd *fds, int max) {
- int i;
- for (i = 0; i < max; i++) {
- struct connection *c = Connections[fds[i].fd];
- if (fds[i].revents & POLLIN) {
- try_read (c);
- }
- if (fds[i].revents & (POLLHUP | POLLERR | POLLRDHUP)) {
- vlogprintf (E_NOTICE, "fail_connection: events_mask=0x%08x\n", fds[i].revents);
- fail_connection (c);
- } else if (fds[i].revents & POLLOUT) {
- if (c->state == conn_connecting) {
- vlogprintf (E_DEBUG, "connection ready\n");
- c->state = conn_ready;
- c->last_receive_time = tglt_get_double_time ();
- }
- if (c->out_bytes) {
- try_write (c);
- }
- }
- }
-}*/
static void incr_out_packet_num (struct connection *c) {
c->out_packet_num ++;
diff --git a/tgl.c b/tgl.c
index a02cf6b..60c2fc0 100644
--- a/tgl.c
+++ b/tgl.c
@@ -135,3 +135,7 @@ void tgl_set_app_version (struct tgl_state *TLS, const char *app_version) {
}
TLS->app_version = tstrdup (app_version);
}
+
+void tgl_enable_ipv6 (struct tgl_state *TLS) {
+ TLS->ipv6_enabled = 1;
+}
diff --git a/tgl.h b/tgl.h
index 24d39a5..ea4f442 100644
--- a/tgl.h
+++ b/tgl.h
@@ -30,11 +30,20 @@
#define TG_SERVER_3 "174.140.142.6"
#define TG_SERVER_4 "149.154.167.91"
#define TG_SERVER_5 "149.154.171.5"
-#define TG_SERVER_DEFAULT 4
+
+#define TG_SERVER_IPV6_1 "2001:b28:f23d:f001::a"
+#define TG_SERVER_IPV6_2 "2001:67c:4e8:f002::a"
+#define TG_SERVER_IPV6_3 "2001:b28:f23d:f003::a"
+#define TG_SERVER_IPV6_4 "2001:67c:4e8:f004::a"
+#define TG_SERVER_IPV6_5 "2001:b28:f23f:f005::a"
+#define TG_SERVER_DEFAULT 2
#define TG_SERVER_TEST_1 "173.240.5.253"
#define TG_SERVER_TEST_2 "149.154.167.40"
#define TG_SERVER_TEST_3 "174.140.142.5"
+#define TG_SERVER_TEST_IPV6_1 "2001:b28:f23d:f001::e"
+#define TG_SERVER_TEST_IPV6_2 "2001:67c:4e8:f002::e"
+#define TG_SERVER_TEST_IPV6_3 "2001:b28:f23d:f003::e"
#define TG_SERVER_TEST_DEFAULT 2
// JUST RANDOM STRING
@@ -223,6 +232,7 @@ struct tgl_state {
void *ev_login;
char *app_version;
+ int ipv6_enabled;
};
#pragma pack(pop)
//extern struct tgl_state tgl_state;
@@ -386,6 +396,7 @@ void tgl_free_all (struct tgl_state *TLS);
void tgl_register_app_id (struct tgl_state *TLS, int app_id, char *app_hash);
void tgl_login (struct tgl_state *TLS);
+void tgl_enable_ipv6 (struct tgl_state *TLS);
struct tgl_state *tgl_state_alloc (void);
#endif