Stroika Library 3.0d25
 
Loading...
Searching...
No Matches
LocationProvider.cpp
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include "Stroika/Frameworks/StroikaPreComp.h"
5
8#include "Stroika/Foundation/Containers/Sequence.h"
9
10#include "LocationProvider.h"
11
12using namespace Stroika::Foundation;
15
16using namespace Stroika::Frameworks::UPnP::SSDP;
17using namespace Stroika::Frameworks::UPnP::SSDP::Server;
18
19namespace {
20 // a URL naming a link-local IPv6 address needs a zone naming an interface of THIS machine - meaningless to the receiver
21 bool Advertisable_ (const InternetAddress& a)
22 {
23 return not(a.GetAddressFamily () == InternetAddress::AddressFamily::V6 and a.IsLinkLocalAddress ());
24 }
25}
26
27/*
28 ********************************************************************************
29 *************************** Server::LocationContext ****************************
30 ********************************************************************************
31 */
33{
35 sb << "{"sv;
36 sb << "LocalAddress: "sv << Characters::ToString (fLocalAddress);
37 if (fAsker) {
38 sb << ", Asker: "sv << Characters::ToString (*fAsker);
39 }
40 sb << "}"sv;
41 return sb;
42}
43
44/*
45 ********************************************************************************
46 ************************ Server::LocationFromBindings **************************
47 ********************************************************************************
48 */
49LocationProvider Server::LocationFromBindings (const Traversal::Iterable<SocketAddress>& webServerBindings, const String& path, const URI::SchemeType& scheme)
50{
51 Containers::Sequence<SocketAddress> bindings{webServerBindings}; // a copy, independent of where they came from
52 return [bindings, path, scheme] (const LocationContext& context) -> optional<URI> {
53 const InternetAddress& thisMachineAddressOnCandidateNetwork = context.fLocalAddress;
54 if (not Advertisable_ (thisMachineAddressOnCandidateNetwork)) {
55 return nullopt;
56 }
57 const InternetAddress anyOfFamily =
58 thisMachineAddressOnCandidateNetwork.GetAddressFamily () == InternetAddress::AddressFamily::V4 ? V4::kAddrAny : V6::kAddrAny;
59 optional<SocketAddress> b = bindings.First ([&] (const SocketAddress& sa) {
60 return sa.IsInternetAddress () and sa.GetInternetAddress () == thisMachineAddressOnCandidateNetwork;
61 });
62 if (not b) {
63 b = bindings.First ([&] (const SocketAddress& sa) { return sa.IsInternetAddress () and sa.GetInternetAddress () == anyOfFamily; });
64 }
65 if (not b) {
66 return nullopt; // the web server isn't reachable on that network
67 }
68 return URI{scheme, URI::Authority{thisMachineAddressOnCandidateNetwork, b->GetPort ()}, path};
69 };
70}
71
72/*
73 ********************************************************************************
74 **************************** Server::FixedLocation *****************************
75 ********************************************************************************
76 */
77LocationProvider Server::FixedLocation (const URI& url)
78{
79 return [url] ([[maybe_unused]] const LocationContext& context) -> optional<URI> { return url; };
80}
81
82/*
83 ********************************************************************************
84 ************************ Server::LocationFillingInHost *************************
85 ********************************************************************************
86 */
87LocationProvider Server::LocationFillingInHost (const URI& location)
88{
89 return [location] (const LocationContext& context) -> optional<URI> {
90 optional<URI::Authority> authority = location.GetAuthority ();
91 if (authority and authority->GetHost ()) {
92 return location; // it names its own host
93 }
94 if (not Advertisable_ (context.fLocalAddress)) {
95 return nullopt;
96 }
97 URI::Authority useAuthority = authority.value_or (URI::Authority{});
98 useAuthority.SetHost (context.fLocalAddress);
99 URI result = location;
100 result.SetAuthority (useAuthority);
101 return result;
102 };
103}
104
105/*
106 ********************************************************************************
107 ******************** Server::Private_::AdvertisableAddress *********************
108 ********************************************************************************
109 */
110optional<InternetAddress> Server::Private_::LocalAddressOnAskersNetwork (const InternetAddress& asker, const Traversal::Iterable<Interface>& interfaces)
111{
112 if (asker.GetAddressFamily () == InternetAddress::AddressFamily::V6 and asker.IsLinkLocalAddress ()) {
113 return nullopt; // in every interface's subnet: which interface, only its scope id says - which the routing table has
114 }
115 if (interfaces.Any ([&] (const Interface& i) { return i.fBindings.fAddresses.Contains (asker); })) {
116 return asker; // this machine, asking itself
117 }
118 for (const Interface& i : interfaces) {
119 for (const CIDR& subnet : i.fBindings.fAddressRanges) {
120 auto inSubnet = [&] (const InternetAddress& a) {
121 return a.GetAddressFamily () == subnet.GetBaseInternetAddress ().GetAddressFamily () and subnet.GetRange ().Contains (a);
122 };
123 if (inSubnet (asker)) {
124 if (optional<InternetAddress> local = i.fBindings.fAddresses.First (inSubnet)) {
125 return local;
126 }
127 }
128 }
129 }
130 return nullopt;
131}
132
133optional<InternetAddress> Server::Private_::AdvertisableAddress (const Interface& i, InternetAddress::AddressFamily f)
134{
135 optional<InternetAddress> linkLocal;
136 for (const InternetAddress& a : i.fBindings.fAddresses) {
137 if (a.GetAddressFamily () == f) {
138 if (not a.IsLinkLocalAddress ()) {
139 return a;
140 }
141 if (not linkLocal) {
142 linkLocal = a;
143 }
144 }
145 }
146 return linkLocal;
147}
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
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 constexpr AddressFamily GetAddressFamily() const
nonvirtual InternetAddress GetInternetAddress() const
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...
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:234
nonvirtual bool Any() const
Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any va...
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
Definition ToString.inl:424