- }
- }
- sort.Strings(subscriptions)
- client.ReplyNicknamed("319", c.nickname, strings.Join(subscriptions, " "))
- client.ReplyNicknamed("318", c.nickname, "End of /WHOIS list")
- }
- if !found {
- client.ReplyNoNickChan(nickname)
- }
- }
-}
-
-func (daemon *Daemon) SendList(client *Client, cols []string) {
- var rooms []string
- if (len(cols) > 1) && (cols[1] != "") {
- rooms = strings.Split(strings.Split(cols[1], " ")[0], ",")
- } else {
- rooms = []string{}
- for room := range daemon.rooms {
- rooms = append(rooms, room)
- }
- }
- sort.Strings(rooms)
- for _, room := range rooms {
- r, found := daemon.rooms[room]
- if found {
- client.ReplyNicknamed("322", room, fmt.Sprintf("%d", len(r.members)), r.topic)
- }
- }
- client.ReplyNicknamed("323", "End of /LIST")
-}
-
-// Unregistered client workflow processor. Unregistered client:
-// * is not PINGed
-// * only QUIT, NICK and USER commands are processed
-// * other commands are quietly ignored
-// When client finishes NICK/USER workflow, then MOTD and LUSERS are send to him.
-func (daemon *Daemon) ClientRegister(client *Client, command string, cols []string) {
- switch command {
- case "NICK":
- if len(cols) == 1 || len(cols[1]) < 1 {
- client.ReplyParts("431", "No nickname given")
- return
- }
- nickname := cols[1]
- for client := range daemon.clients {
- if client.nickname == nickname {
- client.ReplyParts("433", "*", nickname, "Nickname is already in use")
- return
- }
- }
- if !RE_NICKNAME.MatchString(nickname) {
- client.ReplyParts("432", "*", cols[1], "Erroneous nickname")
- return
- }
- client.nickname = nickname
- case "USER":
- if len(cols) == 1 {
- client.ReplyNotEnoughParameters("USER")
- return
- }
- args := strings.SplitN(cols[1], " ", 4)
- if len(args) < 4 {
- client.ReplyNotEnoughParameters("USER")
- return
- }
- client.username = args[0]
- client.realname = strings.TrimLeft(args[3], ":")
- }
- if client.nickname != "*" && client.username != "" {
- client.registered = true
- client.ReplyNicknamed("001", "Hi, welcome to IRC")
- client.ReplyNicknamed("002", "Your host is "+daemon.hostname+", running goircd")
- client.ReplyNicknamed("003", "This server was created sometime")
- client.ReplyNicknamed("004", daemon.hostname+" goircd o o")
- daemon.SendLusers(client)
- daemon.SendMotd(client)
- }
-}
-
-// Register new room in Daemon. Create an object, events sink, save pointers
-// to corresponding daemon's places and start room's processor goroutine.
-func (daemon *Daemon) RoomRegister(name string) (*Room, chan<- ClientEvent) {
- room_new := NewRoom(daemon.hostname, name, daemon.log_sink, daemon.state_sink)
- room_sink := make(chan ClientEvent)
- daemon.rooms[name] = room_new
- daemon.room_sinks[room_new] = room_sink
- go room_new.Processor(room_sink)
- return room_new, room_sink
-}
-
-func (daemon *Daemon) HandlerJoin(client *Client, cmd string) {
- args := strings.Split(cmd, " ")
- rooms := strings.Split(args[0], ",")
- var keys []string
- if len(args) > 1 {
- keys = strings.Split(args[1], ",")
- } else {
- keys = []string{}
- }
- for n, room := range rooms {
- if !RoomNameValid(room) {
- client.ReplyNoChannel(room)
- continue
- }
- var key string
- if (n < len(keys)) && (keys[n] != "") {
- key = keys[n]
- } else {
- key = ""
- }
- denied := false
- joined := false
- for room_existing, room_sink := range daemon.room_sinks {
- if room == room_existing.name {
- if (room_existing.key != "") && (room_existing.key != key) {
- denied = true
- } else {
- room_sink <- ClientEvent{client, EVENT_NEW, ""}
- joined = true
- }
- break
- }
- }
- if denied {
- client.ReplyNicknamed("475", room, "Cannot join channel (+k) - bad key")
- }
- if denied || joined {
- continue
- }
- room_new, room_sink := daemon.RoomRegister(room)
- if key != "" {
- room_new.key = key
- room_new.StateSave()
- }
- room_sink <- ClientEvent{client, EVENT_NEW, ""}
- }
-}
-
-func (daemon *Daemon) Processor(events <-chan ClientEvent) {
- for event := range events {
-
- // Check for clients aliveness
- now := time.Now()
- if daemon.last_aliveness_check.Add(ALIVENESS_CHECK).Before(now) {
- for c := range daemon.clients {
- if c.timestamp.Add(PING_TIMEOUT).Before(now) {
- log.Println(c, "ping timeout")
- c.conn.Close()