Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
1f37c8efa5 | |||
999cb97cc8 | |||
455ab71314 | |||
f0dcff0671 | |||
460b04a42b | |||
97857ce12c | |||
461b1b16b1 | |||
bd351ec732 |
220
Application/loopback/loopback.c
Normal file
220
Application/loopback/loopback.c
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "loopback.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "wizchip_conf.h"
|
||||||
|
|
||||||
|
#if LOOPBACK_MODE == LOOPBACK_MAIN_NOBLCOK
|
||||||
|
|
||||||
|
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
|
||||||
|
{
|
||||||
|
int32_t ret;
|
||||||
|
uint16_t size = 0, sentsize=0;
|
||||||
|
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
uint8_t destip[4];
|
||||||
|
uint16_t destport;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(getSn_SR(sn))
|
||||||
|
{
|
||||||
|
case SOCK_ESTABLISHED :
|
||||||
|
if(getSn_IR(sn) & Sn_IR_CON)
|
||||||
|
{
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
getSn_DIPR(sn, destip);
|
||||||
|
destport = getSn_DPORT(sn);
|
||||||
|
|
||||||
|
printf("%d:Connected - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
|
||||||
|
#endif
|
||||||
|
setSn_IR(sn,Sn_IR_CON);
|
||||||
|
}
|
||||||
|
if((size = getSn_RX_RSR(sn)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
|
||||||
|
{
|
||||||
|
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
|
||||||
|
ret = recv(sn, buf, size);
|
||||||
|
|
||||||
|
if(ret <= 0) return ret; // check SOCKERR_BUSY & SOCKERR_XXX. For showing the occurrence of SOCKERR_BUSY.
|
||||||
|
sentsize = 0;
|
||||||
|
|
||||||
|
while(size != sentsize)
|
||||||
|
{
|
||||||
|
ret = send(sn, buf+sentsize, size-sentsize);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
close(sn);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOCK_CLOSE_WAIT :
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
//printf("%d:CloseWait\r\n",sn);
|
||||||
|
#endif
|
||||||
|
if((ret = disconnect(sn)) != SOCK_OK) return ret;
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d:Socket Closed\r\n", sn);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SOCK_INIT :
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d:Listen, TCP server loopback, port [%d]\r\n", sn, port);
|
||||||
|
#endif
|
||||||
|
if( (ret = listen(sn)) != SOCK_OK) return ret;
|
||||||
|
break;
|
||||||
|
case SOCK_CLOSED:
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
//printf("%d:TCP server loopback start\r\n",sn);
|
||||||
|
#endif
|
||||||
|
if((ret = socket(sn, Sn_MR_TCP, port, 0x00)) != sn) return ret;
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
//printf("%d:Socket opened\r\n",sn);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport)
|
||||||
|
{
|
||||||
|
int32_t ret; // return value for SOCK_ERRORs
|
||||||
|
uint16_t size = 0, sentsize=0;
|
||||||
|
|
||||||
|
// Destination (TCP Server) IP info (will be connected)
|
||||||
|
// >> loopback_tcpc() function parameter
|
||||||
|
// >> Ex)
|
||||||
|
// uint8_t destip[4] = {192, 168, 0, 214};
|
||||||
|
// uint16_t destport = 5000;
|
||||||
|
|
||||||
|
// Port number for TCP client (will be increased)
|
||||||
|
uint16_t any_port = 50000;
|
||||||
|
|
||||||
|
// Socket Status Transitions
|
||||||
|
// Check the W5500 Socket n status register (Sn_SR, The 'Sn_SR' controlled by Sn_CR command or Packet send/recv status)
|
||||||
|
switch(getSn_SR(sn))
|
||||||
|
{
|
||||||
|
case SOCK_ESTABLISHED :
|
||||||
|
if(getSn_IR(sn) & Sn_IR_CON) // Socket n interrupt register mask; TCP CON interrupt = connection with peer is successful
|
||||||
|
{
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d:Connected to - %d.%d.%d.%d : %d\r\n",sn, destip[0], destip[1], destip[2], destip[3], destport);
|
||||||
|
#endif
|
||||||
|
setSn_IR(sn, Sn_IR_CON); // this interrupt should be write the bit cleared to '1'
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Data Transaction Parts; Handle the [data receive and send] process
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if((size = getSn_RX_RSR(sn)) > 0) // Sn_RX_RSR: Socket n Received Size Register, Receiving data length
|
||||||
|
{
|
||||||
|
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE; // DATA_BUF_SIZE means user defined buffer size (array)
|
||||||
|
ret = recv(sn, buf, size); // Data Receive process (H/W Rx socket buffer -> User's buffer)
|
||||||
|
|
||||||
|
if(ret <= 0) return ret; // If the received data length <= 0, receive failed and process end
|
||||||
|
sentsize = 0;
|
||||||
|
|
||||||
|
// Data sentsize control
|
||||||
|
while(size != sentsize)
|
||||||
|
{
|
||||||
|
ret = send(sn, buf+sentsize, size-sentsize); // Data send process (User's buffer -> Destination through H/W Tx socket buffer)
|
||||||
|
if(ret < 0) // Send Error occurred (sent data length < 0)
|
||||||
|
{
|
||||||
|
close(sn); // socket close
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSE_WAIT :
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
//printf("%d:CloseWait\r\n",sn);
|
||||||
|
#endif
|
||||||
|
if((ret=disconnect(sn)) != SOCK_OK) return ret;
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d:Socket Closed\r\n", sn);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_INIT :
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d:Try to connect to the %d.%d.%d.%d : %d\r\n", sn, destip[0], destip[1], destip[2], destip[3], destport);
|
||||||
|
#endif
|
||||||
|
if( (ret = connect(sn, destip, destport)) != SOCK_OK) return ret; // Try to TCP connect to the TCP server (destination)
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSED:
|
||||||
|
close(sn);
|
||||||
|
if((ret=socket(sn, Sn_MR_TCP, any_port++, 0x00)) != sn) return ret; // TCP socket open with 'any_port' port number
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
//printf("%d:TCP client loopback start\r\n",sn);
|
||||||
|
//printf("%d:Socket opened\r\n",sn);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port)
|
||||||
|
{
|
||||||
|
int32_t ret;
|
||||||
|
uint16_t size, sentsize;
|
||||||
|
uint8_t destip[4];
|
||||||
|
uint16_t destport;
|
||||||
|
|
||||||
|
switch(getSn_SR(sn))
|
||||||
|
{
|
||||||
|
case SOCK_UDP :
|
||||||
|
if((size = getSn_RX_RSR(sn)) > 0)
|
||||||
|
{
|
||||||
|
if(size > DATA_BUF_SIZE) size = DATA_BUF_SIZE;
|
||||||
|
ret = recvfrom(sn, buf, size, destip, (uint16_t*)&destport);
|
||||||
|
if(ret <= 0)
|
||||||
|
{
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d: recvfrom error. %ld\r\n",sn,ret);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
size = (uint16_t) ret;
|
||||||
|
sentsize = 0;
|
||||||
|
while(sentsize != size)
|
||||||
|
{
|
||||||
|
ret = sendto(sn, buf+sentsize, size-sentsize, destip, destport);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d: sendto error. %ld\r\n",sn,ret);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
sentsize += ret; // Don't care SOCKERR_BUSY, because it is zero.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOCK_CLOSED:
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
//printf("%d:UDP loopback start\r\n",sn);
|
||||||
|
#endif
|
||||||
|
if((ret = socket(sn, Sn_MR_UDP, port, 0x00)) != sn)
|
||||||
|
return ret;
|
||||||
|
#ifdef _LOOPBACK_DEBUG_
|
||||||
|
printf("%d:Opened, UDP loopback, port [%d]\r\n", sn, port);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
30
Application/loopback/loopback.h
Normal file
30
Application/loopback/loopback.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef _LOOPBACK_H_
|
||||||
|
#define _LOOPBACK_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Loopback test debug message printout enable */
|
||||||
|
#define _LOOPBACK_DEBUG_
|
||||||
|
|
||||||
|
/* DATA_BUF_SIZE define for Loopback example */
|
||||||
|
#ifndef DATA_BUF_SIZE
|
||||||
|
#define DATA_BUF_SIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************/
|
||||||
|
/* Select LOOPBACK_MODE */
|
||||||
|
/************************/
|
||||||
|
#define LOOPBACK_MAIN_NOBLOCK 0
|
||||||
|
#define LOOPBACK_MODE LOOPBACK_MAIN_NOBLOCK
|
||||||
|
|
||||||
|
|
||||||
|
/* TCP server Loopback test example */
|
||||||
|
int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port);
|
||||||
|
|
||||||
|
/* TCP client Loopback test example */
|
||||||
|
int32_t loopback_tcpc(uint8_t sn, uint8_t* buf, uint8_t* destip, uint16_t destport);
|
||||||
|
|
||||||
|
/* UDP Loopback test example */
|
||||||
|
int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port);
|
||||||
|
|
||||||
|
#endif
|
980
Internet/FTPServer/ftpd.c
Normal file
980
Internet/FTPServer/ftpd.c
Normal file
@ -0,0 +1,980 @@
|
|||||||
|
/*
|
||||||
|
* Wiznet.
|
||||||
|
* (c) Copyright 2002, Wiznet.
|
||||||
|
*
|
||||||
|
* Filename : ftpd.c
|
||||||
|
* Version : 1.0
|
||||||
|
* Programmer(s) :
|
||||||
|
* Created : 2003/01/28
|
||||||
|
* Description : FTP daemon. (AVR-GCC Compiler)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "stdio_private.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "ftpd.h"
|
||||||
|
|
||||||
|
/* Command table */
|
||||||
|
static char *commands[] = {
|
||||||
|
"user",
|
||||||
|
"acct",
|
||||||
|
"pass",
|
||||||
|
"type",
|
||||||
|
"list",
|
||||||
|
"cwd",
|
||||||
|
"dele",
|
||||||
|
"name",
|
||||||
|
"quit",
|
||||||
|
"retr",
|
||||||
|
"stor",
|
||||||
|
"port",
|
||||||
|
"nlst",
|
||||||
|
"pwd",
|
||||||
|
"xpwd",
|
||||||
|
"mkd",
|
||||||
|
"xmkd",
|
||||||
|
"xrmd",
|
||||||
|
"rmd ",
|
||||||
|
"stru",
|
||||||
|
"mode",
|
||||||
|
"syst",
|
||||||
|
"xmd5",
|
||||||
|
"xcwd",
|
||||||
|
"feat",
|
||||||
|
"pasv",
|
||||||
|
"size",
|
||||||
|
"mlsd",
|
||||||
|
"appe",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* Response messages */
|
||||||
|
char banner[] = "220 %s FTP version %s ready.\r\n";
|
||||||
|
char badcmd[] = "500 Unknown command '%s'\r\n";
|
||||||
|
char binwarn[] = "100 Warning: type is ASCII and %s appears to be binary\r\n";
|
||||||
|
char unsupp[] = "500 Unsupported command or option\r\n";
|
||||||
|
char givepass[] = "331 Enter PASS command\r\n";
|
||||||
|
char logged[] = "230 Logged in\r\n";
|
||||||
|
char typeok[] = "200 Type %s OK\r\n";
|
||||||
|
char only8[] = "501 Only logical bytesize 8 supported\r\n";
|
||||||
|
char deleok[] = "250 File deleted\r\n";
|
||||||
|
char mkdok[] = "200 MKD ok\r\n";
|
||||||
|
char delefail[] = "550 Delete failed: %s\r\n";
|
||||||
|
char pwdmsg[] = "257 \"%s\" is current directory\r\n";
|
||||||
|
char badtype[] = "501 Unknown type \"%s\"\r\n";
|
||||||
|
char badport[] = "501 Bad port syntax\r\n";
|
||||||
|
char unimp[] = "502 Command does not implemented yet.\r\n";
|
||||||
|
char bye[] = "221 Goodbye!\r\n";
|
||||||
|
char nodir[] = "553 Can't read directory \"%s\": %s\r\n";
|
||||||
|
char cantopen[] = "550 Can't read file \"%s\": %s\r\n";
|
||||||
|
char sending[] = "150 Opening data connection for %s (%d.%d.%d.%d,%d)\r\n";
|
||||||
|
char cantmake[] = "553 Can't create \"%s\": %s\r\n";
|
||||||
|
char writerr[] = "552 Write error: %s\r\n";
|
||||||
|
char portok[] = "200 PORT command successful.\r\n";
|
||||||
|
char rxok[] = "226 Transfer complete.\r\n";
|
||||||
|
char txok[] = "226 Transfer complete.\r\n";
|
||||||
|
char noperm[] = "550 Permission denied\r\n";
|
||||||
|
char noconn[] = "425 Data connection reset\r\n";
|
||||||
|
char lowmem[] = "421 System overloaded, try again later\r\n";
|
||||||
|
char notlog[] = "530 Please log in with USER and PASS\r\n";
|
||||||
|
char userfirst[] = "503 Login with USER first.\r\n";
|
||||||
|
char okay[] = "200 Ok\r\n";
|
||||||
|
char syst[] = "215 %s Type: L%d Version: %s\r\n";
|
||||||
|
char sizefail[] = "550 File not found\r\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
un_l2cval remote_ip;
|
||||||
|
uint16_t remote_port;
|
||||||
|
un_l2cval local_ip;
|
||||||
|
uint16_t local_port;
|
||||||
|
uint8_t connect_state_control = 0;
|
||||||
|
uint8_t connect_state_data = 0;
|
||||||
|
|
||||||
|
struct ftpd ftp;
|
||||||
|
|
||||||
|
int current_year = 2014;
|
||||||
|
int current_month = 12;
|
||||||
|
int current_day = 31;
|
||||||
|
int current_hour = 10;
|
||||||
|
int current_min = 10;
|
||||||
|
int current_sec = 30;
|
||||||
|
|
||||||
|
int fsprintf(uint8_t s, const char *format, ...)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/*
|
||||||
|
char buf[LINELEN];
|
||||||
|
FILE f;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
f.flags = __SWR | __SSTR;
|
||||||
|
f.buf = buf;
|
||||||
|
f.size = INT_MAX;
|
||||||
|
va_start(ap, format);
|
||||||
|
i = vfprintf(&f, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
buf[f.len] = 0;
|
||||||
|
|
||||||
|
send(s, (uint8_t *)buf, strlen(buf));
|
||||||
|
*/
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ftpd_init(uint8_t * src_ip)
|
||||||
|
{
|
||||||
|
ftp.state = FTPS_NOT_LOGIN;
|
||||||
|
ftp.current_cmd = NO_CMD;
|
||||||
|
ftp.dsock_mode = ACTIVE_MODE;
|
||||||
|
|
||||||
|
local_ip.cVal[0] = src_ip[0];
|
||||||
|
local_ip.cVal[1] = src_ip[1];
|
||||||
|
local_ip.cVal[2] = src_ip[2];
|
||||||
|
local_ip.cVal[3] = src_ip[3];
|
||||||
|
local_port = 35000;
|
||||||
|
|
||||||
|
strcpy(ftp.workingdir, "/");
|
||||||
|
|
||||||
|
socket(CTRL_SOCK, Sn_MR_TCP, IPPORT_FTP, 0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ftpd_run(uint8_t * dbuf)
|
||||||
|
{
|
||||||
|
uint16_t size = 0, i;
|
||||||
|
long ret = 0;
|
||||||
|
uint32_t blocklen, send_byte, recv_byte;
|
||||||
|
uint32_t remain_filesize;
|
||||||
|
uint32_t remain_datasize;
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
//FILINFO fno;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//memset(dbuf, 0, sizeof(_MAX_SS));
|
||||||
|
|
||||||
|
switch(getSn_SR(CTRL_SOCK))
|
||||||
|
{
|
||||||
|
case SOCK_ESTABLISHED :
|
||||||
|
if(!connect_state_control)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:FTP Connected\r\n", CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
//fsprintf(CTRL_SOCK, banner, HOSTNAME, VERSION);
|
||||||
|
strcpy(ftp.workingdir, "/");
|
||||||
|
sprintf((char *)dbuf, "220 %s FTP version %s ready.\r\n", HOSTNAME, VERSION);
|
||||||
|
ret = send(CTRL_SOCK, (uint8_t *)dbuf, strlen((const char *)dbuf));
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:send() error:%ld\r\n",CTRL_SOCK,ret);
|
||||||
|
#endif
|
||||||
|
close(CTRL_SOCK);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
connect_state_control = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
//printf("ftp socket %d\r\n", CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((size = getSn_RX_RSR(CTRL_SOCK)) > 0) // Don't need to check SOCKERR_BUSY because it doesn't not occur.
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("size: %d\r\n", size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(dbuf, 0, _MAX_SS);
|
||||||
|
|
||||||
|
if(size > _MAX_SS) size = _MAX_SS - 1;
|
||||||
|
|
||||||
|
ret = recv(CTRL_SOCK,dbuf,size);
|
||||||
|
dbuf[ret] = '\0';
|
||||||
|
if(ret != size)
|
||||||
|
{
|
||||||
|
if(ret==SOCK_BUSY) return 0;
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:recv() error:%ld\r\n",CTRL_SOCK,ret);
|
||||||
|
#endif
|
||||||
|
close(CTRL_SOCK);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("Rcvd Command: %s", dbuf);
|
||||||
|
#endif
|
||||||
|
proc_ftpd((char *)dbuf);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSE_WAIT :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:CloseWait\r\n",CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
if((ret=disconnect(CTRL_SOCK)) != SOCK_OK) return ret;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Closed\r\n",CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSED :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:FTPStart\r\n",CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
if((ret=socket(CTRL_SOCK, Sn_MR_TCP, IPPORT_FTP, 0x0)) != CTRL_SOCK)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:socket() error:%ld\r\n", CTRL_SOCK, ret);
|
||||||
|
#endif
|
||||||
|
close(CTRL_SOCK);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_INIT :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Opened\r\n",CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
//strcpy(ftp.workingdir, "/");
|
||||||
|
if( (ret = listen(CTRL_SOCK)) != SOCK_OK)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Listen error\r\n",CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
connect_state_control = 0;
|
||||||
|
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Listen ok\r\n",CTRL_SOCK);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
switch(getSn_SR(DATA_SOCK))
|
||||||
|
{
|
||||||
|
case SOCK_ESTABLISHED :
|
||||||
|
if(!connect_state_data)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:FTP Data socket Connected\r\n", DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
connect_state_data = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(ftp.current_cmd)
|
||||||
|
{
|
||||||
|
case LIST_CMD:
|
||||||
|
case MLSD_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("previous size: %d\r\n", size);
|
||||||
|
#endif
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
scan_files(ftp.workingdir, dbuf, (int *)&size);
|
||||||
|
#endif
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("returned size: %d\r\n", size);
|
||||||
|
printf("%s\r\n", dbuf);
|
||||||
|
#endif
|
||||||
|
#if !defined(F_FILESYSTEM)
|
||||||
|
if (strncmp(ftp.workingdir, "/$Recycle.Bin", sizeof("/$Recycle.Bin")) != 0)
|
||||||
|
size = sprintf(dbuf, "drwxr-xr-x 1 ftp ftp 0 Dec 31 2014 $Recycle.Bin\r\n-rwxr-xr-x 1 ftp ftp 512 Dec 31 2014 test.txt\r\n");
|
||||||
|
#endif
|
||||||
|
size = strlen(dbuf);
|
||||||
|
send(DATA_SOCK, dbuf, size);
|
||||||
|
ftp.current_cmd = NO_CMD;
|
||||||
|
disconnect(DATA_SOCK);
|
||||||
|
size = sprintf(dbuf, "226 Successfully transferred \"%s\"\r\n", ftp.workingdir);
|
||||||
|
send(CTRL_SOCK, dbuf, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RETR_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("filename to retrieve : %s %d\r\n", ftp.filename, strlen(ftp.filename));
|
||||||
|
#endif
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
ftp.fr = f_open(&(ftp.fil), (const char *)ftp.filename, FA_READ);
|
||||||
|
//print_filedsc(&(ftp.fil));
|
||||||
|
if(ftp.fr == FR_OK){
|
||||||
|
remain_filesize = ftp.fil.fsize;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("f_open return FR_OK\r\n");
|
||||||
|
#endif
|
||||||
|
do{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
//printf("remained file size: %d\r\n", ftp.fil.fsize);
|
||||||
|
#endif
|
||||||
|
memset(dbuf, 0, _MAX_SS);
|
||||||
|
|
||||||
|
if(remain_filesize > _MAX_SS)
|
||||||
|
send_byte = _MAX_SS;
|
||||||
|
else
|
||||||
|
send_byte = remain_filesize;
|
||||||
|
|
||||||
|
ftp.fr = f_read(&(ftp.fil), dbuf, send_byte , &blocklen);
|
||||||
|
if(ftp.fr != FR_OK)
|
||||||
|
break;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("#");
|
||||||
|
//printf("----->fsize:%d recv:%d len:%d \r\n", remain_filesize, send_byte, blocklen);
|
||||||
|
//printf("----->fn:%s data:%s \r\n", ftp.filename, dbuf);
|
||||||
|
#endif
|
||||||
|
send(DATA_SOCK, dbuf, blocklen);
|
||||||
|
remain_filesize -= blocklen;
|
||||||
|
}while(remain_filesize != 0);
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("\r\nFile read finished\r\n");
|
||||||
|
#endif
|
||||||
|
ftp.fr = f_close(&(ftp.fil));
|
||||||
|
}else{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("File Open Error: %d\r\n", ftp.fr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
remain_filesize = strlen(ftp.filename);
|
||||||
|
|
||||||
|
do{
|
||||||
|
memset(dbuf, 0, _MAX_SS);
|
||||||
|
|
||||||
|
blocklen = sprintf(dbuf, "%s", ftp.filename);
|
||||||
|
|
||||||
|
printf("########## dbuf:%s\r\n", dbuf);
|
||||||
|
|
||||||
|
send(DATA_SOCK, dbuf, blocklen);
|
||||||
|
remain_filesize -= blocklen;
|
||||||
|
}while(remain_filesize != 0);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
ftp.current_cmd = NO_CMD;
|
||||||
|
disconnect(DATA_SOCK);
|
||||||
|
size = sprintf(dbuf, "226 Successfully transferred \"%s\"\r\n", ftp.filename);
|
||||||
|
send(CTRL_SOCK, dbuf, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STOR_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("filename to store : %s %d\r\n", ftp.filename, strlen(ftp.filename));
|
||||||
|
#endif
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
ftp.fr = f_open(&(ftp.fil), (const char *)ftp.filename, FA_CREATE_ALWAYS | FA_WRITE);
|
||||||
|
//print_filedsc(&(ftp.fil));
|
||||||
|
if(ftp.fr == FR_OK){
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("f_open return FR_OK\r\n");
|
||||||
|
#endif
|
||||||
|
while(1){
|
||||||
|
if((remain_datasize = getSn_RX_RSR(DATA_SOCK)) > 0){
|
||||||
|
while(1){
|
||||||
|
memset(dbuf, 0, _MAX_SS);
|
||||||
|
|
||||||
|
if(remain_datasize > _MAX_SS)
|
||||||
|
recv_byte = _MAX_SS;
|
||||||
|
else
|
||||||
|
recv_byte = remain_datasize;
|
||||||
|
|
||||||
|
ret = recv(DATA_SOCK, dbuf, recv_byte);
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
//printf("----->fn:%s data:%s \r\n", ftp.filename, dbuf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ftp.fr = f_write(&(ftp.fil), dbuf, (UINT)ret, &blocklen);
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
//printf("----->dsize:%d recv:%d len:%d \r\n", remain_datasize, ret, blocklen);
|
||||||
|
#endif
|
||||||
|
remain_datasize -= blocklen;
|
||||||
|
|
||||||
|
if(ftp.fr != FR_OK){
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("f_write failed\r\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(remain_datasize <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ftp.fr != FR_OK){
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("f_write failed\r\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("#");
|
||||||
|
#endif
|
||||||
|
}else{
|
||||||
|
if(getSn_SR(DATA_SOCK) != SOCK_ESTABLISHED)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("\r\nFile write finished\r\n");
|
||||||
|
#endif
|
||||||
|
ftp.fr = f_close(&(ftp.fil));
|
||||||
|
}else{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("File Open Error: %d\r\n", ftp.fr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//fno.fdate = (WORD)(((current_year - 1980) << 9) | (current_month << 5) | current_day);
|
||||||
|
//fno.ftime = (WORD)((current_hour << 11) | (current_min << 5) | (current_sec >> 1));
|
||||||
|
//f_utime((const char *)ftp.filename, &fno);
|
||||||
|
#else
|
||||||
|
while(1){
|
||||||
|
if((remain_datasize = getSn_RX_RSR(DATA_SOCK)) > 0){
|
||||||
|
while(1){
|
||||||
|
memset(dbuf, 0, _MAX_SS);
|
||||||
|
|
||||||
|
if(remain_datasize > _MAX_SS)
|
||||||
|
recv_byte = _MAX_SS;
|
||||||
|
else
|
||||||
|
recv_byte = remain_datasize;
|
||||||
|
|
||||||
|
ret = recv(DATA_SOCK, dbuf, recv_byte);
|
||||||
|
|
||||||
|
printf("########## dbuf:%s\r\n", dbuf);
|
||||||
|
|
||||||
|
remain_datasize -= ret;
|
||||||
|
|
||||||
|
if(remain_datasize <= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(getSn_SR(DATA_SOCK) != SOCK_ESTABLISHED)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
ftp.current_cmd = NO_CMD;
|
||||||
|
disconnect(DATA_SOCK);
|
||||||
|
size = sprintf(dbuf, "226 Successfully transferred \"%s\"\r\n", ftp.filename);
|
||||||
|
send(CTRL_SOCK, dbuf, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NO_CMD:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSE_WAIT :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:CloseWait\r\n",DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
if((ret=disconnect(DATA_SOCK)) != SOCK_OK) return ret;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Closed\r\n",DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSED :
|
||||||
|
if(ftp.dsock_state == DATASOCK_READY)
|
||||||
|
{
|
||||||
|
if(ftp.dsock_mode == PASSIVE_MODE){
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:FTPDataStart, port : %d\r\n",DATA_SOCK, local_port);
|
||||||
|
#endif
|
||||||
|
if((ret=socket(DATA_SOCK, Sn_MR_TCP, local_port, 0x0)) != DATA_SOCK)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:socket() error:%ld\r\n", DATA_SOCK, ret);
|
||||||
|
#endif
|
||||||
|
close(DATA_SOCK);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
local_port++;
|
||||||
|
if(local_port > 50000)
|
||||||
|
local_port = 35000;
|
||||||
|
}else{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:FTPDataStart, port : %d\r\n",DATA_SOCK, IPPORT_FTPD);
|
||||||
|
#endif
|
||||||
|
if((ret=socket(DATA_SOCK, Sn_MR_TCP, IPPORT_FTPD, 0x0)) != DATA_SOCK)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:socket() error:%ld\r\n", DATA_SOCK, ret);
|
||||||
|
#endif
|
||||||
|
close(DATA_SOCK);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ftp.dsock_state = DATASOCK_START;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_INIT :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Opened\r\n",DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
if(ftp.dsock_mode == PASSIVE_MODE){
|
||||||
|
if( (ret = listen(DATA_SOCK)) != SOCK_OK)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Listen error\r\n",DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Listen ok\r\n",DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
}else{
|
||||||
|
if((ret = connect(DATA_SOCK, remote_ip.cVal, remote_port)) != SOCK_OK){
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Connect error\r\n", DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect_state_data = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char proc_ftpd(char * buf)
|
||||||
|
{
|
||||||
|
char **cmdp, *cp, *arg, *tmpstr;
|
||||||
|
char sendbuf[200];
|
||||||
|
int slen;
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
|
||||||
|
/* Translate first word to lower case */
|
||||||
|
for (cp = buf; *cp != ' ' && *cp != '\0'; cp++)
|
||||||
|
*cp = tolower(*cp);
|
||||||
|
|
||||||
|
/* Find command in table; if not present, return syntax error */
|
||||||
|
for (cmdp = commands; *cmdp != NULL; cmdp++)
|
||||||
|
if (strncmp(*cmdp, buf, strlen(*cmdp)) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*cmdp == NULL)
|
||||||
|
{
|
||||||
|
//fsprintf(CTRL_SOCK, badcmd, buf);
|
||||||
|
slen = sprintf(sendbuf, "500 Unknown command '%s'\r\n", buf);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Allow only USER, PASS and QUIT before logging in */
|
||||||
|
if (ftp.state == FTPS_NOT_LOGIN)
|
||||||
|
{
|
||||||
|
switch(cmdp - commands)
|
||||||
|
{
|
||||||
|
case USER_CMD:
|
||||||
|
case PASS_CMD:
|
||||||
|
case QUIT_CMD:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//fsprintf(CTRL_SOCK, notlog);
|
||||||
|
slen = sprintf(sendbuf, "530 Please log in with USER and PASS\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = &buf[strlen(*cmdp)];
|
||||||
|
while(*arg == ' ') arg++;
|
||||||
|
|
||||||
|
/* Execute specific command */
|
||||||
|
switch (cmdp - commands)
|
||||||
|
{
|
||||||
|
case USER_CMD :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("USER_CMD : %s", arg);
|
||||||
|
#endif
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
strcpy(ftp.username, arg);
|
||||||
|
//fsprintf(CTRL_SOCK, givepass);
|
||||||
|
slen = sprintf(sendbuf, "331 Enter PASS command\r\n");
|
||||||
|
ret = send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
if(ret < 0)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:send() error:%ld\r\n",CTRL_SOCK,ret);
|
||||||
|
#endif
|
||||||
|
close(CTRL_SOCK);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PASS_CMD :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("PASS_CMD : %s", arg);
|
||||||
|
#endif
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
ftplogin(arg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TYPE_CMD :
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
switch(arg[0])
|
||||||
|
{
|
||||||
|
case 'A':
|
||||||
|
case 'a': /* Ascii */
|
||||||
|
ftp.type = ASCII_TYPE;
|
||||||
|
//fsprintf(CTRL_SOCK, typeok, arg);
|
||||||
|
slen = sprintf(sendbuf, "200 Type set to %s\r\n", arg);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
case 'b': /* Binary */
|
||||||
|
case 'I':
|
||||||
|
case 'i': /* Image */
|
||||||
|
ftp.type = IMAGE_TYPE;
|
||||||
|
//fsprintf(CTRL_SOCK, typeok, arg);
|
||||||
|
slen = sprintf(sendbuf, "200 Type set to %s\r\n", arg);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* Invalid */
|
||||||
|
//fsprintf(CTRL_SOCK, badtype, arg);
|
||||||
|
slen = sprintf(sendbuf, "501 Unknown type \"%s\"\r\n", arg);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FEAT_CMD :
|
||||||
|
slen = sprintf(sendbuf, "211-Features:\r\n MDTM\r\n REST STREAM\r\n SIZE\r\n MLST size*;type*;create*;modify*;\r\n MLSD\r\n UTF8\r\n CLNT\r\n MFMT\r\n211 END\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QUIT_CMD :
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("QUIT_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
//fsprintf(CTRL_SOCK, bye);
|
||||||
|
slen = sprintf(sendbuf, "221 Goodbye!\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
disconnect(CTRL_SOCK);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RETR_CMD :
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("RETR_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
if(strlen(ftp.workingdir) == 1)
|
||||||
|
sprintf(ftp.filename, "/%s", arg);
|
||||||
|
else
|
||||||
|
sprintf(ftp.filename, "%s/%s", ftp.workingdir, arg);
|
||||||
|
slen = sprintf(sendbuf, "150 Opening data channel for file downloand from server of \"%s\"\r\n", ftp.filename);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
ftp.current_cmd = RETR_CMD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case APPE_CMD :
|
||||||
|
case STOR_CMD:
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("STOR_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
if(strlen(ftp.workingdir) == 1)
|
||||||
|
sprintf(ftp.filename, "/%s", arg);
|
||||||
|
else
|
||||||
|
sprintf(ftp.filename, "%s/%s", ftp.workingdir, arg);
|
||||||
|
slen = sprintf(sendbuf, "150 Opening data channel for file upload to server of \"%s\"\r\n", ftp.filename);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
ftp.current_cmd = STOR_CMD;
|
||||||
|
if((ret = connect(DATA_SOCK, remote_ip.cVal, remote_port)) != SOCK_OK){
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%d:Connect error\r\n", DATA_SOCK);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
connect_state_data = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PORT_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("PORT_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
if (pport(arg) == -1){
|
||||||
|
//fsprintf(CTRL_SOCK, badport);
|
||||||
|
slen = sprintf(sendbuf, "501 Bad port syntax\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
} else{
|
||||||
|
//fsprintf(CTRL_SOCK, portok);
|
||||||
|
ftp.dsock_mode = ACTIVE_MODE;
|
||||||
|
ftp.dsock_state = DATASOCK_READY;
|
||||||
|
slen = sprintf(sendbuf, "200 PORT command successful.\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MLSD_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("MLSD_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
slen = sprintf(sendbuf, "150 Opening data channel for directory listing of \"%s\"\r\n", ftp.workingdir);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
ftp.current_cmd = MLSD_CMD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LIST_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("LIST_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
slen = sprintf(sendbuf, "150 Opening data channel for directory listing of \"%s\"\r\n", ftp.workingdir);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
ftp.current_cmd = LIST_CMD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NLST_CMD:
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("NLST_CMD\r\n");
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYST_CMD:
|
||||||
|
slen = sprintf(sendbuf, "215 UNIX emulated by WIZnet\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PWD_CMD:
|
||||||
|
case XPWD_CMD:
|
||||||
|
slen = sprintf(sendbuf, "257 \"%s\" is current directory.\r\n", ftp.workingdir);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PASV_CMD:
|
||||||
|
slen = sprintf(sendbuf, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n", local_ip.cVal[0], local_ip.cVal[1], local_ip.cVal[2], local_ip.cVal[3], local_port >> 8, local_port & 0x00ff);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
disconnect(DATA_SOCK);
|
||||||
|
ftp.dsock_mode = PASSIVE_MODE;
|
||||||
|
ftp.dsock_state = DATASOCK_READY;
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("PASV port: %d\r\n", local_port);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SIZE_CMD:
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
if(slen > 3)
|
||||||
|
{
|
||||||
|
tmpstr = strrchr(arg, '/');
|
||||||
|
*tmpstr = 0;
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
slen = get_filesize(arg, tmpstr + 1);
|
||||||
|
#else
|
||||||
|
slen = _MAX_SS;
|
||||||
|
#endif
|
||||||
|
if(slen > 0)
|
||||||
|
slen = sprintf(sendbuf, "213 %d\r\n", slen);
|
||||||
|
else
|
||||||
|
slen = sprintf(sendbuf, "550 File not Found\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slen = sprintf(sendbuf, "550 File not Found\r\n");
|
||||||
|
}
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CWD_CMD:
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
if(slen > 3)
|
||||||
|
{
|
||||||
|
arg[slen - 3] = 0x00;
|
||||||
|
tmpstr = strrchr(arg, '/');
|
||||||
|
*tmpstr = 0;
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
slen = get_filesize(arg, tmpstr + 1);
|
||||||
|
#else
|
||||||
|
slen = 0;
|
||||||
|
#endif
|
||||||
|
*tmpstr = '/';
|
||||||
|
if(slen == 0){
|
||||||
|
slen = sprintf(sendbuf, "213 %d\r\n", slen);
|
||||||
|
strcpy(ftp.workingdir, arg);
|
||||||
|
slen = sprintf(sendbuf, "250 CWD successful. \"%s\" is current directory.\r\n", ftp.workingdir);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slen = sprintf(sendbuf, "550 CWD failed. \"%s\"\r\n", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(ftp.workingdir, arg);
|
||||||
|
slen = sprintf(sendbuf, "250 CWD successful. \"%s\" is current directory.\r\n", ftp.workingdir);
|
||||||
|
}
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKD_CMD:
|
||||||
|
case XMKD_CMD:
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
if (f_mkdir(arg) != 0)
|
||||||
|
{
|
||||||
|
slen = sprintf(sendbuf, "550 Can't create directory. \"%s\"\r\n", arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slen = sprintf(sendbuf, "257 MKD command successful. \"%s\"\r\n", arg);
|
||||||
|
//strcpy(ftp.workingdir, arg);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
slen = sprintf(sendbuf, "550 Can't create directory. Permission denied\r\n");
|
||||||
|
#endif
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DELE_CMD:
|
||||||
|
slen = strlen(arg);
|
||||||
|
arg[slen - 1] = 0x00;
|
||||||
|
arg[slen - 2] = 0x00;
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
if (f_unlink(arg) != 0)
|
||||||
|
{
|
||||||
|
slen = sprintf(sendbuf, "550 Could not delete. \"%s\"\r\n", arg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slen = sprintf(sendbuf, "250 Deleted. \"%s\"\r\n", arg);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
slen = sprintf(sendbuf, "550 Could not delete. Permission denied\r\n");
|
||||||
|
#endif
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XCWD_CMD:
|
||||||
|
case ACCT_CMD:
|
||||||
|
case XRMD_CMD:
|
||||||
|
case RMD_CMD:
|
||||||
|
case STRU_CMD:
|
||||||
|
case MODE_CMD:
|
||||||
|
case XMD5_CMD:
|
||||||
|
//fsprintf(CTRL_SOCK, unimp);
|
||||||
|
slen = sprintf(sendbuf, "502 Command does not implemented yet.\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: /* Invalid */
|
||||||
|
//fsprintf(CTRL_SOCK, badcmd, arg);
|
||||||
|
slen = sprintf(sendbuf, "500 Unknown command \'%s\'\r\n", arg);
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char ftplogin(char * pass)
|
||||||
|
{
|
||||||
|
char sendbuf[100];
|
||||||
|
int slen = 0;
|
||||||
|
|
||||||
|
//memset(sendbuf, 0, DATA_BUF_SIZE);
|
||||||
|
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("%s logged in\r\n", ftp.username);
|
||||||
|
#endif
|
||||||
|
//fsprintf(CTRL_SOCK, logged);
|
||||||
|
slen = sprintf(sendbuf, "230 Logged on\r\n");
|
||||||
|
send(CTRL_SOCK, (uint8_t *)sendbuf, slen);
|
||||||
|
ftp.state = FTPS_LOGIN;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pport(char * arg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char* tok=0;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if(i==0) tok = strtok(arg,",\r\n");
|
||||||
|
else tok = strtok(NULL,",");
|
||||||
|
remote_ip.cVal[i] = (uint8_t)atoi(tok, 10);
|
||||||
|
if (!tok)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("bad pport : %s\r\n", arg);
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
remote_port = 0;
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
tok = strtok(NULL,",\r\n");
|
||||||
|
remote_port <<= 8;
|
||||||
|
remote_port += atoi(tok, 10);
|
||||||
|
if (!tok)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("bad pport : %s\r\n", arg);
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("ip : %d.%d.%d.%d, port : %d\r\n", remote_ip.cVal[0], remote_ip.cVal[1], remote_ip.cVal[2], remote_ip.cVal[3], remote_port);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
void print_filedsc(FIL *fil)
|
||||||
|
{
|
||||||
|
#if defined(_FTP_DEBUG_)
|
||||||
|
printf("File System pointer : %08X\r\n", fil->fs);
|
||||||
|
printf("File System mount ID : %d\r\n", fil->id);
|
||||||
|
printf("File status flag : %08X\r\n", fil->flag);
|
||||||
|
printf("File System pads : %08X\r\n", fil->err);
|
||||||
|
printf("File read write pointer : %08X\r\n", fil->fptr);
|
||||||
|
printf("File size : %08X\r\n", fil->fsize);
|
||||||
|
printf("File start cluster : %08X\r\n", fil->sclust);
|
||||||
|
printf("current cluster : %08X\r\n", fil->clust);
|
||||||
|
printf("current data sector : %08X\r\n", fil->dsect);
|
||||||
|
printf("dir entry sector : %08X\r\n", fil->dir_sect);
|
||||||
|
printf("dir entry pointer : %08X\r\n", fil->dir_ptr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
145
Internet/FTPServer/ftpd.h
Normal file
145
Internet/FTPServer/ftpd.h
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
#ifndef _FTPD_H_
|
||||||
|
#define _FTPD_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wiznet.
|
||||||
|
* (c) Copyright 2002, Wiznet.
|
||||||
|
*
|
||||||
|
* Filename : ftpd.h
|
||||||
|
* Version : 1.0
|
||||||
|
* Programmer(s) :
|
||||||
|
* Created : 2003/01/28
|
||||||
|
* Description : Header file of FTP daemon. (AVR-GCC Compiler)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//#define F_FILESYSTEM // If your target support a file system, you have to activate this feature and implement.
|
||||||
|
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
#include "ff.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define F_APP_FTP
|
||||||
|
#define _FTP_DEBUG_
|
||||||
|
|
||||||
|
|
||||||
|
#define LINELEN 100
|
||||||
|
//#define DATA_BUF_SIZE 100
|
||||||
|
#if !defined(F_FILESYSTEM)
|
||||||
|
#define _MAX_SS 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CTRL_SOCK 2
|
||||||
|
#define DATA_SOCK 3
|
||||||
|
|
||||||
|
#define IPPORT_FTPD 20 /* FTP Data port */
|
||||||
|
#define IPPORT_FTP 21 /* FTP Control port */
|
||||||
|
|
||||||
|
#define HOSTNAME "iinChip"
|
||||||
|
#define VERSION "1.0"
|
||||||
|
|
||||||
|
#define FILENAME "a.txt"
|
||||||
|
|
||||||
|
/* FTP commands */
|
||||||
|
enum ftp_cmd {
|
||||||
|
USER_CMD,
|
||||||
|
ACCT_CMD,
|
||||||
|
PASS_CMD,
|
||||||
|
TYPE_CMD,
|
||||||
|
LIST_CMD,
|
||||||
|
CWD_CMD,
|
||||||
|
DELE_CMD,
|
||||||
|
NAME_CMD,
|
||||||
|
QUIT_CMD,
|
||||||
|
RETR_CMD,
|
||||||
|
STOR_CMD,
|
||||||
|
PORT_CMD,
|
||||||
|
NLST_CMD,
|
||||||
|
PWD_CMD,
|
||||||
|
XPWD_CMD,
|
||||||
|
MKD_CMD,
|
||||||
|
XMKD_CMD,
|
||||||
|
XRMD_CMD,
|
||||||
|
RMD_CMD,
|
||||||
|
STRU_CMD,
|
||||||
|
MODE_CMD,
|
||||||
|
SYST_CMD,
|
||||||
|
XMD5_CMD,
|
||||||
|
XCWD_CMD,
|
||||||
|
FEAT_CMD,
|
||||||
|
PASV_CMD,
|
||||||
|
SIZE_CMD,
|
||||||
|
MLSD_CMD,
|
||||||
|
APPE_CMD,
|
||||||
|
NO_CMD,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ftp_type {
|
||||||
|
ASCII_TYPE,
|
||||||
|
IMAGE_TYPE,
|
||||||
|
LOGICAL_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ftp_state {
|
||||||
|
FTPS_NOT_LOGIN,
|
||||||
|
FTPS_LOGIN
|
||||||
|
};
|
||||||
|
|
||||||
|
enum datasock_state{
|
||||||
|
DATASOCK_IDLE,
|
||||||
|
DATASOCK_READY,
|
||||||
|
DATASOCK_START
|
||||||
|
};
|
||||||
|
|
||||||
|
enum datasock_mode{
|
||||||
|
PASSIVE_MODE,
|
||||||
|
ACTIVE_MODE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ftpd {
|
||||||
|
uint8_t control; /* Control stream */
|
||||||
|
uint8_t data; /* Data stream */
|
||||||
|
|
||||||
|
enum ftp_type type; /* Transfer type */
|
||||||
|
enum ftp_state state;
|
||||||
|
|
||||||
|
enum ftp_cmd current_cmd;
|
||||||
|
|
||||||
|
enum datasock_state dsock_state;
|
||||||
|
enum datasock_mode dsock_mode;
|
||||||
|
|
||||||
|
char username[LINELEN]; /* Arg to USER command */
|
||||||
|
char workingdir[LINELEN];
|
||||||
|
char filename[LINELEN];
|
||||||
|
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
FIL fil; // FatFs File objects
|
||||||
|
FRESULT fr; // FatFs function common result code
|
||||||
|
#endif
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef un_I2cval
|
||||||
|
typedef union _un_l2cval {
|
||||||
|
uint32_t lVal;
|
||||||
|
uint8_t cVal[4];
|
||||||
|
}un_l2cval;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ftpd_init(uint8_t * src_ip);
|
||||||
|
uint8_t ftpd_run(uint8_t * dbuf);
|
||||||
|
char proc_ftpd(char * buf);
|
||||||
|
char ftplogin(char * pass);
|
||||||
|
int pport(char * arg);
|
||||||
|
|
||||||
|
int sendit(char * command);
|
||||||
|
int recvit(char * command);
|
||||||
|
|
||||||
|
long sendfile(uint8_t s, char * command);
|
||||||
|
long recvfile(uint8_t s);
|
||||||
|
|
||||||
|
#if defined(F_FILESYSTEM)
|
||||||
|
void print_filedsc(FIL *fil);
|
||||||
|
#endif
|
||||||
|
#endif // _FTPD_H_
|
67
Internet/FTPServer/stdio_private.h
Normal file
67
Internet/FTPServer/stdio_private.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* Copyright (c) 2002, Joerg Wunsch
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
* Neither the name of the copyright holders nor the names of
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id: stdio_private.h,v 1.6 2003/01/07 22:17:24 joerg_wunsch Exp $ */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
struct __file {
|
||||||
|
char *buf; /* buffer pointer */
|
||||||
|
unsigned char unget; /* ungetc() buffer */
|
||||||
|
uint8_t flags; /* flags, see below */
|
||||||
|
#define __SRD 0x0001 /* OK to read */
|
||||||
|
#define __SWR 0x0002 /* OK to write */
|
||||||
|
#define __SSTR 0x0004 /* this is an sprintf/snprintf string */
|
||||||
|
#define __SPGM 0x0008 /* fmt string is in progmem */
|
||||||
|
#define __SERR 0x0010 /* found error */
|
||||||
|
#define __SEOF 0x0020 /* found EOF */
|
||||||
|
#define __SUNGET 0x040 /* ungetc() happened */
|
||||||
|
#if 0
|
||||||
|
/* possible future extensions, will require uint16_t flags */
|
||||||
|
#define __SRW 0x0080 /* open for reading & writing */
|
||||||
|
#define __SLBF 0x0100 /* line buffered */
|
||||||
|
#define __SNBF 0x0200 /* unbuffered */
|
||||||
|
#define __SMBF 0x0400 /* buf is from malloc */
|
||||||
|
#endif
|
||||||
|
int size; /* size of buffer */
|
||||||
|
int len; /* characters read or written so far */
|
||||||
|
int (*put)(char); /* function to write one char to device */
|
||||||
|
int (*get)(void); /* function to read one char from device */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* values for PRINTF_LEVEL */
|
||||||
|
#define PRINTF_MIN 1
|
||||||
|
#define PRINTF_STD 2
|
||||||
|
#define PRINTF_FLT 3
|
||||||
|
|
||||||
|
/* values for SCANF_LEVEL */
|
||||||
|
#define SCANF_MIN 1
|
||||||
|
#define SCANF_STD 2
|
||||||
|
#define SCANF_FLT 3
|
927
Internet/SNMP/snmp.c
Normal file
927
Internet/SNMP/snmp.c
Normal file
@ -0,0 +1,927 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
#include "snmp.h"
|
||||||
|
#include "snmp_custom.h"
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
/* SNMP : Functions declaration */
|
||||||
|
/********************************************************************************************/
|
||||||
|
// SNMP Parsing functions
|
||||||
|
int32_t findEntry(uint8_t *oid, int32_t len);
|
||||||
|
int32_t getOID(int32_t id, uint8_t *oid, uint8_t *len);
|
||||||
|
int32_t getValue( uint8_t *vptr, int32_t vlen);
|
||||||
|
int32_t getEntry(int32_t id, uint8_t *dataType, void *ptr, int32_t *len);
|
||||||
|
int32_t setEntry(int32_t id, void *val, int32_t vlen, uint8_t dataType, int32_t index);
|
||||||
|
int32_t makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32_t *len);
|
||||||
|
|
||||||
|
int32_t parseLength(const uint8_t *msg, int32_t *len);
|
||||||
|
int32_t parseTLV(const uint8_t *msg, int32_t index, tlvStructType *tlv);
|
||||||
|
void insertRespLen(int32_t reqStart, int32_t respStart, int32_t size);
|
||||||
|
int32_t parseVarBind(int32_t reqType, int32_t index);
|
||||||
|
int32_t parseSequence(int32_t reqType, int32_t index);
|
||||||
|
int32_t parseSequenceOf(int32_t reqType);
|
||||||
|
int32_t parseRequest();
|
||||||
|
int32_t parseCommunity();
|
||||||
|
int32_t parseVersion();
|
||||||
|
int32_t parseSNMPMessage();
|
||||||
|
|
||||||
|
// Debugging function
|
||||||
|
#ifdef _SNMP_DEBUG_
|
||||||
|
void dumpCode(uint8_t* header, uint8_t* tail, uint8_t *buff, int32_t len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Utils
|
||||||
|
void ipToByteArray(int8_t *ip, uint8_t *pDes);
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
/* SNMP : Variable declaration */
|
||||||
|
/********************************************************************************************/
|
||||||
|
// SNMP message structures
|
||||||
|
struct messageStruct request_msg;
|
||||||
|
struct messageStruct response_msg;
|
||||||
|
|
||||||
|
// SNMP Time counter
|
||||||
|
static time_t startTime = 0;
|
||||||
|
volatile uint32_t snmp_tick_10ms = 0; //volatile uint32_t snmp_tick_1ms = 0;
|
||||||
|
|
||||||
|
// SNMP Sockets
|
||||||
|
static uint8_t SOCK_SNMP_AGENT;
|
||||||
|
static uint8_t SOCK_SNMP_TRAP;
|
||||||
|
|
||||||
|
uint8_t packet_trap[MAX_TRAPMSG_LEN] = {0,};
|
||||||
|
uint8_t errorStatus, errorIndex;
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
/* SNMP : Time handler */
|
||||||
|
/********************************************************************************************/
|
||||||
|
void currentUptime(void *ptr, uint8_t *len)
|
||||||
|
{
|
||||||
|
time_t curTime = getSNMPTimeTick();
|
||||||
|
|
||||||
|
//*(uint32_t *)ptr = (uint32_t)(curTime - startTime) / 10; // calculation for 1ms tick
|
||||||
|
*(uint32_t *)ptr = (uint32_t)(curTime - startTime); // calculation for 10ms tick
|
||||||
|
*len = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNMP_time_handler(void)
|
||||||
|
{
|
||||||
|
//snmp_tick_1ms++;
|
||||||
|
snmp_tick_10ms++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getSNMPTimeTick(void)
|
||||||
|
{
|
||||||
|
//return snmp_tick_1ms;
|
||||||
|
return snmp_tick_10ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
/* SNMP : Library Part */
|
||||||
|
/********************************************************************************************/
|
||||||
|
/**
|
||||||
|
* @addtogroup snmp_module
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize SNMP Daemon.
|
||||||
|
* This should be called just one time at first time
|
||||||
|
*
|
||||||
|
* @param none
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void snmpd_init(uint8_t * managerIP, uint8_t * agentIP, uint8_t sn_agent, uint8_t sn_trap)
|
||||||
|
{
|
||||||
|
#ifdef _SNMP_DEBUG_
|
||||||
|
printf("\r\n - SNMP : Start SNMP Agent Daemon\r\n");
|
||||||
|
#endif
|
||||||
|
SOCK_SNMP_AGENT = sn_agent;
|
||||||
|
SOCK_SNMP_TRAP = sn_trap;
|
||||||
|
|
||||||
|
if((SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) || (SOCK_SNMP_TRAP > _WIZCHIP_SOCK_NUM_)) return;
|
||||||
|
|
||||||
|
startTime = getSNMPTimeTick(); // Start time (unit: 10ms)
|
||||||
|
initTable(); // Settings for OID entry values
|
||||||
|
|
||||||
|
initial_Trap(managerIP, agentIP);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Example Codes for SNMP Trap
|
||||||
|
{
|
||||||
|
dataEntryType enterprise_oid = {0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
|
||||||
|
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\x9b\x19\x10\x00"}, NULL, NULL};
|
||||||
|
|
||||||
|
dataEntryType trap_oid1 = {8, {0x2b, 6, 1, 4, 1, 0, 11, 0}, SNMPDTYPE_OCTET_STRING, 30, {""}, NULL, NULL};
|
||||||
|
dataEntryType trap_oid2 = {8, {0x2b, 6, 1, 4, 1, 0, 12, 0}, SNMPDTYPE_INTEGER, 4, {""}, NULL, NULL};
|
||||||
|
|
||||||
|
strcpy((char *)trap_oid1.u.octetstring, "Alert!!!"); // String added
|
||||||
|
trap_oid2.u.intval = 123456; // Integer value added
|
||||||
|
|
||||||
|
// Generic Trap: warmStart
|
||||||
|
snmp_sendTrap((void *)"192.168.0.214", (void *)"192.168.0.112", (void *)"public", enterprise_oid, SNMPTRAP_WARMSTART, 0, 0);
|
||||||
|
|
||||||
|
// Enterprise-Specific Trap
|
||||||
|
snmp_sendTrap((void *)"192.168.0.214", (void *)"192.168.0.112", (void *)"public", enterprise_oid, 6, 0, 2, &trap_oid1, &trap_oid2);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SNMP Process Handler.
|
||||||
|
* UDP Socket and SNMP Agent transaction handling.
|
||||||
|
*
|
||||||
|
* @param none
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
|
||||||
|
int32_t snmpd_run(void)
|
||||||
|
{
|
||||||
|
int32_t ret;
|
||||||
|
int32_t len = 0;
|
||||||
|
|
||||||
|
uint8_t svr_addr[6];
|
||||||
|
uint16_t svr_port;
|
||||||
|
|
||||||
|
if(SOCK_SNMP_AGENT > _WIZCHIP_SOCK_NUM_) return -99;
|
||||||
|
|
||||||
|
switch(getSn_SR(SOCK_SNMP_AGENT))
|
||||||
|
{
|
||||||
|
case SOCK_UDP :
|
||||||
|
if ( (len = getSn_RX_RSR(SOCK_SNMP_AGENT)) > 0)
|
||||||
|
{
|
||||||
|
request_msg.len= recvfrom(SOCK_SNMP_AGENT, request_msg.buffer, len, svr_addr, &svr_port);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request_msg.len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request_msg.len > 0)
|
||||||
|
{
|
||||||
|
#ifdef _SNMP_DEBUG_
|
||||||
|
dumpCode((void *)"\r\n[Request]\r\n", (void *)"\r\n", request_msg.buffer, request_msg.len);
|
||||||
|
#endif
|
||||||
|
// Initialize
|
||||||
|
request_msg.index = 0;
|
||||||
|
response_msg.index = 0;
|
||||||
|
errorStatus = errorIndex = 0;
|
||||||
|
memset(response_msg.buffer, 0x00, MAX_SNMPMSG_LEN);
|
||||||
|
|
||||||
|
// Received message parsing and send response process
|
||||||
|
if (parseSNMPMessage() != -1)
|
||||||
|
{
|
||||||
|
sendto(SOCK_SNMP_AGENT, response_msg.buffer, response_msg.index, svr_addr, svr_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SNMP_DEBUG_
|
||||||
|
dumpCode((void *)"\r\n[Response]\r\n", (void *)"\r\n", response_msg.buffer, response_msg.index);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSED :
|
||||||
|
if((ret = socket(SOCK_SNMP_AGENT, Sn_MR_UDP, PORT_SNMP_AGENT, 0x00)) != SOCK_SNMP_AGENT)
|
||||||
|
return ret;
|
||||||
|
#ifdef _SNMP_DEBUG_
|
||||||
|
printf(" - [%d] UDP Socket for SNMP Agent, port [%d]\r\n", SOCK_SNMP_AGENT, PORT_SNMP_AGENT);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t findEntry(uint8_t *oid, int32_t len)
|
||||||
|
{
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < maxData ; i++)
|
||||||
|
{
|
||||||
|
if (len == snmpData[i].oidlen)
|
||||||
|
{
|
||||||
|
if (!memcmp(snmpData[i].oid, oid, len)) return(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OID_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t getOID(int32_t id, uint8_t *oid, uint8_t *len)
|
||||||
|
{
|
||||||
|
int32_t j;
|
||||||
|
|
||||||
|
if (!((id >= 0) && (id < maxData))) return INVALID_ENTRY_ID;
|
||||||
|
|
||||||
|
*len = snmpData[id].oidlen;
|
||||||
|
|
||||||
|
for (j = 0 ; j < *len ; j++)
|
||||||
|
{
|
||||||
|
oid[j] = snmpData[id].oid[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t getValue( uint8_t *vptr, int32_t vlen)
|
||||||
|
{
|
||||||
|
int32_t index = 0;
|
||||||
|
int32_t value = 0;
|
||||||
|
|
||||||
|
while (index < vlen)
|
||||||
|
{
|
||||||
|
if (index != 0) value <<= 8;
|
||||||
|
value |= vptr[index++];
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t getEntry(int32_t id, uint8_t *dataType, void *ptr, int32_t *len)
|
||||||
|
{
|
||||||
|
uint8_t * ptr_8;
|
||||||
|
int32_t value;
|
||||||
|
|
||||||
|
uint8_t * string;
|
||||||
|
int32_t j;
|
||||||
|
|
||||||
|
if (!((id >= 0) && (id < maxData))) return INVALID_ENTRY_ID;
|
||||||
|
|
||||||
|
*dataType = snmpData[id].dataType;
|
||||||
|
|
||||||
|
switch(*dataType)
|
||||||
|
{
|
||||||
|
case SNMPDTYPE_OCTET_STRING :
|
||||||
|
case SNMPDTYPE_OBJ_ID :
|
||||||
|
{
|
||||||
|
string = ptr;
|
||||||
|
|
||||||
|
if (snmpData[id].getfunction != NULL)
|
||||||
|
{
|
||||||
|
snmpData[id].getfunction( (void *)&snmpData[id].u.octetstring, &snmpData[id].dataLen );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (*dataType)==SNMPDTYPE_OCTET_STRING )
|
||||||
|
{
|
||||||
|
snmpData[id].dataLen = (uint8_t)strlen((char const*)&snmpData[id].u.octetstring);
|
||||||
|
}
|
||||||
|
|
||||||
|
*len = snmpData[id].dataLen;
|
||||||
|
for (j = 0 ; j < *len ; j++)
|
||||||
|
{
|
||||||
|
string[j] = snmpData[id].u.octetstring[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNMPDTYPE_INTEGER :
|
||||||
|
case SNMPDTYPE_TIME_TICKS :
|
||||||
|
case SNMPDTYPE_COUNTER :
|
||||||
|
case SNMPDTYPE_GAUGE :
|
||||||
|
{
|
||||||
|
if (snmpData[id].getfunction != NULL)
|
||||||
|
{
|
||||||
|
snmpData[id].getfunction( (void *)&snmpData[id].u.intval, &snmpData[id].dataLen );
|
||||||
|
}
|
||||||
|
|
||||||
|
if(snmpData[id].dataLen) *len = snmpData[id].dataLen;
|
||||||
|
else *len = sizeof(uint32_t);
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Original code (IAR, STM32)
|
||||||
|
// This code is not working in NXP+LPCXpresso (32-bit pointer operation error)
|
||||||
|
value = (int32_t *)ptr;
|
||||||
|
*value = HTONL(snmpData[id].u.intval);
|
||||||
|
*/
|
||||||
|
|
||||||
|
ptr_8 = ptr;
|
||||||
|
//value = HTONL(snmpData[id].u.intval); // Endian convert when processing 32bit pointer operation
|
||||||
|
value = snmpData[id].u.intval;
|
||||||
|
|
||||||
|
for (j = 0 ; j < *len ; j++)
|
||||||
|
{
|
||||||
|
ptr_8[j] = (uint8_t)((value >> ((*len-j-1)*8)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
return INVALID_DATA_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t setEntry(int32_t id, void *val, int32_t vlen, uint8_t dataType, int32_t index)
|
||||||
|
{
|
||||||
|
|
||||||
|
int32_t retStatus=OID_NOT_FOUND;
|
||||||
|
int32_t j;
|
||||||
|
|
||||||
|
if (snmpData[id].dataType != dataType)
|
||||||
|
{
|
||||||
|
errorStatus = BAD_VALUE;
|
||||||
|
errorIndex = index;
|
||||||
|
return INVALID_DATA_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(snmpData[id].dataType)
|
||||||
|
{
|
||||||
|
case SNMPDTYPE_OCTET_STRING :
|
||||||
|
case SNMPDTYPE_OBJ_ID :
|
||||||
|
{
|
||||||
|
uint8_t *string = val;
|
||||||
|
for (j = 0 ; j < vlen ; j++)
|
||||||
|
{
|
||||||
|
snmpData[id].u.octetstring[j] = string[j];
|
||||||
|
}
|
||||||
|
snmpData[id].dataLen = vlen;
|
||||||
|
}
|
||||||
|
retStatus = SNMP_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNMPDTYPE_INTEGER :
|
||||||
|
case SNMPDTYPE_TIME_TICKS :
|
||||||
|
case SNMPDTYPE_COUNTER :
|
||||||
|
case SNMPDTYPE_GAUGE :
|
||||||
|
{
|
||||||
|
snmpData[id].u.intval = getValue( (uint8_t *)val, vlen);
|
||||||
|
snmpData[id].dataLen = vlen;
|
||||||
|
|
||||||
|
if (snmpData[id].setfunction != NULL)
|
||||||
|
{
|
||||||
|
snmpData[id].setfunction(snmpData[id].u.intval);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
retStatus = SNMP_SUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
retStatus = INVALID_DATA_TYPE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return retStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseLength(const uint8_t *msg, int32_t *len)
|
||||||
|
{
|
||||||
|
int32_t i=1;
|
||||||
|
|
||||||
|
if (msg[0] & 0x80)
|
||||||
|
{
|
||||||
|
int32_t tlen = (msg[0] & 0x7f) - 1;
|
||||||
|
*len = msg[i++];
|
||||||
|
|
||||||
|
while (tlen--)
|
||||||
|
{
|
||||||
|
*len <<= 8;
|
||||||
|
*len |= msg[i++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*len = msg[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseTLV(const uint8_t *msg, int32_t index, tlvStructType *tlv)
|
||||||
|
{
|
||||||
|
int32_t Llen = 0;
|
||||||
|
|
||||||
|
tlv->start = index;
|
||||||
|
|
||||||
|
Llen = parseLength((const uint8_t *)&msg[index+1], &tlv->len );
|
||||||
|
|
||||||
|
tlv->vstart = index + Llen + 1;
|
||||||
|
|
||||||
|
switch (msg[index])
|
||||||
|
{
|
||||||
|
case SNMPDTYPE_SEQUENCE:
|
||||||
|
case GET_REQUEST:
|
||||||
|
case GET_NEXT_REQUEST:
|
||||||
|
case SET_REQUEST:
|
||||||
|
tlv->nstart = tlv->vstart;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
tlv->nstart = tlv->vstart + tlv->len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void insertRespLen(int32_t reqStart, int32_t respStart, int32_t size)
|
||||||
|
{
|
||||||
|
int32_t indexStart, lenLength;
|
||||||
|
uint32_t mask = 0xff;
|
||||||
|
int32_t shift = 0;
|
||||||
|
|
||||||
|
if (request_msg.buffer[reqStart+1] & 0x80)
|
||||||
|
{
|
||||||
|
lenLength = request_msg.buffer[reqStart+1] & 0x7f;
|
||||||
|
indexStart = respStart+2;
|
||||||
|
|
||||||
|
while (lenLength--)
|
||||||
|
{
|
||||||
|
response_msg.buffer[indexStart+lenLength] =
|
||||||
|
(uint8_t)((size & mask) >> shift);
|
||||||
|
shift+=8;
|
||||||
|
mask <<= shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response_msg.buffer[respStart+1] = (uint8_t)(size & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t parseVarBind(int32_t reqType, int32_t index)
|
||||||
|
{
|
||||||
|
int32_t seglen = 0, id;
|
||||||
|
tlvStructType name, value;
|
||||||
|
int32_t size = 0;
|
||||||
|
|
||||||
|
//extern const int32_t maxData;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &name);
|
||||||
|
|
||||||
|
if ( request_msg.buffer[name.start] != SNMPDTYPE_OBJ_ID ) return -1;
|
||||||
|
|
||||||
|
id = findEntry(&request_msg.buffer[name.vstart], name.len);
|
||||||
|
|
||||||
|
if ((reqType == GET_REQUEST) || (reqType == SET_REQUEST))
|
||||||
|
{
|
||||||
|
seglen = name.nstart - name.start;
|
||||||
|
COPY_SEGMENT(name);
|
||||||
|
size = seglen;
|
||||||
|
}
|
||||||
|
else if (reqType == GET_NEXT_REQUEST)
|
||||||
|
{
|
||||||
|
response_msg.buffer[response_msg.index] = request_msg.buffer[name.start];
|
||||||
|
|
||||||
|
if (++id >= maxData)
|
||||||
|
{
|
||||||
|
id = OID_NOT_FOUND;
|
||||||
|
seglen = name.nstart - name.start;
|
||||||
|
COPY_SEGMENT(name);
|
||||||
|
size = seglen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request_msg.index += name.nstart - name.start;
|
||||||
|
|
||||||
|
getOID(id, &response_msg.buffer[response_msg.index+2], &response_msg.buffer[response_msg.index+1]);
|
||||||
|
|
||||||
|
seglen = response_msg.buffer[response_msg.index+1]+2;
|
||||||
|
response_msg.index += seglen ;
|
||||||
|
size = seglen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &value);
|
||||||
|
|
||||||
|
if (id != OID_NOT_FOUND)
|
||||||
|
{
|
||||||
|
uint8_t dataType;
|
||||||
|
int32_t len;
|
||||||
|
|
||||||
|
if ((reqType == GET_REQUEST) || (reqType == GET_NEXT_REQUEST))
|
||||||
|
{
|
||||||
|
getEntry(id, &dataType, &response_msg.buffer[response_msg.index+2], &len);
|
||||||
|
|
||||||
|
response_msg.buffer[response_msg.index] = dataType;
|
||||||
|
response_msg.buffer[response_msg.index+1] = len;
|
||||||
|
seglen = (2 + len);
|
||||||
|
response_msg.index += seglen;
|
||||||
|
|
||||||
|
request_msg.index += (value.nstart - value.start);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (reqType == SET_REQUEST)
|
||||||
|
{
|
||||||
|
setEntry(id, &request_msg.buffer[value.vstart], value.len, request_msg.buffer[value.start], index);
|
||||||
|
seglen = value.nstart - value.start;
|
||||||
|
COPY_SEGMENT(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
seglen = value.nstart - value.start;
|
||||||
|
COPY_SEGMENT(value);
|
||||||
|
|
||||||
|
errorIndex = index;
|
||||||
|
errorStatus = NO_SUCH_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
size += seglen;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseSequence(int32_t reqType, int32_t index)
|
||||||
|
{
|
||||||
|
int32_t seglen;
|
||||||
|
tlvStructType seq;
|
||||||
|
int32_t size = 0, respLoc;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &seq);
|
||||||
|
|
||||||
|
if ( request_msg.buffer[seq.start] != SNMPDTYPE_SEQUENCE ) return -1;
|
||||||
|
|
||||||
|
seglen = seq.vstart - seq.start;
|
||||||
|
respLoc = response_msg.index;
|
||||||
|
COPY_SEGMENT(seq);
|
||||||
|
|
||||||
|
size = parseVarBind( reqType, index );
|
||||||
|
insertRespLen(seq.start, respLoc, size);
|
||||||
|
size += seglen;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseSequenceOf(int32_t reqType)
|
||||||
|
{
|
||||||
|
int32_t seglen;
|
||||||
|
tlvStructType seqof;
|
||||||
|
int32_t size = 0, respLoc;
|
||||||
|
int32_t index = 0;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &seqof);
|
||||||
|
|
||||||
|
if ( request_msg.buffer[seqof.start] != SNMPDTYPE_SEQUENCE_OF ) return -1;
|
||||||
|
|
||||||
|
seglen = seqof.vstart - seqof.start;
|
||||||
|
respLoc = response_msg.index;
|
||||||
|
COPY_SEGMENT(seqof);
|
||||||
|
|
||||||
|
while (request_msg.index < request_msg.len)
|
||||||
|
{
|
||||||
|
size += parseSequence( reqType, index++ );
|
||||||
|
}
|
||||||
|
|
||||||
|
insertRespLen(seqof.start, respLoc, size);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseRequest()
|
||||||
|
{
|
||||||
|
int32_t ret, seglen;
|
||||||
|
tlvStructType snmpreq, requestid, errStatus, errIndex;
|
||||||
|
int32_t size = 0, respLoc, reqType;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &snmpreq);
|
||||||
|
|
||||||
|
reqType = request_msg.buffer[snmpreq.start];
|
||||||
|
|
||||||
|
if ( !VALID_REQUEST(reqType) ) return -1;
|
||||||
|
|
||||||
|
seglen = snmpreq.vstart - snmpreq.start;
|
||||||
|
respLoc = snmpreq.start;
|
||||||
|
size += seglen;
|
||||||
|
COPY_SEGMENT(snmpreq);
|
||||||
|
|
||||||
|
response_msg.buffer[snmpreq.start] = GET_RESPONSE;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &requestid);
|
||||||
|
seglen = requestid.nstart - requestid.start;
|
||||||
|
size += seglen;
|
||||||
|
COPY_SEGMENT(requestid);
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &errStatus);
|
||||||
|
seglen = errStatus.nstart - errStatus.start;
|
||||||
|
size += seglen;
|
||||||
|
COPY_SEGMENT(errStatus);
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &errIndex);
|
||||||
|
seglen = errIndex.nstart - errIndex.start;
|
||||||
|
size += seglen;
|
||||||
|
COPY_SEGMENT(errIndex);
|
||||||
|
|
||||||
|
ret = parseSequenceOf(reqType);
|
||||||
|
if (ret == -1) return -1;
|
||||||
|
else size += ret;
|
||||||
|
|
||||||
|
insertRespLen(snmpreq.start, respLoc, size);
|
||||||
|
|
||||||
|
if (errorStatus)
|
||||||
|
{
|
||||||
|
response_msg.buffer[errStatus.vstart] = errorStatus;
|
||||||
|
response_msg.buffer[errIndex.vstart] = errorIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseCommunity()
|
||||||
|
{
|
||||||
|
int32_t seglen;
|
||||||
|
tlvStructType community;
|
||||||
|
int32_t size=0;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &community);
|
||||||
|
|
||||||
|
if (!((request_msg.buffer[community.start] == SNMPDTYPE_OCTET_STRING) && (community.len == COMMUNITY_SIZE)))
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!memcmp(&request_msg.buffer[community.vstart], (int8_t *)COMMUNITY, COMMUNITY_SIZE))
|
||||||
|
{
|
||||||
|
seglen = community.nstart - community.start;
|
||||||
|
size += seglen;
|
||||||
|
COPY_SEGMENT(community);
|
||||||
|
|
||||||
|
size += parseRequest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseVersion()
|
||||||
|
{
|
||||||
|
int32_t size = 0, seglen;
|
||||||
|
tlvStructType tlv;
|
||||||
|
|
||||||
|
size = parseTLV(request_msg.buffer, request_msg.index, &tlv);
|
||||||
|
|
||||||
|
if (!((request_msg.buffer[tlv.start] == SNMPDTYPE_INTEGER) && (request_msg.buffer[tlv.vstart] == SNMP_V1)))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
seglen = tlv.nstart - tlv.start;
|
||||||
|
size += seglen;
|
||||||
|
COPY_SEGMENT(tlv);
|
||||||
|
size = parseCommunity();
|
||||||
|
|
||||||
|
if (size == -1) return size;
|
||||||
|
else return (size + seglen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t parseSNMPMessage()
|
||||||
|
{
|
||||||
|
int32_t size = 0, seglen, respLoc;
|
||||||
|
tlvStructType tlv;
|
||||||
|
|
||||||
|
parseTLV(request_msg.buffer, request_msg.index, &tlv);
|
||||||
|
|
||||||
|
if (request_msg.buffer[tlv.start] != SNMPDTYPE_SEQUENCE_OF) return -1;
|
||||||
|
|
||||||
|
seglen = tlv.vstart - tlv.start;
|
||||||
|
respLoc = tlv.start;
|
||||||
|
COPY_SEGMENT(tlv);
|
||||||
|
|
||||||
|
size = parseVersion();
|
||||||
|
|
||||||
|
if (size == -1) return -1;
|
||||||
|
else size += seglen;
|
||||||
|
|
||||||
|
insertRespLen(tlv.start, respLoc, size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipToByteArray(int8_t *ip, uint8_t *pDes)
|
||||||
|
{
|
||||||
|
uint32_t i, ip1=0, ip2=0, ip3=0, ip4=0;
|
||||||
|
int8_t buff[32];
|
||||||
|
uint32_t len = (uint32_t)strlen((char const*)ip);
|
||||||
|
strcpy((char *)buff, (char const*)ip);
|
||||||
|
|
||||||
|
for (i=0; i<len; i++)
|
||||||
|
{
|
||||||
|
if ( buff[i]=='.' ) buff[i] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
sscanf((char const*)buff, "%u %u %u %u", &ip1, &ip2, &ip3, &ip4);
|
||||||
|
pDes[0] = ip1; pDes[1] = ip2; pDes[2] = ip3; pDes[3] = ip4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t makeTrapVariableBindings(dataEntryType *oid_data, void *ptr, uint32_t *len)
|
||||||
|
{
|
||||||
|
uint32_t j;
|
||||||
|
|
||||||
|
((uint8_t*)ptr)[0] = 0x30;
|
||||||
|
((uint8_t*)ptr)[1] = 0xff;
|
||||||
|
((uint8_t*)ptr)[2] = 0x06;
|
||||||
|
((uint8_t*)ptr)[3] = oid_data->oidlen;
|
||||||
|
|
||||||
|
for (j = 0 ; j < oid_data->oidlen ; j++)
|
||||||
|
{
|
||||||
|
((uint8_t*)ptr)[j+4] = oid_data->oid[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(oid_data->dataType)
|
||||||
|
{
|
||||||
|
case SNMPDTYPE_OCTET_STRING :
|
||||||
|
case SNMPDTYPE_OBJ_ID :
|
||||||
|
{
|
||||||
|
uint8_t *string = &((uint8_t*)ptr)[4+oid_data->oidlen+2];
|
||||||
|
|
||||||
|
if ( oid_data->dataType==SNMPDTYPE_OCTET_STRING )
|
||||||
|
{
|
||||||
|
oid_data->dataLen = (uint8_t)strlen((char const*)&oid_data->u.octetstring);
|
||||||
|
}
|
||||||
|
for (j = 0 ; j < oid_data->dataLen ; j++)
|
||||||
|
{
|
||||||
|
string[j] = oid_data->u.octetstring[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
((uint8_t*)ptr)[4+oid_data->oidlen] = oid_data->dataType;
|
||||||
|
((uint8_t*)ptr)[4+oid_data->oidlen+1] = oid_data->dataLen;
|
||||||
|
((uint8_t*)ptr)[1] = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
|
||||||
|
*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SNMPDTYPE_INTEGER :
|
||||||
|
case SNMPDTYPE_TIME_TICKS :
|
||||||
|
case SNMPDTYPE_COUNTER :
|
||||||
|
case SNMPDTYPE_GAUGE :
|
||||||
|
{
|
||||||
|
oid_data->dataLen = 4;
|
||||||
|
|
||||||
|
*(int32_t*)(&((uint8_t*)ptr)[4+oid_data->oidlen+2]) = HTONL(oid_data->u.intval);
|
||||||
|
|
||||||
|
((uint8_t*)ptr)[4+oid_data->oidlen] = oid_data->dataType;
|
||||||
|
((uint8_t*)ptr)[4+oid_data->oidlen+1] = oid_data->dataLen;
|
||||||
|
((uint8_t*)ptr)[1] = 2 + oid_data->oidlen + 2 + oid_data->dataLen;
|
||||||
|
*len = 4 + oid_data->oidlen + 2 + oid_data->dataLen;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
return INVALID_DATA_TYPE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SNMP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32_t snmp_sendTrap(uint8_t * managerIP, uint8_t * agentIP, int8_t* community, dataEntryType enterprise_oid, uint32_t genericTrap, uint32_t specificTrap, uint32_t va_count, ...)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
int32_t packet_index = 0;
|
||||||
|
int32_t packet_buff1 = 0;
|
||||||
|
int32_t packet_buff2 = 0;
|
||||||
|
int32_t packet_buff3 = 0;
|
||||||
|
|
||||||
|
va_list ap;
|
||||||
|
uint32_t length_var_bindings = 0;
|
||||||
|
uint32_t length_buff = 0;
|
||||||
|
|
||||||
|
//SNMP Trap packet generation
|
||||||
|
packet_trap[packet_index++] = 0x30; // ASN.1 Header
|
||||||
|
|
||||||
|
packet_trap[packet_index] = 0xff; // pdu_length, temp
|
||||||
|
packet_buff1 = packet_index++;
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x02; // Version
|
||||||
|
packet_trap[packet_index++] = 0x01;
|
||||||
|
packet_trap[packet_index++] = 0x00;
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x04; // Community
|
||||||
|
packet_trap[packet_index++] = (uint8_t)strlen((char const*)community);
|
||||||
|
memcpy(&(packet_trap[packet_index]), community, strlen((char const*)community));
|
||||||
|
|
||||||
|
packet_index = packet_index + (uint8_t)strlen((char const*)community);
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0xa4; // trap
|
||||||
|
packet_trap[packet_index] = 0xff; // length, temp
|
||||||
|
packet_buff2 = packet_index++;
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x06; // enterprise_oid
|
||||||
|
packet_trap[packet_index++] = enterprise_oid.oidlen;
|
||||||
|
for (i=0; i<enterprise_oid.oidlen; i++)
|
||||||
|
{
|
||||||
|
packet_trap[packet_index++] = enterprise_oid.oid[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x40; // agent ip
|
||||||
|
packet_trap[packet_index++] = 0x04;
|
||||||
|
packet_trap[packet_index++] = agentIP[0];
|
||||||
|
packet_trap[packet_index++] = agentIP[1];
|
||||||
|
packet_trap[packet_index++] = agentIP[2];
|
||||||
|
packet_trap[packet_index++] = agentIP[3];
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x02; // Generic Trap
|
||||||
|
packet_trap[packet_index++] = 0x01;
|
||||||
|
packet_trap[packet_index++] = (uint8_t)genericTrap;
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x02; // Specific Trap
|
||||||
|
packet_trap[packet_index++] = 0x01;
|
||||||
|
packet_trap[packet_index++] = (uint8_t)specificTrap;
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x43; // Timestamp
|
||||||
|
packet_trap[packet_index++] = 0x01;
|
||||||
|
packet_trap[packet_index++] = 0x00;
|
||||||
|
|
||||||
|
packet_trap[packet_index++] = 0x30; // Sequence of variable-bindings
|
||||||
|
packet_trap[packet_index] = 0xff;
|
||||||
|
packet_buff3 = packet_index++;
|
||||||
|
|
||||||
|
// variable-bindings
|
||||||
|
{
|
||||||
|
va_start (ap, va_count);
|
||||||
|
|
||||||
|
for (i=0; i<va_count; i++)
|
||||||
|
{
|
||||||
|
dataEntryType* fff = va_arg(ap, dataEntryType*);
|
||||||
|
makeTrapVariableBindings(fff, &(packet_trap[packet_index]), &length_buff);
|
||||||
|
packet_index = packet_index + length_buff;
|
||||||
|
length_var_bindings = length_var_bindings + length_buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_trap[packet_buff3] = length_var_bindings;
|
||||||
|
|
||||||
|
va_end (ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
packet_trap[packet_buff1] = packet_index - 2;
|
||||||
|
packet_trap[packet_buff2] = packet_index - (9 + (uint8_t)strlen((char const*)community));
|
||||||
|
|
||||||
|
// Send SNMP Trap Packet to NMS
|
||||||
|
{
|
||||||
|
socket(SOCK_SNMP_TRAP, Sn_MR_UDP, PORT_SNMP_TRAP, 0);
|
||||||
|
sendto(SOCK_SNMP_TRAP, packet_trap, packet_index, managerIP, PORT_SNMP_TRAP);
|
||||||
|
|
||||||
|
close(SOCK_SNMP_TRAP);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _SNMP_DEBUG_
|
||||||
|
void dumpCode(uint8_t* header, uint8_t* tail, uint8_t *buff, int32_t len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
printf((char const*)header);
|
||||||
|
|
||||||
|
for (i=0; i<len; i++)
|
||||||
|
{
|
||||||
|
if ( i%16==0 ) printf("0x%04x : ", i);
|
||||||
|
printf("%02x ",buff[i]);
|
||||||
|
|
||||||
|
if ( i%16-15==0 )
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
printf(" ");
|
||||||
|
for (j=i-15; j<=i; j++)
|
||||||
|
{
|
||||||
|
if ( isprint(buff[j]) ) printf("%c", buff[j]);
|
||||||
|
else printf(".");
|
||||||
|
}
|
||||||
|
printf("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( i%16!=0 )
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
int spaces=(len-i+16-i%16)*3+2;
|
||||||
|
for (j=0; j<spaces; j++) printf(" ");
|
||||||
|
for (j=i-i%16; j<len; j++)
|
||||||
|
{
|
||||||
|
if ( isprint(buff[j]) ) printf("%c", buff[j]);
|
||||||
|
else printf(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf((char const*)tail);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
114
Internet/SNMP/snmp.h
Normal file
114
Internet/SNMP/snmp.h
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#ifndef _SNMP_H_
|
||||||
|
#define _SNMP_H_
|
||||||
|
|
||||||
|
// SNMP Debug Message (dump) Enable
|
||||||
|
#define _SNMP_DEBUG_
|
||||||
|
|
||||||
|
#define PORT_SNMP_AGENT 161
|
||||||
|
#define PORT_SNMP_TRAP 162
|
||||||
|
|
||||||
|
#define SNMP_V1 0
|
||||||
|
|
||||||
|
#define MAX_OID 12
|
||||||
|
#define MAX_STRING 64
|
||||||
|
#define MAX_SNMPMSG_LEN 512
|
||||||
|
#define MAX_TRAPMSG_LEN 512
|
||||||
|
|
||||||
|
// SNMP Error code
|
||||||
|
#define SNMP_SUCCESS 0
|
||||||
|
#define OID_NOT_FOUND -1
|
||||||
|
#define TABLE_FULL -2
|
||||||
|
#define ILLEGAL_LENGTH -3
|
||||||
|
#define INVALID_ENTRY_ID -4
|
||||||
|
#define INVALID_DATA_TYPE -5
|
||||||
|
|
||||||
|
#define NO_SUCH_NAME 2
|
||||||
|
#define BAD_VALUE 3
|
||||||
|
|
||||||
|
// SNMPv1 Commands
|
||||||
|
#define GET_REQUEST 0xa0
|
||||||
|
#define GET_NEXT_REQUEST 0xa1
|
||||||
|
#define GET_RESPONSE 0xa2
|
||||||
|
#define SET_REQUEST 0xa3
|
||||||
|
|
||||||
|
// Macros: SNMPv1 request validation checker
|
||||||
|
#define VALID_REQUEST(x) ((x == GET_REQUEST) || (x == GET_NEXT_REQUEST) || (x == SET_REQUEST))
|
||||||
|
|
||||||
|
// SNMPv1 Return Types
|
||||||
|
#define SNMPDTYPE_INTEGER 0x02
|
||||||
|
#define SNMPDTYPE_OCTET_STRING 0x04
|
||||||
|
#define SNMPDTYPE_NULL_ITEM 0x05
|
||||||
|
#define SNMPDTYPE_OBJ_ID 0x06
|
||||||
|
#define SNMPDTYPE_SEQUENCE 0x30
|
||||||
|
#define SNMPDTYPE_SEQUENCE_OF SNMPDTYPE_SEQUENCE
|
||||||
|
|
||||||
|
#define SNMPDTYPE_COUNTER 0x41
|
||||||
|
#define SNMPDTYPE_GAUGE 0x42
|
||||||
|
#define SNMPDTYPE_TIME_TICKS 0x43
|
||||||
|
#define SNMPDTYPE_OPAQUE 0x44
|
||||||
|
|
||||||
|
// SNMP Trap: Standard Trap Types (Generic)
|
||||||
|
#define SNMPTRAP_COLDSTART 0x00 // Generic trap-type 0: Cold Start
|
||||||
|
#define SNMPTRAP_WARMSTART 0x01 // Generic trap-type 1: Warm Start
|
||||||
|
#define SNMPTRAP_LINKDOWN 0x02 // Generic trap-type 2: Link Down
|
||||||
|
#define SNMPTRAP_LINKUP 0x03 // Generic trap-type 3: Link Up
|
||||||
|
#define SNMPTRAP_AUTHENTICATION 0x04 // Generic trap-type 4: Authentication Failure
|
||||||
|
#define SNMPTRAP_EGPNEIGHBORLOSS 0x05 // Generic trap-type 5: EGP Neighbor Loss
|
||||||
|
|
||||||
|
// Macros
|
||||||
|
#define COPY_SEGMENT(x) \
|
||||||
|
{ \
|
||||||
|
request_msg.index += seglen; \
|
||||||
|
memcpy(&response_msg.buffer[response_msg.index], &request_msg.buffer[x.start], seglen ); \
|
||||||
|
response_msg.index += seglen; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HTONL
|
||||||
|
#define HTONL(x) \
|
||||||
|
((((x) >> 24) & 0x000000ff) | \
|
||||||
|
(((x) >> 8) & 0x0000ff00) | \
|
||||||
|
(((x) << 8) & 0x00ff0000) | \
|
||||||
|
(((x) << 24) & 0xff000000))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t oidlen;
|
||||||
|
uint8_t oid[MAX_OID];
|
||||||
|
uint8_t dataType;
|
||||||
|
uint8_t dataLen;
|
||||||
|
union {
|
||||||
|
uint8_t octetstring[MAX_STRING];
|
||||||
|
uint32_t intval;
|
||||||
|
} u;
|
||||||
|
void (*getfunction)(void *, uint8_t *);
|
||||||
|
void (*setfunction)(int32_t);
|
||||||
|
} dataEntryType;
|
||||||
|
|
||||||
|
struct messageStruct {
|
||||||
|
uint8_t buffer[MAX_SNMPMSG_LEN];
|
||||||
|
int32_t len;
|
||||||
|
int32_t index;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t start; /* Absolute Index of the TLV */
|
||||||
|
int32_t len; /* The L value of the TLV */
|
||||||
|
int32_t vstart; /* Absolute Index of this TLV's Value */
|
||||||
|
int32_t nstart; /* Absolute Index of the next TLV */
|
||||||
|
} tlvStructType;
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************************************************/
|
||||||
|
/* SNMP : Functions */
|
||||||
|
/********************************************************************************************/
|
||||||
|
// SNMP Main functions
|
||||||
|
void snmpd_init(uint8_t * managerIP, uint8_t * agentIP, uint8_t sn_agent, uint8_t sn_trap);
|
||||||
|
int32_t snmpd_run(void);
|
||||||
|
int32_t snmp_sendTrap(uint8_t * managerIP, uint8_t * agentIP, int8_t* community, dataEntryType enterprise_oid, uint32_t genericTrap, uint32_t specificTrap, uint32_t va_count, ...);
|
||||||
|
|
||||||
|
// SNMP Time handler functions
|
||||||
|
void SNMP_time_handler(void);
|
||||||
|
uint32_t getSNMPTimeTick(void);
|
||||||
|
void currentUptime(void *ptr, uint8_t *len);
|
||||||
|
|
||||||
|
#endif
|
147
Internet/SNMP/snmp_custom.c
Normal file
147
Internet/SNMP/snmp_custom.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
|
||||||
|
/********************************************************************************************
|
||||||
|
* SNMP : User Customization Part
|
||||||
|
* - OID Registration
|
||||||
|
* - User defined functions for OID related
|
||||||
|
* + Integer value, String
|
||||||
|
* + I/O control / Chip registers
|
||||||
|
* + Network Informations
|
||||||
|
* + Etc.
|
||||||
|
*
|
||||||
|
*********************************************************************************************/
|
||||||
|
#include "snmp_custom.h"
|
||||||
|
|
||||||
|
#ifdef _USE_WIZNET_W5500_EVB_
|
||||||
|
#include "board.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dataEntryType snmpData[] =
|
||||||
|
{
|
||||||
|
// System MIB
|
||||||
|
// SysDescr Entry
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 1, 0},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 30, {"WIZnet Embedded SNMP Agent"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// SysObjectID Entry
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 2, 0},
|
||||||
|
SNMPDTYPE_OBJ_ID, 8, {"\x2b\x06\x01\x02\x01\x01\x02\x00"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// SysUptime Entry
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 3, 0},
|
||||||
|
SNMPDTYPE_TIME_TICKS, 0, {""},
|
||||||
|
currentUptime, NULL},
|
||||||
|
|
||||||
|
// sysContact Entry
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 4, 0},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 30, {"http://www.wizwiki.net/forum"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// sysName Entry
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 5, 0},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 30, {"http://www.wiznet.co.kr"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// Location Entry
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 6, 0},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 30, {"4F Humax Village"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// SysServices
|
||||||
|
{8, {0x2b, 6, 1, 2, 1, 1, 7, 0},
|
||||||
|
SNMPDTYPE_INTEGER, 4, {""},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
#ifdef _USE_WIZNET_W5500_EVB_
|
||||||
|
// Get the WIZnet W5500-EVB LED Status
|
||||||
|
{8, {0x2b, 6, 1, 4, 1, 6, 1, 0},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 40, {""},
|
||||||
|
get_LEDStatus_all, NULL},
|
||||||
|
|
||||||
|
// Set the LED_R (RGB LED)
|
||||||
|
{8, {0x2b, 6, 1, 4, 1, 6, 1, 1},
|
||||||
|
SNMPDTYPE_INTEGER, 4, {""},
|
||||||
|
NULL, set_LEDStatus_R},
|
||||||
|
|
||||||
|
// Set the LED_G (RGB LED)
|
||||||
|
{8, {0x2b, 6, 1, 4, 1, 6, 1, 2},
|
||||||
|
SNMPDTYPE_INTEGER, 4, {""},
|
||||||
|
NULL, set_LEDStatus_G},
|
||||||
|
|
||||||
|
// Set the LED_B (RGB LED)
|
||||||
|
{8, {0x2b, 6, 1, 4, 1, 6, 1, 3},
|
||||||
|
SNMPDTYPE_INTEGER, 4, {""},
|
||||||
|
NULL, set_LEDStatus_B},
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// OID Test #1 (long-length OID example, 19865)
|
||||||
|
{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test #1"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// OID Test #2 (long-length OID example, 22210)
|
||||||
|
{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x01, 0x00},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 35, {"long-length OID Test #2"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
// OID Test #2: SysObjectID Entry
|
||||||
|
{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0xad, 0x42, 0x02, 0x00},
|
||||||
|
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\xad\x42\x02\x00"},
|
||||||
|
NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
const int32_t maxData = (sizeof(snmpData) / sizeof(dataEntryType));
|
||||||
|
|
||||||
|
void initTable()
|
||||||
|
{
|
||||||
|
// Example integer value for [OID 1.3.6.1.2.1.1.7.0]
|
||||||
|
snmpData[6].u.intval = -5;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// W5500-EVB: LED Control ///////////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef _USE_WIZNET_W5500_EVB_
|
||||||
|
void get_LEDStatus_all(void *ptr, uint8_t *len)
|
||||||
|
{
|
||||||
|
uint8_t led_status[3] = {0, };
|
||||||
|
|
||||||
|
led_status[LED_R] = (uint8_t)Board_LED_Test(LED_R);
|
||||||
|
led_status[LED_G] = (uint8_t)Board_LED_Test(LED_G);
|
||||||
|
led_status[LED_B] = (uint8_t)Board_LED_Test(LED_B);
|
||||||
|
|
||||||
|
*len = sprintf((char *)ptr, "LED R [%s] / G [%s] / B [%s]", led_status[LED_R]?"On":"Off", led_status[LED_G]?"On":"Off", led_status[LED_B]?"On":"Off");
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_LEDStatus_R(int32_t val)
|
||||||
|
{
|
||||||
|
if(val == 0) Board_LED_Set(LED_R, false);
|
||||||
|
else Board_LED_Set(LED_R, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_LEDStatus_G(int32_t val)
|
||||||
|
{
|
||||||
|
if(val == 0) Board_LED_Set(LED_G, false);
|
||||||
|
else Board_LED_Set(LED_G, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_LEDStatus_B(int32_t val)
|
||||||
|
{
|
||||||
|
if(val == 0) Board_LED_Set(LED_B, false);
|
||||||
|
else Board_LED_Set(LED_B, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void initial_Trap(uint8_t * managerIP, uint8_t * agentIP)
|
||||||
|
{
|
||||||
|
// SNMP Trap: WarmStart(1) Trap
|
||||||
|
{
|
||||||
|
dataEntryType enterprise_oid = {0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
|
||||||
|
SNMPDTYPE_OBJ_ID, 0x0a, {"\x2b\x06\x01\x04\x01\x81\x9b\x19\x10\x00"}, NULL, NULL};
|
||||||
|
// Generic Trap: warmStart COMMUNITY
|
||||||
|
snmp_sendTrap(managerIP, agentIP, (void *)COMMUNITY, enterprise_oid, SNMPTRAP_WARMSTART, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
Internet/SNMP/snmp_custom.h
Normal file
33
Internet/SNMP/snmp_custom.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef _SNMP_CUSTOM_H_
|
||||||
|
#define _SNMP_CUSTOM_H_
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "snmp.h"
|
||||||
|
|
||||||
|
extern dataEntryType snmpData[];
|
||||||
|
extern const int32_t maxData;
|
||||||
|
|
||||||
|
// Define for using W5500-EVB: H/W Dependency (e.g., LEDs...)
|
||||||
|
//#define _USE_WIZNET_W5500_EVB_
|
||||||
|
|
||||||
|
#define COMMUNITY "public\0"
|
||||||
|
#define COMMUNITY_SIZE (strlen(COMMUNITY))
|
||||||
|
|
||||||
|
/* Predefined function: Response value control */
|
||||||
|
void initTable();
|
||||||
|
|
||||||
|
/* User defined functions: LED control examples */
|
||||||
|
#ifdef _USE_WIZNET_W5500_EVB_
|
||||||
|
void get_LEDStatus_all(void *ptr, uint8_t *len);
|
||||||
|
void set_LEDStatus_R(int32_t val);
|
||||||
|
void set_LEDStatus_G(int32_t val);
|
||||||
|
void set_LEDStatus_B(int32_t val);
|
||||||
|
#endif
|
||||||
|
/* SNMP Trap: warmStart(1) */
|
||||||
|
void initial_Trap(uint8_t * managerIP, uint8_t * agentIP);
|
||||||
|
|
||||||
|
#endif
|
45
Internet/SNMP/tools/OID_Converter/Readme.txt
Normal file
45
Internet/SNMP/tools/OID_Converter/Readme.txt
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
============================================================
|
||||||
|
<OID encoding steps for WIZnet SNMP Agent>
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
+ Example OID for convert
|
||||||
|
1.3.6.1.4.1.19865.1.0
|
||||||
|
|
||||||
|
(1) Convert Usage
|
||||||
|
CMD>>oid 1.3.6.1.4.1.19865.1.0
|
||||||
|
=> 06 0A 2B 06 01 04 01 81 9B 19 01 00
|
||||||
|
|
||||||
|
>> TLV(tag-length-value) Example OID
|
||||||
|
(06) Tag
|
||||||
|
(0A) Length
|
||||||
|
[2B] 1(iso).3(identified-organization) (in ASN.1 BER encoding, i.e. 1*40+3 = 0x2b)
|
||||||
|
[06] 6(dod)
|
||||||
|
[01] 1(internet)
|
||||||
|
[04] 4(private)
|
||||||
|
[01] 1(enterprise)
|
||||||
|
[81 9B 19] 19865(Vendor-Specific)
|
||||||
|
...
|
||||||
|
|
||||||
|
(2) Add the entry to OID table in source code (DataEntryType, put the converted value to array)
|
||||||
|
{0x0a, {0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x9b, 0x19, 0x01, 0x00},
|
||||||
|
SNMPDTYPE_OCTET_STRING, 30, {"long-length OID Test"},
|
||||||
|
NULL, NULL},
|
||||||
|
|
||||||
|
============================================================
|
||||||
|
OID Converter: OID encoder/decoder
|
||||||
|
v1.3 - Matthias Gaertner 1999/2001 - Freeware
|
||||||
|
============================================================
|
||||||
|
|
||||||
|
The OID converter is a handy little tool to convert ASN.1 OIDs from readable dotted decimal notation to binary hexadecimal Distinguished Encoding Rules (DER) representation and vice versa.
|
||||||
|
If you're into x.509 certificates, this may be useful to you, too.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
OID [-c|-C] [-o] {-i|1.2.3.4}
|
||||||
|
converts dotted form to ASCII HEX DER output.
|
||||||
|
OID -x [-o] {-i|hex-digits}
|
||||||
|
decodes ASCII HEX DER and gives dotted form.
|
||||||
|
|
||||||
|
If you need more information, please refer to Matthias Gaertner's page,
|
||||||
|
http://www.rtner.de/software/oid.html
|
||||||
|
|
||||||
|
===============================================================================================
|
33
Internet/SNMP/tools/net-snmp-5.7(win32-bin)/snmptrapd.conf
Normal file
33
Internet/SNMP/tools/net-snmp-5.7(win32-bin)/snmptrapd.conf
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#
|
||||||
|
# net-snmp (or ucd-snmp) persistent data file.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
# STOP STOP STOP STOP STOP STOP STOP STOP STOP
|
||||||
|
#
|
||||||
|
# **** DO NOT EDIT THIS FILE ****
|
||||||
|
#
|
||||||
|
# STOP STOP STOP STOP STOP STOP STOP STOP STOP
|
||||||
|
############################################################################
|
||||||
|
#
|
||||||
|
# DO NOT STORE CONFIGURATION ENTRIES HERE.
|
||||||
|
# Please save normal configuration tokens for snmptrapd in SNMPCONFPATH/snmptrapd.conf.
|
||||||
|
# Only "createUser" tokens should be placed here by snmptrapd administrators.
|
||||||
|
# (Did I mention: do not edit this file?)
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
authCommunity log,execute,net public
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
engineBoots 1
|
||||||
|
oldEngineID 0x80001f88803d6f00001ba7934e00000000
|
448
Internet/SNTP/sntp.c
Normal file
448
Internet/SNTP/sntp.c
Normal file
@ -0,0 +1,448 @@
|
|||||||
|
/*
|
||||||
|
* sntp.c
|
||||||
|
*
|
||||||
|
* Created on: 2014. 12. 15.
|
||||||
|
* Author: Administrator
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "sntp.h"
|
||||||
|
#include "socket.h"
|
||||||
|
|
||||||
|
ntpformat NTPformat;
|
||||||
|
datetime Nowdatetime;
|
||||||
|
uint8_t ntpmessage[48];
|
||||||
|
uint8_t *data_buf;
|
||||||
|
uint8_t NTP_SOCKET;
|
||||||
|
uint8_t time_zone;
|
||||||
|
uint16_t ntp_retry_cnt=0; //counting the ntp retry number
|
||||||
|
|
||||||
|
/*
|
||||||
|
00)UTC-12:00 Baker Island, Howland Island (both uninhabited)
|
||||||
|
01) UTC-11:00 American Samoa, Samoa
|
||||||
|
02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii)
|
||||||
|
03) UTC-09:30 Marquesas Islands
|
||||||
|
04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska)
|
||||||
|
05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California)
|
||||||
|
06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state))
|
||||||
|
07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta)
|
||||||
|
08) UTC-07:00 Mexico (Chihuahua), United States (Colorado)
|
||||||
|
09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras
|
||||||
|
10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas)
|
||||||
|
11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru
|
||||||
|
12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec)
|
||||||
|
13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.)
|
||||||
|
14) UTC-04:30 Venezuela
|
||||||
|
15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay,
|
||||||
|
16) UTC-04:00 Puerto Rico, Trinidad and Tobago
|
||||||
|
17) UTC-03:30 Canada (Newfoundland)
|
||||||
|
18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay
|
||||||
|
19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands
|
||||||
|
20) UTC-01:00 Portugal (Azores), Cape Verde
|
||||||
|
21) UTC±00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira)
|
||||||
|
22) UTC±00:00 Spain (Canary Islands), Morocco, United Kingdom
|
||||||
|
23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina,
|
||||||
|
24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo,
|
||||||
|
25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland
|
||||||
|
26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia,
|
||||||
|
27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine
|
||||||
|
28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia,
|
||||||
|
29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen
|
||||||
|
30) UTC+03:30 (Summer)Iran
|
||||||
|
31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates
|
||||||
|
32) UTC+04:30 Afghanistan
|
||||||
|
33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan
|
||||||
|
34) UTC+05:30 India, Sri Lanka
|
||||||
|
35) UTC+05:45 Nepal
|
||||||
|
36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast)
|
||||||
|
37) UTC+06:30 Cocos Islands, Myanmar
|
||||||
|
38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam
|
||||||
|
39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia
|
||||||
|
40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan
|
||||||
|
41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia))
|
||||||
|
42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria)
|
||||||
|
43) UTC+10:30 Lord Howe Island
|
||||||
|
44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands
|
||||||
|
45) UTC+11:30 Norfolk Island
|
||||||
|
46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand
|
||||||
|
47) UTC+12:45 (Summer)New Zealand
|
||||||
|
48) UTC+13:00 Tonga
|
||||||
|
49) UTC+14:00 Kiribati (Line Islands)
|
||||||
|
*/
|
||||||
|
void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx)
|
||||||
|
{
|
||||||
|
tstamp seconds = 0;
|
||||||
|
uint8_t i=0;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
seconds = (seconds << 8) | buf[idx + i];
|
||||||
|
}
|
||||||
|
switch (time_zone)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
seconds -= 12*3600;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
seconds -= 11*3600;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
seconds -= 10*3600;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
seconds -= (9*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
seconds -= 9*3600;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
case 6:
|
||||||
|
seconds -= 8*3600;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
seconds -= 7*3600;
|
||||||
|
break;
|
||||||
|
case 9:
|
||||||
|
case 10:
|
||||||
|
seconds -= 6*3600;
|
||||||
|
break;
|
||||||
|
case 11:
|
||||||
|
case 12:
|
||||||
|
case 13:
|
||||||
|
seconds -= 5*3600;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
seconds -= (4*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 15:
|
||||||
|
case 16:
|
||||||
|
seconds -= 4*3600;
|
||||||
|
break;
|
||||||
|
case 17:
|
||||||
|
seconds -= (3*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 18:
|
||||||
|
seconds -= 3*3600;
|
||||||
|
break;
|
||||||
|
case 19:
|
||||||
|
seconds -= 2*3600;
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
seconds -= 1*3600;
|
||||||
|
break;
|
||||||
|
case 21: //?
|
||||||
|
case 22:
|
||||||
|
break;
|
||||||
|
case 23:
|
||||||
|
case 24:
|
||||||
|
case 25:
|
||||||
|
seconds += 1*3600;
|
||||||
|
break;
|
||||||
|
case 26:
|
||||||
|
case 27:
|
||||||
|
seconds += 2*3600;
|
||||||
|
break;
|
||||||
|
case 28:
|
||||||
|
case 29:
|
||||||
|
seconds += 3*3600;
|
||||||
|
break;
|
||||||
|
case 30:
|
||||||
|
seconds += (3*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 31:
|
||||||
|
seconds += 4*3600;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
seconds += (4*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 33:
|
||||||
|
seconds += 5*3600;
|
||||||
|
break;
|
||||||
|
case 34:
|
||||||
|
seconds += (5*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 35:
|
||||||
|
seconds += (5*3600+45*60);
|
||||||
|
break;
|
||||||
|
case 36:
|
||||||
|
seconds += 6*3600;
|
||||||
|
break;
|
||||||
|
case 37:
|
||||||
|
seconds += (6*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 38:
|
||||||
|
seconds += 7*3600;
|
||||||
|
break;
|
||||||
|
case 39:
|
||||||
|
seconds += 8*3600;
|
||||||
|
break;
|
||||||
|
case 40:
|
||||||
|
seconds += 9*3600;
|
||||||
|
break;
|
||||||
|
case 41:
|
||||||
|
seconds += (9*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 42:
|
||||||
|
seconds += 10*3600;
|
||||||
|
break;
|
||||||
|
case 43:
|
||||||
|
seconds += (10*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 44:
|
||||||
|
seconds += 11*3600;
|
||||||
|
break;
|
||||||
|
case 45:
|
||||||
|
seconds += (11*3600+30*60);
|
||||||
|
break;
|
||||||
|
case 46:
|
||||||
|
seconds += 12*3600;
|
||||||
|
break;
|
||||||
|
case 47:
|
||||||
|
seconds += (12*3600+45*60);
|
||||||
|
break;
|
||||||
|
case 48:
|
||||||
|
seconds += 13*3600;
|
||||||
|
break;
|
||||||
|
case 49:
|
||||||
|
seconds += 14*3600;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculation for date
|
||||||
|
calcdatetime(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf)
|
||||||
|
{
|
||||||
|
NTPformat.dstaddr[0] = ntp_server[0];
|
||||||
|
NTPformat.dstaddr[1] = ntp_server[1];
|
||||||
|
NTPformat.dstaddr[2] = ntp_server[2];
|
||||||
|
NTPformat.dstaddr[3] = ntp_server[3];
|
||||||
|
|
||||||
|
time_zone = tz;
|
||||||
|
|
||||||
|
data_buf = buf;
|
||||||
|
|
||||||
|
uint8_t Flag;
|
||||||
|
NTPformat.leap = 0; /* leap indicator */
|
||||||
|
NTPformat.version = 4; /* version number */
|
||||||
|
NTPformat.mode = 3; /* mode */
|
||||||
|
NTPformat.stratum = 0; /* stratum */
|
||||||
|
NTPformat.poll = 0; /* poll interval */
|
||||||
|
NTPformat.precision = 0; /* precision */
|
||||||
|
NTPformat.rootdelay = 0; /* root delay */
|
||||||
|
NTPformat.rootdisp = 0; /* root dispersion */
|
||||||
|
NTPformat.refid = 0; /* reference ID */
|
||||||
|
NTPformat.reftime = 0; /* reference time */
|
||||||
|
NTPformat.org = 0; /* origin timestamp */
|
||||||
|
NTPformat.rec = 0; /* receive timestamp */
|
||||||
|
NTPformat.xmt = 1; /* transmit timestamp */
|
||||||
|
|
||||||
|
Flag = (NTPformat.leap<<6)+(NTPformat.version<<3)+NTPformat.mode; //one byte Flag
|
||||||
|
memcpy(ntpmessage,(void const*)(&Flag),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t SNTP_run(datetime *time)
|
||||||
|
{
|
||||||
|
uint16_t RSR_len;
|
||||||
|
uint32_t destip = 0;
|
||||||
|
uint16_t destport;
|
||||||
|
uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40
|
||||||
|
|
||||||
|
switch(getSn_SR(NTP_SOCKET))
|
||||||
|
{
|
||||||
|
case SOCK_UDP:
|
||||||
|
if ((RSR_len = getSn_RX_RSR(NTP_SOCKET)) > 0)
|
||||||
|
{
|
||||||
|
if (RSR_len > MAX_SNTP_BUF_SIZE) RSR_len = MAX_SNTP_BUF_SIZE; // if Rx data size is lager than TX_RX_MAX_BUF_SIZE
|
||||||
|
recvfrom(NTP_SOCKET, data_buf, RSR_len, (uint8_t *)&destip, &destport);
|
||||||
|
|
||||||
|
get_seconds_from_ntp_server(data_buf,startindex);
|
||||||
|
time->yy = Nowdatetime.yy;
|
||||||
|
time->mo = Nowdatetime.mo;
|
||||||
|
time->dd = Nowdatetime.dd;
|
||||||
|
time->hh = Nowdatetime.hh;
|
||||||
|
time->mm = Nowdatetime.mm;
|
||||||
|
time->ss = Nowdatetime.ss;
|
||||||
|
|
||||||
|
ntp_retry_cnt=0;
|
||||||
|
close(NTP_SOCKET);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ntp_retry_cnt<0xFFFF)
|
||||||
|
{
|
||||||
|
if(ntp_retry_cnt==0)//first send request, no need to wait
|
||||||
|
{
|
||||||
|
sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port);
|
||||||
|
ntp_retry_cnt++;
|
||||||
|
}
|
||||||
|
else // send request again? it should wait for a while
|
||||||
|
{
|
||||||
|
if((ntp_retry_cnt % 0xFFF) == 0) //wait time
|
||||||
|
{
|
||||||
|
sendto(NTP_SOCKET,ntpmessage,sizeof(ntpmessage),NTPformat.dstaddr,ntp_port);
|
||||||
|
#ifdef _SNTP_DEBUG_
|
||||||
|
printf("ntp retry: %d\r\n", ntp_retry_cnt);
|
||||||
|
#endif
|
||||||
|
ntp_retry_cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //ntp retry fail
|
||||||
|
{
|
||||||
|
ntp_retry_cnt=0;
|
||||||
|
#ifdef _SNTP_DEBUG_
|
||||||
|
printf("ntp retry failed!\r\n");
|
||||||
|
#endif
|
||||||
|
close(NTP_SOCKET);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SOCK_CLOSED:
|
||||||
|
socket(NTP_SOCKET,Sn_MR_UDP,ntp_port,0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Return value
|
||||||
|
// 0 - failed / 1 - success
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calcdatetime(tstamp seconds)
|
||||||
|
{
|
||||||
|
uint8_t yf=0;
|
||||||
|
tstamp n=0,d=0,total_d=0,rz=0;
|
||||||
|
uint16_t y=0,r=0,yr=0;
|
||||||
|
signed long long yd=0;
|
||||||
|
|
||||||
|
n = seconds;
|
||||||
|
total_d = seconds/(SECS_PERDAY);
|
||||||
|
d=0;
|
||||||
|
uint32_t p_year_total_sec=SECS_PERDAY*365;
|
||||||
|
uint32_t r_year_total_sec=SECS_PERDAY*366;
|
||||||
|
while(n>=p_year_total_sec)
|
||||||
|
{
|
||||||
|
if((EPOCH+r)%400==0 || ((EPOCH+r)%100!=0 && (EPOCH+r)%4==0))
|
||||||
|
{
|
||||||
|
n = n -(r_year_total_sec);
|
||||||
|
d = d + 366;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = n - (p_year_total_sec);
|
||||||
|
d = d + 365;
|
||||||
|
}
|
||||||
|
r+=1;
|
||||||
|
y+=1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
y += EPOCH;
|
||||||
|
|
||||||
|
Nowdatetime.yy = y;
|
||||||
|
|
||||||
|
yd=0;
|
||||||
|
yd = total_d - d;
|
||||||
|
|
||||||
|
yf=1;
|
||||||
|
while(yd>=28)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(yf==1 || yf==3 || yf==5 || yf==7 || yf==8 || yf==10 || yf==12)
|
||||||
|
{
|
||||||
|
yd -= 31;
|
||||||
|
if(yd<0)break;
|
||||||
|
rz += 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yf==2)
|
||||||
|
{
|
||||||
|
if (y%400==0 || (y%100!=0 && y%4==0))
|
||||||
|
{
|
||||||
|
yd -= 29;
|
||||||
|
if(yd<0)break;
|
||||||
|
rz += 29;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yd -= 28;
|
||||||
|
if(yd<0)break;
|
||||||
|
rz += 28;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(yf==4 || yf==6 || yf==9 || yf==11 )
|
||||||
|
{
|
||||||
|
yd -= 30;
|
||||||
|
if(yd<0)break;
|
||||||
|
rz += 30;
|
||||||
|
}
|
||||||
|
yf += 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
Nowdatetime.mo=yf;
|
||||||
|
yr = total_d-d-rz;
|
||||||
|
|
||||||
|
yr += 1;
|
||||||
|
|
||||||
|
Nowdatetime.dd=yr;
|
||||||
|
|
||||||
|
//calculation for time
|
||||||
|
seconds = seconds%SECS_PERDAY;
|
||||||
|
Nowdatetime.hh = seconds/3600;
|
||||||
|
Nowdatetime.mm = (seconds%3600)/60;
|
||||||
|
Nowdatetime.ss = (seconds%3600)%60;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tstamp changedatetime_to_seconds(void)
|
||||||
|
{
|
||||||
|
tstamp seconds=0;
|
||||||
|
uint32_t total_day=0;
|
||||||
|
uint16_t i=0,run_year_cnt=0,l=0;
|
||||||
|
|
||||||
|
l = Nowdatetime.yy;//low
|
||||||
|
|
||||||
|
|
||||||
|
for(i=EPOCH;i<l;i++)
|
||||||
|
{
|
||||||
|
if((i%400==0) || ((i%100!=0) && (i%4==0)))
|
||||||
|
{
|
||||||
|
run_year_cnt += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total_day=(l-EPOCH-run_year_cnt)*365+run_year_cnt*366;
|
||||||
|
|
||||||
|
for(i=1;i<=Nowdatetime.mo;i++)
|
||||||
|
{
|
||||||
|
if(i==5 || i==7 || i==10 || i==12)
|
||||||
|
{
|
||||||
|
total_day += 30;
|
||||||
|
}
|
||||||
|
if (i==3)
|
||||||
|
{
|
||||||
|
if (l%400==0 && l%100!=0 && l%4==0)
|
||||||
|
{
|
||||||
|
total_day += 29;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
total_day += 28;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(i==2 || i==4 || i==6 || i==8 || i==9 || i==11)
|
||||||
|
{
|
||||||
|
total_day += 31;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
seconds = (total_day+Nowdatetime.dd-1)*24*3600;
|
||||||
|
seconds += Nowdatetime.ss;//seconds
|
||||||
|
seconds += Nowdatetime.mm*60;//minute
|
||||||
|
seconds += Nowdatetime.hh*3600;//hour
|
||||||
|
|
||||||
|
return seconds;
|
||||||
|
}
|
68
Internet/SNTP/sntp.h
Normal file
68
Internet/SNTP/sntp.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* sntp.h
|
||||||
|
*
|
||||||
|
* Created on: 2014. 12. 15.
|
||||||
|
* Author: Administrator
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SNTP_H_
|
||||||
|
#define SNTP_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief Define it for Debug & Monitor DNS processing.
|
||||||
|
* @note If defined, it dependens on <stdio.h>
|
||||||
|
*/
|
||||||
|
//#define _SNTP_DEBUG_
|
||||||
|
|
||||||
|
#define MAX_SNTP_BUF_SIZE sizeof(ntpformat) ///< maximum size of DNS buffer. */
|
||||||
|
|
||||||
|
/* for ntpclient */
|
||||||
|
typedef signed char s_char;
|
||||||
|
typedef unsigned long long tstamp;
|
||||||
|
typedef unsigned int tdist;
|
||||||
|
|
||||||
|
typedef struct _ntpformat
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t dstaddr[4]; /* destination (local) address */
|
||||||
|
char version; /* version number */
|
||||||
|
char leap; /* leap indicator */
|
||||||
|
char mode; /* mode */
|
||||||
|
char stratum; /* stratum */
|
||||||
|
char poll; /* poll interval */
|
||||||
|
s_char precision; /* precision */
|
||||||
|
tdist rootdelay; /* root delay */
|
||||||
|
tdist rootdisp; /* root dispersion */
|
||||||
|
char refid; /* reference ID */
|
||||||
|
tstamp reftime; /* reference time */
|
||||||
|
tstamp org; /* origin timestamp */
|
||||||
|
tstamp rec; /* receive timestamp */
|
||||||
|
tstamp xmt; /* transmit timestamp */
|
||||||
|
|
||||||
|
|
||||||
|
} ntpformat;
|
||||||
|
|
||||||
|
typedef struct _datetime
|
||||||
|
{
|
||||||
|
uint16_t yy;
|
||||||
|
uint8_t mo;
|
||||||
|
uint8_t dd;
|
||||||
|
uint8_t hh;
|
||||||
|
uint8_t mm;
|
||||||
|
uint8_t ss;
|
||||||
|
} datetime;
|
||||||
|
|
||||||
|
#define ntp_port 123 //ntp server port number
|
||||||
|
#define SECS_PERDAY 86400UL // seconds in a day = 60*60*24
|
||||||
|
#define UTC_ADJ_HRS 9 // SEOUL : GMT+9
|
||||||
|
#define EPOCH 1900 // NTP start year
|
||||||
|
|
||||||
|
void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx);
|
||||||
|
void SNTP_init(uint8_t s, uint8_t *ntp_server, uint8_t tz, uint8_t *buf);
|
||||||
|
int8_t SNTP_run(datetime *time);
|
||||||
|
tstamp changedatetime_to_seconds(void);
|
||||||
|
void calcdatetime(tstamp seconds);
|
||||||
|
|
||||||
|
#endif /* SNTP_H_ */
|
158
Internet/TFTP/netutil.c
Normal file
158
Internet/TFTP/netutil.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "netutil.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a 32bit Address into a Dotted Decimal Format string.
|
||||||
|
*
|
||||||
|
* @param addr 32bit address.
|
||||||
|
* @return Dotted Decimal Format string.
|
||||||
|
*/
|
||||||
|
int8_t* inet_ntoa(uint32_t addr)
|
||||||
|
{
|
||||||
|
static int8_t addr_str[16];
|
||||||
|
memset(addr_str,0,16);
|
||||||
|
sprintf((char*)addr_str,"%d.%d.%d.%d",(int32_t)(addr>>24 & 0xFF),(int32_t)(addr>>16 & 0xFF),(int32_t)(addr>>8 & 0xFF),(int32_t)(addr & 0xFF));
|
||||||
|
return addr_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a 32bit Address into a Dotted Decimal Format string.
|
||||||
|
* This is differ from inet_ntoa in fixed length.
|
||||||
|
*
|
||||||
|
* @param addr 32bit address.
|
||||||
|
* @return Dotted Decimal Format string.
|
||||||
|
*/
|
||||||
|
int8_t* inet_ntoa_pad(uint32_t addr)
|
||||||
|
{
|
||||||
|
static int8_t addr_str[16];
|
||||||
|
memset(addr_str,0,16);
|
||||||
|
sprintf((char*)addr_str,"%03d.%03d.%03d.%03d",(int32_t)(addr>>24 & 0xFF),(int32_t)(addr>>16 & 0xFF),(int32_t)(addr>>8 & 0xFF),(int32_t)(addr & 0xFF));
|
||||||
|
return addr_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string containing an (Ipv4) Internet Protocol decimal dotted address into a 32bit address.
|
||||||
|
*
|
||||||
|
* @param addr Dotted Decimal Format string.
|
||||||
|
* @return 32bit address.
|
||||||
|
*/
|
||||||
|
uint32_t inet_addr(uint8_t* addr)
|
||||||
|
{
|
||||||
|
int8_t i;
|
||||||
|
uint32_t inetaddr = 0;
|
||||||
|
int8_t taddr[30];
|
||||||
|
int8_t * nexttok;
|
||||||
|
int32_t num;
|
||||||
|
strcpy((char*)taddr,(char*)addr);
|
||||||
|
|
||||||
|
nexttok = taddr;
|
||||||
|
for(i = 0; i < 4 ; i++)
|
||||||
|
{
|
||||||
|
nexttok = (int8_t*)strtok((char*)nexttok,".");
|
||||||
|
if(nexttok[0] == '0' && nexttok[1] == 'x') num = strtol((char*)nexttok+2, NULL, 16);
|
||||||
|
else num = strtol((char*)nexttok, NULL, 10);
|
||||||
|
inetaddr = inetaddr << 8;
|
||||||
|
inetaddr |= (num & 0xFF);
|
||||||
|
nexttok = NULL;
|
||||||
|
}
|
||||||
|
return inetaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap the byte order of 16bit(short) wide variable.
|
||||||
|
*
|
||||||
|
* @param i 16bit value to swap
|
||||||
|
* @return Swapped value
|
||||||
|
*/
|
||||||
|
uint16_t swaps(uint16_t i)
|
||||||
|
{
|
||||||
|
uint16_t ret=0;
|
||||||
|
ret = (i & 0xFF) << 8;
|
||||||
|
ret |= ((i >> 8)& 0xFF);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap the byte order of 32bit(long) wide variable.
|
||||||
|
*
|
||||||
|
* @param l 32bit value to convert
|
||||||
|
* @return Swapped value
|
||||||
|
*/
|
||||||
|
uint32_t swapl(uint32_t l)
|
||||||
|
{
|
||||||
|
uint32_t ret=0;
|
||||||
|
ret = (l & 0xFF) << 24;
|
||||||
|
ret |= ((l >> 8) & 0xFF) << 16;
|
||||||
|
ret |= ((l >> 16) & 0xFF) << 8;
|
||||||
|
ret |= ((l >> 24) & 0xFF);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* htons function converts a unsigned short from host to TCP/IP network byte order (which is big-endian).
|
||||||
|
*
|
||||||
|
* @param hostshort The value to convert.
|
||||||
|
* @return The value in TCP/IP network byte order.
|
||||||
|
*/
|
||||||
|
uint16_t htons(uint16_t hostshort)
|
||||||
|
{
|
||||||
|
#ifdef SYSTEM_LITTLE_ENDIAN
|
||||||
|
return swaps(hostshort);
|
||||||
|
#else
|
||||||
|
return hostshort;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* htonl function converts a unsigned long from host to TCP/IP network byte order (which is big-endian).
|
||||||
|
*
|
||||||
|
* @param hostlong The value to convert.
|
||||||
|
* @return The value in TCP/IP network byte order.
|
||||||
|
*/
|
||||||
|
uint32_t htonl(uint32_t hostlong)
|
||||||
|
{
|
||||||
|
#ifdef SYSTEM_LITTLE_ENDIAN
|
||||||
|
return swapl(hostlong);
|
||||||
|
#else
|
||||||
|
return hostlong;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ntohs function converts a unsigned short from TCP/IP network byte order
|
||||||
|
* to host byte order (which is little-endian on Intel processors).
|
||||||
|
*
|
||||||
|
* @param netshort The value to convert.
|
||||||
|
* @return A 16-bit number in host byte order
|
||||||
|
*/
|
||||||
|
uint32_t ntohs(uint16_t netshort)
|
||||||
|
{
|
||||||
|
#ifdef SYSTEM_LITTLE_ENDIAN
|
||||||
|
return htons(netshort);
|
||||||
|
#else
|
||||||
|
return netshort;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* converts a unsigned long from TCP/IP network byte order to host byte order
|
||||||
|
* (which is little-endian on Intel processors).
|
||||||
|
*
|
||||||
|
* @param netlong The value to convert.
|
||||||
|
* @return A 16-bit number in host byte order
|
||||||
|
*/
|
||||||
|
uint32_t ntohl(uint32_t netlong)
|
||||||
|
{
|
||||||
|
#ifdef SYSTEM_LITTLE_ENDIAN
|
||||||
|
return swapl(netlong);
|
||||||
|
#else
|
||||||
|
return netlong;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
19
Internet/TFTP/netutil.h
Normal file
19
Internet/TFTP/netutil.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
|
||||||
|
#ifndef __NETUTIL_H__
|
||||||
|
#define __NETUTIL_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SYSTEM_LITTLE_ENDIAN
|
||||||
|
|
||||||
|
int8_t* inet_ntoa(uint32_t addr);
|
||||||
|
int8_t* inet_ntoa_pad(uint32_t addr);
|
||||||
|
uint32_t inet_addr(uint8_t* addr);
|
||||||
|
uint16_t swaps(uint16_t i);
|
||||||
|
uint32_t swapl(uint32_t l);
|
||||||
|
uint16_t htons(uint16_t hostshort);
|
||||||
|
uint32_t htonl(uint32_t hostlong);
|
||||||
|
uint32_t ntohs(uint16_t netshort);
|
||||||
|
uint32_t ntohl(uint32_t netlong);
|
||||||
|
|
||||||
|
#endif
|
660
Internet/TFTP/tftp.c
Normal file
660
Internet/TFTP/tftp.c
Normal file
@ -0,0 +1,660 @@
|
|||||||
|
/**
|
||||||
|
* @file tftp.c
|
||||||
|
* @brief TFTP Source File.
|
||||||
|
* @version 0.1.0
|
||||||
|
* @author Sang-sik Kim
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Includes -----------------------------------------------------*/
|
||||||
|
#include <string.h>
|
||||||
|
#include "tftp.h"
|
||||||
|
#include "socket.h"
|
||||||
|
#include "netutil.h"
|
||||||
|
|
||||||
|
/* define -------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* typedef ------------------------------------------------------*/
|
||||||
|
|
||||||
|
/* Extern Variable ----------------------------------------------*/
|
||||||
|
|
||||||
|
/* Extern Functions ---------------------------------------------*/
|
||||||
|
#ifdef F_STORAGE
|
||||||
|
extern void save_data(uint8_t *data, uint32_t data_len, uint16_t block_number);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Global Variable ----------------------------------------------*/
|
||||||
|
static int g_tftp_socket = -1;
|
||||||
|
|
||||||
|
static uint8_t g_filename[FILE_NAME_SIZE];
|
||||||
|
|
||||||
|
static uint32_t g_server_ip = 0;
|
||||||
|
static uint16_t g_server_port = 0;
|
||||||
|
static uint16_t g_local_port = 0;
|
||||||
|
|
||||||
|
static uint32_t g_tftp_state = STATE_NONE;
|
||||||
|
static uint16_t g_block_num = 0;
|
||||||
|
|
||||||
|
static uint32_t g_timeout = 5;
|
||||||
|
static uint32_t g_resend_flag = 0;
|
||||||
|
static uint32_t tftp_time_cnt = 0;
|
||||||
|
static uint32_t tftp_retry_cnt = 0;
|
||||||
|
|
||||||
|
static uint8_t *g_tftp_rcv_buf = NULL;
|
||||||
|
|
||||||
|
static TFTP_OPTION default_tftp_opt = {
|
||||||
|
.code = (uint8_t *)"timeout",
|
||||||
|
.value = (uint8_t *)"5"
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t g_progress_state = TFTP_PROGRESS;
|
||||||
|
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
int dbg_level = (INFO_DBG | ERROR_DBG | IPC_DBG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* static function define ---------------------------------------*/
|
||||||
|
static void set_filename(uint8_t *file, uint32_t file_size)
|
||||||
|
{
|
||||||
|
memcpy(g_filename, file, file_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_server_ip(uint32_t ipaddr)
|
||||||
|
{
|
||||||
|
g_server_ip = ipaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_server_ip()
|
||||||
|
{
|
||||||
|
return g_server_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_server_port(uint16_t port)
|
||||||
|
{
|
||||||
|
g_server_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t get_server_port()
|
||||||
|
{
|
||||||
|
return g_server_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_local_port(uint16_t port)
|
||||||
|
{
|
||||||
|
g_local_port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t get_local_port()
|
||||||
|
{
|
||||||
|
return g_local_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t genernate_port()
|
||||||
|
{
|
||||||
|
/* TODO */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_tftp_state(uint32_t state)
|
||||||
|
{
|
||||||
|
g_tftp_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_tftp_state()
|
||||||
|
{
|
||||||
|
return g_tftp_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_tftp_timeout(uint32_t timeout)
|
||||||
|
{
|
||||||
|
g_timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t get_tftp_timeout()
|
||||||
|
{
|
||||||
|
return g_timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void set_block_number(uint16_t block_number)
|
||||||
|
{
|
||||||
|
g_block_num = block_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint16_t get_block_number()
|
||||||
|
{
|
||||||
|
return g_block_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_tftp_socket(uint8_t sock)
|
||||||
|
{
|
||||||
|
uint8_t sd, sck_state;
|
||||||
|
|
||||||
|
sd = socket(sock, Sn_MR_UDP, 51000, SF_IO_NONBLOCK);
|
||||||
|
if(sd != sock) {
|
||||||
|
//DBG_PRINT(ERROR_DBG, "[%s] socket error\r\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
getsockopt(sd , SO_STATUS, &sck_state);
|
||||||
|
} while(sck_state != SOCK_UDP);
|
||||||
|
|
||||||
|
return sd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_udp_packet(int socket, uint8_t *packet, uint32_t len, uint32_t ip, uint16_t port)
|
||||||
|
{
|
||||||
|
int snd_len;
|
||||||
|
|
||||||
|
ip = htonl(ip);
|
||||||
|
|
||||||
|
snd_len = sendto(socket, packet, len, (uint8_t *)&ip, port);
|
||||||
|
if(snd_len != len) {
|
||||||
|
//DBG_PRINT(ERROR_DBG, "[%s] sendto error\r\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return snd_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int recv_udp_packet(int socket, uint8_t *packet, uint32_t len, uint32_t *ip, uint16_t *port)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
uint8_t sck_state;
|
||||||
|
uint16_t recv_len;
|
||||||
|
|
||||||
|
/* Receive Packet Process */
|
||||||
|
ret = getsockopt(socket, SO_STATUS, &sck_state);
|
||||||
|
if(ret != SOCK_OK) {
|
||||||
|
//DBG_PRINT(ERROR_DBG, "[%s] getsockopt SO_STATUS error\r\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sck_state == SOCK_UDP) {
|
||||||
|
ret = getsockopt(socket, SO_RECVBUF, &recv_len);
|
||||||
|
if(ret != SOCK_OK) {
|
||||||
|
//DBG_PRINT(ERROR_DBG, "[%s] getsockopt SO_RECVBUF error\r\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(recv_len) {
|
||||||
|
recv_len = recvfrom(socket, packet, len, (uint8_t *)ip, port);
|
||||||
|
if(recv_len < 0) {
|
||||||
|
//DBG_PRINT(ERROR_DBG, "[%s] recvfrom error\r\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ip = ntohl(*ip);
|
||||||
|
|
||||||
|
return recv_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_tftp_socket(int socket)
|
||||||
|
{
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void init_tftp(void)
|
||||||
|
{
|
||||||
|
g_filename[0] = 0;
|
||||||
|
|
||||||
|
set_server_ip(0);
|
||||||
|
set_server_port(0);
|
||||||
|
set_local_port(0);
|
||||||
|
|
||||||
|
set_tftp_state(STATE_NONE);
|
||||||
|
set_block_number(0);
|
||||||
|
|
||||||
|
/* timeout flag */
|
||||||
|
g_resend_flag = 0;
|
||||||
|
tftp_retry_cnt = tftp_time_cnt = 0;
|
||||||
|
|
||||||
|
g_progress_state = TFTP_PROGRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tftp_cancel_timeout(void)
|
||||||
|
{
|
||||||
|
if(g_resend_flag) {
|
||||||
|
g_resend_flag = 0;
|
||||||
|
tftp_retry_cnt = tftp_time_cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tftp_reg_timeout()
|
||||||
|
{
|
||||||
|
if(g_resend_flag == 0) {
|
||||||
|
g_resend_flag = 1;
|
||||||
|
tftp_retry_cnt = tftp_time_cnt = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_tftp_option(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
/* TODO Option Process */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_tftp_rrq(uint8_t *filename, uint8_t *mode, TFTP_OPTION *opt, uint8_t opt_len)
|
||||||
|
{
|
||||||
|
uint8_t snd_buf[MAX_MTU_SIZE];
|
||||||
|
uint8_t *pkt = snd_buf;
|
||||||
|
uint32_t i, len;
|
||||||
|
|
||||||
|
*((uint16_t *)pkt) = htons(TFTP_RRQ);
|
||||||
|
pkt += 2;
|
||||||
|
strcpy((char *)pkt, (const char *)filename);
|
||||||
|
pkt += strlen((char *)filename) + 1;
|
||||||
|
strcpy((char *)pkt, (const char *)mode);
|
||||||
|
pkt += strlen((char *)mode) + 1;
|
||||||
|
|
||||||
|
for(i = 0 ; i < opt_len ; i++) {
|
||||||
|
strcpy((char *)pkt, (const char *)opt[i].code);
|
||||||
|
pkt += strlen((char *)opt[i].code) + 1;
|
||||||
|
strcpy((char *)pkt, (const char *)opt[i].value);
|
||||||
|
pkt += strlen((char *)opt[i].value) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = pkt - snd_buf;
|
||||||
|
|
||||||
|
send_udp_packet(g_tftp_socket, snd_buf, len, get_server_ip(), TFTP_SERVER_PORT);
|
||||||
|
set_tftp_state(STATE_RRQ);
|
||||||
|
set_filename(filename, strlen((char *)filename) + 1);
|
||||||
|
tftp_reg_timeout();
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, ">> TFTP RRQ : FileName(%s), Mode(%s)\r\n", filename, mode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // 2014.07.01 sskim
|
||||||
|
static void send_tftp_wrq(uint8_t *filename, uint8_t *mode, TFTP_OPTION *opt, uint8_t opt_len)
|
||||||
|
{
|
||||||
|
uint8_t snd_buf[MAX_MTU_SIZE];
|
||||||
|
uint8_t *pkt = snd_buf;
|
||||||
|
uint32_t i, len;
|
||||||
|
|
||||||
|
*((uint16_t *)pkt) = htons((uint16_t)TFTP_WRQ);
|
||||||
|
pkt += 2;
|
||||||
|
strcpy((char *)pkt, (const char *)filename);
|
||||||
|
pkt += strlen((char *)filename) + 1;
|
||||||
|
strcpy((char *)pkt, (const char *)mode);
|
||||||
|
pkt += strlen((char *)mode) + 1;
|
||||||
|
|
||||||
|
for(i = 0 ; i < opt_len ; i++) {
|
||||||
|
strcpy((char *)pkt, (const char *)opt[i].code);
|
||||||
|
pkt += strlen((char *)opt[i].code) + 1;
|
||||||
|
strcpy((char *)pkt, (const char *)opt[i].value);
|
||||||
|
pkt += strlen((char *)opt[i].value) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = pkt - snd_buf;
|
||||||
|
|
||||||
|
send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), TFTP_SERVER_PORT);
|
||||||
|
set_tftp_state(STATE_WRQ);
|
||||||
|
set_filename(filename, strlen((char *)filename) + 1);
|
||||||
|
tftp_reg_timeout();
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, ">> TFTP WRQ : FileName(%s), Mode(%s)\r\n", filename, mode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 // 2014.07.01 sskim
|
||||||
|
static void send_tftp_data(uint16_t block_number, uint8_t *data, uint16_t data_len)
|
||||||
|
{
|
||||||
|
uint8_t snd_buf[MAX_MTU_SIZE];
|
||||||
|
uint8_t *pkt = snd_buf;
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
|
*((uint16_t *)pkt) = htons((uint16_t)TFTP_DATA);
|
||||||
|
pkt += 2;
|
||||||
|
*((uint16_t *)pkt) = htons(block_number);
|
||||||
|
pkt += 2;
|
||||||
|
memcpy(pkt, data, data_len);
|
||||||
|
pkt += data_len;
|
||||||
|
|
||||||
|
len = pkt - snd_buf;
|
||||||
|
|
||||||
|
send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), get_server_port());
|
||||||
|
tftp_reg_timeout();
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, ">> TFTP DATA : Block Number(%d), Data Length(%d)\r\n", block_number, data_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void send_tftp_ack(uint16_t block_number)
|
||||||
|
{
|
||||||
|
uint8_t snd_buf[4];
|
||||||
|
uint8_t *pkt = snd_buf;
|
||||||
|
|
||||||
|
*((uint16_t *)pkt) = htons((uint16_t)TFTP_ACK);
|
||||||
|
pkt += 2;
|
||||||
|
*((uint16_t *)pkt) = htons(block_number);
|
||||||
|
pkt += 2;
|
||||||
|
|
||||||
|
send_udp_packet(g_tftp_socket , snd_buf, 4, get_server_ip(), get_server_port());
|
||||||
|
tftp_reg_timeout();
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, ">> TFTP ACK : Block Number(%d)\r\n", block_number);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 // 2014.07.01 sskim
|
||||||
|
static void send_tftp_oack(TFTP_OPTION *opt, uint8_t opt_len)
|
||||||
|
{
|
||||||
|
uint8_t snd_buf[MAX_MTU_SIZE];
|
||||||
|
uint8_t *pkt = snd_buf;
|
||||||
|
uint32_t i, len;
|
||||||
|
|
||||||
|
*((uint16_t *)pkt) = htons((uint16_t)TFTP_OACK);
|
||||||
|
pkt += 2;
|
||||||
|
|
||||||
|
for(i = 0 ; i < opt_len ; i++) {
|
||||||
|
strcpy((char *)pkt, (const char *)opt[i].code);
|
||||||
|
pkt += strlen((char *)opt[i].code) + 1;
|
||||||
|
strcpy((char *)pkt, (const char *)opt[i].value);
|
||||||
|
pkt += strlen((char *)opt[i].value) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = pkt - snd_buf;
|
||||||
|
|
||||||
|
send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), get_server_port());
|
||||||
|
tftp_reg_timeout();
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, ">> TFTP OACK \r\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 // 2014.07.01 sskim
|
||||||
|
static void send_tftp_error(uint16_t error_number, uint8_t *error_message)
|
||||||
|
{
|
||||||
|
uint8_t snd_buf[MAX_MTU_SIZE];
|
||||||
|
uint8_t *pkt = snd_buf;
|
||||||
|
uint32_t len;
|
||||||
|
|
||||||
|
*((uint16_t *)pkt) = htons((uint16_t)TFTP_ERROR);
|
||||||
|
pkt += 2;
|
||||||
|
*((uint16_t *)pkt) = htons(error_number);
|
||||||
|
pkt += 2;
|
||||||
|
strcpy((char *)pkt, (const char *)error_message);
|
||||||
|
pkt += strlen((char *)error_message) + 1;
|
||||||
|
|
||||||
|
len = pkt - snd_buf;
|
||||||
|
|
||||||
|
send_udp_packet(g_tftp_socket , snd_buf, len, get_server_ip(), get_server_port());
|
||||||
|
tftp_reg_timeout();
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, ">> TFTP ERROR : Error Number(%d)\r\n", error_number);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void recv_tftp_rrq(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
/* When TFTP Server Mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_tftp_wrq(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
/* When TFTP Server Mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_tftp_data(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
TFTP_DATA_T *data = (TFTP_DATA_T *)msg;
|
||||||
|
|
||||||
|
data->opcode = ntohs(data->opcode);
|
||||||
|
data->block_num = ntohs(data->block_num);
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, "<< TFTP_DATA : opcode(%d), block_num(%d)\r\n", data->opcode, data->block_num);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(get_tftp_state())
|
||||||
|
{
|
||||||
|
case STATE_RRQ :
|
||||||
|
case STATE_OACK :
|
||||||
|
if(data->block_num == 1) {
|
||||||
|
set_tftp_state(STATE_DATA);
|
||||||
|
set_block_number(data->block_num);
|
||||||
|
#ifdef F_STORAGE
|
||||||
|
save_data(data->data, msg_len - 4, data->block_num);
|
||||||
|
#endif
|
||||||
|
tftp_cancel_timeout();
|
||||||
|
}
|
||||||
|
send_tftp_ack(data->block_num);
|
||||||
|
|
||||||
|
if((msg_len - 4) < TFTP_BLK_SIZE) {
|
||||||
|
init_tftp();
|
||||||
|
g_progress_state = TFTP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_DATA :
|
||||||
|
if(data->block_num == (get_block_number() + 1)) {
|
||||||
|
set_block_number(data->block_num);
|
||||||
|
#ifdef F_STORAGE
|
||||||
|
save_data(data->data, msg_len - 4, data->block_num);
|
||||||
|
#endif
|
||||||
|
tftp_cancel_timeout();
|
||||||
|
}
|
||||||
|
send_tftp_ack(data->block_num);
|
||||||
|
|
||||||
|
if((msg_len - 4) < TFTP_BLK_SIZE) {
|
||||||
|
init_tftp();
|
||||||
|
g_progress_state = TFTP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
/* invalid message */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_tftp_ack(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, "<< TFTP_ACK : \r\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(get_tftp_state())
|
||||||
|
{
|
||||||
|
case STATE_WRQ :
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_ACK :
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
/* invalid message */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_tftp_oack(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, "<< TFTP_OACK : \r\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch(get_tftp_state())
|
||||||
|
{
|
||||||
|
case STATE_RRQ :
|
||||||
|
process_tftp_option(msg, msg_len);
|
||||||
|
set_tftp_state(STATE_OACK);
|
||||||
|
tftp_cancel_timeout();
|
||||||
|
send_tftp_ack(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_WRQ :
|
||||||
|
process_tftp_option(msg, msg_len);
|
||||||
|
set_tftp_state(STATE_ACK);
|
||||||
|
tftp_cancel_timeout();
|
||||||
|
|
||||||
|
/* TODO DATA Transfer */
|
||||||
|
//send_tftp_data(...);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
/* invalid message */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_tftp_error(uint8_t *msg, uint32_t msg_len)
|
||||||
|
{
|
||||||
|
TFTP_ERROR_T *data= (TFTP_ERROR_T *)msg;
|
||||||
|
|
||||||
|
data->opcode = ntohs(data->opcode);
|
||||||
|
data->error_code = ntohs(data->error_code);
|
||||||
|
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(IPC_DBG, "<< TFTP_ERROR : %d (%s)\r\n", data->error_code, data->error_msg);
|
||||||
|
DBG_PRINT(ERROR_DBG, "[%s] Error Code : %d (%s)\r\n", __func__, data->error_code, data->error_msg);
|
||||||
|
#endif
|
||||||
|
init_tftp();
|
||||||
|
g_progress_state = TFTP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void recv_tftp_packet(uint8_t *packet, uint32_t packet_len, uint32_t from_ip, uint16_t from_port)
|
||||||
|
{
|
||||||
|
uint16_t opcode;
|
||||||
|
|
||||||
|
/* Verify Server IP */
|
||||||
|
if(from_ip != get_server_ip()) {
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(ERROR_DBG, "[%s] Server IP faults\r\n", __func__);
|
||||||
|
DBG_PRINT(ERROR_DBG, "from IP : %08x, Server IP : %08x\r\n", from_ip, get_server_ip());
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opcode = ntohs(*((uint16_t *)packet));
|
||||||
|
|
||||||
|
/* Set Server Port */
|
||||||
|
if((get_tftp_state() == STATE_WRQ) || (get_tftp_state() == STATE_RRQ)) {
|
||||||
|
set_server_port(from_port);
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(INFO_DBG, "[%s] Set Server Port : %d\r\n", __func__, from_port);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(opcode)
|
||||||
|
{
|
||||||
|
case TFTP_RRQ : /* When Server */
|
||||||
|
recv_tftp_rrq(packet, packet_len);
|
||||||
|
break;
|
||||||
|
case TFTP_WRQ : /* When Server */
|
||||||
|
recv_tftp_wrq(packet, packet_len);
|
||||||
|
break;
|
||||||
|
case TFTP_DATA :
|
||||||
|
recv_tftp_data(packet, packet_len);
|
||||||
|
break;
|
||||||
|
case TFTP_ACK :
|
||||||
|
recv_tftp_ack(packet, packet_len);
|
||||||
|
break;
|
||||||
|
case TFTP_OACK :
|
||||||
|
recv_tftp_oack(packet, packet_len);
|
||||||
|
break;
|
||||||
|
case TFTP_ERROR :
|
||||||
|
recv_tftp_error(packet, packet_len);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
// Unknown Mesage
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Functions ----------------------------------------------------*/
|
||||||
|
void TFTP_init(uint8_t socket, uint8_t *buf)
|
||||||
|
{
|
||||||
|
init_tftp();
|
||||||
|
|
||||||
|
g_tftp_socket = open_tftp_socket(socket);
|
||||||
|
g_tftp_rcv_buf = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFTP_exit(void)
|
||||||
|
{
|
||||||
|
init_tftp();
|
||||||
|
|
||||||
|
close_tftp_socket(g_tftp_socket);
|
||||||
|
g_tftp_socket = -1;
|
||||||
|
|
||||||
|
g_tftp_rcv_buf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TFTP_run(void)
|
||||||
|
{
|
||||||
|
uint16_t len, from_port;
|
||||||
|
uint32_t from_ip;
|
||||||
|
|
||||||
|
/* Timeout Process */
|
||||||
|
if(g_resend_flag) {
|
||||||
|
if(tftp_time_cnt >= g_timeout) {
|
||||||
|
switch(get_tftp_state()) {
|
||||||
|
case STATE_WRQ: // 미구현
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_RRQ:
|
||||||
|
send_tftp_rrq(g_filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_OACK:
|
||||||
|
case STATE_DATA:
|
||||||
|
send_tftp_ack(get_block_number());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_ACK: // 미구현
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
tftp_time_cnt = 0;
|
||||||
|
tftp_retry_cnt++;
|
||||||
|
|
||||||
|
if(tftp_retry_cnt >= 5) {
|
||||||
|
init_tftp();
|
||||||
|
g_progress_state = TFTP_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive Packet Process */
|
||||||
|
len = recv_udp_packet(g_tftp_socket, g_tftp_rcv_buf, MAX_MTU_SIZE, &from_ip, &from_port);
|
||||||
|
if(len < 0) {
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(ERROR_DBG, "[%s] recv_udp_packet error\r\n", __func__);
|
||||||
|
#endif
|
||||||
|
return g_progress_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_tftp_packet(g_tftp_rcv_buf, len, from_ip, from_port);
|
||||||
|
|
||||||
|
return g_progress_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFTP_read_request(uint32_t server_ip, uint8_t *filename)
|
||||||
|
{
|
||||||
|
set_server_ip(server_ip);
|
||||||
|
#ifdef __TFTP_DEBUG__
|
||||||
|
DBG_PRINT(INFO_DBG, "[%s] Set Tftp Server : %x\r\n", __func__, server_ip);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_progress_state = TFTP_PROGRESS;
|
||||||
|
send_tftp_rrq(filename, (uint8_t *)TRANS_BINARY, &default_tftp_opt, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tftp_timeout_handler(void)
|
||||||
|
{
|
||||||
|
if(g_resend_flag)
|
||||||
|
tftp_time_cnt++;
|
||||||
|
}
|
93
Internet/TFTP/tftp.h
Normal file
93
Internet/TFTP/tftp.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
* @file tftp.h
|
||||||
|
* @brief TFTP Header File.
|
||||||
|
* @version 0.1.0
|
||||||
|
* @author Sang-sik Kim
|
||||||
|
*/
|
||||||
|
#ifndef __TFTP_H__
|
||||||
|
#define __TFTP_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define F_APP_TFTP
|
||||||
|
#define __TFTP_DEBUG__
|
||||||
|
|
||||||
|
#define F_STORAGE // If your target support a storage, you have to activate this feature and implement.
|
||||||
|
|
||||||
|
#define SOCK_TFTP 1
|
||||||
|
|
||||||
|
#define INFO_DBG 0x01
|
||||||
|
#define ERROR_DBG 0x02
|
||||||
|
#define DEBUG_DBG 0x04
|
||||||
|
#define IPC_DBG 0x08
|
||||||
|
|
||||||
|
#define DBG_PRINT(level, format, args...) { \
|
||||||
|
if(dbg_level & level) \
|
||||||
|
printf(format, ##args); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NORMAL_MODE 0
|
||||||
|
#define TFTP_MODE 1
|
||||||
|
|
||||||
|
extern int dbg_level;
|
||||||
|
|
||||||
|
/* tftp message */
|
||||||
|
#define TFTP_RRQ 1
|
||||||
|
#define TFTP_WRQ 2
|
||||||
|
#define TFTP_DATA 3
|
||||||
|
#define TFTP_ACK 4
|
||||||
|
#define TFTP_ERROR 5
|
||||||
|
#define TFTP_OACK 6
|
||||||
|
|
||||||
|
/* tftp state */
|
||||||
|
#define STATE_NONE 0
|
||||||
|
#define STATE_RRQ 1
|
||||||
|
#define STATE_WRQ 2
|
||||||
|
#define STATE_DATA 3
|
||||||
|
#define STATE_ACK 4
|
||||||
|
#define STATE_OACK 5
|
||||||
|
|
||||||
|
/* tftp transfer mode */
|
||||||
|
#define TRANS_ASCII "netascii"
|
||||||
|
#define TRANS_BINARY "octet"
|
||||||
|
|
||||||
|
/* tftp progress state */
|
||||||
|
#define TFTP_PROGRESS 0
|
||||||
|
#define TFTP_FAIL 1
|
||||||
|
#define TFTP_SUCCESS 2
|
||||||
|
|
||||||
|
/* define */
|
||||||
|
#define TFTP_SERVER_PORT 69
|
||||||
|
#define TFTP_TEMP_PORT 51000
|
||||||
|
#define TFTP_BLK_SIZE 512
|
||||||
|
#define MAX_MTU_SIZE 1514
|
||||||
|
#define FILE_NAME_SIZE 20
|
||||||
|
|
||||||
|
//#define __TFTP_DEBUG__
|
||||||
|
|
||||||
|
/* typedef */
|
||||||
|
typedef struct tftp_data {
|
||||||
|
uint16_t opcode;
|
||||||
|
uint16_t block_num;
|
||||||
|
uint8_t data[0];
|
||||||
|
} TFTP_DATA_T;
|
||||||
|
|
||||||
|
typedef struct tftp_error {
|
||||||
|
uint16_t opcode;
|
||||||
|
uint16_t error_code;
|
||||||
|
uint8_t error_msg[0];
|
||||||
|
} TFTP_ERROR_T;
|
||||||
|
|
||||||
|
typedef struct tftp_option {
|
||||||
|
uint8_t *code;
|
||||||
|
uint8_t *value;
|
||||||
|
} TFTP_OPTION;
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
void TFTP_init(uint8_t socket, uint8_t *buf);
|
||||||
|
void TFTP_exit(void);
|
||||||
|
int TFTP_run(void);
|
||||||
|
void TFTP_read_request(uint32_t server_ip, uint8_t *filename);
|
||||||
|
void tftp_timeout_handler(void);
|
||||||
|
|
||||||
|
#endif /*__TFTP_H__ */
|
402
Internet/httpServer/httpParser.c
Normal file
402
Internet/httpServer/httpParser.c
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
/**
|
||||||
|
@file httpd.c
|
||||||
|
@brief functions associated http processing
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "socket.h"
|
||||||
|
#include "httpParser.h"
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Public types/enumerations/variables
|
||||||
|
****************************************************************************/
|
||||||
|
//uint8_t BUFPUB[2048];
|
||||||
|
uint8_t BUFPUB[256];
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private functions
|
||||||
|
****************************************************************************/
|
||||||
|
static void replacetochar(uint8_t * str, uint8_t oldchar, uint8_t newchar); /* Replace old character with new character in the string */
|
||||||
|
static uint8_t C2D(uint8_t c); /* Convert a character to HEX */
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief convert escape characters(%XX) to ASCII character
|
||||||
|
*/
|
||||||
|
void unescape_http_url(
|
||||||
|
char * url /**< pointer to be converted ( escape characters )*/
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
for (x = 0, y = 0; url[y]; ++x, ++y) {
|
||||||
|
if ((url[x] = url[y]) == '%') {
|
||||||
|
url[x] = C2D(url[y+1])*0x10+C2D(url[y+2]);
|
||||||
|
y+=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
url[x] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief make response header such as html, gif, jpeg,etc.
|
||||||
|
*/
|
||||||
|
void make_http_response_head(
|
||||||
|
char * buf, /**< pointer to response header to be made */
|
||||||
|
char type, /**< response type */
|
||||||
|
uint32_t len /**< size of response header */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char * head;
|
||||||
|
char tmp[10];
|
||||||
|
|
||||||
|
/* file type*/
|
||||||
|
if (type == PTYPE_HTML) head = RES_HTMLHEAD_OK;
|
||||||
|
else if (type == PTYPE_GIF) head = RES_GIFHEAD_OK;
|
||||||
|
else if (type == PTYPE_TEXT) head = RES_TEXTHEAD_OK;
|
||||||
|
else if (type == PTYPE_JPEG) head = RES_JPEGHEAD_OK;
|
||||||
|
else if (type == PTYPE_FLASH) head = RES_FLASHHEAD_OK;
|
||||||
|
else if (type == PTYPE_XML) head = RES_XMLHEAD_OK;
|
||||||
|
else if (type == PTYPE_CSS) head = RES_CSSHEAD_OK;
|
||||||
|
else if (type == PTYPE_JSON) head = RES_JSONHEAD_OK;
|
||||||
|
else if (type == PTYPE_JS) head = RES_JSHEAD_OK;
|
||||||
|
else if (type == PTYPE_CGI) head = RES_CGIHEAD_OK;
|
||||||
|
else if (type == PTYPE_PNG) head = RES_PNGHEAD_OK;
|
||||||
|
else if (type == PTYPE_ICO) head = RES_ICOHEAD_OK;
|
||||||
|
else if (type == PTYPE_TTF) head = RES_TTFHEAD_OK;
|
||||||
|
else if (type == PTYPE_OTF) head = RES_OTFHEAD_OK;
|
||||||
|
else if (type == PTYPE_WOFF) head = RES_WOFFHEAD_OK;
|
||||||
|
else if (type == PTYPE_EOT) head = RES_EOTHEAD_OK;
|
||||||
|
else if (type == PTYPE_SVG) head = RES_SVGHEAD_OK;
|
||||||
|
#ifdef _HTTPPARSER_DEBUG_
|
||||||
|
else
|
||||||
|
{
|
||||||
|
head = NULL;
|
||||||
|
printf("\r\n\r\n-MAKE HEAD UNKNOWN-\r\n");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
else head = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sprintf(tmp, "%ld", len);
|
||||||
|
strcpy(buf, head);
|
||||||
|
strcat(buf, tmp);
|
||||||
|
strcat(buf, "\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief find MIME type of a file
|
||||||
|
*/
|
||||||
|
void find_http_uri_type(
|
||||||
|
uint8_t * type, /**< type to be returned */
|
||||||
|
uint8_t * buff /**< file name */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* Decide type according to extension*/
|
||||||
|
|
||||||
|
char * buf;
|
||||||
|
buf = (char *)buff;
|
||||||
|
|
||||||
|
if (strstr(buf, ".htm") || strstr(buf, ".html")) *type = PTYPE_HTML;
|
||||||
|
else if (strstr(buf, ".gif")) *type = PTYPE_GIF;
|
||||||
|
else if (strstr(buf, ".text") || strstr(buf,".txt")) *type = PTYPE_TEXT;
|
||||||
|
else if (strstr(buf, ".jpeg") || strstr(buf,".jpg")) *type = PTYPE_JPEG;
|
||||||
|
else if (strstr(buf, ".swf")) *type = PTYPE_FLASH;
|
||||||
|
else if (strstr(buf, ".cgi") || strstr(buf,".CGI")) *type = PTYPE_CGI;
|
||||||
|
else if (strstr(buf, ".json") || strstr(buf,".JSON")) *type = PTYPE_JSON;
|
||||||
|
else if (strstr(buf, ".js") || strstr(buf,".JS")) *type = PTYPE_JS;
|
||||||
|
else if (strstr(buf, ".CGI") || strstr(buf,".cgi")) *type = PTYPE_CGI;
|
||||||
|
else if (strstr(buf, ".xml") || strstr(buf,".XML")) *type = PTYPE_XML;
|
||||||
|
else if (strstr(buf, ".css") || strstr(buf,".CSS")) *type = PTYPE_CSS;
|
||||||
|
else if (strstr(buf, ".png") || strstr(buf,".PNG")) *type = PTYPE_PNG;
|
||||||
|
else if (strstr(buf, ".ico") || strstr(buf,".ICO")) *type = PTYPE_ICO;
|
||||||
|
else if (strstr(buf, ".ttf") || strstr(buf,".TTF")) *type = PTYPE_TTF;
|
||||||
|
else if (strstr(buf, ".otf") || strstr(buf,".OTF")) *type = PTYPE_OTF;
|
||||||
|
else if (strstr(buf, ".woff") || strstr(buf,".WOFF")) *type = PTYPE_WOFF;
|
||||||
|
else if (strstr(buf, ".eot") || strstr(buf,".EOT")) *type = PTYPE_EOT;
|
||||||
|
else if (strstr(buf, ".svg") || strstr(buf,".SVG")) *type = PTYPE_SVG;
|
||||||
|
else *type = PTYPE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief parse http request from a peer
|
||||||
|
*/
|
||||||
|
void parse_http_request(
|
||||||
|
st_http_request * request, /**< request to be returned */
|
||||||
|
uint8_t * buf /**< pointer to be parsed */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char * nexttok;
|
||||||
|
nexttok = strtok((char*)buf," ");
|
||||||
|
if(!nexttok)
|
||||||
|
{
|
||||||
|
request->METHOD = METHOD_ERR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(!strcmp(nexttok, "GET") || !strcmp(nexttok,"get"))
|
||||||
|
{
|
||||||
|
request->METHOD = METHOD_GET;
|
||||||
|
nexttok = strtok(NULL," ");
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (!strcmp(nexttok, "HEAD") || !strcmp(nexttok,"head"))
|
||||||
|
{
|
||||||
|
request->METHOD = METHOD_HEAD;
|
||||||
|
nexttok = strtok(NULL," ");
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (!strcmp(nexttok, "POST") || !strcmp(nexttok,"post"))
|
||||||
|
{
|
||||||
|
nexttok = strtok(NULL,"\0");
|
||||||
|
request->METHOD = METHOD_POST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request->METHOD = METHOD_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!nexttok)
|
||||||
|
{
|
||||||
|
request->METHOD = METHOD_ERR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy((char *)request->URI, nexttok);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _OLD_
|
||||||
|
/**
|
||||||
|
@brief get next parameter value in the request
|
||||||
|
*/
|
||||||
|
uint8_t * get_http_param_value(
|
||||||
|
char* uri,
|
||||||
|
char* param_name
|
||||||
|
)
|
||||||
|
{
|
||||||
|
char tempURI[MAX_URI_SIZE];
|
||||||
|
uint8_t * name = 0;
|
||||||
|
|
||||||
|
|
||||||
|
if(!uri || !param_name) return 0;
|
||||||
|
|
||||||
|
strcpy((char*)tempURI,uri);
|
||||||
|
if((name = (uint8_t*)strstr(tempURI, param_name)))
|
||||||
|
{
|
||||||
|
name += strlen(param_name) + 1; // strlen(para_name) + strlen("=")
|
||||||
|
if((name = (uint8_t*)strtok((char *)name,"& \r\n\t\0")))
|
||||||
|
{
|
||||||
|
unescape_http_url((char *)name);
|
||||||
|
replacetochar(name, '+', ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef _HTTPPARSER_DEBUG_
|
||||||
|
printf(" %s=%s",param_name,name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
@brief get next parameter value in the request
|
||||||
|
*/
|
||||||
|
uint8_t * get_http_param_value(char* uri, char* param_name)
|
||||||
|
{
|
||||||
|
|
||||||
|
uint8_t * name = 0;
|
||||||
|
uint8_t * ret = BUFPUB;
|
||||||
|
uint8_t * pos2;
|
||||||
|
uint16_t len = 0, content_len = 0;
|
||||||
|
uint8_t tmp_buf[10]={0x00, };
|
||||||
|
|
||||||
|
if(!uri || !param_name) return 0;
|
||||||
|
|
||||||
|
/***************/
|
||||||
|
mid(uri, "Content-Length: ", "\r\n", (char *)tmp_buf);
|
||||||
|
content_len = ATOI(tmp_buf, 10);
|
||||||
|
uri = strstr(uri, "\r\n\r\n");
|
||||||
|
uri += 4;
|
||||||
|
uri[content_len] = 0;
|
||||||
|
/***************/
|
||||||
|
|
||||||
|
if((name = (uint8_t *)strstr(uri, param_name)))
|
||||||
|
{
|
||||||
|
name += strlen(param_name) + 1;
|
||||||
|
pos2 = (uint8_t*)strstr((char*)name, "&");
|
||||||
|
if(!pos2)
|
||||||
|
{
|
||||||
|
pos2 = name + strlen((char*)name);
|
||||||
|
}
|
||||||
|
len = pos2 - name;
|
||||||
|
|
||||||
|
if(len)
|
||||||
|
{
|
||||||
|
ret[len] = 0;
|
||||||
|
strncpy((char*)ret,(char*)name, len);
|
||||||
|
unescape_http_url((char *)ret);
|
||||||
|
replacetochar(ret, '+' ,' ');
|
||||||
|
//ret[len] = 0;
|
||||||
|
//ret[strlen((int8*)ret)] = 0;
|
||||||
|
//printf("len=%d\r\n",len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret[0] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#ifdef _HTTPPARSER_DEBUG_
|
||||||
|
printf(" %s=%s\r\n", param_name, ret);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _OLD_
|
||||||
|
uint8_t * get_http_uri_name(uint8_t * uri)
|
||||||
|
{
|
||||||
|
char tempURI[MAX_URI_SIZE];
|
||||||
|
uint8_t * uri_name;
|
||||||
|
|
||||||
|
if(!uri) return 0;
|
||||||
|
|
||||||
|
strcpy(tempURI, (char *)uri);
|
||||||
|
|
||||||
|
uri_name = (uint8_t *)strtok(tempURI, " ?");
|
||||||
|
|
||||||
|
if(strcmp((char *)uri_name,"/")) uri_name++;
|
||||||
|
|
||||||
|
#ifdef _HTTPPARSER_DEBUG_
|
||||||
|
printf(" uri_name = %s\r\n", uri_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return uri_name;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf)
|
||||||
|
{
|
||||||
|
uint8_t * uri_ptr;
|
||||||
|
if(!uri) return 0;
|
||||||
|
|
||||||
|
strcpy((char *)uri_buf, (char *)uri);
|
||||||
|
|
||||||
|
uri_ptr = (uint8_t *)strtok((char *)uri_buf, " ?");
|
||||||
|
|
||||||
|
if(strcmp((char *)uri_ptr,"/")) uri_ptr++;
|
||||||
|
strcpy((char *)uri_buf, (char *)uri_ptr);
|
||||||
|
|
||||||
|
#ifdef _HTTPPARSER_DEBUG_
|
||||||
|
printf(" uri_name = %s\r\n", uri_buf);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void inet_addr_(uint8_t * addr, uint8_t *ip)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
uint8_t taddr[30];
|
||||||
|
uint8_t * nexttok;
|
||||||
|
uint8_t num;
|
||||||
|
|
||||||
|
strcpy((char *)taddr, (char *)addr);
|
||||||
|
|
||||||
|
nexttok = taddr;
|
||||||
|
for(i = 0; i < 4 ; i++)
|
||||||
|
{
|
||||||
|
nexttok = (uint8_t *)strtok((char *)nexttok, ".");
|
||||||
|
if(nexttok[0] == '0' && nexttok[1] == 'x') num = ATOI(nexttok+2,0x10);
|
||||||
|
else num = ATOI(nexttok,10);
|
||||||
|
ip[i] = num;
|
||||||
|
nexttok = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CONVERT STRING INTO INTEGER
|
||||||
|
@return a integer number
|
||||||
|
*/
|
||||||
|
uint16_t ATOI(
|
||||||
|
uint8_t * str, /**< is a pointer to convert */
|
||||||
|
uint8_t base /**< is a base value (must be in the range 2 - 16) */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
unsigned int num = 0;
|
||||||
|
// debug_2013_11_25
|
||||||
|
// while (*str !=0)
|
||||||
|
while ((*str !=0) && (*str != 0x20)) // not include the space(0x020)
|
||||||
|
num = num * base + C2D(*str++);
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check strings and then execute callback function by each string.
|
||||||
|
* @param src The information of URI
|
||||||
|
* @param s1 The start string to be researched
|
||||||
|
* @param s2 The end string to be researched
|
||||||
|
* @param sub The string between s1 and s2
|
||||||
|
* @return The length value atfer working
|
||||||
|
*/
|
||||||
|
void mid(char* src, char* s1, char* s2, char* sub)
|
||||||
|
{
|
||||||
|
char* sub1;
|
||||||
|
char* sub2;
|
||||||
|
uint16_t n;
|
||||||
|
|
||||||
|
sub1=strstr((char*)src,(char*)s1);
|
||||||
|
sub1+=strlen((char*)s1);
|
||||||
|
sub2=strstr((char*)sub1,(char*)s2);
|
||||||
|
|
||||||
|
n=sub2-sub1;
|
||||||
|
strncpy((char*)sub,(char*)sub1,n);
|
||||||
|
sub[n]='\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Static functions
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief replace the specified character in a string with new character
|
||||||
|
*/
|
||||||
|
static void replacetochar(
|
||||||
|
uint8_t * str, /**< pointer to be replaced */
|
||||||
|
uint8_t oldchar, /**< old character */
|
||||||
|
uint8_t newchar /**< new character */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
for (x = 0; str[x]; x++)
|
||||||
|
if (str[x] == oldchar) str[x] = newchar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief CONVERT CHAR INTO HEX
|
||||||
|
@return HEX
|
||||||
|
|
||||||
|
This function converts HEX(0-F) to a character
|
||||||
|
*/
|
||||||
|
static uint8_t C2D(
|
||||||
|
uint8_t c /**< is a character('0'-'F') to convert to HEX */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
if (c >= 'a' && c <= 'f')
|
||||||
|
return 10 + c -'a';
|
||||||
|
if (c >= 'A' && c <= 'F')
|
||||||
|
return 10 + c -'A';
|
||||||
|
|
||||||
|
return (char)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
150
Internet/httpServer/httpParser.h
Normal file
150
Internet/httpServer/httpParser.h
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/**
|
||||||
|
@file httpd.h
|
||||||
|
@brief Define Constants and fucntions associated with HTTP protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef __HTTPPARSER_H__
|
||||||
|
#define __HTTPPARSER_H__
|
||||||
|
|
||||||
|
//#define _HTTPPARSER_DEBUG_
|
||||||
|
|
||||||
|
#define HTTP_SERVER_PORT 80 /**< HTTP server well-known port number */
|
||||||
|
|
||||||
|
/* HTTP Method */
|
||||||
|
#define METHOD_ERR 0 /**< Error Method. */
|
||||||
|
#define METHOD_GET 1 /**< GET Method. */
|
||||||
|
#define METHOD_HEAD 2 /**< HEAD Method. */
|
||||||
|
#define METHOD_POST 3 /**< POST Method. */
|
||||||
|
|
||||||
|
/* HTTP GET Method */
|
||||||
|
#define PTYPE_ERR 0 /**< Error file. */
|
||||||
|
#define PTYPE_HTML 1 /**< HTML file. */
|
||||||
|
#define PTYPE_GIF 2 /**< GIF file. */
|
||||||
|
#define PTYPE_TEXT 3 /**< TEXT file. */
|
||||||
|
#define PTYPE_JPEG 4 /**< JPEG file. */
|
||||||
|
#define PTYPE_FLASH 5 /**< FLASH file. */
|
||||||
|
#define PTYPE_MPEG 6 /**< MPEG file. */
|
||||||
|
#define PTYPE_PDF 7 /**< PDF file. */
|
||||||
|
#define PTYPE_CGI 8 /**< CGI file. */
|
||||||
|
#define PTYPE_XML 9 /**< XML file. */
|
||||||
|
#define PTYPE_CSS 10 /**< CSS file. */
|
||||||
|
#define PTYPE_JS 11 /**< JavaScript file. */
|
||||||
|
#define PTYPE_JSON 12 /**< JSON (JavaScript Standard Object Notation) file. */
|
||||||
|
#define PTYPE_PNG 13 /**< PNG file. */
|
||||||
|
#define PTYPE_ICO 14 /**< ICON file. */
|
||||||
|
|
||||||
|
#define PTYPE_TTF 20 /**< Font type: TTF file. */
|
||||||
|
#define PTYPE_OTF 21 /**< Font type: OTF file. */
|
||||||
|
#define PTYPE_WOFF 22 /**< Font type: WOFF file. */
|
||||||
|
#define PTYPE_EOT 23 /**< Font type: EOT file. */
|
||||||
|
#define PTYPE_SVG 24 /**< Font type: SVG file. */
|
||||||
|
|
||||||
|
|
||||||
|
/* HTTP response */
|
||||||
|
#define STATUS_OK 200
|
||||||
|
#define STATUS_CREATED 201
|
||||||
|
#define STATUS_ACCEPTED 202
|
||||||
|
#define STATUS_NO_CONTENT 204
|
||||||
|
#define STATUS_MV_PERM 301
|
||||||
|
#define STATUS_MV_TEMP 302
|
||||||
|
#define STATUS_NOT_MODIF 304
|
||||||
|
#define STATUS_BAD_REQ 400
|
||||||
|
#define STATUS_UNAUTH 401
|
||||||
|
#define STATUS_FORBIDDEN 403
|
||||||
|
#define STATUS_NOT_FOUND 404
|
||||||
|
#define STATUS_INT_SERR 500
|
||||||
|
#define STATUS_NOT_IMPL 501
|
||||||
|
#define STATUS_BAD_GATEWAY 502
|
||||||
|
#define STATUS_SERV_UNAVAIL 503
|
||||||
|
|
||||||
|
/* HTML Doc. for ERROR */
|
||||||
|
static const char ERROR_HTML_PAGE[] = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: 78\r\n\r\n<HTML>\r\n<BODY>\r\nSorry, the page you requested was not found.\r\n</BODY>\r\n</HTML>\r\n\0";
|
||||||
|
static const char ERROR_REQUEST_PAGE[] = "HTTP/1.1 400 OK\r\nContent-Type: text/html\r\nContent-Length: 50\r\n\r\n<HTML>\r\n<BODY>\r\nInvalid request.\r\n</BODY>\r\n</HTML>\r\n\0";
|
||||||
|
|
||||||
|
/* HTML Doc. for CGI result */
|
||||||
|
#define HTML_HEADER "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response header for HTML*/
|
||||||
|
#define RES_HTMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for TEXT */
|
||||||
|
#define RES_TEXTHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for GIF */
|
||||||
|
#define RES_GIFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/gif\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for JPEG */
|
||||||
|
#define RES_JPEGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for PNG */
|
||||||
|
#define RES_PNGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for FLASH */
|
||||||
|
#define RES_FLASHHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-shockwave-flash\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for XML */
|
||||||
|
#define RES_XMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nConnection: keep-alive\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for CSS */
|
||||||
|
#define RES_CSSHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/css\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for JavaScript */
|
||||||
|
#define RES_JSHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/javascript\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for JSON */
|
||||||
|
#define RES_JSONHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for ICO */
|
||||||
|
#define RES_ICOHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/x-icon\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for CGI */
|
||||||
|
#define RES_CGIHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for TTF, Font */
|
||||||
|
#define RES_TTFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-font-truetype\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for OTF, Font */
|
||||||
|
#define RES_OTFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-font-opentype\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for WOFF, Font */
|
||||||
|
#define RES_WOFFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/font-woff\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for EOT, Font */
|
||||||
|
#define RES_EOTHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.ms-fontobject\r\nContent-Length: "
|
||||||
|
|
||||||
|
/* Response head for SVG, Font */
|
||||||
|
#define RES_SVGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/svg+xml\r\nContent-Length: "
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Structure of HTTP REQUEST
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define MAX_URI_SIZE 1461
|
||||||
|
#define MAX_URI_SIZE 512
|
||||||
|
|
||||||
|
typedef struct _st_http_request
|
||||||
|
{
|
||||||
|
uint8_t METHOD; /**< request method(METHOD_GET...). */
|
||||||
|
uint8_t TYPE; /**< request type(PTYPE_HTML...). */
|
||||||
|
uint8_t URI[MAX_URI_SIZE]; /**< request file name. */
|
||||||
|
}st_http_request;
|
||||||
|
|
||||||
|
// HTTP Parsing functions
|
||||||
|
void unescape_http_url(char * url); /* convert escape character to ascii */
|
||||||
|
void parse_http_request(st_http_request *, uint8_t *); /* parse request from peer */
|
||||||
|
void find_http_uri_type(uint8_t *, uint8_t *); /* find MIME type of a file */
|
||||||
|
void make_http_response_head(char *, char, uint32_t); /* make response header */
|
||||||
|
uint8_t * get_http_param_value(char* uri, char* param_name); /* get the user-specific parameter value */
|
||||||
|
uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf); /* get the requested URI name */
|
||||||
|
#ifdef _OLD_
|
||||||
|
uint8_t * get_http_uri_name(uint8_t * uri);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
uint16_t ATOI(uint8_t * str, uint8_t base);
|
||||||
|
void mid(char* src, char* s1, char* s2, char* sub);
|
||||||
|
void inet_addr_(uint8_t * addr, uint8_t * ip);
|
||||||
|
|
||||||
|
#endif /* end of __HTTPPARSER_H__ */
|
751
Internet/httpServer/httpServer.c
Normal file
751
Internet/httpServer/httpServer.c
Normal file
@ -0,0 +1,751 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
#include "wizchip_conf.h"
|
||||||
|
|
||||||
|
#include "httpServer.h"
|
||||||
|
#include "httpParser.h"
|
||||||
|
#include "httpUtil.h"
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#ifdef _USE_SDCARD_
|
||||||
|
#include "ff.h" // header file for FatFs library (FAT file system)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DATA_BUF_SIZE
|
||||||
|
#define DATA_BUF_SIZE 2048
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private types/enumerations/variables
|
||||||
|
****************************************************************************/
|
||||||
|
static uint8_t HTTPSock_Num[_WIZCHIP_SOCK_NUM_] = {0, };
|
||||||
|
static st_http_request * http_request; /**< Pointer to received HTTP request */
|
||||||
|
static st_http_request * parsed_http_request; /**< Pointer to parsed HTTP request */
|
||||||
|
static uint8_t * http_response; /**< Pointer to HTTP response */
|
||||||
|
|
||||||
|
// ## For Debugging
|
||||||
|
//static uint8_t uri_buf[128];
|
||||||
|
|
||||||
|
// Number of registered web content in code flash memory
|
||||||
|
static uint16_t total_content_cnt = 0;
|
||||||
|
/*****************************************************************************
|
||||||
|
* Public types/enumerations/variables
|
||||||
|
****************************************************************************/
|
||||||
|
uint8_t * pHTTP_TX;
|
||||||
|
uint8_t * pHTTP_RX;
|
||||||
|
|
||||||
|
volatile uint32_t httpServer_tick_1s = 0;
|
||||||
|
st_http_socket HTTPSock_Status[_WIZCHIP_SOCK_NUM_] = { {STATE_HTTP_IDLE, }, };
|
||||||
|
httpServer_webContent web_content[MAX_CONTENT_CALLBACK];
|
||||||
|
|
||||||
|
#ifdef _USE_SDCARD_
|
||||||
|
FIL fs; // FatFs: File object
|
||||||
|
FRESULT fr; // FatFs: File function return code
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Private functions
|
||||||
|
****************************************************************************/
|
||||||
|
void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist);
|
||||||
|
static uint8_t getHTTPSocketNum(uint8_t seqnum);
|
||||||
|
static int8_t getHTTPSequenceNum(uint8_t socket);
|
||||||
|
static int8_t http_disconnect(uint8_t sn);
|
||||||
|
|
||||||
|
static void http_process_handler(uint8_t s, st_http_request * p_http_request);
|
||||||
|
static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status);
|
||||||
|
static void send_http_response_body(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len);
|
||||||
|
static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len);
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Public functions
|
||||||
|
****************************************************************************/
|
||||||
|
// Callback functions definition: MCU Reset / WDT Reset
|
||||||
|
void default_mcu_reset(void) {;}
|
||||||
|
void default_wdt_reset(void) {;}
|
||||||
|
void (*HTTPServer_ReStart)(void) = default_mcu_reset;
|
||||||
|
void (*HTTPServer_WDT_Reset)(void) = default_wdt_reset;
|
||||||
|
|
||||||
|
void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
// Mapping the H/W socket numbers to the sequential index numbers
|
||||||
|
HTTPSock_Num[i] = socklist[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t getHTTPSocketNum(uint8_t seqnum)
|
||||||
|
{
|
||||||
|
// Return the 'H/W socket number' corresponding to the index number
|
||||||
|
return HTTPSock_Num[seqnum];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int8_t getHTTPSequenceNum(uint8_t socket)
|
||||||
|
{
|
||||||
|
uint8_t i;
|
||||||
|
|
||||||
|
for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++)
|
||||||
|
if(HTTPSock_Num[i] == socket) return i;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist)
|
||||||
|
{
|
||||||
|
// User's shared buffer
|
||||||
|
pHTTP_TX = tx_buf;
|
||||||
|
pHTTP_RX = rx_buf;
|
||||||
|
|
||||||
|
// H/W Socket number mapping
|
||||||
|
httpServer_Sockinit(cnt, socklist);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Register the call back functions for HTTP Server */
|
||||||
|
void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void))
|
||||||
|
{
|
||||||
|
// Callback: HW Reset and WDT reset function for each MCU platforms
|
||||||
|
if(mcu_reset) HTTPServer_ReStart = mcu_reset;
|
||||||
|
if(wdt_reset) HTTPServer_WDT_Reset = wdt_reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void httpServer_run(uint8_t seqnum)
|
||||||
|
{
|
||||||
|
uint8_t s; // socket number
|
||||||
|
uint16_t len;
|
||||||
|
uint32_t gettime = 0;
|
||||||
|
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
uint8_t destip[4] = {0, };
|
||||||
|
uint16_t destport = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
http_request = (st_http_request *)pHTTP_RX; // Structure of HTTP Request
|
||||||
|
parsed_http_request = (st_http_request *)pHTTP_TX;
|
||||||
|
|
||||||
|
// Get the H/W socket number
|
||||||
|
s = getHTTPSocketNum(seqnum);
|
||||||
|
|
||||||
|
/* HTTP Service Start */
|
||||||
|
switch(getSn_SR(s))
|
||||||
|
{
|
||||||
|
case SOCK_ESTABLISHED:
|
||||||
|
// Interrupt clear
|
||||||
|
if(getSn_IR(s) & Sn_IR_CON)
|
||||||
|
{
|
||||||
|
setSn_IR(s, Sn_IR_CON);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HTTP Process states
|
||||||
|
switch(HTTPSock_Status[seqnum].sock_status)
|
||||||
|
{
|
||||||
|
|
||||||
|
case STATE_HTTP_IDLE :
|
||||||
|
if ((len = getSn_RX_RSR(s)) > 0)
|
||||||
|
{
|
||||||
|
if (len > DATA_BUF_SIZE) len = DATA_BUF_SIZE;
|
||||||
|
len = recv(s, (uint8_t *)http_request, len);
|
||||||
|
|
||||||
|
*(((uint8_t *)http_request) + len) = '\0';
|
||||||
|
|
||||||
|
parse_http_request(parsed_http_request, (uint8_t *)http_request);
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
getSn_DIPR(s, destip);
|
||||||
|
destport = getSn_DPORT(s);
|
||||||
|
printf("\r\n");
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Request received ", s);
|
||||||
|
printf("from %d.%d.%d.%d : %d\r\n", destip[0], destip[1], destip[2], destip[3], destport);
|
||||||
|
#endif
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE\r\n", s);
|
||||||
|
#endif
|
||||||
|
// HTTP 'response' handler; includes send_http_response_header / body function
|
||||||
|
http_process_handler(s, parsed_http_request);
|
||||||
|
|
||||||
|
gettime = get_httpServer_timecount();
|
||||||
|
// Check the TX socket buffer for End of HTTP response sends
|
||||||
|
while(getSn_TX_FSR(s) != (getSn_TXBUF_SIZE(s)*1024))
|
||||||
|
{
|
||||||
|
if((get_httpServer_timecount() - gettime) > 3)
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE: TX Buffer clear timeout\r\n", s);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(HTTPSock_Status[seqnum].file_len > 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_INPROC;
|
||||||
|
else HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE; // Send the 'HTTP response' end
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_HTTP_RES_INPROC :
|
||||||
|
/* Repeat: Send the remain parts of HTTP responses */
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_INPROC\r\n", s);
|
||||||
|
#endif
|
||||||
|
// Repeatedly send remaining data to client
|
||||||
|
send_http_response_body(s, 0, http_response, 0, 0);
|
||||||
|
|
||||||
|
if(HTTPSock_Status[seqnum].file_len == 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_HTTP_RES_DONE :
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [State] STATE_HTTP_RES_DONE\r\n", s);
|
||||||
|
#endif
|
||||||
|
// Socket file info structure re-initialize
|
||||||
|
HTTPSock_Status[seqnum].file_len = 0;
|
||||||
|
HTTPSock_Status[seqnum].file_offset = 0;
|
||||||
|
HTTPSock_Status[seqnum].file_start = 0;
|
||||||
|
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_IDLE;
|
||||||
|
|
||||||
|
//#ifdef _USE_SDCARD_
|
||||||
|
// f_close(&fs);
|
||||||
|
//#endif
|
||||||
|
#ifdef _USE_WATCHDOG_
|
||||||
|
HTTPServer_WDT_Reset();
|
||||||
|
#endif
|
||||||
|
http_disconnect(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSE_WAIT:
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : ClOSE_WAIT\r\n", s); // if a peer requests to close the current connection
|
||||||
|
#endif
|
||||||
|
disconnect(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_CLOSED:
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : CLOSED\r\n", s);
|
||||||
|
#endif
|
||||||
|
if(socket(s, Sn_MR_TCP, HTTP_SERVER_PORT, 0x00) == s) /* Reinitialize the socket */
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : OPEN\r\n", s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_INIT:
|
||||||
|
listen(s);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SOCK_LISTEN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
break;
|
||||||
|
|
||||||
|
} // end of switch
|
||||||
|
|
||||||
|
#ifdef _USE_WATCHDOG_
|
||||||
|
HTTPServer_WDT_Reset();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////
|
||||||
|
// Private Functions
|
||||||
|
////////////////////////////////////////////
|
||||||
|
static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status)
|
||||||
|
{
|
||||||
|
switch(http_status)
|
||||||
|
{
|
||||||
|
case STATUS_OK: // HTTP/1.1 200 OK
|
||||||
|
if((content_type != PTYPE_CGI) && (content_type != PTYPE_XML)) // CGI/XML type request does not respond HTTP header
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_OK\r\n", s);
|
||||||
|
#endif
|
||||||
|
make_http_response_head((char*)http_response, content_type, body_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response Header - NONE / CGI or XML\r\n", s);
|
||||||
|
#endif
|
||||||
|
// CGI/XML type request does not respond HTTP header to client
|
||||||
|
http_status = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case STATUS_BAD_REQ: // HTTP/1.1 400 OK
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_BAD_REQ\r\n", s);
|
||||||
|
#endif
|
||||||
|
memcpy(http_response, ERROR_REQUEST_PAGE, sizeof(ERROR_REQUEST_PAGE));
|
||||||
|
break;
|
||||||
|
case STATUS_NOT_FOUND: // HTTP/1.1 404 Not Found
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response Header - STATUS_NOT_FOUND\r\n", s);
|
||||||
|
#endif
|
||||||
|
memcpy(http_response, ERROR_HTML_PAGE, sizeof(ERROR_HTML_PAGE));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send the HTTP Response 'header'
|
||||||
|
if(http_status)
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [Send] HTTP Response Header [ %d ]byte\r\n", s, (uint16_t)strlen((char *)http_response));
|
||||||
|
#endif
|
||||||
|
send(s, http_response, strlen((char *)http_response));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_http_response_body(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len)
|
||||||
|
{
|
||||||
|
int8_t get_seqnum;
|
||||||
|
uint32_t send_len;
|
||||||
|
|
||||||
|
uint8_t flag_datasend_end = 0;
|
||||||
|
|
||||||
|
#ifdef _USE_SDCARD_
|
||||||
|
uint16_t blocklen;
|
||||||
|
#endif
|
||||||
|
#ifdef _USE_FLASH_
|
||||||
|
uint32_t addr = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number
|
||||||
|
|
||||||
|
// Send the HTTP Response 'body'; requested file
|
||||||
|
if(!HTTPSock_Status[get_seqnum].file_len) // ### Send HTTP response body: First part ###
|
||||||
|
{
|
||||||
|
if (file_len > DATA_BUF_SIZE - 1)
|
||||||
|
{
|
||||||
|
HTTPSock_Status[get_seqnum].file_start = start_addr;
|
||||||
|
HTTPSock_Status[get_seqnum].file_len = file_len;
|
||||||
|
send_len = DATA_BUF_SIZE - 1;
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
|
||||||
|
memset(HTTPSock_Status[get_seqnum].file_name, 0x00, MAX_CONTENT_NAME_LEN);
|
||||||
|
strcpy((char *)HTTPSock_Status[get_seqnum].file_name, (char *)uri_name);
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response body - file name [ %s ]\r\n", s, HTTPSock_Status[get_seqnum].file_name);
|
||||||
|
#endif
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response body - file len [ %ld ]byte\r\n", s, file_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Send process end
|
||||||
|
send_len = file_len;
|
||||||
|
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response end - file len [ %ld ]byte\r\n", s, send_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#ifdef _USE_FLASH_
|
||||||
|
if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH) addr = start_addr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else // remained parts
|
||||||
|
{
|
||||||
|
#ifdef _USE_FLASH_
|
||||||
|
if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH)
|
||||||
|
{
|
||||||
|
addr = HTTPSock_Status[get_seqnum].file_start + HTTPSock_Status[get_seqnum].file_offset;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
send_len = HTTPSock_Status[get_seqnum].file_len - HTTPSock_Status[get_seqnum].file_offset;
|
||||||
|
|
||||||
|
if(send_len > DATA_BUF_SIZE - 1)
|
||||||
|
{
|
||||||
|
send_len = DATA_BUF_SIZE - 1;
|
||||||
|
//HTTPSock_Status[get_seqnum]->file_offset += send_len;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response end - file len [ %ld ]byte\r\n", s, HTTPSock_Status[get_seqnum].file_len);
|
||||||
|
#endif
|
||||||
|
// Send process end
|
||||||
|
flag_datasend_end = 1;
|
||||||
|
}
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response body - send len [ %ld ]byte\r\n", s, send_len);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************/
|
||||||
|
//HTTPSock_Status[get_seqnum]->storage_type == NONE
|
||||||
|
//HTTPSock_Status[get_seqnum]->storage_type == CODEFLASH
|
||||||
|
//HTTPSock_Status[get_seqnum]->storage_type == SDCARD
|
||||||
|
//HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH
|
||||||
|
/*****************************************************/
|
||||||
|
|
||||||
|
if(HTTPSock_Status[get_seqnum].storage_type == CODEFLASH)
|
||||||
|
{
|
||||||
|
if(HTTPSock_Status[get_seqnum].file_len) start_addr = HTTPSock_Status[get_seqnum].file_start;
|
||||||
|
read_userReg_webContent(start_addr, &buf[0], HTTPSock_Status[get_seqnum].file_offset, send_len);
|
||||||
|
}
|
||||||
|
#ifdef _USE_SDCARD_
|
||||||
|
else if(HTTPSock_Status[get_seqnum].storage_type == SDCARD)
|
||||||
|
{
|
||||||
|
// Data read from SD Card
|
||||||
|
fr = f_read(&fs, &buf[0], send_len, (void *)&blocklen);
|
||||||
|
if(fr != FR_OK)
|
||||||
|
{
|
||||||
|
send_len = 0;
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [FatFs] Error code return: %d (File Read) / HTTP Send Failed - %s\r\n", s, fr, HTTPSock_Status[get_seqnum].file_name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*(buf+send_len+1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _USE_FLASH_
|
||||||
|
else if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH)
|
||||||
|
{
|
||||||
|
// Data read from external data flash memory
|
||||||
|
read_from_flashbuf(addr, &buf[0], send_len);
|
||||||
|
*(buf+send_len+1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
send_len = 0;
|
||||||
|
}
|
||||||
|
// Requested content send to HTTP client
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [Send] HTTP Response body [ %ld ]byte\r\n", s, send_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(send_len) send(s, buf, send_len);
|
||||||
|
else flag_datasend_end = 1;
|
||||||
|
|
||||||
|
if(flag_datasend_end)
|
||||||
|
{
|
||||||
|
HTTPSock_Status[get_seqnum].file_start = 0;
|
||||||
|
HTTPSock_Status[get_seqnum].file_len = 0;
|
||||||
|
HTTPSock_Status[get_seqnum].file_offset = 0;
|
||||||
|
flag_datasend_end = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
HTTPSock_Status[get_seqnum].file_offset += send_len;
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response body - offset [ %ld ]\r\n", s, HTTPSock_Status[get_seqnum].file_offset);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
|
||||||
|
#ifdef _USE_SDCARD_
|
||||||
|
f_close(&fs);
|
||||||
|
#endif
|
||||||
|
// ## 20141219 added end
|
||||||
|
}
|
||||||
|
|
||||||
|
static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len)
|
||||||
|
{
|
||||||
|
uint16_t send_len = 0;
|
||||||
|
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response Header + Body - CGI\r\n", s);
|
||||||
|
#endif
|
||||||
|
send_len = sprintf((char *)buf, "%s%d\r\n\r\n%s", RES_CGIHEAD_OK, file_len, http_body);
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : HTTP Response Header + Body - send len [ %d ]byte\r\n", s, send_len);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
send(s, buf, send_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int8_t http_disconnect(uint8_t sn)
|
||||||
|
{
|
||||||
|
setSn_CR(sn,Sn_CR_DISCON);
|
||||||
|
/* wait to process the command... */
|
||||||
|
while(getSn_CR(sn));
|
||||||
|
|
||||||
|
return SOCK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void http_process_handler(uint8_t s, st_http_request * p_http_request)
|
||||||
|
{
|
||||||
|
uint8_t * uri_name;
|
||||||
|
uint32_t content_addr = 0;
|
||||||
|
uint16_t content_num = 0;
|
||||||
|
uint32_t file_len = 0;
|
||||||
|
|
||||||
|
uint8_t uri_buf[MAX_URI_SIZE]={0x00, };
|
||||||
|
|
||||||
|
uint16_t http_status;
|
||||||
|
int8_t get_seqnum;
|
||||||
|
uint8_t content_found;
|
||||||
|
|
||||||
|
if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number
|
||||||
|
|
||||||
|
http_status = 0;
|
||||||
|
http_response = pHTTP_RX;
|
||||||
|
file_len = 0;
|
||||||
|
|
||||||
|
//method Analyze
|
||||||
|
switch (p_http_request->METHOD)
|
||||||
|
{
|
||||||
|
case METHOD_ERR :
|
||||||
|
http_status = STATUS_BAD_REQ;
|
||||||
|
send_http_response_header(s, 0, 0, http_status);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case METHOD_HEAD :
|
||||||
|
case METHOD_GET :
|
||||||
|
get_http_uri_name(p_http_request->URI, uri_buf);
|
||||||
|
uri_name = uri_buf;
|
||||||
|
|
||||||
|
if (!strcmp((char *)uri_name, "/")) strcpy((char *)uri_name, INITIAL_WEBPAGE); // If URI is "/", respond by index.html
|
||||||
|
if (!strcmp((char *)uri_name, "m")) strcpy((char *)uri_name, M_INITIAL_WEBPAGE);
|
||||||
|
if (!strcmp((char *)uri_name, "mobile")) strcpy((char *)uri_name, MOBILE_INITIAL_WEBPAGE);
|
||||||
|
find_http_uri_type(&p_http_request->TYPE, uri_name); // Checking requested file types (HTML, TEXT, GIF, JPEG and Etc. are included)
|
||||||
|
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("\r\n> HTTPSocket[%d] : HTTP Method GET\r\n", s);
|
||||||
|
printf("> HTTPSocket[%d] : Request Type = %d\r\n", s, p_http_request->TYPE);
|
||||||
|
printf("> HTTPSocket[%d] : Request URI = %s\r\n", s, uri_name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(p_http_request->TYPE == PTYPE_CGI)
|
||||||
|
{
|
||||||
|
content_found = http_get_cgi_handler(uri_name, pHTTP_TX, &file_len);
|
||||||
|
if(content_found && (file_len <= (DATA_BUF_SIZE-(strlen(RES_CGIHEAD_OK)+8))))
|
||||||
|
{
|
||||||
|
send_http_response_cgi(s, http_response, pHTTP_TX, (uint16_t)file_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Find the User registered index for web content
|
||||||
|
if(find_userReg_webContent(uri_buf, &content_num, &file_len))
|
||||||
|
{
|
||||||
|
content_found = 1; // Web content found in code flash memory
|
||||||
|
content_addr = (uint32_t)content_num;
|
||||||
|
HTTPSock_Status[get_seqnum].storage_type = CODEFLASH;
|
||||||
|
}
|
||||||
|
// Not CGI request, Web content in 'SD card' or 'Data flash' requested
|
||||||
|
#ifdef _USE_SDCARD_
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("\r\n> HTTPSocket[%d] : Searching the requested content\r\n", s);
|
||||||
|
#endif
|
||||||
|
if((fr = f_open(&fs, (const char *)uri_name, FA_READ)) == 0)
|
||||||
|
{
|
||||||
|
content_found = 1; // file open succeed
|
||||||
|
|
||||||
|
file_len = fs.fsize;
|
||||||
|
content_addr = fs.sclust;
|
||||||
|
HTTPSock_Status[get_seqnum].storage_type = SDCARD;
|
||||||
|
}
|
||||||
|
#elif _USE_FLASH_
|
||||||
|
else if(/* Read content from Dataflash */)
|
||||||
|
{
|
||||||
|
content_found = 1;
|
||||||
|
HTTPSock_Status[get_seqnum]->storage_type = DATAFLASH;
|
||||||
|
; // To do
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
{
|
||||||
|
content_found = 0; // fail to find content
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!content_found)
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : Unknown Page Request\r\n", s);
|
||||||
|
#endif
|
||||||
|
http_status = STATUS_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : Find Content [%s] ok - Start [%ld] len [ %ld ]byte\r\n", s, uri_name, content_addr, file_len);
|
||||||
|
#endif
|
||||||
|
http_status = STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send HTTP header
|
||||||
|
if(http_status)
|
||||||
|
{
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : Requested content len = [ %ld ]byte\r\n", s, file_len);
|
||||||
|
#endif
|
||||||
|
send_http_response_header(s, p_http_request->TYPE, file_len, http_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send HTTP body (content)
|
||||||
|
if(http_status == STATUS_OK)
|
||||||
|
{
|
||||||
|
send_http_response_body(s, uri_name, http_response, content_addr, file_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case METHOD_POST :
|
||||||
|
mid((char *)p_http_request->URI, "/", " HTTP", (char *)uri_buf);
|
||||||
|
uri_name = uri_buf;
|
||||||
|
find_http_uri_type(&p_http_request->TYPE, uri_name); // Check file type (HTML, TEXT, GIF, JPEG are included)
|
||||||
|
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("\r\n> HTTPSocket[%d] : HTTP Method POST\r\n", s);
|
||||||
|
printf("> HTTPSocket[%d] : Request URI = %s ", s, uri_name);
|
||||||
|
printf("Type = %d\r\n", p_http_request->TYPE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(p_http_request->TYPE == PTYPE_CGI) // HTTP POST Method; CGI Process
|
||||||
|
{
|
||||||
|
content_found = http_post_cgi_handler(uri_name, p_http_request, http_response, &file_len);
|
||||||
|
#ifdef _HTTPSERVER_DEBUG_
|
||||||
|
printf("> HTTPSocket[%d] : [CGI: %s] / Response len [ %ld ]byte\r\n", s, content_found?"Content found":"Content not found", file_len);
|
||||||
|
#endif
|
||||||
|
if(content_found && (file_len <= (DATA_BUF_SIZE-(strlen(RES_CGIHEAD_OK)+8))))
|
||||||
|
{
|
||||||
|
send_http_response_cgi(s, pHTTP_TX, http_response, (uint16_t)file_len);
|
||||||
|
|
||||||
|
// Reset the H/W for apply to the change configuration information
|
||||||
|
if(content_found == HTTP_RESET) HTTPServer_ReStart();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // HTTP POST Method; Content not found
|
||||||
|
{
|
||||||
|
send_http_response_header(s, 0, 0, STATUS_NOT_FOUND);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default :
|
||||||
|
http_status = STATUS_BAD_REQ;
|
||||||
|
send_http_response_header(s, 0, 0, http_status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void httpServer_time_handler(void)
|
||||||
|
{
|
||||||
|
httpServer_tick_1s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_httpServer_timecount(void)
|
||||||
|
{
|
||||||
|
return httpServer_tick_1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content)
|
||||||
|
{
|
||||||
|
uint16_t name_len;
|
||||||
|
uint32_t content_len;
|
||||||
|
|
||||||
|
if(content_name == NULL || content == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(total_content_cnt >= MAX_CONTENT_CALLBACK)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
name_len = strlen((char *)content_name);
|
||||||
|
content_len = strlen((char *)content);
|
||||||
|
|
||||||
|
web_content[total_content_cnt].content_name = malloc(name_len+1);
|
||||||
|
strcpy((char *)web_content[total_content_cnt].content_name, (const char *)content_name);
|
||||||
|
web_content[total_content_cnt].content_len = content_len;
|
||||||
|
web_content[total_content_cnt].content = content;
|
||||||
|
|
||||||
|
total_content_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t display_reg_webContent_list(void)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint8_t ret;
|
||||||
|
|
||||||
|
if(total_content_cnt == 0)
|
||||||
|
{
|
||||||
|
printf(">> Web content file not found\r\n");
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("\r\n=== List of Web content in code flash ===\r\n");
|
||||||
|
for(i = 0; i < total_content_cnt; i++)
|
||||||
|
{
|
||||||
|
printf(" [%d] ", i+1);
|
||||||
|
printf("%s, ", web_content[i].content_name);
|
||||||
|
printf("%ld byte, ", web_content[i].content_len);
|
||||||
|
|
||||||
|
if(web_content[i].content_len < 30) printf("[%s]\r\n", web_content[i].content);
|
||||||
|
else printf("[ ... ]\r\n");
|
||||||
|
}
|
||||||
|
printf("=========================================\r\n\r\n");
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len)
|
||||||
|
{
|
||||||
|
uint16_t i;
|
||||||
|
uint8_t ret = 0; // '0' means 'File Not Found'
|
||||||
|
|
||||||
|
for(i = 0; i < total_content_cnt; i++)
|
||||||
|
{
|
||||||
|
if(!strcmp((char *)content_name, (char *)web_content[i].content_name))
|
||||||
|
{
|
||||||
|
*file_len = web_content[i].content_len;
|
||||||
|
*content_num = i;
|
||||||
|
ret = 1; // If the requested content found, ret set to '1' (Found)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size)
|
||||||
|
{
|
||||||
|
uint16_t ret = 0;
|
||||||
|
uint8_t * ptr;
|
||||||
|
|
||||||
|
if(content_num > total_content_cnt) return 0;
|
||||||
|
|
||||||
|
ptr = web_content[content_num].content;
|
||||||
|
if(offset) ptr += offset;
|
||||||
|
|
||||||
|
strncpy((char *)buf, (char *)ptr, size);
|
||||||
|
*(buf+size) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
|
||||||
|
|
||||||
|
ret = strlen((void *)buf);
|
||||||
|
return ret;
|
||||||
|
}
|
103
Internet/httpServer/httpServer.h
Normal file
103
Internet/httpServer/httpServer.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
@file httpServer.h
|
||||||
|
@brief Define constants and functions related HTTP Web server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifndef __HTTPSERVER_H__
|
||||||
|
#define __HTTPSERVER_H__
|
||||||
|
|
||||||
|
// HTTP Server debug message enable
|
||||||
|
#define _HTTPSERVER_DEBUG_
|
||||||
|
|
||||||
|
#define INITIAL_WEBPAGE "index.html"
|
||||||
|
#define M_INITIAL_WEBPAGE "m/index.html"
|
||||||
|
#define MOBILE_INITIAL_WEBPAGE "mobile/index.html"
|
||||||
|
|
||||||
|
/* Web Server Content Storage Select */
|
||||||
|
//#define _USE_SDCARD_
|
||||||
|
#ifndef _USE_SDCARD_
|
||||||
|
//#define _USE_FLASH_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(_USE_SDCARD_) && !defined(_USE_FLASH_)
|
||||||
|
#define _NOTUSED_STORAGE_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Watchdog timer */
|
||||||
|
//#define _USE_WATCHDOG_
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* HTTP Process states list
|
||||||
|
*********************************************/
|
||||||
|
#define STATE_HTTP_IDLE 0 /* IDLE, Waiting for data received (TCP established) */
|
||||||
|
#define STATE_HTTP_REQ_INPROC 1 /* Received HTTP request from HTTP client */
|
||||||
|
#define STATE_HTTP_REQ_DONE 2 /* The end of HTTP request parse */
|
||||||
|
#define STATE_HTTP_RES_INPROC 3 /* Sending the HTTP response to HTTP client (in progress) */
|
||||||
|
#define STATE_HTTP_RES_DONE 4 /* The end of HTTP response send (HTTP transaction ended) */
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* HTTP Simple Return Value
|
||||||
|
*********************************************/
|
||||||
|
#define HTTP_FAILED 0
|
||||||
|
#define HTTP_OK 1
|
||||||
|
#define HTTP_RESET 2
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* HTTP Content NAME length
|
||||||
|
*********************************************/
|
||||||
|
#define MAX_CONTENT_NAME_LEN 128
|
||||||
|
|
||||||
|
/*********************************************
|
||||||
|
* HTTP Timeout
|
||||||
|
*********************************************/
|
||||||
|
#define HTTP_MAX_TIMEOUT_SEC 3 // Sec.
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
NONE, ///< Web storage none
|
||||||
|
CODEFLASH, ///< Code flash memory
|
||||||
|
SDCARD, ///< SD card
|
||||||
|
DATAFLASH ///< External data flash memory
|
||||||
|
}StorageType;
|
||||||
|
|
||||||
|
typedef struct _st_http_socket
|
||||||
|
{
|
||||||
|
uint8_t sock_status;
|
||||||
|
uint8_t file_name[MAX_CONTENT_NAME_LEN];
|
||||||
|
uint32_t file_start;
|
||||||
|
uint32_t file_len;
|
||||||
|
uint32_t file_offset; // (start addr + sent size...)
|
||||||
|
uint8_t storage_type; // Storage type; Code flash, SDcard, Data flash ...
|
||||||
|
}st_http_socket;
|
||||||
|
|
||||||
|
// Web content structure for file in code flash memory
|
||||||
|
#define MAX_CONTENT_CALLBACK 20
|
||||||
|
|
||||||
|
typedef struct _httpServer_webContent
|
||||||
|
{
|
||||||
|
uint8_t * content_name;
|
||||||
|
uint32_t content_len;
|
||||||
|
uint8_t * content;
|
||||||
|
}httpServer_webContent;
|
||||||
|
|
||||||
|
|
||||||
|
void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist);
|
||||||
|
void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void));
|
||||||
|
void httpServer_run(uint8_t seqnum);
|
||||||
|
|
||||||
|
void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content);
|
||||||
|
uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len);
|
||||||
|
uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size);
|
||||||
|
uint8_t display_reg_webContent_list(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief HTTP Server 1sec Tick Timer handler
|
||||||
|
* @note SHOULD BE register to your system 1s Tick timer handler
|
||||||
|
*/
|
||||||
|
void httpServer_time_handler(void);
|
||||||
|
uint32_t get_httpServer_timecount(void);
|
||||||
|
|
||||||
|
#endif
|
65
Internet/httpServer/httpUtil.c
Normal file
65
Internet/httpServer/httpUtil.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* @file httpUtil.c
|
||||||
|
* @brief HTTP Server Utilities
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2014/07/15
|
||||||
|
* @par Revision
|
||||||
|
* 2014/07/15 - 1.0 Release
|
||||||
|
* @author
|
||||||
|
* \n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "httpUtil.h"
|
||||||
|
|
||||||
|
uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len)
|
||||||
|
{
|
||||||
|
uint8_t ret = HTTP_OK;
|
||||||
|
uint16_t len = 0;
|
||||||
|
|
||||||
|
if(predefined_get_cgi_processor(uri_name, buf, &len))
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else if(strcmp((const char *)uri_name, "example.cgi") == 0)
|
||||||
|
{
|
||||||
|
// To do
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// CGI file not found
|
||||||
|
ret = HTTP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret) *file_len = len;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len)
|
||||||
|
{
|
||||||
|
uint8_t ret = HTTP_OK;
|
||||||
|
uint16_t len = 0;
|
||||||
|
uint8_t val = 0;
|
||||||
|
|
||||||
|
if(predefined_set_cgi_processor(uri_name, p_http_request->URI, buf, &len))
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
|
else if(strcmp((const char *)uri_name, "example.cgi") == 0)
|
||||||
|
{
|
||||||
|
// To do
|
||||||
|
val = 1;
|
||||||
|
len = sprintf((char *)buf, "%d", val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// CGI file not found
|
||||||
|
ret = HTTP_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret) *file_len = len;
|
||||||
|
return ret;
|
||||||
|
}
|
24
Internet/httpServer/httpUtil.h
Normal file
24
Internet/httpServer/httpUtil.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* @file httpUtil.h
|
||||||
|
* @brief Header File for HTTP Server Utilities
|
||||||
|
* @version 1.0
|
||||||
|
* @date 2014/07/15
|
||||||
|
* @par Revision
|
||||||
|
* 2014/07/15 - 1.0 Release
|
||||||
|
* @author
|
||||||
|
* \n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HTTPUTIL_H__
|
||||||
|
#define __HTTPUTIL_H__
|
||||||
|
|
||||||
|
#include "httpServer.h"
|
||||||
|
#include "httpParser.h"
|
||||||
|
|
||||||
|
uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len);
|
||||||
|
uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len);
|
||||||
|
|
||||||
|
uint8_t predefined_get_cgi_processor(uint8_t * uri_name, uint8_t * buf, uint16_t * len);
|
||||||
|
uint8_t predefined_set_cgi_processor(uint8_t * uri_name, uint8_t * uri, uint8_t * buf, uint16_t * len);
|
||||||
|
|
||||||
|
#endif
|
@ -14,5 +14,8 @@ This driver provides the Berkeley Socket type APIs.
|
|||||||
- DNS client
|
- DNS client
|
||||||
- Others will be added.
|
- Others will be added.
|
||||||
|
|
||||||
|
## How to add an ioLibrary in project through github site.
|
||||||
|
- Example, refer to https://www.youtube.com/watch?v=mt815RBGdsA
|
||||||
|
|
||||||
## Revision History
|
## Revision History
|
||||||
Last release : Nov. 2014
|
Last release : Nov. 2014
|
||||||
|
Reference in New Issue
Block a user