implemented key -> accept + working upgrade
This commit is contained in:
parent
df8c9bc61c
commit
6c8afe8720
|
@ -43,13 +43,23 @@ func manageClient(sock net.Conn) {
|
||||||
|
|
||||||
for {
|
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 {
|
if err != nil {
|
||||||
fmt.Printf("STATUS CODE: %d %s\n", req.StatusCode(), req.StatusCode().Explicit())
|
fmt.Printf("WRITE ERROR: %s\n", err);
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("%v\n", req)
|
fmt.Printf("Written %d bytes\n", written)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
// Parse builds an upgrade HTTP request
|
// Parse builds an upgrade HTTP request
|
||||||
// from a reader (typically bufio.NewRead of the socket)
|
// 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 := new(T)
|
||||||
req.code = 500
|
req.code = 500
|
||||||
|
@ -75,3 +75,24 @@ func (r T) String() string{
|
||||||
func (r T) StatusCode() response.StatusCode {
|
func (r T) StatusCode() response.StatusCode {
|
||||||
return r.code
|
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
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
||||||
|
}
|
|
@ -1,9 +1,15 @@
|
||||||
package response
|
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
|
// T represents an HTTP Upgrade Response
|
||||||
type T struct {
|
type T struct {
|
||||||
|
|
||||||
code StatusCode // status code
|
code StatusCode // status code
|
||||||
accept []byte // processed from Sec-WebSocket-Key
|
accept []byte // processed from Sec-WebSocket-Key
|
||||||
protocol []byte // set from Sec-WebSocket-Protocol or none if not received
|
protocol []byte // set from Sec-WebSocket-Protocol or none if not received
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue