Add the handler program call

This commit is contained in:
Neale Pickett 2016-01-18 18:09:29 -07:00
parent 53d8d003b4
commit b3a222ba88
4 changed files with 111 additions and 57 deletions

View File

@ -3,10 +3,10 @@ package main
import ( import (
"strconv" "strconv"
"strings" "strings"
"fmt"
) )
type Message struct { type Message struct {
Unparsed string
Command string Command string
FullSender string FullSender string
Sender string Sender string
@ -20,6 +20,7 @@ func NewMessage(v string) (Message, error) {
var parts []string var parts []string
var lhs string var lhs string
m.Unparsed = v
parts = strings.SplitN(v, " :", 2) parts = strings.SplitN(v, " :", 2)
if len(parts) == 2 { if len(parts) == 2 {
lhs = parts[0] lhs = parts[0]
@ -98,11 +99,9 @@ func NewMessage(v string) (Message, error) {
} }
func (m Message) String() string { func (m Message) String() string {
args := strings.Join(m.Args, " ") return m.Unparsed
return fmt.Sprintf("%s %s %s %s %s :%s", m.FullSender, m.Command, m.Sender, m.Forum, args, m.Text)
} }
func SplitTarget(s string) (string, string, string) { func SplitTarget(s string) (string, string, string) {
var parts []string var parts []string
@ -130,4 +129,3 @@ func IsChannel(s string) bool {
return false return false
} }
} }

View File

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"os" "os"
"log"
"path" "path"
"time" "time"
) )
@ -13,19 +14,56 @@ type Logfile struct {
name string name string
nlines int nlines int
maxlines int maxlines int
outq chan string
}
func timestamp(s string) string {
ret := fmt.Sprintf("%d %s", time.Now().Unix(), s)
return ret
} }
func NewLogfile(baseDir string, maxlines int) (*Logfile) { func NewLogfile(baseDir string, maxlines int) (*Logfile) {
return &Logfile{baseDir, nil, "", 0, maxlines} lf := Logfile{baseDir, nil, "", 0, maxlines, make(chan string, 50)}
go lf.processQueue();
return &lf
} }
func (lf *Logfile) Close() { func (lf *Logfile) Close() {
if lf.file != nil { if lf.file != nil {
lf.writeln("EXIT") lf.Log("EXIT")
lf.file.Close() close(lf.outq)
} }
} }
func (lf *Logfile) Log(s string) error {
lf.outq <- timestamp(s)
return nil
}
//
//
func (lf *Logfile) processQueue() {
for line := range lf.outq {
if (lf.file == nil) || (lf.nlines >= lf.maxlines) {
if err := lf.rotate(); err != nil {
// Just keep trying, I guess.
log.Print(err)
continue
}
lf.nlines = 0
}
if _, err := fmt.Fprintln(lf.file, line); err != nil {
log.Print(err)
continue
}
lf.nlines += 1
}
lf.file.Close()
}
func (lf *Logfile) writeln(s string) error { func (lf *Logfile) writeln(s string) error {
_, err := fmt.Fprintf(lf.file, "%d %s\n", time.Now().Unix(), s) _, err := fmt.Fprintf(lf.file, "%d %s\n", time.Now().Unix(), s)
if err == nil { if err == nil {
@ -52,8 +90,8 @@ func (lf *Logfile) rotate() error {
if lf.file != nil { if lf.file != nil {
// Note location of new log // Note location of new log
logmsg := fmt.Sprintf(". NEXTLOG %s", fn) logmsg := fmt.Sprintf("NEXTLOG %s", fn)
lf.writeln(logmsg) lf.writeln(timestamp(logmsg))
// All done with the current log // All done with the current log
lf.file.Close() lf.file.Close()
@ -66,27 +104,10 @@ func (lf *Logfile) rotate() error {
os.Remove(currentPath) os.Remove(currentPath)
os.Symlink(fn, currentPath) os.Symlink(fn, currentPath)
logmsg := fmt.Sprintf(". PREVLOG %s", lf.name) logmsg := fmt.Sprintf("PREVLOG %s", lf.name)
lf.writeln(logmsg) lf.writeln(timestamp(logmsg))
lf.name = fn lf.name = fn
return nil return nil
} }
func (lf *Logfile) Log(s string) error {
if lf.file == nil {
lf.rotate()
}
err := lf.writeln(s)
if err == nil {
return err
}
if lf.nlines >= lf.maxlines {
return lf.rotate()
}
return nil
}

View File

@ -9,6 +9,7 @@ import (
"net" "net"
"os" "os"
"os/user" "os/user"
"os/exec"
"path" "path"
"strings" "strings"
"time" "time"
@ -48,7 +49,9 @@ type Network struct {
serverIndex int serverIndex int
conn io.ReadWriteCloser conn io.ReadWriteCloser
logq chan Message
logf *Logfile
inq chan string inq chan string
outq chan string outq chan string
} }
@ -57,23 +60,21 @@ func NewNetwork(basePath string) *Network {
nw := Network{ nw := Network{
running: true, running: true,
basePath: basePath, basePath: basePath,
logq: make(chan Message, 20),
} }
nw.logf = NewLogfile(nw.basePath, int(maxlogsize))
go nw.LogLoop()
return &nw return &nw
} }
func (nw *Network) Close() { func (nw *Network) Close() {
nw.running = false nw.running = false
close(nw.logq)
if nw.conn != nil { if nw.conn != nil {
nw.conn.Close() nw.conn.Close()
} }
nw.logf.Close()
} }
func (nw *Network) WatchOutqDirectory() { func (nw *Network) watchOutqDirectory() {
outqDirname := path.Join(nw.basePath, "outq") outqDirname := path.Join(nw.basePath, "outq")
dir, err := os.Open(outqDirname) dir, err := os.Open(outqDirname)
@ -113,20 +114,12 @@ func (nw *Network) HandleInfile(fn string) {
} }
} }
func (nw *Network) LogLoop() { func (nw *Network) serverWriteLoop() {
logf := NewLogfile(nw.basePath, int(maxlogsize))
defer logf.Close()
for m := range nw.logq {
logf.Log(m.String())
}
}
func (nw *Network) ServerWriteLoop() {
for v := range nw.outq { for v := range nw.outq {
m, _ := NewMessage(v) debug("» %s", v)
nw.logq <- m nw.logf.Log(v)
fmt.Fprintln(nw.conn, v) fmt.Fprintln(nw.conn, v)
time.Sleep(500 * time.Millisecond)
} }
} }
@ -163,21 +156,21 @@ func (nw *Network) JoinChannels() {
} }
for _, ch := range chans { for _, ch := range chans {
debug("Joining %s", ch)
nw.outq <- "JOIN " + ch nw.outq <- "JOIN " + ch
} }
} }
func (nw *Network) MessageDispatch() { func (nw *Network) messageDispatchLoop() {
for line := range nw.inq { for line := range nw.inq {
nw.logf.Log(line)
m, err := NewMessage(line) m, err := NewMessage(line)
if err != nil { if err != nil {
log.Print(err) log.Print(err)
continue continue
} }
nw.logq <- m
// XXX: Add in a handler subprocess call
switch m.Command { switch m.Command {
case "PING": case "PING":
nw.outq <- "PONG :" + m.Text nw.outq <- "PONG :" + m.Text
@ -186,6 +179,30 @@ func (nw *Network) MessageDispatch() {
case "433": case "433":
nw.NextNick() nw.NextNick()
} }
handlerPath := path.Join(nw.basePath, "handler")
cmd := exec.Command(handlerPath, m.Args...)
cmd.Env = []string{
"command=" + m.Command,
"fullsender=" + m.FullSender,
"sender=" + m.Sender,
"forum=" + m.Forum,
"text=" + m.Text,
"raw=" + line,
}
cmd.Stderr = os.Stderr
out, err := cmd.Output()
if err != nil {
log.Print(err)
continue
}
if len(out) > 0 {
outlines := strings.Split(string(out), "\n")
for _, line := range outlines {
nw.outq <- line
}
}
} }
} }
@ -201,6 +218,7 @@ func (nw *Network) ConnectToNextServer() bool {
} }
server := servers[nw.serverIndex] server := servers[nw.serverIndex]
debug("Connecting to %s", server)
switch (server[0]) { switch (server[0]) {
case '|': case '|':
parts := strings.Split(server[1:], " ") parts := strings.Split(server[1:], " ")
@ -219,6 +237,7 @@ func (nw *Network) ConnectToNextServer() bool {
log.Print(err) log.Print(err)
return false return false
} }
debug("Connected")
return true return true
} }
@ -246,8 +265,15 @@ func (nw *Network) login() {
nw.NextNick() nw.NextNick()
} }
func (nw *Network) keepaliveLoop() {
for nw.running {
time.Sleep(1 * time.Minute)
nw.outq <- "PING :keepalive"
}
}
func (nw *Network) Connect(){
func (nw *Network) Connect() {
for nw.running { for nw.running {
if ! nw.ConnectToNextServer() { if ! nw.ConnectToNextServer() {
time.Sleep(8 * time.Second) time.Sleep(8 * time.Second)
@ -257,9 +283,10 @@ func (nw *Network) Connect(){
nw.inq = make(chan string, 20) nw.inq = make(chan string, 20)
nw.outq = make(chan string, 20) nw.outq = make(chan string, 20)
go nw.ServerWriteLoop() go nw.serverWriteLoop()
go nw.MessageDispatch() go nw.messageDispatchLoop()
go nw.WatchOutqDirectory() go nw.watchOutqDirectory()
go nw.keepaliveLoop()
nw.login() nw.login()

View File

@ -11,8 +11,15 @@ import (
) )
var running bool = true var running bool = true
var verbose bool = false
var maxlogsize uint var maxlogsize uint
func debug(format string, a ...interface{}) {
if verbose {
log.Printf(format, a...)
}
}
func exists(filename string) bool { func exists(filename string) bool {
_, err := os.Stat(filename); if err != nil { _, err := os.Stat(filename); if err != nil {
return false return false
@ -78,8 +85,9 @@ func usage() {
func main() { func main() {
flag.Usage = usage flag.Usage = usage
flag.UintVar(&maxlogsize, "logsize", 1000, "Log entries before rotating") flag.UintVar(&maxlogsize, "logsize", 6000, "Log entries before rotating")
notime := flag.Bool("notime", false, "Don't timestamp log messages") flag.BoolVar(&verbose, "verbose", false, "Verbose logging")
notime := flag.Bool("notime", false, "Don't timestamp debugging messages")
flag.Parse() flag.Parse()
if flag.NArg() != 1 { if flag.NArg() != 1 {
usage() usage()