Example #1
0
func sendFullWrite(filename string, content string) {
	//sends inital WRQ
	//waits for ack block 0,0 or times out
	//loop
	//  sends data
	//  waits for ack, or handles error, or resends
	//  if data sent and acknowledged was last data, end

	ServerAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:10001")
	checkError(err)

	LocalAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
	checkError(err)

	Conn, err := net.DialUDP("udp", LocalAddr, ServerAddr)
	checkError(err)
	defer Conn.Close()

	/* initialize variables for tracking acknowledgements and location in content*/
	index := 0
	f := []byte(content)
	max := min(512, len(f))
	data := f[index:max]
	block := []byte{0, 0}

	/*send inital WRQ*/

	/*send inital WRQ*/
	tftp.SendWRQ(filename, Conn)
	packet := make(chan []byte)
	defer close(packet)
	go getPacket(Conn, packet)

	select {
	case <-time.After(15 * time.Second):
		fmt.Println("WRQ from ", LocalAddr, " never acknowledged")
		return
	case r := <-packet:
		switch r[1] {
		case 4:
			//ACK packet recieved
			ackBlock, err := tftp.GetAckBlock(r)
			if err != nil {
				errCode := []byte{0, 0}
				errMsg := "badly formed ACK packet"
				tftp.SendERROR(errCode, errMsg, Conn)
				return
			}
			if ackBlock[1] == block[1] {
				break
			}

		case 5:
			//ERROR packet recieved
			_, errMsg, err := tftp.GetError(r)
			if err != nil {
				return
			}
			fmt.Println(string(errMsg), " recieved by ", LocalAddr)
			return
		}
	}

SendLoop:
	for {
		//send Data
		block[1]++
		tftp.SendDATA(block, data, Conn)

		//wait for ack
	LoopAck:
		for {
			select {
			case <-time.After(time.Second * 3):
				tftp.SendDATA(block, data, Conn)
			case <-time.After(time.Second * 15):
				fmt.Println("DATA packet ", string(block), " from ", LocalAddr, " never acknowledged")
				return
			case r := <-packet:
				switch r[1] {
				case 4:
					//ACK packet recieved
					ackBlock, err := tftp.GetAckBlock(r)
					if err != nil {
						errCode := []byte{0, 0}
						errMsg := "badly formed ACK packet"
						tftp.SendERROR(errCode, errMsg, Conn)
						return
					}
					if ackBlock[1] == block[1] {
						break LoopAck
					}

				case 5:
					//ERROR packet recieved
					_, errMsg, err := tftp.GetError(r)
					if err != nil {
						return
					}
					fmt.Println(string(errMsg), " recieved by ", LocalAddr)
					return
				}
			}
		}

		if max == len(content) {
			break SendLoop
		}

		//update data
		index += 512
		max = min(index+512, len(f))
		data = f[index:max]

	}

}
Example #2
0
func sendFullRead(filename string) (string, error) {
	//sends RRQ
	//loop:
	//  listens for DATA with block ahead of prev ACK packet
	//  send ACK packet for current DATA
	//  if len(current DATA) < 512, send final ACK and close
	ServerAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:10001")
	checkError(err)

	LocalAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
	checkError(err)

	Conn, err := net.DialUDP("udp", LocalAddr, ServerAddr)
	checkError(err)
	defer Conn.Close()

	temp := []byte{}
	tftp.SendRRQ(filename, Conn)
	prev_block := []byte{0, 0}
	packet := make(chan []byte)
	defer close(packet)
	go getPacket(Conn, packet)

Read:
	for {
		select {
		case r := <-packet:
			switch r[1] {
			case 3:
				//DATA packet recieved
				block, data, err := tftp.GetData(r)
				if err != nil {
					return "", err
				}
				if block[1] == prev_block[1]+1 {
					tftp.SendACK(block, Conn)
					prev_block[1] = block[1]
					temp = append(temp, data...)
					if len(data) < 512 {
						break Read
					}
				} else if block[1] != 0 {
					tftp.SendACK(prev_block, Conn)
				} // else the RRQ itself failed somehow

			case 5:
				//ERROR packet recieved
				_, errMsg, err := tftp.GetError(r)
				if err != nil {
					return "", err
				}
				fmt.Println(string(errMsg), " recieved by ", LocalAddr)
				return "", errors.New(string(errMsg))
			}
		case <-time.After(1 * time.Second):
			tftp.SendACK(prev_block, Conn)

		case <-time.After(15 * time.Second):
			fmt.Println("A read request by ", LocalAddr, " timed out")
			return "", errors.New("rrq timed out")
		}
	}

	return string(temp), nil
}