1 //
2 // Copyright (C) 2021 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 #include "host/frontend/webrtc/client_server.h"
17 #include <android-base/logging.h>
18
19 namespace cuttlefish {
20 struct ClientFilesServer::Config {
Configcuttlefish::ClientFilesServer::Config21 Config(const std::string& dir)
22 : dir_(dir),
23 mount_({
24 .mount_next = nullptr, /* linked-list "next" */
25 .mountpoint = "/", /* mountpoint URL */
26 .origin = dir_.c_str(), /* serve from dir */
27 .def = "client.html", /* default filename */
28 .protocol = nullptr,
29 .cgienv = nullptr,
30 .extra_mimetypes = nullptr,
31 .interpret = nullptr,
32 .cgi_timeout = 0,
33 .cache_max_age = 0,
34 .auth_mask = 0,
35 .cache_reusable = 0,
36 .cache_revalidate = 0,
37 .cache_intermediaries = 0,
38 .origin_protocol = LWSMPRO_FILE, /* files in a dir */
39 .mountpoint_len = 1, /* char count */
40 .basic_auth_login_file = nullptr,
41 }) {
42 memset(&info_, 0, sizeof info_);
43 info_.port = 0; // let the kernel select an available port
44 info_.iface = "127.0.0.1"; // listen only on localhost
45 info_.mounts = &mount_;
46 }
47
48 std::string dir_;
49 lws_http_mount mount_;
50 lws_context_creation_info info_;
51 };
52
ClientFilesServer(std::unique_ptr<Config> config,lws_context * context)53 ClientFilesServer::ClientFilesServer(std::unique_ptr<Config> config,
54 lws_context* context)
55 : config_(std::move(config)),
56 context_(context),
57 running_(true),
58 server_thread_([this]() { Serve(); }) {}
59
~ClientFilesServer()60 ClientFilesServer::~ClientFilesServer() {
61 if (running_) {
62 running_ = false;
63 server_thread_.join();
64 }
65 if (context_) {
66 // Release the port and other resources
67 lws_context_destroy(context_);
68 }
69 }
70
New(const std::string & dir)71 std::unique_ptr<ClientFilesServer> ClientFilesServer::New(
72 const std::string& dir) {
73 std::unique_ptr<Config> conf(new Config(dir));
74 if (!conf) {
75 return nullptr;
76 }
77
78 auto ctx = lws_create_context(&conf->info_);
79 if (!ctx) {
80 LOG(ERROR) << "Failed to create lws context";
81 return nullptr;
82 }
83 return std::unique_ptr<ClientFilesServer>(
84 new ClientFilesServer(std::move(conf), ctx));
85 }
86
port() const87 int ClientFilesServer::port() const {
88 // Get the port for the first (and only) vhost.
89 return lws_get_vhost_listen_port(lws_get_vhost_by_name(context_, "default"));
90 }
91
Serve()92 void ClientFilesServer::Serve() {
93 while (running_) {
94 if (lws_service(context_, 0) < 0) {
95 LOG(ERROR) << "Error serving client files";
96 return;
97 }
98 }
99 }
100 } // namespace cuttlefish
101
102