This repository has been archived by the owner on May 11, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
server.go
56 lines (51 loc) · 1.7 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package websocket
import (
"crypto/sha1"
"encoding/base64"
"errors"
"io"
"strings"
"github.com/tsingson/ex-goim/pkg/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))
}