Browse Source

Working Gemini Support

main
Tanner Mckenney 3 years ago
parent
commit
e6e446a65a
  1. 20
      src/Request.php
  2. 58
      src/Response.php
  3. 121
      src/Server.php
  4. 18
      test/server.php

20
src/Request.php

@ -6,5 +6,25 @@ namespace TitanII; @@ -6,5 +6,25 @@ namespace TitanII;
* Gemini Request
*/
class Request {
/**
* Maximum length in bytes of the URL request.
*/
const MAX_LENGTH = 1024;
/**
* URL string.
*
* @var string
*/
private string $url;
public function __construct(string $url)
{
$this->url = substr($url, 0, self::MAX_LENGTH);
}
public function __toString(): string
{
return $this->url;
}
}

58
src/Response.php

@ -6,5 +6,61 @@ namespace TitanII; @@ -6,5 +6,61 @@ namespace TitanII;
* Gemini Response
*/
class Response {
/**
* Valid Response Codes
*/
const CODES = [10, 11, 20, 30, 31, 40, 41, 42, 43, 44, 50, 51, 52, 53, 59, 60, 61, 62];
/**
* Response Code
*
* @var int
*/
private int $code = 20;
/**
* Meta Data
*
* @var string
*/
private string $meta = "application/octet-stream";
/**
* Body Content.
*
* @var string
*/
private string $content = "";
public function __construct()
{
}
public function setCode(int $code): self
{
if (!in_array($code, self::CODES)) {
throw new \Exception("Not a valid Gemini response code!");
}
$this->code = $code;
return $this;
}
public function setMeta(string $meta): self
{
$this->meta = $meta;
return $this;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function __toString(): string
{
return $this->code . ' ' . $this->meta . "\r\n" . $this->content;
}
}

121
src/Server.php

@ -11,10 +11,125 @@ use TitanII\Response; @@ -11,10 +11,125 @@ use TitanII\Response;
* @author Tanner Mckenney <tmckenney7@outlook.com>
*/
class Server {
public function start(callable $action): void
/**
* Context created by stream_context_create();
*
* @var resource
*/
private $context = null;
/**
* Socket created by stream_socket_server();
*
* @var resource
*/
private $socket = null;
/**
* Function that gets called to handle incoming requests.
*
* @var callable
*/
private $handler = null;
/**
* Server active flag.
*
* @var bool
*/
private bool $active = false;
/**
* Constructor
*/
public function __construct()
{
$request = new Request();
$this->context = stream_context_create();
stream_context_set_option($this->context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($this->context, 'ssl', 'verify_peer', false);
}
$response = $action($request);
/**
* @param callable Handle incoming requests.
*
* Parameter 1 Callable is expected to handle the following:
*
* @param Request
*
* @return Response
*/
public function setHandler(callable $handler): self
{
$this->handler = $handler;
return $this;
}
public function setCert(string $file): self
{
stream_context_set_option($this->context, 'ssl', 'local_cert', $file);
return $this;
}
public function setCertPassphrase(string $passphrase): self
{
stream_context_set_option($this->context, 'ssl', 'passphrase', $passphrase);
return $this;
}
public function setKey(string $key): self
{
stream_context_set_option($this->context, 'ssl', 'local_pk', $key);
return $this;
}
protected function openSocket(string $ip, int $port): bool
{
$addr = "tcp://" . $ip . ':' . $port;
$this->socket = stream_socket_server($addr, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $this->context);
if (empty($this->socket)) {
return false;
}
stream_socket_enable_crypto($this->socket, false);
return true;
}
public function start(string $ip = '0', int $port = 1965): void
{
$this->openSocket($ip, $port);
$this->active = true;
while ($this->active) {
$incoming = stream_socket_accept($this->socket, -1, $peername);
stream_set_blocking($incoming, true);
stream_socket_enable_crypto($incoming, true, STREAM_CRYPTO_METHOD_TLSv1_2_SERVER);
$body = fread($incoming, 1024);
stream_set_blocking($incoming, false);
$request = new Request($body);
$response = call_user_func($this->handler, $request);
fwrite($incoming, $response);
fclose($incoming);
}
}
public function stop(): void
{
$this->active = false;
}
}

18
test/server.php

@ -10,6 +10,18 @@ use TitanII\Response; @@ -10,6 +10,18 @@ use TitanII\Response;
$server = new Server();
$server->start(function (Request $request): Response {
return new Response();
});
$server->setCert(__DIR__ . DIRECTORY_SEPARATOR . 'certs' . DIRECTORY_SEPARATOR . 'cert.pem');
$server->setKey(__DIR__ . DIRECTORY_SEPARATOR . 'certs' . DIRECTORY_SEPARATOR . 'key.rsa');
$server->setHandler(function (Request $request): Response {
$response = new Response();
$response->setMeta('text/plain');
$response->setContent("Hello world!");
echo $request;
return $response;
});
$server->start();
Loading…
Cancel
Save