Exemple #1
0
func main() {

	// By default, Go seeds its RNG with 1. This would cause every program to

	// generate the same sequence of IDs.

	rand.Seed(time.Now().UnixNano())

	// Get the bind and connect connection strings from command-line arguments.

	flag.Parse()

	args := flag.Args()

	if len(args) != 2 {

		log.Fatal("Must be invoked with exactly two arguments!\n")

	}

	listenStr := args[0]

	firstPeerStr := args[1]

	fmt.Printf("kademlia starting up!\n")

	kadem := kademlia.NewKademlia()

	tcpAddr, err := net.ResolveTCPAddr("tcp4", args[0])

	kadem.MyContact.Host = tcpAddr.IP

	kadem.MyContact.Port = uint16(tcpAddr.Port)

	rpc.Register(kadem)

	rpc.HandleHTTP()

	l, err := net.Listen("tcp", listenStr)

	if err != nil {

		log.Fatal("Listen: ", err)

	}

	// Serve forever.

	go http.Serve(l, nil)

	// Confirm our server is up with a PING request and then exit.

	// Your code should loop forever, reading instructions from stdin and

	// printing their results to stdout. See README.txt for more details.

	client, err := rpc.DialHTTP("tcp", firstPeerStr)

	if err != nil {

		log.Fatal("DialHTTP: ", err)

	}

	ping := new(kademlia.Ping)

	ping.MsgID = kademlia.NewRandomID()

	var pong kademlia.Pong

	err = client.Call("Kademlia.Ping", ping, &pong)

	if err != nil {

		log.Fatal("Call: ", err)

	}

	//log.Printf("ping msgID: %s\n", ping.MsgID.AsString())

	// log.Printf("pong msgID: %s\n", pong.MsgID.AsString())

	tcpAdd, err := net.ResolveTCPAddr("tcp4", args[1])

	host := tcpAdd.IP

	port := uint16(tcpAdd.Port)

	//fmt.Println(pong.Sender)

	nodeID := pong.Sender.NodeID

	cont := kademlia.Contact{nodeID, host, port}

	kademlia.Join(kadem, cont)

	for true {

		var command, arg1, arg2, arg3 string

		fmt.Scanf("%s", &command, "\n")

		//fmt.Print("command:", command)

		switch command {

		case "whoami":

			//Print your node ID

			kademlia.WhoAmI(kadem)

		case "local_find_value":

			//If your node has data for the given key, print it.

			//If your node does not have data for the given key, you should print "ERR".

			fmt.Scanf("%s", &arg1)

			key := arg1

			kademlia.LocalFindValue(kadem, key)

		case "get_contact":

			//If your buckets contain a node with the given ID, printf("%v %v\n",theNode.addr,theNode.port)

			//If your buckers do not contain any such node, print "ERR".

			fmt.Scanf("%s", &arg1)

			ID := arg1

			//fmt.Println(ID)

			kademlia.GetContact(kadem, ID)

		case "iterativeStore":

			//Perform the iterativeStore operation and then print the ID of the node that received the final STORE operation.

			fmt.Scanf("%s %s", &arg1, &arg2)

			key := arg1

			keyId, err := kademlia.FromString(key)

			if err != nil {

			}

			value := arg2

			//fmt.Println(key,value)

			storereq := kademlia.StoreRequest{}

			var kclosenodes *list.List

			storereq.Sender = kadem.MyContact

			storereq.MsgID = kademlia.NewRandomID()

			storereq.Key = keyId

			storereq.Value = []byte(value)

			kadem.IterativeStore(storereq, kclosenodes)

		case "iterativeFindNode":

			//Print a list of ≤ k closest nodes and print their IDs. You should collect the IDs in a slice and print that.

			fmt.Scanf("%s", &arg1)

			ID := arg1

			//fmt.Println(ID)

			ID2, err := kademlia.FromString(ID)

			if err != nil {

			}

		//kadem.IterativeFindNode(ID2, false)

		case "iterativeFindValue":

			//printf("%v %v\n"  ID, value), where ID refers to the node that finally returned the value. If you do not find a value, print "ERR".

			fmt.Scanf("%s", &arg1)

			key := arg1

			//fmt.Println(key)

			keyId, err := kademlia.FromString(key)

			if err != nil {

			}

			findvalueresult := kademlia.FindValueResult{}

			kadem.IterativeFindValue(keyId, &findvalueresult)

		case "ping":

			fmt.Scanf("%s", &arg1)

			nodeID := arg1

			//fmt.Println(nodeID)

			if strings.ContainsAny(nodeID, ":") {

				client, err := rpc.DialHTTP("tcp", arg1)

				if err != nil {

					log.Fatal("DialHTTP: ", err)

				}

				ping := new(kademlia.Ping)

				ping.MsgID = kademlia.NewRandomID()

				var pong kademlia.Pong

				err = client.Call("Kademlia.Ping", ping, &pong)

				if err != nil {

					log.Fatal("Call: ", err)

					fmt.Println("Err")

					continue

				}

				tcpAdd, err := net.ResolveTCPAddr("tcp4", arg1)

				host := tcpAdd.IP

				port := uint16(tcpAdd.Port)

				//fmt.Println(pong.Sender)

				nodeID := pong.Sender.NodeID

				cont := kademlia.Contact{nodeID, host, port}

				kademlia.Update(kadem, &cont)

				fmt.Println("Ping success")

				continue

			}

			isPing := kademlia.CallPings(kadem, nodeID)

			if isPing != true {

				fmt.Println("Error in Ping")

			}

		case "store":

			//Perform a store and print a blank line.

			fmt.Scanf("%s %s", &arg1, &arg2)

			nodeID := arg1

			key := arg2

			r := bufio.NewReader(os.Stdin)

			arg3, err = r.ReadString(10)

			//fmt.Fscanln(r, &arg3)

			//arg3 = bufio.ReadString('\n')

			value := arg3

			//fmt.Println("ID: ", nodeID, "key: ", key, "value", value)

			isStored := kademlia.CallStore(kadem, nodeID, key, value)

			if isStored != true {

				fmt.Println("Error in Store")

			}

		case "find_node":

			//Perform a find_node and print its results as for iterativeFindNode.

			fmt.Scanf("%s %s", &arg1, &arg2)

			nodeID := arg1

			key := arg2

			//fmt.Println(nodeID, key)

			isFound := kademlia.CallFindNode(kadem, nodeID, key)

			if isFound != true {

				fmt.Println("Error in finding")

			}

		case "find_value":

			//Perform a find_value. If it returns nodes, print them as for find_node. If it returns a value, print the value as in iterativeFindValue.

			fmt.Scanf("%s %s", &arg1, &arg2)

			nodeID := arg1

			key := arg2

			//fmt.Println(nodeID, key)

			isFound := kademlia.CallFindValue(kadem, nodeID, key)

			if isFound != true {

				fmt.Println("UnSuccessful ")

			}
			break

		case "exit":
			break

		}

		if command == "exit" {
			break
		}

	}

}