Example #1
0
// sendDataPacket sends the given data packet to the connected client
// and waits for the correct ACK, or times out
func sendDataPacket(s *Server, d *pkt.DataPacket, con *net.UDPConn) error {
	_, err := con.Write(d.Bytes())
	if err != nil {
		return err
	}

	// Now wait for the ACK...
	maxtimeout := time.After(AckTimeout)
	ackch := make(chan error)

	// Move it to its own function
	go func() {
		ack := make([]byte, 256)
		for {
			n, _, err := con.ReadFromUDP(ack)
			if err != nil {
				ackch <- err
				return
			}

			pack, err := pkt.ParsePacket(ack[:n])
			if err != nil {
				ackch <- err
				return
			}

			// Check packet type
			ackpack, ok := pack.(*pkt.AckPacket)
			if !ok {
				ackch <- pkt.ErrPacketType
				return
			}

			if ackpack.GetBlocknum() != d.BlockNum {
				s.Logger.Warning("got ack(%d) but expected ack(%d)\n", d.BlockNum, ackpack.GetBlocknum())
				continue
			}
			ackch <- nil
			return
		}
	}()

	// Loop and retransmit until ack or timeout
	retransmit := time.After(RetransmitTime)
	for {
		select {
		case <-maxtimeout:
			return ErrTimeout
		case <-retransmit:
			s.Logger.Warning("Retransmit")
			_, err := con.Write(d.Bytes())
			if err != nil {
				return err
			}
			retransmit = time.After(RetransmitTime)
		case err := <-ackch:
			return err
		}
	}
}
Example #2
0
// Serve opens up a udp socket listening on the given
// address and handles incoming connections received on it
func (s *Server) Serve(addr string) error {
	uaddr, err := net.ResolveUDPAddr("udp", addr)
	if err != nil {
		return err
	}

	uconn, err := net.ListenUDP("udp", uaddr)
	if err != nil {
		return err
	}

	for { // read in new requests
		buf := make([]byte, TftpMaxPacketSize) // TODO: sync.Pool
		n, ua, err := uconn.ReadFromUDP(buf)
		if err != nil {
			return err
		}

		s.Logger.Debug("New Connection!")

		buf = buf[:n]
		packet, err := pkt.ParsePacket(buf)
		if err != nil {
			s.Logger.Debug("Got bad packet: %s", err)
			continue
		}

		go s.HandleClient(ua, packet)
	}
}
Example #3
0
// HandleWriteRequest makes a UDP connection back to the client
// and completes a TFTP Write request with them
func (s *Server) HandleWriteReq(wrq *pkt.ReqPacket, addr *net.UDPAddr) error {
	s.Logger.Debug("Write Request: %s", wrq.Filename)

	// 'Our' Address
	listaddr, err := net.ResolveUDPAddr("udp", ":0")
	if err != nil {
		return err
	}

	// Connection directly to their open port
	con, err := net.DialUDP("udp", listaddr, addr)
	if err != nil {
		return err
	}

	if s.ReadOnly {
		errPkt := pkt.ErrorPacket{}
		errPkt.Value = "writing disallowed"
		errPkt.Code = pkt.TFTPErrAccessViolation
		_, err := con.Write(errPkt.Bytes())
		return err
	}

	// Lol, security? What security?
	fi, err := s.WriteFunc(s.servdir + "/" + wrq.Filename)
	if err != nil {
		return err
	}

	// Send ACK(0)
	ackPkt := pkt.NewAck(0)
	_, err = con.Write(ackPkt.Bytes())
	if err != nil {
		return err
	}

	curblk := uint16(1)
	buf := make([]byte, TftpMaxPacketSize)
	for {
		n, _, err := con.ReadFromUDP(buf)
		if err != nil {
			return err
		}

		idata, err := pkt.ParsePacket(buf[:n])
		if err != nil {
			return err
		}

		data, ok := idata.(*pkt.DataPacket)
		if !ok {
			return ErrUnexpectedPacket
		}

		if data.BlockNum == curblk-1 {
			// They didnt get our ack... lets send it again
			ackPkt := pkt.NewAck(curblk - 1)
			_, err = con.Write(ackPkt.Bytes())
			if err != nil {
				return err
			}

			continue
		} else if data.BlockNum != curblk {
			return errors.New("Received unexpected blocknum... stopping transfer.")
		}

		_, err = fi.Write(data.Data)
		if err != nil {
			return err
		}

		ackPkt := pkt.NewAck(curblk)
		_, err = con.Write(ackPkt.Bytes())
		if err != nil {
			return err
		}

		if len(data.Data) < 512 {
			return nil
		}

		curblk++
	}
}