예제 #1
0
파일: host.go 프로젝트: nikirill/cothority
// 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
}
예제 #2
0
// 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)
}
예제 #3
0
파일: host.go 프로젝트: nikirill/cothority
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)
}
예제 #4
0
파일: host.go 프로젝트: nikirill/cothority
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)

}
예제 #5
0
파일: host.go 프로젝트: nikirill/cothority
// 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()
		}
	}
}
예제 #6
0
func (h *Host) Receive() network.Packet {
	data := <-h.networkChan
	log.Lvl5("Got message", data)
	return data
}
예제 #7
0
// 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)
		}
	}
}