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
41int 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
53int 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
99int 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
193int 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
211int 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
228int 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
235int 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
252int 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
268int 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