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.Message()) /* (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 } // GetProtocol returns the choosen protocol if set, else nil func (r T) GetProtocol() []byte { return r.protocol }