github.com/searKing/golang/go@v1.2.117/net/mux/server_mux.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package mux
     6  
     7  import (
     8  	"errors"
     9  	"io"
    10  	"net"
    11  	"sync"
    12  	"time"
    13  
    14  	io_ "github.com/searKing/golang/go/io"
    15  	net_ "github.com/searKing/golang/go/net"
    16  )
    17  
    18  // NotFound replies to the request with an HTTP 404 not found error.
    19  func NotFound(c net.Conn) {
    20  	_, _ = c.Write([]byte("404 page not found"))
    21  }
    22  
    23  // NotFoundHandler returns a simple request handler
    24  // that replies to each request with a “404 page not found” reply.
    25  func NotFoundHandler() HandlerConn { return HandlerConnFunc(NotFound) }
    26  
    27  // ServeMux is a net.ServeMux that accepts only the connections that matched.
    28  // goroutine unsafe
    29  type ServeMux struct {
    30  	// NotFound replies to the listener with a not found error.
    31  	NotFoundHandler HandlerConn
    32  	sniffTimeout    time.Duration
    33  
    34  	mu sync.RWMutex
    35  	m  []muxEntry
    36  }
    37  
    38  type muxEntry struct {
    39  	h HandlerConn
    40  	l *net_.NotifyListener
    41  
    42  	pattern Matcher
    43  }
    44  
    45  func (e muxEntry) Serve(c net.Conn) {
    46  	if e.h != nil {
    47  		e.h.Serve(c)
    48  		return
    49  	}
    50  	if e.l != nil {
    51  		e.l.C <- c
    52  		return
    53  	}
    54  	panic("mux_entry: nil handler")
    55  }
    56  
    57  type Matcher interface {
    58  	Match(io.Writer, io.Reader) bool
    59  }
    60  
    61  // MatcherFunc is a match that can also write response (say to do handshake).
    62  type MatcherFunc func(io.Writer, io.Reader) bool
    63  
    64  func (f MatcherFunc) Match(w io.Writer, r io.Reader) bool {
    65  	return f(w, r)
    66  }
    67  
    68  func MatcherAny(matchers ...Matcher) Matcher {
    69  	return MatcherFunc(func(w io.Writer, r io.Reader) bool {
    70  		sniffReader := io_.SniffReader(r)
    71  		for _, pattern := range matchers {
    72  			sniffReader.Sniff(true)
    73  			if pattern.Match(w, sniffReader) {
    74  				sniffReader.Sniff(false)
    75  				return true
    76  			}
    77  			sniffReader.Sniff(false)
    78  		}
    79  		return false
    80  	})
    81  }
    82  
    83  // NewServeMux allocates and returns a new ServeMux.
    84  func NewServeMux() *ServeMux {
    85  	return &ServeMux{
    86  		NotFoundHandler: HandlerConnFunc(func(net.Conn) {}),
    87  	}
    88  }
    89  
    90  // DefaultServeMux is the default ServeMux used by Serve.
    91  var DefaultServeMux = &defaultServeMux
    92  
    93  var defaultServeMux ServeMux
    94  
    95  // SetReadTimeout sets a timeout for the read of matchers
    96  func (mux *ServeMux) SetReadTimeout(t time.Duration) {
    97  	mux.sniffTimeout = t
    98  }
    99  
   100  func (mux *ServeMux) HandleListener(pattern Matcher) net.Listener {
   101  	mux.mu.Lock()
   102  	defer mux.mu.Unlock()
   103  
   104  	if pattern == nil {
   105  		panic("listener: invalid pattern")
   106  	}
   107  
   108  	e := muxEntry{l: net_.NewNotifyListener(), pattern: pattern}
   109  	mux.m = append(mux.m, e)
   110  	return e.l
   111  }
   112  
   113  func (mux *ServeMux) Handle(pattern Matcher, handler HandlerConn) {
   114  	mux.mu.Lock()
   115  	defer mux.mu.Unlock()
   116  
   117  	if pattern == nil {
   118  		panic("listener: invalid pattern")
   119  	}
   120  	if handler == nil {
   121  		panic("listener: nil handler")
   122  	}
   123  
   124  	e := muxEntry{h: handler, pattern: pattern}
   125  	mux.m = append(mux.m, e)
   126  	return
   127  }
   128  
   129  // HandleFunc registers the handler function for the given pattern.
   130  func (mux *ServeMux) HandleFunc(pattern Matcher, handler func(net.Conn)) {
   131  	if handler == nil {
   132  		panic("http: nil handler")
   133  	}
   134  	mux.Handle(pattern, HandlerConnFunc(handler))
   135  }
   136  
   137  // Find a handler on a handler map.
   138  func (mux *ServeMux) match(c *sniffConn) (h HandlerConn) {
   139  	for _, e := range mux.m {
   140  		c.startSniffing()
   141  		if e.pattern.Match(c, c) {
   142  			c.doneSniffing()
   143  			return e
   144  		}
   145  		c.doneSniffing()
   146  	}
   147  	return nil
   148  
   149  }
   150  
   151  // Handler is the main implementation of HandlerConn.
   152  func (mux *ServeMux) Handler(c *sniffConn) (h HandlerConn) {
   153  	mux.mu.RLock()
   154  	defer mux.mu.RUnlock()
   155  
   156  	// set sniff timeout
   157  	if mux.sniffTimeout > noTimeout {
   158  		_ = c.SetReadDeadline(time.Now().Add(mux.sniffTimeout))
   159  	}
   160  	h = mux.match(c)
   161  
   162  	// unset sniff timeout
   163  	if mux.sniffTimeout > noTimeout {
   164  		_ = c.SetReadDeadline(noTimeoutDeadline)
   165  	}
   166  	if h == nil {
   167  		notFoundHandler := mux.NotFoundHandler
   168  		if notFoundHandler == nil {
   169  			notFoundHandler = NotFoundHandler()
   170  		}
   171  		h = muxEntry{
   172  			h: notFoundHandler,
   173  		}
   174  	}
   175  	return
   176  }
   177  
   178  func (mux *ServeMux) Serve(c net.Conn) {
   179  	muxC, ok := c.(*sniffConn)
   180  	if !ok {
   181  		muxC = newMuxConn(c)
   182  	}
   183  
   184  	h := mux.Handler(muxC)
   185  	h.Serve(c)
   186  }
   187  
   188  func (mux *ServeMux) Close() error {
   189  	var errs []error
   190  	for _, e := range mux.m {
   191  		if l := e.l; l != nil {
   192  			errs = append(errs, l.Close())
   193  		}
   194  	}
   195  	return errors.Join(errs...)
   196  }
   197  
   198  func HandleListener(pattern Matcher) net.Listener {
   199  	return DefaultServeMux.HandleListener(pattern)
   200  }
   201  
   202  func Handle(pattern Matcher, handler HandlerConn) {
   203  	DefaultServeMux.Handle(pattern, handler)
   204  }
   205  
   206  // HandleFunc registers the handler function for the given pattern.
   207  func HandleFunc(pattern Matcher, handler func(net.Conn)) {
   208  	DefaultServeMux.HandleFunc(pattern, handler)
   209  }
   210  func SetReadTimeout(t time.Duration) {
   211  	DefaultServeMux.SetReadTimeout(t)
   212  }