func Multi(channels interface{}) (*multi, error) { m := new(multi) m.me = make(MultiEncodeGob) val := reflect.ValueOf(channels) cases := make([]reflect.SelectCase, val.Len()) for i := 0; i < val.Len(); i++ { v := val.Index(i) cases[i] = reflect.SelectCase{ Dir: reflect.SelectRecv, Chan: v, } } go func() { for { _, recv, recvOk := reflect.Select(cases) if recvOk { m.lck.Lock() if len(m.me) == 0 { m.lck.Unlock() continue } name := types.NameOf(recv.Type()) if recv.Kind() == reflect.Interface { recv = recv.Elem() name = types.NameOf(recv.Type()) } err := m.me.Encode(name) if err != nil { m.lck.Unlock() log.Println("Multi failed, can't encode:", e.Trace(err)) continue } err = m.me.EncodeValue(recv) if err != nil { m.lck.Unlock() log.Println("Multi failed, can't encode:", e.Trace(err)) continue } m.lck.Unlock() } } }() return m, nil }
// NewChannelDescriptor creates a ChannelDescriptor for the channel in the // parameter func NewChannelDescriptor(val reflect.Value) *ChannelDescriptor { t := val.Type() return &ChannelDescriptor{ Dir: t.ChanDir(), TypeName: types.NameOf(t.Elem()), Size: val.Cap(), } }
func (t *Time) EncodeMsgpack(enc *msgpack.Encoder) error { val := reflect.ValueOf(t.t) if !val.IsValid() { err := enc.Encode(stNotIsValid) if err != nil { return err } return nil } err := enc.Encode(stIsValid) if err != nil { return err } err = enc.Encode(types.NameOf(val.Elem().Type())) if err != nil { return err } return enc.EncodeValue(val) }
// MsgPackEncode encode a reflect.Value value in enc. func MsgPackEncode(enc *msgpack.Encoder, arg reflect.Value) error { var err error if arg.Kind() == reflect.Func { err = enc.Encode(Func) if err != nil { return e.Forward(err) } return nil } if !arg.IsValid() { err = enc.Encode(NotValid) if err != nil { return e.Forward(err) } return nil } err = enc.Encode(Valid) if err != nil { return e.Forward(err) } if (arg.Kind() == reflect.Interface || arg.Kind() == reflect.Map || arg.Kind() == reflect.Ptr || arg.Kind() == reflect.Slice) && arg.IsNil() { err = enc.Encode(ArgNil) if err != nil { return e.Forward(err) } t, err := TypeOf(arg) // Hum, arg.IsValid(). Why not? if err != nil { err = enc.Encode(ZeroArg) if err != nil { return e.Forward(err) } return nil } err = enc.Encode(NoZeroArg) if err != nil { return e.Forward(err) } err = enc.Encode(types.NameOf(t)) if err != nil { return e.Forward(err) } return nil } err = enc.Encode(NotNil) if err != nil { return e.Forward(err) } if zero.IsZero(arg) { err = enc.Encode(ZeroArg) if err != nil { return e.Forward(err) } err = enc.Encode(NameOf(arg)) if err != nil { return e.Forward(err) } return nil } err = enc.Encode(NoZeroArg) if err != nil { return e.Forward(err) } switch v := arg.Interface().(type) { case *e.Error: err := enc.Encode(ArgNormal) if err != nil { return e.Forward(err) } err = enc.Encode(NameOf(arg)) if err != nil { return e.Forward(err) } err = enc.EncodeValue(Strip(arg)) if err != nil { return e.Forward(err) } case error: err := enc.Encode(ArgError) if err != nil { return e.Forward(err) } err = enc.Encode(v.Error()) if err != nil { return e.Forward(err) } default: err := enc.Encode(ArgNormal) if err != nil { return e.Forward(err) } err = enc.Encode(NameOf(arg)) if err != nil { return e.Forward(err) } err = enc.EncodeValue(Strip(arg)) if err != nil { return e.Forward(err) } } return nil }
// NameOf return the value types' string name. func NameOf(val reflect.Value) string { if val.Kind() == reflect.Interface { return types.NameOf(val.Elem().Type()) } return types.NameOf(val.Type()) }
func (s *Server) protoCall(conn InstConn) (err error) { enc := conn.Encoder() dec := conn.Decoder() defer func() { if err != nil { err = enc.Encode(&respCall{Err: err}) if err != nil { log.ProtoLevel().Tag("server", "gormethods").Printf("Encode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), err) err = e.Push(err, ErrWire) } } }() inst, err := s.Insts.Get(conn.SessionName(), conn.InstanceName()) if err != nil { log.Tag("server", "gormethods").Errorf("Error getting the instance %v/%v: %v", conn.SessionName(), conn.InstanceName(), e.Forward(err)) err = e.Forward(err) return } if inst.Type() != WithValue { log.Tag("server", "gormethods").Errorf("Instance %v/%v is of wrong type", conn.SessionName(), conn.InstanceName()) return e.New("instance is of wrong type") } log.ProtoLevel().Tag("gormethods", "server", "call").Printf("Call %v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type())) var req reqCall err = dec.Decode(&req) if e.Find(err, io.EOF) >= 0 { return e.Push(err, ErrWire) } else if err != nil { log.ProtoLevel().Tag("server", "gormethods").Printf("Decode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), err) err = e.Push(err, ErrWire) return } // Tratar argumentos (req.Args) com channel // criar channel // recebe do channel envia pelo conn // recebe do conn envia para channel // (faz isso até fechar o channel em um dos lados) // substutui em req.Args os channels // Se existem channels enviar instancias err = s.mkChServer(conn, req.Args, enc) if err != nil { err = e.Forward(err) log.Tag("server", "gormethods").Errorf("Channel arguments setup failed: %v", err) return } method := inst.Instance().MethodByName(req.Method) if !method.IsValid() { err = e.Push(e.New(ErrMethodNotFound), e.New("method %v not found", req.Method)) log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } log.ProtoLevel().Tag("server", "gormethods").Printf("Call %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) var retvals []reflect.Value if method.Type().IsVariadic() { retvals = method.CallSlice(req.Args) } else { retvals = method.Call(req.Args) } log.ProtoLevel().Tag("server", "gormethods").Printf("Call returned %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) for i := range retvals { var exp *Export exp, err = s.Insts.ExportGet(conn.SessionName(), conn.InstanceName(), req.Method, i) if err != nil { continue } var instname string instname, err = rand.Chars(16, rand.NumberLetters, "go") if err != nil { err = e.Push(err, "can't create the instance name for exported retval") log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } owners := auth.NewPlainTextCredentials() err = owners.Add(conn.Auth()) if err != nil { err = e.Push(err, "can't authorize the exported retval") log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } err = s.Insts.New(conn.SessionName(), instname, retvals[i], owners) if err != nil { err = e.Push(err, "can't crete the instance for the exported retval") log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), instname, err) return } for _, to := range exp.ToExport { err = s.Insts.Export(conn.SessionName(), instname, to) if err != nil { err = e.Push(err, e.New("can't export %v/%v %v %v %v to %v", conn.SessionName(), instname, to.Method, to.RetvalPos, types.Name(retvals[i].Interface()), types.Name(exp.Client))) log.Tag("server", "gormethods").Errorf("Error in call %v/%v: %v", conn.SessionName(), conn.InstanceName(), err) return } } exp.Client.Associate(conn.SessionName(), instname, conn.Auth()) retvals[i] = reflect.ValueOf(exp.Client) continue } log.ProtoLevel().Tag("server", "gormethods").Printf("Send returned values %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) err = enc.Encode(&respCall{ Vals: retvals, Err: nil, }) if err != nil { log.ProtoLevel().Tag("server", "gormethods").Printf("Encode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), err) err = e.Push(err, ErrWire) return } log.ProtoLevel().Tag("server", "gormethods").Printf("Send returned values done %v/%v %v %v", conn.SessionName(), conn.InstanceName(), types.NameOf(inst.Instance().Type()), req.Method) return }