Ton

Форк
0
/
adnl-ext-client.cpp 
291 строка · 9.3 Кб
1
/*
2
    This file is part of TON Blockchain Library.
3

4
    TON Blockchain 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
    TON Blockchain 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 TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
16

17
    Copyright 2017-2020 Telegram Systems LLP
18
*/
19
#include "adnl-ext-client.hpp"
20
#include "adnl-ext-client.h"
21

22
namespace ton {
23

24
namespace adnl {
25

26
void AdnlExtClientImpl::alarm() {
27
  if (is_closing_) {
28
    return;
29
  }
30
  if (conn_.empty() || !conn_.is_alive()) {
31
    next_create_at_ = td::Timestamp::in(10.0);
32
    alarm_timestamp() = next_create_at_;
33

34
    auto fd = td::SocketFd::open(dst_addr_);
35
    if (fd.is_error()) {
36
      LOG(INFO) << "failed to connect to " << dst_addr_ << ": " << fd.move_as_error();
37
      return;
38
    }
39

40
    class Cb : public AdnlExtConnection::Callback {
41
     private:
42
      td::actor::ActorId<AdnlExtClientImpl> id_;
43

44
     public:
45
      void on_ready(td::actor::ActorId<AdnlExtConnection> conn) {
46
        td::actor::send_closure(id_, &AdnlExtClientImpl::conn_ready, conn);
47
      }
48
      void on_close(td::actor::ActorId<AdnlExtConnection> conn) {
49
        td::actor::send_closure(id_, &AdnlExtClientImpl::conn_stopped, conn);
50
      }
51
      Cb(td::actor::ActorId<AdnlExtClientImpl> id) : id_(id) {
52
      }
53
    };
54

55
    conn_ = td::actor::create_actor<AdnlOutboundConnection>(td::actor::ActorOptions().with_name("outconn").with_poll(),
56
                                                            fd.move_as_ok(), std::make_unique<Cb>(actor_id(this)), dst_,
57
                                                            local_id_, actor_id(this));
58
  }
59
}
60

61
void AdnlExtClientImpl::hangup() {
62
  conn_ = {};
63
  is_closing_ = true;
64
  ref_cnt_--;
65
  for (auto &it : out_queries_) {
66
    td::actor::ActorOwn<>(it.second);  // send hangup
67
  }
68
  try_stop();
69
}
70

71
void AdnlExtClientImpl::try_stop() {
72
  if (is_closing_ && ref_cnt_ == 0 && out_queries_.empty()) {
73
    stop();
74
  }
75
}
76

77
td::Status AdnlOutboundConnection::process_custom_packet(td::BufferSlice &data, bool &processed) {
78
  if (data.size() == 12) {
79
    auto F = fetch_tl_object<ton_api::tcp_pong>(data.clone(), true);
80
    if (F.is_ok()) {
81
      processed = true;
82
      return td::Status::OK();
83
    }
84
  }
85
  if (!local_id_.empty() && nonce_.size() != 0) {
86
    auto F = fetch_tl_object<ton_api::tcp_authentificationNonce>(data.clone(), true);
87
    if (F.is_ok()) {
88
      auto f = F.move_as_ok();
89
      if (f->nonce_.size() == 0 || f->nonce_.size() > 512) {
90
        return td::Status::Error(ErrorCode::protoviolation, "bad nonce size");
91
      }
92
      td::SecureString ss{nonce_.size() + f->nonce_.size()};
93
      ss.as_mutable_slice().copy_from(nonce_.as_slice());
94
      ss.as_mutable_slice().remove_prefix(nonce_.size()).copy_from(f->nonce_.as_slice());
95

96
      TRY_RESULT(dec, local_id_.create_decryptor());
97
      TRY_RESULT(B, dec->sign(ss.as_slice()));
98

99
      auto obj =
100
          create_tl_object<ton_api::tcp_authentificationComplete>(local_id_.compute_public_key().tl(), std::move(B));
101
      send(serialize_tl_object(obj, true));
102

103
      nonce_.clear();
104

105
      processed = true;
106
      authorization_complete_ = true;
107
      return td::Status::OK();
108
    }
109
  }
110
  return td::Status::OK();
111
}
112

113
void AdnlOutboundConnection::start_up() {
114
  AdnlExtConnection::start_up();
115
  auto X = dst_.pubkey().create_encryptor();
116
  if (X.is_error()) {
117
    LOG(ERROR) << "failed to init encryptor: " << X.move_as_error();
118
    stop();
119
    return;
120
  }
121
  auto enc = X.move_as_ok();
122

123
  td::BufferSlice d{256};
124
  auto id = dst_.compute_short_id();
125
  auto S = d.as_slice();
126
  S.copy_from(id.as_slice());
127
  S.remove_prefix(32);
128
  S.truncate(256 - 64 - 32);
129
  td::Random::secure_bytes(S);
130
  init_crypto(S);
131

132
  auto R = enc->encrypt(S);
133
  if (R.is_error()) {
134
    LOG(ERROR) << "failed to  encrypt: " << R.move_as_error();
135
    stop();
136
    return;
137
  }
138
  auto data = R.move_as_ok();
139
  LOG_CHECK(data.size() == 256 - 32) << "size=" << data.size();
140
  S = d.as_slice();
141
  S.remove_prefix(32);
142
  CHECK(S.size() == data.size());
143
  S.copy_from(data.as_slice());
144

145
  send_uninit(std::move(d));
146

147
  if (!local_id_.empty()) {
148
    nonce_ = td::SecureString{32};
149
    td::Random::secure_bytes(nonce_.as_mutable_slice());
150
    auto obj = create_tl_object<ton_api::tcp_authentificate>(td::BufferSlice{nonce_.as_slice()});
151
    send(serialize_tl_object(obj, true));
152
  }
153
}
154

155
void AdnlExtClientImpl::check_ready(td::Promise<td::Unit> promise) {
156
  if (conn_.empty() || !conn_.is_alive()) {
157
    promise.set_error(td::Status::Error(ErrorCode::notready, "not ready"));
158
    return;
159
  }
160
  td::actor::send_closure(td::actor::ActorId<AdnlExtConnection>{conn_.get()}, &AdnlExtConnection::check_ready_async,
161
                          std::move(promise));
162
}
163

164
td::actor::ActorOwn<AdnlExtClient> AdnlExtClient::create(AdnlNodeIdFull dst, td::IPAddress dst_addr,
165
                                                         std::unique_ptr<AdnlExtClient::Callback> callback) {
166
  return td::actor::create_actor<AdnlExtClientImpl>("extclient", std::move(dst), dst_addr, std::move(callback));
167
}
168

169
td::actor::ActorOwn<AdnlExtClient> AdnlExtClient::create(AdnlNodeIdFull dst, PrivateKey local_id,
170
                                                         td::IPAddress dst_addr,
171
                                                         std::unique_ptr<AdnlExtClient::Callback> callback) {
172
  return td::actor::create_actor<AdnlExtClientImpl>("extclient", std::move(dst), std::move(local_id), dst_addr,
173
                                                    std::move(callback));
174
}
175

176
td::Status AdnlOutboundConnection::process_packet(td::BufferSlice data) {
177
  TRY_RESULT(F, fetch_tl_object<lite_api::adnl_message_answer>(std::move(data), true));
178
  td::actor::send_closure(ext_client_, &AdnlExtClientImpl::answer_query, F->query_id_, std::move(F->answer_));
179
  return td::Status::OK();
180
}
181

182
void AdnlExtMultiClientImpl::start_up() {
183
  for (auto &id : ids_) {
184
    add_server(id.first, id.second, [](td::Result<td::Unit> R) {});
185
  }
186
  ids_.clear();
187
}
188

189
void AdnlExtMultiClientImpl::add_server(AdnlNodeIdFull dst, td::IPAddress dst_addr, td::Promise<td::Unit> promise) {
190
  for (auto &c : clients_) {
191
    if (c.second->addr == dst_addr) {
192
      promise.set_error(td::Status::Error(ErrorCode::error, "duplicate ip"));
193
      return;
194
    }
195
  }
196

197
  auto g = ++generation_;
198
  auto cli = std::make_unique<Client>(AdnlExtClient::create(dst, dst_addr, make_callback(g)), dst, dst_addr, g);
199
  clients_[g] = std::move(cli);
200
}
201

202
void AdnlExtMultiClientImpl::del_server(td::IPAddress dst_addr, td::Promise<td::Unit> promise) {
203
  for (auto &c : clients_) {
204
    if (c.second->addr == dst_addr) {
205
      if (c.second->ready) {
206
        total_ready_--;
207
        if (!total_ready_) {
208
          callback_->on_stop_ready();
209
        }
210
      }
211
      clients_.erase(c.first);
212
      promise.set_value(td::Unit());
213
      return;
214
    }
215
  }
216
  promise.set_error(td::Status::Error(ErrorCode::error, "ip not found"));
217
}
218

219
void AdnlExtMultiClientImpl::send_query(std::string name, td::BufferSlice data, td::Timestamp timeout,
220
                                        td::Promise<td::BufferSlice> promise) {
221
  if (total_ready_ == 0) {
222
    promise.set_error(td::Status::Error(ErrorCode::notready, "conn not ready"));
223
    return;
224
  }
225

226
  std::vector<td::uint32> vec;
227
  for (auto &c : clients_) {
228
    if (c.second->ready) {
229
      vec.push_back(c.first);
230
    }
231
  }
232
  CHECK(vec.size() == total_ready_);
233

234
  auto &c = clients_[vec[td::Random::fast(0, td::narrow_cast<td::uint32>(vec.size() - 1))]];
235

236
  td::actor::send_closure(c->client, &AdnlExtClient::send_query, std::move(name), std::move(data), timeout,
237
                          std::move(promise));
238
}
239

240
void AdnlExtMultiClientImpl::client_ready(td::uint32 idx, bool value) {
241
  auto it = clients_.find(idx);
242
  if (it == clients_.end()) {
243
    return;
244
  }
245
  auto &c = it->second;
246
  if (c->ready == value) {
247
    return;
248
  }
249
  c->ready = value;
250
  if (value) {
251
    total_ready_++;
252
    if (total_ready_ == 1) {
253
      callback_->on_ready();
254
    }
255
  } else {
256
    total_ready_--;
257
    if (total_ready_ == 0) {
258
      callback_->on_stop_ready();
259
    }
260
  }
261
}
262

263
std::unique_ptr<AdnlExtClient::Callback> AdnlExtMultiClientImpl::make_callback(td::uint32 g) {
264
  class Cb : public Callback {
265
   public:
266
    Cb(td::actor::ActorId<AdnlExtMultiClientImpl> id, td::uint32 idx) : id_(id), idx_(idx) {
267
    }
268

269
    void on_ready() override {
270
      td::actor::send_closure(id_, &AdnlExtMultiClientImpl::client_ready, idx_, true);
271
    }
272

273
    void on_stop_ready() override {
274
      td::actor::send_closure(id_, &AdnlExtMultiClientImpl::client_ready, idx_, false);
275
    }
276

277
   private:
278
    td::actor::ActorId<AdnlExtMultiClientImpl> id_;
279
    td::uint32 idx_;
280
  };
281
  return std::make_unique<Cb>(actor_id(this), g);
282
}
283

284
td::actor::ActorOwn<AdnlExtMultiClient> AdnlExtMultiClient::create(
285
    std::vector<std::pair<AdnlNodeIdFull, td::IPAddress>> ids, std::unique_ptr<AdnlExtClient::Callback> callback) {
286
  return td::actor::create_actor<AdnlExtMultiClientImpl>("extmulticlient", std::move(ids), std::move(callback));
287
}
288

289
}  // namespace adnl
290

291
}  // namespace ton
292

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.