This is a fork of: https://github.com/roglew/puppy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

122 lines
2.7 KiB

8 years ago
package puppy
8 years ago
import (
"bufio"
"encoding/json"
"fmt"
"io"
"log"
"net"
"strings"
8 years ago
)
/*
Message Server
*/
8 years ago
// A handler to handle a JSON message
type MessageHandler func(message []byte, conn net.Conn, logger *log.Logger, iproxy *InterceptingProxy)
8 years ago
8 years ago
// A listener that handles reading JSON messages and sending them to the correct handler
8 years ago
type MessageListener struct {
handlers map[string]MessageHandler
iproxy *InterceptingProxy
Logger *log.Logger
8 years ago
}
type commandData struct {
Command string
}
type errorMessage struct {
Success bool
Reason string
8 years ago
}
8 years ago
// NewMessageListener creates a new message listener associated with the given intercepting proxy
8 years ago
func NewMessageListener(l *log.Logger, iproxy *InterceptingProxy) *MessageListener {
m := &MessageListener{
handlers: make(map[string]MessageHandler),
iproxy: iproxy,
Logger: l,
8 years ago
}
return m
}
8 years ago
// AddHandler will have the listener call the given handler when the "Command" parameter matches the given value
8 years ago
func (l *MessageListener) AddHandler(command string, handler MessageHandler) {
l.handlers[strings.ToLower(command)] = handler
}
func (l *MessageListener) Handle(message []byte, conn net.Conn) error {
var c commandData
if err := json.Unmarshal(message, &c); err != nil {
return fmt.Errorf("error parsing message: %s", err.Error())
}
handler, ok := l.handlers[strings.ToLower(c.Command)]
if !ok {
return fmt.Errorf("unknown command: %s", c.Command)
}
l.Logger.Printf("Calling handler for \"%s\"...", c.Command)
handler(message, conn, l.Logger, l.iproxy)
return nil
}
8 years ago
// Serve will have the listener serve messages on the given listener
8 years ago
func (l *MessageListener) Serve(nl net.Listener) {
for {
conn, err := nl.Accept()
if err != nil {
// Listener closed
break
}
reader := bufio.NewReader(conn)
go func() {
for {
m, err := ReadMessage(reader)
l.Logger.Printf("> %s\n", m)
if err != nil {
if err != io.EOF {
ErrorResponse(conn, "error reading message")
}
return
}
err = l.Handle(m, conn)
if err != nil {
ErrorResponse(conn, err.Error())
}
}
}()
}
}
8 years ago
// Error response writes an error message to the given writer
8 years ago
func ErrorResponse(w io.Writer, reason string) {
var m errorMessage
m.Success = false
m.Reason = reason
MessageResponse(w, m)
}
8 years ago
// MessageResponse writes a response to a given writer
8 years ago
func MessageResponse(w io.Writer, m interface{}) {
b, err := json.Marshal(&m)
if err != nil {
panic(err)
}
w.Write(b)
w.Write([]byte("\n"))
}
8 years ago
// ReadMessage reads a message from the given reader
8 years ago
func ReadMessage(r *bufio.Reader) ([]byte, error) {
m, err := r.ReadBytes('\n')
if err != nil {
return nil, err
}
return m, nil
}