Пример #1
0
// 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
// RegisterProtocolInstance takes a PI and stores it for dispatching the message
// to it.
func (o *Overlay) RegisterProtocolInstance(pi ProtocolInstance) error {
	o.instancesLock.Lock()
	defer o.instancesLock.Unlock()
	var tni *TreeNodeInstance
	var tok = pi.Token()
	var ok bool
	// if the TreeNodeInstance doesn't exist
	if tni, ok = o.instances[tok.ID()]; !ok {
		return ErrWrongTreeNodeInstance
	}

	if tni.isBound() {
		return ErrProtocolRegistered
	}

	tni.bind(pi)
	o.protocolInstances[tok.ID()] = pi
	log.Lvlf4("%s registered ProtocolInstance %x", o.host.workingAddress, tok.ID())
	return nil
}
Пример #3
0
// 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()
		}
	}
}
Пример #4
0
// TransmitMsg takes a message received from the host and treats it. It might
// - ask for the identityList
// - ask for the Tree
// - create a new protocolInstance
// - pass it to a given protocolInstance
func (o *Overlay) TransmitMsg(sdaMsg *ProtocolMsg) error {
	o.transmitMux.Lock()
	defer o.transmitMux.Unlock()
	// do we have the entitylist ? if not, ask for it.
	if o.Roster(sdaMsg.To.RosterID) == nil {
		log.Lvl4("Will ask the Roster from token", sdaMsg.To.RosterID, len(o.entityLists), o.host.workingAddress)
		return o.host.requestTree(sdaMsg.ServerIdentity, sdaMsg)
	}
	tree := o.Tree(sdaMsg.To.TreeID)
	if tree == nil {
		log.Lvl4("Will ask for tree from token")
		return o.host.requestTree(sdaMsg.ServerIdentity, sdaMsg)
	}
	// TreeNodeInstance
	var pi ProtocolInstance
	o.instancesLock.Lock()
	pi, ok := o.protocolInstances[sdaMsg.To.ID()]
	done := o.instancesInfo[sdaMsg.To.ID()]
	o.instancesLock.Unlock()
	if done {
		log.Lvl4("Message for TreeNodeInstance that is already finished")
		return nil
	}
	// if the TreeNodeInstance is not there, creates it
	if !ok {
		log.Lvlf4("Creating TreeNodeInstance at %s %x", o.host.ServerIdentity, sdaMsg.To.ID())
		tn, err := o.TreeNodeFromToken(sdaMsg.To)
		if err != nil {
			return errors.New("No TreeNode defined in this tree here")
		}
		tni := o.newTreeNodeInstanceFromToken(tn, sdaMsg.To)
		// see if we know the Service Recipient
		s, ok := o.host.serviceStore.serviceByID(sdaMsg.To.ServiceID)

		// no servies defined => check if there is a protocol that can be
		// created
		if !ok {
			pi, err = ProtocolInstantiate(sdaMsg.To.ProtoID, tni)
			if err != nil {
				return err
			}
			go pi.Dispatch()

			/// use the Services to instantiate it
		} else {
			// request the PI from the Service and binds the two
			pi, err = s.NewProtocol(tni, &sdaMsg.Config)
			if err != nil {
				return err
			}
			if pi == nil {
				return nil
			}
			go pi.Dispatch()
		}
		if err := o.RegisterProtocolInstance(pi); err != nil {
			return errors.New("Error Binding TreeNodeInstance and ProtocolInstance: " +
				err.Error())
		}
		log.Lvl4(o.host.workingAddress, "Overlay created new ProtocolInstace msg => ",
			fmt.Sprintf("%+v", sdaMsg.To))

	}

	log.Lvl4("Dispatching message", o.host.ServerIdentity)
	// TODO Check if TreeNodeInstance is already Done
	pi.ProcessProtocolMsg(sdaMsg)

	return nil
}
Пример #5
0
// Send opens the connection to 'dst' and sends the message 'req'. The
// reply is returned, or an error if the timeout of 10 seconds is reached.
func (c *Client) Send(dst *network.ServerIdentity, msg network.Body) (*network.Packet, error) {
	c.Lock()
	defer c.Unlock()
	if c.host == nil {
		kp := config.NewKeyPair(network.Suite)
		c.host = network.NewSecureTCPHost(kp.Secret,
			network.NewServerIdentity(kp.Public, ""))
	}

	// Connect to the root
	log.Lvl4("Opening connection to", dst)
	con, err := c.host.Open(dst)
	defer c.host.Close()
	if err != nil {
		return nil, err
	}

	m, err := network.NewNetworkMessage(msg)
	if err != nil {
		return nil, err
	}

	b, err := m.MarshalBinary()
	if err != nil {
		return nil, err
	}

	serviceReq := &ClientRequest{
		Service: c.ServiceID,
		Data:    b,
	}
	pchan := make(chan network.Packet)
	go func() {
		// send the request
		log.Lvlf4("Sending request %x", serviceReq.Service)
		if err := con.Send(context.TODO(), serviceReq); err != nil {
			close(pchan)
			return
		}
		log.Lvl4("Waiting for the response from", reflect.ValueOf(con).Pointer())
		// wait for the response
		packet, err := con.Receive(context.TODO())
		if err != nil {
			packet.Msg = StatusRet{err.Error()}
			packet.MsgType = network.TypeFromData(&StatusRet{})
		}
		pchan <- packet
	}()
	select {
	case response := <-pchan:
		log.Lvlf5("Response: %+v %+v", response, response.Msg)
		// Catch an eventual error
		err := ErrMsg(&response, nil)
		if err != nil {
			return nil, err
		}
		return &response, nil
	case <-time.After(time.Second * 10):
		return &network.Packet{}, errors.New("Timeout on sending message")
	}
}