3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-24 21:09:30 +01:00

organize like a proper go package

This commit is contained in:
Jeremy Latt 2014-02-08 13:18:11 -08:00
parent f04dd7c5d5
commit b9cb539219
13 changed files with 57 additions and 123 deletions

2
.gitignore vendored
View File

@ -1,5 +1,3 @@
pkg pkg
bin bin
src/code.google.com/
src/github.com/
ergonomadic.db ergonomadic.db

View File

@ -1,5 +0,0 @@
#!/bin/bash
export GOPATH="$PWD"
#go get "code.google.com/p/go.crypto/bcrypt"
#go get "github.com/mattn/go-sqlite3"
go install ergonomadic genpasswd

17
ergonomadic.go Normal file
View File

@ -0,0 +1,17 @@
package main
import (
"flag"
"github.com/jlatt/ergonomadic/irc"
)
func main() {
name := flag.String("name", "localhost", "A name for the server")
listen := flag.String("listen", ":6667", "interface to listen on")
flag.BoolVar(&irc.DEBUG_NET, "dnet", false, "debug net")
flag.BoolVar(&irc.DEBUG_CLIENT, "dclient", false, "debug client")
flag.BoolVar(&irc.DEBUG_CHANNEL, "dchannel", false, "debug channel")
flag.BoolVar(&irc.DEBUG_SERVER, "dserver", false, "debug server")
flag.Parse()
irc.NewServer(*name).Listen(*listen)
}

View File

