yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
unified_grpc_server.cc
Go to the documentation of this file.
2
3#ifdef YAZE_WITH_GRPC
4
6
7#include <grpcpp/grpcpp.h>
8
9#include <iostream>
10#include <thread>
11
12#include "absl/strings/str_format.h"
17#include "protos/canvas_automation.grpc.pb.h"
18#include "rom/rom.h"
19
21
22namespace yaze {
23
24YazeGRPCServer::YazeGRPCServer() : is_running_(false) {}
25
26YazeGRPCServer::~YazeGRPCServer() {
27 Shutdown();
28}
29
30absl::Status YazeGRPCServer::Initialize(
31 int port, emu::IEmulator* emulator, RomGetter rom_getter,
32 RomLoader rom_loader, test::TestManager* test_manager,
33 net::RomVersionManager* version_mgr,
34 net::ProposalApprovalManager* approval_mgr,
35 CanvasAutomationServiceImpl* canvas_service) {
36 if (is_running_) {
37 return absl::FailedPreconditionError("Server is already running");
38 }
39
40 config_.port = port;
41
42 // Create ImGuiTestHarness service if test_manager provided
43 if (config_.enable_test_harness && test_manager) {
44 test_harness_service_ =
45 std::make_unique<test::ImGuiTestHarnessServiceImpl>(test_manager);
46 std::cout << "✓ ImGuiTestHarness service initialized\n";
47 }
48
49 // Create Emulator service if emulator provided
50 if (config_.enable_emulator_service && emulator) {
51 emulator_service_ = std::make_unique<net::EmulatorServiceImpl>(
52 emulator, rom_getter, rom_loader);
53 std::cout << "✓ Emulator service initialized\n";
54 } else if (config_.enable_emulator_service) {
55 std::cout << "⚠ Emulator service requested but no emulator provided\n";
56 }
57
58 // Create ROM service if rom_getter provided
59 if (config_.enable_rom_service && rom_getter) {
60 rom_service_ = std::make_unique<net::RomServiceImpl>(
61 rom_getter, version_mgr, approval_mgr);
62
63 // Configure ROM service
64 net::RomServiceImpl::Config rom_config;
65 rom_config.require_approval_for_writes =
66 config_.require_approval_for_rom_writes;
67 rom_service_->SetConfig(rom_config);
68
69 std::cout << "✓ ROM service initialized\n";
70 } else if (config_.enable_rom_service) {
71 std::cout << "⚠ ROM service requested but no ROM provided\n";
72 }
73
74 // Create Canvas Automation service if canvas_service provided
75 if (config_.enable_canvas_automation && canvas_service) {
76 // Store the provided service (not owned by us)
77 canvas_service_ = canvas_service;
78 std::cout << "✓ Canvas Automation service initialized\n";
79 } else if (config_.enable_canvas_automation) {
80 std::cout << "⚠ Canvas Automation requested but no service provided\n";
81 }
82
83 if (!test_harness_service_ && !rom_service_ && !canvas_service_ &&
84 !emulator_service_) {
85 return absl::InvalidArgumentError(
86 "At least one service must be enabled and initialized");
87 }
88
89 return absl::OkStatus();
90}
91
92absl::Status YazeGRPCServer::Start() {
93 auto status = BuildServer();
94 if (!status.ok()) {
95 return status;
96 }
97
98 std::cout << "✓ YAZE gRPC automation server listening on 0.0.0.0:"
99 << config_.port << "\n";
100
101 if (test_harness_service_) {
102 std::cout << " ✓ ImGuiTestHarness available\n";
103 }
104 if (emulator_service_) {
105 std::cout << " ✓ EmulatorService available\n";
106 }
107 if (rom_service_) {
108 std::cout << " ✓ ROM service available\n";
109 }
110 if (canvas_service_) {
111 std::cout << " ✓ Canvas Automation available\n";
112 }
113
114 std::cout << "\nServer is ready to accept requests...\n";
115
116 // Block until server is shut down
117 server_->Wait();
118 is_running_ = false;
119
120 return absl::OkStatus();
121}
122
123absl::Status YazeGRPCServer::StartAsync() {
124 auto status = BuildServer();
125 if (!status.ok()) {
126 return status;
127 }
128
129 std::cout << "✓ Unified gRPC server started on port " << config_.port << "\n";
130
131 // Server runs in background, doesn't block
132 return absl::OkStatus();
133}
134
135absl::Status YazeGRPCServer::AddService(
136 std::unique_ptr<grpc::Service> service) {
137 if (!service) {
138 return absl::InvalidArgumentError("Service is null");
139 }
140 if (is_running_) {
141 return absl::FailedPreconditionError(
142 "Cannot add services after the server has started");
143 }
144 extra_services_.push_back(std::move(service));
145 return absl::OkStatus();
146}
147
148void YazeGRPCServer::Shutdown() {
149 if (server_) {
150 std::cout << "⏹ Shutting down unified gRPC server...\n";
151 if (is_running_) {
152 server_->Shutdown();
153 }
154 server_->Wait();
155 server_.reset();
156 is_running_ = false;
157 ReleaseRegisteredServices();
158 std::cout << "✓ Server stopped\n";
159 }
160}
161
162bool YazeGRPCServer::IsRunning() const {
163 return is_running_;
164}
165
166absl::Status YazeGRPCServer::BuildServer() {
167 if (is_running_) {
168 return absl::FailedPreconditionError("Server already running");
169 }
170
171 std::string server_address = absl::StrFormat("0.0.0.0:%d", config_.port);
172
173 grpc::ServerBuilder builder;
174
175 // Listen on all interfaces
176 int selected_port = 0;
177 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(),
178 &selected_port);
179
180 // Register services
181 if (test_harness_service_) {
182 // Create gRPC wrapper for the test harness service
183 test_harness_grpc_wrapper_ =
184 test::CreateImGuiTestHarnessServiceGrpc(test_harness_service_.get());
185 std::cout << " Registering ImGuiTestHarness service...\n";
186 builder.RegisterService(test_harness_grpc_wrapper_.get());
187 }
188
189 if (emulator_service_) {
190 std::cout << " Registering EmulatorService...\n";
191 builder.RegisterService(emulator_service_.get());
192 }
193
194 if (rom_service_) {
195 std::cout << " Registering ROM service...\n";
196 builder.RegisterService(rom_service_.get());
197 }
198
199 if (canvas_service_) {
200 std::cout << " Registering Canvas Automation service...\n";
201 // Create gRPC wrapper using factory function
202 canvas_grpc_service_ = CreateCanvasAutomationServiceGrpc(canvas_service_);
203 builder.RegisterService(canvas_grpc_service_.get());
204 }
205
206 for (auto& service : extra_services_) {
207 builder.RegisterService(service.get());
208 }
209
210 // Build and start
211 server_ = builder.BuildAndStart();
212
213 if (!server_) {
214 return absl::InternalError(
215 absl::StrFormat("Failed to start server on %s", server_address));
216 }
217
218 is_running_ = true;
219 if (selected_port > 0) {
220 config_.port = selected_port;
221 }
222
223 return absl::OkStatus();
224}
225
226void YazeGRPCServer::ReleaseRegisteredServices() {
227 canvas_grpc_service_.reset();
228 test_harness_grpc_wrapper_.reset();
229 extra_services_.clear();
230 emulator_service_.reset();
231 rom_service_.reset();
232 test_harness_service_.reset();
233 canvas_service_ = nullptr;
234}
235
236} // namespace yaze
237
238#endif // YAZE_WITH_GRPC