#include "lwip/opt.h" #include "lwip/arch.h" #include "lwip/api.h" #include "lwip/tcp.h" #include "http_server.h" #include "web_params_api.h" #include "parameters.h" #include "trap_params.h" #include "fsdata.c" #include "settings_api.h" #include "netconf.h" #include "common_config.h" //#include "testing.h" #include "rtc.h" #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #include #include static int fs_open(char *name, struct fs_file *file); static err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len); static void send_data(struct tcp_pcb *pcb, struct http_state *hs); SET_PAGE_t SET_PAGE = SET_PAGE_IDLE; #define SEND_BUF_MAX_LEN 2000 #define RECIVE_BUF_MAX_LEN 1500 char sendBuf[SEND_BUF_MAX_LEN]; uint16_t sendBufLoadLen = 0; uint16_t printLen = 0; //char printBuf[1000]; char receiveBuf[RECIVE_BUF_MAX_LEN]; uint16_t receivedBufLen = 0; /** * @brief closes tcp connection * @param pcb: pointer to a tcp_pcb struct * @param hs: pointer to a http_state struct * @retval */ static void close_conn(struct tcp_pcb *pcb, struct http_state *hs) { tcp_arg(pcb, NULL); tcp_sent(pcb, NULL); tcp_recv(pcb, NULL); mem_free(hs); tcp_close(pcb); } /** * @brief callback function for handling TCP HTTP traffic * @param arg: pointer to an argument structure to be passed to callback function * @param pcb: pointer to a tcp_pcb structure * @param p: pointer to a packet buffer * @param err: LwIP error code * @retval err */ static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) { char *data; struct http_state *hs; struct fs_file file = {0, 0}; hs = arg; if (err == ERR_OK && p != NULL) { tcp_recved(pcb, p->tot_len); if (hs->file == NULL) { data = p->payload; /* printLen = p->tot_len; memcpy(printBuf, p->payload , printLen); printf(printBuf); */ receivedBufLen = p->tot_len; memcpy(receiveBuf, p->payload , receivedBufLen); if (strncmp(data, "GET /main.css", 13) == 0) // + { fs_open("/main.css", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /rotek.png", 14) == 0) // + { fs_open("/rotek.png", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /favicon.ico", 16) == 0) // ? { fs_open("/favicon.ico", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /main.js", 12) == 0) // + { fs_open("/main.js", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /settings.html", 18) == 0) // + { fs_open("/settings.html", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /info.html", 14) == 0) // + { fs_open("/info.html", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /getJson.cgi", 16) == 0) // + { HTTP_GetParamsPage1(sendBuf); hs->file = sendBuf; hs->left = strlen(sendBuf); send_data(pcb, hs); tcp_sent(pcb, http_sent); } else if (strncmp(data, "GET /settings.cgi", 17) == 0) // + { SET_PAGE = SET_PAGE_PAGE2; if (HTTP_SettingsPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen) == SEND_REQUIRED_YES) { hs->file = sendBuf; hs->left = sendBufLoadLen; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else { fs_open("/settings.html", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } } else if (strncmp(data, "GET /info.cgi", 13) == 0) // + { if (HTTP_InfoPage(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen) == SEND_REQUIRED_YES) { hs->file = sendBuf; hs->left = sendBufLoadLen; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else { fs_open("/info.html", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } } /* Сброс настроек и сохранине */ else if (strncmp(data, "GET /reset.cgi", 14) == 0) { HTTP_ResetSettings(); HTTP_SaveSettings(); fs_open("/settings.html", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } /* Перезагрузка контроллера */ else if (strncmp(data, "GET /reboot.cgi", 15) == 0) { HTTP_Reboot(); } /* Подтверждение новых сетевых настроек */ else if (strncmp(data, "GET /confirm.cgi", 16) == 0) { SetWebReinitFlag(false); SetConfirmWebParamsFlag(); fs_open("/index.html", &file); hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } /* Проверка пароля, переход в bootloader */ else if (strncmp(data, "POST /checkpwd.cgi", 18) == 0) { HTTP_ConfirmBootPwd(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen); hs->file = sendBuf; hs->left = sendBufLoadLen; send_data(pcb, hs); tcp_sent(pcb, http_sent); } // На производстве else if (strncmp(data, "GET /setProdate.cgi", 19) == 0) { HTTP_Prodate(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen); hs->file = sendBuf; hs->left = sendBufLoadLen; send_data(pcb, hs); tcp_sent(pcb, http_sent); } // На производстве else if (strncmp(data, "GET /progon.cgi", 15) == 0) { HTTP_Progon(receiveBuf, sendBuf, receivedBufLen, &sendBufLoadLen); hs->file = sendBuf; hs->left = sendBufLoadLen; send_data(pcb, hs); tcp_sent(pcb, http_sent); } else { fs_open("/index.html", &file); // + hs->file = file.data; hs->left = file.len; send_data(pcb, hs); tcp_sent(pcb, http_sent); } } pbuf_free(p); close_conn(pcb,hs); } if (err == ERR_OK && p == NULL) { close_conn(pcb, hs); } return ERR_OK; } /** * @brief callback function for handling connection errors * @param arg: pointer to an argument to be passed to callback function * @param err: LwIP error code * @retval none */ static void conn_err(void *arg, err_t err) { struct http_state *hs; hs = arg; mem_free(hs); } /** * @brief callback function called after a successfull TCP data packet transmission * @param arg: pointer to an argument to be passed to callback function * @param pcb: pointer on tcp_pcb structure * @param len * @retval err : LwIP error code */ static err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len) { struct http_state *hs; hs = arg; if (hs->left > 0) { send_data(pcb, hs); } else { close_conn(pcb, hs); } return ERR_OK; } /** * @brief sends data found in member "file" of a http_state struct * @param pcb: pointer to a tcp_pcb struct * @param hs: pointer to a http_state struct * @retval none */ static void send_data(struct tcp_pcb *pcb, struct http_state *hs) { err_t err; u16_t len; /* We cannot send more data than space available in the send buffer */ if (tcp_sndbuf(pcb) < hs->left) { len = tcp_sndbuf(pcb); } else { len = hs->left; } err = tcp_write(pcb, hs->file, len, 0); if (err == ERR_OK) { hs->file += len; hs->left -= len; } } /** * @brief tcp poll callback function * @param arg: pointer to an argument to be passed to callback function * @param pcb: pointer on tcp_pcb structure * @retval err_t */ static err_t http_poll(void *arg, struct tcp_pcb *pcb) { if (arg == NULL) { tcp_close(pcb); } else { send_data(pcb, (struct http_state *)arg); } return ERR_OK; } /** * @brief callback function on TCP connection setup ( on port 80) * @param arg: pointer to an argument structure to be passed to callback function * @param pcb: pointer to a tcp_pcb structure * ¶m err: Lwip stack error code * @retval err */ static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err) { struct http_state *hs; /* Allocate memory for the structure that holds the state of the connection */ hs = mem_malloc(sizeof(struct http_state)); if (hs == NULL) { return ERR_MEM; } /* Initialize the structure. */ hs->file = NULL; hs->left = 0; /* Tell TCP that this is the structure we wish to be passed for our callbacks. */ tcp_arg(pcb, hs); /* Tell TCP that we wish to be informed of incoming data by a call to the http_recv() function. */ tcp_recv(pcb, http_recv); tcp_err(pcb, conn_err); tcp_poll(pcb, http_poll, 10); return ERR_OK; } /** * @brief Opens a file defined in fsdata.c ROM filesystem * @param name : pointer to a file name * @param file : pointer to a fs_file structure * @retval 1 if success, 0 if fail */ static int fs_open(char *name, struct fs_file *file) { struct fsdata_file_noconst *f; for (f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next) { if (!strcmp(name, f->name)) { file->data = f->data; file->len = f->len; return 1; } } return 0; } /** * @brief Initialize the HTTP server (start its thread) * @param none * @retval None */ void HTTP_Init() { //sys_thread_new("HTTP", http_server_netconn_thread, NULL, 3000, 2); struct tcp_pcb *pcb; /*create new pcb*/ pcb = tcp_new(); /* bind HTTP traffic to pcb */ tcp_bind(pcb, IP_ADDR_ANY, 80); /* start listening on port 80 */ pcb = tcp_listen(pcb); /* define callback function for TCP connection setup */ tcp_accept(pcb, http_accept); } /** * @brief * @retval None */ int HTTP_SettingsPage(char *bufIn, char *bufOut, uint16_t lenBufIn, uint16_t *lenBufOut) { char tempStr[30]; strncpy(tempStr, bufIn, 30); /* В запросе нет параметров, нужно формировать JSON ответ */ if (strpbrk(tempStr,"?") == 0) { memset(bufOut, 0, SEND_BUF_MAX_LEN); HTTP_GetSettings(bufOut); //printf(bufOut); *lenBufOut = strlen(bufOut); return SEND_REQUIRED_YES; } /* В запросе есть параметры, нужно парсить и сохранять настройки */ else { HTTP_SetSettings(bufIn, lenBufIn); return SEND_REQUIRED_NO; } } /** * @brief * @retval None */ int HTTP_InfoPage(char *bufIn, char *bufOut, uint16_t lenBufIn, uint16_t *lenBufOut) { char tempStr[30]; strncpy(tempStr, bufIn, 30); /* В запросе нет параметров, нужно формировать JSON ответ */ if (strpbrk(tempStr,"?") == 0) { memset(bufOut, 0, SEND_BUF_MAX_LEN); HTTP_GetInfo(bufOut); *lenBufOut = strlen(bufOut); return SEND_REQUIRED_YES; } /* В запросе есть параметры, нужно парсить и сохранять настройки */ else { HTTP_SetInfo(bufIn, lenBufIn); return SEND_REQUIRED_NO; /* HTTP_SetSettings(bufIn, lenBufIn); return SEND_REQUIRED_NO; */ } } /** * @brief Установка даты производства */ // TODO Убрать заглушку! void HTTP_Prodate(char *bufIn, char *bufOut, uint16_t lenBufIn, uint16_t *lenBufOut) { uint8_t valueLen = 0; char value[20]; memset(bufOut, 0, SEND_BUF_MAX_LEN); ClearParamString(bufIn); memset(value, 0, 20); GetParamValue(bufIn, "prodate=", value, &valueLen); /* printf("Prodate: "); printf(value); printf("\r\n"); */ /* Устанавливаем дату производства */ SETTINGS_SetProDate(value, valueLen); /* Устанавливаем дату следующей профилактики +1 год */ RTC_SetProfTime(value); /* Пока отправляем true */ strcpy(bufOut, "HTTP/1.0 200 OK\r\nContent-Type:text/html\r\n\r\nTrue"); *lenBufOut = strlen(bufOut); // TEST_SetServerFlag(); } /** * @brief Возвращает uptime, freq, dutycicle */ void HTTP_Progon(char *bufIn, char *bufOut, uint16_t lenBufIn, uint16_t *lenBufOut) { memset(bufOut, 0, SEND_BUF_MAX_LEN); HTTP_GetProgonParams(bufOut); *lenBufOut = strlen(bufOut); } /** * @brief * @retval None */ void HTTP_SetSettings(char *buf, uint16_t lenBuf) { uint8_t valueLen = 0; const uint8_t len = 20; char value[20]; //printf(buf); ClearParamString(buf); memset(value, 0, len); /* SNMP */ GetParamValue(buf, "read_community=", value, &valueLen); SetReadCommunity(value); memset(value, 0, len); GetParamValue(buf, "write_community=", value, &valueLen); SetWriteCommunity(value); memset(value, 0, len); GetParamValue(buf, "managerIP=", value, &valueLen); SetManagerIp(value); memset(value, 0, len); GetParamValue(buf, "managerIP2=", value, &valueLen); SetManagerIp2(value); memset(value, 0, len); GetParamValue(buf, "managerIP3=", value, &valueLen); SetManagerIp3(value); memset(value, 0, len); /* Сетевые параметры */ GetParamValue(buf, "dhcp=", value, &valueLen); SetDhcpStateStr(value); if (strncmp(value, "on", 2) != 0) // Если dhcp off устанавливаем параметры { memset(value, 0, len); GetParamValue(buf, "ipaddr=", value, &valueLen); SetIPStr(value); memset(value, 0, len); GetParamValue(buf, "gw=", value, &valueLen); SetGatewayStr(value); memset(value, 0, len); GetParamValue(buf, "mask=", value, &valueLen); SetMaskStr(value); memset(value, 0, len); } memset(value, 0, len); /* Если параметры WEB изменились выставляем флаг, сохраняем настройки и перезагружаемся */ if (GetStateWebReinit() == true) { SetWebReinitFlag(true); HTTP_SaveSettings(); /* Блокируем управление ключем на тау секунд*/ //IO_KeyBlockOn(); vTaskDelay(1010); NVIC_SystemReset(); } HTTP_SaveSettings(); } /** * @brief * @retval None */ void HTTP_SetInfo(char *buf, uint16_t lenBuf) { uint8_t valueLen = 0; const uint8_t len = 110; char value[110]; ClearParamString(buf); memset(value, 0, len); /* Владелец */ GetParamValue(buf, "owner=", value, &valueLen); HTTP_ReplaceSimbol(value, '+', ' '); SetOwner(value); memset(value, 0, len); /* Владелец */ GetParamValue(buf, "sysLocation=", value, &valueLen); HTTP_ReplaceSimbol(value, '+', ' '); SetLocation(value); memset(value, 0, len); /* Комментарий */ GetParamValue(buf, "comment=", value, &valueLen); HTTP_ReplaceSimbol(value, '+', ' '); SetComment(value); memset(value, 0, len); HTTP_SaveSettings(); } /** * @brief Проверка пароля для перехода в режим bootloader * @retval None */ void HTTP_ConfirmBootPwd(char *bufIn, char *bufOut, uint16_t lenBufIn, uint16_t *lenBufOut) { char tempStr[50]; strncpy(tempStr, bufIn, 50); char value[20]; uint8_t valueLen; memset(value, 0, 20); if (GetParamValue(tempStr, "password=", value, &valueLen)) { if (strcmp(BOOTLOADER_PASWORD, value) == 0) { *bufOut = '1'; /* Запускаем задачу отложенной перезагрузки. Контроллер должен успеть отправить ответ серверу о статусе пароля */ HTTP_StartResetTask(true); } else *bufOut = '0'; *lenBufOut = 1; } } /** * @brief * @retval None */ uint8_t GetParamValue(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen) { char *beginValue = 0; char *endValue = 0; int len = 0; char *strPtr = 0; strPtr = strstr(inStr, paramName); if (strPtr != 0) { beginValue = strpbrk(strPtr,"="); endValue = strpbrk(strPtr,"&"); if (endValue == 0) endValue = strpbrk(strPtr," "); len = endValue - beginValue - 1; strncpy(paramValue, beginValue + 1, len); *endValue = '0'; *beginValue = '0'; *paramLen = len; return 1; } else { *paramLen = 0; return 0; } } /** * @brief * @retval None */ /* uint8_t GetParamValueInEnd(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen) { char *beginValue = 0; char *endValue = 0; int len = 0; char *strPtr = 0; strPtr = strstr(inStr, paramName); if (strPtr != 0) { beginValue = strpbrk(strPtr,"="); endValue = strpbrk(strPtr," "); len = endValue - beginValue - 1; strncpy(paramValue, beginValue + 1, len); *endValue = '0'; *beginValue = '0'; *paramLen = len; return 1; } else { *paramLen = 0; return 0; } } */ void ClearParamString(char *inBuf) { uint16_t len; char *str; str = strstr(inBuf, "HTTP"); if (str != 0) { len = str - inBuf; memset(str, 0, RECIVE_BUF_MAX_LEN - len - 1); } } /** * @brief Замена символа в строке * @param *str - входная строка * @param sim1 - символ который надо заменить * @param sim2 - символ на который надо заменить */ void HTTP_ReplaceSimbol(char *str, char sim1, char sim2) { uint16_t len = strlen(str); for (uint16_t i = 0; i < len; i++) { if (*str == sim1) *str = sim2; str++; } }