From 6681c1d64b72ce4eb1b94e71ade383f0fb06848c Mon Sep 17 00:00:00 2001 From: Kane York Date: Sat, 24 Oct 2015 21:33:55 -0700 Subject: [PATCH] Stub all command handlers on server --- socketserver/lib/commands.go | 84 +++++++++++++++++++++++++++++++++ socketserver/lib/handlecore.go | 85 ++++++++++++++++++++++++++++------ 2 files changed, 154 insertions(+), 15 deletions(-) diff --git a/socketserver/lib/commands.go b/socketserver/lib/commands.go index 55c21f80..317e1305 100644 --- a/socketserver/lib/commands.go +++ b/socketserver/lib/commands.go @@ -1 +1,85 @@ package lib +import ( + "golang.org/x/net/websocket" + "github.com/satori/go.uuid" + "log" +) + +func HandleHello(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + version, clientId, err := msg.ArgumentsAsTwoStrings() + + client.Version = version + client.ClientID = uuid.FromStringOrNil(clientId) + if client.ClientID == uuid.Nil { + client.ClientID = uuid.NewV4() + } + + return ClientMessage{ + Arguments: client.ClientID.String(), + }, nil +} + +func HandleSetUser(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleSub(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleUnsub(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleSubChannel(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleUnsubChannel(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleChatHistory(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + // Ignore, send empty history + return ClientMessage{Arguments: []string{}}, nil +} + +func HandleSurvey(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + log.Println("Ignoring survey response from", client.ClientID) + return ClientMessage{}, nil +} + +func HandleUpdateFollowButtons(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleTrackFollow(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleEmoticonUses(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleTwitchEmote(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleGetLink(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} + +func HandleGetDisplayName(conn *websocket.Conn, client *ClientInfo, msg ClientMessage) (rmsg ClientMessage, err error) { + + return ClientMessage{}, nil +} diff --git a/socketserver/lib/handlecore.go b/socketserver/lib/handlecore.go index 4f272faf..5edbb61f 100644 --- a/socketserver/lib/handlecore.go +++ b/socketserver/lib/handlecore.go @@ -62,12 +62,28 @@ type ClientInfo struct { } // A function that is called to respond to a Command. -type CommandHandler func(*websocket.Conn, *ClientInfo, ClientMessage) *ClientMessage +type CommandHandler func(*websocket.Conn, *ClientInfo, ClientMessage) (ClientMessage, error) -var CommandHandlers = make(map[Command]CommandHandler) +var CommandHandlers = map[Command]CommandHandler { + HelloCommand: HandleHello, + "get_display_name": HandleGetDisplayName, + "sub": HandleSub, + "unsub": HandleUnsub, + "chat_history": HandleChatHistory, + "sub_channel": HandleSubChannel, + "unsub_channel": HandleUnsubChannel, + "setuser": HandleSetUser, + "update_follow_buttons": HandleUpdateFollowButtons, + "track_follow": HandleTrackFollow, + "emoticon_uses": HandleEmoticonUses, + "twitch_emote": HandleTwitchEmote, + "get_link": HandleGetLink, + "survey": HandleSurvey, +} // Sent by the server in ClientMessage.Command to indicate success. const SuccessCommand Command = "True" +const HelloCommand Command = "hello" // A websocket.Codec that translates the protocol into ClientMessage objects. var FFZCodec websocket.Codec = websocket.Codec{ @@ -120,9 +136,12 @@ func SetupServerAndHandle(config *Config) { func HandleSocketConnection(conn *websocket.Conn) { // websocket.Conn is a ReadWriteCloser - closer := sync.Once(func() { - conn.Close() - }) + var _closer sync.Once + closer := func() { + _closer.Do(func() { + conn.Close() + }) + } defer func() { closer() @@ -161,24 +180,46 @@ func HandleSocketConnection(conn *websocket.Conn) { for { select { case err := <-errorChan: - FFZCodec.Send(conn, ClientMessage{ Command: "error", Arguments: err.Error() }) + // note - socket might not be open at this point + // don't care + FFZCodec.Send(conn, ClientMessage{ + MessageID: -1, + Command: "error", + Arguments: err.Error(), + }) break RunLoop - case cmsg := <-clientChan: - handler, ok := CommandHandlers[cmsg.Command] + case msg := <-clientChan: + if client.Version == "" && msg.Command != HelloCommand { + FFZCodec.Send(conn, ClientMessage{ + MessageID: msg.MessageID, + Command: "error", + Arguments: "Error - the first message sent must be a 'hello'", + }) + break RunLoop + } + + handler, ok := CommandHandlers[msg.Command] if !ok { - log.Print("[!] Unknown command", cmsg.Command, "- sent by client", client.ClientID, "@", conn.RemoteAddr()) - // TODO - after commands are implemented + log.Print("[!] Unknown command", msg.Command, "- sent by client", client.ClientID, "@", conn.RemoteAddr()) + // uncomment after commands are implemented // closer() continue } client.Mutex.Lock() - response := handler(conn, &client, cmsg) - if response != nil { - response.MessageID = cmsg.MessageID - FFZCodec.Send(conn, response) - } + response, err := CallHandler(handler, conn, &client, msg) client.Mutex.Unlock() + + if err == nil { + response.MessageID = msg.MessageID + FFZCodec.Send(conn, response) + } else { + FFZCodec.Send(conn, ClientMessage{ + MessageID: msg.MessageID, + Command: "error", + Arguments: err.Error(), + }) + } case smsg := <-serverMessageChan: FFZCodec.Send(conn, smsg) } @@ -186,6 +227,20 @@ func HandleSocketConnection(conn *websocket.Conn) { // exit } +func CallHandler(handler CommandHandler, conn *websocket.Conn, client *ClientInfo, cmsg ClientMessage) (rmsg ClientMessage, err error) { + defer func() { + if r := recover(); r != nil { + var ok bool + fmt.Print("[!] Error executing command", cmsg.Command, "--", r) + err, ok = r.(error) + if !ok { + err = fmt.Errorf("command handler: %v", r) + } + } + }() + return handler(conn, client, cmsg) +} + // Unpack a message sent from the client into a ClientMessage. func UnmarshalClientMessage(data []byte, payloadType byte, v interface{}) (err error) { var spaceIdx int