示例#1
0
// Adds a peer to the swarm.info file
// @param string addPath - the path of the file to be added
// @param string swarmPath - the path of the swarminfo file
// @return error - An error can be produced when issues arise from trying to access
// the swarm file or if the file to be added already exists in the swarm file - otherwise
// error will be nil.
func addToSwarminfo(addPeer lynxutil.Peer, swarmPath string) error {
	swarmFile, err := os.OpenFile(swarmPath, os.O_APPEND|os.O_WRONLY, 0644) // Opens for appending
	if err != nil {
		return err
	}

	lynkName := getTLynkName(swarmPath)
	lynk := lynxutil.GetLynk(tLynks, lynkName)
	if lynk == nil {
		tLynks = append(tLynks, lynxutil.Lynk{Name: lynkName})
		lynk = lynxutil.GetLynk(tLynks, lynkName)
	}

	parseSwarminfo(swarmPath)

	i := 0
	for i < len(lynk.Peers) {
		if lynk.Peers[i].IP == addPeer.IP && lynk.Peers[i].Port == addPeer.Port {
			return errors.New("Can't Add Duplicates To Swarminfo")
		}
		i++
	}

	// Write to swarminfo file using ::: to IP and Port
	swarmFile.WriteString(addPeer.IP + ":::" + addPeer.Port + "\n")

	return swarmFile.Close()
}
示例#2
0
// Gets a file from the peer(s)
// @param string fileName - The name of the file to find in the peers
// @param string metaPath - The meta.info path associated with the lynk we're interested in
// @return error - An error can be produced if there are connection issues,
// problems creating or writing to the file, or from not being able to get there
// desired file - otherwise error will be nil.
func getFile(fileName, metaPath string) error {
	// Will parseMetainfo file and then ask tracker for list of peers
	parseMetainfo(metaPath)
	lynkName := GetLynkName(metaPath)
	lynk := lynxutil.GetLynk(lynks, lynkName)
	//fmt.Println("Asking For File From: " + metaPath)
	askTrackerForPeers(lynkName)
	//fmt.Println(lynk.Peers)

	i := 0
	gotFile := false
	for i < len(lynk.Peers) && !gotFile {
		conn, err := net.Dial("tcp", lynk.Peers[i].IP+":"+lynk.Peers[i].Port)
		// We don't want to return on err because we might be able to connect to next peer.
		if err == nil {
			gotFile = askForFile(lynkName, fileName, conn)
		}
		//fmt.Println(i)
		i++
	}

	if gotFile {
		return nil
	}

	return errors.New("Did not receive file") // If we got here - we didn't have the file.
}
示例#3
0
// Parses the information in swarm.info file and places each entry into a Peer
// struct and appends that struct to the array of peers
// @param string swarmPath - The path to the swarminfo file
// @return error - An error can be produced when issues arise from trying to access
// the swarm file or from an invalid swarm file type - otherwise error will be nil.
func parseSwarminfo(swarmPath string) error {
	lynkName := getTLynkName(swarmPath)
	lynk := lynxutil.GetLynk(tLynks, lynkName)

	//fmt.Println(lynk)
	lynk.Peers = nil // Resets peers array

	swarmFile, err := os.Open(swarmPath)
	if err != nil {
		return err
	} else if !strings.Contains(swarmPath, "swarm.info") {
		return errors.New("Invalid File Type")
	}

	scanner := bufio.NewScanner(swarmFile)
	tempPeer := lynxutil.Peer{}

	// Scan each line
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text()) // Trim helps with errors in \n
		split := strings.Split(line, ":::")

		tempPeer.IP = split[0]
		tempPeer.Port = split[1]
		lynk.Peers = append(lynk.Peers, tempPeer)
	}

	//fmt.Println(lynk.Peers)
	return swarmFile.Close()
}
示例#4
0
// Deletes the current swarm.info and replaces it with a new version that
// accurately reflects the array of Peers after they have been modified
// @return error - An error can be produced when issues arise from trying to create
// or remove the swarm file - otherwise error will be nil.
func updateSwarminfo(swarmPath string) error {
	parseSwarminfo(swarmPath)

	err := os.Remove(swarmPath)
	if err != nil {
		fmt.Println(err)
		return err
	}

	newSwarmInfo, err := os.Create(swarmPath)
	if err != nil {
		fmt.Println(err)
		return err
	}

	lynkName := getTLynkName(swarmPath)
	lynk := lynxutil.GetLynk(tLynks, lynkName)

	i := 0
	for i < len(lynk.Peers) {
		newSwarmInfo.WriteString(lynk.Peers[i].IP + ":::" + lynk.Peers[i].Port + "\n")
		i++
	}

	return newSwarmInfo.Close()
}
示例#5
0
// UpdateMetainfo - Deletes the current meta.info and replaces it with a new version that
// accurately reflects the array of Files after they have been modified.
// @return error - An error can be produced when issues arise from trying to create
// or remove the meta file - otherwise error will be nil.
func UpdateMetainfo(metaPath string) error {
	parseMetainfo(metaPath)
	lynkName := GetLynkName(metaPath)
	lynk := lynxutil.GetLynk(lynks, lynkName)

	err := os.Remove(metaPath)
	if err != nil {
		fmt.Println(err)
		return err
	}

	newMetainfo, err := os.Create(metaPath)
	if err != nil {
		fmt.Println(err)
		return err
	}

	newMetainfo.WriteString("announce:::" + lynk.Tracker + "\n") // Write tracker IP
	newMetainfo.WriteString("lynkName:::" + lynk.Name + "\n")
	newMetainfo.WriteString("owner:::" + lynk.Owner + "\n")
	i := 0
	for i < len(lynk.Files) {
		newMetainfo.WriteString("length:::" + strconv.Itoa(lynk.Files[i].Length) + "\n") // str conv
		newMetainfo.WriteString("path:::" + lynk.Files[i].Path + "\n")
		newMetainfo.WriteString("name:::" + lynk.Files[i].Name + "\n")
		newMetainfo.WriteString("chunkLength:::" + strconv.Itoa(lynk.Files[i].ChunkLength) + "\n")
		newMetainfo.WriteString("chunks:::" + lynk.Files[i].Chunks + "\n")
		newMetainfo.WriteString(endOfEntry + "\n")
		i++
	}

	return newMetainfo.Close()
}
示例#6
0
// HaveFile - Checks to see if we have the passed in file.
// @param string filePath - The name of the file to check for - This includes the lynk name.
// E.G. - 'Cool_Lynk/coolFile.txt'
// @return bool - A boolean indicating whether or not we have a file in our
// files array.
func HaveFile(filePath string) bool {
	have := false

	lynkInfo := strings.Split(filePath, "/")
	if len(lynkInfo) != 2 {
		fmt.Println(filePath + " is an invalid filepath")
		return have
	}

	lynkName := lynkInfo[0]
	fileName := lynkInfo[1]
	metaPath := lynxutil.HomePath + lynkName + "/meta.info"
	parseMetainfo(metaPath)
	lynk := lynxutil.GetLynk(lynks, lynkName)

	i := 0
	for i < len(lynk.Files) && !have {
		if lynk.Files[i].Name == fileName {
			have = true
		}
		i++
	}

	return have
}
示例#7
0
// Helper function that verifies there has been a change in the files for the system tests lynk.
// @returns True if there has been a change, False if there has not been a change
func checkChanges() bool {
	changed := len(lynxutil.GetLynk(client.GetLynks(), "SysTests").Files)
	result := false
	if changed != original {
		original = changed
		result = true
	}

	return result
}
示例#8
0
// Unit tests for addToMetainfo function
// @param *testing.T t - The wrapper for the test
func TestAddToMetainfo(t *testing.T) {
	fmt.Println("\n----------------TestAddToMetainfo----------------")

	parseMetainfo(mPath)
	hasTest := false
	tLynk := lynxutil.GetLynk(lynks, "Tests")

	i := 0
	for i < len(tLynk.Files) {
		//fmt.Print(files[i].name)
		if tLynk.Files[i].Name == "test.txt" {
			//fmt.Print(files[i].name)
			hasTest = true
		}
		i++
	}

	// add test.txt to the metainfo
	result := AddToMetainfo("test.txt", mPath)

	if result != nil && !hasTest {
		t.Error("Test failed, expected no errors. Got ", result)
	} else {
		fmt.Println("Successfully Added To Metainfo")
		successful++
	}

	parseMetainfo(mPath)

	// check that test.txt is in the File struct list
	i = 0
	for i < len(tLynk.Files) {
		if tLynk.Files[i].Name == "test.txt" {
			hasTest = true
		}
		i++
	}

	if !hasTest {
		t.Error("test.txt was not added to metainfo.")
	} else {
		fmt.Println("Successfully Added test.txt To Metainfo")
		successful++
	}

	result = AddToMetainfo("test.txt", mPath)

	if result == nil {
		t.Error("Test failed, expected failure due to duplicates. Got ", result)
	} else {
		fmt.Println("Successfully Avoided Adding Duplicates")
		successful++
	}
}
示例#9
0
// UpdateLynk - Function which will update the files of a Lynk with the current versions.
// @param lynkName string - the name of the Lynk we want to update
func UpdateLynk(lynkName string) error {
	// We actually get the files we need over the network.
	lynk := lynxutil.GetLynk(lynks, lynkName)
	var err error // Creates nil error
	for _, file := range lynk.Files {
		err = getFile(file.Name, lynxutil.HomePath+lynkName+"/meta.info")
		// If we fail to get the file the first time, we attempt again.
		if err.Error() == "Did not receive file" {
			for i := 0; i < lynxutil.ReconnAttempts; i++ {
				err = getFile(file.Name, lynxutil.HomePath+lynkName+"/meta.info")
			}
		}
	}

	return err
}
示例#10
0
// Unit tests for GetTrackerIP function
// @param *testing.T t - The wrapper for the test
func TestAskTrackerForPeers(t *testing.T) {
	fmt.Println("\n----------------TestAskTracker----------------")

	lynkName := GetLynkName(mPath)
	lynk := lynxutil.GetLynk(lynks, lynkName)
	askTrackerForPeers(lynkName)

	if len(lynk.Peers) <= 0 {
		t.Error("Did Not Get Correct List Of Peers")
	} else {
		fmt.Println("Successfully Got Peers")
		successful++
	}

	fmt.Println("\nSuccess on ", successful, "/", total, " tests.")
}
示例#11
0
// BroadcastNewIP - This function broadcasts a tracker's new IP address to all of its peers
// @param string swarmPath - The swarm.info path associated with the lynk we're interested in
func BroadcastNewIP(swarmPath string) {
	// Can update Meta here if needed
	lynkName := getTLynkName(swarmPath)
	lynk := lynxutil.GetLynk(tLynks, lynkName)

	i := 0
	for i < len(lynk.Peers) {
		fmt.Println(i)
		conn, err := net.Dial("tcp", lynk.Peers[i].IP+":"+lynk.Peers[i].Port)
		if err == nil {
			sendFile(lynxutil.HomePath+lynk.Name+"/meta.info", conn)
		}
		fmt.Println(lynk.Peers[i].IP)
		i++
	}
}
示例#12
0
// Asks the tracker for a list of peers and then places them into a lynk's peers array
// @param string lynkName - The name of the lynk we're interested in
func askTrackerForPeers(lynkName string) error {
	lynk := lynxutil.GetLynk(lynks, lynkName)
	// Connects to tracker
	conn, err := net.Dial("tcp", lynk.Tracker)
	if err != nil {
		i := 0
		for i < len(lynk.Peers) && err != nil {
			pConn, _ := net.Dial("tcp", lynk.Peers[i].IP+":"+lynk.Peers[i].Port)
			fmt.Fprintf(pConn, "Tracker_Request:"+lynkName+"/\n")
			reply := ""
			reply, err = bufio.NewReader(pConn).ReadString('\n') // Waits for a String ending in newline
			reply = strings.TrimSpace(reply)

			conn, err = net.Dial("tcp", reply)
			i++
		}

		// We could not connect to the tracker
		if err != nil {
			return err
		}
	}

	// Gives IP and ServerPort So It Can Be Added To swarm.info
	fmt.Fprintf(conn, "Swarm_Request:"+lynxutil.GetIP()+":"+lynxutil.ServerPort+":"+lynkName+"\n")
	reader := bufio.NewReader(conn)
	tp := textproto.NewReader(reader)

	reply, err := tp.ReadLine()
	//fmt.Println(reply)

	// Tracker will close connection when finished - which will break us out of this loop
	for err == nil {
		peerArray := strings.Split(reply, ":::")
		tmpPeer := lynxutil.Peer{IP: peerArray[0], Port: peerArray[1]}
		if !contains(lynk.Peers, tmpPeer) {
			lynk.Peers = append(lynk.Peers, tmpPeer)
		}
		reply, err = tp.ReadLine()
	}

	return nil // Did not have an error if we reached this point
}
示例#13
0
// Unit tests for deleteEntry function
// @param *testing.T t - The wrapper for the test
func TestDeleteFile(t *testing.T) {
	fmt.Println("\n----------------TestDeleteFiley----------------")
	failed := false

	parseMetainfo(mPath)
	lynkName := GetLynkName(mPath)
	DeleteFile("test.txt", lynkName)

	tLynk := lynxutil.GetLynk(lynks, lynkName)

	i := 0
	for i < len(tLynk.Files) {
		if tLynk.Files[i].Name == "test.txt" {
			t.Error("Error, test.txt is still in files")
			failed = true
		}
		i++
	}

	if !failed {
		fmt.Println("Successfully Removed The test.txt File")
		successful++
	} else {
		failed = false
	}

	DeleteFile("test11.txt", lynkName)

	i = 0
	for i < len(tLynk.Files) {
		if tLynk.Files[i].Name == "test11.txt" {
			t.Error("Error, test11.txt is still in files")
			failed = true
		}
		i++
	}

	if !failed {
		fmt.Println("Successfully Removed The test11.txt File")
		successful++
	}
}
示例#14
0
// DeleteFile - Function that deletes an entry from a lynk's files array.
// @param string nameToDelete - This is the name of the file we want to delete
// @param string lynkName - The lynk we want to delete it from
func DeleteFile(nameToDelete, lynkName string) error {
	// Need to delete the local file too - so parseMeta properly picks it up
	lynk := lynxutil.GetLynk(lynks, lynkName)
	var err error

	if lynk == nil {
		err = errors.New("Could not delete file")
	}

	i := 0
	for i < len(lynk.Files) {
		if nameToDelete == lynk.Files[i].Name {
			lynk.Files = append(lynk.Files[:i], lynk.Files[i+1:]...)
		}
		i++
	}

	fmt.Println(lynk.Files)
	return err
}
示例#15
0
// Parses the information in meta.info file and places each entry into a File
// struct and appends that struct to the array of structs
// @param string metaPath - The path to the metainfo file
// @return error - An error can be produced when issues arise from trying to access
// the meta file or from an invalid meta file type - otherwise error will be nil.
func parseMetainfo(metaPath string) error {
	lynk := lynxutil.GetLynk(lynks, GetLynkName(metaPath))
	if lynk == nil {
		return errors.New("Lynk Not Found")
	}
	lynk.Files = nil // Resets files array

	metaFile, err := os.Open(metaPath)
	if err != nil {
		return err
	} else if !strings.Contains(metaPath, "meta.info") {
		return errors.New("Invalid File Type")
	}

	scanner := bufio.NewScanner(metaFile)
	tempFile := lynxutil.File{}
	for scanner.Scan() { // Scan each line
		split := strings.Split(strings.TrimSpace(scanner.Text()), ":::")
		if split[0] == "announce" {
			lynk.Tracker = split[metaValueIndex]
		} else if split[0] == "owner" {
			lynk.Owner = split[metaValueIndex]
		} else if split[0] == "lynkName" {
			lynk.Name = split[metaValueIndex]
		} else if split[0] == "chunkLength" {
			tempFile.ChunkLength, _ = strconv.Atoi(split[metaValueIndex])
		} else if split[0] == "length" {
			tempFile.Length, _ = strconv.Atoi(split[metaValueIndex])
		} else if split[0] == "path" {
			tempFile.Path = split[metaValueIndex]
		} else if split[0] == "name" {
			tempFile.Name = split[metaValueIndex]
		} else if split[0] == "chunks" {
			tempFile.Chunks = split[metaValueIndex]
		} else if split[0] == endOfEntry {
			lynk.Files = append(lynk.Files, tempFile) // Append the current file to the file array
			tempFile = lynxutil.File{}                // Empty the current file
		}
	}
	return metaFile.Close()
}
示例#16
0
// AddToMetainfo - Adds a file to the meta.info by parsing that file's information
// @param string addPath - the path of the file to be added
// @param string metaPath - the path of the metainfo file - must be full path from root.
// @return error - An error can be produced when issues arise from trying to access
// the meta file or if the file to be added already exists in the meta file - otherwise
// error will be nil.
func AddToMetainfo(addPath, metaPath string) error {
	metaFile, err := os.OpenFile(metaPath, os.O_APPEND|os.O_WRONLY, 0644) // Opens for appending
	if err != nil {
		fmt.Println(err)
		return err
	}

	addStat, err := os.Stat(addPath)
	if err != nil {
		fmt.Println(err)
		return err
	}

	parseMetainfo(metaPath)
	lynkName := GetLynkName(metaPath)
	lynk := lynxutil.GetLynk(lynks, lynkName)

	i := 0
	for i < len(lynk.Files) {
		if lynk.Files[i].Name == addStat.Name() {
			return errors.New("Can't Add Duplicates To Metainfo")
		}
		i++
	}

	lengthStr := strconv.FormatInt(addStat.Size(), 10) // Convert int64 to string
	metaFile.WriteString("length:::" + lengthStr + "\n")

	tempPath, err := filepath.Abs(addPath) // Find the path of the current file
	if err != nil {
		return err
	}

	// Write to metainfo file using ::: to separate keys and values
	metaFile.WriteString("path:::" + tempPath + "\n")
	metaFile.WriteString("name:::" + addStat.Name() + "\n")
	metaFile.WriteString("chunkLength:::32\n")
	metaFile.WriteString("chunks:::256\n")
	metaFile.WriteString(endOfEntry + "\n")
	return metaFile.Close()
}
示例#17
0
// Function that deletes an entry from a lynk's peers array and the swarm.info file.
// @param string peerToDelete - This is the peer struct we want to delete - uses the IP address
// @param string lynkName - The lynk we want to delete it from
func deletePeer(peerToDelete, lynkName string) {
	lynk := lynxutil.GetLynk(tLynks, lynkName)

	i := 0
	for i < len(lynk.Peers) {
		if peerToDelete == lynk.Peers[i].IP {
			lynk.Peers = append(lynk.Peers[:i], lynk.Peers[i+1:]...)
		}
		i++
	}

	swarmPath := lynxutil.HomePath + lynkName + "/" + lynkName + "_Tracker/" + "swarm.info"

	os.Remove(swarmPath)
	newSwarmInfo, _ := os.Create(swarmPath)

	i = 0
	for i < len(lynk.Peers) {
		newSwarmInfo.WriteString(lynk.Peers[i].IP + ":::" + lynk.Peers[i].Port + "\n")
		i++
	}
}
示例#18
0
// StopDownload - Sets a boolean to stop the lynk from downloading
func StopDownload(lynkName string) {
	lynk := lynxutil.GetLynk(lynks, lynkName)
	lynk.DLing = false
}
示例#19
0
// IsDownloading - Returns whether or not the client associated the specified lynk is downloading
// @param lynkName
// @returns - Returns whether or not the client associated the specified lynk is downloading
func IsDownloading(lynkName string) bool {
	lynk := lynxutil.GetLynk(lynks, lynkName)

	return lynk.DLing
}
示例#20
0
// GetTracker - Simply returns the tracker associated with the passed in Lynk
// @param string metaPath - The meta.info path associated with the lynk we're interested in
// @return string - A string representing the tracker's IP address.
func GetTracker(metaPath string) string {
	parseMetainfo(metaPath)
	lynkName := GetLynkName(metaPath)
	lynk := lynxutil.GetLynk(lynks, lynkName)
	return lynk.Tracker
}