xaizek / rocketgit (License: AGPLv3+) (since 2018-12-09)
Light and fast Git hosting solution suitable to serve both as a hub or as a personal code storage with its tickets, pull requests, API and much more.
<root> / inc / conn.inc.php (ecb8c941df4067cbca9e45c29bfd51af2be8f50d) (3,904B) (mode 100644) [raw]
<?php
$INC = isset($INC) ? $INC : dirname(__FILE__);

$rg_conns = array();
$rg_events = array('r' => array(), 'w' => array());

/*
 * Prepares a string to be sent over a socket
 */
function rg_conn_prepare($s)
{
	if (is_array($s))
		$s = serialize($s);
	return addcslashes($s, "\n\r\\");
}

/*
 * Destroys a connection
 */
function rg_conn_destroy($key)
{
	global $rg_conns;
	global $rg_events;

	if (!isset($rg_conns[$key]))
		rg_internal_error('key not defined!');

	if ($rg_conns[$key]['exit_on_close'])
		exit(1);

	if (isset($rg_events['r'][$key]))
		unset($rg_events['r'][$key]);
	if (isset($rg_events['w'][$key]))
		unset($rg_events['w'][$key]);
	if (isset($rg_conns[$key]['socket']))
		if (is_resource($rg_conns[$key]['socket']))
			@socket_close($rg_conns[$key]['socket']);
	unset($rg_conns[$key]);
}

/*
 * Registers a new socket
 */
function rg_conn_new($key, $socket)
{
	global $rg_conns;
	global $rg_events;

	$rg_conns[$key] = array(
		'socket' => $socket,
		'recv' => '',
		'send' => '',
		'itime' => time(),
		'exit_on_close' => 0,
		'func_error' => 'rg_conn_func_error',
		'func_close' => 'rg_conn_func_close'
	);

	$rg_events['r'][$key] = $socket;
	socket_set_nonblock($socket);
}

/*
 * Enqueues data to a socket
 */
function rg_conn_enq($key, $buf)
{
	global $rg_conns;
	global $rg_events;

	$s = &$rg_conns[$key];
	$s['send'] .= $buf;
	$rg_events['w'][$key] = $s['socket'];
}

/*
 * Called when a socket is ready to send data
 */
function rg_conn_send($key)
{
	global $rg_conns;
	global $rg_events;

	$s = &$rg_conns[$key];
	rg_log('SEND: ' . $s['send']);
	$r = @socket_send($s['socket'], $s['send'], strlen($s['send']), 0);
	if ($r === FALSE) {
		rg_log('Cannot receive!');
		$s['func_error']($key);
		rg_conn_destroy($key);
		return FALSE;
	}

	$s['send'] = substr($s['send'], $r);
	if (empty($s['send']))
		unset($rg_events['w'][$key]);

	return $r;
}

/*
 * Called when a socket is ready to be read
 */
function rg_conn_recv($key)
{
	global $rg_conns;
	global $rg_events;

	$s = &$rg_conns[$key];

	if (isset($s['func_new'])) {
		$client = @socket_accept($s['socket']);
		if ($client === FALSE) {
			rg_log('Cannot accept!');
			return;
		}

		if (isset($s['func_new_arg']))
			$arg = $s['func_new_arg'];
		else
			$arg = FALSE;

		socket_set_nonblock($client);
		$c = intval($client);
		rg_conn_new($c, $client);
		$s['func_new']($c, $arg);
		return;
	}

	$r = @socket_recv($s['socket'], $buf, 4096, 0);
	if ($r === FALSE) {
		rg_log('Cannot receive!');
		$s['func_error']($key);
		rg_conn_destroy($key);
		return FALSE;
	}
	if ($r === 0) {
		rg_log('Cannot receive!');
		$s['func_close']($key);
		rg_conn_destroy($key);
		return FALSE;
	}
	rg_log('RECV: ' . $buf);

	$s['recv'] .= $buf;

	if (isset($s['func_data'])) {
		$s['func_data']($key);
		return;
	}

	if (!isset($s['func_cmd'])) {
		rg_log_ml('key=' . $key . '; s: ' . print_r($s, TRUE));
		rg_log('Neithter func_data nor func_cmd present!');
		return;
	}

	while (1) {
		$pos = strpos($s['recv'], "\n");
		if ($pos === FALSE)
			break;

		$cmd = substr($s['recv'], 0, $pos);
		$s['recv'] = substr($s['recv'], $pos + 1);
		$s['func_cmd']($key, $cmd);
	}
}

/*
 * Function that waits for activity and calls different functions
 */
function rg_conn_wait($timeout)
{
	global $rg_conns;
	global $rg_events;

	$r2 = $rg_events['r'];
	$w2 = $rg_events['w'];
	$e2 = array();

	$r = @socket_select($r2, $w2, $e2, $timeout);
	if ($r === FALSE) {
		rg_log('Cannot select: ' . socket_strerror(socket_last_error()));
		return;
	}
	if ($r === 0)
		return;

	foreach ($r2 as $key => $sock)
		rg_conn_recv($key);

	foreach ($w2 as $key => $sock)
		rg_conn_send($key);

	foreach ($e2 as $key => $sock)
		rg_conn_destroy($key);
}

/*
 * Generic function called when there is an error on a socket
 */
function rg_conn_func_error($key)
{
}

/*
 * Generic function called when a socket closes
 */
function rg_conn_func_close($key)
{
}

?>
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/rocketgit

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/rocketgit

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master