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
92void YazeGRPCServer::SetEmulatorScreenshotCapturer(
93 std::function<absl::StatusOr<test::ScreenshotArtifact>()> capturer) {
94 if (emulator_service_) {
95 emulator_service_->SetScreenshotCapturer(std::move(capturer));
96 }
97}
98
99absl::Status YazeGRPCServer::Start() {
100 auto status = BuildServer();
101 if (!status.ok()) {
102 return status;
103 }
104
105 std::cout << "✓ YAZE gRPC automation server listening on "
106 << config_.bind_address << ":" << config_.port << "\n";
107
108 if (test_harness_service_) {
109 std::cout << " ✓ ImGuiTestHarness available\n";
110 }
111 if (emulator_service_) {
112 std::cout << " ✓ EmulatorService available\n";
113 }
114 if (rom_service_) {
115 std::cout << " ✓ ROM service available\n";
116 }
117 if (canvas_service_) {
118 std::cout << " ✓ Canvas Automation available\n";
119 }
120
121 std::cout << "\nServer is ready to accept requests...\n";
122
123 // Block until server is shut down
124 server_->Wait();
125 is_running_ = false;
126
127 return absl::OkStatus();
128}
129
130absl::Status YazeGRPCServer::StartAsync() {
131 auto status = BuildServer();
132 if (!status.ok()) {
133 return status;
134 }
135
136 std::cout << "✓ Unified gRPC server started on port " << config_.port << "\n";
137
138 // Server runs in background, doesn't block
139 return absl::OkStatus();
140}
141
142absl::Status YazeGRPCServer::AddService(
143 std::unique_ptr<grpc::Service> service) {
144 if (!service) {
145 return absl::InvalidArgumentError("Service is null");
146 }
147 if (is_running_) {
148 return absl::FailedPreconditionError(
149 "Cannot add services after the server has started");
150 }
151 extra_services_.push_back(std::move(service));
152 return absl::OkStatus();
153}
154
155void YazeGRPCServer::Shutdown() {
156 if (server_) {
157 std::cout << "⏹ Shutting down unified gRPC server...\n";
158 if (is_running_) {
159 server_->Shutdown();
160 }
161 server_->Wait();
162 server_.reset();
163 is_running_ = false;
164 ReleaseRegisteredServices();
165 std::cout << "✓ Server stopped\n";
166 }
167}
168
169bool YazeGRPCServer::IsRunning() const {
170 return is_running_;
171}
172
173absl::Status YazeGRPCServer::BuildServer() {
174 if (is_running_) {
175 return absl::FailedPreconditionError("Server already running");
176 }
177
178 std::string server_address =
179 absl::StrFormat("%s:%d", config_.bind_address, config_.port);
180
181 grpc::ServerBuilder builder;
182
183 int selected_port = 0;
184 builder.AddListeningPort(server_address, grpc::InsecureServerCredentials(),
185 &selected_port);
186
187 // Register services
188 if (test_harness_service_) {
189 // Create gRPC wrapper for the test harness service
190 test_harness_grpc_wrapper_ =
191 test::CreateImGuiTestHarnessServiceGrpc(test_harness_service_.get());
192 std::cout << " Registering ImGuiTestHarness service...\n";
193 builder.RegisterService(test_harness_grpc_wrapper_.get());
194 }
195
196 if (emulator_service_) {
197 std::cout << " Registering EmulatorService...\n";
198 builder.RegisterService(emulator_service_.get());
199 }
200
201 if (rom_service_) {
202 std::cout << " Registering ROM service...\n";
203 builder.RegisterService(rom_service_.get());
204 }
205
206 if (canvas_service_) {
207 std::cout << " Registering Canvas Automation service...\n";
208 // Create gRPC wrapper using factory function
209 canvas_grpc_service_ = CreateCanvasAutomationServiceGrpc(canvas_service_);
210 builder.RegisterService(canvas_grpc_service_.get());
211 }
212
213 for (auto& service : extra_services_) {
214 builder.RegisterService(service.get());
215 }
216
217 // Build and start
218 server_ = builder.BuildAndStart();
219
220 if (!server_) {
221 return absl::InternalError(
222 absl::StrFormat("Failed to start server on %s", server_address));
223 }
224
225 is_running_ = true;
226 if (selected_port > 0) {
227 config_.port = selected_port;
228 }
229
230 return absl::OkStatus();
231}
232
233void YazeGRPCServer::ReleaseRegisteredServices() {
234 canvas_grpc_service_.reset();
235 test_harness_grpc_wrapper_.reset();
236 extra_services_.clear();
237 emulator_service_.reset();
238 rom_service_.reset();
239 test_harness_service_.reset();
240 canvas_service_ = nullptr;
241}
242
243} // namespace yaze
244
245#endif // YAZE_WITH_GRPC