Maintain a list of downstream connections

This commit is contained in:
Simon Ser 2020-02-06 21:11:35 +01:00
parent 726d7cb54b
commit 8bbba42aef
No known key found for this signature in database
GPG Key ID: 0FDE7BE0E88F5E48
2 changed files with 50 additions and 35 deletions

View File

@ -42,6 +42,8 @@ type downstreamConn struct {
net net.Conn
irc *irc.Conn
srv *Server
logger Logger
registered bool
closed bool
nick string
@ -49,6 +51,45 @@ type downstreamConn struct {
realname string
}
func newDownstreamConn(srv *Server, netConn net.Conn) *downstreamConn {
return &downstreamConn{
net: netConn,
irc: irc.NewConn(netConn),
srv: srv,
logger: &prefixLogger{srv.Logger, fmt.Sprintf("downstream %q: ", netConn.RemoteAddr())},
}
}
func (c *downstreamConn) readMessages() error {
c.logger.Printf("new connection")
defer c.Close()
for {
msg, err := c.irc.ReadMessage()
if err == io.EOF {
break
} else if err != nil {
return fmt.Errorf("failed to read IRC command: %v", err)
}
err = c.handleMessage(msg)
if ircErr, ok := err.(ircError); ok {
ircErr.Message.Prefix = c.srv.prefix()
if err := c.WriteMessage(ircErr.Message); err != nil {
return fmt.Errorf("failed to write IRC reply: %v", err)
}
} else if err != nil {
return fmt.Errorf("failed to handle IRC command %q: %v", msg.Command, err)
}
if c.closed {
return nil
}
}
return c.Close()
}
func (c *downstreamConn) Close() error {
if err := c.net.Close(); err != nil {
return err
@ -95,6 +136,7 @@ func (c *downstreamConn) handleMessageUnregistered(msg *irc.Message) error {
case "QUIT":
return c.Close()
default:
c.logger.Printf("unhandled message: %v", msg)
return newUnknownCommandError(msg.Command)
}
if c.username != "" && c.nick != "" {
@ -162,38 +204,7 @@ func (c *downstreamConn) handleMessageRegistered(msg *irc.Message) error {
case "QUIT":
return c.Close()
default:
c.logger.Printf("unhandled message: %v", msg)
return newUnknownCommandError(msg.Command)
}
}
func handleConn(s *Server, netConn net.Conn) error {
s.Logger.Printf("Handling connection from %v", netConn.RemoteAddr())
c := downstreamConn{net: netConn, irc: irc.NewConn(netConn), srv: s}
defer c.Close()
for {
msg, err := c.irc.ReadMessage()
if err == io.EOF {
break
} else if err != nil {
return fmt.Errorf("failed to read IRC command: %v", err)
}
s.Logger.Printf("Downstream message: %v", msg)
err = c.handleMessage(msg)
if ircErr, ok := err.(ircError); ok {
ircErr.Message.Prefix = s.prefix()
if err := c.WriteMessage(ircErr.Message); err != nil {
return fmt.Errorf("failed to write IRC reply: %v", err)
}
} else if err != nil {
return fmt.Errorf("failed to handle IRC command %q: %v", msg.Command, err)
}
if c.closed {
return nil
}
}
return c.Close()
}

View File

@ -41,6 +41,8 @@ type Server struct {
Hostname string
Logger Logger
Upstreams []Upstream // TODO: per-user
downstreamConns []*downstreamConn
}
func (s *Server) prefix() *irc.Prefix {
@ -61,14 +63,16 @@ func (s *Server) Run() {
func (s *Server) Serve(ln net.Listener) error {
for {
c, err := ln.Accept()
netConn, err := ln.Accept()
if err != nil {
return fmt.Errorf("failed to accept connection: %v", err)
}
conn := newDownstreamConn(s, netConn)
s.downstreamConns = append(s.downstreamConns, conn)
go func() {
if err := handleConn(s, c); err != nil {
s.Logger.Printf("Error handling connection: %v", err)
if err := conn.readMessages(); err != nil {
conn.logger.Printf("Error handling messages: %v", err)
}
}()
}