manage invalid Close codes + close() now can work without sending the CLOSE frame (if status=NONE)

[TODO] manage fragmentation
This commit is contained in:
xdrm-brackets 2018-05-06 01:37:02 +02:00
parent f07afb8c85
commit 75f568a1ec
1 changed files with 44 additions and 23 deletions

View File

@ -164,6 +164,13 @@ func clientReader(c *client){
if msg.Size > 2 && !utf8.Valid(msg.Data[2:]) { if msg.Size > 2 && !utf8.Valid(msg.Data[2:]) {
errorCode = INVALID_PAYLOAD errorCode = INVALID_PAYLOAD
} }
// invalid code
if msg.Size >= 2 {
cCode := binary.BigEndian.Uint16(msg.Data[0:2])
if invalidCloseCode(cCode) {
errorCode = PROTOCOL_ERR
}
}
clientAck = false clientAck = false
break break
@ -171,7 +178,7 @@ func clientReader(c *client){
/* (5) PING size error */ /* (5) PING size error */
if msg.Type == PING && msg.Size > 125 { if msg.Type == PING && msg.Size > 125 {
fmt.Printf(" [reader] PING payload too big\n") // fmt.Printf(" [reader] PING payload too big\n")
// fmt.Printf("[reader] PING err\n") // fmt.Printf("[reader] PING err\n")
errorCode = PROTOCOL_ERR errorCode = PROTOCOL_ERR
break break
@ -190,14 +197,14 @@ func clientReader(c *client){
/* (7) Invalid UTF8 */ /* (7) Invalid UTF8 */
if msg.Type == TEXT && !utf8.Valid(msg.Data) { if msg.Type == TEXT && !utf8.Valid(msg.Data) {
fmt.Printf(" [reader] invalid utf-8\n") // fmt.Printf(" [reader] invalid utf-8\n")
errorCode = INVALID_PAYLOAD errorCode = INVALID_PAYLOAD
break break
} }
/* (8) Unknown opcode */ /* (8) Unknown opcode */
if msg.Type != TEXT && msg.Type != BINARY { if msg.Type != TEXT && msg.Type != BINARY {
fmt.Printf(" [reader] unknown OpCode %d\n", msg.Type) // fmt.Printf(" [reader] unknown OpCode %d\n", msg.Type)
errorCode = PROTOCOL_ERR errorCode = PROTOCOL_ERR
break break
} }
@ -249,10 +256,10 @@ func clientWriter(c *client){
// close writes the error message (if needed) // closes the connection
// and it closes the socket // send CLOSE frame is 'status' is not NONE
// if 'clientACK' is true, reads the next message (CLOSE acknowledge) // wait for the next message (CLOSE acknowledge) if 'clientACK'
// before closing the socket // then delete client
func (c *client) close(status MessageError, clientACK bool){ func (c *client) close(status MessageError, clientACK bool){
/* (1) Fail if already closing */ /* (1) Fail if already closing */
@ -277,25 +284,24 @@ func (c *client) close(status MessageError, clientACK bool){
if status == NONE { if status != NONE {
status = NORMAL
}
/* (3) Build message */ /* (3) Build message */
msg := &Message{ msg := &Message{
Final: true, Final: true,
Type: CLOSE, Type: CLOSE,
Size: 2, Size: 2,
Data: make([]byte, 2), Data: make([]byte, 2),
} }
binary.BigEndian.PutUint16(msg.Data, uint16(status)) binary.BigEndian.PutUint16(msg.Data, uint16(status))
/* (4) Send message */
err := msg.Send(c.io.sock)
if err != nil {
fmt.Printf("[close] send error (%s0\n", err)
}
/* (4) Send message */
err := msg.Send(c.io.sock)
if err != nil {
fmt.Printf("[close] send error (%s0\n", err)
} }
// fmt.Printf("[close] frame sent\n")
/* (2) Wait for client CLOSE if needed */ /* (2) Wait for client CLOSE if needed */
@ -327,3 +333,18 @@ func (c *client) close(status MessageError, clientACK bool){
return return
} }
func invalidCloseCode(code uint16) bool{
tolow := code < 1000
badrange1 := code >= 1004 && code <= 1006
badrange2 := code >= 1012 && code <= 1016
badspecific := code == 1100 || code == 2000 || code == 2999
return tolow || badrange1 || badrange2 || badspecific
}