func WriteFile(in <-chan *tftp.File, m map[string][]byte, verbose *bool) { for r := range in { if *verbose { fmt.Println(r.Name, " to be written ") } _, present := m[r.Name] if !present { m[r.Name] = r.Data } else { errCode := []byte{0, 6} errMsg := "No overwriting allowed" if *verbose { fmt.Println(errMsg) } tftp.SendERRORTo(errCode, errMsg, r.Conn, r.Raddr) } } }
func main() { /* flag for turning on verbose output */ verbose := flag.Bool("verbose", false, "a bool") flag.Parse() /* handler for map of channels to communicate with routines handling read/write requests */ add := make(chan *net.UDPAddr) send := make(chan sendPair) done := make(chan *net.UDPAddr) getChannel := make(chan *net.UDPAddr) gottenChannel := make(chan chan []byte) sendConfirmation := make(chan bool) defer close(gottenChannel) defer close(sendConfirmation) go ChannelHandler(add, send, sendConfirmation, done, getChannel, gottenChannel, verbose) /* local memory for storing files */ m := map[string][]byte{} /* channel for the file writer go routine */ newFile := make(chan *tftp.File) defer close(newFile) go WriteFile(newFile, m, verbose) /* Lets prepare a address at any address at port 10001*/ ServerAddr, err := net.ResolveUDPAddr("udp", ":10001") CheckError(err) /* Now listen at selected port */ ServerConn, err := net.ListenUDP("udp", ServerAddr) CheckError(err) defer ServerConn.Close() buf := make([]byte, 1024) for { n, addr, err := ServerConn.ReadFromUDP(buf) CheckError(err) if n < 2 || buf[0] != 0 || buf[1] == 0 || buf[1] > 5 { tftp.SendERRORTo([]byte{0, 0}, "bad opcode", ServerConn, addr) continue } switch buf[1] { case 1: //handle RRQ if *verbose { fmt.Println("Recived ", string(buf[0:n]), " from ", addr, " as RRQ") } filename, err := tftp.GetRRQname(buf[0:n]) if err != nil { errCode := []byte{0, 0} errMsg := "Badly formed RRQ packet" if *verbose { fmt.Println(errMsg, " from ", addr) } tftp.SendERRORTo(errCode, errMsg, ServerConn, addr) } else { _, present := m[filename] if present { add <- addr getChannel <- addr temp := <-gottenChannel if temp != nil { go tftp.HandleRRQ(filename, temp, done, ServerConn, addr, m[filename], verbose) } } else { errCode := []byte{0, 1} errMsg := filename + " not found" tftp.SendERRORTo(errCode, errMsg, ServerConn, addr) } } case 2: //handle WRQ if *verbose { fmt.Println("Recieved ", string(buf[0:n]), " from ", addr, " as WRQ") } filename, err := tftp.GetWRQname(buf[0:n]) if err != nil { errCode := []byte{0, 0} errMsg := "Badly formed WRQ packet" if *verbose { fmt.Println(errMsg, " from ", addr) } tftp.SendERRORTo(errCode, errMsg, ServerConn, addr) } else { _, present := m[filename] if present { errCode := []byte{0, 6} errMsg := "No overwriting allowed" if *verbose { fmt.Println(errMsg) } tftp.SendERRORTo(errCode, errMsg, ServerConn, addr) } else { add <- addr getChannel <- addr temp := <-gottenChannel if temp != nil { go tftp.HandleWRQ(filename, temp, done, ServerConn, addr, newFile, verbose) } } } case 3: //handle DATA if *verbose { fmt.Println(" Recieved ", string(buf[0:n]), " from ", addr, " as DATA") } send <- sendPair{addr, buf[0:n]} sent := <-sendConfirmation if !sent { errCode := []byte{0, 5} errMsg := "No write request associated with this return address" if *verbose { fmt.Println(" ", errMsg, " ", addr) } tftp.SendERRORTo(errCode, errMsg, ServerConn, addr) } case 4: //handle ACK if *verbose { fmt.Println(" Recieved ", string(buf[0:n]), " from ", addr, " as ACK") } send <- sendPair{addr, buf[0:n]} sent := <-sendConfirmation if !sent { errCode := []byte{0, 5} errMsg := "No read request associated with this return address" if *verbose { fmt.Println(" ", errMsg, " ", addr) } tftp.SendERRORTo(errCode, errMsg, ServerConn, addr) } case 5: //handle ERROR /* all errors should term connection, EXCEPT if the error is because "the source port of a recieved tftp is incorrect. in this case an errr tftp is sent to the originating host" */ if *verbose { fmt.Println(" Recieved ", string(buf[0:n]), " from ", addr, " as ERROR") } done <- addr } } }