74 lines
1.3 KiB
Go
74 lines
1.3 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
|
|
muWrite sync.Mutex
|
|
}
|
|
|
|
func New(w io.Writer, r io.Reader) *Conn {
|
|
return &Conn{
|
|
w: w,
|
|
r: r,
|
|
}
|
|
}
|
|
|
|
// while serve is running, the conn owns the reader.
|
|
func Serve(ctx context.Context, r io.Reader, wr ircv3.MessageWriter, h ircv3.Handler) error {
|
|
h.Handle(wr, ircv3.NewEvent(ctx, ircv3.EventTypeCONTROL, ircv3.NewMessage("/EVENT_ON_SERVE")))
|
|
dec := &ircdecoder.Decoder{}
|
|
r = bufio.NewReaderSize(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(wr, ircv3.NewEvent(ctx, ircv3.EventTypeIRC, msg))
|
|
}
|
|
}
|
|
|
|
type MessageWriter struct {
|
|
R io.Writer
|
|
Log *slog.Logger
|
|
mu sync.Mutex
|
|
}
|
|
|
|
func (r *MessageWriter) WriteMessage(msg *ircv3.Message) error {
|
|
b := bytebufferpool.Get()
|
|
defer bytebufferpool.Put(b)
|
|
err := msg.Encode(b)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if r.Log != nil {
|
|
r.Log.Info("out >", "msg", msg.String())
|
|
}
|
|
b.WriteString("\r\n")
|
|
r.mu.Lock()
|
|
defer r.mu.Unlock()
|
|
_, err = r.R.Write(b.B)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|