source: code/trunk/server.go@ 4

Last change on this file since 4 was 4, checked in by contact, 5 years ago

Handle NICK and USER

File size: 2.4 KB
RevLine 
[1]1package jounce
2
3import (
4 "fmt"
[3]5 "io"
[1]6 "log"
7 "net"
8
9 "gopkg.in/irc.v3"
10)
11
[4]12type ircError struct {
13 Message *irc.Message
14}
15
16func newUnknownCommandError(cmd string) ircError {
17 return ircError{&irc.Message{
18 Command: irc.ERR_UNKNOWNCOMMAND,
19 Params: []string{
20 "*",
21 cmd,
22 "Unknown command",
23 },
24 }}
25}
26
27func newNeedMoreParamsError(cmd string) ircError {
28 return ircError{&irc.Message{
29 Command: irc.ERR_NEEDMOREPARAMS,
30 Params: []string{
31 "*",
32 cmd,
33 "Not enough parameters",
34 },
35 }}
36}
37
38func (err ircError) Error() string {
39 return err.Message.String()
40}
41
[3]42type conn struct {
[4]43 net net.Conn
44 irc *irc.Conn
45 registered bool
46 nick string
47 username string
48 realname string
[3]49}
[1]50
[4]51func (c *conn) handleMessageUnregistered(msg *irc.Message) error {
52 switch msg.Command {
53 case "NICK":
54 if len(msg.Params) != 1 {
55 return newNeedMoreParamsError(msg.Command)
56 }
57 c.nick = msg.Params[0]
58 case "USER":
59 if len(msg.Params) != 4 {
60 return newNeedMoreParamsError(msg.Command)
61 }
62 c.username = "~" + msg.Params[0]
63 c.realname = msg.Params[3]
64 c.registered = true
65 default:
66 return newUnknownCommandError(msg.Command)
67 }
68 return nil
69}
70
71func (c *conn) handleMessage(msg *irc.Message) error {
72 switch msg.Command {
73 case "NICK", "USER":
74 return ircError{&irc.Message{
75 Command: irc.ERR_ALREADYREGISTERED,
76 Params: []string{
77 c.nick,
78 "You may not reregister",
79 },
80 }}
81 default:
82 return newUnknownCommandError(msg.Command)
83 }
84}
85
[3]86type Server struct{}
87
88func (s *Server) handleConn(netConn net.Conn) error {
89 defer netConn.Close()
90
[4]91 c := conn{net: netConn, irc: irc.NewConn(netConn)}
[1]92 for {
[4]93 msg, err := c.irc.ReadMessage()
[3]94 if err == io.EOF {
95 break
96 } else if err != nil {
[4]97 return fmt.Errorf("failed to read IRC command: %v", err)
[1]98 }
[3]99 log.Println(msg)
[1]100
[4]101 if c.registered {
102 err = c.handleMessage(msg)
103 } else {
104 err = c.handleMessageUnregistered(msg)
[3]105 }
[4]106 if ircErr, ok := err.(ircError); ok {
107 if err := c.irc.WriteMessage(ircErr.Message); err != nil {
108 return fmt.Errorf("failed to write IRC reply: %v", err)
109 }
110 } else if err != nil {
111 return fmt.Errorf("failed to handle IRC command %q: %v", msg.Command, err)
112 }
[1]113 }
[3]114
115 return netConn.Close()
[1]116}
117
[3]118func (s *Server) Serve(ln net.Listener) error {
[1]119 for {
[3]120 c, err := ln.Accept()
[1]121 if err != nil {
122 return fmt.Errorf("failed to accept connection: %v", err)
123 }
124
125 go func() {
[3]126 if err := s.handleConn(c); err != nil {
[1]127 log.Printf("error handling connection: %v", err)
128 }
129 }()
130 }
131}
Note: See TracBrowser for help on using the repository browser.