Stroika Library 3.0d23x
 
Loading...
Searching...
No Matches
BasicServer.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
7#include "Stroika/Foundation/Containers/Sequence.h"
14#include "Stroika/Foundation/Streams/MemoryStream.h"
15
18
19#include "BasicServer.h"
20
21using namespace Stroika::Foundation;
24using namespace Stroika::Foundation::Execution;
25using namespace Stroika::Foundation::IO;
27
28using Memory::MakeSharedPtr;
29
30using namespace Stroika::Frameworks;
31using namespace Stroika::Frameworks::UPnP;
32using namespace Stroika::Frameworks::UPnP::SSDP;
33using namespace Stroika::Frameworks::UPnP::SSDP::Server;
34
35/*
36********************************************************************************
37******************************* BasicServer::Rep_ ******************************
38********************************************************************************
39*/
40class BasicServer::Rep_ final {
41public:
42 Sequence<Advertisement> fAdvertisements;
43 FrequencyInfo fFrequencyInfo;
44 URI fLocation;
45 Rep_ (const Device& d, const DeviceDescription& dd, const FrequencyInfo& fi, IO::Network::InternetProtocol::IP::IPVersionSupport ipVersion)
46 : fFrequencyInfo{fi}
47 , fLocation{d.fLocation}
48 {
49 {
50 SSDP::Advertisement dan;
51 // dan.fLocation set in GetAdjustedAdvertisements_...
52 dan.fServer = d.fServer;
53 {
54 dan.fTarget = kTarget_UPNPRootDevice;
55 dan.fUSN = Format ("uuid:{}::{}"_f, d.fDeviceID, kTarget_UPNPRootDevice);
56 fAdvertisements.Append (dan);
57 }
58 {
59 dan.fUSN = Format ("uuid:{}"_f, d.fDeviceID);
60 dan.fTarget = dan.fUSN;
61 fAdvertisements.Append (dan);
62 }
63 if (not dd.fDeviceType.empty ()) {
64 dan.fUSN = Format ("uuid:{}::{}"_f, d.fDeviceID, dd.fDeviceType);
65 dan.fTarget = dd.fDeviceType;
66 fAdvertisements.Append (dan);
67 }
68 }
69
70 // SEE http://stroika-bugs.sophists.com/browse/STK-962 - make resilient to failures setting up watchers, to retry
71
72 fNotifier_ = make_unique<PeriodicNotifier> (GetAdjustedAdvertisements_ (), fi, ipVersion);
73 fSearchResponder_ = make_unique<SearchResponder> (GetAdjustedAdvertisements_ (), ipVersion);
74
76 LinkMonitor lm;
77 lm.AddCallback ([this] (LinkMonitor::LinkChange lc, String netName, String ipNum) {
78 Debug::TraceContextBumper ctx{"Basic SSDP server - LinkMonitor callback", "lc = {}, netName={}, ipNum={}"_f, lc, netName, ipNum};
79 if (lc == LinkMonitor::LinkChange::eAdded) {
80 this->Restart_ ();
81 }
82 });
83 fLinkMonitor_ = optional<LinkMonitor>{move (lm)};
84 }
85 Sequence<Advertisement> GetAdjustedAdvertisements_ () const
86 {
87 /*
88 * As a convenience, automatically set the LOCATION advertised to be that of the primary IP address of this
89 * host.
90 */
91 if (fLocation.GetAuthority () and fLocation.GetAuthority ()->GetHost ()) {
92 return fAdvertisements;
93 }
94 else {
95 Sequence<Advertisement> revisedAdvertisements;
96 URI useBaseURL = fLocation;
97 URI::Authority useAuthority = useBaseURL.GetAuthority ().value_or (URI::Authority{});
98 useAuthority.SetHost (IO::Network::GetPrimaryInternetAddress ());
99 useBaseURL.SetAuthority (useAuthority);
100 for (auto ai : fAdvertisements) {
101 ai.fLocation = useBaseURL.Combine (ai.fLocation);
102 revisedAdvertisements.Append (ai);
103 }
104 return revisedAdvertisements;
105 }
106 }
107 void Restart_ ()
108 {
109 Debug::TraceContextBumper ctx{"Restarting Basic SSDP server threads"};
110 fNotifier_.reset ();
111 fSearchResponder_.reset ();
112 fNotifier_ = make_unique<PeriodicNotifier> (GetAdjustedAdvertisements_ (), PeriodicNotifier::FrequencyInfo{});
113 fSearchResponder_ = make_unique<SearchResponder> (GetAdjustedAdvertisements_ ());
114 }
115 unique_ptr<PeriodicNotifier> fNotifier_;
116 unique_ptr<SearchResponder> fSearchResponder_;
117 optional<IO::Network::LinkMonitor> fLinkMonitor_; // optional so we can delete it first on shutdown (so no restart while stopping stuff)
118};
119
120/*
121********************************************************************************
122********************************** BasicServer *********************************
123********************************************************************************
124*/
125BasicServer::BasicServer (const Device& d, const DeviceDescription& dd, const FrequencyInfo& fi, IO::Network::InternetProtocol::IP::IPVersionSupport ipVersion)
126 : fRep_{MakeSharedPtr<Rep_> (d, dd, fi, ipVersion)}
127{
128}
auto MakeSharedPtr(ARGS_TYPE &&... args) -> shared_ptr< T >
same as make_shared, but if type T has block allocation, then use block allocation for the 'shared pa...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A generalization of a vector: a container whose elements are keyed by the natural numbers.
nonvirtual void Append(ArgByValueType< value_type > item)
Definition Sequence.inl:330
nonvirtual URI Combine(const URI &overridingURI) const
Combine overridingURI possibly relative url with this base url, to produce a new URI.
Definition URI.cpp:316
nonvirtual optional< Authority > GetAuthority() const
Definition URI.inl:55
Authority is roughly the part of a URL where you say the hostname (and portnumber etc) - part just af...
InternetAddress GetPrimaryInternetAddress()