UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
nat-helper.cpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2021 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37#include <iostream>
38#include <functional>
39#include "nat-helper.hpp"
40
41NatHelper::NatHelper(int port) : port(port),
42 io_service(),
43 //work_guard(io_service.get_executor()),
44 acceptor(io_service),
45 pendingSocket(io_service)
46{
47
48}
49
51{
52
53}
54
55
57 std::cout << "Running" << std::endl;
59 std::cout << "End" << std::endl;
60}
61
62void NatHelper::run(bool async){
63 using namespace std::placeholders;
64
65 asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);
66 acceptor.open(endpoint.protocol());
67 acceptor.bind(endpoint);
68 acceptor.listen(asio::socket_base::max_connections);
69 acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(false));
70 acceptor.async_accept(pendingSocket,
71 std::bind(&NatHelper::onConnectionAccepted, this, _1));
72
73 if(async){
74 std::cout << "Starting thread" << std::endl;
75 worker_thread = std::thread(&NatHelper::worker, this);
76 } else {
77 worker();
78 }
79}
80
82 std::cout << "Stopping..." << std::endl;
83 io_service.stop();
84 worker_thread.join();
85}
86
87void NatHelper::onConnectionAccepted(const std::error_code& ec){
88 if(ec){
89 std::cerr << "Error accepting client connection: " << ec.message() << std::endl;
90 return;
91 }
92
93 using namespace std::placeholders;
94
95 auto client = std::make_shared<Client>(std::move(pendingSocket));
96 client->readDescription(
97 std::bind(&NatHelper::onClientDesc, this, _1, _2));
98 incomingClients.insert({client.get(), std::move(client)});
99
100 acceptor.async_accept(pendingSocket,
101 std::bind(&NatHelper::onConnectionAccepted, this, _1));
102}
103
105 for(auto it = rooms.begin(); it != rooms.end(); ){
106 if(it->second->isEmpty()){
107 std::cout << "Removing empty room " << it->first << "\n";
108 it = rooms.erase(it);
109 } else {
110 it++;
111 }
112 }
113}
114
117 std::cerr << "Error reading client description" << std::endl;
118 incomingClients.erase(&client);
119 return;
120 }
121
122 const auto& roomName = client.getRoomName();
123 std::cout << "Moving client " << client.getClientName()
124 << " to room " << roomName
125 << std::endl;
126
127 auto roomIt = rooms.find(roomName);
128 if(roomIt == rooms.end()){
130 std::cout << "Creating room " << roomName << std::endl;
131 roomIt = rooms.insert({roomName, std::make_shared<Room>(roomName)}).first;
132 }
133
134 auto clientIt = incomingClients.find(&client);
135 auto& room = roomIt->second;
136 if(room->isFull()){
137 std::cerr << "Room " << roomName << " is full, dropping client" << std::endl;
138 } else {
139 roomIt->second->addClient(std::move(clientIt->second));
140 }
141 incomingClients.erase(clientIt);
142}
asio::ip::tcp::acceptor acceptor
void stop()
std::thread worker_thread
void onClientDesc(Client &client, CompletionStatus status)
void cleanEmptyRooms()
asio::io_service io_service
void worker()
asio::ip::tcp::socket pendingSocket
std::map< std::string, std::shared_ptr< Room > > rooms
std::map< Client *, std::shared_ptr< Client > > incomingClients
void run(bool async=true)
void onConnectionAccepted(const std::error_code &ec)
codec_t first
Definition sdl2.c:423
CompletionStatus