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  }