代码拉取完成,页面将自动刷新
/*
* @Author: hongyu guo
* @Description:
* @Version: 1.0.0
* @Date: 11:34 2021/06/15
* @Copyright: MIN-Group;国家重大科技基础设施——未来网络北大实验室;深圳市信息论与未来网络重点实验室
*/
package minhttp
import (
"MINTCP/socket"
"context"
"crypto/tls"
"errors"
"fmt"
"io"
"log"
"minlib/common"
"minlib/minsecurity"
"minlib/minsecurity/identity"
"minlib/security"
"net"
"net/url"
"strings"
"sync"
"sync/atomic"
"time"
)
// A ConnState represents the state of a client connection to a server.
// It's used by the optional Server.ConnState hook.
type ConnState int
type atomicBool int32
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
// A Server defines parameters for running an HTTP server.
// The zero value for Server is a valid configuration.
type Server struct {
// 是符合MIN-TCP的地址格式,
// TODO:暂时还没定义
// Addr optionally specifies the TCP address for the server to listen on,
// in the form "host:port". If empty, ":http" (port 80) is used.
// The service names are defined in RFC 6335 and assigned by IANA.
// See net.Dial for details of the address format.
// Addr string
IdentifierAddr string // 标识地址
IdentifierPasswd string // 身份对应的密码
Handler Handler // handler to invoke, DefaultServeMux if nil
// TODO:TLS 第一版不做
// TLSConfig optionally provides a TLS configuration for use
// by ServeTLS and ListenAndServeTLS. Note that this value is
// cloned by ServeTLS and ListenAndServeTLS, so it's not
// possible to modify the configuration with methods like
// tls.Config.SetSessionTicketKeys. To use
// SetSessionTicketKeys, use Server.Serve with a TLS Listener
// instead.
TLSConfig *tls.Config
// ReadTimeout 是读取整个请求(包括body)的最大超时时间
// ReadTimeout is the maximum duration for reading the entire
// request, including the body.
//
// Because ReadTimeout does not let Handlers make per-request
// decisions on each request body's acceptable deadline or
// upload rate, most users will prefer to use
// ReadHeaderTimeout. It is valid to use them both.
// 因为 ReadTimeout 不允许处理程序根据每个请求主体的可接受期限
// 或上传速率做出每个请求的决定,
// 所以大多数用户会更喜欢使用 ReadHeaderTimeout。
// 两者都使用也是有效的。
ReadTimeout time.Duration
// ReadHeaderTimeout is the amount of time allowed to read
// request headers. The connection's read deadline is reset
// after reading the headers and the Handler can decide what
// is considered too slow for the body. If ReadHeaderTimeout
// is zero, the value of ReadTimeout is used. If both are
// zero, there is no timeout.
// ReadHeaderTimeout 是允许读取请求标头的时间量。
// 读取request header后,连接的读取截止时间会重置,
// handler可以决定哪些内容对于body来说太慢了。
// 如果 ReadHeaderTimeout 为零,则使用 ReadTimeout 的值。
// 如果两者都为零,则没有超时。
ReadHeaderTimeout time.Duration
// WriteTimeout is the maximum duration before timing out
// writes of the response. It is reset whenever a new
// request's header is read. Like ReadTimeout, it does not
// let Handlers make decisions on a per-request basis.
// WriteTimeout 是最大超时时间写入响应的最大超时时间
// 每当读取一个新的请求头, 则重置 WriteTimeout
// 与 ReadTimeout 一样,它不会
// 让 Handler 根据每个请求做出决定。
WriteTimeout time.Duration
// IdleTimeout is the maximum amount of time to wait for the
// next request when keep-alives are enabled. If IdleTimeout
// is zero, the value of ReadTimeout is used. If both are
// zero, there is no timeout.
// // IdleTimeout 是启用 keep-alives 时等待下一个请求的最长时间。
// 如果空闲超时为零,则使用 ReadTimeout 的值。 如果两者都是
// 零,则没有超时。
IdleTimeout time.Duration
// MaxHeaderBytes controls the maximum number of bytes the
// server will read parsing the request header's keys and
// values, including the request line. It does not limit the
// size of the request body.
// If zero, DefaultMaxHeaderBytes is used.
// MaxHeaderBytes 限制服务器将读取的最大字节数,解析请求头的键和值,包括请求行。
// 它不限制请求正文的大小。
// 如果为零,则使用 DefaultMaxHeaderBytes。
MaxHeaderBytes int
// TODO: TLS相关, 第一版不做
// TLSNextProto optionally specifies a function to take over
// ownership of the provided TLS connection when an ALPN
// protocol upgrade has occurred. The map key is the protocol
// name negotiated. The Handler argument should be used to
// handle HTTP requests and will initialize the Request's TLS
// and RemoteAddr if not already set. The connection is
// automatically closed when the function returns.
// If TLSNextProto is not nil, HTTP/2 support is not enabled
// automatically.
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
// ConnState specifies an optional callback function that is
// called when a client connection changes state. See the
// ConnState type and associated constants for details.
// ConnState 指定一个可选的回调函数,
// 当客户端连接改变状态时调用该回调函数。
// 有关详细信息,请参阅 ConnState 类型和相关常量。
ConnState func(net.Conn, ConnState)
// TODO: 修改为minlib正在使用的log
// ErrorLog specifies an optional logger for errors accepting
// connections, unexpected behavior from handlers, and
// underlying FileSystem errors.
// If nil, logging is done via the log package's standard logger.
ErrorLog *log.Logger
// BaseContext optionally specifies a function that returns
// the base context for incoming requests on this server.
// The provided Listener is the specific Listener that's
// about to start accepting requests.
// If BaseContext is nil, the default is context.Background().
// If non-nil, it must return a non-nil context.
// BaseContext 可选地指定一个函数,该函数返回此服务器上传入请求的基本上下文。
// 提供的 Listener 是即将开始接受请求的特定 Listener。
// 如果 BaseContext 为 nil,则默认值为 context.Background()。
// 如果非零,它必须返回一个非零上下文。
BaseContext func(net.Listener) context.Context
// ConnContext optionally specifies a function that modifies
// the context used for a new connection c. The provided ctx
// is derived from the base context and has a ServerContextKey
// value.
// Conn Context 可选地指定一个函数来修改用于新连接的上下文 c.
// 提供的 ctx 派生自基本上下文并具有服务器上下文键值。
ConnContext func(ctx context.Context, c net.Conn) context.Context
inShutdown atomicBool // true when when server is in shutdown
disableKeepAlives int32 // accessed atomically.
// http2暂不考虑
// nextProtoOnce sync.Once // guards setupHTTP2_* init
// nextProtoErr error // result of http2.ConfigureServer if used
mu sync.Mutex
listeners map[*net.Listener]struct{}
activeConn map[*conn]struct{}
doneChan chan struct{}
onShutdown []func()
}
// Create new connection from minConn.
func (srv *Server) newConn(rwc net.Conn) *conn {
c := &conn{
server: srv,
minConn: rwc,
}
return c
}
func (w *response) sendExpectationFailed() {
// TODO(bradfitz): let ServeHTTP handlers handle
// requests with non-standard expectation[s]? Seems
// theoretical at best, and doesn't fit into the
// current ServeHTTP model anyway. We'd need to
// make the ResponseWriter an optional
// "ExpectReplier" interface or something.
//
// For now we'll just obey RFC 7231 5.1.1 which says
// "A server that receives an Expect field-value other
// than 100-continue MAY respond with a 417 (Expectation
// Failed) status code to indicate that the unexpected
// expectation cannot be met."
w.Header().Set("Connection", "close")
w.WriteHeader(StatusExpectationFailed)
w.finishRequest()
}
func (srv *Server) trackConn(c *conn, add bool) {
srv.mu.Lock()
defer srv.mu.Unlock()
if srv.activeConn == nil {
srv.activeConn = make(map[*conn]struct{})
}
if add {
srv.activeConn[c] = struct{}{}
} else {
delete(srv.activeConn, c)
}
}
// trackListener adds or removes a net.Listener to the set of tracked
// listeners.
//
// We store a pointer to interface in the map set, in case the
// net.Listener is not comparable. This is safe because we only call
// trackListener via Serve and can track+defer untrack the same
// pointer to local variable there. We never need to compare a
// Listener from another caller.
//
// It reports whether the server is still up (not Shutdown or Closed).
func (srv *Server) trackListener(ln *net.Listener, add bool) bool {
srv.mu.Lock()
defer srv.mu.Unlock()
if srv.listeners == nil {
srv.listeners = make(map[*net.Listener]struct{})
}
if add {
if srv.shuttingDown() {
return false
}
srv.listeners[ln] = struct{}{}
} else {
delete(srv.listeners, ln)
}
return true
}
func (srv *Server) shuttingDown() bool {
return srv.inShutdown.isSet()
}
func (srv *Server) getDoneChan() <-chan struct{} {
srv.mu.Lock()
defer srv.mu.Unlock()
return srv.getDoneChanLocked()
}
func (srv *Server) getDoneChanLocked() chan struct{} {
if srv.doneChan == nil {
srv.doneChan = make(chan struct{})
}
return srv.doneChan
}
func (srv *Server) logf(format string, args ...interface{}) {
if srv.ErrorLog != nil {
srv.ErrorLog.Printf(format, args...)
} else {
log.Printf(format, args...)
}
}
func (srv *Server) initialReadLimitSize() int64 {
return int64(srv.maxHeaderBytes()) + 4096 // bufio slop
}
func (srv *Server) maxHeaderBytes() int {
if srv.MaxHeaderBytes > 0 {
return srv.MaxHeaderBytes
}
return DefaultMaxHeaderBytes
}
// ListenAndServe DONE: 后续修改为min-tcp的listen函数
func (srv *Server) ListenAndServe(getKeyChain func(...interface{}) (*security.KeyChain, error), getIdentity func(...interface{}) (*identity.Identity, error), portFunc func(...interface{}) uint64) error {
if srv.shuttingDown() {
return ErrServerClosed
}
//
//addr := srv.Addr
//if addr == "" {
// addr = ":http"
//}
// ln, err := net.Listen("tcp", addr)
// 修改为mintcp Listen
// 函数式编程初尝试
//keyChain := new(security.KeyChain)
//if err := keyChain.Init(); err != nil {
// common.LogFatal(err)
//}
// 1. 获取KeyChain
keyChain, err := getKeyChain(nil) // 当生成keyChain的逻辑改变时直接把新函数作为参数
if err != nil {
return err
}
// 2. 获取Identity
identity, err := getIdentity(keyChain, srv.IdentifierAddr, srv.IdentifierPasswd) // 当获取Identity的逻辑改变时直接把新函数作为参数
if err != nil {
return err
}
// 3. Listen
ln, err := socket.Listen("min-push-tcp", portFunc(), identity,
"unix", "/tmp/mir-tcp-message-channel-stack.sock")
if err != nil {
return err
}
return srv.Serve(ln)
}
// 以init方式生成一个Keychain实例
func newKeyChain(param ...interface{}) (*security.KeyChain, error) {
keyChain := new(security.KeyChain)
if err := keyChain.Init(); err != nil {
common.LogFatal(err)
return nil, err
}
return keyChain, nil
}
// 该函数规定:第一个参数是keychain实例,第二个参数是identityName, 第三个参数是identityPasswd
// 根据identityName获取身份,不存在会返回错误
// 根据identityPasswd去解锁身份,失败会返回错误
func getIdentityByNameAndPasswd(param ...interface{}) (*identity.Identity, error) {
keyChain := param[0].(*security.KeyChain)
identityName := param[1].(string)
identityPasswd := param[2].(string)
myIdentity := keyChain.GetIdentityByName(identityName)
if myIdentity == nil {
return nil, errors.New(fmt.Sprintf("Not Found: %s", identityName))
}
_, err := myIdentity.UnLock(identityPasswd, minsecurity.SM4ECB)
return myIdentity, err
}
// 该函数规定:第一个参数是keychain实例,第二个参数是identityName, 第三个参数是identityPasswd
// 根据identityName与passwd生成身份,不存在会返回错误
// 根据identityPasswd去解锁身份,失败会返回错误
func createIdentityByNameAndPasswd(param ...interface{}) (*identity.Identity, error) {
keyChain := param[0].(*security.KeyChain)
identityName := param[1].(string)
identityPasswd := param[2].(string)
myIdentity, err := keyChain.CreateIdentityByName(identityName, identityPasswd)
if myIdentity == nil {
return nil, errors.New(fmt.Sprintf("Not Found: %s", identityName))
}
_, err = myIdentity.UnLock(identityPasswd, minsecurity.SM4ECB)
return myIdentity, err
}
func (srv *Server) readHeaderTimeout() time.Duration {
if srv.ReadHeaderTimeout != 0 {
return srv.ReadHeaderTimeout
}
return srv.ReadTimeout
}
func (srv *Server) doKeepAlives() bool {
return atomic.LoadInt32(&srv.disableKeepAlives) == 0 && !srv.shuttingDown()
}
func (srv *Server) idleTimeout() time.Duration {
if srv.IdleTimeout != 0 {
return srv.IdleTimeout
}
return srv.ReadTimeout
}
// serverHandler delegates to either the server's Handler or
// DefaultServeMux and also handles "OPTIONS *" requests.
type serverHandler struct {
srv *Server
}
func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
handler := sh.srv.Handler
if handler == nil {
handler = DefaultServeMux
}
// if req.RequestURI == "*" && req.Method == "OPTIONS" {
// handler = globalOptionsHandler{}
// }
handler.ServeHTTP(rw, req)
}
// onceCloseListener wraps a net.Listener, protecting it from
// multiple Close calls.
type onceCloseListener struct {
net.Listener
once sync.Once
closeErr error
}
func (oc *onceCloseListener) Close() error {
oc.once.Do(oc.close)
return oc.closeErr
}
func (oc *onceCloseListener) close() { oc.closeErr = oc.Listener.Close() }
// requestBodyRemains reports whether future calls to Read
// on rc might yield more data.
func requestBodyRemains(rc io.ReadCloser) bool {
if rc == NoBody {
return false
}
switch v := rc.(type) {
// case *expectContinueReader:
// return requestBodyRemains(v.readCloser)
case *body:
return v.bodyRemains()
default:
panic("unexpected type " + fmt.Sprintf("%T", rc))
}
}
func registerOnHitEOF(rc io.ReadCloser, fn func()) {
switch v := rc.(type) {
// case *expectContinueReader:
// registerOnHitEOF(v.readCloser, fn)
case *body:
v.registerOnHitEOF(fn)
default:
panic("unexpected type " + fmt.Sprintf("%T", rc))
}
}
// StripPrefix returns a handler that serves HTTP requests by removing the
// given prefix from the request URL's Path (and RawPath if set) and invoking
// the handler h. StripPrefix handles a request for a path that doesn't begin
// with prefix by replying with an HTTP 404 not found error. The prefix must
// match exactly: if the prefix in the request contains escaped characters
// the reply is also an HTTP 404 not found error.
func StripPrefix(prefix string, h Handler) Handler {
if prefix == "" {
return h
}
return HandlerFunc(func(w ResponseWriter, r *Request) {
p := strings.TrimPrefix(r.URL.Path, prefix)
rp := strings.TrimPrefix(r.URL.RawPath, prefix)
if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
r2 := new(Request)
*r2 = *r
r2.URL = new(url.URL)
*r2.URL = *r.URL
r2.URL.Path = p
r2.URL.RawPath = rp
h.ServeHTTP(w, r2)
} else {
NotFound(w, r)
}
})
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。