package server import ( "fmt" "log" "net" "time" "go.rctt.net/solec/core" ) func (s *Server) SendBroadcast(msg string) { payload := core.Message{ Source: "op@example.org", Target: "*@example.org", Timestamp: time.Now(), Content: msg, } data, err := core.Encode(payload) if err != nil { panic(err) } for _, u := range s.users { for c := range u.Conns { if _, err := c.Write(data); err != nil { log.Println("cannot send", err) } } } } func (s *Server) handleMessage(sender net.Conn, connType core.ConnType, msg core.Message) error { if connType == core.ConnTypeUser { msg.Timestamp = time.Now() } log.Println("message:", msg.Source, "->", msg.Target, msg.Content) addr, err := core.ReadAddr(msg.Target) if err != nil { return err } if err := s.Storage.Write(msg); err != nil { log.Println("cannot write to database", err) } if addr.Host == s.name { return s.handleLocalMessage(sender, addr, msg) } return s.handleOutboundMessage(sender, addr, msg) } func (s *Server) handleLocalMessage(sender net.Conn, addr core.Addr, msg core.Message) error { if addr.Type == core.AddrUser { s.usersMu.RLock() user, ok := s.users[addr.Channel] if !ok { return core.Send(sender, core.Error{core.ErrorNotFound}) } s.usersMu.RUnlock() return user.Send(sender, msg) } s.channelsMu.RLock() channel, ok := s.channels[addr.Channel] if !ok { return core.Send(sender, core.Error{core.ErrorNotFound}) } s.channelsMu.RUnlock() channel.Send(sender, msg) return nil } func (s *Server) handleOutboundMessage(sender net.Conn, addr core.Addr, msg core.Message) error { remote, err := s.getRemote(addr.Host) if err != nil { return fmt.Errorf("cannot access remote server: %w", err) } return core.Send(remote.Conn, msg) }