master
cpp 130 lines 5.11 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 #include "precomp.h"
4 #include "lxinitshared.h"
5 #include "GnsChannel.h"
6
7 using namespace wsl::shared;
8 using wsl::core::GnsChannel;
9
10 GnsChannel::GnsChannel(wil::unique_socket&& socket) : m_channel(std::move(socket), "GNS", {m_stopEvent.get()})
11 {
12 WSL_LOG("GnsChannel::GnsChannel", TraceLoggingValue(m_channel.Socket(), "socket"));
13 }
14
15 void GnsChannel::SendEndpointState(const hns::HNSEndpoint& Notification)
16 {
17 // if we have signaled to stop, block anyone making new calls
18 if (m_stopEvent.is_signaled())
19 {
20 return;
21 }
22
23 Message<LX_GNS_INTERFACE_CONFIGURATION>(LxGnsMessageInterfaceConfiguration, ToJson(Notification));
24 }
25
26 template <typename TMessage>
27 int GnsChannel::MessageReturnResult(LX_MESSAGE_TYPE Type, const std::string& Content, const std::function<void(TMessage&)>& BuildMessage)
28 {
29 size_t messageSize;
30 THROW_IF_FAILED(SizeTAdd(offsetof(TMessage, Content), Content.size() + 1, &messageSize));
31
32 // Populate the message that will be sent to gns.
33 std::vector<gsl::byte> buffer(messageSize);
34 const auto messageSpan = gsl::make_span(buffer);
35 auto* message = gslhelpers::get_struct<TMessage>(messageSpan);
36 message->Header.MessageType = Type;
37 message->Header.MessageSize = gsl::narrow_cast<ULONG>(messageSize);
38 if (BuildMessage)
39 {
40 BuildMessage(*message);
41 }
42
43 auto offset = offsetof(TMessage, Content);
44 wsl::shared::string::CopyToSpan(Content, messageSpan, offset);
45 WI_ASSERT(messageSize == offset);
46
47 return m_channel.Transaction<TMessage>(messageSpan).Result;
48 }
49
50 template <typename TMessage>
51 void GnsChannel::Message(LX_MESSAGE_TYPE Type, const std::string& Content, const std::function<void(TMessage&)>& BuildMessage)
52 {
53 const auto result = MessageReturnResult(Type, Content, BuildMessage);
54
55 THROW_HR_IF_MSG(
56 E_UNEXPECTED,
57 result == ERROR_FATAL_APP_EXIT,
58 "Did not receive a LX_GNS_RESULT after sending message %hs, type %u",
59 Content.c_str(),
60 static_cast<uint32_t>(Type));
61
62 THROW_HR_IF_MSG(
63 E_UNEXPECTED,
64 (result != 0),
65 "Error returned from GNS after sending message %hs, type %u. Result=%i",
66 Content.c_str(),
67 static_cast<uint32_t>(Type),
68 result);
69 }
70
71 // the payload is expected to be of type ModifyGuestEndpointSettingRequest
72 void GnsChannel::SendHnsNotification(_In_ LPCWSTR Notification, const GUID& AdapterId)
73 {
74 // if we have signaled to stop, block anyone making new calls
75 if (m_stopEvent.is_signaled())
76 {
77 return;
78 }
79
80 auto AddAdapterId = [&](LX_GNS_NOTIFICATION& Message) { Message.AdapterId = AdapterId; };
81 Message<LX_GNS_NOTIFICATION>(LxGnsMessageNotification, wsl::shared::string::WideToMultiByte(Notification), AddAdapterId);
82 }
83
84 // Network device messages built from the corresponding serialization functions
85 // throws on error
86 void GnsChannel::SendNetworkDeviceMessage(LX_MESSAGE_TYPE MessageType, LPCWSTR MessageContent)
87 {
88 // if we have signaled to stop, block anyone making new calls
89 if (m_stopEvent.is_signaled())
90 {
91 return;
92 }
93
94 WI_ASSERT(
95 MessageType == LxGnsMessageVmNicCreatedNotification || MessageType == LxGnsMessageCreateDeviceRequest ||
96 MessageType == LxGnsMessageModifyGuestDeviceSettingRequest || MessageType == LxGnsMessageLoopbackRoutesRequest ||
97 MessageType == LxGnsMessageDeviceSettingRequest || MessageType == LxGnsMessageInitialIpConfigurationNotification ||
98 MessageType == LxGnsMessageSetupIpv6 || MessageType == LxGnsMessageInterfaceConfiguration ||
99 MessageType == LxGnsMessageNoOp || MessageType == LxGnsMessageGlobalNetFilter ||
100 MessageType == LxGnsMessageInterfaceNetFilter || MessageType == LxGnsMessageConnectTestRequest);
101
102 Message<LX_GNS_JSON_MESSAGE>(MessageType, wsl::shared::string::WideToMultiByte(MessageContent));
103 }
104
105 // Network device messages built from the corresponding serialization functions
106 // throws on error, returns the integer value that was returned from Linux
107 int GnsChannel::SendNetworkDeviceMessageReturnResult(LX_MESSAGE_TYPE MessageType, LPCWSTR MessageContent)
108 {
109 // if we have signaled to stop, block anyone making new calls
110 if (m_stopEvent.is_signaled())
111 {
112 return ERROR_SHUTDOWN_IN_PROGRESS;
113 }
114
115 WI_ASSERT(
116 MessageType == LxGnsMessageVmNicCreatedNotification || MessageType == LxGnsMessageCreateDeviceRequest ||
117 MessageType == LxGnsMessageModifyGuestDeviceSettingRequest || MessageType == LxGnsMessageLoopbackRoutesRequest ||
118 MessageType == LxGnsMessageDeviceSettingRequest || MessageType == LxGnsMessageInitialIpConfigurationNotification ||
119 MessageType == LxGnsMessageSetupIpv6 || MessageType == LxGnsMessageInterfaceConfiguration ||
120 MessageType == LxGnsMessageNoOp || MessageType == LxGnsMessageGlobalNetFilter ||
121 MessageType == LxGnsMessageInterfaceNetFilter || MessageType == LxGnsMessageConnectTestRequest);
122
123 return MessageReturnResult<LX_GNS_JSON_MESSAGE>(MessageType, wsl::shared::string::WideToMultiByte(MessageContent));
124 }
125
126 void GnsChannel::Stop() const
127 {
128 WSL_LOG("GnsChannel::Stop");
129 m_stopEvent.SetEvent();
130 }