57 lines
1.7 KiB
Go
57 lines
1.7 KiB
Go
package websocket
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"encoding/base64"
|
|
"errors"
|
|
"io"
|
|
"strings"
|
|
|
|
"go-common/app/service/main/broadcast/libs/bufio"
|
|
)
|
|
|
|
var (
|
|
keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
|
|
// ErrBadRequestMethod bad request method
|
|
ErrBadRequestMethod = errors.New("bad method")
|
|
// ErrNotWebSocket not websocket protocal
|
|
ErrNotWebSocket = errors.New("not websocket protocol")
|
|
// ErrBadWebSocketVersion bad websocket version
|
|
ErrBadWebSocketVersion = errors.New("missing or bad WebSocket Version")
|
|
// ErrChallengeResponse mismatch challenge response
|
|
ErrChallengeResponse = errors.New("mismatch challenge/response")
|
|
)
|
|
|
|
// Upgrade Switching Protocols
|
|
func Upgrade(rwc io.ReadWriteCloser, rr *bufio.Reader, wr *bufio.Writer, req *Request) (conn *Conn, err error) {
|
|
if req.Method != "GET" {
|
|
return nil, ErrBadRequestMethod
|
|
}
|
|
if req.Header.Get("Sec-Websocket-Version") != "13" {
|
|
return nil, ErrBadWebSocketVersion
|
|
}
|
|
if strings.ToLower(req.Header.Get("Upgrade")) != "websocket" {
|
|
return nil, ErrNotWebSocket
|
|
}
|
|
if !strings.Contains(strings.ToLower(req.Header.Get("Connection")), "upgrade") {
|
|
return nil, ErrNotWebSocket
|
|
}
|
|
challengeKey := req.Header.Get("Sec-Websocket-Key")
|
|
if challengeKey == "" {
|
|
return nil, ErrChallengeResponse
|
|
}
|
|
wr.WriteString("HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\n")
|
|
wr.WriteString("Sec-WebSocket-Accept: " + computeAcceptKey(challengeKey) + "\r\n\r\n")
|
|
if err = wr.Flush(); err != nil {
|
|
return
|
|
}
|
|
return newConn(rwc, rr, wr), nil
|
|
}
|
|
|
|
func computeAcceptKey(challengeKey string) string {
|
|
h := sha1.New()
|
|
h.Write([]byte(challengeKey))
|
|
h.Write(keyGUID)
|
|
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
|
}
|