73 lines
1.5 KiB
Go
73 lines
1.5 KiB
Go
package gopher
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"strings"
|
|
|
|
"tildegit.org/tjp/gus"
|
|
"tildegit.org/tjp/gus/internal"
|
|
"tildegit.org/tjp/gus/logging"
|
|
)
|
|
|
|
type gopherServer struct {
|
|
internal.Server
|
|
handler gus.Handler
|
|
}
|
|
|
|
func (gs gopherServer) Protocol() string { return "GOPHER" }
|
|
|
|
// NewServer builds a gopher server.
|
|
func NewServer(
|
|
ctx context.Context,
|
|
hostname string,
|
|
network string,
|
|
address string,
|
|
handler gus.Handler,
|
|
errLog logging.Logger,
|
|
) (gus.Server, error) {
|
|
gs := &gopherServer{handler: handler}
|
|
|
|
if strings.IndexByte(hostname, ':') < 0 {
|
|
hostname = net.JoinHostPort(hostname, "70")
|
|
}
|
|
|
|
var err error
|
|
gs.Server, err = internal.NewServer(ctx, hostname, network, address, errLog, gs.handleConn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return gs, nil
|
|
}
|
|
|
|
func (gs *gopherServer) handleConn(conn net.Conn) {
|
|
var response *gus.Response
|
|
request, err := ParseRequest(conn)
|
|
if err != nil {
|
|
response = Error(errors.New("Malformed request.")).Response()
|
|
} else {
|
|
request.Server = gs
|
|
request.RemoteAddr = conn.RemoteAddr()
|
|
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
err := fmt.Errorf("%s", r)
|
|
_ = gs.LogError("msg", "panic in handler", "err", err)
|
|
rdr := NewResponseReader(Error(errors.New("Server error.")).Response())
|
|
_, _ = io.Copy(conn, rdr)
|
|
}
|
|
}()
|
|
response = gs.handler(gs.Ctx, request)
|
|
if response == nil {
|
|
response = Error(errors.New("Resource does not exist.")).Response()
|
|
}
|
|
}
|
|
|
|
defer response.Close()
|
|
_, _ = io.Copy(conn, NewResponseReader(response))
|
|
}
|