'Handles each UDP packet. It checks the TFTP opcode and parses
accordingly.'

def packetHandler(self, ip=None):

    try:
        udp = dpkt.ip.IP(ip.pkt).data
    except dpkt.UnpackError:
        return
    data = udp.data
    try:
        flag = struct.unpack('!H', data[:2])[0]
    except struct.error:
        return
    data = data[2:]
    if (flag == self.RRQ):
        try:
            (filename, mode) = data.split('\x00')[0:2]
        except ValueError:
            return
        (clientIP, clientPort, serverIP, serverPort) = (ip.sip, udp.sport, ip.dip, udp.dport)
        self.unsetReadStreams[(clientIP, clientPort, serverIP)] = {'filename': filename, 'mode': mode, 'readwrite': 'read', 'closed_connection': False, 'filedata': {}, 'timestamp': ip.ts}
    elif (flag == self.WRQ):
        try:
            (filename, mode) = data.split('\x00')[0:2]
        except ValueError:
            return
        (clientIP, clientPort, serverIP, serverPort) = (ip.sip, udp.sport, ip.dip, udp.dport)
        self.unsetWriteStreams[(clientIP, clientPort, serverIP)] = {'filename': filename, 'mode': mode, 'readwrite': 'write', 'closed_connection': False, 'filedata': {}, 'timestamp': ip.ts}
    elif (flag == self.DATA):
        (clientIP, clientPort, serverIP, serverPort) = (ip.sip, udp.sport, ip.dip, udp.dport)
        key = (clientIP, clientPort, serverIP, serverPort)
        if (key not in self.openStreams):
            if ((serverIP, serverPort, clientIP) in self.unsetReadStreams):
                self.openStreams[key] = self.unsetReadStreams[(serverIP, serverPort, clientIP)]
                del self.unsetReadStreams[(serverIP, serverPort, clientIP)]
            else:
                self.openStreams[key] = self.defaultStream
        blockNum = struct.unpack('!H', data[:2])[0]
        data = data[2:]
        if (len(data) < 512):
            closedConn = True
        else:
            closedConn = False
        self.openStreams[key]['filedata'][blockNum] = data
        self.openStreams[key]['closed_connection'] = closedConn
    elif (flag == self.ACK):
        blockNum = struct.unpack('!H', data[:2])[0]
        (clientIP, clientPort, serverIP, serverPort) = (ip.sip, udp.sport, ip.dip, udp.dport)
        if (blockNum == 0):
            (clientIP, clientPort, serverIP, serverPort) = (ip.dip, udp.dport, ip.sip, udp.sport)
            i = (clientIP, clientPort, serverIP)
            if (i in self.unsetWriteStreams):
                self.openStreams[(clientIP, clientPort, serverIP, serverPort)] = self.unsetWriteStreams[i]
                del self.unsetWriteStreams[i]
        elif (((clientIP, clientPort, serverIP, serverPort) in self.openStreams) and self.openStreams[(clientIP, clientPort, serverIP, serverPort)]['closed_connection']):
            self.__closeStream((clientIP, clientPort, serverIP, serverPort))
        elif (((serverIP, serverPort, clientIP, clientPort) in self.openStreams) and self.openStreams[(serverIP, serverPort, clientIP, clientPort)]['closed_connection']):
            self.__closeStream((serverIP, serverPort, clientIP, clientPort))
    elif (flag == self.ERROR):
        errCode = struct.unpack('!H', data[:2])[0]
        errMessage = data[2:].strip()
        if (errCode == 1):
            (clientIP, clientPort, serverIP, serverPort) = (ip.dip, udp.dport, ip.sip, udp.sport)
            i = (clientIP, clientPort, serverIP)
            if (i in self.unsetReadStreams):
                self.openStreams[(serverIP, serverPort, clientIP, clientPort)] = self.unsetReadStreams[i]
                del self.unsetReadStreams[i]
            self.__closeStream((serverIP, serverPort, clientIP, clientPort), errMessage)
    elif (flag == self.OACK):
        pass
