implemented key -> accept + working upgrade

This commit is contained in:
xdrm-brackets 2018-04-25 18:58:48 +02:00
parent df8c9bc61c
commit 6c8afe8720
4 changed files with 107 additions and 8 deletions

View File

@ -43,13 +43,23 @@ func manageClient(sock net.Conn) {
for {
req, err := request.Build(sock)
/* (1) Parse request */
req, errRq := request.Parse(sock)
if errRq != nil { fmt.Printf("Request parsing error: %s\n", errRq) }
fmt.Printf("%v\n", req)
/* (2) Build response */
res := req.BuildResponse()
/* (3) Write into socket */
written, err := res.Send(sock)
if err != nil {
fmt.Printf("STATUS CODE: %d %s\n", req.StatusCode(), req.StatusCode().Explicit())
panic(err)
fmt.Printf("WRITE ERROR: %s\n", err);
return
}
fmt.Printf("%v\n", req)
fmt.Printf("Written %d bytes\n", written)
break;
}

View File

@ -9,7 +9,7 @@ import (
// Parse builds an upgrade HTTP request
// from a reader (typically bufio.NewRead of the socket)
func Build(r io.Reader) (request *T, err error) {
func Parse(r io.Reader) (request *T, err error) {
req := new(T)
req.code = 500
@ -75,3 +75,24 @@ func (r T) String() string{
func (r T) StatusCode() response.StatusCode {
return r.code
}
// BuildResponse builds a response.T from the request
func (r *T) BuildResponse() *response.T{
inst := new(response.T)
/* (1) Copy code */
inst.SetStatusCode(r.code)
/* (2) Set Protocol */
if len(r.protocols) > 0 {
inst.SetProtocol(r.protocols[0])
}
/* (4) Process key */
inst.ProcessKey(r.key)
return inst
}

View File

@ -0,0 +1,62 @@
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 */
fmt.Printf("Upgrade Response\n----------------\n%s----------------\n", raw)
written, err := w.Write(raw)
return written, err
}

View File

@ -1,9 +1,15 @@
package response
// Constant
const HttpVersion = "1.1"
const WSVersion = 13
var WSSalt []byte = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
// T represents an HTTP Upgrade Response
type T struct {
code StatusCode // status code
accept []byte // processed from Sec-WebSocket-Key
protocol []byte // set from Sec-WebSocket-Protocol or none if not received
code StatusCode // status code
accept []byte // processed from Sec-WebSocket-Key
protocol []byte // set from Sec-WebSocket-Protocol or none if not received
}