@ -4,10 +4,6 @@ import (
"log" "log"
) )
const (
DEBUG_CHANNEL = true
)
type Channel struct { type Channel struct {
commands chan<- ChannelCommand commands chan<- ChannelCommand
key string key string
@ -59,11 +55,9 @@ func (channel *Channel) receiveReplies(replies <-chan Reply) {
log.Printf("%s ← %s : %s", channel, reply.Source(), reply) log.Printf("%s ← %s : %s", channel, reply.Source(), reply)
} }
for client := range channel.members { for client := range channel.members {
if client != reply.Source() {
client.replies <- reply client.replies <- reply
} }
} }
}
} }
func (channel *Channel) IsEmpty() bool { func (channel *Channel) IsEmpty() bool {
@ -117,7 +111,6 @@ func (channel *Channel) Join(client *Client) {
channel.members[client] = true channel.members[client] = true
client.channels[channel] = true client.channels[channel] = true
reply := RplJoin(channel, client) reply := RplJoin(channel, client)
client.replies <- reply
channel.replies <- reply channel.replies <- reply
channel.GetTopic(client) channel.GetTopic(client)
channel.GetUsers(client) channel.GetUsers(client)

View File

@ -7,20 +7,10 @@ import (
"time" "time"
) )
const (
DEBUG_CLIENT = false
)
type ClientCommand interface {
Command
HandleClient(*Client)
}
type Client struct { type Client struct {
atime time.Time atime time.Time
away bool away bool
channels ChannelSet channels ChannelSet
commands chan<- ClientCommand
conn net.Conn conn net.Conn
hostname string hostname string
nick string nick string
@ -37,12 +27,10 @@ type ClientSet map[*Client]bool
func NewClient(server *Server, conn net.Conn) *Client { func NewClient(server *Server, conn net.Conn) *Client {
read := StringReadChan(conn) read := StringReadChan(conn)
write := StringWriteChan(conn) write := StringWriteChan(conn)
commands := make(chan ClientCommand)
replies := make(chan Reply) replies := make(chan Reply)
client := &Client{ client := &Client{
channels: make(ChannelSet), channels: make(ChannelSet),
commands: commands,
conn: conn, conn: conn,
hostname: LookupHostname(conn.RemoteAddr()), hostname: LookupHostname(conn.RemoteAddr()),
replies: replies, replies: replies,
@ -51,7 +39,6 @@ func NewClient(server *Server, conn net.Conn) *Client {
go client.readConn(read) go client.readConn(read)
go client.writeConn(write, replies) go client.writeConn(write, replies)
go client.receiveCommands(commands)
return client return client
} }
@ -82,15 +69,6 @@ func (c *Client) writeConn(write chan<- string, replies <-chan Reply) {
} }
} }
func (client *Client) receiveCommands(commands <-chan ClientCommand) {
for command := range commands {
if DEBUG_CLIENT {
log.Printf("%s → %s : %s", command.Client(), client, command)
}
command.HandleClient(client)
}
}
func (c *Client) Replies() chan<- Reply { func (c *Client) Replies() chan<- Reply {
return c.replies return c.replies
} }
@ -135,17 +113,9 @@ func (c *Client) Id() string {
} }
func (c *Client) String() string { func (c *Client) String() string {
return c.hostname return c.UserHost()
} }
func (c *Client) PublicId() string { func (c *Client) PublicId() string {
return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Nick(), c.server.Id()) return fmt.Sprintf("%s!%s@%s", c.Nick(), c.Nick(), c.server.Id())
} }
//
// commands
//
func (m *PrivMsgCommand) HandleClient(client *Client) {
client.replies <- RplPrivMsg(m.Client(), client, m.message)
}

View File

@ -1,7 +1,14 @@
package irc package irc
var (
DEBUG_NET = false
DEBUG_CLIENT = false
DEBUG_CHANNEL = false
DEBUG_SERVER = false
)
const ( const (
VERSION = "ergonomadic-1" VERSION = "irc-1"
) )
const ( const (

View File

@ -7,10 +7,6 @@ import (
"strings" "strings"
) )
const (
DEBUG_NET = false
)
func readTrimmedLine(reader *bufio.Reader) (string, error) { func readTrimmedLine(reader *bufio.Reader) (string, error) {
line, err := reader.ReadString('\n') line, err := reader.ReadString('\n')
if err != nil { if err != nil {

View File

@ -115,20 +115,27 @@ func (reply *NamesReply) Format(client *Client, write chan<- string) {
tooLong := func(names []string) bool { tooLong := func(names []string) bool {
return (baseLen + joinedLen(names)) > MAX_REPLY_LEN return (baseLen + joinedLen(names)) > MAX_REPLY_LEN
} }
var start = 0 from, to := 0, 1
nicks := reply.channel.Nicks() nicks := reply.channel.Nicks()
for i := range nicks { for to < len(nicks) {
if (i > start) && tooLong(nicks[start:i]) { if (from < (to - 1)) && tooLong(nicks[from:to]) {
RplNamReply(reply.channel, nicks[start:i-1]).Format(client, write) RplNamReply(reply.channel, nicks[from:to-1]).Format(client, write)
start = i - 1 from, to = to-1, to
} else {
to += 1
} }
} }
if start < (len(nicks) - 1) { if from < len(nicks) {
RplNamReply(reply.channel, nicks[start:]).Format(client, write) RplNamReply(reply.channel, nicks[from:]).Format(client, write)
} }
RplEndOfNames(reply.channel).Format(client, write) RplEndOfNames(reply.channel).Format(client, write)
} }
func (reply *NamesReply) String() string {
return fmt.Sprintf("NamesReply(channel=%s, names=%s)",
reply.channel, reply.channel.Nicks())
}
// messaging replies // messaging replies
func RplPrivMsg(source Identifier, target Identifier, message string) Reply { func RplPrivMsg(source Identifier, target Identifier, message string) Reply {
@ -209,9 +216,9 @@ func RplNamReply(channel *Channel, names []string) *NumericReply {
channel.name, strings.Join(names, " ")) channel.name, strings.Join(names, " "))
} }
func RplEndOfNames(source Identifier) Reply { func RplEndOfNames(channel *Channel) Reply {
return NewNumericReply(source, RPL_ENDOFNAMES, return NewNumericReply(channel, RPL_ENDOFNAMES,
":End of NAMES list") "%s :End of NAMES list", channel.name)
} }
func RplYoureOper(server *Server) Reply { func RplYoureOper(server *Server) Reply {

View File

@ -1,16 +1,11 @@
package irc package irc
import ( import (
"code.google.com/p/go.crypto/bcrypt"
"log" "log"
"net" "net"
"time" "time"
) )
const (
DEBUG_SERVER = true
)
type ChannelNameMap map[string]*Channel type ChannelNameMap map[string]*Channel
type ClientNameMap map[string]*Client type ClientNameMap map[string]*Client
@ -20,7 +15,7 @@ type Server struct {
ctime time.Time ctime time.Time
hostname string hostname string
name string name string
password []byte password string
clients ClientNameMap clients ClientNameMap
} }
@ -54,7 +49,9 @@ func (s *Server) Listen(addr string) {
} }
s.hostname = LookupHostname(listener.Addr()) s.hostname = LookupHostname(listener.Addr())
if DEBUG_SERVER {
log.Print("Server.Listen: listening on ", addr) log.Print("Server.Listen: listening on ", addr)
}
for { for {
conn, err := listener.Accept() conn, err := listener.Accept()
@ -62,7 +59,9 @@ func (s *Server) Listen(addr string) {
log.Print("Server.Listen: ", err) log.Print("Server.Listen: ", err)
continue continue
} }
if DEBUG_SERVER {
log.Print("Server.Listen: accepted ", conn.RemoteAddr()) log.Print("Server.Listen: accepted ", conn.RemoteAddr())
}
NewClient(s, conn) NewClient(s, conn)
} }
} }
@ -94,7 +93,7 @@ func (s *Server) interestedClients(fromClient *Client) ClientSet {
// server functionality // server functionality
func (s *Server) tryRegister(c *Client) { func (s *Server) tryRegister(c *Client) {
if !c.registered && c.HasNick() && c.HasUsername() && s.CheckPassword(c) { if !c.registered && c.HasNick() && c.HasUsername() && c.serverPass {
c.registered = true c.registered = true
replies := []Reply{ replies := []Reply{
RplWelcome(s, c), RplWelcome(s, c),
@ -108,10 +107,6 @@ func (s *Server) tryRegister(c *Client) {
} }
} }
func (s *Server) CheckPassword(c *Client) bool {
return (s.password == nil) || c.serverPass
}
func (s *Server) Id() string { func (s *Server) Id() string {
return s.name return s.name
} }
@ -149,9 +144,9 @@ func (m *PongCommand) HandleServer(s *Server) {
} }
func (m *PassCommand) HandleServer(s *Server) { func (m *PassCommand) HandleServer(s *Server) {
err := bcrypt.CompareHashAndPassword(s.password, []byte(m.password)) if s.password != m.password {
if err != nil {
m.Client().Replies() <- ErrPasswdMismatch(s) m.Client().Replies() <- ErrPasswdMismatch(s)
// TODO disconnect
return return
} }
@ -199,13 +194,14 @@ func (m *QuitCommand) HandleServer(s *Server) {
for client := range s.interestedClients(c) { for client := range s.interestedClients(c) {
client.replies <- reply client.replies <- reply
} }
c.conn.Close()
cmd := &PartCommand{ cmd := &PartCommand{
BaseCommand: BaseCommand{c}, BaseCommand: BaseCommand{c},
} }
for channel := range c.channels { for channel := range c.channels {
channel.commands <- cmd channel.commands <- cmd
} }
c.conn.Close()
delete(s.clients, c.nick)
} }
func (m *JoinCommand) HandleServer(s *Server) { func (m *JoinCommand) HandleServer(s *Server) {
@ -266,8 +262,7 @@ func (m *PrivMsgCommand) HandleServer(s *Server) {
m.Client().replies <- ErrNoSuchNick(s, m.target) m.Client().replies <- ErrNoSuchNick(s, m.target)
return return
} }
target.replies <- RplPrivMsg(m.Client(), target, m.message)
target.commands <- m
} }
func (m *ModeCommand) HandleServer(s *Server) { func (m *ModeCommand) HandleServer(s *Server) {

View File

@ -1,13 +0,0 @@
package main
import (
"flag"
"irc"
)
func main() {
name := flag.String("name", "localhost", "A name for the server")
listen := flag.String("listen", ":6667", "interface to listen on")
flag.Parse()
irc.NewServer(*name).Listen(*listen)
}

View File

@ -1,13 +0,0 @@
package main
import (
"flag"
"irc"
)
func main() {
flag.Parse()
db := irc.NewDatabase()
defer db.Close()
irc.ExecSqlFile(db, flag.Arg(0)+".sql")
}

View File

@ -1,18 +0,0 @@
package main
import (
"code.google.com/p/go.crypto/bcrypt"
"encoding/base64"
"flag"
"fmt"
)
func main() {
flag.Parse()
password := flag.Arg(0)
hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
panic(err)
}
fmt.Println(base64.StdEncoding.EncodeToString(hash))
}