Mount is now MountConfig (and fully public)

This commit is contained in:
Sasha Koshka 2023-05-26 19:42:52 -04:00
parent 92911cdab4
commit 53e7e00f80
2 changed files with 55 additions and 28 deletions

View File

@ -10,7 +10,8 @@ import "hnakra/protocol"
// HTTP is an https:// mount. // HTTP is an https:// mount.
type HTTP struct { type HTTP struct {
Mount // Mount specifies the mount config to use for connecting to the router.
Mount MountConfig
// AllowInsecure allows this mount to respond to plain-text HTTP // AllowInsecure allows this mount to respond to plain-text HTTP
// requests. You can get a TLS cert for free nowadays so there are very // requests. You can get a TLS cert for free nowadays so there are very
@ -25,6 +26,7 @@ type HTTP struct {
connLock sync.Mutex connLock sync.Mutex
connReadWriter *bufio.ReadWriter connReadWriter *bufio.ReadWriter
requests requestManager requests requestManager
idFactory *protocol.IDFactory
} }
// Close closes the mount abruptly, interrupting any active connections. // Close closes the mount abruptly, interrupting any active connections.
@ -45,10 +47,11 @@ func (mount *HTTP) Shutdown () error {
// will only return when the connection to the router has been closed. // will only return when the connection to the router has been closed.
func (mount *HTTP) Run () (err error) { func (mount *HTTP) Run () (err error) {
if mount.AllowInsecure { if mount.AllowInsecure {
mount.conn, err = mount.connect("http") mount.Mount.Scheme = "http"
} else { } else {
mount.conn, err = mount.connect("https") mount.Mount.Scheme = "https"
} }
mount.conn, mount.idFactory, err = mount.Mount.Connect()
if err != nil { return } if err != nil { return }
mount.connReadWriter = bufio.NewReadWriter ( mount.connReadWriter = bufio.NewReadWriter (

View File

@ -10,21 +10,33 @@ import "crypto/tls"
import "encoding/base64" import "encoding/base64"
import "hnakra/protocol" import "hnakra/protocol"
// M creates a very basic mount with the specified name and description. // M creates a very basic MountConfig with the specified name and description.
func M (name, description string) Mount { func M (name, description string) MountConfig {
return Mount { return MountConfig {
Name: name, Name: name,
Description: description, Description: description,
} }
} }
// Mount contains generic information common to all mounts. // Mount is an interface satisfied by all mount types.
type Mount struct { type Mount interface {
Close () error
Shutdown () error
Run () error
}
// MountConfig contains generic information common to all mounts.
type MountConfig struct {
// Host specifies the host to mount on. If the host is left empty, it // Host specifies the host to mount on. If the host is left empty, it
// will default to @ (meaning default/any host). The port is entirely up // will default to @ (meaning default/any host). The port is entirely up
// to the router. Maximum length for host portion: 255 bytes // to the router. Maximum length for host portion: 255 bytes
Host string Host string
// Scheme specifies the protocol to mount on. This will be automatically
// set by specialized mount types, so setting it manually shouldn't be
// needed.
Scheme string
// Path specifies the path to mount on. If the path ends with a /, then // Path specifies the path to mount on. If the path ends with a /, then
// all requests under the path will be sent to this service. If there is // all requests under the path will be sent to this service. If there is
// no trailing /, this service will only recieve requests that match the // no trailing /, this service will only recieve requests that match the
@ -68,13 +80,16 @@ type Mount struct {
// TLSConfig is an optional TLS configuration. // TLSConfig is an optional TLS configuration.
TLSConfig *tls.Config TLSConfig *tls.Config
idFactory *protocol.IDFactory
} }
func (mount *Mount) connect (scheme string) (conn net.Conn, err error) { // Connect creates a new connection to the router specified in the MountConfig.
func (mount *MountConfig) Connect () (
conn net.Conn,
idFactory *protocol.IDFactory,
err error,
) {
log.Println("(i) service", mount.Name) log.Println("(i) service", mount.Name)
mount.idFactory = protocol.NewServiceIDFactory() idFactory = protocol.NewServiceIDFactory()
defaultRouterHost := os.Getenv("HNAKRA_ROUTER_HOST") defaultRouterHost := os.Getenv("HNAKRA_ROUTER_HOST")
if defaultRouterHost == "" { if defaultRouterHost == "" {
@ -95,19 +110,21 @@ func (mount *Mount) connect (scheme string) (conn net.Conn, err error) {
} }
// get mount point // get mount point
scheme := mount.Scheme
host := mount.Host host := mount.Host
if host == "" { if host == "" {
host = "@" host = "@"
} }
if len(host) > 255 { if len(host) > 255 {
return nil, errors.New("mount point host cannot be longer than 255 bytes") return nil, nil, errors.New (
"mount point host cannot be longer than 255 bytes")
} }
path := mount.Path path := mount.Path
if path == "" { if path == "" {
path = "/" path = "/"
} }
if len(path) > int(protocol.MaxIntOfSize(2)) { if len(path) > int(protocol.MaxIntOfSize(2)) {
return nil, errors.New(fmt.Sprint ( return nil, nil, errors.New(fmt.Sprint (
"mount point path cannot be longer than ", "mount point path cannot be longer than ",
protocol.MaxIntOfSize(2), " bytes")) protocol.MaxIntOfSize(2), " bytes"))
} }
@ -118,39 +135,44 @@ func (mount *Mount) connect (scheme string) (conn net.Conn, err error) {
user = os.Getenv("HNAKRA_USER") user = os.Getenv("HNAKRA_USER")
} }
if len(user) > 255 { if len(user) > 255 {
return nil, errors.New("user cannot be longer than 255 bytes") return nil, nil, errors.New (
"user cannot be longer than 255 bytes")
} }
// get key // get key
key := mount.Key key := mount.Key
if key == nil { if key == nil {
key, err = base64.StdEncoding.DecodeString(os.Getenv("HNAKRA_KEY")) base64Key := os.Getenv("HNAKRA_KEY")
if err != nil { return nil, err } key, err = base64.StdEncoding.DecodeString(base64Key)
if err != nil { return nil, nil, err }
} }
if len(key) > 255 { if len(key) > 255 {
return nil, errors.New("key cannot be longer than 255 bytes") return nil, nil, errors.New (
"key cannot be longer than 255 bytes")
} }
// ensure name/description aren't too big // ensure name/description aren't too big
if len(mount.Name) > 255 { if len(mount.Name) > 255 {
return nil, errors.New("service name cannot be longer than 255 bytes") return nil, nil, errors.New (
"service name cannot be longer than 255 bytes")
} }
if len(mount.Description) > 255 { if len(mount.Description) > 255 {
return nil, errors.New("service description cannot be longer than 255 bytes") return nil, nil, errors.New (
"service description cannot be longer than 255 bytes")
} }
// connect to router // connect to router
routerAddr := fmt.Sprint(routerHost, ":", routerPort) routerAddr := fmt.Sprint(routerHost, ":", routerPort)
log.Println("... dialing", routerAddr) log.Println("... dialing", routerAddr)
conn, err = tls.Dial("tcp", routerAddr, mount.TLSConfig) conn, err = tls.Dial("tcp", routerAddr, mount.TLSConfig)
if err != nil { return nil, err } if err != nil { return nil, nil, err }
// log in // log in
log.Println ( log.Println (
"... logging in as", user, "... logging in as", user,
"on", scheme + "://" + host + path) "on", scheme + "://" + host + path)
err = protocol.MessageLogin { err = protocol.MessageLogin {
ID: mount.idFactory.Next(), ID: idFactory.Next(),
Version: protocol.Version { Major: 0, Minor: 0 }, Version: protocol.Version { Major: 0, Minor: 0 },
User: user, User: user,
Key: key, Key: key,
@ -162,24 +184,26 @@ func (mount *Mount) connect (scheme string) (conn net.Conn, err error) {
}.Send(conn) }.Send(conn)
if err != nil { if err != nil {
conn.Close() conn.Close()
return nil, err return nil, nil, err
} }
// read status // read status
message, err := protocol.ReadMessage(conn) message, err := protocol.ReadMessage(conn)
if err != nil { if err != nil {
conn.Close() conn.Close()
return nil, err return nil, nil, err
} }
status, ok := message.(protocol.MessageStatus) status, ok := message.(protocol.MessageStatus)
if !ok { if !ok {
conn.Close() conn.Close()
return nil, errors.New(fmt.Sprint("router sent unknown type, expecting", protocol.TypeStatus)) return nil, nil, errors.New(fmt.Sprint (
"router sent unknown type, expecting",
protocol.TypeStatus))
} }
if status.Status != protocol.StatusOk { if status.Status != protocol.StatusOk {
return nil, status return nil, nil, status
} }
log.Println(".// logged in") log.Println(".// logged in")
return conn, nil return conn, idFactory, nil
} }