95 lines
2.6 KiB
Go
95 lines
2.6 KiB
Go
|
package networker
|
||
|
|
||
|
import (
|
||
|
// stdlib
|
||
|
"bufio"
|
||
|
"log"
|
||
|
"net"
|
||
|
"strings"
|
||
|
|
||
|
// local
|
||
|
"develop.pztrn.name/gonews/gonews/eventer"
|
||
|
)
|
||
|
|
||
|
// This function is a connection worker.
|
||
|
func connectionWorker(conn net.Conn) {
|
||
|
remoteAddr := conn.RemoteAddr()
|
||
|
log.Printf("accepted connection from %v\n", conn.RemoteAddr())
|
||
|
|
||
|
defer func() {
|
||
|
err := conn.Close()
|
||
|
if err != nil {
|
||
|
log.Println("Failed to close connection from " + remoteAddr.String() + ": " + err.Error())
|
||
|
}
|
||
|
log.Println("Connection from " + remoteAddr.String() + " closed")
|
||
|
}()
|
||
|
|
||
|
// Create buffers.
|
||
|
r := bufio.NewReader(conn)
|
||
|
w := bufio.NewWriter(conn)
|
||
|
scanr := bufio.NewScanner(r)
|
||
|
|
||
|
// Send greeting.
|
||
|
greetingData, _ := eventer.LaunchEvent("internal/greeting", nil)
|
||
|
greetingReply := greetingData.(*Reply)
|
||
|
|
||
|
_, err := w.WriteString(greetingReply.Code + " " + greetingReply.Data)
|
||
|
if err != nil {
|
||
|
log.Println("Failed to write greeting for " + remoteAddr.String() + ": " + err.Error())
|
||
|
return
|
||
|
}
|
||
|
w.Flush()
|
||
|
|
||
|
// Start reading for commands.
|
||
|
// Every command can be represented as slice where first element
|
||
|
// is actual command and all next - parameters.
|
||
|
// By default we read only one line per iteration.
|
||
|
// ToDo: multiline data parser for posting.
|
||
|
for {
|
||
|
dataAppeared := scanr.Scan()
|
||
|
if !dataAppeared {
|
||
|
log.Println("Failed to read data from " + remoteAddr.String() + ": " + scanr.Err().Error())
|
||
|
break
|
||
|
}
|
||
|
|
||
|
log.Println("Got data: " + scanr.Text())
|
||
|
|
||
|
// ToDo: what if we'll upload binary data here?
|
||
|
// Not supported yet.
|
||
|
data := strings.Split(scanr.Text(), " ")
|
||
|
replyRaw, err := eventer.LaunchEvent("commands/"+data[0], data[1:])
|
||
|
if err != nil {
|
||
|
// We won't break here as this is just logging of appeared error.
|
||
|
log.Println("Error appeared while processing command '" + data[0] + "' for " + remoteAddr.String() + ": " + err.Error())
|
||
|
}
|
||
|
|
||
|
// We might have nil in reply, so we'll assume that passed command
|
||
|
// is unknown to us.
|
||
|
if replyRaw == nil {
|
||
|
_, err := w.WriteString(unknownCommandErrorCode + " " + unknownCommandErrorText + "\r\n")
|
||
|
if err != nil {
|
||
|
log.Println("Failed to write string to socket for " + remoteAddr.String() + ": " + err.Error())
|
||
|
break
|
||
|
}
|
||
|
w.Flush()
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
// Every reply will be a reply struct.
|
||
|
reply := replyRaw.(*Reply)
|
||
|
|
||
|
_, err1 := w.WriteString(reply.Code + " " + reply.Data)
|
||
|
if err1 != nil {
|
||
|
log.Println("Failed to write string to socket for " + remoteAddr.String() + ": " + err1.Error())
|
||
|
break
|
||
|
}
|
||
|
w.Flush()
|
||
|
|
||
|
// Check for QUIT command.
|
||
|
if strings.ToLower(data[0]) == "quit" {
|
||
|
log.Println("QUIT command received, closing connection to " + remoteAddr.String())
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
}
|