70 lines
1.2 KiB
Go
70 lines
1.2 KiB
Go
|
package ircconn
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"context"
|
||
|
"io"
|
||
|
"log/slog"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/valyala/bytebufferpool"
|
||
|
"tuxpa.in/a/irc/pkg/ircdecoder"
|
||
|
"tuxpa.in/a/irc/pkg/ircv3"
|
||
|
)
|
||
|
|
||
|
type Conn struct {
|
||
|
w io.Writer
|
||
|
r io.Reader
|
||
|
log *slog.Logger
|
||
|
muWrite sync.Mutex
|
||
|
}
|
||
|
|
||
|
func New(log *slog.Logger, w io.Writer, r io.Reader) *Conn {
|
||
|
return &Conn{
|
||
|
log: log,
|
||
|
w: w,
|
||
|
r: r,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// while serve is running, the conn owns the reader.
|
||
|
func (c *Conn) Serve(ctx context.Context, h ircv3.Handler) error {
|
||
|
// once serve is called, we call with an empty message.
|
||
|
h.Handle(ctx, c, &ircv3.Message{})
|
||
|
dec := &ircdecoder.Decoder{}
|
||
|
r := c.r
|
||
|
r = bufio.NewReaderSize(c.r, 10240)
|
||
|
for {
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
return ctx.Err()
|
||
|
default:
|
||
|
}
|
||
|
msg := &ircv3.Message{}
|
||
|
r = io.LimitReader(r, 8191+512)
|
||
|
err := dec.Decode(r, msg)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
h.Handle(ctx, c, msg)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *Conn) WriteMessage(msg *ircv3.Message) error {
|
||
|
b := bytebufferpool.Get()
|
||
|
defer bytebufferpool.Put(b)
|
||
|
err := msg.Encode(b)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
b.WriteString("\r\n")
|
||
|
c.muWrite.Lock()
|
||
|
defer c.muWrite.Unlock()
|
||
|
c.log.Info("out >", "msg", msg.String())
|
||
|
_, err = b.WriteTo(c.w)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|