blob: c8afbee45d31c16dc8f73fc22e5499ca5b8a9f0f [file] [log] [blame]
Jorge E. Moreira4750e542020-01-07 14:35:35 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberad704b02020-01-17 12:42:38 -080017#include "Utils.h"
18
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080019#include <webrtc/AdbWebSocketHandler.h>
20#include <webrtc/DTLS.h>
21#include <webrtc/MyWebSocketHandler.h>
22#include <webrtc/RTPSocketHandler.h>
23#include <webrtc/ServerState.h>
Andreas Huberad704b02020-01-17 12:42:38 -080024#include <webrtc/STUNClient.h>
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080025#include <webrtc/STUNMessage.h>
26
27#include <https/HTTPServer.h>
28#include <https/PlainSocket.h>
29#include <https/RunLoop.h>
30#include <https/SafeCallbackable.h>
31#include <https/SSLSocket.h>
32#include <https/Support.h>
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080033
34#include <iostream>
35#include <unordered_map>
36
Andreas Huberad704b02020-01-17 12:42:38 -080037#include <netdb.h>
38
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080039#include <gflags/gflags.h>
40
Jorge E. Moreiraf0e3d8a2020-01-08 16:39:48 -080041DEFINE_int32(http_server_port, 8443, "The port for the http server.");
42DEFINE_bool(use_secure_http, true, "Whether to use HTTPS or HTTP.");
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080043DEFINE_string(
44 public_ip,
45 "0.0.0.0",
46 "Public IPv4 address of your server, a.b.c.d format");
47DEFINE_string(
48 assets_dir,
49 "webrtc",
50 "Directory with location of webpage assets.");
51DEFINE_string(
52 certs_dir,
53 "webrtc/certs",
54 "Directory to certificates.");
55
56DEFINE_int32(touch_fd, -1, "An fd to listen on for touch connections.");
57DEFINE_int32(keyboard_fd, -1, "An fd to listen on for keyboard connections.");
Jorge E. Moreirae049b792019-12-18 18:17:48 -080058DEFINE_int32(frame_server_fd, -1, "An fd to listen on for frame updates");
59DEFINE_bool(write_virtio_input, false, "Whether to send input events in virtio format.");
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080060
61DEFINE_string(adb, "", "Interface:port of local adb service.");
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080062
Andreas Huberad704b02020-01-17 12:42:38 -080063DEFINE_string(
64 stun_server,
65 "stun.l.google.com:19302",
66 "host:port of STUN server to use for public address resolution");
67
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080068int main(int argc, char **argv) {
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080069 ::gflags::ParseCommandLineFlags(&argc, &argv, true);
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -080070
71 SSLSocket::Init();
72 DTLS::Init();
73
Andreas Huberad704b02020-01-17 12:42:38 -080074 if (FLAGS_public_ip.empty() || FLAGS_public_ip == "0.0.0.0") {
75 // NOTE: We only contact the external STUN server once upon startup
76 // to determine our own public IP.
77 // This only works if NAT does not remap ports, i.e. a local port 15550
78 // is visible to the outside world on port 15550 as well.
79 // If this condition is not met, this code will have to be modified
80 // and a STUN request made for each locally bound socket before
81 // fulfilling a "MyWebSocketHandler::getCandidate" ICE request.
82
83 const addrinfo kHints = {
84 AI_ADDRCONFIG,
85 PF_INET,
86 SOCK_DGRAM,
87 IPPROTO_UDP,
88 0, // ai_addrlen
89 nullptr, // ai_addr
90 nullptr, // ai_canonname
91 nullptr // ai_next
92 };
93
94 auto pieces = SplitString(FLAGS_stun_server, ':');
95 CHECK_EQ(pieces.size(), 2u);
96
97 addrinfo *infos;
98 CHECK(!getaddrinfo(pieces[0].c_str(), pieces[1].c_str(), &kHints, &infos));
99
100 sockaddr_storage stunAddr;
101 memcpy(&stunAddr, infos->ai_addr, infos->ai_addrlen);
102
103 freeaddrinfo(infos);
104 infos = nullptr;
105
106 CHECK_EQ(stunAddr.ss_family, AF_INET);
107
108 std::mutex lock;
109 std::condition_variable cond;
110 bool done = false;
111
112 auto runLoop = std::make_shared<RunLoop>("STUN");
113
114 auto stunClient = std::make_shared<STUNClient>(
115 runLoop,
116 reinterpret_cast<const sockaddr_in &>(stunAddr),
117 [&lock, &cond, &done](int result, const std::string &myPublicIp) {
118 CHECK(!result);
119 LOG(INFO)
120 << "STUN-discovered public IP: " << myPublicIp;
121
122 FLAGS_public_ip = myPublicIp;
123
124 std::lock_guard autoLock(lock);
125 done = true;
126 cond.notify_all();
127 });
128
129 stunClient->run();
130
131 std::unique_lock autoLock(lock);
132 while (!done) {
133 cond.wait(autoLock);
134 }
135 }
136
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800137 auto runLoop = RunLoop::main();
138
139 auto state = std::make_shared<ServerState>(
140 runLoop, ServerState::VideoFormat::VP8);
141
Jorge E. Moreiraf0e3d8a2020-01-08 16:39:48 -0800142 auto port = FLAGS_http_server_port;
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800143
144 auto httpd = std::make_shared<HTTPServer>(
145 runLoop,
146 "0.0.0.0",
147 port,
Jorge E. Moreiraf0e3d8a2020-01-08 16:39:48 -0800148 FLAGS_use_secure_http
149 ? ServerSocket::TransportType::TLS
150 : ServerSocket::TransportType::TCP,
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800151 FLAGS_certs_dir + "/server.crt",
152 FLAGS_certs_dir + "/server.key");
153
154 const std::string index_html = FLAGS_assets_dir + "/index.html";
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800155 const std::string logcat_js = FLAGS_assets_dir + "/js/logcat.js";
Roger Ellisaeec7402020-02-18 17:24:04 -0800156 const std::string receive_js = FLAGS_assets_dir + "/js/receive.js";
157 const std::string viewpane_js = FLAGS_assets_dir + "/js/viewpane.js";
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800158 const std::string style_css = FLAGS_assets_dir + "/style.css";
159
160 httpd->addStaticFile("/index.html", index_html.c_str());
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800161 httpd->addStaticFile("/js/logcat.js", logcat_js.c_str());
Roger Ellisaeec7402020-02-18 17:24:04 -0800162 httpd->addStaticFile("/js/receive.js", receive_js.c_str());
163 httpd->addStaticFile("/js/viewpane.js", viewpane_js.c_str());
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800164 httpd->addStaticFile("/style.css", style_css.c_str());
165
166 httpd->addWebSocketHandlerFactory(
167 "/control",
168 [runLoop, state]{
169 auto id = state->acquireHandlerId();
170
171 auto handler =
172 std::make_shared<MyWebSocketHandler>(runLoop, state, id);
173
174 return std::make_pair(0 /* OK */, handler);
175 });
176
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800177 if (!FLAGS_adb.empty()) {
178 httpd->addWebSocketHandlerFactory(
179 "/control_adb",
180 [runLoop]{
181 auto handler = std::make_shared<AdbWebSocketHandler>(
182 runLoop, FLAGS_adb);
183
184 handler->run();
185
186 return std::make_pair(0 /* OK */, handler);
187 });
188 }
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800189
190 httpd->run();
Jorge E. Moreiraa18ff1a2019-12-17 18:20:56 -0800191 runLoop->run();
192
193 return 0;
194}