Ton

Форк
0
/
tcp_ping_pong.cpp 
148 строк · 5.2 Кб
1
/* 
2
    This file is part of TON Blockchain source code.
3

4
    TON Blockchain is free software; you can redistribute it and/or
5
    modify it under the terms of the GNU General Public License
6
    as published by the Free Software Foundation; either version 2
7
    of the License, or (at your option) any later version.
8

9
    TON Blockchain 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 General Public License for more details.
13

14
    You should have received a copy of the GNU General Public License
15
    along with TON Blockchain.  If not, see <http://www.gnu.org/licenses/>.
16

17
    In addition, as a special exception, the copyright holders give permission 
18
    to link the code of portions of this program with the OpenSSL library. 
19
    You must obey the GNU General Public License in all respects for all 
20
    of the code used other than OpenSSL. If you modify file(s) with this 
21
    exception, you may extend this exception to your version of the file(s), 
22
    but you are not obligated to do so. If you do not wish to do so, delete this 
23
    exception statement from your version. If you delete this exception statement 
24
    from all source files in the program, then also delete it here.
25

26
    Copyright 2017-2020 Telegram Systems LLP
27
*/
28
#include "td/actor/actor.h"
29

30
#include "td/utils/BufferedFd.h"
31
#include "td/utils/OptionParser.h"
32
#include "td/utils/port/SocketFd.h"
33
#include "td/utils/port/ServerSocketFd.h"
34
#include "td/utils/Observer.h"
35

36
#include "td/net/TcpListener.h"
37

38
class PingClient : public td::actor::Actor, td::ObserverBase {
39
 public:
40
  PingClient(td::SocketFd fd) : buffered_fd_(std::move(fd)) {
41
  }
42

43
 private:
44
  td::BufferedFd<td::SocketFd> buffered_fd_;
45
  td::actor::ActorId<PingClient> self_;
46
  void notify() override {
47
    // NB: Interface will be changed
48
    send_closure_later(self_, &PingClient::on_net);
49
  }
50
  void on_net() {
51
    loop();
52
  }
53

54
  void start_up() override {
55
    self_ = actor_id(this);
56
    LOG(INFO) << "Start";
57
    // Subscribe for socket updates
58
    // NB: Interface will be changed
59
    td::actor::SchedulerContext::get()->get_poll().subscribe(buffered_fd_.get_poll_info().extract_pollable_fd(this),
60
                                                             td::PollFlags::ReadWrite());
61

62
    alarm_timestamp() = td::Timestamp::now();
63
  }
64

65
  void tear_down() override {
66
    LOG(INFO) << "Close";
67
    // unsubscribe from socket updates
68
    // nb: interface will be changed
69
    td::actor::SchedulerContext::get()->get_poll().unsubscribe(buffered_fd_.get_poll_info().get_pollable_fd_ref());
70
  }
71

72
  void loop() override {
73
    auto status = [&] {
74
      TRY_STATUS(buffered_fd_.flush_read());
75
      auto &input = buffered_fd_.input_buffer();
76
      while (input.size() >= 12) {
77
        auto query = input.cut_head(12).move_as_buffer_slice();
78
        LOG(INFO) << "Got query " << td::format::escaped(query.as_slice());
79
        if (query[5] == 'i') {
80
          LOG(INFO) << "Send ping";
81
          buffered_fd_.output_buffer().append("magkpongpong");
82
        } else {
83
          LOG(INFO) << "Got pong";
84
        }
85
      }
86

87
      TRY_STATUS(buffered_fd_.flush_write());
88
      if (td::can_close(buffered_fd_)) {
89
        stop();
90
      }
91
      return td::Status::OK();
92
    }();
93
    if (status.is_error()) {
94
      LOG(ERROR) << "Client got error " << status;
95
      stop();
96
    }
97
  }
98

99
  void alarm() override {
100
    alarm_timestamp() = td::Timestamp::in(5);
101
    LOG(INFO) << "Send ping";
102
    buffered_fd_.output_buffer().append("magkpingping");
103
    loop();
104
  }
105
};
106

107
int main(int argc, char *argv[]) {
108
  td::OptionParser options_parser;
109
  options_parser.set_description("Tcp ping server/client (based on td::actors2)");
110

111
  int port = 8081;
112
  bool is_client = false;
113
  options_parser.add_option('p', "port", "listen/connect to tcp port (8081 by default)",
114
                            [&](td::Slice arg) { port = td::to_integer<int>(arg); });
115
  options_parser.add_option('c', "client", "Work as client (server by default)", [&]() { is_client = true; });
116
  auto status = options_parser.run(argc, argv);
117
  if (status.is_error()) {
118
    LOG(ERROR) << status.error();
119
    LOG(INFO) << options_parser;
120
    return 1;
121
  }
122

123
  // NB: Interface will be changed
124
  td::actor::Scheduler scheduler({2});
125
  scheduler.run_in_context([&] {
126
    if (is_client) {
127
      td::IPAddress ip_address;
128
      ip_address.init_ipv4_port("127.0.0.1", port).ensure();
129
      td::actor::create_actor<PingClient>(td::actor::ActorOptions().with_name("TcpClient").with_poll(),
130
                                          td::SocketFd::open(ip_address).move_as_ok())
131
          .release();
132
    } else {
133
      class Callback : public td::TcpListener::Callback {
134
       public:
135
        void accept(td::SocketFd fd) override {
136
          td::actor::create_actor<PingClient>(td::actor::ActorOptions().with_name("TcpClient").with_poll(),
137
                                              std::move(fd))
138
              .release();
139
        }
140
      };
141
      td::actor::create_actor<td::TcpListener>(td::actor::ActorOptions().with_name("TcpServer").with_poll(), port,
142
                                               std::make_unique<Callback>())
143
          .release();
144
    }
145
  });
146
  scheduler.run();
147
  return 0;
148
}
149

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

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

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

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