예제 #1
0
func (s *Server) protocol(conn InstConn) error {
	dec := conn.Decoder()
	defer func() {
		num := conn.StreamNum()
		s.lck.Lock()
		if _, found := s.connections[num]; found {
			delete(s.connections, num)
		}
		s.lck.Unlock()
		conn.Close()
		log.DebugLevel().Tag("server", "gormethods", "protocol").Println("protocol close")
	}()
	for {
		s.lck.Lock()
		connection, found := s.connections[conn.StreamNum()]
		if !found {
			connection = &Connection{}
			s.connections[conn.StreamNum()] = connection
		}
		connection.ttl = time.Now().Add(s.Ttl)
		connection.conn = conn
		s.lck.Unlock()
		var req msgtypes.MessageType
		// se fechar a conn do outro lado deve acontecer um err aqui
		err := dec.Decode(&req)
		if e.Find(err, io.EOF) >= 0 {
			return e.Forward(err)
		} else if err != nil {
			log.DebugLevel().Tag("server", "gormethods").Printf("Decode %v -> %v (%v) error: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), e.Trace(e.Forward(err)))
			return e.Forward(err)
		}
		switch req {
		case msgtypes.Call:
			err = s.protoCall(conn)
			if e.Find(err, ErrWire) >= 0 {
				return e.Forward(err)
			}
		case msgtypes.Destroy:
			err = s.protoDestroy(conn)
			if e.Find(err, ErrWire) >= 0 {
				return e.Forward(err)
			}
			return nil
		case msgtypes.Channel:
			err = s.protoChannel(conn)
			if e.Find(err, ErrWire) >= 0 {
				return e.Forward(err)
			}
			return nil
		default:
			log.ProtoLevel().Tag("server", "gormethods").Printf("Protocol fail from %v -> %v (%v) sent: %v", conn.RemoteAddr(), conn.LocalAddr(), conn.StreamNum(), req)
		}
	}
}
예제 #2
0
func TestNewClient(t *testing.T) {
	client := &Client{
		Proto:        "tcp",
		Addr:         serverTest.Address().String(),
		TlsConfig:    nil,
		SessionName:  "1",
		InstanceName: "1",
		Auth:         &auth.PlainText{"id", "pass1234"},
		DialTimeout:  time.Minute,
		NumClones:    1,
		MaxNumClones: 5,
		Sleep:        100 * time.Millisecond,
		Interval:     time.Minute,
		ConnTimeout:  30 * time.Second,
		KeepAlive:    50 * time.Millisecond,
	}
	err := client.Init()
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}

	var resp int
	err = client.Call("Add", []reflect.Value{reflect.ValueOf(40), reflect.ValueOf(2)}, []reflect.Value{reflect.ValueOf(&resp)})
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}
	if resp != 42 {
		t.Fatal("wrong resp", resp)
	}
	err = client.Call("Mul", []reflect.Value{reflect.ValueOf(2), reflect.ValueOf(2)}, []reflect.Value{reflect.ValueOf(&resp)})
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}
	if resp != 4 {
		t.Fatal("wrong resp", resp)
	}
	err = client.Call("WrongName", []reflect.Value{reflect.ValueOf(2), reflect.ValueOf(2)}, []reflect.Value{reflect.ValueOf(&resp)})
	if err != nil && e.Find(err, ErrMethodNotFound) == -1 {
		t.Fatal(e.Trace(e.Forward(err)))
	}

	err = client.Ping()
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}

	err = client.Destroy()
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}
}
예제 #3
0
func TestServerProtocolFail(t *testing.T) {
	in, err := Discover(net.FlagLoopback)
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}

	server := &Server{}
	server.Name = "master"
	server.PrivateKey = MasterKey
	server.PubKeys = Keys
	server.Interface = in
	server.AddrVer = Ipv4
	server.Protocol = func(addr *net.UDPAddr, req *Request) (resp *Response, err error) {
		if string(req.Data) != "request" {
			return nil, e.New("protocol error")
		}
		t.Log(req)
		return &Response{
			Data: []byte("msg"),
		}, nil
	}
	err = server.Do()
	if err != nil {
		t.Fatal(e.Trace(e.Forward(err)))
	}
	defer server.Close()

	client := &Client{}
	client.ServerName = "master"
	client.ServerKey = &MasterKey.PublicKey
	client.Name = "slave"
	client.PrivateKey = SlaveKey
	client.Interface = in
	client.AddrVer = Ipv4
	client.Port = server.Port
	client.Request = func(dst *net.UDPAddr) (*Request, error) {
		return &Request{
			Data: []byte("request"),
		}, nil
	}
	_, err = client.Discover()
	if err != nil && e.Find(err, "protocol fail") < 0 {
		t.Fatal(e.Trace(e.Forward(err)))
	}
}
예제 #4
0
func TestValProbeName(t *testing.T) {
	err := ValProbeName("")
	if err != nil && !e.Equal(err, text.ErrInvNumberChars) {
		t.Fatal(err)
	} else if err == nil {
		t.Fatal("nil error")
	}
	err = ValProbeName("122")
	if err != nil && !e.Equal(err, ErrFirstChar) {
		t.Fatal(err)
	} else if err == nil {
		t.Fatal("nil error")
	}
	err = ValProbeName("a_")
	if err != nil && e.Find(err, text.ErrInvCharacter) == -1 {
		t.Fatal(err)
	} else if err == nil {
		t.Fatal("nil error")
	}
	err = ValProbeName("aaaaa")
	if err != nil {
		t.Fatal(err)
	}
}
예제 #5
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
}