summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TO_FIX.md2
-rw-r--r--config.toml.sample6
-rwxr-xr-xgmi.pl67
3 files changed, 52 insertions, 23 deletions
diff --git a/TO_FIX.md b/TO_FIX.md
index 16f30ee..e2998bd 100644
--- a/TO_FIX.md
+++ b/TO_FIX.md
@@ -13,5 +13,3 @@ make log output user adjustable
add client certificate stuff
add gmiaccess stuff
-
-set fork() usage toggleable
diff --git a/config.toml.sample b/config.toml.sample
index 3552ae3..ca6313f 100644
--- a/config.toml.sample
+++ b/config.toml.sample
@@ -21,6 +21,10 @@ cert_key_dir = "certs" # avoid putting final '/'
# because generating cert/key pairs will fail and cause the program to die.
# Setting the following to 'false' will not emit an error.
cert_key_dir_write_warning = true
+# For each accepted connection a fork() is called. This toggles if that should happen or not.
+# For debugging or memory reasons, it may help to set this to false, though it may result in clients timing out if your server is busy serving a client.
+# Will cause 'timed-out' and 'sysread failed' to appear at the same time in log files.
+fork = true
## These are not specific to default and can be used with vhost
## Vhost options will override default options
@@ -43,6 +47,8 @@ default_mime = 'text/plain'
# A Vhost is *required* since it both serves as vhost and server name identification (sni)
# Vhost example - probably you want to see that it actually works right away
+# `$ ncat --ssl localhost 1965'. Quick! You have 5 seconds! type: 'gemini://localhost ' (don't forget the whitespace as required by gemini spec)
+# (ncat (probably) packaged with nmap)
['localhost']
# Generate certificate and key automatically? Uses cert_key_dir
auto_cert = true
diff --git a/gmi.pl b/gmi.pl
index 69a87e9..d950d50 100755
--- a/gmi.pl
+++ b/gmi.pl
@@ -7,7 +7,7 @@ use warnings;
use 5.010;
#use diagnostics;
-our $VERSION = 'v0.0.6';
+our $VERSION = 'v0.0.7';
# Modules
use IO::Socket::SSL; # CPAN
@@ -15,7 +15,7 @@ use IO::Socket::SSL::Utils; # CPAN
use URL::XS qw(parse_url split_url_path parse_url_query); # CPAN
#use Term::ANSIColor; # Core
use Path::Naive qw(normalize_path); # CPAN
-use Smart::Comments; # CPAN
+#use Smart::Comments; # CPAN
use URI::Encode qw(uri_encode); # CPAN
use IO::Select;
use TOML qw(from_toml);
@@ -50,7 +50,7 @@ our %GEM_RES_CODES = (
our @VALID_DEFAULT_SETTINGS =
qw/bind ports tls assume_index dir_listing root working_dir cert_key_dir
- log_file log_to_stdout default_mime cert_key_dir_write_warning/;
+ log_file log_to_stdout default_mime cert_key_dir_write_warning fork/;
our @VALID_VHOST_SETTINGS =
qw/auto_cert assume_index dir_listing root cert key default_mime/;
@@ -275,6 +275,20 @@ for my $vhost (keys %{ $config }) {
}
}
+# fork() toggle
+my $fork_toggled = 1;
+if (exists $config->{default}{fork}) {
+ if ($config->{default}{fork} eq 'true') {
+ $fork_toggled = 1;
+ }
+ elsif ($config->{default}{fork} eq 'false') {
+ $fork_toggled = 0;
+ }
+ else {
+ say STDERR "default: fork value ($config->{default}{fork}) is not true/false. Will assume true.";
+ }
+}
+
# let the user know if an invalid option was used
for my $option (keys %{ $config->{default} }) {
my $valid = 0;
@@ -312,14 +326,17 @@ say $out "Server Started on ". localtime();
# Main server loop
while () {
my $cl = $srv->accept() or next;
- my $pid = fork();
- if (not defined $pid) {
- warn "Cannot make a child: $!";
- next;
- }
- if ($pid) {
- undef $cl;
- next;
+
+ if ($fork_toggled) {
+ my $pid = fork();
+ if (not defined $pid) {
+ warn "Cannot make a child: $!";
+ next;
+ }
+ if ($pid) {
+ undef $cl;
+ next;
+ }
}
#close STDIN;
@@ -334,14 +351,14 @@ while () {
} elsif ($opened == -1) {
print $out "IO::Handle opened but the SSL handshake failed.\n";
$cl->close('SHUT_WR');
- exit;
+ exit if ($fork_toggled);
} elsif (! $opened) {
print $out "Socket could not be opened.\n";
- exit;
+ exit if ($fork_toggled);
}
else {
print $out "Something is very wrong.\n";
- exit;
+ exit if ($fork_toggled);
}
my $data;
@@ -351,17 +368,18 @@ while () {
eval {
# We do this because 'naughty' people/bots can clog up the ports doing nothing.
- local $SIG{ALRM} = sub {
+ local $SIG{ALRM} = sub {
+ # cannot goto, we are in a subroutine that gets called when ALRM is triggered.
say $out "$clhost - ($cl_sni) timed-out [". localtime(). ']';
$cl->close('SHUT_WR');
- exit;
+ exit if ($fork_toggled);
};
alarm 5; # TODO make magic number not magic.
if ( ! sysread($cl, $data, 1024) ) {
- $log = "$clhost - ($cl_sni) sysread failed ... Invalid certificate/key?";
+ $log = "$clhost - ($cl_sni) sysread failed";
+ alarm 0;
goto CLOSE;
- exit;
}
alarm 0;
@@ -373,13 +391,19 @@ while () {
eval {
$url = parse_url($data);
};
+
+ # TODO: make user adjustable
+ $log = "$clhost - ($cl_sni) $data";
+
+ if (! $url) {
+ speak($cl, 'bad_request');
+ goto CLOSE;
+ }
$path = $url->{path};
### $data
### $url
# ## $path
- # TODO: make user adjustable
- $log = "$clhost - ($cl_sni) $data";
my $vhost = $url->{host};
my $doc;
@@ -471,7 +495,8 @@ while () {
CLOSE:
$cl->close('SHUT_WR');
print $out "$log [". localtime(). "]\n";
- exit;
+
+ exit if ($fork_toggled);
}
$srv->close();