Initial bare bones implementation.
This commit is contained in:
parent
f686d23c40
commit
0ddf8ca2ae
3 changed files with 132 additions and 0 deletions
41
config.go
Normal file
41
config.go
Normal file
|
@ -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
|
||||
}
|
35
handler.go
Normal file
35
handler.go
Normal file
|
@ -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))
|
||||
}
|
56
main.go
Normal file
56
main.go
Normal file
|
@ -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 a new issue