aboutsummaryrefslogtreecommitdiff
path: root/wmediumd_server/wmediumd_server.cc
diff options
context:
space:
mode:
Diffstat (limited to 'wmediumd_server/wmediumd_server.cc')
-rw-r--r--wmediumd_server/wmediumd_server.cc147
1 files changed, 147 insertions, 0 deletions
diff --git a/wmediumd_server/wmediumd_server.cc b/wmediumd_server/wmediumd_server.cc
new file mode 100644
index 0000000..229d505
--- /dev/null
+++ b/wmediumd_server/wmediumd_server.cc
@@ -0,0 +1,147 @@
+/*
+ *
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <android-base/strings.h>
+#include <gflags/gflags.h>
+#include <grpcpp/ext/proto_server_reflection_plugin.h>
+#include <grpcpp/grpcpp.h>
+#include <grpcpp/health_check_service_interface.h>
+#include <sys/msg.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <array>
+#include <iostream>
+#include <memory>
+#include <string>
+
+#include "wmediumd.grpc.pb.h"
+#include "wmediumd/api.h"
+#include "wmediumd/grpc.h"
+
+using google::protobuf::Empty;
+using grpc::Server;
+using grpc::ServerBuilder;
+using grpc::ServerContext;
+using grpc::Status;
+using grpc::StatusCode;
+using wmediumdserver::SetPositionRequest;
+using wmediumdserver::WmediumdService;
+
+#define MAC_ADDR_LEN 6
+#define STR_MAC_ADDR_LEN 17
+
+template <class T>
+static void AppendBinaryRepresentation(std::string& buf, const T& data) {
+ std::copy(reinterpret_cast<const char*>(&data),
+ reinterpret_cast<const char*>(&data) + sizeof(T),
+ std::back_inserter(buf));
+}
+
+bool IsValidMacAddr(const std::string& mac_address) {
+ if (mac_address.size() != STR_MAC_ADDR_LEN) {
+ return false;
+ }
+
+ if (mac_address[2] != ':' || mac_address[5] != ':' || mac_address[8] != ':' ||
+ mac_address[11] != ':' || mac_address[14] != ':') {
+ return false;
+ }
+
+ for (int i = 0; i < STR_MAC_ADDR_LEN; ++i) {
+ if ((i - 2) % 3 == 0) continue;
+ char c = mac_address[i];
+
+ if (isupper(c)) {
+ c = tolower(c);
+ }
+
+ if ((c < '0' || c > '9') && (c < 'a' || c > 'f')) return false;
+ }
+
+ return true;
+}
+
+static std::array<uint8_t, 6> ParseMacAddress(const std::string& mac_address) {
+ auto split_mac = android::base::Split(mac_address, ":");
+ std::array<uint8_t, 6> mac;
+ for (int i = 0; i < 6; i++) {
+ char* end_ptr;
+ mac[i] = (uint8_t)strtol(split_mac[i].c_str(), &end_ptr, 16);
+ }
+
+ return mac;
+}
+
+class WmediumdServiceImpl final : public WmediumdService::Service {
+ public:
+ WmediumdServiceImpl(int event_fd, int msq_id)
+ : event_fd_(event_fd), msq_id_(msq_id) {}
+
+ Status SetPosition(ServerContext* context, const SetPositionRequest* request,
+ Empty* reply) override {
+ // Validate parameters
+ if (!IsValidMacAddr(request->mac_address())) {
+ return Status(StatusCode::INVALID_ARGUMENT, "Got invalid mac address");
+ }
+ auto mac = ParseMacAddress(request->mac_address());
+
+ // Construct request data
+ struct wmediumd_set_position data;
+ memcpy(data.mac, &mac, sizeof(mac));
+ data.x = request->x_pos();
+ data.y = request->y_pos();
+
+ // Fill data in the message queue
+ struct wmediumd_grpc_message msg;
+ msg.type = GRPC_REQUEST;
+ memcpy(msg.data, &data, sizeof(data));
+ msgsnd(msq_id_, &msg, sizeof(data), 0);
+
+ // Throw an event to wmediumd
+ uint64_t value = REQUEST_SET_POSITION;
+ write(event_fd_, &value, sizeof(uint64_t));
+
+ return Status::OK;
+ }
+
+ private:
+ int event_fd_;
+ int msq_id_;
+};
+
+void RunWmediumdServer(std::string grpc_uds_path, int event_fd, int msq_id) {
+ std::string server_address("unix:" + grpc_uds_path);
+ WmediumdServiceImpl service(event_fd, msq_id);
+
+ grpc::EnableDefaultHealthCheckService(true);
+ grpc::reflection::InitProtoReflectionServerBuilderPlugin();
+ ServerBuilder builder;
+ // Listen on the given address without any authentication mechanism.
+ builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
+ // Register "service" as the instance through which we'll communicate with
+ // clients. In this case it corresponds to an *synchronous* service.
+ builder.RegisterService(&service);
+ // Finally assemble the server.
+ std::unique_ptr<Server> server(builder.BuildAndStart());
+ std::cout << "Server listening on " << server_address << std::endl;
+
+ // Wait for the server to shutdown. Note that some other thread must be
+ // responsible for shutting down the server for this call to ever return.
+ server->Wait();
+}