github.com/mholt/caddy-l4@v0.0.0-20241104153248-ec8fae209322/layer4/handlers.go (about) 1 // Copyright 2020 Matthew Holt 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package layer4 16 17 // Handlers is a list of connection handlers. 18 type Handlers []NextHandler 19 20 // Compile assembles the list of handlers into a 21 // single handler chain. 22 func (h Handlers) Compile() Handler { 23 var midware []Middleware 24 for _, midhandler := range h { 25 midware = append(midware, wrapHandler(midhandler)) 26 } 27 var next Handler = nopHandler{} 28 for i := len(midware) - 1; i >= 0; i-- { 29 next = midware[i](next) 30 } 31 return next 32 } 33 34 // NextHandler is a type that can handle connections 35 // as part of a middleware chain. 36 type NextHandler interface { 37 Handle(*Connection, Handler) error 38 } 39 40 // Handler is a type that can handle connections. 41 type Handler interface { 42 Handle(*Connection) error 43 } 44 45 // Middleware is a function that wraps a handler. 46 type Middleware func(Handler) Handler 47 48 func wrapHandler(h NextHandler) Middleware { 49 return func(next Handler) Handler { 50 // TODO: copy next? 51 return HandlerFunc(func(cx *Connection) error { 52 return h.Handle(cx, next) // TODO: refer to copy here? 53 }) 54 } 55 } 56 57 // HandlerFunc can turn a function into a Handler type. 58 type HandlerFunc func(*Connection) error 59 60 // Handle handles a connection; it implements the Handler interface. 61 func (h HandlerFunc) Handle(cx *Connection) error { return h(cx) } 62 63 // NextHandlerFunc can turn a function into a NextHandler type. 64 type NextHandlerFunc func(cx *Connection, next Handler) error 65 66 func (h NextHandlerFunc) Handle(cx *Connection, next Handler) error { return h(cx, next) } 67 68 // nopHandler is a connection handler that does nothing with the 69 // connection, not even reading from it; it simply returns. It is 70 // the default end of all handler chains. 71 // 72 // A nopHandler is distinct from a "discard" handler that reads 73 // the connection and drains it into a black hole: while such a 74 // handler would ensure that any concurrent branches handling the 75 // connection don't get blocked, it could also burn through data 76 // transfer unnecessarily. So as a slight security feature, we 77 // don't drain a client's unused connection, and instead opt to 78 // return and close the connection. 79 type nopHandler struct{} 80 81 func (nopHandler) Handle(_ *Connection) error { return nil } 82 83 // forwardNextHandler will forward the handling to the next handler in the chain. 84 type forwardNextHandler struct{} 85 86 func (forwardNextHandler) Handle(cx *Connection, next Handler) error { 87 return next.Handle(cx) 88 } 89 90 // listenerHandler is a connection handler that pipe incoming connection to channel as a listener wrapper 91 type listenerHandler struct{} 92 93 func (listenerHandler) Handle(conn *Connection) error { 94 return conn.Context.Value(listenerCtxKey).(*listener).pipeConnection(conn) 95 }