| 261 | } // namespace PINEServer |
| 262 | |
| 263 | bool PINEServer::Initialize(int slot) |
| 264 | { |
| 265 | s_end.store(false, std::memory_order_release); |
| 266 | s_slot = slot; |
| 267 | |
| 268 | #ifdef _WIN32 |
| 269 | if (!InitializeWinsock()) |
| 270 | { |
| 271 | Console.WriteLn(Color_Red, "PINE: Cannot initialize winsock! Shutting down..."); |
| 272 | Deinitialize(); |
| 273 | return false; |
| 274 | } |
| 275 | |
| 276 | s_sock = socket(AF_INET, SOCK_STREAM, 0); |
| 277 | if ((s_sock == INVALID_SOCKET) || slot > 65536) |
| 278 | { |
| 279 | Console.WriteLn(Color_Red, "PINE: Cannot open socket! Shutting down..."); |
| 280 | Deinitialize(); |
| 281 | return false; |
| 282 | } |
| 283 | |
| 284 | sockaddr_in server = {}; |
| 285 | server.sin_family = AF_INET; |
| 286 | server.sin_addr.s_addr = htonl(INADDR_LOOPBACK); // localhost only |
| 287 | server.sin_port = htons(slot); |
| 288 | |
| 289 | if (bind(s_sock, (struct sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) |
| 290 | { |
| 291 | Console.WriteLn(Color_Red, "PINE: Error while binding to socket! Shutting down..."); |
| 292 | Deinitialize(); |
| 293 | return false; |
| 294 | } |
| 295 | |
| 296 | #else |
| 297 | char* runtime_dir = nullptr; |
| 298 | #ifdef __APPLE__ |
| 299 | runtime_dir = std::getenv("TMPDIR"); |
| 300 | #else |
| 301 | runtime_dir = std::getenv("XDG_RUNTIME_DIR"); |
| 302 | #endif |
| 303 | // fallback in case macOS or other OSes don't implement the XDG base |
| 304 | // spec |
| 305 | if (runtime_dir == nullptr) |
| 306 | s_socket_name = "/tmp/" PINE_EMULATOR_NAME ".sock"; |
| 307 | else |
| 308 | { |
| 309 | s_socket_name = runtime_dir; |
| 310 | s_socket_name += "/" PINE_EMULATOR_NAME ".sock"; |
| 311 | } |
| 312 | |
| 313 | if (slot != PINE_DEFAULT_SLOT) |
| 314 | s_socket_name += "." + std::to_string(slot); |
| 315 | |
| 316 | struct sockaddr_un server; |
| 317 | |
| 318 | s_sock = socket(AF_UNIX, SOCK_STREAM, 0); |
| 319 | if (s_sock < 0) |
| 320 | { |