def exchange(self, vault=None):
		'''
		First thing first, the initiator issues a "exchange request".

		In Cyclon protocol, the exchange request consists in generating a
		subset of peers to exchange with the oldest peer. The "age" of a peer
		is based on the how many exchanges have passed since I last updated
		the state of that peer of my neighboring list.
		'''
		if self.itsExchanging():
			return True

		Cyclon.peerList.increaseAges()

		try:
			oldestPeer = Cyclon.peerList.getOldest()

		except IndexError:
			print ' * No peer available for exchanging'
			return True

		print '''Starting an exchange with ''' + oldestPeer.getName()

		self.exchangeStarted()

		print >> stderr, ''' * computing subset '''
		shuffleSize = randint(1, self.getShuffleLength()) - 1
		randomSubset = Cyclon.peerList.drop(oldestPeer).getSubset(shuffleSize)
		sentSet = CyclonPeerList([ oldestPeer ]) + randomSubset

		message = Message(kind='exchange',
			source=Cyclon.myself.getName(),
			destination=oldestPeer.getName())

		randomSubset.insert(0, Cyclon.myself)

		body = message.getBody()

		print >> stderr, ''' * building message '''

		for p in randomSubset:
			node = body.appendChild(message.createElement('node'))
			node.setAttribute('name', p.getName())
			node.childNodes = p.getConnectionsXML()

		print >> stderr, ''' * Sending request '''

		message.send(
			oldestPeer.transport, 3, 3
		).addCallback(
			self.exchangeReplyReceived, sentSet=sentSet
		).addErrback(
			self.removePeerErrback, peer=oldestPeer.getName(), success=False
		).addErrback(
			self.exchangeFinished, success=False
		).addErrback(
			self.exchange)

		return True
	def replyIntroduction(self, peer, introduced):
		replyMessage = Message('intro reply',
			source=Cyclon.myself.getName(), destination=peer.getName(),
			annotations={ 'introduced': introduced })

		node = replyMessage.body.appendChild(Message.createElement("node"))
		node.setAttribute('name', introduced.getName())

		for c in introduced.getConnectionsXML():
			node.appendChild(c)

		replyMessage.send(
			peer.transport, 5, 3
		).addCallback(
			lambda m: (
				Cyclon.peerList.addPeer(peer),
				(Cyclon.peerList.remove(m.introduced) or True
					if m.introduced in Cyclon.peerList else True)
			)
		).addErrback(lambda m: True)
	def sendIntroductions(self, peer, candidatesSet, replacersSet=None):
		# Building the newcomers peer' description
		nodeInfo = Message.createElement('node', { 'name':peer.getName() })

		for c in peer.getConnectionsXML():
			nodeInfo.appendChild(c)

		# The replacersSet is used for replace unreachable peers in the
		# errback method 'introductionErrback'.
		if replacersSet == None:
			replacersSet = Cyclon.peerList.drop(candidatesSet)

		print ' | Sending introduction to the following peers: '
		# Sending the introductory message to the random candidatesSet
		for q in candidatesSet:
			# One message per peer as the destination must be explicit
			introMessage = Message(kind='introduction',
				source=Cyclon.myself.getName(),
				destination=q.getName(),
				extraAttributes={
					'ttl': str(self.getTTL())},
				annotations={
					'candidatesSset': candidatesSet,
					'newcomer': peer,
					'replacersSet': replacersSet})

			# Appending newcomers info
			introMessage.getBody().appendChild(nodeInfo)

			print ' |->', q.getName()
			# The actual sending
			introMessage.send(
				q.transport, 3, 3
			).addCallback(
				lambda m: True
			).addErrback(
				self.introductionErrback, message=introMessage)