forked from solderpunk/molly-brown
Initial bare bones implementation.
This commit is contained in:
parent
f686d23c40
commit
0ddf8ca2ae
|
@ -0,0 +1,41 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Port int
|
||||||
|
Hostname string
|
||||||
|
CertPath string
|
||||||
|
KeyPath string
|
||||||
|
DocBase string
|
||||||
|
HomeDocBase string
|
||||||
|
LogPath string
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfig(filename string) (Config, error) {
|
||||||
|
|
||||||
|
var config Config
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
config.Port = 196
|
||||||
|
config.Hostname = "localhost"
|
||||||
|
config.CertPath = "cert.pem"
|
||||||
|
config.KeyPath = "key.pem"
|
||||||
|
config.DocBase = "/var/gemini/"
|
||||||
|
config.HomeDocBase = "users"
|
||||||
|
config.LogPath = "molly.log"
|
||||||
|
|
||||||
|
// Return defaults if no filename given
|
||||||
|
if filename == "" {
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to overwrite defaults from file
|
||||||
|
_, err := toml.DecodeFile(filename, &config)
|
||||||
|
if err != nil {
|
||||||
|
return config, err
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleGeminiRequest(conn net.Conn, config Config) {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
// Read request
|
||||||
|
reader := bufio.NewReaderSize(conn, 1024)
|
||||||
|
request, overflow, err := reader.ReadLine()
|
||||||
|
if overflow {
|
||||||
|
conn.Write([]byte("59 Request too long!r\n"))
|
||||||
|
return
|
||||||
|
} else if err != nil {
|
||||||
|
conn.Write([]byte("40 Unknown error reading request!r\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse request as URL
|
||||||
|
URL, err := url.Parse(string(request))
|
||||||
|
if err != nil {
|
||||||
|
conn.Write([]byte("59 Error parsing URL!r\n"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generic response
|
||||||
|
conn.Write([]byte("20 text/gemini\r\n"))
|
||||||
|
body := fmt.Sprintf("Molly at %s says \"Hi!\" from %s.\n", URL.Host, URL.Path)
|
||||||
|
conn.Write([]byte(body))
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var conf_file string
|
||||||
|
|
||||||
|
// Parse args and read config
|
||||||
|
flag.StringVar(&conf_file, "c", "", "Path to config file")
|
||||||
|
flag.Parse()
|
||||||
|
if conf_file == "" {
|
||||||
|
_, err := os.Stat("/etc/molly.conf")
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
conf_file = "/etc/molly.conf"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config, err := getConfig(conf_file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error reading config file " + conf_file)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read TLS files, create TLS config
|
||||||
|
cert, err := tls.LoadX509KeyPair(config.CertPath, config.KeyPath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
tlscfg := &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
MinVersion: tls.VersionTLS12,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create TLS listener
|
||||||
|
listener, err := tls.Listen("tcp", ":1965", tlscfg)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer listener.Close()
|
||||||
|
|
||||||
|
// Infinite serve loop
|
||||||
|
for {
|
||||||
|
conn, err := listener.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
go handleGeminiRequest(conn, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue