// RegisterHandler takes a function which takes a struct as argument that contains two // elements: a TreeNode and a message. It will send every message that are the // same type to this channel. // This function handles also // - registration of the message-type // - aggregation or not of messages: if you give a channel of slices, the // messages will be aggregated, else they will come one-by-one func (n *TreeNodeInstance) RegisterHandler(c interface{}) error { flags := uint32(0) cr := reflect.TypeOf(c) // Check we have the correct channel-type if cr.Kind() != reflect.Func { return errors.New("Input is not function") } cr = cr.In(0) if cr.Kind() == reflect.Slice { flags += AggregateMessages cr = cr.Elem() } if cr.Kind() != reflect.Struct { return errors.New("Input is not channel of structure") } if cr.NumField() != 2 { return errors.New("Input is not channel of structure with 2 elements") } if cr.Field(0).Type != reflect.TypeOf(&TreeNode{}) { return errors.New("Input-channel doesn't have TreeNode as element") } // Automatic registration of the message to the network library. typ := network.RegisterMessageUUID(network.RTypeToMessageTypeID( cr.Field(1).Type), cr.Field(1).Type) //typ := network.RTypeToUUID(cr.Elem().Field(1).Type) n.handlers[typ] = c n.messageTypeFlags[typ] = flags log.Lvl3("Registered handler", typ, "with flags", flags) return nil }
// RegisterChannel takes a channel with a struct that contains two // elements: a TreeNode and a message. It will send every message that are the // same type to this channel. // This function handles also // - registration of the message-type // - aggregation or not of messages: if you give a channel of slices, the // messages will be aggregated, else they will come one-by-one func (n *TreeNodeInstance) RegisterChannel(c interface{}) error { flags := uint32(0) cr := reflect.TypeOf(c) if cr.Kind() == reflect.Ptr { val := reflect.ValueOf(c).Elem() val.Set(reflect.MakeChan(val.Type(), 100)) //val.Set(reflect.MakeChan(reflect.Indirect(cr), 1)) return n.RegisterChannel(reflect.Indirect(val).Interface()) } else if reflect.ValueOf(c).IsNil() { return errors.New("Can not Register a (value) channel not initialized") } // Check we have the correct channel-type if cr.Kind() != reflect.Chan { return errors.New("Input is not channel") } if cr.Elem().Kind() == reflect.Slice { flags += AggregateMessages cr = cr.Elem() } if cr.Elem().Kind() != reflect.Struct { return errors.New("Input is not channel of structure") } if cr.Elem().NumField() != 2 { return errors.New("Input is not channel of structure with 2 elements") } if cr.Elem().Field(0).Type != reflect.TypeOf(&TreeNode{}) { return errors.New("Input-channel doesn't have TreeNode as element") } // Automatic registration of the message to the network library. typ := network.RegisterMessageUUID(network.RTypeToMessageTypeID( cr.Elem().Field(1).Type), cr.Elem().Field(1).Type) n.channels[typ] = c //typ := network.RTypeToUUID(cr.Elem().Field(1).Type) n.channels[typ] = c n.messageTypeFlags[typ] = flags log.Lvl4("Registered channel", typ, "with flags", flags) return nil }
// RegisterMessage puts a new message in the message-handler func (p *ServiceProcessor) RegisterMessage(f interface{}) error { ft := reflect.TypeOf(f) // Check we have the correct channel-type if ft.Kind() != reflect.Func { return errors.New("Input is not function") } if ft.NumIn() != 2 { return errors.New("Need two arguments: *network.ServerIdentity and *struct") } if ft.In(0) != reflect.TypeOf(&network.ServerIdentity{}) { return errors.New("First argument must be *network.ServerIdentity") } cr1 := ft.In(1) if cr1.Kind() != reflect.Ptr { return errors.New("Second argument must be a *pointer* to struct") } if cr1.Elem().Kind() != reflect.Struct { return errors.New("Second argument must be a pointer to *struct*") } if ft.NumOut() != 2 { return errors.New("Need 2 return values: network.ProtocolMessage and error") } if ft.Out(0) != reflect.TypeOf((*network.Body)(nil)).Elem() { return errors.New("Need 2 return values: *network.ProtocolMessage* and error") } if ft.Out(1) != reflect.TypeOf((*error)(nil)).Elem() { return errors.New("Need 2 return values: network.ProtocolMessage and *error*") } // Automatic registration of the message to the network library. log.Lvl4("Registering handler", cr1.String()) typ := network.RegisterMessageUUID(network.RTypeToMessageTypeID( cr1.Elem()), cr1.Elem()) p.functions[typ] = f return nil }