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
TFTPClient.cpp@0:a56239ae90c2, 2017-09-25 (annotated)
- Committer:
- acesrobertm
- Date:
- Mon Sep 25 19:02:40 2017 +0000
- Revision:
- 0:a56239ae90c2
in process of moving networking code to non-blocking format
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
acesrobertm | 0:a56239ae90c2 | 1 | |
acesrobertm | 0:a56239ae90c2 | 2 | #include "TFTPClient.h" |
acesrobertm | 0:a56239ae90c2 | 3 | |
acesrobertm | 0:a56239ae90c2 | 4 | bool TFTPClient::readFile(char* data, const char* host, const char* filename, const uint16_t port, const uint32_t timeout) |
acesrobertm | 0:a56239ae90c2 | 5 | { |
acesrobertm | 0:a56239ae90c2 | 6 | printf("TFTP read file\n"); |
acesrobertm | 0:a56239ae90c2 | 7 | m_data = data; |
acesrobertm | 0:a56239ae90c2 | 8 | |
acesrobertm | 0:a56239ae90c2 | 9 | if (m_tftp_addr) |
acesrobertm | 0:a56239ae90c2 | 10 | { |
acesrobertm | 0:a56239ae90c2 | 11 | delete m_tftp_addr; |
acesrobertm | 0:a56239ae90c2 | 12 | m_tftp_addr = NULL; |
acesrobertm | 0:a56239ae90c2 | 13 | } |
acesrobertm | 0:a56239ae90c2 | 14 | m_tftp_addr = new SocketAddress(host, port); |
acesrobertm | 0:a56239ae90c2 | 15 | |
acesrobertm | 0:a56239ae90c2 | 16 | printf("IP: %d\n", m_eth); |
acesrobertm | 0:a56239ae90c2 | 17 | |
acesrobertm | 0:a56239ae90c2 | 18 | m_sock.open(m_eth); |
acesrobertm | 0:a56239ae90c2 | 19 | printf("TFTP before blocking\n"); |
acesrobertm | 0:a56239ae90c2 | 20 | m_sock.set_blocking(false); |
acesrobertm | 0:a56239ae90c2 | 21 | printf("TFTP before bind\n"); |
acesrobertm | 0:a56239ae90c2 | 22 | m_sock.bind(0); |
acesrobertm | 0:a56239ae90c2 | 23 | |
acesrobertm | 0:a56239ae90c2 | 24 | printf("TFTP port bound\n"); |
acesrobertm | 0:a56239ae90c2 | 25 | |
acesrobertm | 0:a56239ae90c2 | 26 | char chunk[TFTP_MAX_PACKET_SIZE]; |
acesrobertm | 0:a56239ae90c2 | 27 | uint16_t tftp_opcode = htons(RRQ); |
acesrobertm | 0:a56239ae90c2 | 28 | char tftp_mode[] = "octet"; |
acesrobertm | 0:a56239ae90c2 | 29 | |
acesrobertm | 0:a56239ae90c2 | 30 | // Construct read request packet |
acesrobertm | 0:a56239ae90c2 | 31 | memcpy(chunk, &tftp_opcode, 2); |
acesrobertm | 0:a56239ae90c2 | 32 | memcpy(chunk + 2, filename, strlen(filename) + 1); |
acesrobertm | 0:a56239ae90c2 | 33 | memcpy(chunk + 2 + (strlen(filename) + 1), tftp_mode, strlen(tftp_mode) + 1); |
acesrobertm | 0:a56239ae90c2 | 34 | int packet_size = 2 + strlen(filename) + 1 + strlen(tftp_mode) + 1; |
acesrobertm | 0:a56239ae90c2 | 35 | |
acesrobertm | 0:a56239ae90c2 | 36 | // Debug output request data. |
acesrobertm | 0:a56239ae90c2 | 37 | printf("TFTP RRQ packet: "); |
acesrobertm | 0:a56239ae90c2 | 38 | fwrite(chunk, 1, packet_size, stdout); |
acesrobertm | 0:a56239ae90c2 | 39 | printf("\n"); |
acesrobertm | 0:a56239ae90c2 | 40 | |
acesrobertm | 0:a56239ae90c2 | 41 | // Send read request |
acesrobertm | 0:a56239ae90c2 | 42 | m_bytes_received = 0; |
acesrobertm | 0:a56239ae90c2 | 43 | m_block_number = 1; |
acesrobertm | 0:a56239ae90c2 | 44 | m_bytes_sent = m_sock.sendto(*m_tftp_addr, chunk, packet_size); |
acesrobertm | 0:a56239ae90c2 | 45 | |
acesrobertm | 0:a56239ae90c2 | 46 | if (m_bytes_sent == packet_size) |
acesrobertm | 0:a56239ae90c2 | 47 | { |
acesrobertm | 0:a56239ae90c2 | 48 | m_download_in_progress = true; |
acesrobertm | 0:a56239ae90c2 | 49 | } |
acesrobertm | 0:a56239ae90c2 | 50 | else |
acesrobertm | 0:a56239ae90c2 | 51 | { |
acesrobertm | 0:a56239ae90c2 | 52 | printf("TFTP read request failed. %d\n", m_bytes_sent); |
acesrobertm | 0:a56239ae90c2 | 53 | } |
acesrobertm | 0:a56239ae90c2 | 54 | |
acesrobertm | 0:a56239ae90c2 | 55 | m_next_data_byte_index = 0; |
acesrobertm | 0:a56239ae90c2 | 56 | |
acesrobertm | 0:a56239ae90c2 | 57 | return m_download_in_progress; |
acesrobertm | 0:a56239ae90c2 | 58 | } |
acesrobertm | 0:a56239ae90c2 | 59 | |
acesrobertm | 0:a56239ae90c2 | 60 | int TFTPClient::update() |
acesrobertm | 0:a56239ae90c2 | 61 | { |
acesrobertm | 0:a56239ae90c2 | 62 | int return_value = -1; |
acesrobertm | 0:a56239ae90c2 | 63 | char chunk[TFTP_MAX_PACKET_SIZE]; |
acesrobertm | 0:a56239ae90c2 | 64 | |
acesrobertm | 0:a56239ae90c2 | 65 | if (m_download_in_progress) |
acesrobertm | 0:a56239ae90c2 | 66 | { |
acesrobertm | 0:a56239ae90c2 | 67 | // Get data packet from the TFTP server |
acesrobertm | 0:a56239ae90c2 | 68 | m_bytes_received = m_sock.recvfrom(m_tftp_addr, chunk, TFTP_MAX_PACKET_SIZE); |
acesrobertm | 0:a56239ae90c2 | 69 | if (m_bytes_received <= 0) |
acesrobertm | 0:a56239ae90c2 | 70 | { |
acesrobertm | 0:a56239ae90c2 | 71 | return_value = m_bytes_received; // UDP packet recevie failed. |
acesrobertm | 0:a56239ae90c2 | 72 | } |
acesrobertm | 0:a56239ae90c2 | 73 | else |
acesrobertm | 0:a56239ae90c2 | 74 | { |
acesrobertm | 0:a56239ae90c2 | 75 | // Convert the opcode and block back into host endian format. |
acesrobertm | 0:a56239ae90c2 | 76 | uint16_t temp_opcode, temp_block; |
acesrobertm | 0:a56239ae90c2 | 77 | memcpy(&temp_opcode, chunk, 2); |
acesrobertm | 0:a56239ae90c2 | 78 | memcpy(&temp_block, chunk + 2, 2); |
acesrobertm | 0:a56239ae90c2 | 79 | temp_opcode = ntohs(temp_opcode); |
acesrobertm | 0:a56239ae90c2 | 80 | temp_block = ntohs(temp_block); |
acesrobertm | 0:a56239ae90c2 | 81 | |
acesrobertm | 0:a56239ae90c2 | 82 | if (temp_opcode == ERR) |
acesrobertm | 0:a56239ae90c2 | 83 | { |
acesrobertm | 0:a56239ae90c2 | 84 | printf(" TFTP Error: %u, %s\n", temp_block, chunk + 4); |
acesrobertm | 0:a56239ae90c2 | 85 | return_value = -2; // Error response from server. |
acesrobertm | 0:a56239ae90c2 | 86 | } |
acesrobertm | 0:a56239ae90c2 | 87 | else if (temp_opcode == DATA) |
acesrobertm | 0:a56239ae90c2 | 88 | { |
acesrobertm | 0:a56239ae90c2 | 89 | if (temp_block == m_block_number) |
acesrobertm | 0:a56239ae90c2 | 90 | { |
acesrobertm | 0:a56239ae90c2 | 91 | int chunk_size = m_bytes_received - 4; |
acesrobertm | 0:a56239ae90c2 | 92 | // Debug output for incoming chunks of data. |
acesrobertm | 0:a56239ae90c2 | 93 | //printf(" TFTP Chunk Received: %u\n", chunk_size); |
acesrobertm | 0:a56239ae90c2 | 94 | //fwrite(chunk, 1, m_bytes_received, stdout); |
acesrobertm | 0:a56239ae90c2 | 95 | |
acesrobertm | 0:a56239ae90c2 | 96 | // Strip the TFTP info from the beginning of the data buffer. |
acesrobertm | 0:a56239ae90c2 | 97 | memcpy(m_data + m_next_data_byte_index, chunk + 4, chunk_size); |
acesrobertm | 0:a56239ae90c2 | 98 | m_next_data_byte_index += chunk_size; |
acesrobertm | 0:a56239ae90c2 | 99 | // Terminate the data string. |
acesrobertm | 0:a56239ae90c2 | 100 | m_data[m_next_data_byte_index] = 0; |
acesrobertm | 0:a56239ae90c2 | 101 | |
acesrobertm | 0:a56239ae90c2 | 102 | // Send an ACK for the current data block |
acesrobertm | 0:a56239ae90c2 | 103 | uint16_t tftp_opcode = htons(ACK); |
acesrobertm | 0:a56239ae90c2 | 104 | temp_block = htons(temp_block); |
acesrobertm | 0:a56239ae90c2 | 105 | memcpy(chunk, &tftp_opcode, 2); |
acesrobertm | 0:a56239ae90c2 | 106 | memcpy(chunk + 2, &temp_block, 2); |
acesrobertm | 0:a56239ae90c2 | 107 | int m_bytes_sent = m_sock.sendto(*m_tftp_addr, chunk, 4); // Send |
acesrobertm | 0:a56239ae90c2 | 108 | |
acesrobertm | 0:a56239ae90c2 | 109 | m_block_number++; |
acesrobertm | 0:a56239ae90c2 | 110 | } |
acesrobertm | 0:a56239ae90c2 | 111 | else |
acesrobertm | 0:a56239ae90c2 | 112 | { |
acesrobertm | 0:a56239ae90c2 | 113 | return_value = -3; // Incorrect data block number. |
acesrobertm | 0:a56239ae90c2 | 114 | m_download_in_progress = false; |
acesrobertm | 0:a56239ae90c2 | 115 | } |
acesrobertm | 0:a56239ae90c2 | 116 | } |
acesrobertm | 0:a56239ae90c2 | 117 | else |
acesrobertm | 0:a56239ae90c2 | 118 | { |
acesrobertm | 0:a56239ae90c2 | 119 | return_value = -4; // Wrong opcode |
acesrobertm | 0:a56239ae90c2 | 120 | m_download_in_progress = false; |
acesrobertm | 0:a56239ae90c2 | 121 | } |
acesrobertm | 0:a56239ae90c2 | 122 | |
acesrobertm | 0:a56239ae90c2 | 123 | if (m_bytes_received != TFTP_MAX_PACKET_SIZE) |
acesrobertm | 0:a56239ae90c2 | 124 | { |
acesrobertm | 0:a56239ae90c2 | 125 | m_download_in_progress = false; |
acesrobertm | 0:a56239ae90c2 | 126 | |
acesrobertm | 0:a56239ae90c2 | 127 | if (m_bytes_received > 0) |
acesrobertm | 0:a56239ae90c2 | 128 | { |
acesrobertm | 0:a56239ae90c2 | 129 | // Finished download. |
acesrobertm | 0:a56239ae90c2 | 130 | return_value = 1; |
acesrobertm | 0:a56239ae90c2 | 131 | } |
acesrobertm | 0:a56239ae90c2 | 132 | } |
acesrobertm | 0:a56239ae90c2 | 133 | } |
acesrobertm | 0:a56239ae90c2 | 134 | } |
acesrobertm | 0:a56239ae90c2 | 135 | |
acesrobertm | 0:a56239ae90c2 | 136 | if (!m_download_in_progress) |
acesrobertm | 0:a56239ae90c2 | 137 | { |
acesrobertm | 0:a56239ae90c2 | 138 | m_sock.close(); |
acesrobertm | 0:a56239ae90c2 | 139 | } |
acesrobertm | 0:a56239ae90c2 | 140 | |
acesrobertm | 0:a56239ae90c2 | 141 | return return_value; |
acesrobertm | 0:a56239ae90c2 | 142 | } |
acesrobertm | 0:a56239ae90c2 | 143 |