summaryrefslogtreecommitdiff
path: root/nex/serve.go
diff options
context:
space:
mode:
Diffstat (limited to 'nex/serve.go')
-rw-r--r--nex/serve.go91
1 files changed, 91 insertions, 0 deletions
diff --git a/nex/serve.go b/nex/serve.go
new file mode 100644
index 0000000..7e103e3
--- /dev/null
+++ b/nex/serve.go
@@ -0,0 +1,91 @@
+package nex
+
+import (
+ "bytes"
+ "context"
+ "crypto/tls"
+ "fmt"
+ "io"
+ "net"
+
+ "tildegit.org/tjp/sliderule/internal"
+ "tildegit.org/tjp/sliderule/internal/types"
+ "tildegit.org/tjp/sliderule/logging"
+)
+
+type nexServer struct {
+ internal.Server
+ handler types.Handler
+}
+
+func (ns nexServer) Protocol() string { return "NEX" }
+
+// NewServer builds a new nex server
+func NewServer(
+ ctx context.Context,
+ hostname string,
+ network string,
+ address string,
+ handler types.Handler,
+ baseLog logging.Logger,
+) (types.Server, error) {
+ ns := &nexServer{handler: handler}
+
+ hostname = internal.JoinDefaultPort(hostname, "1900")
+ address = internal.JoinDefaultPort(address, "1900")
+
+ var err error
+ ns.Server, err = internal.NewServer(ctx, hostname, network, address, baseLog, ns.handleConn)
+ if err != nil {
+ return nil, err
+ }
+
+ return ns, err
+}
+
+func NewTLSServer(
+ ctx context.Context,
+ hostname string,
+ network string,
+ address string,
+ handler types.Handler,
+ baseLog logging.Logger,
+ tlsConfig *tls.Config,
+) (types.Server, error) {
+ ns, err := NewServer(ctx, hostname, network, address, handler, baseLog)
+ if err != nil {
+ return nil, err
+ }
+
+ ns.(*nexServer).Listener = tls.NewListener(ns.(*nexServer).Listener, tlsConfig)
+ return ns, nil
+}
+
+func (ns *nexServer) handleConn(conn net.Conn) {
+ request, err := ParseRequest(conn)
+ if err != nil {
+ _, _ = fmt.Fprint(conn, err.Error()+"\n")
+ }
+
+ request.Server = ns
+ request.RemoteAddr = conn.RemoteAddr()
+
+ if tlsconn, ok := conn.(*tls.Conn); ok {
+ state := tlsconn.ConnectionState()
+ request.TLSState = &state
+ }
+
+ defer func() {
+ if r := recover(); r != nil {
+ _ = ns.LogError("msg", "panic in handler", "err", r)
+ _, _ = fmt.Fprint(conn, "Error handling request.\n")
+ }
+ }()
+ response := ns.handler.Handle(ns.Ctx, request)
+ if response == nil {
+ response = Response(bytes.NewBufferString("Document not found."))
+ }
+
+ defer response.Close()
+ _, _ = io.Copy(conn, response.Body)
+}