blob: 2e1e61e62514a8a7b04f39c1ab56dbb19aff41c6 [file] [log] [blame]
Davide Pesavento22fba352017-10-17 15:53:51 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Davide Pesaventoe422f9e2022-06-03 01:30:23 -04003 * Copyright (c) 2014-2022, Regents of the University of California,
Davide Pesavento22fba352017-10-17 15:53:51 -04004 * Arizona Board of Regents,
5 * Colorado State University,
6 * University Pierre & Marie Curie, Sorbonne University,
7 * Washington University in St. Louis,
8 * Beijing Institute of Technology,
9 * The University of Memphis.
10 *
11 * This file is part of NFD (Named Data Networking Forwarding Daemon).
12 * See AUTHORS.md for complete list of NFD authors and contributors.
13 *
14 * NFD is free software: you can redistribute it and/or modify it under the terms
15 * of the GNU General Public License as published by the Free Software Foundation,
16 * either version 3 of the License, or (at your option) any later version.
17 *
18 * NFD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
19 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
20 * PURPOSE. See the GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License along with
23 * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
24 */
25
26#ifndef NFD_TESTS_DAEMON_FACE_WEBSOCKET_TRANSPORT_FIXTURE_HPP
27#define NFD_TESTS_DAEMON_FACE_WEBSOCKET_TRANSPORT_FIXTURE_HPP
28
29#include "face/websocket-transport.hpp"
30#include "face/face.hpp"
31
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040032#include "tests/test-common.hpp"
Davide Pesavento3dade002019-03-19 11:29:56 -060033#include "tests/daemon/limited-io.hpp"
Davide Pesaventoa8098582019-03-31 15:48:02 -040034#include "tests/daemon/face/dummy-link-service.hpp"
Davide Pesavento22fba352017-10-17 15:53:51 -040035
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040036namespace nfd::tests {
Davide Pesavento22fba352017-10-17 15:53:51 -040037
Davide Pesavento22fba352017-10-17 15:53:51 -040038namespace ip = boost::asio::ip;
Davide Pesaventoe422f9e2022-06-03 01:30:23 -040039using face::WebSocketTransport;
Davide Pesavento22fba352017-10-17 15:53:51 -040040
41/** \brief a fixture that accepts a single WebSocket connection from a client
42 */
Davide Pesaventocf7db2f2019-03-24 23:17:28 -040043class WebSocketTransportFixture : public GlobalIoFixture
Davide Pesavento22fba352017-10-17 15:53:51 -040044{
45protected:
Davide Pesavento22fba352017-10-17 15:53:51 -040046 /** \brief initialize server and start listening
47 */
48 void
49 serverListen(const ip::tcp::endpoint& ep,
Davide Pesavento14e71f02019-03-28 17:35:25 -040050 const time::milliseconds& pongTimeout = 1_s)
Davide Pesavento22fba352017-10-17 15:53:51 -040051 {
52 server.clear_access_channels(websocketpp::log::alevel::all);
53 server.clear_error_channels(websocketpp::log::elevel::all);
54
55 server.init_asio(&g_io);
Davide Pesavento412c9822021-07-02 00:21:05 -040056 server.set_open_handler(std::bind(&WebSocketTransportFixture::serverHandleOpen, this, _1));
57 server.set_close_handler(std::bind(&WebSocketTransportFixture::serverHandleClose, this));
58 server.set_message_handler(std::bind(&WebSocketTransportFixture::serverHandleMessage, this, _2));
59 server.set_pong_handler(std::bind(&WebSocketTransportFixture::serverHandlePong, this));
60 server.set_pong_timeout_handler(std::bind(&WebSocketTransportFixture::serverHandlePongTimeout, this));
Davide Pesavento22fba352017-10-17 15:53:51 -040061 server.set_pong_timeout(pongTimeout.count());
62
63 server.set_reuse_addr(true);
64
65 server.listen(ep);
66 server.start_accept();
67 }
68
69 /** \brief initialize client and connect to server
70 */
71 void
72 clientConnect(const std::string& uri)
73 {
74 client.clear_access_channels(websocketpp::log::alevel::all);
75 client.clear_error_channels(websocketpp::log::elevel::all);
76
77 client.init_asio(&g_io);
Davide Pesavento412c9822021-07-02 00:21:05 -040078 client.set_open_handler(std::bind(&WebSocketTransportFixture::clientHandleOpen, this, _1));
79 client.set_message_handler(std::bind(&WebSocketTransportFixture::clientHandleMessage, this, _2));
80 client.set_ping_handler(std::bind(&WebSocketTransportFixture::clientHandlePing, this));
Davide Pesavento22fba352017-10-17 15:53:51 -040081
82 websocketpp::lib::error_code ec;
83 auto con = client.get_connection(uri, ec);
84 BOOST_REQUIRE_EQUAL(ec, websocketpp::lib::error_code());
85
86 client.connect(con);
87 }
88
89 /** \brief initialize both server and client, and have each other connected, create Transport
90 */
91 void
92 initialize(ip::address address,
Davide Pesavento14e71f02019-03-28 17:35:25 -040093 time::milliseconds pingInterval = 10_s,
94 time::milliseconds pongTimeout = 1_s)
Davide Pesavento22fba352017-10-17 15:53:51 -040095 {
96 ip::tcp::endpoint ep(address, 20070);
97 serverListen(ep, pongTimeout);
98 clientConnect(FaceUri(ep, "ws").toString());
99
100 BOOST_REQUIRE_EQUAL(limitedIo.run(2, // serverHandleOpen, clientHandleOpen
Davide Pesavento14e71f02019-03-28 17:35:25 -0400101 1_s), LimitedIo::EXCEED_OPS);
Davide Pesavento22fba352017-10-17 15:53:51 -0400102
Davide Pesaventoa8098582019-03-31 15:48:02 -0400103 face = make_unique<Face>(make_unique<DummyLinkService>(),
Alexander Afanasyeva6bd7da2019-04-25 17:26:11 -0400104 make_unique<WebSocketTransport>(serverHdl, server, pingInterval));
Davide Pesavento22fba352017-10-17 15:53:51 -0400105 transport = static_cast<WebSocketTransport*>(face->getTransport());
Davide Pesaventoa8098582019-03-31 15:48:02 -0400106 serverReceivedPackets = &static_cast<DummyLinkService*>(face->getLinkService())->receivedPackets;
Davide Pesavento22fba352017-10-17 15:53:51 -0400107
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400108 BOOST_REQUIRE_EQUAL(transport->getState(), face::TransportState::UP);
Davide Pesavento22fba352017-10-17 15:53:51 -0400109 }
110
111private:
112 void
113 serverHandleOpen(websocketpp::connection_hdl hdl)
114 {
115 websocketpp::lib::error_code ec;
116 auto con = server.get_con_from_hdl(hdl, ec);
117 BOOST_REQUIRE_EQUAL(ec, websocketpp::lib::error_code());
118 BOOST_REQUIRE(con);
119 remoteEp = con->get_socket().remote_endpoint();
120
121 serverHdl = hdl;
122 limitedIo.afterOp();
123 }
124
125 void
126 serverHandleClose()
127 {
128 if (transport == nullptr) {
129 return;
130 }
131
132 transport->close();
133 limitedIo.afterOp();
134 }
135
136 void
137 serverHandleMessage(websocket::Server::message_ptr msg)
138 {
139 if (transport == nullptr) {
140 return;
141 }
142
143 transport->receiveMessage(msg->get_payload());
144 limitedIo.afterOp();
145 }
146
147 void
148 serverHandlePong()
149 {
150 if (transport == nullptr) {
151 return;
152 }
153
154 transport->handlePong();
155 limitedIo.afterOp();
156 }
157
158 void
159 serverHandlePongTimeout()
160 {
161 if (transport == nullptr) {
162 return;
163 }
164
165 transport->handlePongTimeout();
166 limitedIo.afterOp();
167 }
168
169 void
170 clientHandleOpen(websocketpp::connection_hdl hdl)
171 {
172 clientHdl = hdl;
173 limitedIo.afterOp();
174 }
175
176 void
177 clientHandleMessage(websocket::Client::message_ptr msg)
178 {
179 clientReceivedMessages.push_back(msg->get_payload());
180 limitedIo.afterOp();
181 }
182
183 bool
184 clientHandlePing()
185 {
186 limitedIo.afterOp();
187 return clientShouldPong;
188 }
189
190protected:
191 LimitedIo limitedIo;
192
193 websocket::Server server;
194 websocketpp::connection_hdl serverHdl;
195 ip::tcp::endpoint remoteEp;
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400196 WebSocketTransport* transport = nullptr;
197 std::vector<RxPacket>* serverReceivedPackets = nullptr;
Davide Pesavento22fba352017-10-17 15:53:51 -0400198
199 websocket::Client client;
200 websocketpp::connection_hdl clientHdl;
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400201 bool clientShouldPong = true;
Davide Pesavento22fba352017-10-17 15:53:51 -0400202 std::vector<std::string> clientReceivedMessages;
203
204private:
205 unique_ptr<Face> face;
206};
207
Davide Pesaventoe422f9e2022-06-03 01:30:23 -0400208} // namespace nfd::tests
Davide Pesavento22fba352017-10-17 15:53:51 -0400209
210#endif // NFD_TESTS_DAEMON_FACE_WEBSOCKET_TRANSPORT_FIXTURE_HPP