]> Cypherpunks.ru repositories - goircd.git/blobdiff - client.go
Refactored and corrected client's network data reading
[goircd.git] / client.go
index 4f48daf90be4f1f0981b96f6e30ca04fa1f438a0..9bcaf30575d6829b00d96cedd04b7166330fb986 100644 (file)
--- a/client.go
+++ b/client.go
@@ -1,6 +1,6 @@
 /*
 goircd -- minimalistic simple Internet Relay Chat (IRC) server
-Copyright (C) 2014 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -15,6 +15,7 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
+
 package main
 
 import (
@@ -26,18 +27,22 @@ import (
 )
 
 const (
-       CRLF    = "\x0d\x0a"
-       BufSize = 1380
+       BufSize = 1500
+)
+
+var (
+       CRLF []byte = []byte{'\x0d', '\x0a'}
 )
 
 type Client struct {
-       hostname   string
+       hostname   *string
        conn       net.Conn
        registered bool
        nickname   string
        username   string
        realname   string
        password   string
+       away       *string
 }
 
 type ClientAlivenessState struct {
@@ -49,7 +54,7 @@ func (client Client) String() string {
        return client.nickname + "!" + client.username + "@" + client.conn.RemoteAddr().String()
 }
 
-func NewClient(hostname string, conn net.Conn) *Client {
+func NewClient(hostname *string, conn net.Conn) *Client {
        return &Client{hostname: hostname, conn: conn, nickname: "*", password: ""}
 }
 
@@ -57,39 +62,46 @@ 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.
 func (client *Client) Reply(text string) {
-       client.Msg(":" + client.hostname + " " + text)
+       client.Msg(":" + *client.hostname + " " + text)
 }
 
 // Send server message, concatenating all provided text parts and