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) } } }
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))) } }
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))) } }
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) } }
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 }