Example #1
0
//given an ID, searches the local store, DHT, and if found unmarshals the bytes into a MartiniContact
func findMartiniContact(dm *DryMartini, hashedID kademlia.ID) (MartiniContact, bool) {
	var mcBytes []byte
	var mc MartiniContact
	var err error
	var success bool

	mcBytes, success = dm.KademliaInst.ValueStore.Get(hashedID)
	if !success {
		success, _, mcBytes, err = kademlia.IterativeFind(dm.KademliaInst, hashedID, 2)
		if err != nil {
			dbg.Printf("findingMartiniContact failed. searching for key:%s. err:%s\n", ERRORS, hashedID.AsString(), err)
			return mc, false
		}
		if success {
			dbg.Printf("findMartiniContact: foundValue\n", Verbose)
		} else {
			dbg.Printf("IterativeFind failed to findvalue for key:%s\n", ERRORS, hashedID.AsString())
			return mc, false
		}
	} else {
		//dbg.Printf("found martiniContact locally. Key:%+v\n", hashedID)
	}
	err = json.Unmarshal(mcBytes, &mc)
	dbg.Printf("findMartiniContact: 'foundContact.NodeIP:%s, Port:%d\n", Verbose, mc.NodeIP, mc.NodePort)
	if err != nil {
		dbg.Printf("Error unmarshaling found MartiniContact. %s\n", ERRORS, err)
		panic(1)
	}
	return mc, true
}
Example #2
0
func (kInst *KademliaInstruction) Execute(k *kademlia.Kademlia) (status bool) {
	var found bool
	var remoteContact *kademlia.Contact

	switch {
	case kInst.IsExit():
		if kademlia.RunningTests {
			log.Printf("Executing Exit Instruction\n")
		}
		return true
	case kInst.IsSkip():
		if kademlia.RunningTests {
			log.Printf("Executing Skip Instruction: _%s_\n", kInst.Data)
		}
		return true
	case kInst.IsPing():
		var success bool

		if kInst.Addr != "" { //ping host:port
			log.Printf("Executing Ping Instruction 'ping Addr:%s\n", kInst.Addr)
			remoteHost, remotePort, err := kademlia.AddrStrToHostPort(kInst.Addr)
			kademlia.Assert(err == nil, "Error converting AddrToHostPort")
			success = kademlia.MakePingCall(k, remoteHost, remotePort)
		} else { //ping nodeID
			log.Printf("Executing Ping Instruction 'ping nodeID:%s\n", kInst.NodeID.AsString())
			var searchRequest *kademlia.SearchRequest

			searchRequest = &kademlia.SearchRequest{kInst.NodeID, make(chan *kademlia.Contact)}
			k.SearchChannel <- searchRequest
			remoteContact = <-searchRequest.ReturnChan
			found = (remoteContact != nil)
			if found {
				success = kademlia.MakePingCall(k, remoteContact.Host, remoteContact.Port)
			} else {
				log.Printf("Error: Ping, nodeID %s could not be found\n", kInst.NodeID.AsString())
				return false
			}
		}
		return success
	case kInst.IsStore():
		var searchRequest *kademlia.SearchRequest
		var success bool
		if kademlia.RunningTests {
			log.Printf("Executing Store Instruction %s %s %s\n", kInst.NodeID.AsString(), kInst.Key.AsString(), kInst.Data)
		}

		searchRequest = &kademlia.SearchRequest{kInst.NodeID, make(chan *kademlia.Contact)}
		k.SearchChannel <- searchRequest
		remoteContact = <-searchRequest.ReturnChan
		found = (remoteContact != nil)
		if found {
			success = kademlia.MakeStore(k, remoteContact, kInst.Key, []byte(kInst.Data))
		} else {
			log.Printf("Error: Store, nodeID %s could not be found\n", kInst.NodeID.AsString())
			return false
		}
		return success
	case kInst.IsFindNode():
		var searchRequest *kademlia.SearchRequest
		var success bool
		if kademlia.RunningTests {
			log.Printf("Executing FindNode Instruction %s %s\n", kInst.NodeID.AsString(), kInst.Key.AsString())
		}
		searchRequest = &kademlia.SearchRequest{kInst.NodeID, make(chan *kademlia.Contact)}
		k.SearchChannel <- searchRequest
		remoteContact = <-searchRequest.ReturnChan
		found = (remoteContact != nil)
		if found {
			var fsResponseChan chan *kademlia.FindStarCallResponse
			var findStarResult *kademlia.FindStarCallResponse

			fsResponseChan = make(chan *kademlia.FindStarCallResponse, 1)
			go kademlia.MakeFindNodeCall(k, remoteContact, kInst.Key, fsResponseChan)
			findStarResult = <-fsResponseChan

			success = findStarResult.Responded
			if success {
				kademlia.Assert(findStarResult.ReturnedFNRes != nil, "findStarResult Struct error in FindNode")
				kademlia.PrintArrayOfFoundNodes(&(findStarResult.ReturnedFNRes.Nodes))
			}
		} else {
			log.Printf("Error: FindNode, nodeID %s could not be found\n", kInst.NodeID.AsString())
			return false
		}
		return success
	case kInst.IsFindValue():
		var searchRequest *kademlia.SearchRequest
		var success bool
		if kademlia.RunningTests {
			log.Printf("Executing FindValue Instruction %s %s\n", kInst.NodeID.AsString(), kInst.Key.AsString())
		}
		searchRequest = &kademlia.SearchRequest{kInst.NodeID, make(chan *kademlia.Contact)}
		k.SearchChannel <- searchRequest
		remoteContact = <-searchRequest.ReturnChan
		found = (remoteContact != nil)
		if found {
			var fsResponseChan chan *kademlia.FindStarCallResponse
			var findStarResult *kademlia.FindStarCallResponse

			fsResponseChan = make(chan *kademlia.FindStarCallResponse, 1)
			go kademlia.MakeFindValueCall(k, remoteContact, kInst.Key, fsResponseChan)
			findStarResult = <-fsResponseChan

			success = findStarResult.Responded
			if success {
				kademlia.Assert(findStarResult.ReturnedFVRes != nil, "findStarResult Struct error in FindValue")
				if findStarResult.ReturnedFVRes.Value != nil {
					log.Printf("FindValue: found [%s:%s]\n", kInst.Key.AsString(), string(findStarResult.ReturnedFVRes.Value))
				} else {
					log.Printf("FindValue: Could not locate value, printing closest nodes\n")
					kademlia.PrintArrayOfFoundNodes(&(findStarResult.ReturnedFVRes.Nodes))
				}
			}
		} else {
			log.Printf("Error: FindValue, nodeID %s could not be found\n", kInst.NodeID.AsString())
			return false
		}
		return success
	case kInst.IsWhoami():
		if kademlia.RunningTests {
			log.Printf("Executing Whoami Instruction\n")
			fmt.Printf("Local Node ID: %s\n", k.ContactInfo.NodeID.AsString())
		} else {
			fmt.Printf("%s\n", k.ContactInfo.NodeID.AsString())
		}
		return true
	case kInst.IsLocalFindValue():
		if kademlia.RunningTests {
			log.Printf("Executing LocalFindValue Instruction\n")
		}
		localvalue, found := k.ValueStore.Get(kInst.Key)
		if found {
			if kademlia.RunningTests {
				fmt.Printf("Value for key %s --> %s\n", kInst.Key.AsString(), string(localvalue))
			} else {
				fmt.Printf("%s\n", string(localvalue))
			}
		} else {
			if kademlia.RunningTests {
				fmt.Printf("Value for Key %s NOT found\n", kInst.Key.AsString())
			} else {
				fmt.Printf("ERR\n")
			}
		}
		return true
	case kInst.IsGetContact():
		var searchRequest *kademlia.SearchRequest
		if kademlia.RunningTests {
			log.Printf("Executing GetContact Instruction %s\n", kInst.NodeID.AsString())
		}

		searchRequest = &kademlia.SearchRequest{kInst.NodeID, make(chan *kademlia.Contact)}
		k.SearchChannel <- searchRequest
		remoteContact = <-searchRequest.ReturnChan
		found = (remoteContact != nil)
		if found {
			if kademlia.RunningTests {
				log.Printf("GetContact: Addr:%v, Port: %v\n", remoteContact.Host, remoteContact.Port)
			} else {
				fmt.Printf("%v %v\n", remoteContact.Host, remoteContact.Port)
			}
		} else {
			if kademlia.RunningTests {
				log.Printf("GetContact: Could not locate in local buckets nodeID %s\n", kInst.NodeID.AsString())
			} else {
				fmt.Printf("ERR\n")
			}
		}
		return true
	case kInst.IsIterativeStore():
		var success bool
		var nodes []kademlia.FoundNode
		var err error

		if kademlia.RunningTests {
			log.Printf("Executing iterativeStore Instruction %s %s\n", kInst.Key.AsString(), kInst.Data)
		}

		//NOTE: the third returned value is dropped on the assumption it would always be nil for this call
		success, nodes, _, err = kademlia.IterativeFind(k, kInst.Key, 1) //findType of 1 is FindNode
		if err != nil {
			log.Printf("IterativeFind: Error %s\n", err)
			return false
		}
		if success {
			if nodes != nil {
				for _, node := range nodes {
					kademlia.MakeStore(k, node.FoundNodeToContact(), kInst.Key, []byte(kInst.Data))
				}
				kademlia.PrintArrayOfFoundNodes(&nodes)
			} else {
				kademlia.Assert(false, "iterativeFindStore: TODO: This should probably never happen right?")
			}
		}
		return success
	case kInst.IsIterativeFindNode():
		var success bool
		var nodes []kademlia.FoundNode
		//var value []byte //This is probably not needed as iterativeFindNode should never return a value
		var err error

		if kademlia.RunningTests {
			log.Printf("Executing iterativeFindNode Instruction %s\n", kInst.NodeID.AsString())
		}

		//NOTE: the third returned value is dropped on the assumption it would always be nil for this call
		success, nodes, _, err = kademlia.IterativeFind(k, kInst.NodeID, 1) //findType of 1 is FindNode
		if err != nil {
			log.Printf("IterativeFind: Error %s\n", err)
			return false
		}
		if success {
			if nodes != nil {
				kademlia.PrintArrayOfFoundNodes(&nodes)
			} else {
				kademlia.Assert(false, "iterativeFindNode: TODO: This should probably never happen right?")
			}
		}
		return success
	case kInst.IsIterativeFindValue():
		var success bool
		var nodes []kademlia.FoundNode
		var value []byte
		var err error

		if kademlia.RunningTests {
			log.Printf("Executing iterativeFindValue Instruction %s\n", kInst.Key.AsString())
		}

		success, nodes, value, err = kademlia.IterativeFind(k, kInst.Key, 2) //findType of 2 is FindValue
		if err != nil {
			log.Printf("IterativeFind: Error %s\n", err)
			return false
		}
		if success {
			if value != nil {
				if kademlia.RunningTests {
					fmt.Printf("iterativeFindValue: Value for key %s --> %s\n", kInst.Key.AsString(), string(value))
				} else {
					fmt.Printf("%v %v\n", nodes[0].NodeID, value)
				}
			} else {
				if kademlia.RunningTests {
					fmt.Printf("iterativeFindValue: Value for key %s NOT FOUND\n", kInst.Key.AsString())
					kademlia.PrintArrayOfFoundNodes(&nodes)
				} else {
					fmt.Printf("ERR")
				}
			}
		}
		return success
	case kInst.IsRunTests():
		log.Printf("Executing RunTests!\n")
		kademlia.RunTests(kInst.Data)
		return true
	case kInst.IsPrintLocalBuckets():
		log.Printf("Print Local Buckets!\n")
		kademlia.PrintLocalBuckets(k)
		return true
	case kInst.IsPrintLocalData():
		log.Printf("Print Local Data!\n")
		kademlia.PrintLocalData(k)
		return true
	}

	return false
}
Example #3
0
//returns array of random known-to-be-live MartiniContacts (for use as a path)
func GeneratePath(dm *DryMartini, min, max int) (mcPath []MartiniContact) {
	const safetyMax int = 50
	var err error
	//var threshold int
	//var myRand *big.Int
	var randId kademlia.ID
	var pathMap map[MartiniContact]bool = make(map[MartiniContact]bool)
	//minBig := big.NewInt(int64(min))
	//myRand, err = rand.Int(rand.Reader, big.NewInt(int64(max-min)))
	//threshold = int((minBig.Int64() + myRand.Int64()))
	mcPath = make([]MartiniContact, max)
	var safetyCounter int = 0
	for i := 0; i < max; i++ {
		var foundNodes []kademlia.FoundNode
		var success bool
		safetyCounter++
		dbg.Printf("Attempt %d to add to path (curlength %d)\n", Verbose, safetyCounter, i)
		if safetyCounter == safetyMax {
			dbg.Printf("GeneratePath failure. Made %d attempts. unable to get enough MartiniContacts to build path of length:%d\n", ERRORS, safetyMax, max)
			panic(1)
		}
		randId = kademlia.NewRandomID()
		success, foundNodes, _, err = kademlia.IterativeFind(dm.KademliaInst, randId, 1)
		if len(foundNodes) == 0 {
			dbg.Printf("GeneratePath:316. no nodes found; continueing\n", Verbose)
			i--
			continue
		}

		/*
			dbg.Printf("GeneratePath: found live nodes:\n")
			kademlia.PrintArrayOfFoundNodes(&foundNodes)
		*/

		if err != nil {
			dbg.Printf("error finding random NodeID:%s, success:%s msg:%s\n", ERRORS, randId, success, err)
			panic(1)
		}
		fuckthis, fuckingo := rand.Int(rand.Reader, big.NewInt(int64(len(foundNodes))))
		if fuckingo != nil {
			dbg.Printf("error making rand:%s\n", ERRORS, fuckingo)
		}
		index := int(fuckthis.Int64())
		var hashedID kademlia.ID = foundNodes[index].NodeID.SHA1Hash()
		dbg.Printf("generatePath: findMartiniContact for mc:%+v\n", Verbose, foundNodes[index])
		var tempMC MartiniContact
		tempMC, success = findMartiniContact(dm, hashedID)
		if !success {
			dbg.Printf("error finding MartiniContact with key:%s. err:%s\n", ERRORS, hashedID.AsString(), err)
			i--
			continue
		}
		_, alreadyInPath := pathMap[tempMC]
		if alreadyInPath {
			dbg.Printf("trying to make a circular path. skipping!\n", Verbose)
			i--
			continue
		} else {
			pathMap[tempMC] = true
			mcPath[i] = tempMC
		}
		//err = json.Unmarshal(mcBytes, &mcPath[i])
		dbg.Printf("GeneratePath path-mid-build: %+v\n", Verbose, mcPath)
	}
	return
}
Example #4
0
func (dmInst *DryMartiniInstruction) Execute(dm *drymartini.DryMartini) (status bool) {
	var err error

	switch {
	case dmInst.IsExit():
		if Verbose {
			log.Printf("Executing Exit Instruction\n")
		}
		return true
	case dmInst.IsSkip():
		if Verbose {
			log.Printf("Executing Skip Instruction: _%s_\n", dmInst.CmdStr)
		}
		return true
	case dmInst.IsPing():
		var success bool

		if Verbose {
			log.Printf("Executing Ping Instruction 'ping Addr:%s\n", dmInst.Addr)
		}
		remoteHost, remotePort, err := kademlia.AddrStrToHostPort(dmInst.Addr)
		if err != nil {
			log.Printf("Error converting AddrToHostPort, %s", err)
			os.Exit(1)
		}
		success = drymartini.MakeMartiniPing(dm, remoteHost, remotePort)

		return success
	case dmInst.IsJoin():
		if Verbose {
			log.Printf("Executing MartiniJoin Instruction\n")
		}
		//remoteHost, remotePort, err := kademlia.AddrStrToHostPort(dmInst.Addr)
		//drymartini.MakeJoin(dm, remoteHost, remotePort)
		//if err != nil {
		//	log.Printf("Error converting AddrToHostPort, %s", err)
		//	os.Exit(1)
		//}
		return true
	case dmInst.IsWhoami():
		if Verbose {
			log.Printf("Executing Whoami Instruction\n")
			fmt.Printf("Local Node ID: %s\n", dm.KademliaInst.ContactInfo.NodeID.AsString())
		} else {
			fmt.Printf("%s\n", dm.KademliaInst.ContactInfo.NodeID.AsString())
		}
		return true
	case dmInst.IsPrintLocalBuckets():
		log.Printf("Print Local Buckets!\n")
		kademlia.PrintLocalBuckets(dm.KademliaInst)
		return true
	case dmInst.IsPrintLocalData():
		log.Printf("Print Local Data!\n")
		//kademlia.PrintLocalData(dm.KademliaInst)
		drymartini.PrintLocalData(dm)
		return true
	case dmInst.IsPrintLocalFlowData():
		log.Printf("Print Local FlowData!\n")
		drymartini.PrintLocalFlowData(dm)
		return true
	case dmInst.IsGeneratePath():
		log.Printf("Generate Path\n")
		drymartini.GeneratePath(dm, dmInst.minNodes, dmInst.maxNodes)
		return true
	case dmInst.IsBarCrawl():
		log.Printf("Bar Crawl (negotiating symmkeys with nodes)")
		drymartini.BarCrawl(dm, dmInst.request, dmInst.minNodes, dmInst.maxNodes)
	case dmInst.IsFindValue():
		log.Printf("Find Value")
		var sucess bool
		//var nodes[]kademlia.FoundNode
		var value []byte
		sucess, _, value, err = kademlia.IterativeFind(dm.KademliaInst, dmInst.Key, 2)
		if err != nil {
			log.Printf("IterativeFind: error %s\n", err)
		}
		if sucess {
			if value != nil {
				log.Printf("IterativeFindValue err: success = true. value is nil\n")
			}
		}
	case dmInst.IsSend():
		log.Printf("Send %d %s\n", dmInst.FlowIndex, dmInst.request)
		drymartini.SendData(dm, dmInst.FlowIndex, dmInst.request)
	case dmInst.IsMakeSwarm():
		log.Printf("Making swarm: numNodes:%d\n", dmInst.minNodes)
		var swarm []*drymartini.DryMartini = drymartini.MakeSwarm(dmInst.minNodes, dmInst.maxNodes, time.Now().UnixNano())
		drymartini.WarmSwarm(dm, swarm, rand.New(rand.NewSource(time.Now().UnixNano())))
	case dmInst.IsRunTests():
		log.Printf("Running tests: numNodes:%d\n", dmInst.minNodes)
		drymartini.RunTests(dm, dmInst.minNodes, dmInst.maxNodes, time.Now().UnixNano(), 4, 4)
	case dmInst.IsSleep():
		log.Printf("Sleeping %d ms\n", dmInst.minNodes)
		time.Sleep(time.Millisecond * time.Duration(dmInst.minNodes))
	case dmInst.IsBlock():
		fmt.Printf("Blocking comm on node\n")
		log.Printf("Blocking comm on this node\n")
		dm.KademliaInst.KListener.Close()
	case dmInst.IsOpen():
		fmt.Printf("Accepting comm on node again\n")
		log.Printf("Accepting comms again\n")
		go http.Serve(dm.KademliaInst.KListener, nil)
	case dmInst.IsBCAndSend():
		log.Printf("bc and send\n")
		success, index := drymartini.FindGoodPath(dm)
		if !success {
			success, index = drymartini.BarCrawl(dm, dmInst.request, dmInst.minNodes, dmInst.maxNodes)
			if !success {
				log.Printf("Error: main. bcandsend; bc failed\n")
				return
			}
		}
		drymartini.SendData(dm, index, dmInst.request)
	}
	return false
}