xref: /aosp_15_r20/external/openscreen/osp/demo/osp_demo.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include <getopt.h>
6*3f982cf4SFabien Sanglard #include <poll.h>
7*3f982cf4SFabien Sanglard #include <signal.h>
8*3f982cf4SFabien Sanglard #include <unistd.h>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include <algorithm>
11*3f982cf4SFabien Sanglard #include <iostream>
12*3f982cf4SFabien Sanglard #include <memory>
13*3f982cf4SFabien Sanglard #include <string>
14*3f982cf4SFabien Sanglard #include <vector>
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard #include "absl/strings/string_view.h"
17*3f982cf4SFabien Sanglard #include "osp/msgs/osp_messages.h"
18*3f982cf4SFabien Sanglard #include "osp/public/mdns_service_listener_factory.h"
19*3f982cf4SFabien Sanglard #include "osp/public/message_demuxer.h"
20*3f982cf4SFabien Sanglard #include "osp/public/network_service_manager.h"
21*3f982cf4SFabien Sanglard #include "osp/public/presentation/presentation_controller.h"
22*3f982cf4SFabien Sanglard #include "osp/public/presentation/presentation_receiver.h"
23*3f982cf4SFabien Sanglard #include "osp/public/protocol_connection_client.h"
24*3f982cf4SFabien Sanglard #include "osp/public/protocol_connection_client_factory.h"
25*3f982cf4SFabien Sanglard #include "osp/public/protocol_connection_server.h"
26*3f982cf4SFabien Sanglard #include "osp/public/protocol_connection_server_factory.h"
27*3f982cf4SFabien Sanglard #include "osp/public/service_listener.h"
28*3f982cf4SFabien Sanglard #include "osp/public/service_publisher.h"
29*3f982cf4SFabien Sanglard #include "osp/public/service_publisher_factory.h"
30*3f982cf4SFabien Sanglard #include "platform/api/network_interface.h"
31*3f982cf4SFabien Sanglard #include "platform/api/time.h"
32*3f982cf4SFabien Sanglard #include "platform/impl/logging.h"
33*3f982cf4SFabien Sanglard #include "platform/impl/platform_client_posix.h"
34*3f982cf4SFabien Sanglard #include "platform/impl/task_runner.h"
35*3f982cf4SFabien Sanglard #include "platform/impl/text_trace_logging_platform.h"
36*3f982cf4SFabien Sanglard #include "platform/impl/udp_socket_reader_posix.h"
37*3f982cf4SFabien Sanglard #include "third_party/tinycbor/src/src/cbor.h"
38*3f982cf4SFabien Sanglard #include "util/trace_logging.h"
39*3f982cf4SFabien Sanglard 
40*3f982cf4SFabien Sanglard namespace {
41*3f982cf4SFabien Sanglard 
42*3f982cf4SFabien Sanglard const char* kReceiverLogFilename = "_recv_fifo";
43*3f982cf4SFabien Sanglard const char* kControllerLogFilename = "_cntl_fifo";
44*3f982cf4SFabien Sanglard 
45*3f982cf4SFabien Sanglard bool g_done = false;
46*3f982cf4SFabien Sanglard bool g_dump_services = false;
47*3f982cf4SFabien Sanglard 
sigusr1_dump_services(int)48*3f982cf4SFabien Sanglard void sigusr1_dump_services(int) {
49*3f982cf4SFabien Sanglard   g_dump_services = true;
50*3f982cf4SFabien Sanglard }
51*3f982cf4SFabien Sanglard 
sigint_stop(int)52*3f982cf4SFabien Sanglard void sigint_stop(int) {
53*3f982cf4SFabien Sanglard   OSP_LOG_INFO << "caught SIGINT, exiting...";
54*3f982cf4SFabien Sanglard   g_done = true;
55*3f982cf4SFabien Sanglard }
56*3f982cf4SFabien Sanglard 
SignalThings()57*3f982cf4SFabien Sanglard void SignalThings() {
58*3f982cf4SFabien Sanglard   struct sigaction usr1_sa;
59*3f982cf4SFabien Sanglard   struct sigaction int_sa;
60*3f982cf4SFabien Sanglard   struct sigaction unused;
61*3f982cf4SFabien Sanglard 
62*3f982cf4SFabien Sanglard   usr1_sa.sa_handler = &sigusr1_dump_services;
63*3f982cf4SFabien Sanglard   sigemptyset(&usr1_sa.sa_mask);
64*3f982cf4SFabien Sanglard   usr1_sa.sa_flags = 0;
65*3f982cf4SFabien Sanglard 
66*3f982cf4SFabien Sanglard   int_sa.sa_handler = &sigint_stop;
67*3f982cf4SFabien Sanglard   sigemptyset(&int_sa.sa_mask);
68*3f982cf4SFabien Sanglard   int_sa.sa_flags = 0;
69*3f982cf4SFabien Sanglard 
70*3f982cf4SFabien Sanglard   sigaction(SIGUSR1, &usr1_sa, &unused);
71*3f982cf4SFabien Sanglard   sigaction(SIGINT, &int_sa, &unused);
72*3f982cf4SFabien Sanglard 
73*3f982cf4SFabien Sanglard   OSP_LOG_INFO << "signal handlers setup" << std::endl << "pid: " << getpid();
74*3f982cf4SFabien Sanglard }
75*3f982cf4SFabien Sanglard 
76*3f982cf4SFabien Sanglard }  // namespace
77*3f982cf4SFabien Sanglard 
78*3f982cf4SFabien Sanglard namespace openscreen {
79*3f982cf4SFabien Sanglard namespace osp {
80*3f982cf4SFabien Sanglard 
81*3f982cf4SFabien Sanglard class DemoListenerObserver final : public ServiceListener::Observer {
82*3f982cf4SFabien Sanglard  public:
83*3f982cf4SFabien Sanglard   ~DemoListenerObserver() override = default;
OnStarted()84*3f982cf4SFabien Sanglard   void OnStarted() override { OSP_LOG_INFO << "listener started!"; }
OnStopped()85*3f982cf4SFabien Sanglard   void OnStopped() override { OSP_LOG_INFO << "listener stopped!"; }
OnSuspended()86*3f982cf4SFabien Sanglard   void OnSuspended() override { OSP_LOG_INFO << "listener suspended!"; }
OnSearching()87*3f982cf4SFabien Sanglard   void OnSearching() override { OSP_LOG_INFO << "listener searching!"; }
88*3f982cf4SFabien Sanglard 
OnReceiverAdded(const ServiceInfo & info)89*3f982cf4SFabien Sanglard   void OnReceiverAdded(const ServiceInfo& info) override {
90*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "found! " << info.friendly_name;
91*3f982cf4SFabien Sanglard   }
OnReceiverChanged(const ServiceInfo & info)92*3f982cf4SFabien Sanglard   void OnReceiverChanged(const ServiceInfo& info) override {
93*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "changed! " << info.friendly_name;
94*3f982cf4SFabien Sanglard   }
OnReceiverRemoved(const ServiceInfo & info)95*3f982cf4SFabien Sanglard   void OnReceiverRemoved(const ServiceInfo& info) override {
96*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "removed! " << info.friendly_name;
97*3f982cf4SFabien Sanglard   }
OnAllReceiversRemoved()98*3f982cf4SFabien Sanglard   void OnAllReceiversRemoved() override { OSP_LOG_INFO << "all removed!"; }
OnError(ServiceListenerError)99*3f982cf4SFabien Sanglard   void OnError(ServiceListenerError) override {}
OnMetrics(ServiceListener::Metrics)100*3f982cf4SFabien Sanglard   void OnMetrics(ServiceListener::Metrics) override {}
101*3f982cf4SFabien Sanglard };
102*3f982cf4SFabien Sanglard 
SanitizeServiceId(absl::string_view service_id)103*3f982cf4SFabien Sanglard std::string SanitizeServiceId(absl::string_view service_id) {
104*3f982cf4SFabien Sanglard   std::string safe_service_id(service_id);
105*3f982cf4SFabien Sanglard   for (auto& c : safe_service_id) {
106*3f982cf4SFabien Sanglard     if (c < ' ' || c > '~') {
107*3f982cf4SFabien Sanglard       c = '.';
108*3f982cf4SFabien Sanglard     }
109*3f982cf4SFabien Sanglard   }
110*3f982cf4SFabien Sanglard   return safe_service_id;
111*3f982cf4SFabien Sanglard }
112*3f982cf4SFabien Sanglard 
113*3f982cf4SFabien Sanglard class DemoReceiverObserver final : public ReceiverObserver {
114*3f982cf4SFabien Sanglard  public:
115*3f982cf4SFabien Sanglard   ~DemoReceiverObserver() override = default;
116*3f982cf4SFabien Sanglard 
OnRequestFailed(const std::string & presentation_url,const std::string & service_id)117*3f982cf4SFabien Sanglard   void OnRequestFailed(const std::string& presentation_url,
118*3f982cf4SFabien Sanglard                        const std::string& service_id) override {
119*3f982cf4SFabien Sanglard     std::string safe_service_id = SanitizeServiceId(service_id);
120*3f982cf4SFabien Sanglard     OSP_LOG_WARN << "request failed: (" << presentation_url << ", "
121*3f982cf4SFabien Sanglard                  << safe_service_id << ")";
122*3f982cf4SFabien Sanglard   }
OnReceiverAvailable(const std::string & presentation_url,const std::string & service_id)123*3f982cf4SFabien Sanglard   void OnReceiverAvailable(const std::string& presentation_url,
124*3f982cf4SFabien Sanglard                            const std::string& service_id) override {
125*3f982cf4SFabien Sanglard     std::string safe_service_id = SanitizeServiceId(service_id);
126*3f982cf4SFabien Sanglard     safe_service_ids_.emplace(safe_service_id, service_id);
127*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "available! " << safe_service_id;
128*3f982cf4SFabien Sanglard   }
OnReceiverUnavailable(const std::string & presentation_url,const std::string & service_id)129*3f982cf4SFabien Sanglard   void OnReceiverUnavailable(const std::string& presentation_url,
130*3f982cf4SFabien Sanglard                              const std::string& service_id) override {
131*3f982cf4SFabien Sanglard     std::string safe_service_id = SanitizeServiceId(service_id);
132*3f982cf4SFabien Sanglard     safe_service_ids_.erase(safe_service_id);
133*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "unavailable! " << safe_service_id;
134*3f982cf4SFabien Sanglard   }
135*3f982cf4SFabien Sanglard 
GetServiceId(const std::string & safe_service_id)136*3f982cf4SFabien Sanglard   const std::string& GetServiceId(const std::string& safe_service_id) {
137*3f982cf4SFabien Sanglard     OSP_DCHECK(safe_service_ids_.find(safe_service_id) !=
138*3f982cf4SFabien Sanglard                safe_service_ids_.end())
139*3f982cf4SFabien Sanglard         << safe_service_id << " not found in map";
140*3f982cf4SFabien Sanglard     return safe_service_ids_[safe_service_id];
141*3f982cf4SFabien Sanglard   }
142*3f982cf4SFabien Sanglard 
143*3f982cf4SFabien Sanglard  private:
144*3f982cf4SFabien Sanglard   std::map<std::string, std::string> safe_service_ids_;
145*3f982cf4SFabien Sanglard };
146*3f982cf4SFabien Sanglard 
147*3f982cf4SFabien Sanglard class DemoPublisherObserver final : public ServicePublisher::Observer {
148*3f982cf4SFabien Sanglard  public:
149*3f982cf4SFabien Sanglard   ~DemoPublisherObserver() override = default;
150*3f982cf4SFabien Sanglard 
OnStarted()151*3f982cf4SFabien Sanglard   void OnStarted() override { OSP_LOG_INFO << "publisher started!"; }
OnStopped()152*3f982cf4SFabien Sanglard   void OnStopped() override { OSP_LOG_INFO << "publisher stopped!"; }
OnSuspended()153*3f982cf4SFabien Sanglard   void OnSuspended() override { OSP_LOG_INFO << "publisher suspended!"; }
154*3f982cf4SFabien Sanglard 
OnError(Error error)155*3f982cf4SFabien Sanglard   void OnError(Error error) override {
156*3f982cf4SFabien Sanglard     OSP_LOG_ERROR << "publisher error: " << error;
157*3f982cf4SFabien Sanglard   }
OnMetrics(ServicePublisher::Metrics)158*3f982cf4SFabien Sanglard   void OnMetrics(ServicePublisher::Metrics) override {}
159*3f982cf4SFabien Sanglard };
160*3f982cf4SFabien Sanglard 
161*3f982cf4SFabien Sanglard class DemoConnectionClientObserver final
162*3f982cf4SFabien Sanglard     : public ProtocolConnectionServiceObserver {
163*3f982cf4SFabien Sanglard  public:
164*3f982cf4SFabien Sanglard   ~DemoConnectionClientObserver() override = default;
OnRunning()165*3f982cf4SFabien Sanglard   void OnRunning() override {}
OnStopped()166*3f982cf4SFabien Sanglard   void OnStopped() override {}
167*3f982cf4SFabien Sanglard 
OnMetrics(const NetworkMetrics & metrics)168*3f982cf4SFabien Sanglard   void OnMetrics(const NetworkMetrics& metrics) override {}
OnError(const Error & error)169*3f982cf4SFabien Sanglard   void OnError(const Error& error) override {}
170*3f982cf4SFabien Sanglard };
171*3f982cf4SFabien Sanglard 
172*3f982cf4SFabien Sanglard class DemoConnectionServerObserver final
173*3f982cf4SFabien Sanglard     : public ProtocolConnectionServer::Observer {
174*3f982cf4SFabien Sanglard  public:
175*3f982cf4SFabien Sanglard   class ConnectionObserver final : public ProtocolConnection::Observer {
176*3f982cf4SFabien Sanglard    public:
ConnectionObserver(DemoConnectionServerObserver * parent)177*3f982cf4SFabien Sanglard     explicit ConnectionObserver(DemoConnectionServerObserver* parent)
178*3f982cf4SFabien Sanglard         : parent_(parent) {}
179*3f982cf4SFabien Sanglard     ~ConnectionObserver() override = default;
180*3f982cf4SFabien Sanglard 
OnConnectionClosed(const ProtocolConnection & connection)181*3f982cf4SFabien Sanglard     void OnConnectionClosed(const ProtocolConnection& connection) override {
182*3f982cf4SFabien Sanglard       auto& connections = parent_->connections_;
183*3f982cf4SFabien Sanglard       connections.erase(
184*3f982cf4SFabien Sanglard           std::remove_if(
185*3f982cf4SFabien Sanglard               connections.begin(), connections.end(),
186*3f982cf4SFabien Sanglard               [this](const std::pair<std::unique_ptr<ConnectionObserver>,
187*3f982cf4SFabien Sanglard                                      std::unique_ptr<ProtocolConnection>>& p) {
188*3f982cf4SFabien Sanglard                 return p.first.get() == this;
189*3f982cf4SFabien Sanglard               }),
190*3f982cf4SFabien Sanglard           connections.end());
191*3f982cf4SFabien Sanglard     }
192*3f982cf4SFabien Sanglard 
193*3f982cf4SFabien Sanglard    private:
194*3f982cf4SFabien Sanglard     DemoConnectionServerObserver* const parent_;
195*3f982cf4SFabien Sanglard   };
196*3f982cf4SFabien Sanglard 
197*3f982cf4SFabien Sanglard   ~DemoConnectionServerObserver() override = default;
198*3f982cf4SFabien Sanglard 
OnRunning()199*3f982cf4SFabien Sanglard   void OnRunning() override {}
OnStopped()200*3f982cf4SFabien Sanglard   void OnStopped() override {}
OnSuspended()201*3f982cf4SFabien Sanglard   void OnSuspended() override {}
202*3f982cf4SFabien Sanglard 
OnMetrics(const NetworkMetrics & metrics)203*3f982cf4SFabien Sanglard   void OnMetrics(const NetworkMetrics& metrics) override {}
OnError(const Error & error)204*3f982cf4SFabien Sanglard   void OnError(const Error& error) override {}
205*3f982cf4SFabien Sanglard 
OnIncomingConnection(std::unique_ptr<ProtocolConnection> connection)206*3f982cf4SFabien Sanglard   void OnIncomingConnection(
207*3f982cf4SFabien Sanglard       std::unique_ptr<ProtocolConnection> connection) override {
208*3f982cf4SFabien Sanglard     auto observer = std::make_unique<ConnectionObserver>(this);
209*3f982cf4SFabien Sanglard     connection->SetObserver(observer.get());
210*3f982cf4SFabien Sanglard     connections_.emplace_back(std::move(observer), std::move(connection));
211*3f982cf4SFabien Sanglard     connections_.back().second->CloseWriteEnd();
212*3f982cf4SFabien Sanglard   }
213*3f982cf4SFabien Sanglard 
214*3f982cf4SFabien Sanglard  private:
215*3f982cf4SFabien Sanglard   std::vector<std::pair<std::unique_ptr<ConnectionObserver>,
216*3f982cf4SFabien Sanglard                         std::unique_ptr<ProtocolConnection>>>
217*3f982cf4SFabien Sanglard       connections_;
218*3f982cf4SFabien Sanglard };
219*3f982cf4SFabien Sanglard 
220*3f982cf4SFabien Sanglard class DemoRequestDelegate final : public RequestDelegate {
221*3f982cf4SFabien Sanglard  public:
222*3f982cf4SFabien Sanglard   DemoRequestDelegate() = default;
223*3f982cf4SFabien Sanglard   ~DemoRequestDelegate() override = default;
224*3f982cf4SFabien Sanglard 
OnConnection(std::unique_ptr<Connection> connection)225*3f982cf4SFabien Sanglard   void OnConnection(std::unique_ptr<Connection> connection) override {
226*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "request successful";
227*3f982cf4SFabien Sanglard     this->connection = std::move(connection);
228*3f982cf4SFabien Sanglard   }
229*3f982cf4SFabien Sanglard 
OnError(const Error & error)230*3f982cf4SFabien Sanglard   void OnError(const Error& error) override {
231*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "on request error";
232*3f982cf4SFabien Sanglard   }
233*3f982cf4SFabien Sanglard 
234*3f982cf4SFabien Sanglard   std::unique_ptr<Connection> connection;
235*3f982cf4SFabien Sanglard };
236*3f982cf4SFabien Sanglard 
237*3f982cf4SFabien Sanglard class DemoConnectionDelegate final : public Connection::Delegate {
238*3f982cf4SFabien Sanglard  public:
239*3f982cf4SFabien Sanglard   DemoConnectionDelegate() = default;
240*3f982cf4SFabien Sanglard   ~DemoConnectionDelegate() override = default;
241*3f982cf4SFabien Sanglard 
OnConnected()242*3f982cf4SFabien Sanglard   void OnConnected() override {
243*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "presentation connection connected";
244*3f982cf4SFabien Sanglard   }
OnClosedByRemote()245*3f982cf4SFabien Sanglard   void OnClosedByRemote() override {
246*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "presentation connection closed by remote";
247*3f982cf4SFabien Sanglard   }
OnDiscarded()248*3f982cf4SFabien Sanglard   void OnDiscarded() override {}
OnError(const absl::string_view message)249*3f982cf4SFabien Sanglard   void OnError(const absl::string_view message) override {}
OnTerminated()250*3f982cf4SFabien Sanglard   void OnTerminated() override { OSP_LOG_INFO << "presentation terminated"; }
251*3f982cf4SFabien Sanglard 
OnStringMessage(absl::string_view message)252*3f982cf4SFabien Sanglard   void OnStringMessage(absl::string_view message) override {
253*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "got message: " << message;
254*3f982cf4SFabien Sanglard   }
OnBinaryMessage(const std::vector<uint8_t> & data)255*3f982cf4SFabien Sanglard   void OnBinaryMessage(const std::vector<uint8_t>& data) override {}
256*3f982cf4SFabien Sanglard };
257*3f982cf4SFabien Sanglard 
258*3f982cf4SFabien Sanglard class DemoReceiverConnectionDelegate final : public Connection::Delegate {
259*3f982cf4SFabien Sanglard  public:
260*3f982cf4SFabien Sanglard   DemoReceiverConnectionDelegate() = default;
261*3f982cf4SFabien Sanglard   ~DemoReceiverConnectionDelegate() override = default;
262*3f982cf4SFabien Sanglard 
OnConnected()263*3f982cf4SFabien Sanglard   void OnConnected() override {
264*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "presentation connection connected";
265*3f982cf4SFabien Sanglard   }
OnClosedByRemote()266*3f982cf4SFabien Sanglard   void OnClosedByRemote() override {
267*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "presentation connection closed by remote";
268*3f982cf4SFabien Sanglard   }
OnDiscarded()269*3f982cf4SFabien Sanglard   void OnDiscarded() override {}
OnError(const absl::string_view message)270*3f982cf4SFabien Sanglard   void OnError(const absl::string_view message) override {}
OnTerminated()271*3f982cf4SFabien Sanglard   void OnTerminated() override { OSP_LOG_INFO << "presentation terminated"; }
272*3f982cf4SFabien Sanglard 
OnStringMessage(const absl::string_view message)273*3f982cf4SFabien Sanglard   void OnStringMessage(const absl::string_view message) override {
274*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "got message: " << message;
275*3f982cf4SFabien Sanglard     connection->SendString("--echo-- " + std::string(message));
276*3f982cf4SFabien Sanglard   }
OnBinaryMessage(const std::vector<uint8_t> & data)277*3f982cf4SFabien Sanglard   void OnBinaryMessage(const std::vector<uint8_t>& data) override {}
278*3f982cf4SFabien Sanglard 
279*3f982cf4SFabien Sanglard   Connection* connection;
280*3f982cf4SFabien Sanglard };
281*3f982cf4SFabien Sanglard 
282*3f982cf4SFabien Sanglard class DemoReceiverDelegate final : public ReceiverDelegate {
283*3f982cf4SFabien Sanglard  public:
284*3f982cf4SFabien Sanglard   ~DemoReceiverDelegate() override = default;
285*3f982cf4SFabien Sanglard 
OnUrlAvailabilityRequest(uint64_t client_id,uint64_t request_duration,std::vector<std::string> urls)286*3f982cf4SFabien Sanglard   std::vector<msgs::UrlAvailability> OnUrlAvailabilityRequest(
287*3f982cf4SFabien Sanglard       uint64_t client_id,
288*3f982cf4SFabien Sanglard       uint64_t request_duration,
289*3f982cf4SFabien Sanglard       std::vector<std::string> urls) override {
290*3f982cf4SFabien Sanglard     std::vector<msgs::UrlAvailability> result;
291*3f982cf4SFabien Sanglard     result.reserve(urls.size());
292*3f982cf4SFabien Sanglard     for (const auto& url : urls) {
293*3f982cf4SFabien Sanglard       OSP_LOG_INFO << "got availability request for: " << url;
294*3f982cf4SFabien Sanglard       result.push_back(msgs::UrlAvailability::kAvailable);
295*3f982cf4SFabien Sanglard     }
296*3f982cf4SFabien Sanglard     return result;
297*3f982cf4SFabien Sanglard   }
298*3f982cf4SFabien Sanglard 
StartPresentation(const Connection::PresentationInfo & info,uint64_t source_id,const std::vector<msgs::HttpHeader> & http_headers)299*3f982cf4SFabien Sanglard   bool StartPresentation(
300*3f982cf4SFabien Sanglard       const Connection::PresentationInfo& info,
301*3f982cf4SFabien Sanglard       uint64_t source_id,
302*3f982cf4SFabien Sanglard       const std::vector<msgs::HttpHeader>& http_headers) override {
303*3f982cf4SFabien Sanglard     presentation_id = info.id;
304*3f982cf4SFabien Sanglard     connection = std::make_unique<Connection>(info, &cd, Receiver::Get());
305*3f982cf4SFabien Sanglard     cd.connection = connection.get();
306*3f982cf4SFabien Sanglard     Receiver::Get()->OnPresentationStarted(info.id, connection.get(),
307*3f982cf4SFabien Sanglard                                            ResponseResult::kSuccess);
308*3f982cf4SFabien Sanglard     return true;
309*3f982cf4SFabien Sanglard   }
310*3f982cf4SFabien Sanglard 
ConnectToPresentation(uint64_t request_id,const std::string & id,uint64_t source_id)311*3f982cf4SFabien Sanglard   bool ConnectToPresentation(uint64_t request_id,
312*3f982cf4SFabien Sanglard                              const std::string& id,
313*3f982cf4SFabien Sanglard                              uint64_t source_id) override {
314*3f982cf4SFabien Sanglard     connection = std::make_unique<Connection>(
315*3f982cf4SFabien Sanglard         Connection::PresentationInfo{id, connection->presentation_info().url},
316*3f982cf4SFabien Sanglard         &cd, Receiver::Get());
317*3f982cf4SFabien Sanglard     cd.connection = connection.get();
318*3f982cf4SFabien Sanglard     Receiver::Get()->OnConnectionCreated(request_id, connection.get(),
319*3f982cf4SFabien Sanglard                                          ResponseResult::kSuccess);
320*3f982cf4SFabien Sanglard     return true;
321*3f982cf4SFabien Sanglard   }
322*3f982cf4SFabien Sanglard 
TerminatePresentation(const std::string & id,TerminationReason reason)323*3f982cf4SFabien Sanglard   void TerminatePresentation(const std::string& id,
324*3f982cf4SFabien Sanglard                              TerminationReason reason) override {
325*3f982cf4SFabien Sanglard     Receiver::Get()->OnPresentationTerminated(id, reason);
326*3f982cf4SFabien Sanglard   }
327*3f982cf4SFabien Sanglard 
328*3f982cf4SFabien Sanglard   std::string presentation_id;
329*3f982cf4SFabien Sanglard   std::unique_ptr<Connection> connection;
330*3f982cf4SFabien Sanglard   DemoReceiverConnectionDelegate cd;
331*3f982cf4SFabien Sanglard };
332*3f982cf4SFabien Sanglard 
333*3f982cf4SFabien Sanglard struct CommandLineSplit {
334*3f982cf4SFabien Sanglard   std::string command;
335*3f982cf4SFabien Sanglard   std::string argument_tail;
336*3f982cf4SFabien Sanglard };
337*3f982cf4SFabien Sanglard 
SeparateCommandFromArguments(const std::string & line)338*3f982cf4SFabien Sanglard CommandLineSplit SeparateCommandFromArguments(const std::string& line) {
339*3f982cf4SFabien Sanglard   size_t split_index = line.find_first_of(' ');
340*3f982cf4SFabien Sanglard   // NOTE: |split_index| can be std::string::npos because not all commands
341*3f982cf4SFabien Sanglard   // accept arguments.
342*3f982cf4SFabien Sanglard   std::string command = line.substr(0, split_index);
343*3f982cf4SFabien Sanglard   std::string argument_tail =
344*3f982cf4SFabien Sanglard       split_index < line.size() ? line.substr(split_index + 1) : std::string();
345*3f982cf4SFabien Sanglard   return {std::move(command), std::move(argument_tail)};
346*3f982cf4SFabien Sanglard }
347*3f982cf4SFabien Sanglard 
348*3f982cf4SFabien Sanglard struct CommandWaitResult {
349*3f982cf4SFabien Sanglard   bool done;
350*3f982cf4SFabien Sanglard   CommandLineSplit command_line;
351*3f982cf4SFabien Sanglard };
352*3f982cf4SFabien Sanglard 
WaitForCommand(pollfd * pollfd)353*3f982cf4SFabien Sanglard CommandWaitResult WaitForCommand(pollfd* pollfd) {
354*3f982cf4SFabien Sanglard   while (poll(pollfd, 1, 10) >= 0) {
355*3f982cf4SFabien Sanglard     if (g_done) {
356*3f982cf4SFabien Sanglard       return {true};
357*3f982cf4SFabien Sanglard     }
358*3f982cf4SFabien Sanglard 
359*3f982cf4SFabien Sanglard     if (pollfd->revents == 0) {
360*3f982cf4SFabien Sanglard       continue;
361*3f982cf4SFabien Sanglard     } else if (pollfd->revents & (POLLERR | POLLHUP)) {
362*3f982cf4SFabien Sanglard       return {true};
363*3f982cf4SFabien Sanglard     }
364*3f982cf4SFabien Sanglard 
365*3f982cf4SFabien Sanglard     std::string line;
366*3f982cf4SFabien Sanglard     if (!std::getline(std::cin, line)) {
367*3f982cf4SFabien Sanglard       return {true};
368*3f982cf4SFabien Sanglard     }
369*3f982cf4SFabien Sanglard 
370*3f982cf4SFabien Sanglard     CommandWaitResult result;
371*3f982cf4SFabien Sanglard     result.done = false;
372*3f982cf4SFabien Sanglard     result.command_line = SeparateCommandFromArguments(line);
373*3f982cf4SFabien Sanglard     return result;
374*3f982cf4SFabien Sanglard   }
375*3f982cf4SFabien Sanglard   return {true};
376*3f982cf4SFabien Sanglard }
377*3f982cf4SFabien Sanglard 
RunControllerPollLoop(Controller * controller)378*3f982cf4SFabien Sanglard void RunControllerPollLoop(Controller* controller) {
379*3f982cf4SFabien Sanglard   DemoReceiverObserver receiver_observer;
380*3f982cf4SFabien Sanglard   DemoRequestDelegate request_delegate;
381*3f982cf4SFabien Sanglard   DemoConnectionDelegate connection_delegate;
382*3f982cf4SFabien Sanglard   Controller::ReceiverWatch watch;
383*3f982cf4SFabien Sanglard   Controller::ConnectRequest connect_request;
384*3f982cf4SFabien Sanglard 
385*3f982cf4SFabien Sanglard   pollfd stdin_pollfd{STDIN_FILENO, POLLIN};
386*3f982cf4SFabien Sanglard   while (true) {
387*3f982cf4SFabien Sanglard     OSP_CHECK_EQ(write(STDOUT_FILENO, "$ ", 2), 2);
388*3f982cf4SFabien Sanglard 
389*3f982cf4SFabien Sanglard     CommandWaitResult command_result = WaitForCommand(&stdin_pollfd);
390*3f982cf4SFabien Sanglard     if (command_result.done) {
391*3f982cf4SFabien Sanglard       break;
392*3f982cf4SFabien Sanglard     }
393*3f982cf4SFabien Sanglard 
394*3f982cf4SFabien Sanglard     if (command_result.command_line.command == "avail") {
395*3f982cf4SFabien Sanglard       watch = controller->RegisterReceiverWatch(
396*3f982cf4SFabien Sanglard           {std::string(command_result.command_line.argument_tail)},
397*3f982cf4SFabien Sanglard           &receiver_observer);
398*3f982cf4SFabien Sanglard     } else if (command_result.command_line.command == "start") {
399*3f982cf4SFabien Sanglard       const absl::string_view& argument_tail =
400*3f982cf4SFabien Sanglard           command_result.command_line.argument_tail;
401*3f982cf4SFabien Sanglard       size_t next_split = argument_tail.find_first_of(' ');
402*3f982cf4SFabien Sanglard       const std::string& service_id = receiver_observer.GetServiceId(
403*3f982cf4SFabien Sanglard           std::string(argument_tail.substr(next_split + 1)));
404*3f982cf4SFabien Sanglard       const std::string url =
405*3f982cf4SFabien Sanglard           static_cast<std::string>(argument_tail.substr(0, next_split));
406*3f982cf4SFabien Sanglard       connect_request = controller->StartPresentation(
407*3f982cf4SFabien Sanglard           url, service_id, &request_delegate, &connection_delegate);
408*3f982cf4SFabien Sanglard     } else if (command_result.command_line.command == "msg") {
409*3f982cf4SFabien Sanglard       request_delegate.connection->SendString(
410*3f982cf4SFabien Sanglard           command_result.command_line.argument_tail);
411*3f982cf4SFabien Sanglard     } else if (command_result.command_line.command == "close") {
412*3f982cf4SFabien Sanglard       request_delegate.connection->Close(Connection::CloseReason::kClosed);
413*3f982cf4SFabien Sanglard     } else if (command_result.command_line.command == "reconnect") {
414*3f982cf4SFabien Sanglard       connect_request = controller->ReconnectConnection(
415*3f982cf4SFabien Sanglard           std::move(request_delegate.connection), &request_delegate);
416*3f982cf4SFabien Sanglard     } else if (command_result.command_line.command == "term") {
417*3f982cf4SFabien Sanglard       request_delegate.connection->Terminate(
418*3f982cf4SFabien Sanglard           TerminationReason::kControllerTerminateCalled);
419*3f982cf4SFabien Sanglard     }
420*3f982cf4SFabien Sanglard   }
421*3f982cf4SFabien Sanglard 
422*3f982cf4SFabien Sanglard   watch = Controller::ReceiverWatch();
423*3f982cf4SFabien Sanglard }
424*3f982cf4SFabien Sanglard 
ListenerDemo()425*3f982cf4SFabien Sanglard void ListenerDemo() {
426*3f982cf4SFabien Sanglard   SignalThings();
427*3f982cf4SFabien Sanglard 
428*3f982cf4SFabien Sanglard   DemoListenerObserver listener_observer;
429*3f982cf4SFabien Sanglard   MdnsServiceListenerConfig listener_config;
430*3f982cf4SFabien Sanglard   auto mdns_listener = MdnsServiceListenerFactory::Create(
431*3f982cf4SFabien Sanglard       listener_config, &listener_observer,
432*3f982cf4SFabien Sanglard       PlatformClientPosix::GetInstance()->GetTaskRunner());
433*3f982cf4SFabien Sanglard 
434*3f982cf4SFabien Sanglard   MessageDemuxer demuxer(Clock::now, MessageDemuxer::kDefaultBufferLimit);
435*3f982cf4SFabien Sanglard   DemoConnectionClientObserver client_observer;
436*3f982cf4SFabien Sanglard   auto connection_client = ProtocolConnectionClientFactory::Create(
437*3f982cf4SFabien Sanglard       &demuxer, &client_observer,
438*3f982cf4SFabien Sanglard       PlatformClientPosix::GetInstance()->GetTaskRunner());
439*3f982cf4SFabien Sanglard 
440*3f982cf4SFabien Sanglard   auto* network_service = NetworkServiceManager::Create(
441*3f982cf4SFabien Sanglard       std::move(mdns_listener), nullptr, std::move(connection_client), nullptr);
442*3f982cf4SFabien Sanglard   auto controller = std::make_unique<Controller>(Clock::now);
443*3f982cf4SFabien Sanglard 
444*3f982cf4SFabien Sanglard   network_service->GetMdnsServiceListener()->Start();
445*3f982cf4SFabien Sanglard   network_service->GetProtocolConnectionClient()->Start();
446*3f982cf4SFabien Sanglard 
447*3f982cf4SFabien Sanglard   RunControllerPollLoop(controller.get());
448*3f982cf4SFabien Sanglard 
449*3f982cf4SFabien Sanglard   network_service->GetMdnsServiceListener()->Stop();
450*3f982cf4SFabien Sanglard   network_service->GetProtocolConnectionClient()->Stop();
451*3f982cf4SFabien Sanglard 
452*3f982cf4SFabien Sanglard   controller.reset();
453*3f982cf4SFabien Sanglard 
454*3f982cf4SFabien Sanglard   NetworkServiceManager::Dispose();
455*3f982cf4SFabien Sanglard }
456*3f982cf4SFabien Sanglard 
HandleReceiverCommand(absl::string_view command,absl::string_view argument_tail,DemoReceiverDelegate & delegate,NetworkServiceManager * manager)457*3f982cf4SFabien Sanglard void HandleReceiverCommand(absl::string_view command,
458*3f982cf4SFabien Sanglard                            absl::string_view argument_tail,
459*3f982cf4SFabien Sanglard                            DemoReceiverDelegate& delegate,
460*3f982cf4SFabien Sanglard                            NetworkServiceManager* manager) {
461*3f982cf4SFabien Sanglard   if (command == "avail") {
462*3f982cf4SFabien Sanglard     ServicePublisher* publisher = manager->GetServicePublisher();
463*3f982cf4SFabien Sanglard 
464*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "publisher->state() == "
465*3f982cf4SFabien Sanglard                  << static_cast<int>(publisher->state());
466*3f982cf4SFabien Sanglard 
467*3f982cf4SFabien Sanglard     if (publisher->state() == ServicePublisher::State::kSuspended) {
468*3f982cf4SFabien Sanglard       publisher->Resume();
469*3f982cf4SFabien Sanglard     } else {
470*3f982cf4SFabien Sanglard       publisher->Suspend();
471*3f982cf4SFabien Sanglard     }
472*3f982cf4SFabien Sanglard   } else if (command == "close") {
473*3f982cf4SFabien Sanglard     delegate.connection->Close(Connection::CloseReason::kClosed);
474*3f982cf4SFabien Sanglard   } else if (command == "msg") {
475*3f982cf4SFabien Sanglard     delegate.connection->SendString(argument_tail);
476*3f982cf4SFabien Sanglard   } else if (command == "term") {
477*3f982cf4SFabien Sanglard     Receiver::Get()->OnPresentationTerminated(
478*3f982cf4SFabien Sanglard         delegate.presentation_id, TerminationReason::kReceiverUserTerminated);
479*3f982cf4SFabien Sanglard   } else {
480*3f982cf4SFabien Sanglard     OSP_LOG_FATAL << "Received unknown receiver command: " << command;
481*3f982cf4SFabien Sanglard   }
482*3f982cf4SFabien Sanglard }
483*3f982cf4SFabien Sanglard 
RunReceiverPollLoop(pollfd & file_descriptor,NetworkServiceManager * manager,DemoReceiverDelegate & delegate)484*3f982cf4SFabien Sanglard void RunReceiverPollLoop(pollfd& file_descriptor,
485*3f982cf4SFabien Sanglard                          NetworkServiceManager* manager,
486*3f982cf4SFabien Sanglard                          DemoReceiverDelegate& delegate) {
487*3f982cf4SFabien Sanglard   pollfd stdin_pollfd{STDIN_FILENO, POLLIN};
488*3f982cf4SFabien Sanglard   while (true) {
489*3f982cf4SFabien Sanglard     OSP_CHECK_EQ(write(STDOUT_FILENO, "$ ", 2), 2);
490*3f982cf4SFabien Sanglard 
491*3f982cf4SFabien Sanglard     CommandWaitResult command_result = WaitForCommand(&stdin_pollfd);
492*3f982cf4SFabien Sanglard     if (command_result.done) {
493*3f982cf4SFabien Sanglard       break;
494*3f982cf4SFabien Sanglard     }
495*3f982cf4SFabien Sanglard 
496*3f982cf4SFabien Sanglard     HandleReceiverCommand(command_result.command_line.command,
497*3f982cf4SFabien Sanglard                           command_result.command_line.argument_tail, delegate,
498*3f982cf4SFabien Sanglard                           manager);
499*3f982cf4SFabien Sanglard   }
500*3f982cf4SFabien Sanglard }
501*3f982cf4SFabien Sanglard 
CleanupPublisherDemo(NetworkServiceManager * manager)502*3f982cf4SFabien Sanglard void CleanupPublisherDemo(NetworkServiceManager* manager) {
503*3f982cf4SFabien Sanglard   Receiver::Get()->SetReceiverDelegate(nullptr);
504*3f982cf4SFabien Sanglard   Receiver::Get()->Deinit();
505*3f982cf4SFabien Sanglard   manager->GetServicePublisher()->Stop();
506*3f982cf4SFabien Sanglard   manager->GetProtocolConnectionServer()->Stop();
507*3f982cf4SFabien Sanglard 
508*3f982cf4SFabien Sanglard   NetworkServiceManager::Dispose();
509*3f982cf4SFabien Sanglard }
510*3f982cf4SFabien Sanglard 
PublisherDemo(absl::string_view friendly_name)511*3f982cf4SFabien Sanglard void PublisherDemo(absl::string_view friendly_name) {
512*3f982cf4SFabien Sanglard   SignalThings();
513*3f982cf4SFabien Sanglard 
514*3f982cf4SFabien Sanglard   constexpr uint16_t server_port = 6667;
515*3f982cf4SFabien Sanglard 
516*3f982cf4SFabien Sanglard   // TODO(btolsch): aggregate initialization probably better?
517*3f982cf4SFabien Sanglard   ServicePublisher::Config publisher_config;
518*3f982cf4SFabien Sanglard   publisher_config.friendly_name = std::string(friendly_name);
519*3f982cf4SFabien Sanglard   publisher_config.hostname = "turtle-deadbeef";
520*3f982cf4SFabien Sanglard   publisher_config.service_instance_name = "deadbeef";
521*3f982cf4SFabien Sanglard   publisher_config.connection_server_port = server_port;
522*3f982cf4SFabien Sanglard 
523*3f982cf4SFabien Sanglard   ServerConfig server_config;
524*3f982cf4SFabien Sanglard   for (const InterfaceInfo& interface : GetNetworkInterfaces()) {
525*3f982cf4SFabien Sanglard     OSP_VLOG << "Found interface: " << interface;
526*3f982cf4SFabien Sanglard     if (!interface.addresses.empty()) {
527*3f982cf4SFabien Sanglard       server_config.connection_endpoints.push_back(
528*3f982cf4SFabien Sanglard           IPEndpoint{interface.addresses[0].address, server_port});
529*3f982cf4SFabien Sanglard       publisher_config.network_interfaces.push_back(interface);
530*3f982cf4SFabien Sanglard     }
531*3f982cf4SFabien Sanglard   }
532*3f982cf4SFabien Sanglard   OSP_LOG_IF(WARN, server_config.connection_endpoints.empty())
533*3f982cf4SFabien Sanglard       << "No network interfaces had usable addresses for mDNS publishing.";
534*3f982cf4SFabien Sanglard 
535*3f982cf4SFabien Sanglard   DemoPublisherObserver publisher_observer;
536*3f982cf4SFabien Sanglard   auto service_publisher = ServicePublisherFactory::Create(
537*3f982cf4SFabien Sanglard       publisher_config, &publisher_observer,
538*3f982cf4SFabien Sanglard       PlatformClientPosix::GetInstance()->GetTaskRunner());
539*3f982cf4SFabien Sanglard 
540*3f982cf4SFabien Sanglard   MessageDemuxer demuxer(Clock::now, MessageDemuxer::kDefaultBufferLimit);
541*3f982cf4SFabien Sanglard   DemoConnectionServerObserver server_observer;
542*3f982cf4SFabien Sanglard   auto connection_server = ProtocolConnectionServerFactory::Create(
543*3f982cf4SFabien Sanglard       server_config, &demuxer, &server_observer,
544*3f982cf4SFabien Sanglard       PlatformClientPosix::GetInstance()->GetTaskRunner());
545*3f982cf4SFabien Sanglard 
546*3f982cf4SFabien Sanglard   auto* network_service =
547*3f982cf4SFabien Sanglard       NetworkServiceManager::Create(nullptr, std::move(service_publisher),
548*3f982cf4SFabien Sanglard                                     nullptr, std::move(connection_server));
549*3f982cf4SFabien Sanglard 
550*3f982cf4SFabien Sanglard   DemoReceiverDelegate receiver_delegate;
551*3f982cf4SFabien Sanglard   Receiver::Get()->Init();
552*3f982cf4SFabien Sanglard   Receiver::Get()->SetReceiverDelegate(&receiver_delegate);
553*3f982cf4SFabien Sanglard   network_service->GetServicePublisher()->Start();
554*3f982cf4SFabien Sanglard   network_service->GetProtocolConnectionServer()->Start();
555*3f982cf4SFabien Sanglard 
556*3f982cf4SFabien Sanglard   pollfd stdin_pollfd{STDIN_FILENO, POLLIN};
557*3f982cf4SFabien Sanglard 
558*3f982cf4SFabien Sanglard   RunReceiverPollLoop(stdin_pollfd, network_service, receiver_delegate);
559*3f982cf4SFabien Sanglard 
560*3f982cf4SFabien Sanglard   receiver_delegate.connection.reset();
561*3f982cf4SFabien Sanglard   CleanupPublisherDemo(network_service);
562*3f982cf4SFabien Sanglard }
563*3f982cf4SFabien Sanglard 
564*3f982cf4SFabien Sanglard }  // namespace osp
565*3f982cf4SFabien Sanglard }  // namespace openscreen
566*3f982cf4SFabien Sanglard 
567*3f982cf4SFabien Sanglard struct InputArgs {
568*3f982cf4SFabien Sanglard   absl::string_view friendly_server_name;
569*3f982cf4SFabien Sanglard   bool is_verbose;
570*3f982cf4SFabien Sanglard   bool is_help;
571*3f982cf4SFabien Sanglard   bool tracing_enabled;
572*3f982cf4SFabien Sanglard };
573*3f982cf4SFabien Sanglard 
LogUsage(const char * argv0)574*3f982cf4SFabien Sanglard void LogUsage(const char* argv0) {
575*3f982cf4SFabien Sanglard   std::cerr << R"(
576*3f982cf4SFabien Sanglard usage: )" << argv0
577*3f982cf4SFabien Sanglard             << R"( <options> <friendly_name>
578*3f982cf4SFabien Sanglard 
579*3f982cf4SFabien Sanglard     friendly_name
580*3f982cf4SFabien Sanglard         Server name, runs the publisher demo. Omission runs the listener demo.
581*3f982cf4SFabien Sanglard 
582*3f982cf4SFabien Sanglard     -t, --tracing: Enable performance trace logging.
583*3f982cf4SFabien Sanglard 
584*3f982cf4SFabien Sanglard     -v, --verbose: Enable verbose logging.
585*3f982cf4SFabien Sanglard 
586*3f982cf4SFabien Sanglard     -h, --help: Show this help message.
587*3f982cf4SFabien Sanglard   )";
588*3f982cf4SFabien Sanglard }
589*3f982cf4SFabien Sanglard 
GetInputArgs(int argc,char ** argv)590*3f982cf4SFabien Sanglard InputArgs GetInputArgs(int argc, char** argv) {
591*3f982cf4SFabien Sanglard   // A note about modifying command line arguments: consider uniformity
592*3f982cf4SFabien Sanglard   // between all Open Screen executables. If it is a platform feature
593*3f982cf4SFabien Sanglard   // being exposed, consider if it applies to the standalone receiver,
594*3f982cf4SFabien Sanglard   // standalone sender, osp demo, and test_main argument options.
595*3f982cf4SFabien Sanglard   const struct option kArgumentOptions[] = {
596*3f982cf4SFabien Sanglard       {"tracing", no_argument, nullptr, 't'},
597*3f982cf4SFabien Sanglard       {"verbose", no_argument, nullptr, 'v'},
598*3f982cf4SFabien Sanglard       {"help", no_argument, nullptr, 'h'},
599*3f982cf4SFabien Sanglard       {nullptr, 0, nullptr, 0}};
600*3f982cf4SFabien Sanglard 
601*3f982cf4SFabien Sanglard   InputArgs args = {};
602*3f982cf4SFabien Sanglard   int ch = -1;
603*3f982cf4SFabien Sanglard   while ((ch = getopt_long(argc, argv, "tvh", kArgumentOptions, nullptr)) !=
604*3f982cf4SFabien Sanglard          -1) {
605*3f982cf4SFabien Sanglard     switch (ch) {
606*3f982cf4SFabien Sanglard       case 't':
607*3f982cf4SFabien Sanglard         args.tracing_enabled = true;
608*3f982cf4SFabien Sanglard         break;
609*3f982cf4SFabien Sanglard 
610*3f982cf4SFabien Sanglard       case 'v':
611*3f982cf4SFabien Sanglard         args.is_verbose = true;
612*3f982cf4SFabien Sanglard         break;
613*3f982cf4SFabien Sanglard 
614*3f982cf4SFabien Sanglard       case 'h':
615*3f982cf4SFabien Sanglard         args.is_help = true;
616*3f982cf4SFabien Sanglard         break;
617*3f982cf4SFabien Sanglard     }
618*3f982cf4SFabien Sanglard   }
619*3f982cf4SFabien Sanglard 
620*3f982cf4SFabien Sanglard   if (optind < argc) {
621*3f982cf4SFabien Sanglard     args.friendly_server_name = argv[optind];
622*3f982cf4SFabien Sanglard   }
623*3f982cf4SFabien Sanglard 
624*3f982cf4SFabien Sanglard   return args;
625*3f982cf4SFabien Sanglard }
626*3f982cf4SFabien Sanglard 
main(int argc,char ** argv)627*3f982cf4SFabien Sanglard int main(int argc, char** argv) {
628*3f982cf4SFabien Sanglard   using openscreen::Clock;
629*3f982cf4SFabien Sanglard   using openscreen::LogLevel;
630*3f982cf4SFabien Sanglard   using openscreen::PlatformClientPosix;
631*3f982cf4SFabien Sanglard 
632*3f982cf4SFabien Sanglard   InputArgs args = GetInputArgs(argc, argv);
633*3f982cf4SFabien Sanglard   if (args.is_help) {
634*3f982cf4SFabien Sanglard     LogUsage(argv[0]);
635*3f982cf4SFabien Sanglard     return 1;
636*3f982cf4SFabien Sanglard   }
637*3f982cf4SFabien Sanglard 
638*3f982cf4SFabien Sanglard   std::unique_ptr<openscreen::TextTraceLoggingPlatform> trace_logging_platform;
639*3f982cf4SFabien Sanglard   if (args.tracing_enabled) {
640*3f982cf4SFabien Sanglard     trace_logging_platform =
641*3f982cf4SFabien Sanglard         std::make_unique<openscreen::TextTraceLoggingPlatform>();
642*3f982cf4SFabien Sanglard   }
643*3f982cf4SFabien Sanglard 
644*3f982cf4SFabien Sanglard   const LogLevel level = args.is_verbose ? LogLevel::kVerbose : LogLevel::kInfo;
645*3f982cf4SFabien Sanglard   openscreen::SetLogLevel(level);
646*3f982cf4SFabien Sanglard 
647*3f982cf4SFabien Sanglard   const bool is_receiver_demo = !args.friendly_server_name.empty();
648*3f982cf4SFabien Sanglard   const char* log_filename =
649*3f982cf4SFabien Sanglard       is_receiver_demo ? kReceiverLogFilename : kControllerLogFilename;
650*3f982cf4SFabien Sanglard   // TODO(jophba): Mac on Mojave hangs on this command forever.
651*3f982cf4SFabien Sanglard   openscreen::SetLogFifoOrDie(log_filename);
652*3f982cf4SFabien Sanglard 
653*3f982cf4SFabien Sanglard   PlatformClientPosix::Create(std::chrono::milliseconds(50));
654*3f982cf4SFabien Sanglard 
655*3f982cf4SFabien Sanglard   if (is_receiver_demo) {
656*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "Running publisher demo...";
657*3f982cf4SFabien Sanglard     openscreen::osp::PublisherDemo(args.friendly_server_name);
658*3f982cf4SFabien Sanglard   } else {
659*3f982cf4SFabien Sanglard     OSP_LOG_INFO << "Running listener demo...";
660*3f982cf4SFabien Sanglard     openscreen::osp::ListenerDemo();
661*3f982cf4SFabien Sanglard   }
662*3f982cf4SFabien Sanglard 
663*3f982cf4SFabien Sanglard   PlatformClientPosix::ShutDown();
664*3f982cf4SFabien Sanglard 
665*3f982cf4SFabien Sanglard   return 0;
666*3f982cf4SFabien Sanglard }
667