106 lines
1.6 KiB
Go
106 lines
1.6 KiB
Go
package meanstoanend
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"errors"
|
|
"io"
|
|
"net"
|
|
|
|
"github.com/charmbracelet/log"
|
|
)
|
|
|
|
type message struct {
|
|
a int32
|
|
b int32
|
|
}
|
|
|
|
type client struct {
|
|
conn net.Conn
|
|
prices map[int32]int32
|
|
log *log.Logger
|
|
buf []byte
|
|
}
|
|
|
|
func (c *client) handleMessage() error {
|
|
_, err := io.ReadFull(c.conn, c.buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
msg := new(message)
|
|
|
|
_, err = binary.Decode(c.buf[1:5], binary.BigEndian, &msg.a)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = binary.Decode(c.buf[5:], binary.BigEndian, &msg.b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch c.buf[0] {
|
|
case 'I':
|
|
c.prices[msg.a] = msg.b
|
|
case 'Q':
|
|
var i int64
|
|
var mean int64
|
|
|
|
for k, v := range c.prices {
|
|
if k >= msg.a && k <= msg.b {
|
|
mean += int64(v)
|
|
i += 1
|
|
}
|
|
}
|
|
|
|
if i > 0 {
|
|
mean /= i
|
|
}
|
|
|
|
binary.Write(c.conn, binary.BigEndian, int32(mean))
|
|
default:
|
|
c.conn.Close()
|
|
return errors.New("bad message")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func acceptConn(conn net.Conn) {
|
|
log.Info("accepting connection", "remote", conn.RemoteAddr())
|
|
|
|
var err error
|
|
|
|
c := new(client)
|
|
c.log = log.Default().WithPrefix(conn.RemoteAddr().String())
|
|
|
|
c.buf = make([]byte, 9)
|
|
c.conn = conn
|
|
c.prices = map[int32]int32{}
|
|
|
|
defer c.conn.Close()
|
|
|
|
for {
|
|
c.log.Debug("waiting for message", "remote", conn.RemoteAddr())
|
|
err = c.handleMessage()
|
|
if err != nil {
|
|
if err != io.EOF {
|
|
c.log.Error("unable to read data", "err", err)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
|
|
c.log.Info("released connection")
|
|
}
|
|
|
|
func New(listener net.Listener) error {
|
|
for {
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
go acceptConn(conn)
|
|
}
|
|
}
|