//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 }
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 }
//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 }
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 }