PHP Classes

File: scripts/binkp_server.php

Recommend this page to a friend!
  Packages of Matthew Asham   Binkterm PHP   scripts/binkp_server.php   Download  
File: scripts/binkp_server.php
Role: Example script
Content type: text/plain
Description: Example script
Class: Binkterm PHP
Bulletin board system based on the Web
Author: By
Last change:
Date: 5 days ago
Size: 5,029 bytes
 

Contents

Class file image Download
#!/usr/bin/env php
<?php

chdir
(__DIR__."/../");

require_once
__DIR__ . '/../vendor/autoload.php';

use
BinktermPHP\Binkp\Protocol\BinkpServer;
use
BinktermPHP\Binkp\Config\BinkpConfig;
use
BinktermPHP\Binkp\Logger;
use
BinktermPHP\Version;

function
showUsage()
{
    echo
"Usage: php binkp_server.php [options]\n";
    echo
"Options:\n";
    echo
" --port=PORT Listen on specific port (default: from config)\n";
    echo
" --bind=ADDRESS Bind to specific address (default: from config)\n";
    echo
" --log-level=LEVEL Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL\n";
    echo
" --log-file=FILE Log file path (default: " . \BinktermPHP\Config::getLogPath('binkp_server.log') . ")\n";
    echo
" --no-console Disable console logging\n";
    echo
" --daemon Run as daemon (detach from terminal)\n";
    echo
" --pid-file=FILE Write PID file\n";
    echo
" --help Show this help message\n";
    echo
"\n";
}

function
parseArgs($argv)
{
   
$args = [];
   
    foreach (
$argv as $arg) {
        if (
strpos($arg, '--') === 0) {
            if (
strpos($arg, '=') !== false) {
                list(
$key, $value) = explode('=', substr($arg, 2), 2);
               
$args[$key] = $value;
            } else {
               
$args[substr($arg, 2)] = true;
            }
        }
    }
   
    return
$args;
}

function
daemonize()
{
   
$pid = pcntl_fork();
   
    if (
$pid == -1) {
        die(
"Could not fork process\n");
    } elseif (
$pid) {
        echo
"Server started with PID: $pid\n";
        exit(
0);
    }
   
    if (
posix_setsid() == -1) {
        die(
"Could not detach from terminal\n");
    }
   
   
chdir('/');
   
umask(0);
   
   
fclose(STDIN);
   
fclose(STDOUT);
   
fclose(STDERR);
}

function
setConsoleTitle(string $title): void
{
    echo
"\033]0;{$title}\007";
}

$args = parseArgs($argv);
$defaultPidFile = __DIR__ . '/../data/run/binkp_server.pid';
$pidFile = $args['pid-file'] ?? (\BinktermPHP\Config::env('BINKP_SERVER_PID_FILE') ?: $defaultPidFile);

if (isset(
$args['help'])) {
   
showUsage();
    exit(
0);
}

try {
   
$config = BinkpConfig::getInstance();
   
    if (isset(
$args['port'])) {
       
$config->setBinkpConfig((int) $args['port']);
    }
   
    if (isset(
$args['bind'])) {
       
$config->setBinkpConfig(null, null, null, $args['bind']);
    }
   
   
$logLevel = isset($args['log-level']) ? $args['log-level'] : 'INFO';
   
$logFile = isset($args['log-file']) ? $args['log-file'] : \BinktermPHP\Config::getLogPath('binkp_server.log');
   
$logToConsole = !isset($args['no-console']);
   
   
$logger = new Logger($logFile, $logLevel, $logToConsole);
   
    if (isset(
$args['daemon']) && function_exists('pcntl_fork')) {
       
$logger->setLogToConsole(false);
       
daemonize();
    } else {
       
setConsoleTitle('BinktermPHP Binkp Server');
    }

    if (
$pidFile) {
       
$pidDir = dirname($pidFile);
        if (!
is_dir($pidDir)) {
            @
mkdir($pidDir, 0755, true);
        }
        @
file_put_contents($pidFile, (string)getmypid());
    }
   
   
$server = new BinkpServer($config, $logger);
   
   
$logger->info("Starting BinktermPHP binkd server ".Version::getVersion()."...");
   
$logger->info("System address: " . $config->getSystemAddress());
   
$logger->info("Listening on: " . $config->getBindAddress() . ":" . $config->getBinkpPort());
   
$logger->info("Max connections: " . $config->getMaxConnections());
   
$logger->info("Timeout: " . $config->getBinkpTimeout() . "s");
   
   
$uplinks = $config->getUplinks();
   
$logger->info("Configured uplinks: " . count($uplinks));
   
    foreach (
$uplinks as $uplink) {
       
$status = ($uplink['enabled'] ?? true) ? 'enabled' : 'disabled';
       
$logger->info(" - {$uplink['address']} ({$uplink['hostname']}) [{$status}]");
    }
   
   
// Enable async signal handling so handlers run immediately when signals arrive
   
if (function_exists('pcntl_async_signals')) {
       
pcntl_async_signals(true);
    }

    if (
function_exists('pcntl_signal')) {
       
pcntl_signal(SIGTERM, function() use ($server, $logger) {
           
$logger->info("Received SIGTERM, shutting down...");
           
$server->stop();
        });

       
pcntl_signal(SIGINT, function() use ($server, $logger) {
           
$logger->info("Received SIGINT, shutting down...");
           
$server->stop();
        });

       
pcntl_signal(SIGHUP, function() use ($server, $logger) {
           
$logger->info("Received SIGHUP, reloading configuration...");
            try {
               
// Force reload of config by getting a fresh instance
               
BinkpConfig::getInstance()->reloadConfig();
               
$logger->info("Configuration reloaded successfully");
            } catch (
Exception $e) {
               
$logger->error("Failed to reload configuration: " . $e->getMessage());
            }
        });
    }
   
   
$server->start();
   
} catch (
Exception $e) {
    echo
"Error: " . $e->getMessage() . "\n";
    exit(
1);
}