Sfoglia il codice sorgente

Wire up VERB_USER_MESSAGE in core.

Adam Ierymenko 8 anni fa
parent
commit
d5528e4e9a
6 ha cambiato i file con 99 aggiunte e 3 eliminazioni
  1. 51 1
      include/ZeroTierOne.h
  2. 19 2
      node/IncomingPacket.cpp
  3. 1 0
      node/IncomingPacket.hpp
  4. 23 0
      node/Node.cpp
  5. 1 0
      node/Node.hpp
  6. 4 0
      node/Packet.hpp

+ 51 - 1
include/ZeroTierOne.h

@@ -393,7 +393,17 @@ enum ZT_Event
 	 *
 	 * Meta-data: C string, TRACE message
 	 */
-	ZT_EVENT_TRACE = 5
+	ZT_EVENT_TRACE = 5,
+
+	/**
+	 * VERB_USER_MESSAGE received
+	 *
+	 * These are generated when a VERB_USER_MESSAGE packet is received via
+	 * ZeroTier VL1.
+	 *
+	 * Meta-data: ZT_UserMessage structure
+	 */
+	ZT_EVENT_USER_MESSAGE = 6
 };
 
 /**
@@ -406,6 +416,32 @@ enum ZT_RelayPolicy
 	ZT_RELAY_POLICY_ALWAYS = 2
 };
 
+/**
+ * User message used with ZT_EVENT_USER_MESSAGE
+ */
+typedef struct
+{
+	/**
+	 * ZeroTier address of sender (least significant 40 bits)
+	 */
+	uint64_t origin;
+
+	/**
+	 * User message type ID
+	 */
+	uint64_t typeId;
+
+	/**
+	 * User message data (not including type ID)
+	 */
+	const void *data;
+
+	/**
+	 * Length of data in bytes
+	 */
+	unsigned int length;
+} ZT_UserMessage;
+
 /**
  * Current node status
  */
@@ -1853,6 +1889,20 @@ int ZT_Node_addLocalInterfaceAddress(ZT_Node *node,const struct sockaddr_storage
  */
 void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node);
 
+/**
+ * Send a VERB_USER_MESSAGE to another ZeroTier node
+ *
+ * There is no delivery guarantee here. Failure can occur if the message is
+ * too large or if dest is not a valid ZeroTier address.
+ *
+ * @param dest Destination ZeroTier address
+ * @param typeId VERB_USER_MESSAGE type ID
+ * @param data Payload data to attach to user message
+ * @param len Length of data in bytes
+ * @return Boolean: non-zero on success, zero on failure
+ */
+int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
+
 /**
  * Set peer role
  *

+ 19 - 2
node/IncomingPacket.cpp

@@ -106,8 +106,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR)
 				case Packet::VERB_PUSH_DIRECT_PATHS:          return _doPUSH_DIRECT_PATHS(RR,peer);
 				case Packet::VERB_CIRCUIT_TEST:               return _doCIRCUIT_TEST(RR,peer);
 				case Packet::VERB_CIRCUIT_TEST_REPORT:        return _doCIRCUIT_TEST_REPORT(RR,peer);
-				case Packet::VERB_USER_MESSAGE:
-					return true;
+				case Packet::VERB_USER_MESSAGE:               return _doUSER_MESSAGE(RR,peer);
 			}
 		} else {
 			RR->sw->requestWhois(sourceAddress);
@@ -1345,6 +1344,24 @@ bool IncomingPacket::_doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const S
 	return true;
 }
 
+bool IncomingPacket::_doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer)
+{
+	try {
+		if (size() >= (ZT_PACKET_IDX_PAYLOAD + 8)) {
+			ZT_UserMessage um;
+			um.origin = peer->address().toInt();
+			um.typeId = at<uint64_t>(ZT_PACKET_IDX_PAYLOAD);
+			um.data = reinterpret_cast<const void *>(reinterpret_cast<const uint8_t *>(data()) + ZT_PACKET_IDX_PAYLOAD + 8);
+			um.length = size() - (ZT_PACKET_IDX_PAYLOAD + 8);
+			RR->node->postEvent(ZT_EVENT_USER_MESSAGE,reinterpret_cast<const void *>(&um));
+		}
+		peer->received(_path,hops(),packetId(),Packet::VERB_CIRCUIT_TEST_REPORT,0,Packet::VERB_NOP,false);
+	} catch ( ... ) {
+		TRACE("dropped CIRCUIT_TEST_REPORT from %s(%s): unexpected exception",source().toString().c_str(),_path->address().toString().c_str());
+	}
+	return true;
+}
+
 void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,const uint64_t nwid)
 {
 	const uint64_t now = RR->node->now();

+ 1 - 0
node/IncomingPacket.hpp

@@ -131,6 +131,7 @@ private:
 	bool _doPUSH_DIRECT_PATHS(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
 	bool _doCIRCUIT_TEST(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
 	bool _doCIRCUIT_TEST_REPORT(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
+	bool _doUSER_MESSAGE(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer);
 
 	void _sendErrorNeedCredentials(const RuntimeEnvironment *RR,const SharedPtr<Peer> &peer,const uint64_t nwid);
 

+ 23 - 0
node/Node.cpp

@@ -473,6 +473,20 @@ void Node::clearLocalInterfaceAddresses()
 	_directPaths.clear();
 }
 
+int Node::sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
+{
+	try {
+		Packet outp(Address(dest),RR->identity.address(),Packet::VERB_USER_MESSAGE);
+		outp.append(typeId);
+		outp.append(data,len);
+		outp.compress();
+		RR->sw->send(outp,true);
+		return 1;
+	} catch ( ... ) {
+		return 0;
+	}
+}
+
 void Node::setRole(uint64_t ztAddress,ZT_PeerRole role)
 {
 	RR->topology->setUpstream(Address(ztAddress),(role == ZT_PEER_ROLE_UPSTREAM));
@@ -992,6 +1006,15 @@ void ZT_Node_clearLocalInterfaceAddresses(ZT_Node *node)
 	} catch ( ... ) {}
 }
 
+int ZT_Node_sendUserMessage(ZT_Node *node,uint64_t dest,uint64_t typeId,const void *data,unsigned int len)
+{
+	try {
+		return reinterpret_cast<ZeroTier::Node *>(node)->sendUserMessage(dest,typeId,data,len);
+	} catch ( ... ) {
+		return 0;
+	}
+}
+
 void ZT_Node_setRole(ZT_Node *node,uint64_t ztAddress,ZT_PeerRole role)
 {
 	try {

+ 1 - 0
node/Node.hpp

@@ -98,6 +98,7 @@ public:
 	void freeQueryResult(void *qr);
 	int addLocalInterfaceAddress(const struct sockaddr_storage *addr);
 	void clearLocalInterfaceAddresses();
+	int sendUserMessage(uint64_t dest,uint64_t typeId,const void *data,unsigned int len);
 	void setRole(uint64_t ztAddress,ZT_PeerRole role);
 	void setNetconfMaster(void *networkControllerInstance);
 	ZT_ResultCode circuitTestBegin(ZT_CircuitTest *test,void (*reportCallback)(ZT_Node *,ZT_CircuitTest *,const ZT_CircuitTestReport *));

+ 4 - 0
node/Packet.hpp

@@ -1048,6 +1048,10 @@ public:
 		 * This can be used to send arbitrary messages over VL1. It generates no
 		 * OK or ERROR and has no special semantics outside of whatever the user
 		 * (via the ZeroTier core API) chooses to give it.
+		 *
+		 * Message type IDs less than or equal to 65535 are reserved for use by
+		 * ZeroTier, Inc. itself. We recommend making up random ones for your own
+		 * implementations.
 		 */
 		VERB_USER_MESSAGE = 0x14
 	};