package service import "log" import "errors" import "net/http" import "hnakra/protocol" // HTTP is an https:// mount. type HTTP struct { MountInfo // AllowInsecure allows this mount to respond to plain-text HTTP // requests. You can get a TLS cert for free nowadays so there are very // few cases where you'd want this on. AllowInsecure bool // Handler specifies the handler to invoke. If it is nil, // http.DefaultServeMux is used. Handler http.Handler conn *Conn running bool requests requestManager } // Close closes the mount abruptly, interrupting any active connections. func (htmount *HTTP) Close () error { htmount.running = false return htmount.conn.Close() } // Shutdown gracefully shuts down the service without interrupting any active // connections. func (htmount *HTTP) Shutdown () error { // TODO return htmount.Close() } // Run connects to the router, and blocks while fulfilling requests. This method // will only return when the connection to the router has been closed. func (htmount *HTTP) Run (service ServiceInfo) (err error) { if htmount.AllowInsecure { htmount.MountInfo.Scheme = "http" } else { htmount.MountInfo.Scheme = "https" } htmount.conn, err = Dial(htmount.MountInfo, service) if err != nil { return } htmount.running = true htmount.requests.init() for { message, err := htmount.conn.Receive() if err != nil { if htmount.running { return err } else { return nil } } switch message.(type) { case protocol.MessageHTTPRequest: request := message.(protocol.MessageHTTPRequest) htmount.requests.add(request.ID) go htmount.handle(request) case protocol.MessageHTTPBodySegment: segment := message.(protocol.MessageHTTPBodySegment) htmount.requests.feed(segment.ID, segment.Data) case protocol.MessageHTTPBodyEnd: end := message.(protocol.MessageHTTPBodyEnd) htmount.requests.end(end.ID) case protocol.MessageStatus: status := message.(protocol.MessageStatus) log.Println("router says:", status.Status) default: htmount.Close() return errors.New("router sent unknown type code") } } } // NewHTTP creates a new HTTPS mount that uses the specified handler. func NewHTTP (host, path string, handler http.Handler) *HTTP { return &HTTP { MountInfo: MountInfo { Host: host, Path: path, }, Handler: handler, } }