F1CTL/Core/Src/http_server.c

197 lines
6.2 KiB
C
Raw Normal View History

2024-12-15 02:41:36 +00:00
#include "http_server.h"
// HTML页面模板
2024-12-15 06:07:02 +00:00
#include "html_files.h"
2024-12-15 02:41:36 +00:00
// 解析HTTP请求
static void parse_http_request(uint8_t* buffer, uint16_t length, http_request* req)
{
char* method = strtok((char*)buffer, " ");
char* uri = strtok(NULL, " ");
if(strcmp(method, "GET") == 0) {
req->method = HTTP_GET;
} else if(strcmp(method, "POST") == 0) {
req->method = HTTP_POST;
} else {
req->method = HTTP_UNKNOWN;
}
strncpy(req->uri, uri, MAX_URI_SIZE);
// 如果是POST请求查找请求体
if(req->method == HTTP_POST) {
char* body = strstr((char*)buffer, "\r\n\r\n");
if(body) {
body += 4;
req->body = (uint8_t*)body;
req->body_length = length - (body - (char*)buffer);
}
}
}
// 发送HTTP响应
2024-12-15 06:07:02 +00:00
static int send_all(uint8_t sn, const uint8_t* data, uint16_t length)
2024-12-15 02:41:36 +00:00
{
2024-12-15 06:07:02 +00:00
int total_sent = 0;
while (total_sent < length) {
int sent = send(sn, data + total_sent, length - total_sent);
if (sent <= 0) {
return -1; // 发送错误
}
total_sent += sent;
}
return total_sent;
}
static void send_chunked_response_header(uint8_t sn)
{
const char* header =
"HTTP/1.1 200 OK\r\n"
"Content-Type: text/html\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n";
2024-12-15 02:41:36 +00:00
2024-12-15 06:07:02 +00:00
send_all(sn, (uint8_t*)header, strlen(header));
}
static void send_chunk(uint8_t sn, const char* data, uint16_t length)
{
char chunk_header[10];
sprintf(chunk_header, "%X\r\n", length);
send_all(sn, (uint8_t*)chunk_header, strlen(chunk_header));
send_all(sn, (uint8_t*)data, length);
send_all(sn, (uint8_t*)"\r\n", 2);
2024-12-15 02:41:36 +00:00
}
2024-12-15 06:07:02 +00:00
static void send_chunk_end(uint8_t sn)
{
send_all(sn, (uint8_t*)"0\r\n\r\n", 5);
}
#define CHUNK_SIZE 512
2024-12-15 02:41:36 +00:00
// 处理配置页面请求
static void handle_config_page(uint8_t sn)
{
2024-12-15 06:07:02 +00:00
char buffer[CHUNK_SIZE];
2024-12-15 02:41:36 +00:00
bool is_connected = (wizphy_getphylink() == PHY_LINK_ON);
char* link_status = is_connected ? "Connected" : "Disconnected";
char* status_class = is_connected ? "connected" : "disconnected";
2024-12-15 06:07:02 +00:00
// 先将完整的HTML内容格式化到一个临时缓冲区
char full_page[8192]; // 确保足够大
int total_len = sprintf(full_page, index_html,
2024-12-15 02:41:36 +00:00
gWIZNETINFO.mac[0], gWIZNETINFO.mac[1], gWIZNETINFO.mac[2],
gWIZNETINFO.mac[3], gWIZNETINFO.mac[4], gWIZNETINFO.mac[5],
gWIZNETINFO.ip[0], gWIZNETINFO.ip[1], gWIZNETINFO.ip[2], gWIZNETINFO.ip[3],
gWIZNETINFO.sn[0], gWIZNETINFO.sn[1], gWIZNETINFO.sn[2], gWIZNETINFO.sn[3],
gWIZNETINFO.gw[0], gWIZNETINFO.gw[1], gWIZNETINFO.gw[2], gWIZNETINFO.gw[3],
status_class, link_status);
2024-12-15 06:07:02 +00:00
// 发送响应头
send_chunked_response_header(sn);
// 分块发送内容
int sent = 0;
while (sent < total_len) {
int chunk_len = (total_len - sent) > CHUNK_SIZE ? CHUNK_SIZE : (total_len - sent);
memcpy(buffer, full_page + sent, chunk_len);
send_chunk(sn, buffer, chunk_len);
sent += chunk_len;
}
// 发送结束块
send_chunk_end(sn);
2024-12-15 02:41:36 +00:00
}
// 解析并更新网络配置
static void update_network_config(const char* body)
{
char mac[18], ip[16], subnet[16], gateway[16];
uint32_t mac_values[6], ip_values[4], subnet_values[4], gateway_values[4];
if(sscanf(body, "mac=%02X%%3A%02X%%3A%02X%%3A%02X%%3A%02X%%3A%02X&"
"ip=%d.%d.%d.%d&"
"subnet=%d.%d.%d.%d&"
"gateway=%d.%d.%d.%d",
&mac_values[0], &mac_values[1], &mac_values[2],
&mac_values[3], &mac_values[4], &mac_values[5],
&ip_values[0], &ip_values[1], &ip_values[2], &ip_values[3],
&subnet_values[0], &subnet_values[1], &subnet_values[2], &subnet_values[3],
&gateway_values[0], &gateway_values[1], &gateway_values[2], &gateway_values[3]) == 18)
{
// 更新MAC地址
for(int i = 0; i < 6; i++) {
gWIZNETINFO.mac[i] = (uint8_t)mac_values[i];
}
// 更新IP地址
for(int i = 0; i < 4; i++) {
gWIZNETINFO.ip[i] = (uint8_t)ip_values[i];
gWIZNETINFO.sn[i] = (uint8_t)subnet_values[i];
gWIZNETINFO.gw[i] = (uint8_t)gateway_values[i];
}
// 应用新的网络配置
wizchip_setnetinfo(&gWIZNETINFO);
}
}
void http_server_init(void)
{
// 创建服务器socket
socket(HTTP_SERVER_SOCKET, Sn_MR_TCP, HTTP_SERVER_PORT, 0);
listen(HTTP_SERVER_SOCKET);
}
void http_server_task(void)
{
uint8_t buffer[2048];
uint16_t size;
uint8_t status = getSn_SR(HTTP_SERVER_SOCKET);
switch(status)
{
case SOCK_LISTEN:
// 等待连接
break;
case SOCK_ESTABLISHED:
{
// 接收数据
if((size = getSn_RX_RSR(HTTP_SERVER_SOCKET)) > 0)
{
size = recv(HTTP_SERVER_SOCKET, buffer, sizeof(buffer));
if(size > 0)
{
http_request req;
parse_http_request(buffer, size, &req);
if(req.method == HTTP_GET) {
handle_config_page(HTTP_SERVER_SOCKET);
}
else if(req.method == HTTP_POST && strcmp(req.uri, "/config") == 0) {
update_network_config((char*)req.body);
// 重定向回配置页面
2024-12-15 06:07:02 +00:00
send_chunked_response_header(HTTP_SERVER_SOCKET);
send_chunk(HTTP_SERVER_SOCKET,
2024-12-15 02:41:36 +00:00
"<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>",
strlen("<html><head><meta http-equiv='refresh' content='0;url=/'></head></html>"));
2024-12-15 06:07:02 +00:00
send_chunk_end(HTTP_SERVER_SOCKET);
2024-12-15 02:41:36 +00:00
}
}
}
break;
}
case SOCK_CLOSE_WAIT:
disconnect(HTTP_SERVER_SOCKET);
break;
case SOCK_CLOSED:
socket(HTTP_SERVER_SOCKET, Sn_MR_TCP, HTTP_SERVER_PORT, 0);
listen(HTTP_SERVER_SOCKET);
break;
}
}