// SendRaw sends to an ServerIdentity without wrapping the msg into a SDAMessage func (h *Host) SendRaw(e *network.ServerIdentity, msg network.Body) error { if msg == nil { return errors.New("Can't send nil-packet") } h.networkLock.RLock() c, ok := h.connections[e.ID] h.networkLock.RUnlock() if !ok { var err error c, err = h.Connect(e) if err != nil { return err } } log.Lvlf4("%s sends to %s msg: %+v", h.ServerIdentity.Addresses, e, msg) var err error err = c.Send(context.TODO(), msg) if err != nil /*&& err != network.ErrClosed*/ { log.Lvl2("Couldn't send to", c.ServerIdentity().First(), ":", err, "trying again") c, err = h.Connect(e) if err != nil { return err } err = c.Send(context.TODO(), msg) if err != nil { return err } } log.Lvl5("Message sent") return nil }
// TypeToMessageTypeID converts a ProtocolMessage to a MessageTypeID func TypeToMessageTypeID(msg Body) MessageTypeID { val := reflect.ValueOf(msg) if val.Kind() == reflect.Ptr { val = val.Elem() } url := NamespaceProtocolMessageType + val.Type().String() u := uuid.NewV5(uuid.NamespaceURL, url) log.Lvl5("Reflecting", reflect.TypeOf(msg), "to", u) return MessageTypeID(u) }
func (h *Host) processRequest(e *network.ServerIdentity, r *ClientRequest) { // check if the target service is indeed existing s, ok := h.serviceStore.serviceByID(r.Service) if !ok { log.Error("Received a request for an unknown service", r.Service) // XXX TODO should reply with some generic response => // 404 Service Unknown return } log.Lvl5("host", h.Address(), " => Dispatch request to Request") go s.ProcessClientRequest(e, r) }
func (h *Host) processServiceMessage(e *network.ServerIdentity, m *InterServiceMessage) { // check if the target service is indeed existing s, ok := h.serviceStore.serviceByID(m.Service) if !ok { log.Error("Received a message for an unknown service", m.Service) // XXX TODO should reply with some generic response => // 404 Service Unknown return } log.Lvl5("host", h.Address(), m) go s.ProcessServiceMessage(e, m) }
// Handle a connection => giving messages to the MsgChans func (h *Host) handleConn(c network.SecureConn) { address := c.Remote() for { ctx := context.TODO() am, err := c.Receive(ctx) // This is for testing purposes only: if the connection is missing // in the map, we just return silently h.networkLock.Lock() _, cont := h.connections[c.ServerIdentity().ID] h.networkLock.Unlock() if !cont { log.Lvl3(h.workingAddress, "Quitting handleConn ", c.Remote(), " because entry is not there") return } // So the receiver can know about the error am.SetError(err) am.From = address log.Lvl5("Got message", am) if err != nil { h.closingMut.Lock() log.Lvlf4("%+v got error (%+s) while receiving message (isClosing=%+v)", h.ServerIdentity.First(), err, h.isClosing) h.closingMut.Unlock() if err == network.ErrClosed || err == network.ErrEOF || err == network.ErrTemp { log.Lvl4(h.ServerIdentity.First(), c.Remote(), "quitting handleConn for-loop", err) h.closeConnection(c) return } log.Error(h.ServerIdentity.Addresses, "Error with connection", address, "=>", err) } else { h.closingMut.Lock() if !h.isClosing { h.networkChan <- am } h.closingMut.Unlock() } } }
func (h *Host) Receive() network.Packet { data := <-h.networkChan log.Lvl5("Got message", data) return data }
// There seems to be an error if a lot of hosts communicate with each other // - this function tries to trigger that error so that it can be removed // It generates one connection between each host and then starts sending // messages all around. func TestHugeConnections(t *testing.T) { defer log.AfterTest(t) // How many hosts are run nbrHosts := 10 // 16MB of message size msgSize := 1024 * 1024 * 1 big := bigMessage{ Msize: msgSize, Msg: make([]byte, msgSize), Pcrc: 25, } bigMessageType := RegisterMessageType(big) log.TestOutput(testing.Verbose(), 3) privkeys := make([]abstract.Scalar, nbrHosts) ids := make([]*ServerIdentity, nbrHosts) hosts := make([]SecureHost, nbrHosts) // 2-dimensional array of connections between all hosts, where only // the upper-right half is populated. The lower-left half is the // mirror of the upper-right half, and the diagonal is empty, as there // are no connections from one host to itself. conns := make([][]SecureConn, nbrHosts) wg := sync.WaitGroup{} // Create all hosts and open the connections for i := 0; i < nbrHosts; i++ { privkeys[i], ids[i] = genServerIdentity("localhost:" + strconv.Itoa(2000+i)) hosts[i] = NewSecureTCPHost(privkeys[i], ids[i]) log.Lvl5("Host is", hosts[i], "id is", ids[i]) go func(h int) { err := hosts[h].Listen(func(c SecureConn) { log.Lvl5(2000+h, "got a connection") nm, err := c.Receive(context.TODO()) if err != nil { t.Fatal("Couldn't receive msg:", err) } if nm.MsgType != bigMessageType { t.Fatal("Received message type is wrong") } big_copy := nm.Msg.(bigMessage) if big_copy.Msize != msgSize { t.Fatal(h, "Message-size is wrong:", big_copy.Msize, big_copy, big) } if big_copy.Pcrc != 25 { t.Fatal("CRC is wrong") } // And send it back log.Lvl3(h, "sends it back") go func(h int) { log.Lvl3(h, "Sending back") err := c.Send(context.TODO(), &big) if err != nil { t.Fatal(h, "couldn't send message:", err) } }(h) log.Lvl3(h, "done sending messages") }) if err != nil { t.Fatal(err) } }(i) conns[i] = make([]SecureConn, nbrHosts) for j := 0; j < i; j++ { wg.Add(1) var err error log.Lvl5("Connecting", ids[i], "with", ids[j]) conns[i][j], err = hosts[i].Open(ids[j]) if err != nil { t.Fatal("Couldn't open:", err) } // Populate also the lower left for easy sending to // everybody conns[j][i] = conns[i][j] } } // Start sending messages back and forth for i := 0; i < nbrHosts; i++ { for j := 0; j < i; j++ { c := conns[i][j] go func(conn SecureConn, i, j int) { defer wg.Done() log.Lvl3("Sending from", i, "to", j, ":") ctx := context.TODO() if err := conn.Send(ctx, &big); err != nil { t.Fatal(i, j, "Couldn't send:", err) } nm, err := conn.Receive(context.TODO()) if err != nil { t.Fatal(i, j, "Couldn't receive:", err) } bc := nm.Msg.(bigMessage) if bc.Msize != msgSize { t.Fatal(i, j, "Message-size is wrong") } if bc.Pcrc != 25 { t.Fatal(i, j, "CRC is wrong") } log.Lvl3(i, j, "Done") }(c, i, j) } } wg.Wait() // Close all for _, h := range hosts { if err := h.Close(); err != nil { t.Fatal("Couldn't close:", err) } } }