1 | /* |
2 | This file is part of Mtproto-proxy Library. |
3 | |
4 | Mtproto-proxy Library is free software: you can redistribute it and/or modify |
5 | it under the terms of the GNU Lesser General Public License as published by |
6 | the Free Software Foundation, either version 2 of the License, or |
7 | (at your option) any later version. |
8 | |
9 | Mtproto-proxy Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | GNU Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public License |
15 | along with Mtproto-proxy Library. If not, see <http://www.gnu.org/licenses/>. |
16 | |
17 | Copyright 2009-2013 Vkontakte Ltd |
18 | 2008-2013 Nikolai Durov |
19 | 2008-2013 Andrey Lopatin |
20 | 2013 Vitaliy Valtman |
21 | |
22 | Copyright 2014-2016 Telegram Messenger Inc |
23 | 2015-2016 Vitaly Valtman |
24 | */ |
25 | |
26 | #include <errno.h> |
27 | #include <sys/uio.h> |
28 | #include <stdlib.h> |
29 | #include <assert.h> |
30 | #include <stdio.h> |
31 | #include <unistd.h> |
32 | |
33 | #include "net/net-connections.h" |
34 | #include "net/net-msg.h" |
35 | #include "net/net-msg-buffers.h" |
36 | #include "crypto/aesni256.h" |
37 | #include "net/net-crypto-aes.h" |
38 | #include "kprintf.h" |
39 | |
40 | |
41 | int cpu_tcp_free_connection_buffers (connection_job_t C) /* {{{ */ { |
42 | struct connection_info *c = CONN_INFO (C); |
43 | assert_net_cpu_thread (); |
44 | rwm_free (&c->in); |
45 | rwm_free (&c->in_u); |
46 | rwm_free (&c->out); |
47 | rwm_free (&c->out_p); |
48 | return 0; |
49 | } |
50 | /* }}} */ |
51 | |
52 | |
53 | int cpu_tcp_server_writer (connection_job_t C) /* {{{ */ { |
54 | assert_net_cpu_thread (); |
55 | |
56 | struct connection_info *c = CONN_INFO (C); |
57 | |
58 | int stop = 0; |
59 | if (c->status == conn_write_close) { |
60 | stop = 1; |
61 | } |
62 | |
63 | while (1) { |
64 | struct raw_message *raw = mpq_pop_nw (c->out_queue, 4); |
65 | if (!raw) { break; } |
66 | //rwm_union (out, raw); |
67 | c->type->write_packet (C, raw); |
68 | free (raw); |
69 | } |
70 | |
71 | c->type->flush (C); |
72 | |
73 | struct raw_message *raw = malloc (sizeof (*raw)); |
74 | |
75 | if (c->type->crypto_encrypt_output && c->crypto) { |
76 | c->type->crypto_encrypt_output (C); |
77 | *raw = c->out_p; |
78 | rwm_init (&c->out_p, 0); |
79 | } else { |
80 | *raw = c->out; |
81 | rwm_init (&c->out, 0); |
82 | } |
83 | |
84 | if (raw->total_bytes && c->io_conn) { |
85 | mpq_push_w (SOCKET_CONN_INFO(c->io_conn)->out_packet_queue, raw, 0); |
86 | if (stop) { |
87 | __sync_fetch_and_or (&SOCKET_CONN_INFO(c->io_conn)->flags, C_STOPWRITE); |
88 | } |
89 | job_signal (JOB_REF_CREATE_PASS (c->io_conn), JS_RUN); |
90 | } else { |
91 | rwm_free (raw); |
92 | free (raw); |
93 | } |
94 | |
95 | return 0; |
96 | } |
97 | /* }}} */ |
98 | |
99 | int cpu_tcp_server_reader (connection_job_t C) /* {{{ */ { |
100 | assert_net_cpu_thread (); |
101 | struct connection_info *c = CONN_INFO(C); |
102 | |
103 | while (1) { |
104 | struct raw_message *raw = mpq_pop_nw (c->in_queue, 4); |
105 | if (!raw) { break; } |
106 | |
107 | if (c->crypto) { |
108 | rwm_union (&c->in_u, raw); |
109 | } else { |
110 | rwm_union (&c->in, raw); |
111 | } |
112 | free (raw); |
113 | } |
114 | |
115 | if (c->crypto) { |
116 | assert (c->type->crypto_decrypt_input (C) >= 0); |
117 | } |
118 | |
119 | int r = c->in.total_bytes; |
120 | |
121 | int s = c->skip_bytes; |
122 | |
123 | if (c->type->data_received) { |
124 | c->type->data_received (C, r); |
125 | } |
126 | |
127 | if (c->flags & (C_FAILED | C_ERROR | C_NET_FAILED)) { |
128 | return -1; |
129 | } |
130 | if (c->flags & C_STOPREAD) { |
131 | return 0; |
132 | } |
133 | |
134 | int r1 = r; |
135 | |
136 | if (s < 0) { |
137 | // have to skip s more bytes |
138 | if (r1 > -s) { |
139 | r1 = -s; |
140 | } |
141 | rwm_skip_data (&c->in, r1); |
142 | c->skip_bytes = s += r1; |
143 | |
144 | vkprintf (2, "skipped %d bytes, %d more to skip\n" , r1, -s); |
145 | |
146 | if (s) { |
147 | return 0; |
148 | } |
149 | } |
150 | |
151 | if (s > 0) { |
152 | // need to read s more bytes before invoking parse_execute() |
153 | if (r1 >= s) { |
154 | c->skip_bytes = s = 0; |
155 | } |
156 | |
157 | vkprintf (1, "fetched %d bytes, %d available bytes, %d more to load\n" , r, r1, s ? s - r1 : 0); |
158 | if (s) { |
159 | return 0; |
160 | } |
161 | } |
162 | |
163 | |
164 | while (!c->skip_bytes && !(c->flags & (C_ERROR | C_FAILED | C_NET_FAILED | C_STOPREAD)) && c->status != conn_error) { |
165 | int bytes = c->in.total_bytes; |
166 | if (!bytes) { |
167 | break; |
168 | } |
169 | |
170 | int res = c->type->parse_execute (C); |
171 | |
172 | // 0 - ok/done, >0 - need that much bytes, <0 - skip bytes, or NEED_MORE_BYTES |
173 | if (!res) { |
174 | } else if (res != NEED_MORE_BYTES) { |
175 | bytes = (c->crypto ? c->in.total_bytes : c->in_u.total_bytes); |
176 | // have to load or skip abs(res) bytes before invoking parse_execute |
177 | if (res < 0) { |
178 | res -= bytes; |
179 | } else { |
180 | res += bytes; |
181 | } |
182 | c->skip_bytes = res; |
183 | break; |
184 | } else { |
185 | break; |
186 | } |
187 | } |
188 | |
189 | return 0; |
190 | } |
191 | /* }}} */ |
192 | |
193 | int cpu_tcp_aes_crypto_encrypt_output (connection_job_t C) /* {{{ */ { |
194 | assert_net_cpu_thread (); |
195 | struct connection_info *c = CONN_INFO (C); |
196 | |
197 | struct aes_crypto *T = c->crypto; |
198 | assert (c->crypto); |
199 | struct raw_message *out = &c->out; |
200 | |
201 | int l = out->total_bytes; |
202 | l &= ~15; |
203 | if (l) { |
204 | assert (rwm_encrypt_decrypt_to (&c->out, &c->out_p, l, &T->write_aeskey, (void *)T->write_aeskey.type->cbc_crypt, T->write_iv, 16, 0, 0) == l); |
205 | } |
206 | |
207 | return (-out->total_bytes) & 15; |
208 | } |
209 | /* }}} */ |
210 | |
211 | int cpu_tcp_aes_crypto_decrypt_input (connection_job_t C) /* {{{ */ { |
212 | assert_net_cpu_thread (); |
213 | struct connection_info *c = CONN_INFO (C); |
214 | struct aes_crypto *T = c->crypto; |
215 | assert (c->crypto); |
216 | struct raw_message *in = &c->in_u; |
217 | |
218 | int l = in->total_bytes; |
219 | l &= ~15; |
220 | if (l) { |
221 | assert (rwm_encrypt_decrypt_to (&c->in_u, &c->in, l, &T->read_aeskey, (void *)T->read_aeskey.type->cbc_crypt, T->read_iv, 16, 0, 0) == l); |
222 | } |
223 | |
224 | return (-in->total_bytes) & 15; |
225 | } |
226 | /* }}} */ |
227 | |
228 | int cpu_tcp_aes_crypto_needed_output_bytes (connection_job_t C) /* {{{ */ { |
229 | struct connection_info *c = CONN_INFO (C); |
230 | assert (c->crypto); |
231 | return -c->out.total_bytes & 15; |
232 | } |
233 | /* }}} */ |
234 | |
235 | int cpu_tcp_aes_crypto_ctr128_encrypt_output (connection_job_t C) /* {{{ */ { |
236 | assert_net_cpu_thread (); |
237 | struct connection_info *c = CONN_INFO (C); |
238 | |
239 | struct aes_crypto *T = c->crypto; |
240 | assert (c->crypto); |
241 | struct raw_message *out = &c->out; |
242 | |
243 | int l = out->total_bytes; |
244 | if (l) { |
245 | assert (rwm_encrypt_decrypt_to (&c->out, &c->out_p, l, &T->write_aeskey, (void *)T->write_aeskey.type->ctr128_crypt, T->write_iv, 1, T->write_ebuf, &T->write_num) == l); |
246 | } |
247 | |
248 | return 0; |
249 | } |
250 | /* }}} */ |
251 | |
252 | int cpu_tcp_aes_crypto_ctr128_decrypt_input (connection_job_t C) /* {{{ */ { |
253 | assert_net_cpu_thread (); |
254 | struct connection_info *c = CONN_INFO (C); |
255 | struct aes_crypto *T = c->crypto; |
256 | assert (c->crypto); |
257 | struct raw_message *in = &c->in_u; |
258 | |
259 | int l = in->total_bytes; |
260 | if (l) { |
261 | assert (rwm_encrypt_decrypt_to (&c->in_u, &c->in, l, &T->read_aeskey, (void *)T->read_aeskey.type->ctr128_crypt, T->read_iv, 1, T->read_ebuf, &T->read_num) == l); |
262 | } |
263 | |
264 | return 0; |
265 | } |
266 | /* }}} */ |
267 | |
268 | int cpu_tcp_aes_crypto_ctr128_needed_output_bytes (connection_job_t C) /* {{{ */ { |
269 | struct connection_info *c = CONN_INFO (C); |
270 | assert (c->crypto); |
271 | return 0; |
272 | } |
273 | /* }}} */ |
274 | |