Skip to content

Instantly share code, notes, and snippets.

@weltling
Created April 23, 2018 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save weltling/0d78544fa3b4c1342027229aaf7ae43c to your computer and use it in GitHub Desktop.
Save weltling/0d78544fa3b4c1342027229aaf7ae43c to your computer and use it in GitHub Desktop.
<?php
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$is_master_proc = !isset($argv[1]) || !$argv[1];
if ($is_master_proc) {
$address = 'localhost';
//$address = '::1';
$port = 10000;
if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
//if (($sock = socket_create(AF_INET6, SOCK_STREAM, SOL_TCP)) === false) {
fprintf(STDERR, "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n");
}
if (socket_bind($sock, $address, $port) === false) {
fprintf(STDERR, "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n");
}
if (socket_listen($sock, 5) === false) {
fprintf(STDERR, "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\n");
}
echo "parent: ", getmypid(), PHP_EOL;
$cwd = getcwd();
$env = getenv();
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "a"),
);
$cmd = PHP_BINARY . " -n -c " . php_ini_loaded_file() . " " . $_SERVER["PHP_SELF"] . " 1";
$extra = array("bypass_shell" => true);
$process = proc_open($cmd, $descriptorspec, $pipes, $cwd, $env, $extra);
if (is_resource($process)) {
$status = proc_get_status($process);
$pid = $status["pid"];
echo "child: ", $pid, PHP_EOL;
$info = socket_wsaprotocol_info_export($sock, $pid);
fwrite($pipes[0], $info);
fflush($pipes[0]);
$it = 42;
do {
if ("wsaprotocol_info_import_ok" == fread($pipes[1], 1024)) {
socket_wsaprotocol_info_release($info);
break;
}
usleep(300);
$status = proc_get_status($process);
} while ($status["running"] && 0 > $it--);
do {
echo fread($pipes[1], 1024);
echo fread($pipes[2], 1024);
usleep(300);
$status = proc_get_status($process);
} while ($status["running"]);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
$status = proc_close($process);
exit((int)$status);
}
} else {
$pid = getmypid();
$info = fread(STDIN, 1024);
$sock = socket_wsaprotocol_info_import($info);
if (!$sock) {
fprintf(STDERR, "PID: $pid: couldn't import socket");
exit(3);
}
fprintf(STDOUT, "wsaprotocol_info_import_ok");
fflush(STDOUT);
do {
if (($msgsock = socket_accept($sock)) === false) {
fprintf(STDERR, "socket_accept() failed: reason: " . socket_strerror(socket_last_error($sock)) . "\r\n");
fflush(STDERR);
break;
}
fprintf(STDOUT, "PID: $pid: incoming connection\r\n");
fflush(STDOUT);
/* Send instructions. */
$msg = "\r\nWelcome to the PHP Test Server. \r\n" .
"To quit, type 'quit'. To shut down the server type 'shutdown'.\r\n";
socket_write($msgsock, $msg, strlen($msg));
do {
if (false === ($buf = socket_read($msgsock, 2048, PHP_NORMAL_READ))) {
fprintf(STDERR, "socket_read() failed: reason: " . socket_strerror(socket_last_error($msgsock)) . "\r\n");
fflush(STDERR);
break 2;
}
if (!$buf = trim($buf)) {
continue;
}
if ($buf == 'quit') {
fprintf(STDOUT, "PID: $pid: connection quit\r\n");
fflush(STDOUT);
break;
}
if ($buf == 'shutdown') {
fprintf(STDOUT, "PID: $pid: shutdown\r\n");
fflush(STDOUT);
socket_close($msgsock);
break 2;
}
$talkback = "You said '$buf'.\r\n";
socket_write($msgsock, $talkback, strlen($talkback));
fprintf(STDOUT, "PID: $pid: $buf\r\n");
fflush(STDOUT);
fflush(STDERR);
} while (true);
socket_close($msgsock);
} while (true);
}
socket_close($sock);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment