| 
					
				 | 
			
			
				@@ -531,11 +531,14 @@ unsigned long Switch::doTimerTasks(uint64_t now) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	{	// Time out packets that didn't get all their fragments. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Mutex::Lock _l(_defragQueue_m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for(std::map< uint64_t,DefragQueueEntry >::iterator i(_defragQueue.begin());i!=_defragQueue.end();) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if ((now - i->second.creationTime) > ZT_FRAGMENTED_PACKET_RECEIVE_TIMEOUT) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		Hashtable< uint64_t,DefragQueueEntry >::Iterator i(_defragQueue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		uint64_t *packetId = (uint64_t *)0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DefragQueueEntry *qe = (DefragQueueEntry *)0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		while (i.next(packetId,qe)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ((now - qe->creationTime) > ZT_FRAGMENTED_PACKET_RECEIVE_TIMEOUT) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				TRACE("incomplete fragmented packet %.16llx timed out, fragments discarded",i->first); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				_defragQueue.erase(i++); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} else ++i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				_defragQueue.erase(*packetId); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -577,32 +580,31 @@ void Switch::_handleRemotePacketFragment(const InetAddress &fromAddr,const void 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			// seeing a Packet::Fragment? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			Mutex::Lock _l(_defragQueue_m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			std::map< uint64_t,DefragQueueEntry >::iterator dqe(_defragQueue.find(pid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			DefragQueueEntry &dq = _defragQueue[pid]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if (dqe == _defragQueue.end()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if (!dq.creationTime) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				// We received a Packet::Fragment without its head, so queue it and wait 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				DefragQueueEntry &dq = _defragQueue[pid]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				dq.creationTime = RR->node->now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				dq.frags[fno - 1] = fragment; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				dq.totalFragments = tf; // total fragment count is known 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				dq.haveFragments = 1 << fno; // we have only this fragment 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				//TRACE("fragment (%u/%u) of %.16llx from %s",fno + 1,tf,pid,fromAddr.toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			} else if (!(dqe->second.haveFragments & (1 << fno))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			} else if (!(dq.haveFragments & (1 << fno))) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				// We have other fragments and maybe the head, so add this one and check 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				dqe->second.frags[fno - 1] = fragment; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				dqe->second.totalFragments = tf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				dq.frags[fno - 1] = fragment; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				dq.totalFragments = tf; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				//TRACE("fragment (%u/%u) of %.16llx from %s",fno + 1,tf,pid,fromAddr.toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if (Utils::countBits(dqe->second.haveFragments |= (1 << fno)) == tf) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if (Utils::countBits(dq.haveFragments |= (1 << fno)) == tf) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					// We have all fragments -- assemble and process full Packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					//TRACE("packet %.16llx is complete, assembling and processing...",pid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					SharedPtr<IncomingPacket> packet(dqe->second.frag0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					SharedPtr<IncomingPacket> packet(dq.frag0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					for(unsigned int f=1;f<tf;++f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						packet->append(dqe->second.frags[f - 1].payload(),dqe->second.frags[f - 1].payloadLength()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					_defragQueue.erase(dqe); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						packet->append(dq.frags[f - 1].payload(),dq.frags[f - 1].payloadLength()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					_defragQueue.erase(pid); // dq no longer valid after this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					if (!packet->tryDecode(RR)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						Mutex::Lock _l(_rxQueue_m); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -645,26 +647,27 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		uint64_t pid = packet->packetId(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		Mutex::Lock _l(_defragQueue_m); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		std::map< uint64_t,DefragQueueEntry >::iterator dqe(_defragQueue.find(pid)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		DefragQueueEntry &dq = _defragQueue[pid]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if (dqe == _defragQueue.end()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if (!dq.creationTime) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			// If we have no other fragments yet, create an entry and save the head 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			DefragQueueEntry &dq = _defragQueue[pid]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			dq.creationTime = RR->node->now(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			dq.frag0 = packet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			dq.totalFragments = 0; // 0 == unknown, waiting for Packet::Fragment 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			dq.haveFragments = 1; // head is first bit (left to right) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			//TRACE("fragment (0/?) of %.16llx from %s",pid,fromAddr.toString().c_str()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		} else if (!(dqe->second.haveFragments & 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		} else if (!(dq.haveFragments & 1)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			// If we have other fragments but no head, see if we are complete with the head 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if ((dqe->second.totalFragments)&&(Utils::countBits(dqe->second.haveFragments |= 1) == dqe->second.totalFragments)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if ((dq.totalFragments)&&(Utils::countBits(dq.haveFragments |= 1) == dq.totalFragments)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				// We have all fragments -- assemble and process full Packet 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				//TRACE("packet %.16llx is complete, assembling and processing...",pid); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				// packet already contains head, so append fragments 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				for(unsigned int f=1;f<dqe->second.totalFragments;++f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					packet->append(dqe->second.frags[f - 1].payload(),dqe->second.frags[f - 1].payloadLength()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				_defragQueue.erase(dqe); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				for(unsigned int f=1;f<dq.totalFragments;++f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					packet->append(dq.frags[f - 1].payload(),dq.frags[f - 1].payloadLength()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				_defragQueue.erase(pid); // dq no longer valid after this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				if (!packet->tryDecode(RR)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					Mutex::Lock _l(_rxQueue_m); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -672,7 +675,7 @@ void Switch::_handleRemotePacketHead(const InetAddress &fromAddr,const void *dat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				// Still waiting on more fragments, so queue the head 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				dqe->second.frag0 = packet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				dq.frag0 = packet; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} // else this is a duplicate head, ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} else { 
			 |