func TestServiceProtocolProcessMessage(t *testing.T) { ds := &DummyService{ link: make(chan bool), } var count int sda.RegisterNewService("DummyService", func(c *sda.Context, path string) sda.Service { if count == 0 { count++ // the client does not need a Service return &DummyService{link: make(chan bool)} } ds.c = c ds.path = path ds.Config = DummyConfig{ Send: true, } return ds }) // fake a client h2 := sda.NewLocalHost(2010) defer h2.Close() host := sda.NewLocalHost(2000) host.ListenAndBind() host.StartProcessMessages() log.Lvl1("Host created and listening") defer host.Close() // create the entityList and tree el := sda.NewRoster([]*network.ServerIdentity{host.ServerIdentity}) tree := el.GenerateBinaryTree() // give it to the service ds.fakeTree = tree // Send a request to the service b, err := network.MarshalRegisteredType(&DummyMsg{10}) log.ErrFatal(err) re := &sda.ClientRequest{ Service: sda.ServiceFactory.ServiceID("DummyService"), Data: b, } log.Lvl1("Client connecting to host") if _, err := h2.Connect(host.ServerIdentity); err != nil { t.Fatal(err) } log.Lvl1("Sending request to service...") if err := h2.SendRaw(host.ServerIdentity, re); err != nil { t.Fatal(err) } // wait for the link from the protocol waitOrFatalValue(ds.link, true, t) // now wait for the same link as the protocol should have sent a message to // himself ! waitOrFatalValue(ds.link, true, t) }
// CreateServiceMessage takes a service name and some data and encodes the whole // as a ServiceMessage. func CreateServiceMessage(service string, r interface{}) (*InterServiceMessage, error) { sid := ServiceFactory.ServiceID(service) buff, err := network.MarshalRegisteredType(r) if err != nil { return nil, err } return &InterServiceMessage{ Service: sid, Data: buff, }, nil }
// CreateClientRequest creates a Request message out of any message that is // destined to a Service. XXX For the moment it uses protobuf, as it is already // handling abstract.Scalar/Public stuff that json can't do. Later we may want // to think on how to change that. func CreateClientRequest(service string, r interface{}) (*ClientRequest, error) { sid := ServiceFactory.ServiceID(service) log.Lvl1("Name", service, " <-> ServiceID", sid.String()) buff, err := network.MarshalRegisteredType(r) if err != nil { return nil, err } return &ClientRequest{ Service: sid, Data: buff, }, nil }
// Test if a request that makes the service create a new protocol works func TestServiceRequestNewProtocol(t *testing.T) { ds := &DummyService{ link: make(chan bool), } sda.RegisterNewService("DummyService", func(c *sda.Context, path string) sda.Service { ds.c = c ds.path = path return ds }) host := sda.NewLocalHost(2000) host.Listen() host.StartProcessMessages() log.Lvl1("Host created and listening") defer host.Close() // create the entityList and tree el := sda.NewRoster([]*network.ServerIdentity{host.ServerIdentity}) tree := el.GenerateBinaryTree() // give it to the service ds.fakeTree = tree // Send a request to the service b, err := network.MarshalRegisteredType(&DummyMsg{10}) log.ErrFatal(err) re := &sda.ClientRequest{ Service: sda.ServiceFactory.ServiceID("DummyService"), Data: b, } // fake a client h2 := sda.NewLocalHost(2010) defer h2.Close() log.Lvl1("Client connecting to host") if _, err := h2.Connect(host.ServerIdentity); err != nil { t.Fatal(err) } log.Lvl1("Sending request to service...") if err := h2.SendRaw(host.ServerIdentity, re); err != nil { t.Fatal(err) } // wait for the link from the waitOrFatalValue(ds.link, true, t) // Now RESEND the value so we instantiate using the SAME TREENODE log.Lvl1("Sending request AGAIN to service...") if err := h2.SendRaw(host.ServerIdentity, re); err != nil { t.Fatal(err) } // wait for the link from the // NOW expect false waitOrFatalValue(ds.link, false, t) }
// BinaryMarshaler does the same as Marshal func (t *Tree) BinaryMarshaler() ([]byte, error) { bt, err := t.Marshal() if err != nil { return nil, err } tbm := &tbmStruct{ T: bt, EL: t.Roster, } b, err := network.MarshalRegisteredType(tbm) if err != nil { return nil, err } return b, nil }
// SendTreeNode injects a message directly in the Overlay-layer, bypassing // Host and Network func (l *LocalTest) SendTreeNode(proto string, from, to *TreeNodeInstance, msg network.Body) error { if from.Tree().ID != to.Tree().ID { return errors.New("Can't send from one tree to another") } b, err := network.MarshalRegisteredType(msg) if err != nil { return err } sdaMsg := &ProtocolMsg{ MsgSlice: b, MsgType: network.TypeToMessageTypeID(msg), From: from.token, To: to.token, } return to.overlay.TransmitMsg(sdaMsg) }
// Save takes everything in the SimulationConfig structure and saves it to // dir + SimulationFileName func (sc *SimulationConfig) Save(dir string) error { network.RegisterMessageType(&SimulationConfigFile{}) scf := &SimulationConfigFile{ TreeMarshal: sc.Tree.MakeTreeMarshal(), Roster: sc.Roster, PrivateKeys: sc.PrivateKeys, Config: sc.Config, } buf, err := network.MarshalRegisteredType(scf) if err != nil { log.Fatal(err) } err = ioutil.WriteFile(dir+"/"+SimulationFileName, buf, 0660) if err != nil { log.Fatal(err) } return nil }
// Separate function for testing func propagateStartAndWait(pi sda.ProtocolInstance, msg network.Body, msec int, f func(network.Body)) (int, error) { d, err := network.MarshalRegisteredType(msg) if err != nil { return -1, err } protocol := pi.(*Propagate) protocol.Lock() protocol.sd.Data = d protocol.sd.Msec = msec protocol.onData = f done := make(chan int) protocol.onDoneCb = func(i int) { done <- i } protocol.Unlock() if err = protocol.Start(); err != nil { return -1, err } ret := <-done log.Lvl2("Finished propagation with", ret, "replies") return ret, nil }
func TestServiceBackForthProtocol(t *testing.T) { local := sda.NewLocalTest() defer local.CloseAll() // register service sda.RegisterNewService("BackForth", func(c *sda.Context, path string) sda.Service { return &simpleService{ ctx: c, } }) // create hosts hosts, el, _ := local.GenTree(4, true, true, false) // create client priv, pub := sda.PrivPub() client := network.NewSecureTCPHost(priv, network.NewServerIdentity(pub, "")) c, err := client.Open(hosts[0].ServerIdentity) assert.Nil(t, err) // create request r := &simpleRequest{ ServerIdentities: el, Val: 10, } buff, err := network.MarshalRegisteredType(r) assert.Nil(t, err) req := &sda.ClientRequest{ Service: sda.ServiceFactory.ServiceID("BackForth"), Data: buff, } assert.Nil(t, c.Send(context.TODO(), req)) nm, err := c.Receive(context.TODO()) assert.Nil(t, err) assert.Equal(t, nm.MsgType, simpleResponseType) resp := nm.Msg.(simpleResponse) assert.Equal(t, resp.Val, 10) }
// sendSDAData marshals the inner msg and then sends a Data msg // to the appropriate entity func (h *Host) sendSDAData(e *network.ServerIdentity, sdaMsg *ProtocolMsg) error { b, err := network.MarshalRegisteredType(sdaMsg.Msg) if err != nil { typ := network.TypeFromData(sdaMsg.Msg) rtype := reflect.TypeOf(sdaMsg.Msg) var str string if typ == network.ErrorType { str = " Non registered Type !" } else { str = typ.String() } str += " (reflect= " + rtype.String() return fmt.Errorf("Error marshaling message: %s ( msg = %+v)", err.Error(), sdaMsg.Msg) } sdaMsg.MsgSlice = b sdaMsg.MsgType = network.TypeFromData(sdaMsg.Msg) // put to nil so protobuf won't encode it and there won't be any error on the // other side (because it doesn't know how to decode it) sdaMsg.Msg = nil log.Lvl4("Sending to", e.Addresses) return h.SendRaw(e, sdaMsg) }
// Marshal creates a simple binary-representation of the tree containing only // the ids of the elements. Use NewTreeFromMarshal to get back the original // tree func (t *Tree) Marshal() ([]byte, error) { buf, err := network.MarshalRegisteredType(t.MakeTreeMarshal()) return buf, err }
// test for calling the NewProtocol method on a remote Service func TestServiceNewProtocol(t *testing.T) { ds1 := &DummyService{ link: make(chan bool), Config: DummyConfig{ Send: true, }, } ds2 := &DummyService{ link: make(chan bool), } var count int sda.RegisterNewService("DummyService", func(c *sda.Context, path string) sda.Service { var localDs *DummyService switch count { case 2: // the client does not need a Service return &DummyService{link: make(chan bool)} case 1: // children localDs = ds2 case 0: // root localDs = ds1 } localDs.c = c localDs.path = path count++ return localDs }) host := sda.NewLocalHost(2000) host.ListenAndBind() host.StartProcessMessages() log.Lvl1("Host created and listening") defer host.Close() host2 := sda.NewLocalHost(2002) host2.ListenAndBind() host2.StartProcessMessages() defer host2.Close() // create the entityList and tree el := sda.NewRoster([]*network.ServerIdentity{host.ServerIdentity, host2.ServerIdentity}) tree := el.GenerateBinaryTree() // give it to the service ds1.fakeTree = tree // Send a request to the service b, err := network.MarshalRegisteredType(&DummyMsg{10}) log.ErrFatal(err) re := &sda.ClientRequest{ Service: sda.ServiceFactory.ServiceID("DummyService"), Data: b, } // fake a client client := sda.NewLocalHost(2010) defer client.Close() log.Lvl1("Client connecting to host") if _, err := client.Connect(host.ServerIdentity); err != nil { t.Fatal(err) } log.Lvl1("Sending request to service...") if err := client.SendRaw(host.ServerIdentity, re); err != nil { t.Fatal(err) } // wait for the link from the protocol that Starts waitOrFatalValue(ds1.link, true, t) // now wait for the same link as the protocol should have sent a message to // himself ! waitOrFatalValue(ds1.link, true, t) // now wait for the SECOND LINK on the SECOND HOST that the SECOND SERVICE // should have started (ds2) in ProcessRequest waitOrFatalValue(ds2.link, true, t) }
func mkClientRequest(msg network.Body) []byte { b, err := network.MarshalRegisteredType(msg) log.ErrFatal(err) return b }