Changeset 13 in code for trunk/server.go
- Timestamp:
- Feb 6, 2020, 3:18:19 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server.go
r12 r13 2 2 3 3 import ( 4 "crypto/tls"5 4 "fmt" 6 "io"7 "log"8 5 "net" 9 6 … … 14 11 Print(v ...interface{}) 15 12 Printf(format string, v ...interface{}) 16 }17 18 type ircError struct {19 Message *irc.Message20 }21 22 func newUnknownCommandError(cmd string) ircError {23 return ircError{&irc.Message{24 Command: irc.ERR_UNKNOWNCOMMAND,25 Params: []string{26 "*",27 cmd,28 "Unknown command",29 },30 }}31 }32 33 func newNeedMoreParamsError(cmd string) ircError {34 return ircError{&irc.Message{35 Command: irc.ERR_NEEDMOREPARAMS,36 Params: []string{37 "*",38 cmd,39 "Not enough parameters",40 },41 }}42 }43 44 func (err ircError) Error() string {45 return err.Message.String()46 }47 48 type downstreamConn struct {49 net net.Conn50 irc *irc.Conn51 srv *Server52 registered bool53 closed bool54 nick string55 username string56 realname string57 }58 59 func (c *downstreamConn) Close() error {60 if err := c.net.Close(); err != nil {61 return err62 }63 c.closed = true64 return nil65 }66 67 func (c *downstreamConn) WriteMessage(msg *irc.Message) error {68 msg.Prefix = c.srv.prefix()69 return c.irc.WriteMessage(msg)70 }71 72 func (c *downstreamConn) handleMessage(msg *irc.Message) error {73 switch msg.Command {74 case "PING":75 // TODO: handle params76 return c.WriteMessage(&irc.Message{77 Command: "PONG",78 Params: []string{c.srv.Hostname},79 })80 default:81 if c.registered {82 return c.handleMessageRegistered(msg)83 } else {84 return c.handleMessageUnregistered(msg)85 }86 }87 }88 89 func (c *downstreamConn) handleMessageUnregistered(msg *irc.Message) error {90 switch msg.Command {91 case "NICK":92 if len(msg.Params) != 1 {93 return newNeedMoreParamsError(msg.Command)94 }95 c.nick = msg.Params[0]96 case "USER":97 if len(msg.Params) != 4 {98 return newNeedMoreParamsError(msg.Command)99 }100 c.username = "~" + msg.Params[0]101 c.realname = msg.Params[3]102 case "QUIT":103 return c.Close()104 default:105 return newUnknownCommandError(msg.Command)106 }107 if c.username != "" && c.nick != "" {108 return c.register()109 }110 return nil111 }112 113 func (c *downstreamConn) register() error {114 c.registered = true115 116 err := c.WriteMessage(&irc.Message{117 Command: irc.RPL_WELCOME,118 Params: []string{c.nick, "Welcome to jounce, " + c.nick},119 })120 if err != nil {121 return err122 }123 124 err = c.WriteMessage(&irc.Message{125 Command: irc.RPL_YOURHOST,126 Params: []string{c.nick, "Your host is " + c.srv.Hostname},127 })128 if err != nil {129 return err130 }131 132 err = c.WriteMessage(&irc.Message{133 Command: irc.RPL_CREATED,134 Params: []string{c.nick, "This server was created <datetime>"}, // TODO135 })136 if err != nil {137 return err138 }139 140 err = c.WriteMessage(&irc.Message{141 Command: irc.RPL_MYINFO,142 Params: []string{c.nick, c.srv.Hostname, "unknown", "", ""},143 })144 if err != nil {145 return err146 }147 148 err = c.WriteMessage(&irc.Message{149 Command: irc.ERR_NOMOTD,150 Params: []string{c.nick, "No MOTD"},151 })152 if err != nil {153 return err154 }155 156 return nil157 }158 159 func (c *downstreamConn) handleMessageRegistered(msg *irc.Message) error {160 switch msg.Command {161 case "NICK", "USER":162 return ircError{&irc.Message{163 Command: irc.ERR_ALREADYREGISTERED,164 Params: []string{165 c.nick,166 "You may not reregister",167 },168 }}169 case "QUIT":170 return c.Close()171 default:172 return newUnknownCommandError(msg.Command)173 }174 }175 176 type upstreamConn struct {177 net net.Conn178 irc *irc.Conn179 srv *Server180 }181 182 func (c *upstreamConn) handleMessage(msg *irc.Message) error {183 switch msg.Command {184 case "PING":185 // TODO: handle params186 return c.irc.WriteMessage(&irc.Message{187 Command: "PONG",188 Params: []string{c.srv.Hostname},189 })190 default:191 c.srv.Logger.Printf("Unhandled upstream message: %v", msg)192 return nil193 }194 13 } 195 14 … … 211 30 } 212 31 213 func (s *Server) handleConn(netConn net.Conn) error {214 s.Logger.Printf("Handling connection from %v", netConn.RemoteAddr())215 216 c := downstreamConn{net: netConn, irc: irc.NewConn(netConn), srv: s}217 defer c.Close()218 for {219 msg, err := c.irc.ReadMessage()220 if err == io.EOF {221 break222 } else if err != nil {223 return fmt.Errorf("failed to read IRC command: %v", err)224 }225 s.Logger.Printf("Downstream message: %v", msg)226 227 err = c.handleMessage(msg)228 if ircErr, ok := err.(ircError); ok {229 ircErr.Message.Prefix = s.prefix()230 if err := c.WriteMessage(ircErr.Message); err != nil {231 return fmt.Errorf("failed to write IRC reply: %v", err)232 }233 } else if err != nil {234 return fmt.Errorf("failed to handle IRC command %q: %v", msg.Command, err)235 }236 237 if c.closed {238 return nil239 }240 }241 242 return c.Close()243 }244 245 func (s *Server) connect(upstream *Upstream) error {246 s.Logger.Printf("Connecting to %v", upstream.Addr)247 248 netConn, err := tls.Dial("tcp", upstream.Addr, nil)249 if err != nil {250 return fmt.Errorf("failed to dial %q: %v", upstream.Addr, err)251 }252 253 c := upstreamConn{net: netConn, irc: irc.NewConn(netConn), srv: s}254 defer netConn.Close()255 256 err = c.irc.WriteMessage(&irc.Message{257 Command: "NICK",258 Params: []string{upstream.Nick},259 })260 if err != nil {261 return err262 }263 264 err = c.irc.WriteMessage(&irc.Message{265 Command: "USER",266 Params: []string{upstream.Username, "0", "*", upstream.Realname},267 })268 if err != nil {269 return err270 }271 272 for {273 msg, err := c.irc.ReadMessage()274 if err == io.EOF {275 break276 } else if err != nil {277 return fmt.Errorf("failed to read IRC command: %v", err)278 }279 280 if err := c.handleMessage(msg); err != nil {281 return err282 }283 }284 285 return netConn.Close()286 }287 288 32 func (s *Server) Run() { 289 33 for i := range s.Upstreams { … … 291 35 // TODO: retry connecting 292 36 go func() { 293 if err := s.connect(upstream); err != nil {37 if err := connect(s, upstream); err != nil { 294 38 s.Logger.Printf("Failed to connect to upstream server %q: %v", upstream.Addr, err) 295 39 } … … 306 50 307 51 go func() { 308 if err := s.handleConn(c); err != nil {309 log.Printf("error handling connection: %v", err)52 if err := handleConn(s, c); err != nil { 53 s.Logger.Printf("Error handling connection: %v", err) 310 54 } 311 55 }()
Note:
See TracChangeset
for help on using the changeset viewer.