summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Matveev <stargrave@stargrave.org>2015-10-06 11:27:11 +0300
committerSergey Matveev <stargrave@stargrave.org>2015-10-06 12:48:04 +0300
commit0b8c40aa61e899edb3e563b7771e3d7927d6e859 (patch)
treeefd9293ef7e0e361cf293467f0d4d6ca46d017bd
parent63f94d18c90f290d9cdffb703fc97c266320738d (diff)
downloadgoircd-0b8c40aa61e899edb3e563b7771e3d7927d6e859.tar.xz
Refactored and corrected client's network data reading
-rw-r--r--client.go44
-rw-r--r--client_test.go4
-rw-r--r--daemon_test.go1
-rw-r--r--room_test.go7
4 files changed, 34 insertions, 22 deletions
diff --git a/client.go b/client.go
index 95dd93f..9bcaf30 100644
--- a/client.go
+++ b/client.go
@@ -27,8 +27,11 @@ import (
)
const (
- CRLF = "\x0d\x0a"
- BufSize = 1380
+ BufSize = 1500
+)
+
+var (
+ CRLF []byte = []byte{'\x0d', '\x0a'}
)
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
// it futher. Also it can signalize that client is unavailable (disconnected).
func (client *Client) Processor(sink chan<- ClientEvent) {
- var bufNet []byte
- buf := make([]byte, 0)
- log.Println(client, "New client")
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 {
- bufNet = make([]byte, BufSize)
- _, err := client.conn.Read(bufNet)
+ if prev == BufSize {
+ 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 {
sink <- ClientEvent{client, EventDel, ""}
break
}
- bufNet = bytes.TrimRight(bufNet, "\x00")
- buf = append(buf, bufNet...)
- if !bytes.HasSuffix(buf, []byte(CRLF)) {
+ prev += n
+ CheckMore:
+ i = bytes.Index(buf[:prev], CRLF)
+ if i == -1 {
continue
}
- for _, msg := range bytes.Split(buf[:len(buf)-2], []byte(CRLF)) {
- if len(msg) > 0 {
- sink <- ClientEvent{client, EventMsg, string(msg)}
- }
- }
- buf = []byte{}
+ sink <- ClientEvent{client, EventMsg, string(buf[:i])}
+ copy(buf, buf[i+2:prev])
+ prev -= (i + 2)
+ goto CheckMore
}
}
// Send message as is with CRLF appended.
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.
diff --git a/client_test.go b/client_test.go
index 38f8808..3735e1f 100644
--- a/client_test.go
+++ b/client_test.go
@@ -47,10 +47,10 @@ func (conn *TestingConn) Read(b []byte) (n int, err error) {
if msg == "" {
return 0, conn
}
- for n, bt := range []byte(msg + CRLF) {
+ for n, bt := range append([]byte(msg), CRLF...) {
b[n] = bt
}
- return len(msg), nil
+ return len(msg)+2, nil
}
type MyAddr struct{}
diff --git a/daemon_test.go b/daemon_test.go
index 3db72cb..efdb39f 100644
--- a/daemon_test.go
+++ b/daemon_test.go
@@ -91,6 +91,7 @@ func TestRegistrationWorkflow(t *testing.T) {
conn.inbound <- "AWAY"
conn.inbound <- "UNEXISTENT CMD"
+ <-conn.outbound
if r := <-conn.outbound; r != ":foohost 421 meinick UNEXISTENT :Unknown command\r\n" {
t.Fatal("reply for unexistent command", r)
}
diff --git a/room_test.go b/room_test.go
index d5bf411..d94e8d4 100644
--- a/room_test.go
+++ b/room_test.go
@@ -56,8 +56,8 @@ func TestTwoUsers(t *testing.T) {
go client1.Processor(events)
go client2.Processor(events)
- conn1.inbound <- "NICK nick1\r\nUSER foo1 bar1 baz1 :Long name1\r\n"
- conn2.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2\r\n"
+ conn1.inbound <- "NICK nick1\r\nUSER foo1 bar1 baz1 :Long name1"
+ conn2.inbound <- "NICK nick2\r\nUSER foo2 bar2 baz2 :Long name2"
for i := 0; i < 6; i++ {
<-conn1.outbound
<-conn2.outbound
@@ -105,6 +105,7 @@ func TestTwoUsers(t *testing.T) {
conn1.inbound <- "PRIVMSG nick2 :Hello"
conn1.inbound <- "PRIVMSG #foo :world"
conn1.inbound <- "NOTICE #foo :world"
+ <-conn2.outbound
if r := <-conn2.outbound; r != ":nick1!foo1@someclient PRIVMSG nick2 :Hello\r\n" {
t.Fatal("first message", r)
}
@@ -127,7 +128,7 @@ func TestJoin(t *testing.T) {
client := NewClient(&host, conn)
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++ {
<-conn.outbound
}