Reorganized package tree and added doc comments

This commit is contained in:
Sasha Koshka 2023-05-26 01:18:16 -04:00
parent c300567c0c
commit 60e5a1c729
11 changed files with 48 additions and 44 deletions

View File

@ -1,7 +1,9 @@
// Config provides a configuration system for routers.
package config
import "crypto/tls"
// Config is an interface that configuration objects must fulfill.
type Config interface {
User (name string) User
OverUsers (func (name string, user User) bool)
@ -22,6 +24,7 @@ type Config interface {
OverAliases (func (alias, target string) bool)
}
// User represents a Hnakra user.
type User interface {
Validate (key []byte) bool
RconAllow () bool

View File

@ -3,10 +3,12 @@ package mux
import "net/url"
import "net/http"
// HTTP is an HTTP request multiplexer.
type HTTP struct {
Mux[http.Handler]
}
// NewHTTP creates a new HTTP request multiplexer.
func NewHTTP (resolver Resolver) *HTTP {
mux := &HTTP { }
mux.Mux.Redirect = mux.newRedirect

View File

@ -1,3 +1,4 @@
// Package mux provides request multiplexers for all protocols Hnakra supports.
package mux
import "net"
@ -8,6 +9,8 @@ import "errors"
import "strings"
import "net/url"
// Resolver represents an object capable of transforming a hosname alias into
// another hostname.
type Resolver interface {
ResolveAlias (alias string) string
}
@ -68,6 +71,7 @@ func stripHostPort (h string) string {
return host
}
// Handler returns the handler for a particular URL.
func (mux *Mux[HANDLER]) Handler (where *url.URL) (h HANDLER, pattern string) {
// All other requests have any port stripped and path cleaned
// before passing to mux.handler.
@ -144,6 +148,10 @@ func (mux *Mux[HANDLER]) match (path string, original *url.URL) (h HANDLER, patt
return mux.NotFound(original), ""
}
// Handle registers a handler on the specified pattern. If a pattern ends in
// '/', all requests for URLS under the pattern will be directed to the handler,
// as well as the pattern itself. Additionally, requests for the pattern without
// the trailing slash will be redirected to the pattern with the trailing slash.
func (mux *Mux[HANDLER]) Handle (pattern string, handler HANDLER) error {
mux.mutex.Lock()
defer mux.mutex.Unlock()
@ -176,6 +184,7 @@ func (mux *Mux[HANDLER]) Handle (pattern string, handler HANDLER) error {
return nil
}
// Unhandler removes the handler that was registered on the specified pattern.
func (mux *Mux[HANDLER]) Unhandle (pattern string) error {
mux.mutex.Lock()
defer mux.mutex.Unlock()
@ -199,6 +208,7 @@ func (mux *Mux[HANDLER]) Unhandle (pattern string) error {
return nil
}
// OverHandlers calls a function for each registered handler.
func (mux *Mux[HANDLER]) OverHandlers (callback func (pattern string, handler HANDLER) bool) {
overSorted (mux.exactEntries, func (pattern string, entry muxEntry[HANDLER]) bool {
return callback(pattern, entry.handler)

View File

@ -8,10 +8,10 @@ import "io"
import "fmt"
import "net/url"
import "net/http"
import "hnakra/config"
import "hnakra/router"
import "hnakra/rotate"
import "hnakra/protocol"
import "hnakra/router/config"
const css = `
body { background-color: #161815; color: #aea894; margin: 3em; }
@ -200,7 +200,7 @@ func (rcon *Rcon) serveServices (res http.ResponseWriter, req *http.Request) {
service.Name(),
service.Name(),
service.Description(),
service.Pattern())))
router.FormatPattern(service.Pattern()))))
return true
})

View File

@ -1,32 +1,13 @@
// Package router provides a reusable router implementation.
package router
import "log"
import "net"
// import "errors"
import "net/http"
import "hnakra/config"
import "hnakra/protocol"
import "hnakra/router/mux"
type Pattern struct {
Scheme string
Host string
Path string
}
func (pattern Pattern) MuxPattern () string {
return pattern.Host + pattern.Path
}
func (pattern Pattern) String () string {
return pattern.Scheme + "://" + pattern.Host + pattern.Path
}
func (pattern *Pattern) FillDefaults () {
if pattern.Scheme == "" { pattern.Scheme = "https" }
if pattern.Host == "" { pattern.Host = "@" }
if pattern.Path == "" { pattern.Path = "/" }
}
import "hnakra/router/config"
type Router struct {
config config.Config
@ -81,13 +62,17 @@ func (router *Router) unlist (service *Service) {
delete(router.services, service)
}
func (router *Router) Validate (name string, key []byte, pattern Pattern) protocol.Status {
func (router *Router) Validate (name string, key []byte, scheme, host, path string) protocol.Status {
user := router.config.User(name)
if user == nil || !user.Validate(key) {
return protocol.StatusBadCredentials
}
if !user.CanMountOn(pattern.Scheme, pattern.Host, pattern.Path) {
if !user.CanMountOn(scheme, host, path) {
return protocol.StatusBadMount
}
return protocol.StatusOk
}
func FormatPattern (scheme, host, path string) string {
return scheme + "://" + host + path
}

View File

@ -38,8 +38,7 @@ func (request *activeRequest) ensureHeader () {
type Service struct {
router *Router
validate func (user string, key []byte, pattern Pattern) protocol.Status
pattern Pattern
scheme, host, path string
user, name, description string
@ -57,7 +56,6 @@ func (router *Router) newService (conn net.Conn) (service *Service) {
service = &Service {
idFactory: protocol.NewRouterIDFactory(),
router: router,
validate: router.Validate,
conn: conn,
requests: make(map[protocol.ID] *activeRequest),
connReadWriter: bufio.NewReadWriter (
@ -88,8 +86,8 @@ func (service *Service) Description () string {
return service.description
}
func (service *Service) Pattern () Pattern {
return service.pattern
func (service *Service) Pattern () (user, name, description string) {
return service.user, service.name, service.description
}
func (service *Service) Close () error {
@ -104,9 +102,9 @@ func (service *Service) Shutdown () error {
func (service *Service) ServeHTTP (res http.ResponseWriter, req *http.Request) {
// if we are only accepting https requests and we recieve an http one,
// redirect to the https version
if req.TLS == nil && service.pattern.Scheme == "https" {
if req.TLS == nil && service.scheme == "https" {
newURL := req.URL
newURL.Scheme = service.pattern.Scheme
newURL.Scheme = service.scheme
http.Redirect(res, req, newURL.String(), http.StatusPermanentRedirect)
return
}
@ -326,15 +324,17 @@ func (service *Service) authenticate () (func(), bool) {
}
// create pattern
service.pattern = Pattern {
Scheme: login.Scheme,
Host: login.Host,
Path: login.Path,
}
service.pattern.FillDefaults()
service.scheme = login.Scheme
service.host = login.Host
service.path = login.Path
if service.scheme == "" { service.scheme = "https://" }
if service.host == "" { service.host = "@" }
if service.path == "" { service.path = "/" }
// validate credentials
status := service.validate(login.User, login.Key, service.pattern)
status := service.router.Validate (
login.User, login.Key,
service.scheme, service.host, service.path)
service.send(protocol.MessageStatus { Status: status })
if status == protocol.StatusOk {
service.user = login.User
@ -343,19 +343,21 @@ func (service *Service) authenticate () (func(), bool) {
log.Println (
"-->", service.conn.RemoteAddr(),
"logged in as", login.User, "on", service.pattern)
"logged in as", login.User, "on",
FormatPattern(service.scheme, service.host, service.path))
} else {
log.Println (
"ERR", service.conn.RemoteAddr(),
"failed login as", login.User, "on", service.pattern)
"failed login as", login.User, "on",
FormatPattern(service.scheme, service.host, service.path))
service.conn.Close()
return nil, false
}
// mount service on the mux.
var unhandle func ()
muxPattern := service.pattern.MuxPattern()
switch service.pattern.Scheme {
muxPattern := service.host + service.path
switch service.scheme {
case "http", "https":
err = service.router.HTTPMux().Handle(muxPattern, service)
unhandle = func () {
@ -367,7 +369,8 @@ func (service *Service) authenticate () (func(), bool) {
if err != nil {
log.Println (
"ERR", service.name,
"sent bad mount pattern:", service.pattern)
"sent bad mount pattern:",
FormatPattern(service.scheme, service.host, service.path))
service.send(protocol.MessageStatus {
Status: protocol.StatusBadMount,
})

View File

@ -1,3 +1,4 @@
// Package service provides a toolkit for creating Hnakra services.
package service
import "os"