MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
lila_server.cpp
Go to the documentation of this file.
1/**
2 * @file lila_server.cpp
3 * @brief Entry point for the Lila live coding TCP server binary.
4 *
5 * This program launches the Lila server, which enables interactive live coding sessions
6 * over TCP for MayaFlux. It parses command-line options for port, verbosity, and log level,
7 * sets up signal handling for graceful shutdown, and manages the main server loop.
8 *
9 * @note This binary is a reference implementation of the Lila server.
10 * Community module types are not available as they require the host
11 * process to have them linked in. For community module support, embed
12 * Lila via MayaFluxHost::start_lila() in your project binary instead.
13 *
14 * Usage:
15 * lila_server [OPTIONS]
16 *
17 * Options:
18 * -p, --port <port> Server port (default: 9090)
19 * -v, --verbose Enable verbose logging
20 * -l, --level <level> Set log level (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
21 * -h, --help Show help message
22 */
23
24#include "Lila/Commentator.hpp"
25#include "Lila/Lila.hpp"
26
27#include "Lila/EventBus.hpp"
28
29#include <atomic>
30#include <csignal>
31#include <iostream>
32
33/**
34 * @brief Global flag to control server running state.
35 */
36std::atomic<bool> g_running { true };
37
38/**
39 * @brief Handles SIGINT and SIGTERM for graceful shutdown.
40 * @param signal Signal number
41 */
42void signal_handler(int signal)
43{
44 if (signal == SIGINT || signal == SIGTERM) {
45 LILA_INFO(Lila::Emitter::SYSTEM, "Received shutdown signal");
46 g_running = false;
47 }
48}
49
50/**
51 * @brief Prints usage information for the server binary.
52 * @param program_name Name of the executable
53 */
54void print_usage(const char* program_name)
55{
56 std::cout << "Usage: " << program_name << " [OPTIONS]\n"
57 << "\nOptions:\n"
58 << " -p, --port <port> Server port (default: 9090)\n"
59 << " -v, --verbose Enable verbose logging\n"
60 << " -l, --level <level> Set log level (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)\n"
61 << " -h, --help Show this help message\n"
62 << "\nExamples:\n"
63 << " " << program_name << " # Start on default port 9090\n"
64 << " " << program_name << " -p 8080 # Start on port 8080\n"
65 << " " << program_name << " -v -l DEBUG # Verbose mode with DEBUG level\n"
66 << '\n';
67}
68
69/**
70 * @brief Parses a string to a Lila::LogLevel value.
71 * @param level_str Log level string
72 * @return Corresponding LogLevel enum value
73 */
74Lila::LogLevel parse_log_level(const std::string& level_str)
75{
76 if (level_str == "TRACE")
77 return Lila::LogLevel::TRACE;
78 if (level_str == "DEBUG")
79 return Lila::LogLevel::DEBUG;
80 if (level_str == "INFO")
81 return Lila::LogLevel::INFO;
82 if (level_str == "WARN")
83 return Lila::LogLevel::WARN;
84 if (level_str == "ERROR")
85 return Lila::LogLevel::ERROR;
86 if (level_str == "FATAL")
87 return Lila::LogLevel::FATAL;
88
89 LILA_WARN(Lila::Emitter::SYSTEM,
90 std::string("Unknown log level '") + level_str + "', using INFO");
91 return Lila::LogLevel::INFO;
92}
93
94/**
95 * @brief Main entry point for the Lila server binary.
96 * @param argc Argument count
97 * @param argv Argument vector
98 * @return Exit code
99 */
100int main(int argc, char** argv)
101{
102 int port = 9090;
103 bool verbose = false;
104 Lila::LogLevel log_level = Lila::LogLevel::INFO;
105
106 for (int i = 1; i < argc; ++i) {
107 std::string arg = argv[i];
108
109 if (arg == "-h" || arg == "--help") {
110 print_usage(argv[0]);
111 return 0;
112 }
113
114 if (arg == "-p" || arg == "--port") {
115 if (i + 1 < argc) {
116 port = std::atoi(argv[++i]);
117 if (port <= 0 || port > 65535) {
118 std::cerr << "Error: Invalid port number\n";
119 return 1;
120 }
121 } else {
122 std::cerr << "Error: --port requires an argument\n";
123 return 1;
124 }
125 } else if (arg == "-v" || arg == "--verbose") {
126 verbose = true;
127 } else if (arg == "-l" || arg == "--level") {
128 if (i + 1 < argc) {
129 log_level = parse_log_level(argv[++i]);
130 } else {
131 std::cerr << "Error: --level requires an argument\n";
132 return 1;
133 }
134 } else {
135 std::cerr << "Error: Unknown option '" << arg << "'\n";
136 print_usage(argv[0]);
137 return 1;
138 }
139 }
140
141 auto& logger = Lila::Commentator::instance();
142 logger.set_level(log_level);
143 logger.set_verbose(verbose);
144
145 std::signal(SIGINT, signal_handler);
146 std::signal(SIGTERM, signal_handler);
147
148 LILA_INFO(Lila::Emitter::SYSTEM, "Starting Lila live coding server");
149 LILA_INFO(Lila::Emitter::SYSTEM, std::string("Port: ") + std::to_string(port));
150
151 std::string level_str;
152 switch (log_level) {
153 case Lila::LogLevel::TRACE:
154 level_str = "TRACE";
155 break;
156 case Lila::LogLevel::DEBUG:
157 level_str = "DEBUG";
158 break;
159 case Lila::LogLevel::INFO:
160 level_str = "INFO";
161 break;
162 case Lila::LogLevel::WARN:
163 level_str = "WARN";
164 break;
165 case Lila::LogLevel::ERROR:
166 level_str = "ERROR";
167 break;
168 case Lila::LogLevel::FATAL:
169 level_str = "FATAL";
170 break;
171 default:
172 level_str = "UNKNOWN";
173 break;
174 }
175 LILA_INFO(Lila::Emitter::SYSTEM, std::string("Log level: ") + level_str);
176
177 if (verbose) {
178 LILA_INFO(Lila::Emitter::SYSTEM, "Verbose mode enabled");
179 }
180
181 Lila::Lila playground;
182
183 if (!playground.initialize(Lila::OperationMode::Server, port)) {
184 LILA_FATAL(Lila::Emitter::SYSTEM,
185 std::string("Failed to initialize: ") + playground.get_last_error());
186 return 1;
187 }
188
189 playground.on_server_started([]() {
190 std::cout << "LILA_SERVER_READY\n"
191 << std::flush;
192 LILA_INFO(Lila::Emitter::SYSTEM, "Server is ready to accept connections");
193 });
194
195 playground.on_success([]() {
196 LILA_INFO(Lila::Emitter::GENERAL, "Code evaluation succeeded");
197 });
198
199 /*
200 playground.on_error([](const std::string& error) {
201 LILA_ERROR(Lila::Emitter::GENERAL,
202 std::string("Evaluation error: ") + error);
203 });
204 */
205
206 playground.on_server_client_connected([](const Lila::ClientInfo& client) {
207 LILA_INFO(Lila::Emitter::SERVER,
208 std::string("New client connection (fd: ") + std::to_string(client.fd) + ", session: " + (client.session_id.empty() ? "none" : client.session_id) + ")");
209 });
210
211 playground.on_server_client_disconnected([](const Lila::ClientInfo& client) {
212 LILA_INFO(Lila::Emitter::SERVER,
213 std::string("Client disconnected (fd: ") + std::to_string(client.fd) + ", session: " + (client.session_id.empty() ? "none" : client.session_id) + ")");
214 });
215
216 LILA_INFO(Lila::Emitter::SYSTEM, "Server running. Press Ctrl+C to stop.");
217
218 playground.await_shutdown(&g_running);
219
220 LILA_INFO(Lila::Emitter::SYSTEM, "Shutting down...");
221 playground.stop_server();
222 LILA_INFO(Lila::Emitter::SYSTEM, "Goodbye!");
223
224 return 0;
225}
#define LILA_WARN(emitter, msg)
#define LILA_INFO(emitter, msg)
#define LILA_FATAL(emitter, msg)
static Commentator & instance()
bool initialize(OperationMode mode=OperationMode::Direct, int server_port=9090, bool skip_host_library_load=false) noexcept
Initializes the live coding environment.
Definition Lila.cpp:32
void stop_server()
Stops the TCP server and disconnects all clients.
Definition Lila.cpp:137
void on_server_client_disconnected(std::function< void(const ClientInfo &)> callback)
Registers a callback for client disconnections (server mode)
Definition Lila.cpp:210
void on_server_client_connected(std::function< void(const ClientInfo &)> callback)
Registers a callback for new client connections (server mode)
Definition Lila.cpp:202
std::string get_last_error() const
Gets the last error message.
Definition Lila.cpp:218
void await_shutdown(const std::atomic< bool > *external_flag)
Blocks until server shutdown (main thread event loop)
Definition Lila.cpp:228
void on_success(std::function< void()> callback)
Registers a callback for successful code evaluation.
Definition Lila.cpp:182
void on_server_started(std::function< void()> callback)
Registers a callback for server start events.
Definition Lila.cpp:194
void signal_handler(int signal)
Handles SIGINT and SIGTERM for graceful shutdown.
int main(int argc, char **argv)
Main entry point for the Lila server binary.
Lila::LogLevel parse_log_level(const std::string &level_str)
Parses a string to a Lila::LogLevel value.
std::atomic< bool > g_running
Global flag to control server running state.
void print_usage(const char *program_name)
Prints usage information for the server binary.
std::string session_id
Session identifier (if set)
Definition EventBus.hpp:60
int fd
Client socket file descriptor.
Definition EventBus.hpp:59
Information about a connected client.
Definition EventBus.hpp:58