caller. handler's args are optional.

This commit is contained in:
Gennadii Kovalev 2016-05-22 20:04:25 +02:00
parent b811737225
commit 79023de6ce
5 changed files with 49 additions and 23 deletions

View File

@ -18,7 +18,7 @@ Examples directory contains simple client and server.
server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport()) server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())
//handle connected //handle connected
server.On(gosocketio.OnConnection, func(c *gosocketio.Channel, args interface{}) { server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
log.Println("New client connected") log.Println("New client connected")
//join them to room //join them to room
c.Join("chat") c.Join("chat")
@ -89,7 +89,9 @@ var socket = io('ws://yourdomain.com', {transports: ['websocket']});
log.Println(len(channels), "clients in room") log.Println(len(channels), "clients in room")
}) })
//on disconnection handler, if client hangs connection unexpectedly, it will still occurs //on disconnection handler, if client hangs connection unexpectedly, it will still occurs
server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel, args interface{}) { //you can omit function args if you do not need them
//you can return string value for ack, or return nothing for emit
server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
//this is not necessary, client will be removed from rooms //this is not necessary, client will be removed from rooms
//automatically on disconnect //automatically on disconnect
//but you can remove client from room whenever you need to //but you can remove client from room whenever you need to
@ -98,7 +100,7 @@ var socket = io('ws://yourdomain.com', {transports: ['websocket']});
log.Println("Disconnected") log.Println("Disconnected")
}) })
//error catching handler //error catching handler
server.On(gosocketio.OnError, func(c *gosocketio.Channel, args interface{}) { server.On(gosocketio.OnError, func(c *gosocketio.Channel) {
log.Println("Error occurs") log.Println("Error occurs")
}) })

View File

@ -8,12 +8,13 @@ import (
type caller struct { type caller struct {
Func reflect.Value Func reflect.Value
Args reflect.Type Args reflect.Type
ArgsPresent bool
Out bool Out bool
} }
var ( var (
ErrorCallerNotFunc = errors.New("f is not function") ErrorCallerNotFunc = errors.New("f is not function")
ErrorCallerNot2Args = errors.New("f should have 2 args") ErrorCallerNot2Args = errors.New("f should have 1 or 2 args")
ErrorCallerMaxOneValue = errors.New("f should return not more than one value") ErrorCallerMaxOneValue = errors.New("f should return not more than one value")
) )
@ -28,19 +29,25 @@ func newCaller(f interface{}) (*caller, error) {
} }
fType := fVal.Type() fType := fVal.Type()
if fType.NumIn() != 2 {
return nil, ErrorCallerNot2Args
}
if fType.NumOut() > 1 { if fType.NumOut() > 1 {
return nil, ErrorCallerMaxOneValue return nil, ErrorCallerMaxOneValue
} }
return &caller{ curCaller := &caller{
Func: fVal, Func: fVal,
Args: fType.In(1),
Out: fType.NumOut() == 1, Out: fType.NumOut() == 1,
}, nil }
if fType.NumIn() == 1 {
curCaller.Args = nil
curCaller.ArgsPresent = false
} else if fType.NumIn() == 2 {
curCaller.Args = fType.In(1)
curCaller.ArgsPresent = true
} else {
return nil, ErrorCallerNot2Args
}
return curCaller, nil
} }
/** /**
@ -55,6 +62,9 @@ calls function with given arguments from its representation using reflection
*/ */
func (c *caller) callFunc(h *Channel, args interface{}) []reflect.Value { func (c *caller) callFunc(h *Channel, args interface{}) []reflect.Value {
a := []reflect.Value{reflect.ValueOf(h), reflect.ValueOf(args).Elem()} a := []reflect.Value{reflect.ValueOf(h), reflect.ValueOf(args).Elem()}
if !c.ArgsPresent {
a = a[0:1]
}
return c.Func.Call(a) return c.Func.Call(a)
} }

View File

@ -45,14 +45,14 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel, args interface{}) { err = c.On(gosocketio.OnDisconnection, func(h *gosocketio.Channel) {
log.Fatal("Disconnected") log.Fatal("Disconnected")
}) })
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
err = c.On(gosocketio.OnConnection, func(h *gosocketio.Channel, args interface{}) { err = c.On(gosocketio.OnConnection, func(h *gosocketio.Channel) {
log.Println("Connected") log.Println("Connected")
}) })
if err != nil { if err != nil {

View File

@ -21,7 +21,7 @@ type Message struct {
func main() { func main() {
server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport()) server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())
server.On(gosocketio.OnConnection, func(c *gosocketio.Channel, args interface{}) { server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
log.Println("Connected") log.Println("Connected")
c.Emit("/message", Message{10, "main", "using emit"}) c.Emit("/message", Message{10, "main", "using emit"})
@ -29,12 +29,13 @@ func main() {
c.Join("test") c.Join("test")
c.BroadcastTo("test", "/message", Message{10, "main", "using broadcast"}) c.BroadcastTo("test", "/message", Message{10, "main", "using broadcast"})
}) })
server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel, args interface{}) { server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
log.Println("Disconnected") log.Println("Disconnected")
}) })
server.On("/join", func(c *gosocketio.Channel, channel Channel) string { server.On("/join", func(c *gosocketio.Channel, channel Channel) string {
time.Sleep(2 * time.Second) time.Sleep(2 * time.Second)
log.Println("Client joined to ", channel.Channel)
return "joined to " + channel.Channel return "joined to " + channel.Channel
}) })

View File

@ -4,6 +4,7 @@ import (
"encoding/json" "encoding/json"
"github.com/graarh/golang-socketio/protocol" "github.com/graarh/golang-socketio/protocol"
"sync" "sync"
"reflect"
) )
const ( const (
@ -92,6 +93,11 @@ func (m *methods) processIncomingMessage(c *Channel, msg *protocol.Message) {
return return
} }
if !f.ArgsPresent {
f.callFunc(c, &struct{}{})
return
}
data := f.getArgs() data := f.getArgs()
err := json.Unmarshal([]byte(msg.Args), &data) err := json.Unmarshal([]byte(msg.Args), &data)
if err != nil { if err != nil {
@ -106,13 +112,20 @@ func (m *methods) processIncomingMessage(c *Channel, msg *protocol.Message) {
return return
} }
var result []reflect.Value
if f.ArgsPresent {
//data type should be defined for unmarshall
data := f.getArgs() data := f.getArgs()
err := json.Unmarshal([]byte(msg.Args), &data) err := json.Unmarshal([]byte(msg.Args), &data)
if err != nil { if err != nil {
return return
} }
result := f.callFunc(c, data) result = f.callFunc(c, data)
} else {
result = f.callFunc(c, &struct{}{})
}
ack := &protocol.Message{ ack := &protocol.Message{
Type: protocol.MessageTypeAckResponse, Type: protocol.MessageTypeAckResponse,
AckId: msg.AckId, AckId: msg.AckId,