master
cpp 92 lines 3.03 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #include "precomp.h"
4 #include "socket.hpp"
5 #include "GnsPortTrackerChannel.h"
6
7 using wsl::core::GnsPortTrackerChannel;
8
9 GnsPortTrackerChannel::GnsPortTrackerChannel(
10 wil::unique_socket&& Socket,
11 const std::function<int(const SOCKADDR_INET&, int, bool)>& Callback,
12 const std::function<void(const std::string&, bool)>& InterfaceStateCallback) :
13 m_callback(Callback),
14 m_interfaceStateCallback(InterfaceStateCallback),
15 m_channel(std::move(Socket), "GNSPortTracker", {m_stopEvent.get()})
16 {
17 m_thread = std::thread{std::bind(&GnsPortTrackerChannel::Run, this)};
18 }
19
20 GnsPortTrackerChannel::~GnsPortTrackerChannel()
21 {
22 LOG_IF_WIN32_BOOL_FALSE(SetEvent(m_stopEvent.get()));
23
24 if (m_thread.joinable())
25 {
26 m_thread.join();
27 }
28 }
29
30 void GnsPortTrackerChannel::Run()
31 {
32 try
33 {
34 for (;;)
35 {
36 auto transaction = m_channel.ReceiveTransaction();
37 auto [header, range] = transaction.ReceiveOrClosed<MESSAGE_HEADER>();
38 if (header == nullptr)
39 {
40 return;
41 }
42
43 switch (header->MessageType)
44 {
45 case LxGnsMessagePortMappingRequest:
46 {
47 const auto* message = gslhelpers::try_get_struct<LX_GNS_PORT_ALLOCATION_REQUEST>(range);
48 THROW_HR_IF_MSG(E_UNEXPECTED, !message, "Unexpected message size: %i", header->MessageSize);
49
50 transaction.SendResultMessage<int32_t>(
51 m_callback(ConvertPortRequestToSockAddr(message), message->Protocol, message->Allocate));
52 }
53 break;
54 case LxGnsMessageIfStateChangeRequest:
55 {
56 const auto* message = gslhelpers::try_get_struct<LX_GNS_TUN_BRIDGE_REQUEST>(range);
57 THROW_HR_IF_MSG(E_UNEXPECTED, !message, "Unexpected message size: %i", header->MessageSize);
58
59 m_interfaceStateCallback(message->InterfaceName, message->InterfaceUp);
60 transaction.SendResultMessage<int32_t>(0);
61 }
62 break;
63 default:
64 THROW_HR_MSG(E_UNEXPECTED, "Unexpected message type: %i", header->MessageType);
65 }
66 }
67 }
68 CATCH_LOG()
69 }
70
71 SOCKADDR_INET GnsPortTrackerChannel::ConvertPortRequestToSockAddr(_In_ const LX_GNS_PORT_ALLOCATION_REQUEST* portAllocationRequest)
72 {
73 SOCKADDR_INET address{};
74
75 address.si_family = static_cast<uint16_t>(portAllocationRequest->Af);
76
77 if (portAllocationRequest->Af == AF_INET)
78 {
79 IN_ADDR ipv4Addr{};
80 ipv4Addr.S_un.S_addr = portAllocationRequest->Address32[0];
81 IN4ADDR_SETSOCKADDR(&address.Ipv4, &ipv4Addr, portAllocationRequest->Port);
82 }
83 else
84 {
85 IN6_ADDR ipv6Addr{};
86 // Copy 16 bytes that represent IPv6 address
87 memcpy(&ipv6Addr.u, portAllocationRequest->Address32, sizeof(portAllocationRequest->Address32));
88 IN6ADDR_SETSOCKADDR(&address.Ipv6, &ipv6Addr, SCOPEID_UNSPECIFIED_INIT, portAllocationRequest->Port);
89 }
90
91 return address;
92 }