mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-16 06:58:14 +08:00
修复mico-sdk错误
This commit is contained in:
@@ -1,213 +1,213 @@
|
||||
/**
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mico.h"
|
||||
#include "tftp.h"
|
||||
#include "CheckSumUtils.h"
|
||||
#include "mico_system.h"
|
||||
|
||||
|
||||
#define DEFAULT_OTA_AP "MICO_OTA_AP"
|
||||
#define DEFAULT_OTA_NETMASK "255.0.0.0"
|
||||
#define DEFAULT_OTA_SERVER "10.0.0.2"
|
||||
#define UDP_PORT 20000
|
||||
#define TCP_PORT 30000
|
||||
|
||||
#define fota_log(M, ...) custom_log("Force OTA", M, ##__VA_ARGS__)
|
||||
#define fota_log_trace() custom_log_trace("Force OTA")
|
||||
|
||||
static int wifi_up = 0;
|
||||
extern void mico_write_ota_tbl(int len, uint16_t crc);
|
||||
|
||||
|
||||
void wlan_get_mac_address( uint8_t *mac );
|
||||
|
||||
enum {
|
||||
OTA_SUCCESS = 0,
|
||||
OTA_NO_AP = -1,
|
||||
OTA_NO_FILE = -2,
|
||||
OTA_MD5_FAIL = -3,
|
||||
OTA_NO_MEM = -4,
|
||||
};
|
||||
/* Call back for OTA finished */
|
||||
WEAK void mico_ota_finished(int result, uint8_t *reserved)
|
||||
{
|
||||
switch(result) {
|
||||
case OTA_SUCCESS:
|
||||
printf("OTA SUCCESS. Rebooting...\r\n");
|
||||
MicoSystemReboot();
|
||||
break;
|
||||
case OTA_NO_AP:
|
||||
printf("OTA FAIL. Can't find the OTA AP\r\n");
|
||||
break;
|
||||
case OTA_NO_FILE:
|
||||
printf("OTA FAIL. Can't find the OTA image\r\n");
|
||||
break;
|
||||
case OTA_MD5_FAIL:
|
||||
printf("OTA FAIL. MD5 check failed\r\n");
|
||||
break;
|
||||
case OTA_NO_MEM:
|
||||
printf("OTA FAIL. Don't have enough memory\r\n");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FOTA_WifiStatusHandler(WiFiEvent event, void * arg)
|
||||
{
|
||||
UNUSED_PARAMETER(arg);
|
||||
switch (event) {
|
||||
case NOTIFY_STATION_UP:
|
||||
wifi_up = 1;
|
||||
break;
|
||||
case NOTIFY_STATION_DOWN:
|
||||
wifi_up = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect to AP: ssid="mico_ota_ap", security=OPEN.
|
||||
* Broadcast to find OTA server
|
||||
* Connect to OTA server, request to OTA.
|
||||
*/
|
||||
void tftp_ota(void)
|
||||
{
|
||||
network_InitTypeDef_st conf;
|
||||
tftp_file_info_t fileinfo;
|
||||
uint32_t ipaddr = inet_addr(DEFAULT_OTA_SERVER), flashaddr;
|
||||
int filelen, maxretry = 5, len, left, i = 0;
|
||||
uint8_t md5_recv[16];
|
||||
uint8_t md5_calc[16];
|
||||
uint8_t *tmpbuf;
|
||||
md5_context ctx;
|
||||
uint8_t mac[6], sta_ip_addr[16];
|
||||
mico_logic_partition_t* ota_partition = MicoFlashGetInfo( MICO_PARTITION_OTA_TEMP );
|
||||
uint16_t crc = 0;
|
||||
CRC16_Context contex;
|
||||
|
||||
#define TMP_BUF_LEN 1024
|
||||
|
||||
fota_log("Start OTA");
|
||||
mico_system_notify_remove_all(mico_notify_WIFI_STATUS_CHANGED);
|
||||
mico_system_notify_remove_all(mico_notify_WiFI_PARA_CHANGED);
|
||||
mico_system_notify_remove_all(mico_notify_DHCP_COMPLETED);
|
||||
mico_system_notify_remove_all(mico_notify_WIFI_CONNECT_FAILED);
|
||||
mico_system_notify_remove_all(mico_notify_EASYLINK_WPS_COMPLETED);
|
||||
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *)FOTA_WifiStatusHandler, NULL );
|
||||
micoWlanStopEasyLink();
|
||||
micoWlanStopEasyLinkPlus();
|
||||
micoWlanStopAirkiss();
|
||||
mico_rtos_thread_msleep(10);
|
||||
|
||||
tmpbuf = (uint8_t*)malloc(TMP_BUF_LEN);
|
||||
if (tmpbuf == NULL) {
|
||||
fota_log("ERROR!! Can't get enough memory");
|
||||
mico_ota_finished(OTA_NO_MEM, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_get_mac_address(mac);
|
||||
|
||||
sprintf((char *)sta_ip_addr, "10.%d.%d.%d",
|
||||
mac[3], mac[4], mac[5]);
|
||||
|
||||
fota_log("Staic IP = %s", sta_ip_addr);
|
||||
|
||||
memset(&conf, 0, sizeof(network_InitTypeDef_st));
|
||||
|
||||
conf.wifi_mode = Station;
|
||||
strcpy(conf.wifi_ssid, DEFAULT_OTA_AP);
|
||||
|
||||
conf.dhcpMode = DHCP_Disable;
|
||||
strcpy(conf.net_mask, DEFAULT_OTA_NETMASK);
|
||||
strcpy(conf.local_ip_addr, (char *)sta_ip_addr);
|
||||
|
||||
wifi_up = 0;
|
||||
fota_log("Connect to AP %s...", DEFAULT_OTA_AP);
|
||||
micoWlanStart(&conf);
|
||||
|
||||
while(wifi_up == 0) {
|
||||
mico_rtos_thread_msleep(100);
|
||||
i++;
|
||||
if (i > 100) {
|
||||
fota_log("ERROR!! Can't find the OTA AP");
|
||||
mico_ota_finished(OTA_NO_AP, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fota_log("AP connected, tftp download image... to 0x%lx", ota_partition->partition_start_addr);
|
||||
|
||||
fileinfo.filelen = ota_partition->partition_length;
|
||||
fileinfo.flashaddr = 0;
|
||||
fileinfo.flashtype = MICO_PARTITION_OTA_TEMP;
|
||||
strcpy(fileinfo.filename, "mico_ota.bin");
|
||||
|
||||
while((filelen = tget (&fileinfo, ipaddr)) < 0) {
|
||||
fota_log("tget return filelen %d, maxretry %d", filelen, maxretry);
|
||||
maxretry--;
|
||||
if (maxretry < 0) {
|
||||
fota_log("ERROR!! Can't get OTA image.");
|
||||
free(tmpbuf);
|
||||
mico_ota_finished(OTA_NO_FILE, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
filelen -= 16; // remove md5.
|
||||
fota_log("tftp download image finished, OTA bin len %d", filelen);
|
||||
flashaddr = filelen;
|
||||
MicoFlashRead(MICO_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)md5_recv, 16);
|
||||
InitMd5( &ctx );
|
||||
CRC16_Init( &contex );
|
||||
flashaddr = 0;
|
||||
left = filelen;
|
||||
while(left > 0) {
|
||||
if (left > TMP_BUF_LEN) {
|
||||
len = TMP_BUF_LEN;
|
||||
} else {
|
||||
len = left;
|
||||
}
|
||||
left -= len;
|
||||
MicoFlashRead(MICO_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)tmpbuf, len);
|
||||
Md5Update( &ctx, (uint8_t *)tmpbuf, len);
|
||||
CRC16_Update( &contex, tmpbuf, len );
|
||||
}
|
||||
Md5Final( &ctx, md5_calc );
|
||||
CRC16_Final( &contex, &crc );
|
||||
|
||||
if(memcmp(md5_calc, md5_recv, 16) != 0) {
|
||||
fota_log("ERROR!! MD5 Error.");
|
||||
fota_log("RX: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
md5_recv[0],md5_recv[1],md5_recv[2],md5_recv[3],
|
||||
md5_recv[4],md5_recv[5],md5_recv[6],md5_recv[7],
|
||||
md5_recv[8],md5_recv[9],md5_recv[10],md5_recv[11],
|
||||
md5_recv[12],md5_recv[13],md5_recv[14],md5_recv[15]);
|
||||
fota_log("Need: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
md5_calc[0],md5_calc[1],md5_calc[2],md5_calc[3],
|
||||
md5_calc[4],md5_calc[5],md5_calc[6],md5_calc[7],
|
||||
md5_calc[8],md5_calc[9],md5_calc[10],md5_calc[11],
|
||||
md5_calc[12],md5_calc[13],md5_calc[14],md5_calc[15]);
|
||||
mico_ota_finished(OTA_MD5_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
fota_log("OTA bin md5 check success, CRC %x. upgrading...", crc);
|
||||
mico_ota_switch_to_new_fw( filelen, crc );
|
||||
mico_ota_finished(OTA_SUCCESS, NULL);
|
||||
while(1)
|
||||
mico_rtos_thread_sleep(100);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mico.h"
|
||||
#include "tftp.h"
|
||||
#include "CheckSumUtils.h"
|
||||
#include "mico_system.h"
|
||||
|
||||
|
||||
#define DEFAULT_OTA_AP "MICO_OTA_AP"
|
||||
#define DEFAULT_OTA_NETMASK "255.0.0.0"
|
||||
#define DEFAULT_OTA_SERVER "10.0.0.2"
|
||||
#define UDP_PORT 20000
|
||||
#define TCP_PORT 30000
|
||||
|
||||
#define fota_log(M, ...) custom_log("Force OTA", M, ##__VA_ARGS__)
|
||||
#define fota_log_trace() custom_log_trace("Force OTA")
|
||||
|
||||
static int wifi_up = 0;
|
||||
extern void mico_write_ota_tbl(int len, uint16_t crc);
|
||||
|
||||
|
||||
void wlan_get_mac_address( uint8_t *mac );
|
||||
|
||||
enum {
|
||||
OTA_SUCCESS = 0,
|
||||
OTA_NO_AP = -1,
|
||||
OTA_NO_FILE = -2,
|
||||
OTA_MD5_FAIL = -3,
|
||||
OTA_NO_MEM = -4,
|
||||
};
|
||||
/* Call back for OTA finished */
|
||||
WEAK void mico_ota_finished(int result, uint8_t *reserved)
|
||||
{
|
||||
switch(result) {
|
||||
case OTA_SUCCESS:
|
||||
printf("OTA SUCCESS. Rebooting...\r\n");
|
||||
MicoSystemReboot();
|
||||
break;
|
||||
case OTA_NO_AP:
|
||||
printf("OTA FAIL. Can't find the OTA AP\r\n");
|
||||
break;
|
||||
case OTA_NO_FILE:
|
||||
printf("OTA FAIL. Can't find the OTA image\r\n");
|
||||
break;
|
||||
case OTA_MD5_FAIL:
|
||||
printf("OTA FAIL. MD5 check failed\r\n");
|
||||
break;
|
||||
case OTA_NO_MEM:
|
||||
printf("OTA FAIL. Don't have enough memory\r\n");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FOTA_WifiStatusHandler(WiFiEvent event, void * arg)
|
||||
{
|
||||
UNUSED_PARAMETER(arg);
|
||||
switch (event) {
|
||||
case NOTIFY_STATION_UP:
|
||||
wifi_up = 1;
|
||||
break;
|
||||
case NOTIFY_STATION_DOWN:
|
||||
wifi_up = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect to AP: ssid="mico_ota_ap", security=OPEN.
|
||||
* Broadcast to find OTA server
|
||||
* Connect to OTA server, request to OTA.
|
||||
*/
|
||||
void tftp_ota(void)
|
||||
{
|
||||
network_InitTypeDef_st conf;
|
||||
tftp_file_info_t fileinfo;
|
||||
uint32_t ipaddr = inet_addr(DEFAULT_OTA_SERVER), flashaddr;
|
||||
int filelen, maxretry = 5, len, left, i = 0;
|
||||
uint8_t md5_recv[16];
|
||||
uint8_t md5_calc[16];
|
||||
uint8_t *tmpbuf;
|
||||
md5_context ctx;
|
||||
uint8_t mac[6], sta_ip_addr[16];
|
||||
mico_logic_partition_t* ota_partition = MicoFlashGetInfo( MICO_PARTITION_OTA_TEMP );
|
||||
uint16_t crc = 0;
|
||||
CRC16_Context contex;
|
||||
|
||||
#define TMP_BUF_LEN 1024
|
||||
|
||||
fota_log("Start OTA");
|
||||
mico_system_notify_remove_all(mico_notify_WIFI_STATUS_CHANGED);
|
||||
mico_system_notify_remove_all(mico_notify_WiFI_PARA_CHANGED);
|
||||
mico_system_notify_remove_all(mico_notify_DHCP_COMPLETED);
|
||||
mico_system_notify_remove_all(mico_notify_WIFI_CONNECT_FAILED);
|
||||
mico_system_notify_remove_all(mico_notify_EASYLINK_WPS_COMPLETED);
|
||||
mico_system_notify_register( mico_notify_WIFI_STATUS_CHANGED, (void *)FOTA_WifiStatusHandler, NULL );
|
||||
micoWlanStopEasyLink();
|
||||
micoWlanStopEasyLinkPlus();
|
||||
micoWlanStopAirkiss();
|
||||
mico_rtos_thread_msleep(10);
|
||||
|
||||
tmpbuf = (uint8_t*)malloc(TMP_BUF_LEN);
|
||||
if (tmpbuf == NULL) {
|
||||
fota_log("ERROR!! Can't get enough memory");
|
||||
mico_ota_finished(OTA_NO_MEM, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
wlan_get_mac_address(mac);
|
||||
|
||||
sprintf((char *)sta_ip_addr, "10.%d.%d.%d",
|
||||
mac[3], mac[4], mac[5]);
|
||||
|
||||
fota_log("Staic IP = %s", sta_ip_addr);
|
||||
|
||||
memset(&conf, 0, sizeof(network_InitTypeDef_st));
|
||||
|
||||
conf.wifi_mode = Station;
|
||||
strcpy(conf.wifi_ssid, DEFAULT_OTA_AP);
|
||||
|
||||
conf.dhcpMode = DHCP_Disable;
|
||||
strcpy(conf.net_mask, DEFAULT_OTA_NETMASK);
|
||||
strcpy(conf.local_ip_addr, (char *)sta_ip_addr);
|
||||
|
||||
wifi_up = 0;
|
||||
fota_log("Connect to AP %s...", DEFAULT_OTA_AP);
|
||||
micoWlanStart(&conf);
|
||||
|
||||
while(wifi_up == 0) {
|
||||
mico_rtos_thread_msleep(100);
|
||||
i++;
|
||||
if (i > 100) {
|
||||
fota_log("ERROR!! Can't find the OTA AP");
|
||||
mico_ota_finished(OTA_NO_AP, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fota_log("AP connected, tftp download image... to 0x%lx", ota_partition->partition_start_addr);
|
||||
|
||||
fileinfo.filelen = ota_partition->partition_length;
|
||||
fileinfo.flashaddr = 0;
|
||||
fileinfo.flashtype = MICO_PARTITION_OTA_TEMP;
|
||||
strcpy(fileinfo.filename, "mico_ota.bin");
|
||||
|
||||
while((filelen = tget (&fileinfo, ipaddr)) < 0) {
|
||||
fota_log("tget return filelen %d, maxretry %d", filelen, maxretry);
|
||||
maxretry--;
|
||||
if (maxretry < 0) {
|
||||
fota_log("ERROR!! Can't get OTA image.");
|
||||
free(tmpbuf);
|
||||
mico_ota_finished(OTA_NO_FILE, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
filelen -= 16; // remove md5.
|
||||
fota_log("tftp download image finished, OTA bin len %d", filelen);
|
||||
flashaddr = filelen;
|
||||
MicoFlashRead(MICO_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)md5_recv, 16);
|
||||
InitMd5( &ctx );
|
||||
CRC16_Init( &contex );
|
||||
flashaddr = 0;
|
||||
left = filelen;
|
||||
while(left > 0) {
|
||||
if (left > TMP_BUF_LEN) {
|
||||
len = TMP_BUF_LEN;
|
||||
} else {
|
||||
len = left;
|
||||
}
|
||||
left -= len;
|
||||
MicoFlashRead(MICO_PARTITION_OTA_TEMP, &flashaddr, (uint8_t *)tmpbuf, len);
|
||||
Md5Update( &ctx, (uint8_t *)tmpbuf, len);
|
||||
CRC16_Update( &contex, tmpbuf, len );
|
||||
}
|
||||
Md5Final( &ctx, md5_calc );
|
||||
CRC16_Final( &contex, &crc );
|
||||
|
||||
if(memcmp(md5_calc, md5_recv, 16) != 0) {
|
||||
fota_log("ERROR!! MD5 Error.");
|
||||
fota_log("RX: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
md5_recv[0],md5_recv[1],md5_recv[2],md5_recv[3],
|
||||
md5_recv[4],md5_recv[5],md5_recv[6],md5_recv[7],
|
||||
md5_recv[8],md5_recv[9],md5_recv[10],md5_recv[11],
|
||||
md5_recv[12],md5_recv[13],md5_recv[14],md5_recv[15]);
|
||||
fota_log("Need: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
md5_calc[0],md5_calc[1],md5_calc[2],md5_calc[3],
|
||||
md5_calc[4],md5_calc[5],md5_calc[6],md5_calc[7],
|
||||
md5_calc[8],md5_calc[9],md5_calc[10],md5_calc[11],
|
||||
md5_calc[12],md5_calc[13],md5_calc[14],md5_calc[15]);
|
||||
mico_ota_finished(OTA_MD5_FAIL, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
fota_log("OTA bin md5 check success, CRC %x. upgrading...", crc);
|
||||
mico_ota_switch_to_new_fw( filelen, crc );
|
||||
mico_ota_finished(OTA_SUCCESS, NULL);
|
||||
while(1)
|
||||
mico_rtos_thread_sleep(100);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/**
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Download a new firmware and update from TFTP server use a predefined ssid, key, ip address */
|
||||
void tftp_ota(void);
|
||||
/**
|
||||
* UNPUBLISHED PROPRIETARY SOURCE CODE
|
||||
* Copyright (c) 2016 MXCHIP Inc.
|
||||
*
|
||||
* The contents of this file may not be disclosed to third parties, copied or
|
||||
* duplicated in any form, in whole or in part, without the prior written
|
||||
* permission of MXCHIP Corporation.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* Download a new firmware and update from TFTP server use a predefined ssid, key, ip address */
|
||||
void tftp_ota(void);
|
||||
|
||||
@@ -1,495 +1,495 @@
|
||||
/**********************************************************
|
||||
Date: NOV 28th, 2006
|
||||
Project : TFTP Client
|
||||
Programers:
|
||||
Jonathan Felske
|
||||
Andrew Fullard
|
||||
Craig Holmes
|
||||
Reza Rahmanian
|
||||
Adam Tomalty
|
||||
File: TFTP Client (main)
|
||||
Purpose: A TFTP client that will request a connections from
|
||||
the server and transefet files.
|
||||
Notes: Here we are using the sendto and recvfrom
|
||||
functions so the server and client can exchange data.
|
||||
***********************************************************/
|
||||
|
||||
#include "tftp.h"
|
||||
|
||||
static const char err_msg [7][40] = {"Not defined, see error message if any",
|
||||
"File not fount",
|
||||
"Access Violation",
|
||||
"Disk full, or allocation exceeded",
|
||||
"Illegal TFTP operation",
|
||||
"Unknown transfer ID",
|
||||
"File already exists"};
|
||||
|
||||
/*a function to create the request packet, read or write*/
|
||||
static int req_packet (int opcode, char *filename, char *mode, unsigned char buf[]);
|
||||
/*a function to creat an ACK packet*/
|
||||
//static int ack_packet (int block, char buf[]);
|
||||
/*a function to create the Error packets*/
|
||||
static int err_packet (int err_code, const char *err_msg, unsigned char buf[]);
|
||||
|
||||
/* A function that will create a request packet*/
|
||||
/*I'm not sure if I need the last 0x00 because sprintf will end the string with \0*/
|
||||
static int
|
||||
req_packet (int opcode, char *filename, char *mode, unsigned char buf[])
|
||||
{
|
||||
int i = 0, len;
|
||||
|
||||
buf[i++] = 0x00;
|
||||
buf[i++] = (char)opcode;
|
||||
len = strlen(filename);
|
||||
memcpy(&buf[i], filename, len);
|
||||
i+=len;
|
||||
buf[i++] = 0x00;
|
||||
len = strlen(mode);
|
||||
memcpy(&buf[i], mode, len);
|
||||
i+=len;
|
||||
buf[i++] = 0x00;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* A function that will create an ACK packet*/
|
||||
/*problem that we will have here is that we can only get up to 255 blocks*/
|
||||
/*
|
||||
static int
|
||||
ack_packet (int block, char buf[])
|
||||
{
|
||||
buf[0] = 0x00;
|
||||
buf[1] = ACK;
|
||||
buf[2] = (block & 0xFF00) >> 8;
|
||||
buf[3] = (block & 0x00FF);
|
||||
|
||||
return 4;
|
||||
}
|
||||
*/
|
||||
|
||||
/* A function that will create an error packet based on the error code*/
|
||||
static int
|
||||
err_packet (int err_code, const char *err_msg, unsigned char buf[])
|
||||
{
|
||||
int i = 0;
|
||||
int len;
|
||||
|
||||
len = strlen(err_msg);
|
||||
memset (buf, 0, 5 + len);
|
||||
buf[i++] = 0x00;
|
||||
buf[i++] = ERR;
|
||||
buf[i++] = 0x00;
|
||||
buf[i++] = err_code;
|
||||
memcpy(&buf[i], err_msg, len);
|
||||
i+=len;
|
||||
buf[i++] = 0x00;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*This function is called when the client would like to upload a file to the server.
|
||||
*/
|
||||
int tsend (tftp_file_info_t *fileinfo, uint32_t ipaddr)
|
||||
{
|
||||
int len, server_len, opcode= WRQ, ssize = 0, n, i, j, tid;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
unsigned char filebuf[MAXDATASIZE + 1];
|
||||
unsigned char packetbuf[MAXDATASIZE + 12],
|
||||
recvbuf[MAXDATASIZE + 12];
|
||||
char *bufindex; //fullpath[196],
|
||||
struct sockaddr_in ack;
|
||||
int sock;
|
||||
uint32_t flashaddr = fileinfo->flashaddr;
|
||||
struct sockaddr_in server;
|
||||
unsigned short int ackfreq = 1;
|
||||
int errno;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = ipaddr;
|
||||
server.sin_port = htons((uint16_t)69);
|
||||
|
||||
/*Create the socket, a -1 will show us an error */
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (filebuf, 0, MAXDATASIZE); /*clear the buffer */
|
||||
/* this is the first request message */
|
||||
len = req_packet (opcode, fileinfo->filename, "octet", filebuf);
|
||||
server_len = sizeof(struct sockaddr);
|
||||
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, server_len) !=
|
||||
len)
|
||||
{
|
||||
close(sock);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*At this point I have to wait to recieve an ACK from the server before I start sending the file*/
|
||||
/*open the file to read */
|
||||
//get ACK for WRQ
|
||||
/* The following 'for' loop is used to recieve/timeout ACKs */
|
||||
for (j = 0; j < RETRIES - 2; j++)
|
||||
{
|
||||
server_len = sizeof (ack);
|
||||
errno = EAGAIN;
|
||||
n = -1;
|
||||
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
|
||||
{
|
||||
n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &ack, (socklen_t *) & server_len);
|
||||
mico_rtos_delay_milliseconds(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tid = (ack.sin_port); //get the tid of the server.
|
||||
server.sin_port = (tid); //set the tid for rest of the transfer
|
||||
|
||||
if (n < 0) {
|
||||
|
||||
}
|
||||
else
|
||||
{ /*changed client to server here */
|
||||
if (server.sin_addr.s_addr != ack.sin_addr.s_addr ) /* checks to ensure send to ip is same from ACK IP */
|
||||
{
|
||||
j--; /* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
|
||||
continue;
|
||||
}
|
||||
if (tid != (server.sin_port)) /* checks to ensure get from the correct TID */
|
||||
{
|
||||
len = err_packet (5, err_msg[5], filebuf);
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) recvbuf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00) {
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
if (opcode != 4 || rcount != count) /* ack packet should have code 4 (ack) and should be acking the packet we just sent */
|
||||
{
|
||||
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
|
||||
len = err_packet (4, err_msg[4], filebuf);
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
}
|
||||
/* from here we will loop back and resend */
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} //end of else
|
||||
|
||||
}
|
||||
/* The ack sending 'for' loop ends here */
|
||||
|
||||
|
||||
|
||||
memset (filebuf, 0, sizeof (filebuf)); //clear the filebuf
|
||||
while (1) /* our break statement will escape us when we are done */
|
||||
{
|
||||
//acked = 0;
|
||||
if (fileinfo->filelen > MAXDATASIZE)
|
||||
ssize = MAXDATASIZE;
|
||||
else
|
||||
ssize = fileinfo->filelen;
|
||||
fileinfo->filelen -= ssize;
|
||||
MicoFlashRead(fileinfo->flashtype, &flashaddr, (uint8_t *)filebuf, ssize);
|
||||
|
||||
|
||||
count++; /* count number of datasize byte portions we read from the file */
|
||||
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x03;
|
||||
packetbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
packetbuf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
memcpy ((char *) packetbuf + 4, filebuf, ssize);
|
||||
len = 4 + ssize;
|
||||
/* send the data packet */
|
||||
if (sendto
|
||||
(sock, packetbuf, len, 0, (struct sockaddr *) &server,
|
||||
sizeof (server)) != len)
|
||||
{
|
||||
close(sock);
|
||||
return -3;
|
||||
}
|
||||
//if ((count - 1) == 0 || ((count - 1) % ackfreq) == 0 || ssize != datasize)
|
||||
if (((count) % ackfreq) == 0 || ssize != MAXDATASIZE)
|
||||
{
|
||||
/* The following 'for' loop is used to recieve/timeout ACKs */
|
||||
for (j = 0; j < RETRIES; j++)
|
||||
{
|
||||
server_len = sizeof (ack);
|
||||
errno = EAGAIN;
|
||||
n = -1;
|
||||
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
|
||||
{
|
||||
n =
|
||||
recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &ack,
|
||||
(socklen_t *) & server_len);
|
||||
mico_rtos_delay_milliseconds(1);
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
|
||||
}
|
||||
else
|
||||
{ /* checks to ensure send to ip is same from ACK IP */
|
||||
if (server.sin_addr.s_addr != ack.sin_addr.s_addr )
|
||||
{
|
||||
/* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
if (tid != (server.sin_port)) /* checks to ensure get from the correct TID */
|
||||
{
|
||||
len = err_packet (5, err_msg[5], filebuf);
|
||||
/* send the data packet */
|
||||
if (sendto
|
||||
(sock, filebuf, len, 0, (struct sockaddr *) &server,
|
||||
sizeof (server)) != len)
|
||||
{
|
||||
}
|
||||
j--;
|
||||
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) recvbuf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00) {
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
if (opcode != 4 || rcount != count) /* ack packet should have code 4 (ack) and should be acking the packet we just sent */
|
||||
{
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
len = err_packet (4, err_msg[4], filebuf);
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
}
|
||||
/* from here we will loop back and resend */
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* resend the data packet */
|
||||
{
|
||||
close(sock);
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/* The ack sending 'for' loop ends here */
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (j == RETRIES)
|
||||
{
|
||||
close(sock);
|
||||
return -5;
|
||||
}
|
||||
if (ssize != MAXDATASIZE)
|
||||
break;
|
||||
|
||||
memset (filebuf, 0, sizeof (filebuf)); /* fill the filebuf with zeros so that when the fread fills it, it is a null terminated string */
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return 0;
|
||||
} //end of tsend function
|
||||
|
||||
|
||||
/*
|
||||
*This function is called when the client would like to download a file from the server. Return the downloaded file length
|
||||
*/
|
||||
int
|
||||
tget (tftp_file_info_t *fileinfo, uint32_t ipaddr)
|
||||
{
|
||||
/* local variables */
|
||||
int len, server_len, opcode = RRQ, i, j, n, tid = 0, flag = 1;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
unsigned char filebuf[MAXDATASIZE + 12];
|
||||
unsigned char packetbuf[128];
|
||||
int errno;
|
||||
char *bufindex;
|
||||
struct sockaddr_in data;
|
||||
int sock;
|
||||
uint32_t flashaddr = fileinfo->flashaddr;
|
||||
struct sockaddr_in server;
|
||||
//unsigned short int ackfreq = 1;
|
||||
int totalen = 0;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = ipaddr;
|
||||
server.sin_port = htons((uint16_t)69);
|
||||
|
||||
/*Create the socket, a -1 will show us an error */
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
MicoFlashErase(fileinfo->flashtype,fileinfo->flashaddr,fileinfo->filelen);
|
||||
|
||||
memset (packetbuf, 0, sizeof(packetbuf)); /*clear the buffer */
|
||||
/* this is the first request message */
|
||||
len = req_packet (opcode, fileinfo->filename, "octet", packetbuf);
|
||||
server_len = sizeof(struct sockaddr);
|
||||
|
||||
sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, server_len);
|
||||
n = MAXDATASIZE + 4;
|
||||
do
|
||||
{
|
||||
/* zero buffers so if there are any errors only NULLs will be exposed */
|
||||
memset (filebuf, 0, sizeof (filebuf));
|
||||
|
||||
|
||||
for (j = 0; j < RETRIES; j++) /* this allows us to loop until we either break out by getting the correct ack OR time out because we've looped more than RETRIES times */
|
||||
{
|
||||
server_len = sizeof (data);
|
||||
errno = EAGAIN; /* this allows us to enter the loop */
|
||||
n = -1;
|
||||
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++) /* this for loop will just keep checking the non-blocking socket until timeout */
|
||||
{
|
||||
|
||||
n =
|
||||
recvfrom (sock, filebuf, sizeof (filebuf) - 1,
|
||||
MSG_DONTWAIT, (struct sockaddr *) &data,
|
||||
(socklen_t *) & server_len);
|
||||
mico_rtos_delay_milliseconds(1);
|
||||
}
|
||||
if (!tid)
|
||||
{
|
||||
tid = (data.sin_port); //get the tid of the server.
|
||||
server.sin_port = (tid); //set the tid for rest of the transfer
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, server_len);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (server.sin_addr.s_addr != data.sin_addr.s_addr) /* checks to ensure get from ip is same from ACK IP */
|
||||
{
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
if (tid != (server.sin_port)) /* checks to ensure get from the correct TID */
|
||||
{
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x05;
|
||||
packetbuf[2] = 0x00;
|
||||
packetbuf[3] = 0x05;
|
||||
len = strlen("Bad/Unknown TID");
|
||||
memcpy(&packetbuf[4], "Bad/Unknown TID", len);
|
||||
len += 4;
|
||||
packetbuf[len++] = 0x00;
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) filebuf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00) {
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
if (flag)
|
||||
{
|
||||
flag = 0;
|
||||
}
|
||||
if (opcode != 3) /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
|
||||
{
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x05;
|
||||
packetbuf[2] = 0x00;
|
||||
packetbuf[3] = 0x04;
|
||||
len = strlen("Illegal operation");
|
||||
memcpy(&packetbuf[4], "Illegal operation", len);
|
||||
len += 4;
|
||||
packetbuf[len++] = 0x00;
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count + 1 == rcount) {// received right seq no, save and ack
|
||||
MicoFlashWrite(fileinfo->flashtype, &flashaddr, (uint8_t *)bufindex, n - 4);
|
||||
totalen += n-4;
|
||||
}
|
||||
|
||||
len = 4;
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x04;
|
||||
packetbuf[2] = (rcount & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
packetbuf[3] = (rcount & 0x00FF); //fill in the lower part of the count
|
||||
count = rcount;
|
||||
|
||||
|
||||
sendto(sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server));
|
||||
break;
|
||||
} //end of else
|
||||
}
|
||||
}
|
||||
if (j == RETRIES)
|
||||
{
|
||||
close(sock);
|
||||
return -4;
|
||||
}
|
||||
if (n != (MAXDATASIZE + 4)) /* remember if our datasize is less than a full packet this was the last packet to be received */
|
||||
{
|
||||
goto done; /* gotos are not optimal, but a good solution when exiting a multi-layer loop */
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
done:
|
||||
|
||||
close(sock);
|
||||
return totalen;
|
||||
}
|
||||
/**********************************************************
|
||||
Date: NOV 28th, 2006
|
||||
Project : TFTP Client
|
||||
Programers:
|
||||
Jonathan Felske
|
||||
Andrew Fullard
|
||||
Craig Holmes
|
||||
Reza Rahmanian
|
||||
Adam Tomalty
|
||||
File: TFTP Client (main)
|
||||
Purpose: A TFTP client that will request a connections from
|
||||
the server and transefet files.
|
||||
Notes: Here we are using the sendto and recvfrom
|
||||
functions so the server and client can exchange data.
|
||||
***********************************************************/
|
||||
|
||||
#include "tftp.h"
|
||||
|
||||
static const char err_msg [7][40] = {"Not defined, see error message if any",
|
||||
"File not fount",
|
||||
"Access Violation",
|
||||
"Disk full, or allocation exceeded",
|
||||
"Illegal TFTP operation",
|
||||
"Unknown transfer ID",
|
||||
"File already exists"};
|
||||
|
||||
/*a function to create the request packet, read or write*/
|
||||
static int req_packet (int opcode, char *filename, char *mode, unsigned char buf[]);
|
||||
/*a function to creat an ACK packet*/
|
||||
//static int ack_packet (int block, char buf[]);
|
||||
/*a function to create the Error packets*/
|
||||
static int err_packet (int err_code, const char *err_msg, unsigned char buf[]);
|
||||
|
||||
/* A function that will create a request packet*/
|
||||
/*I'm not sure if I need the last 0x00 because sprintf will end the string with \0*/
|
||||
static int
|
||||
req_packet (int opcode, char *filename, char *mode, unsigned char buf[])
|
||||
{
|
||||
int i = 0, len;
|
||||
|
||||
buf[i++] = 0x00;
|
||||
buf[i++] = (char)opcode;
|
||||
len = strlen(filename);
|
||||
memcpy(&buf[i], filename, len);
|
||||
i+=len;
|
||||
buf[i++] = 0x00;
|
||||
len = strlen(mode);
|
||||
memcpy(&buf[i], mode, len);
|
||||
i+=len;
|
||||
buf[i++] = 0x00;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* A function that will create an ACK packet*/
|
||||
/*problem that we will have here is that we can only get up to 255 blocks*/
|
||||
/*
|
||||
static int
|
||||
ack_packet (int block, char buf[])
|
||||
{
|
||||
buf[0] = 0x00;
|
||||
buf[1] = ACK;
|
||||
buf[2] = (block & 0xFF00) >> 8;
|
||||
buf[3] = (block & 0x00FF);
|
||||
|
||||
return 4;
|
||||
}
|
||||
*/
|
||||
|
||||
/* A function that will create an error packet based on the error code*/
|
||||
static int
|
||||
err_packet (int err_code, const char *err_msg, unsigned char buf[])
|
||||
{
|
||||
int i = 0;
|
||||
int len;
|
||||
|
||||
len = strlen(err_msg);
|
||||
memset (buf, 0, 5 + len);
|
||||
buf[i++] = 0x00;
|
||||
buf[i++] = ERR;
|
||||
buf[i++] = 0x00;
|
||||
buf[i++] = err_code;
|
||||
memcpy(&buf[i], err_msg, len);
|
||||
i+=len;
|
||||
buf[i++] = 0x00;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*This function is called when the client would like to upload a file to the server.
|
||||
*/
|
||||
int tsend (tftp_file_info_t *fileinfo, uint32_t ipaddr)
|
||||
{
|
||||
int len, server_len, opcode= WRQ, ssize = 0, n, i, j, tid;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
unsigned char filebuf[MAXDATASIZE + 1];
|
||||
unsigned char packetbuf[MAXDATASIZE + 12],
|
||||
recvbuf[MAXDATASIZE + 12];
|
||||
char *bufindex; //fullpath[196],
|
||||
struct sockaddr_in ack;
|
||||
int sock;
|
||||
uint32_t flashaddr = fileinfo->flashaddr;
|
||||
struct sockaddr_in server;
|
||||
unsigned short int ackfreq = 1;
|
||||
int errno;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = ipaddr;
|
||||
server.sin_port = htons((uint16_t)69);
|
||||
|
||||
/*Create the socket, a -1 will show us an error */
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset (filebuf, 0, MAXDATASIZE); /*clear the buffer */
|
||||
/* this is the first request message */
|
||||
len = req_packet (opcode, fileinfo->filename, "octet", filebuf);
|
||||
server_len = sizeof(struct sockaddr);
|
||||
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, server_len) !=
|
||||
len)
|
||||
{
|
||||
close(sock);
|
||||
return -2;
|
||||
}
|
||||
|
||||
/*At this point I have to wait to recieve an ACK from the server before I start sending the file*/
|
||||
/*open the file to read */
|
||||
//get ACK for WRQ
|
||||
/* The following 'for' loop is used to recieve/timeout ACKs */
|
||||
for (j = 0; j < RETRIES - 2; j++)
|
||||
{
|
||||
server_len = sizeof (ack);
|
||||
errno = EAGAIN;
|
||||
n = -1;
|
||||
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
|
||||
{
|
||||
n = recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &ack, (socklen_t *) & server_len);
|
||||
mico_rtos_delay_milliseconds(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tid = (ack.sin_port); //get the tid of the server.
|
||||
server.sin_port = (tid); //set the tid for rest of the transfer
|
||||
|
||||
if (n < 0) {
|
||||
|
||||
}
|
||||
else
|
||||
{ /*changed client to server here */
|
||||
if (server.sin_addr.s_addr != ack.sin_addr.s_addr ) /* checks to ensure send to ip is same from ACK IP */
|
||||
{
|
||||
j--; /* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
|
||||
continue;
|
||||
}
|
||||
if (tid != (server.sin_port)) /* checks to ensure get from the correct TID */
|
||||
{
|
||||
len = err_packet (5, err_msg[5], filebuf);
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) recvbuf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00) {
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
if (opcode != 4 || rcount != count) /* ack packet should have code 4 (ack) and should be acking the packet we just sent */
|
||||
{
|
||||
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
|
||||
len = err_packet (4, err_msg[4], filebuf);
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
}
|
||||
/* from here we will loop back and resend */
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
} //end of else
|
||||
|
||||
}
|
||||
/* The ack sending 'for' loop ends here */
|
||||
|
||||
|
||||
|
||||
memset (filebuf, 0, sizeof (filebuf)); //clear the filebuf
|
||||
while (1) /* our break statement will escape us when we are done */
|
||||
{
|
||||
//acked = 0;
|
||||
if (fileinfo->filelen > MAXDATASIZE)
|
||||
ssize = MAXDATASIZE;
|
||||
else
|
||||
ssize = fileinfo->filelen;
|
||||
fileinfo->filelen -= ssize;
|
||||
MicoFlashRead(fileinfo->flashtype, &flashaddr, (uint8_t *)filebuf, ssize);
|
||||
|
||||
|
||||
count++; /* count number of datasize byte portions we read from the file */
|
||||
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x03;
|
||||
packetbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
packetbuf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
memcpy ((char *) packetbuf + 4, filebuf, ssize);
|
||||
len = 4 + ssize;
|
||||
/* send the data packet */
|
||||
if (sendto
|
||||
(sock, packetbuf, len, 0, (struct sockaddr *) &server,
|
||||
sizeof (server)) != len)
|
||||
{
|
||||
close(sock);
|
||||
return -3;
|
||||
}
|
||||
//if ((count - 1) == 0 || ((count - 1) % ackfreq) == 0 || ssize != datasize)
|
||||
if (((count) % ackfreq) == 0 || ssize != MAXDATASIZE)
|
||||
{
|
||||
/* The following 'for' loop is used to recieve/timeout ACKs */
|
||||
for (j = 0; j < RETRIES; j++)
|
||||
{
|
||||
server_len = sizeof (ack);
|
||||
errno = EAGAIN;
|
||||
n = -1;
|
||||
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++)
|
||||
{
|
||||
n =
|
||||
recvfrom (sock, recvbuf, sizeof (recvbuf), MSG_DONTWAIT,
|
||||
(struct sockaddr *) &ack,
|
||||
(socklen_t *) & server_len);
|
||||
mico_rtos_delay_milliseconds(1);
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
|
||||
}
|
||||
else
|
||||
{ /* checks to ensure send to ip is same from ACK IP */
|
||||
if (server.sin_addr.s_addr != ack.sin_addr.s_addr )
|
||||
{
|
||||
/* in this case someone else connected to our port. Ignore this fact and retry getting the ack */
|
||||
j--;
|
||||
continue;
|
||||
}
|
||||
if (tid != (server.sin_port)) /* checks to ensure get from the correct TID */
|
||||
{
|
||||
len = err_packet (5, err_msg[5], filebuf);
|
||||
/* send the data packet */
|
||||
if (sendto
|
||||
(sock, filebuf, len, 0, (struct sockaddr *) &server,
|
||||
sizeof (server)) != len)
|
||||
{
|
||||
}
|
||||
j--;
|
||||
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) recvbuf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00) {
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
if (opcode != 4 || rcount != count) /* ack packet should have code 4 (ack) and should be acking the packet we just sent */
|
||||
{
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
len = err_packet (4, err_msg[4], filebuf);
|
||||
if (sendto (sock, filebuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
}
|
||||
/* from here we will loop back and resend */
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* resend the data packet */
|
||||
{
|
||||
close(sock);
|
||||
return -4;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/* The ack sending 'for' loop ends here */
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (j == RETRIES)
|
||||
{
|
||||
close(sock);
|
||||
return -5;
|
||||
}
|
||||
if (ssize != MAXDATASIZE)
|
||||
break;
|
||||
|
||||
memset (filebuf, 0, sizeof (filebuf)); /* fill the filebuf with zeros so that when the fread fills it, it is a null terminated string */
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return 0;
|
||||
} //end of tsend function
|
||||
|
||||
|
||||
/*
|
||||
*This function is called when the client would like to download a file from the server. Return the downloaded file length
|
||||
*/
|
||||
int
|
||||
tget (tftp_file_info_t *fileinfo, uint32_t ipaddr)
|
||||
{
|
||||
/* local variables */
|
||||
int len, server_len, opcode = RRQ, i, j, n, tid = 0, flag = 1;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
unsigned char filebuf[MAXDATASIZE + 12];
|
||||
unsigned char packetbuf[128];
|
||||
int errno;
|
||||
char *bufindex;
|
||||
struct sockaddr_in data;
|
||||
int sock;
|
||||
uint32_t flashaddr = fileinfo->flashaddr;
|
||||
struct sockaddr_in server;
|
||||
//unsigned short int ackfreq = 1;
|
||||
int totalen = 0;
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_addr.s_addr = ipaddr;
|
||||
server.sin_port = htons((uint16_t)69);
|
||||
|
||||
/*Create the socket, a -1 will show us an error */
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
MicoFlashErase(fileinfo->flashtype,fileinfo->flashaddr,fileinfo->filelen);
|
||||
|
||||
memset (packetbuf, 0, sizeof(packetbuf)); /*clear the buffer */
|
||||
/* this is the first request message */
|
||||
len = req_packet (opcode, fileinfo->filename, "octet", packetbuf);
|
||||
server_len = sizeof(struct sockaddr);
|
||||
|
||||
sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, server_len);
|
||||
n = MAXDATASIZE + 4;
|
||||
do
|
||||
{
|
||||
/* zero buffers so if there are any errors only NULLs will be exposed */
|
||||
memset (filebuf, 0, sizeof (filebuf));
|
||||
|
||||
|
||||
for (j = 0; j < RETRIES; j++) /* this allows us to loop until we either break out by getting the correct ack OR time out because we've looped more than RETRIES times */
|
||||
{
|
||||
server_len = sizeof (data);
|
||||
errno = EAGAIN; /* this allows us to enter the loop */
|
||||
n = -1;
|
||||
for (i = 0; errno == EAGAIN && i <= TIMEOUT && n < 0; i++) /* this for loop will just keep checking the non-blocking socket until timeout */
|
||||
{
|
||||
|
||||
n =
|
||||
recvfrom (sock, filebuf, sizeof (filebuf) - 1,
|
||||
MSG_DONTWAIT, (struct sockaddr *) &data,
|
||||
(socklen_t *) & server_len);
|
||||
mico_rtos_delay_milliseconds(1);
|
||||
}
|
||||
if (!tid)
|
||||
{
|
||||
tid = (data.sin_port); //get the tid of the server.
|
||||
server.sin_port = (tid); //set the tid for rest of the transfer
|
||||
}
|
||||
|
||||
if (n < 0) {
|
||||
sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, server_len);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (server.sin_addr.s_addr != data.sin_addr.s_addr) /* checks to ensure get from ip is same from ACK IP */
|
||||
{
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
if (tid != (server.sin_port)) /* checks to ensure get from the correct TID */
|
||||
{
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x05;
|
||||
packetbuf[2] = 0x00;
|
||||
packetbuf[3] = 0x05;
|
||||
len = strlen("Bad/Unknown TID");
|
||||
memcpy(&packetbuf[4], "Bad/Unknown TID", len);
|
||||
len += 4;
|
||||
packetbuf[len++] = 0x00;
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) filebuf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00) {
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
if (flag)
|
||||
{
|
||||
flag = 0;
|
||||
}
|
||||
if (opcode != 3) /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
|
||||
{
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x05;
|
||||
packetbuf[2] = 0x00;
|
||||
packetbuf[3] = 0x04;
|
||||
len = strlen("Illegal operation");
|
||||
memcpy(&packetbuf[4], "Illegal operation", len);
|
||||
len += 4;
|
||||
packetbuf[len++] = 0x00;
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len) /* send the data packet */
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (count + 1 == rcount) {// received right seq no, save and ack
|
||||
MicoFlashWrite(fileinfo->flashtype, &flashaddr, (uint8_t *)bufindex, n - 4);
|
||||
totalen += n-4;
|
||||
}
|
||||
|
||||
len = 4;
|
||||
packetbuf[0] = 0x00;
|
||||
packetbuf[1] = 0x04;
|
||||
packetbuf[2] = (rcount & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
packetbuf[3] = (rcount & 0x00FF); //fill in the lower part of the count
|
||||
count = rcount;
|
||||
|
||||
|
||||
sendto(sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server));
|
||||
break;
|
||||
} //end of else
|
||||
}
|
||||
}
|
||||
if (j == RETRIES)
|
||||
{
|
||||
close(sock);
|
||||
return -4;
|
||||
}
|
||||
if (n != (MAXDATASIZE + 4)) /* remember if our datasize is less than a full packet this was the last packet to be received */
|
||||
{
|
||||
goto done; /* gotos are not optimal, but a good solution when exiting a multi-layer loop */
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
done:
|
||||
|
||||
close(sock);
|
||||
return totalen;
|
||||
}
|
||||
|
||||
0
mico-os/MiCO/system/tftp_ota/tftpc.o
Executable file → Normal file
0
mico-os/MiCO/system/tftp_ota/tftpc.o
Executable file → Normal file
Reference in New Issue
Block a user