Refactored and corrected client's network data reading
This commit is contained in:
parent
63f94d18c9
commit
0b8c40aa61
44
client.go
44
client.go
@ -27,8 +27,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CRLF = "\x0d\x0a"
|
BufSize = 1500
|
||||||
BufSize = 1380
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
CRLF []byte = []byte{'\x0d', '\x0a'}
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
@ -59,34 +62,41 @@ func NewClient(hostname *string, conn net.Conn) *Client {
|
|||||||
// splits messages by CRLF and send them to Daemon gorouting for processing
|
// splits messages by CRLF and send them to Daemon gorouting for processing
|
||||||
// it futher. Also it can signalize that client is unavailable (disconnected).
|
// it futher. Also it can signalize that client is unavailable (disconnected).
|
||||||
func (client *Client) Processor(sink chan<- ClientEvent) {
|
func (client *Client) Processor(sink chan<- ClientEvent) {
|
||||||
var bufNet []byte
|
|
||||||
buf := make([]byte, 0)
|
|
||||||
log.Println(client, "New client")
|
|
||||||
sink <- ClientEvent{client, EventNew, ""}
|
sink <- ClientEvent{client, EventNew, ""}
|
||||||
|
log.Println(client, "New client")
|
||||||
|
buf := make([]byte, BufSize*2)
|
||||||
|
var n int
|
||||||
|
var prev int
|
||||||
|
var i int
|
||||||
|
var err error
|
||||||
for {
|
for {
|
||||||
bufNet = make([]byte, BufSize)
|
if prev == BufSize {
|
||||||
_, err := client.conn.Read(bufNet)
|
log.Println(client, "buffer size exceeded, kicking him")
|
||||||
|
sink <- ClientEvent{client, EventDel, ""}
|
||||||
|
client.conn.Close()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
n, err = client.conn.Read(buf[prev:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sink <- ClientEvent{client, EventDel, ""}
|
sink <- ClientEvent{client, EventDel, ""}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
bufNet = bytes.TrimRight(bufNet, "\x00")
|
prev += n
|
||||||
buf = append(buf, bufNet...)
|
CheckMore:
|
||||||
if !bytes.HasSuffix(buf, []byte(CRLF)) {
|
i = bytes.Index(buf[:prev], CRLF)
|
||||||
|
if i == -1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, msg := range bytes.Split(buf[:len(buf)-2], []byte(CRLF)) {
|
sink <- ClientEvent{client, EventMsg, string(buf[:i])}
|
||||||
if len(msg) > 0 {
|
copy(buf, buf[i+2:prev])
|
||||||
sink <- ClientEvent{client, EventMsg, string(msg)}
|
prev -= (i + 2)
|
||||||
}
|
goto CheckMore
|
||||||
}
|
|
||||||
buf = []byte{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send message as is with CRLF appended.
|
// Send message as is with CRLF appended.
|
||||||
func (client *Client) Msg(text string) {
|
func (client *Client) Msg(text string) {
|
||||||
client.conn.Write([]byte(text + CRLF))
|
client.conn.Write(append([]byte(text), CRLF...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send message from server. It has ": servername" prefix.
|
// Send message from server. It has ": servername" prefix.
|
||||||
|
@ -47,10 +47,10 @@ func (conn *TestingConn) Read(b []byte) (n int, err error) {
|
|||||||
if msg == "" {
|
if msg == "" {
|
||||||
return 0, conn
|
return 0, conn
|
||||||
}
|
}
|
||||||
for n, bt := range []byte(msg + CRLF) {
|
for n, bt := range append([]byte(msg), CRLF...) {
|
||||||
b[n] = bt
|
b[n] = bt
|
||||||
}
|
}
|
||||||
return len(msg), nil
|
return len(msg)+2, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type MyAddr struct{}
|
type MyAddr struct{}
|
||||||
|
@ -91,6 +91,7 @@ func TestRegistrationWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
conn.inbound <- "AWAY"
|
conn.inbound <- "AWAY"
|
||||||
conn.inbound <- "UNEXISTENT CMD"
|
conn.inbound <- "UNEXISTENT CMD"
|
||||||
|
<-conn.outbound
|
||||||
if r := <-conn.outbound; r != ":foohost 421 meinick UNEXISTENT :Unknown command\r\n" {
|
if r := <-conn.outbound; r != ":foohost 421 meinick UNEXISTENT :Unknown command\r\n" {
|
||||||
t.Fatal("reply for unexistent command", r)
|
t.Fatal("reply for unexistent command", r)
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,8 @@ func TestTwoUsers(t *testing.T) {
|
|||||||
go client1.Processor(events)
|
go client1.Processor(events)
|
||||||
go client2.Processor(events)
|
go client2.Processor(events)
|
||||||
|
|
||||||
conn1.inbound <- "NICK nick1\r\nUSER foo1 bar1 baz1 :Long name1\r\n"
|
conn1.inbound <- "NICK nick1\r\nUSER foo1 bar1 baz1 :Long name1"
|
||||||
conn2.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2\r\n"
|
conn2.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2"
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
<-conn1.outbound
|
<-conn1.outbound
|
||||||
<-conn2.outbound
|
<-conn2.outbound
|
||||||
@ -105,6 +105,7 @@ func TestTwoUsers(t *testing.T) {
|
|||||||
conn1.inbound <- "PRIVMSG nick2 :Hello"
|
conn1.inbound <- "PRIVMSG nick2 :Hello"
|
||||||
conn1.inbound <- "PRIVMSG #foo :world"
|
conn1.inbound <- "PRIVMSG #foo :world"
|
||||||
conn1.inbound <- "NOTICE #foo :world"
|
conn1.inbound <- "NOTICE #foo :world"
|
||||||
|
<-conn2.outbound
|
||||||
if r := <-conn2.outbound; r != ":nick1!foo1@someclient PRIVMSG nick2 :Hello\r\n" {
|
if r := <-conn2.outbound; r != ":nick1!foo1@someclient PRIVMSG nick2 :Hello\r\n" {
|
||||||
t.Fatal("first message", r)
|
t.Fatal("first message", r)
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ func TestJoin(t *testing.T) {
|
|||||||
client := NewClient(&host, conn)
|
client := NewClient(&host, conn)
|
||||||
go client.Processor(events)
|
go client.Processor(events)
|
||||||
|
|
||||||
conn.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2\r\n"
|
conn.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2"
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 6; i++ {
|
||||||
<-conn.outbound
|
<-conn.outbound
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user