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 2012-2013 Vkontakte Ltd
18 2012-2013 Nikolai Durov
19 2012-2013 Andrey Lopatin
20 2013 Vitaliy Valtman
21
22 Copyright 2014-2016 Telegram Messenger Inc
23 2014-2016 Vitaly Valtman
24*/
25
26#pragma once
27
28#include <stdlib.h>
29#include <sys/uio.h>
30#include <assert.h>
31
32#include "crypto/aesni256.h"
33#include "net/net-msg-buffers.h"
34#include "crc32.h"
35
36
37/* INVARIANTS FOR MULTITHREAD USE:
38 - any raw message is valid until you have the link
39 - any tmp raw message is valid until it's parent is not modified
40 - pointer to raw message implies lock on it.
41 - msg part can be modified only if you have lock or you have only valid link
42 - msg buffer can be modified if it's reference counter is 1 and overlying msg part can be modified
43 - msg parts can not have loops
44*/
45
46/*
47 msg_part mp can be expanded to left, if mp->refcnt=1, mp->part->refcnt=1, mp=raw->first, where raw is raw_message we have in this thread
48 msg_part mp can be expanded to right, if mp->part->refcnt=1, mp->next=NULL and ((mp is locked) or (refcnt on chain from raw->first to mp is 1))
49
50 it is invalid to change any msg_parts after raw->last
51*/
52/*
53 * MESSAGE PARTS (struct msg_part)
54 */
55
56struct msg_part {
57 // fields inherited from msg_buffer
58 //struct msg_buffers_chunk *chunk;
59#ifndef _LP64
60 int resvd;
61#endif
62 int refcnt;
63 int magic;
64 // fields specific to msg_part
65 struct msg_part *next;
66 struct msg_buffer *part;
67 int offset; // data offset inside part->data
68 int data_end; // end of data offset inside part->data
69};
70
71extern int rwm_total_msg_parts;
72extern int rwm_total_msgs;
73
74#define MSG_PART_MAGIC 0x8341aa7
75#define MSG_PART_LOCKED_MAGIC (~MSG_PART_MAGIC)
76struct msg_part *new_msg_part (struct msg_part *neighbor, struct msg_buffer *X);
77
78/*
79 * RAW MESSAGES (struct raw_message) = chains of MESSAGE PARTs
80 */
81
82// ordinary raw message (changing refcnt of pointed msg_parts)
83#define RM_INIT_MAGIC 0x23513473
84// temp raw message (doesn't change refcnts of pointed msg_parts), used for fast read iterators
85#define RM_TMP_MAGIC 0x52a717f3
86
87#define RM_PREPEND_RESERVE 128
88
89struct raw_message {
90 struct msg_part *first, *last; // 'last' doesn't increase refcnt of pointed msg_part
91 int total_bytes; // bytes in the chain (extra bytes ignored even if present)
92 int magic; // one of RM_INIT_MAGIC, RM_TMP_MAGIC
93 int first_offset; // offset of first used byte inside first buffer data
94 int last_offset; // offset after last used byte inside last buffer data
95};
96
97/* NB: struct raw_message itself is never allocated or freed by the following functions since
98 it is usually part (field) of a larger structure
99*/
100
101int rwm_free (struct raw_message *raw);
102int rwm_init (struct raw_message *raw, int alloc_bytes);
103int rwm_create (struct raw_message *raw, const void *data, int alloc_bytes);
104void rwm_clone (struct raw_message *dest_raw, struct raw_message *src_raw);
105void rwm_move (struct raw_message *dest_raw, struct raw_message *src_raw);
106int rwm_push_data (struct raw_message *raw, const void *data, int alloc_bytes);
107int rwm_push_data_ext (struct raw_message *raw, const void *data, int alloc_bytes, int prepend, int small_buffer, int std_buffer);
108int rwm_push_data_front (struct raw_message *raw, const void *data, int alloc_bytes);
109int rwm_fetch_data (struct raw_message *raw, void *data, int bytes);
110int rwm_skip_data (struct raw_message *raw, int bytes);
111int rwm_fetch_lookup (struct raw_message *raw, void *buf, int bytes);
112int rwm_fetch_data_back (struct raw_message *raw, void *data, int bytes);
113int rwm_fetch_lookup_back (struct raw_message *raw, void *data, int bytes);
114int rwm_trunc (struct raw_message *raw, int len);
115int rwm_union (struct raw_message *raw, struct raw_message *tail);
116int rwm_split (struct raw_message *raw, struct raw_message *tail, int bytes);
117int rwm_split_head (struct raw_message *head, struct raw_message *raw, int bytes);
118void *rwm_prepend_alloc (struct raw_message *raw, int alloc_bytes);
119void *rwm_postpone_alloc (struct raw_message *raw, int alloc_bytes);
120
121void rwm_clean (struct raw_message *raw);
122void rwm_clear (struct raw_message *raw);
123int rwm_check (struct raw_message *raw);
124int fork_message_chain (struct raw_message *raw);
125
126int rwm_compare (struct raw_message *l, struct raw_message *r);
127
128int rwm_prepare_iovec (const struct raw_message *raw, struct iovec *iov, int iov_len, int bytes);
129int rwm_dump_sizes (struct raw_message *raw);
130int rwm_dump (struct raw_message *raw);
131unsigned rwm_crc32c (struct raw_message *raw, int bytes);
132unsigned rwm_crc32 (struct raw_message *raw, int bytes);
133unsigned rwm_custom_crc32 (struct raw_message *raw, int bytes, crc32_partial_func_t custom_crc32_partial);
134
135int rwm_process (struct raw_message *raw, int bytes, int (*process_block)(void *extra, const void *data, int len), void *extra);
136
137#define RMPF_ADVANCE 1
138#define RMPF_TRUNCATE 2
139int rwm_process_ex (struct raw_message *raw, int bytes, int offset, int flags, int (*process_block)(void *extra, const void *data, int len), void *extra);
140
141
142/* negative exit code of process stops processing */
143int rwm_process_from_offset (struct raw_message *raw, int bytes, int offset, int (*process_block)(void *extra, const void *data, int len), void *extra);
144/* warning: in current realization refcnt of message chain should be 1 */
145int rwm_transform_from_offset (struct raw_message *raw, int bytes, int offset, int (*transform_block)(void *extra, void *data, int len), void *extra);
146int rwm_process_and_advance (struct raw_message *raw, int bytes, int (*process_block)(void *extra, const void *data, int len), void *extra);
147int rwm_sha1 (struct raw_message *raw, int bytes, unsigned char output[20]);
148// int rwm_encrypt_decrypt (struct raw_message *raw, int bytes, tg_aes_ctx_t *ctx, unsigned char iv[32]);
149// int rwm_encrypt_decrypt_cbc (struct raw_message *raw, int bytes, tg_aes_ctx_t *ctx, unsigned char iv[16]);
150int rwm_encrypt_decrypt_to (struct raw_message *raw, struct raw_message *res, int bytes, tg_aes_ctx_t *ctx, void (*crypt)(tg_aes_ctx_t *ctx, const void *src, void *dst, int l, unsigned char *iv, void *extra, void *extra2), unsigned char *iv, int block_size, void *extra, void *extra2);
151
152void *rwm_get_block_ptr (struct raw_message *raw);
153int rwm_get_block_ptr_bytes (struct raw_message *raw);
154
155void rwm_to_tl_string (struct raw_message *raw);
156
157extern struct raw_message empty_rwm;
158void rwm_from_tl_string (struct raw_message *raw);
159