ws/internal/http/upgrade/response/public.go

61 lines
1.3 KiB
Go
Raw Normal View History

package response
import (
"fmt"
"io"
"encoding/base64"
"crypto/sha1"
)
// SetStatusCode sets the status code
func (r *T) SetStatusCode(sc StatusCode) {
r.code = sc
}
// SetProtocols sets the protocols
func (r *T) SetProtocol(p []byte) {
r.protocol = p
}
// ProcessKey processes the accept token according
// to the rfc from the Sec-WebSocket-Key
func (r *T) ProcessKey(k []byte) {
/* (1) Concat with constant salt */
mix := append(k, WSSalt...)
/* (2) Hash with sha1 algorithm */
digest := sha1.Sum(mix)
/* (3) Base64 encode it */
r.accept = []byte( base64.StdEncoding.EncodeToString( digest[:sha1.Size] ) )
}
// Send sends the response through an io.Writer
// typically a socket
func (r T) Send(w io.Writer) (int, error) {
/* (1) Build response line */
responseLine := fmt.Sprintf("HTTP/%s %d %s\r\n", HttpVersion, r.code, r.code.Explicit())
/* (2) Build headers */
optionalProtocol := ""
if len(r.protocol) > 0 {
optionalProtocol = fmt.Sprintf("Sec-WebSocket-Protocol: %s\r\n", r.protocol)
}
headers := fmt.Sprintf("Upgrade: websocket\t\nConnection: Upgrade\r\nSec-WebSocket-Accept: %s\r\nSec-WebSocket-Version: %d\r\n%s", r.accept, WSVersion, optionalProtocol)
/* (3) Build all */
raw := []byte(fmt.Sprintf("%s%s\r\n", responseLine, headers))
/* (4) Write */
written, err := w.Write(raw)
return written, err
}