예제 #1
0
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
}
예제 #2
0
// 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(),
	}
}
예제 #3
0
파일: dummy.go 프로젝트: fcavani/gormethods
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)
}
예제 #4
0
// 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
}
예제 #5
0
// 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())
}
예제 #6
0
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
}