An access controller for man doors at our facility. It receives Wiegand signals from a keypad/card reader and activates a relay to open the door. Access codes are stored in EEPROM. The active code list is updated from TFTP on a local server.
Dependencies: 24LCxx_I2C CardReader USBHOST
Diff: TFTPClient.cpp
- Revision:
- 0:a56239ae90c2
diff -r 000000000000 -r a56239ae90c2 TFTPClient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TFTPClient.cpp Mon Sep 25 19:02:40 2017 +0000 @@ -0,0 +1,143 @@ + +#include "TFTPClient.h" + +bool TFTPClient::readFile(char* data, const char* host, const char* filename, const uint16_t port, const uint32_t timeout) +{ + printf("TFTP read file\n"); + m_data = data; + + if (m_tftp_addr) + { + delete m_tftp_addr; + m_tftp_addr = NULL; + } + m_tftp_addr = new SocketAddress(host, port); + + printf("IP: %d\n", m_eth); + + m_sock.open(m_eth); + printf("TFTP before blocking\n"); + m_sock.set_blocking(false); + printf("TFTP before bind\n"); + m_sock.bind(0); + + printf("TFTP port bound\n"); + + char chunk[TFTP_MAX_PACKET_SIZE]; + uint16_t tftp_opcode = htons(RRQ); + char tftp_mode[] = "octet"; + + // Construct read request packet + memcpy(chunk, &tftp_opcode, 2); + memcpy(chunk + 2, filename, strlen(filename) + 1); + memcpy(chunk + 2 + (strlen(filename) + 1), tftp_mode, strlen(tftp_mode) + 1); + int packet_size = 2 + strlen(filename) + 1 + strlen(tftp_mode) + 1; + + // Debug output request data. + printf("TFTP RRQ packet: "); + fwrite(chunk, 1, packet_size, stdout); + printf("\n"); + + // Send read request + m_bytes_received = 0; + m_block_number = 1; + m_bytes_sent = m_sock.sendto(*m_tftp_addr, chunk, packet_size); + + if (m_bytes_sent == packet_size) + { + m_download_in_progress = true; + } + else + { + printf("TFTP read request failed. %d\n", m_bytes_sent); + } + + m_next_data_byte_index = 0; + + return m_download_in_progress; +} + +int TFTPClient::update() +{ + int return_value = -1; + char chunk[TFTP_MAX_PACKET_SIZE]; + + if (m_download_in_progress) + { + // Get data packet from the TFTP server + m_bytes_received = m_sock.recvfrom(m_tftp_addr, chunk, TFTP_MAX_PACKET_SIZE); + if (m_bytes_received <= 0) + { + return_value = m_bytes_received; // UDP packet recevie failed. + } + else + { + // Convert the opcode and block back into host endian format. + uint16_t temp_opcode, temp_block; + memcpy(&temp_opcode, chunk, 2); + memcpy(&temp_block, chunk + 2, 2); + temp_opcode = ntohs(temp_opcode); + temp_block = ntohs(temp_block); + + if (temp_opcode == ERR) + { + printf(" TFTP Error: %u, %s\n", temp_block, chunk + 4); + return_value = -2; // Error response from server. + } + else if (temp_opcode == DATA) + { + if (temp_block == m_block_number) + { + int chunk_size = m_bytes_received - 4; + // Debug output for incoming chunks of data. + //printf(" TFTP Chunk Received: %u\n", chunk_size); + //fwrite(chunk, 1, m_bytes_received, stdout); + + // Strip the TFTP info from the beginning of the data buffer. + memcpy(m_data + m_next_data_byte_index, chunk + 4, chunk_size); + m_next_data_byte_index += chunk_size; + // Terminate the data string. + m_data[m_next_data_byte_index] = 0; + + // Send an ACK for the current data block + uint16_t tftp_opcode = htons(ACK); + temp_block = htons(temp_block); + memcpy(chunk, &tftp_opcode, 2); + memcpy(chunk + 2, &temp_block, 2); + int m_bytes_sent = m_sock.sendto(*m_tftp_addr, chunk, 4); // Send + + m_block_number++; + } + else + { + return_value = -3; // Incorrect data block number. + m_download_in_progress = false; + } + } + else + { + return_value = -4; // Wrong opcode + m_download_in_progress = false; + } + + if (m_bytes_received != TFTP_MAX_PACKET_SIZE) + { + m_download_in_progress = false; + + if (m_bytes_received > 0) + { + // Finished download. + return_value = 1; + } + } + } + } + + if (!m_download_in_progress) + { + m_sock.close(); + } + + return return_value; +} + \ No newline at end of file