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