httpserver.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585
  1. #include "httpserver.h"
  2. #include "lwip/def.h"
  3. #include "lwip/tcp.h"
  4. #include "fsdata.c"
  5. #include "main.h"
  6. #include "flash_if.h"
  7. #include "common_config.h"
  8. #include "conf.h"
  9. #include "settings_api.h"
  10. #include "crc.h"
  11. #include "board.h"
  12. #include "netconf.h"
  13. #ifdef SLAVEBRD_ENABLE
  14. #include "stm32sprog.h"
  15. #endif
  16. #ifdef LCD_ENABLE
  17. #include "lcd.h"
  18. #endif
  19. #include "led.h"
  20. #include "systick.h"
  21. #include <string.h>
  22. #include "tinystdio.h"
  23. #undef DBG
  24. #define DBG if(0)
  25. /* Uncomment this macro to compleately skip any flash read/write operations/
  26. USE THIS ONLY FOR DEBUG AND TESTING PURPOSES!
  27. NEVER UNKOMMENT FOR RELEASE BUILDS! */
  28. // #define DUMMY_PROG
  29. #ifdef DUMMY_PROG
  30. /* Disable main fw flash read/write operations */
  31. #define FLASH_If_Write(X, ...)
  32. #define FLASH_If_Erase(X, ...)
  33. #define CRC_Read() 0x00
  34. #define CRC_Calculate(X, ...) 0x00
  35. /* Disable daughter fw flash read/write operations */
  36. #define stmProg(X, ...)
  37. #define stmRebootForFlash(X, ...)
  38. #define stmConnect(X, ...) ok
  39. #define stmGetDevParams(X, ...) ok
  40. #define stmEraseFW(X, ...) ok
  41. #define stmReadFlashCrc() 0x00
  42. #define stmCalcFlashCrc(X, ...) 0x00
  43. #endif /* DUMMY_PROG*/
  44. #define FILENAME_MAX_LEN 30
  45. #define BOUNDARY_MAX_LEN 70
  46. #define BLOCK_PROG_TIMEOUT 20000
  47. #define COOKIES_MAX_LEN 64
  48. #define COOKIES_SET_ATTEMPTS 2
  49. #define BD_CONNECT_RETRY 3
  50. /* Max HTTP file name length including "/" */
  51. #define HTTP_FNAME_LEN 32
  52. /* Max HTTP Etag field length */
  53. #define MAX_ETAG_LEN 48
  54. #define MAIN_FW_SIZE USER_FLASH_END_ADDRESS - USER_FLASH_FIRST_PAGE_ADDRESS + 1
  55. #define DB_FW_SIZE DB_CPU_FLASH_END_ADDRESS - DB_CPU_FLASH_FIRST_PAGE_ADDRESS + 1
  56. #define HTTP_RET_UPLOAD_ERROR() do {\
  57. memset(sendBuf, 0, 32);\
  58. strcpy(sendBuf, HTTP_200_OK);\
  59. strcat(sendBuf, "0");\
  60. hs->file = sendBuf;\
  61. hs->left = strlen(sendBuf);\
  62. send_data(pcb, hs);\
  63. tcp_sent(pcb, http_sent);\
  64. htmlpage = UploadErrorPage;\
  65. SET_FWINVALID_FLAG();\
  66. } while(0)
  67. static char sendBuf[512];
  68. static char tempBuf[HW_REV_OFFSET + HW_REV_LEN];
  69. extern bool fDoneReset;
  70. extern bool fUpload;
  71. extern bool fInvalidFw;
  72. char lcdbuf[32] = {0};
  73. static vu32 DataFlag = 0;
  74. static vu32 BoundaryFlag = 0;
  75. static vu32 size = 0;
  76. static __IO uint32_t FlashWriteAddress;
  77. static u32 TotalReceived = 0;
  78. static char LeftBytesTab[4];
  79. static u8 LeftBytes = 0;
  80. static uint32_t BrowserFlag = 0;
  81. static uint32_t ContentOffset = 0;
  82. static __IO uint32_t TotalData = 0;
  83. static uint32_t FwDestSize = 0;
  84. static bool fEraseFlash = true;
  85. uint8_t update_timeout = UPDATE_TIMEOUT;
  86. struct http_state
  87. {
  88. char *file;
  89. u32_t left;
  90. };
  91. typedef enum {
  92. fw_unknown,
  93. fw_main_board,
  94. fw_daughter_board
  95. } fw_type_t;
  96. static fw_type_t fw_type = fw_unknown;
  97. htmlpageState htmlpage;
  98. /* Content Length */
  99. static const char Content_Length[17] = {
  100. 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x3a, 0x20,
  101. };
  102. static const char If_None_Match[] = "If-None-Match: ";
  103. static const char Etag[] = "ETag: ";
  104. const char HTTP_200_OK[] = "HTTP/1.1 200 OK\r\n\r\n";
  105. const char HTTP_304_NOT_MODIFIED[] = "HTTP/1.1 304 Not Modified\r\n\r\n";
  106. const char HTTP_200_OK_TEXT_HTML[] = "HTTP/1.1 200 OK\r\nContent-Type:text/html";
  107. const char Redirect_Head[] = "<!DOCTYPE html><html lang=""><head><meta charset=\"UTF-8\"><meta http-equiv=\"refresh\" ";
  108. const char Msg_Body[] = "<body style=\"background-color:#E8EBF1;\">\
  109. <p style=\"height:300px;line-height:300px;font-family:Arial,Helvetica,sans-serif;text-align:center;color:#333;\">";
  110. uint16_t printLen = 0;
  111. char printBuf[1500];
  112. uint32_t oldAdd = USER_FLASH_FIRST_PAGE_ADDRESS;
  113. uint32_t deltaAdd = 0;
  114. #ifdef SLAVEBRD_ENABLE
  115. uint32_t stm32addr = DB_CPU_FLASH_FIRST_PAGE_ADDRESS;
  116. static void IAP_HTTP_stmProg(char *data, uint32_t len);
  117. bool IAP_HTTP_stmConnect(void);
  118. #endif
  119. static uint32_t Parse_Content_Length(char *data, uint32_t len);
  120. void Parse_IfNonMatch(char *data, uint32_t len, char *value);
  121. static uint32_t Parse_Header(char *data, uint32_t len, const char *field, uint32_t flen, char *value);
  122. static bool Parse_Filename(const char *data, uint32_t len, fw_type_t *fw_type, uint32_t *fw_size);
  123. char *Parce_Boundary(const char *data, uint32_t len, char *dst, uint8_t dstlen);
  124. static void IAP_HTTP_writedata(char *data, uint32_t len);
  125. void ProgTimeout_Handler();
  126. /* file must be allocated by caller and will be filled in by the function. */
  127. static int fs_open(char *name, struct fs_file *file);
  128. bool send_file(char *filename, char *pnonmatch, struct tcp_pcb *pcb, struct http_state *hs, struct fs_file *file);
  129. void send_index_page(struct tcp_pcb *pcb, struct http_state *hs, struct pbuf *p, bool upload);
  130. static void PeriodicHandle(uint8_t progress);
  131. /* Get Cookie parameter value */
  132. bool GetCookieValue(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen);
  133. /* Check if Cookie is set or not */
  134. bool CookieIsSet(char *inStr, uint16_t inLen, char *paramName);
  135. // Implements the GNU function memmem much faster (2x) than the standard memmem
  136. char *memmem(char *haystack, int hlen, char *needle, int nlen)
  137. {
  138. if (nlen > hlen) return 0;
  139. int i = 0, j = 0;
  140. switch (nlen) { // we have a few specialized compares for certain needle sizes
  141. case 0: // no needle? just give the haystack
  142. return haystack;
  143. case 1: // just use memchr for 1-byte needle
  144. return memchr(haystack, needle[0], hlen);
  145. case 2: // use 16-bit compares for 2-byte needles
  146. for (i = 0; i < hlen - nlen + 1; i++) {
  147. if (*(uint16_t *)(haystack + i) == *(uint16_t *)needle) {
  148. return haystack + i;
  149. }
  150. }
  151. break;
  152. case 4: // use 32-bit compares for 4-byte needles
  153. for (i = 0; i < hlen - nlen + 1; i++) {
  154. if (*(uint32_t *)(haystack + i) == *(uint32_t *)needle) {
  155. return haystack + i;
  156. }
  157. }
  158. break;
  159. /* actually slower on my 32-bit machine
  160. case 8: // use 64-bit compares for 8-byte needles
  161. for (i=0; i<hlen-nlen+1; i++) {
  162. if (*(uint64_t*)(haystack+i)==*(uint64_t*)needle) {
  163. return haystack+i;
  164. }
  165. }
  166. break;
  167. */
  168. default: // generic compare for any other needle size
  169. // walk i through the haystack, matching j as long as needle[j] matches haystack[i]
  170. for (i = 0; i < hlen; i++) {
  171. if (haystack[i] == needle[j]) {
  172. if (j == nlen - 1) { // end of needle and it all matched? win.
  173. return haystack + i - j;
  174. } else { // keep advancing j (and i, implicitly)
  175. j++;
  176. }
  177. } else { // no match, rewind i the length of the failed match (j), and reset j
  178. i -= j;
  179. j = 0;
  180. }
  181. }
  182. }
  183. return NULL;
  184. }
  185. /**
  186. * @brief callback function for handling connection errors
  187. * @param arg: pointer to an argument to be passed to callback function
  188. * @param err: LwIP error code
  189. * @retval none
  190. */
  191. static void conn_err(void *arg, err_t err)
  192. {
  193. struct http_state *hs;
  194. (void)err;
  195. hs = arg;
  196. mem_free(hs);
  197. }
  198. /**
  199. * @brief closes tcp connection
  200. * @param pcb: pointer to a tcp_pcb struct
  201. * @param hs: pointer to a http_state struct
  202. * @retval
  203. */
  204. static void close_conn(struct tcp_pcb *pcb, struct http_state *hs)
  205. {
  206. tcp_arg(pcb, NULL);
  207. tcp_sent(pcb, NULL);
  208. tcp_recv(pcb, NULL);
  209. mem_free(hs);
  210. tcp_close(pcb);
  211. }
  212. /**
  213. * @brief sends data found in member "file" of a http_state struct
  214. * @param pcb: pointer to a tcp_pcb struct
  215. * @param hs: pointer to a http_state struct
  216. * @retval none
  217. */
  218. static void send_data(struct tcp_pcb *pcb, struct http_state *hs)
  219. {
  220. err_t err;
  221. u16_t len;
  222. /* We cannot send more data than space available in the send
  223. buffer */
  224. if (tcp_sndbuf(pcb) < hs->left) {
  225. len = tcp_sndbuf(pcb);
  226. } else {
  227. len = hs->left;
  228. }
  229. err = tcp_write(pcb, hs->file, len, 0);
  230. if (err == ERR_OK) {
  231. hs->file += len;
  232. hs->left -= len;
  233. }
  234. }
  235. /**
  236. * @brief tcp poll callback function
  237. * @param arg: pointer to an argument to be passed to callback function
  238. * @param pcb: pointer on tcp_pcb structure
  239. * @retval err_t
  240. */
  241. static err_t http_poll(void *arg, struct tcp_pcb *pcb)
  242. {
  243. if (arg == NULL) {
  244. tcp_close(pcb);
  245. } else {
  246. send_data(pcb, (struct http_state *)arg);
  247. }
  248. return ERR_OK;
  249. }
  250. /**
  251. * @brief callback function called after a successfull TCP data packet transmission
  252. * @param arg: pointer to an argument to be passed to callback function
  253. * @param pcb: pointer on tcp_pcb structure
  254. * @param len
  255. * @retval err : LwIP error code
  256. */
  257. static err_t http_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
  258. {
  259. struct http_state *hs;
  260. hs = arg;
  261. (void)len;
  262. if (hs->left > 0) {
  263. send_data(pcb, hs);
  264. } else {
  265. close_conn(pcb, hs);
  266. if (htmlpage == UploadDonePage) {
  267. #ifndef DUMMY_PROG
  268. fDoneReset = true;
  269. fUpload = false;
  270. #endif
  271. } else if (htmlpage == UploadErrorPage) {
  272. /* Don't reboot if update was failed, just reload main page */
  273. fUpload = false;
  274. }
  275. }
  276. return ERR_OK;
  277. }
  278. /**
  279. * @brief callback function for handling TCP HTTP traffic
  280. * @param arg: pointer to an argument structure to be passed to callback function
  281. * @param pcb: pointer to a tcp_pcb structure
  282. * @param p: pointer to a packet buffer
  283. * @param err: LwIP error code
  284. * @retval err
  285. */
  286. /* goback.cgi - возврат в основную прошивку */
  287. /* upload.cgi - загрузка новой прошивки */
  288. static err_t http_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
  289. {
  290. int32_t i, len = 0;
  291. static uint32_t temp_len = 0;
  292. uint32_t DataOffset, CrcRead = 0, CrcCalc = 0;
  293. char *data, *ptr;
  294. struct fs_file file = {0, 0};
  295. struct http_state *hs;
  296. static bool hw_validated = false;
  297. char fname[HTTP_FNAME_LEN];
  298. uint8_t fname_len;
  299. static struct tcp_pcb *upload_pcb = NULL;
  300. static cookie_attempt = 0;
  301. hs = arg;
  302. if (err == ERR_OK && p != NULL) {
  303. /* Inform TCP that we have taken the data */
  304. tcp_recved(pcb, p->tot_len);
  305. if (hs->file == NULL) {
  306. data = p->payload;
  307. len = p->tot_len;
  308. printLen = p->tot_len > 500 ? 500 : p->tot_len;
  309. memcpy(printBuf, p->payload, printLen);
  310. // DBG printf("\r\n[%d] %s...\r\n", p->tot_len, printBuf);
  311. // DBG printf("pcb: %p (%p)\r\n", pcb, upload_pcb);
  312. /* process HTTP GET requests */
  313. if (strncmp(data, "GET /", 5) == 0 && pcb != upload_pcb) {
  314. /* Возврат в основную прошивку. Сбрасываем флаг loadmode,
  315. * сохраняем настройки и перезагружаемся */
  316. if (strncmp(data, "GET /goback.cgi", 15) == 0) {
  317. /* Check if we realy can go back. Return to IAP if fw update was failed */
  318. if (!fInvalidFw) {
  319. /* Set loadMode = 0 */
  320. RTC_WriteBackupRegister(RTC_BKP_DR1, 0);
  321. } else {
  322. /* Set loadMode = 1 */
  323. RTC_WriteBackupRegister(RTC_BKP_DR1, 1);
  324. }
  325. #ifdef SLAVEBRD_ENABLE
  326. /* Reboot daughter board */
  327. stmReboot();
  328. #endif
  329. /* Self reboot */
  330. NVIC_SystemReset();
  331. }
  332. /* Статус обновления и таймаут до перезагрузки */
  333. else if (strncmp(data, "GET /status.cgi", 15) == 0) {
  334. memset(sendBuf, 0, sizeof(sendBuf));
  335. /* Headers для поддержки saffari */
  336. sprintf(sendBuf, "HTTP/1.1 200 OK\r\nContent-Type:text/json\r\n\r\n");
  337. char buf[32];
  338. uint8_t update_state = 0;
  339. if (upload_pcb != NULL && fw_type == fw_unknown) {
  340. update_state = 1;
  341. } else if (upload_pcb != NULL && fw_type == fw_daughter_board) {
  342. update_state = 2;
  343. } else if (upload_pcb != NULL && fw_type == fw_main_board) {
  344. update_state = 3;
  345. } else {
  346. update_state = 0;
  347. }
  348. strcat(sendBuf, "{");
  349. sprintf(buf, "\"upload\":\"%u\",", (unsigned int)update_state);
  350. strcat(sendBuf, buf);
  351. sprintf(buf, "\"progress\":\"%u\",", (unsigned int)(TotalReceived * 100 / size));
  352. strcat(sendBuf, buf);
  353. sprintf(buf, "\"wrtmr\":\"%u\",", timer_GetCountdown(&ProgTimeout_Handler) / 1000);
  354. strcat(sendBuf, buf);
  355. sprintf(buf, "\"updtmr\":\"%u\",", update_timeout);
  356. strcat(sendBuf, buf);
  357. #ifdef SLAVEBRD_ENABLE
  358. sprintf(buf, "\"file1\":\"%s\",", DAUGHTER_FW_NAME);
  359. strcat(sendBuf, buf);
  360. #endif
  361. sprintf(buf, "\"file2\":\"%s\",", MAIN_FW_NAME);
  362. strcat(sendBuf, buf);
  363. /* sprintf(buf, "\"rev\":\"%s\",", REVISION);
  364. strcat(sendBuf, buf); */
  365. sprintf(buf, "\"invalidfw\":%s", fInvalidFw ? "true" : "false");
  366. strcat(sendBuf, buf);
  367. strcat(sendBuf, "}");
  368. hs->file = sendBuf;
  369. hs->left = strlen(sendBuf);
  370. pbuf_free(p);
  371. send_data(pcb, hs);
  372. tcp_sent(pcb, http_sent);
  373. }
  374. else if ((strncmp(data, "GET /upload.html", 16) == 0) &&
  375. (!CookieIsSet(p->payload, p->tot_len, "file1=") ||
  376. !CookieIsSet(p->payload, p->tot_len, "file2="))) {
  377. if (cookie_attempt < COOKIES_SET_ATTEMPTS) {
  378. /* Cookies not found. Try to set. */
  379. send_index_page(pcb, hs, p, upload_pcb != NULL);
  380. cookie_attempt++;
  381. } else {
  382. cookie_attempt = 0;
  383. /* Send Cookie set error message */
  384. strcpy(sendBuf, HTTP_200_OK_TEXT_HTML);
  385. strcat(sendBuf, "\r\n\r\n");
  386. strcat(sendBuf, Redirect_Head);
  387. strcat(sendBuf, "</head>");
  388. strcat(sendBuf, Msg_Body);
  389. strcat(sendBuf, "Включите файлы cookie в браузере и попробуйте <a href=\"index.html\">еще раз.</a></p></body></html>\r\n\r\n");
  390. hs->file = sendBuf;
  391. hs->left = strlen(sendBuf);
  392. pbuf_free(p);
  393. send_data(pcb, hs);
  394. tcp_sent(pcb, http_sent);
  395. }
  396. }
  397. /* Check common GET request */
  398. else if (GetFileName(data, fname, &fname_len)) {
  399. char nonmatch[MAX_ETAG_LEN];
  400. char *pnonmatch = NULL;
  401. /* Parce If-Non_Match value */
  402. uint8_t nonmatch_len = Parse_Header(data, p->tot_len, If_None_Match, 15, nonmatch);
  403. if (nonmatch_len < MAX_ETAG_LEN && nonmatch_len > 0) {
  404. printf("If_None_Match: %s\r\n", nonmatch);
  405. pnonmatch = nonmatch;
  406. }
  407. if (send_file(fname, pnonmatch, pcb, hs, &file)) {
  408. pbuf_free(p);
  409. } else {
  410. send_index_page(pcb, hs, p, upload_pcb != NULL);
  411. }
  412. }
  413. /* Send default index page */
  414. else {
  415. send_index_page(pcb, hs, p, upload_pcb != NULL);
  416. }
  417. }
  418. /* Process POST request for file upload and incoming data packets after POST request */
  419. /* Tested MTU sizes: 400 - 1500. Sizes < 400 not supported currently. */
  420. else if ((strncmp(data, "POST /upload.cgi", 16) == 0 && upload_pcb == NULL) ||
  421. (DataFlag >= 1 && pcb == upload_pcb)) {
  422. static char boundary[BOUNDARY_MAX_LEN];
  423. static char boundary_part[BOUNDARY_MAX_LEN];
  424. static char *pbound = NULL;
  425. fUpload = true;
  426. DataOffset = 0;
  427. #ifndef DUMMY_PROG
  428. DBG printf("\r\n[%u] ______\r\n", (unsigned int)len);
  429. #endif
  430. /* POST Packet received */
  431. if (DataFlag == 0) {
  432. BrowserFlag = 0;
  433. TotalReceived = 0;
  434. BoundaryFlag = 0;
  435. temp_len = 0;
  436. upload_pcb = pcb;
  437. hw_validated = false;
  438. fw_type = fw_unknown;
  439. /* Reset block receive and prog timeout */
  440. timer_Restart(&ProgTimeout_Handler);
  441. /* Parse packet for Content-length field */
  442. size = Parse_Content_Length(data, p->tot_len);
  443. DBG printf("Content_Length: %u\r\n", (unsigned int)size);
  444. /* Parse packet for the boundary field */
  445. pbound = Parce_Boundary(data, p->tot_len, boundary, sizeof(boundary));
  446. DBG printf("boundary: %s\r\n", pbound ? boundary : "header not found");
  447. /* Find the boundary */
  448. if (pbound != NULL) {
  449. for (i = 0; i < len; i++) {
  450. if (strncmp((char *)(data + i), boundary, strlen(boundary)) == 0) {
  451. ContentOffset = i;
  452. BoundaryFlag = 1;
  453. DBG printf("boundary found\r\n");
  454. /* Parse packet for "\r\n\r\n" field */
  455. for (int32_t j = 0; j < len; j++) {
  456. if (strncmp((char *)(data + i + j), "\r\n\r\n", 4) == 0) {
  457. DataOffset = i + j + 4;
  458. break;
  459. }
  460. }
  461. }
  462. }
  463. }
  464. /* TODO Handle partially received boundary */
  465. if (BoundaryFlag) {
  466. TotalReceived = len - ContentOffset;
  467. }
  468. DBG {
  469. printf("Boundary: %s\r\n", BoundaryFlag ? "yes" : "no");
  470. printf("ContentOffset: %u\r\n", (unsigned int)ContentOffset);
  471. printf("DataOffset: %u\r\n", (unsigned int)DataOffset);
  472. printf("TotalReceived: %u/%u\r\n", (unsigned int)TotalReceived, (unsigned int)size);
  473. }
  474. if (fw_type == fw_unknown) {
  475. Parse_Filename(data, len, &fw_type, &FwDestSize);
  476. }
  477. /* No data in the first POST packet */
  478. if (DataOffset == 0) {
  479. DataFlag++;
  480. BrowserFlag = 1;
  481. pbuf_free(p);
  482. return ERR_OK;
  483. }
  484. }
  485. if (((DataFlag == 1) && (BrowserFlag == 1)) || ((DataFlag == 0) && (BrowserFlag == 0))) {
  486. if ((DataFlag == 0) && (BrowserFlag == 0)) {
  487. DataFlag++;
  488. } else if ((DataFlag == 1) && (BrowserFlag == 1)) {
  489. /* Find the boundary */
  490. for (i = 0; i < len; i++) {
  491. if (pbound != NULL) {
  492. if (strncmp((char *)(data + i), boundary, strlen(boundary)) == 0 || BoundaryFlag == 1) {
  493. /* Parse packet for "\r\n\r\n" field */
  494. for (int32_t j = 0; j < len; j++) {
  495. if (strncmp((char *)(data + i + j), "\r\n\r\n", 4) == 0) {
  496. DataOffset = i + j + 4;
  497. break;
  498. }
  499. }
  500. break;
  501. }
  502. }
  503. }
  504. /* TODO Handle partially received boundary */
  505. TotalReceived += len;
  506. DataFlag++;
  507. }
  508. if (fw_type == fw_unknown) {
  509. Parse_Filename(data, len, &fw_type, &FwDestSize);
  510. }
  511. DBG {
  512. printf("ContentOffset: %u\r\n", (unsigned int)ContentOffset);
  513. printf("DataOffset: %u\r\n", (unsigned int)DataOffset);
  514. printf("TotalReceived: %u/%u\r\n", (unsigned int)TotalReceived, (unsigned int)size);
  515. }
  516. /* Get next packet */
  517. if (!DataOffset) {
  518. DataFlag--;
  519. pbuf_free(p);
  520. return ERR_OK;
  521. }
  522. if (fw_type == fw_unknown) {
  523. htmlpage = FileUploadPage;
  524. /* No filename, in this case reload upload page */
  525. fs_open("/index.html", &file);
  526. hs->file = file.data;
  527. hs->left = file.len;
  528. pbuf_free(p);
  529. send_data(pcb, hs);
  530. tcp_sent(pcb, http_sent);
  531. DataFlag = 0;
  532. upload_pcb = NULL;
  533. printf("Error: Unknown firmware\r\n");
  534. #ifdef LCD_ENABLE
  535. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  536. #endif
  537. return ERR_OK;
  538. }
  539. TotalData = 0;
  540. }
  541. /* DataFlag >1 => the packet is data only */
  542. else {
  543. TotalReceived += len;
  544. }
  545. ptr = (char *)(data + DataOffset);
  546. len -= DataOffset;
  547. /* Update total data received counter */
  548. TotalData += len;
  549. #ifndef DUMMY_PROG
  550. DBG printf("TotalData: +%u %u/%u\r\n", (unsigned int)len,
  551. (unsigned int)TotalData, (unsigned int)FwDestSize);
  552. DBG printf("%u/%u\r\n", (unsigned int)TotalReceived, (unsigned int)size);
  553. #endif
  554. /* Check if last data packet */
  555. if (TotalReceived == size) {
  556. /* Check if boundary was splited into two packets. Get second part. */
  557. /* Data transfer sequence should end with "\r\n" + boundary + "--\rn" (6 extra bytes) */
  558. if ((pbound) && (p->tot_len <= strlen(boundary) + 6)) {
  559. /* No data in packet */
  560. TotalData = TotalData - len;
  561. len = 0;
  562. } else {
  563. char *bptr = memmem(data, p->tot_len, boundary, strlen(boundary));
  564. // DBG printf("boundary: %s\r\n", boundary);
  565. if (bptr != NULL) {
  566. /* Substruct length of "\r\n" - 2 bytes */
  567. uint32_t last_len = bptr - data - 2;
  568. TotalData = TotalData - len + last_len;
  569. len = last_len;
  570. } else {
  571. printf("Boundary not found\r\n");
  572. }
  573. }
  574. }
  575. /* Not the last data packet */
  576. else if (TotalReceived < size) {
  577. /* Check if boundary was splited into two packets. Get first part. */
  578. /* Data transfer sequence should end with "\r\n" + boundary + "--\rn" (6 extra bytes) */
  579. if ((pbound) && (size - TotalReceived < strlen(boundary) + 6)) {
  580. uint16_t tail_len = size - TotalReceived;
  581. uint16_t boundary_len = strlen(boundary) + 6;
  582. /* Find "\r\n" or "\r" depending on a current packet length */
  583. uint8_t marker_len = (tail_len - boundary_len >= 2) ? 2 : 1;
  584. char *ptr = memmem(data + p->tot_len - boundary_len, boundary_len,
  585. marker_len == 2 ? "\r\n" : "\r", marker_len);
  586. if (ptr != NULL) {
  587. DBG {
  588. /* Boundary first part is not actually used, just for debug output */
  589. uint32_t buflen = len - (uint32_t)(ptr + marker_len - data);
  590. printf("buflen: %u\r\n", (unsigned int)buflen);
  591. if (buflen > BOUNDARY_MAX_LEN) buflen = BOUNDARY_MAX_LEN;
  592. memcpy(boundary_part, ptr + marker_len, buflen);
  593. printf("boundary part: %s\r\n", boundary_part);
  594. }
  595. uint32_t last_len = ptr - data;
  596. TotalData = TotalData - len + last_len;
  597. len = last_len;
  598. } else {
  599. DBG printf("Boundary part not found!\r\n");
  600. }
  601. }
  602. /* Validate uploaded binary */
  603. if ((TotalData >= HW_REV_OFFSET + HW_REV_LEN) && (!hw_validated)) {
  604. char rev[HW_REV_LEN];
  605. if (fw_type == fw_main_board) {
  606. strncpy(rev, HW_REV, HW_REV_LEN);
  607. }
  608. #ifdef SLAVEBRD_ENABLE
  609. else if (fw_type == fw_daughter_board) {
  610. strncpy(rev, HW_REV_UPPER, HW_REV_LEN);
  611. }
  612. #endif
  613. else {
  614. strncpy(rev, "-", HW_REV_LEN);
  615. }
  616. char bin_rev[HW_REV_LEN];
  617. memset(bin_rev, 0, sizeof(bin_rev));
  618. uint32_t first_len = temp_len > HW_REV_OFFSET ? temp_len - HW_REV_OFFSET : 0;
  619. /* Copy 1st part (if not empty) */
  620. memcpy(bin_rev, tempBuf + HW_REV_OFFSET, first_len);
  621. /* Copy 2nd part */
  622. memcpy(bin_rev + first_len, ptr + HW_REV_OFFSET - (temp_len - first_len), HW_REV_LEN - first_len);
  623. if (strncmp(bin_rev, rev, HW_REV_LEN) != 0) {
  624. printf("HW version (%s) mismatch: found %s\r\n", rev, bin_rev);
  625. printf("Update aborted!\r\n");
  626. #ifdef LCD_ENABLE
  627. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  628. #endif
  629. DataFlag = 0;
  630. upload_pcb = NULL;
  631. HTTP_RET_UPLOAD_ERROR();
  632. pbuf_free(p);
  633. return ERR_OK;
  634. } else {
  635. printf("HW version (%s) validated\r\n", bin_rev);
  636. hw_validated = true;
  637. printf("State: Erasing...\r\n");
  638. SET_FWINVALID_FLAG();
  639. #ifdef LCD_ENABLE
  640. LCD_ClearRow(7);
  641. #ifdef SLAVEBRD_ENABLE
  642. sprintf(lcdbuf, "Очистка %d/2 ", fw_type == fw_main_board ? 2 : 1);
  643. LCD_PrintAligned(5, alignCENTER, lcdbuf);
  644. #else
  645. LCD_PrintAligned(5, alignCENTER, "Очистка...");
  646. #endif
  647. #endif
  648. switch (fw_type) {
  649. case fw_main_board:
  650. /* Erase flash */
  651. if (fEraseFlash) {
  652. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  653. fEraseFlash = false;
  654. }
  655. /* Init flash */
  656. FLASH_If_Init();
  657. FlashWriteAddress = USER_FLASH_FIRST_PAGE_ADDRESS;
  658. break;
  659. #ifdef SLAVEBRD_ENABLE
  660. case fw_daughter_board:
  661. stm32addr = DB_CPU_FLASH_FIRST_PAGE_ADDRESS;
  662. uint8_t retries = 0;
  663. /* Try to connect to stm32 */
  664. while ((!IAP_HTTP_stmConnect()) && (retries++ < (BD_CONNECT_RETRY - 1))) {
  665. ;
  666. }
  667. /* Error if no device found */
  668. if (retries >= BD_CONNECT_RETRY) {
  669. #ifdef LCD_ENABLE
  670. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  671. #endif
  672. DataFlag = 0;
  673. upload_pcb = NULL;
  674. HTTP_RET_UPLOAD_ERROR();
  675. pbuf_free(p);
  676. return ERR_OK;
  677. }
  678. break;
  679. #endif
  680. default:
  681. break;
  682. }
  683. #ifdef LCD_ENABLE
  684. LCD_ClearRow(7);
  685. #ifdef SLAVEBRD_ENABLE
  686. sprintf(lcdbuf, "Запись %d/2", fw_type == fw_main_board ? 2 : 1);
  687. LCD_PrintAligned(5, alignCENTER, lcdbuf);
  688. #else
  689. LCD_PrintAligned(5, alignCENTER, "Запись...");
  690. #endif
  691. #endif
  692. /*indicate start of flash programming */
  693. printf("\r\nState: Programming..\r\n");
  694. }
  695. }
  696. }
  697. if (hw_validated) {
  698. /* Check fw data size overflow */
  699. if (TotalData > FwDestSize) {
  700. printf("FW binary size mismatch. Aborting update..\r\n");
  701. printf("FW dest size %u was %u\r\n", (unsigned int)FwDestSize, (unsigned int)TotalData);
  702. HTTP_RET_UPLOAD_ERROR();
  703. } else {
  704. static uint8_t progress = 0;
  705. if (progress != TotalReceived * 100 / size) {
  706. progress = TotalReceived * 100 / size;
  707. #ifndef DUMMY_PROG
  708. printf("Writing: %u%%\r\n", (unsigned int)progress);
  709. #ifdef LCD_ENABLE
  710. LCD_PrintBar(7, (unsigned int)(100 * TotalReceived / size));
  711. #endif
  712. #endif
  713. }
  714. /* Reset block prog timeout */
  715. timer_Restart(&ProgTimeout_Handler);
  716. /* Write data in flash */
  717. if (len) {
  718. switch (fw_type) {
  719. case fw_main_board:
  720. if (temp_len) {
  721. IAP_HTTP_writedata(tempBuf, temp_len);
  722. temp_len = 0;
  723. }
  724. IAP_HTTP_writedata(ptr, len);
  725. break;
  726. #ifdef SLAVEBRD_ENABLE
  727. case fw_daughter_board:
  728. if (temp_len) {
  729. IAP_HTTP_stmProg(tempBuf, temp_len);
  730. temp_len = 0;
  731. }
  732. IAP_HTTP_stmProg(ptr, len);
  733. break;
  734. #endif
  735. default:
  736. break;
  737. }
  738. }
  739. }
  740. } else {
  741. /* Save first part */
  742. memcpy(tempBuf + temp_len, ptr, len);
  743. temp_len += len;
  744. DBG printf("Stashed: %u\r\n", (unsigned int)temp_len);
  745. }
  746. if (TotalReceived == size) {
  747. /* Stop block receive timer */
  748. timer_Stop(&ProgTimeout_Handler);
  749. DataFlag = 0;
  750. upload_pcb = NULL;
  751. printf("State: Verifying..\r\n");
  752. #ifdef LCD_ENABLE
  753. LCD_ClearRow(7);
  754. #ifdef SLAVEBRD_ENABLE
  755. sprintf(lcdbuf, "Проверка CRC %d/2", fw_type == fw_main_board ? 2 : 1);
  756. LCD_PrintAligned(5, alignCENTER, lcdbuf);
  757. #else
  758. LCD_PrintAligned(5, alignCENTER, "Проверка CRC...");
  759. #endif
  760. #endif
  761. switch (fw_type) {
  762. case fw_main_board:
  763. CrcRead = CRC_Read();
  764. CrcCalc = CRC_Calculate(&PeriodicHandle);
  765. break;
  766. #ifdef SLAVEBRD_ENABLE
  767. case fw_daughter_board:
  768. CrcRead = stmReadFlashCrc();
  769. CrcCalc = stmCalcFlashCrc(&PeriodicHandle);
  770. break;
  771. #endif
  772. default:
  773. break;
  774. }
  775. printf("State: Prog Finished\r\n\r\n");
  776. printf("Tot bytes received: %u bytes\r\n", (unsigned int)TotalData);
  777. printf("CRC read: 0x%X\r\n", (unsigned int)CrcRead);
  778. printf("CRC calcucated: 0x%X\r\n", (unsigned int)CrcCalc);
  779. /* Check CRC */
  780. if (CrcRead == CrcCalc) {
  781. printf("CRC check: Pass\r\n");
  782. /* Reset block receive and prog timeout */
  783. timer_Restart(&ProgTimeout_Handler);
  784. memset(sendBuf, 0, 32);
  785. strcpy(sendBuf, HTTP_200_OK);
  786. strcat(sendBuf, "1");
  787. hs->file = sendBuf;
  788. hs->left = strlen(sendBuf);
  789. send_data(pcb, hs);
  790. tcp_sent(pcb, http_sent);
  791. #ifdef LCD_ENABLE
  792. LCD_PrintAligned(7, alignCENTER, "Успешно!");
  793. #endif
  794. switch (fw_type) {
  795. case fw_main_board:
  796. /* Run main FW */
  797. htmlpage = UploadDonePage;
  798. break;
  799. #ifdef SLAVEBRD_ENABLE
  800. case fw_daughter_board:
  801. timer_ChangeFrequency(&LED_Blinky_Green, 250);
  802. /* Nothing to do */
  803. break;
  804. #endif
  805. default:
  806. break;
  807. }
  808. } else {
  809. #ifdef LCD_ENABLE
  810. LCD_PrintAligned(7, alignCENTER, "Ошибка!");
  811. #endif
  812. switch (fw_type) {
  813. case fw_main_board:
  814. /* Erase flash */
  815. /* That's a way not to boot wrong FW next time if update was failed */
  816. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  817. fEraseFlash = false;
  818. break;
  819. #ifdef SLAVEBRD_ENABLE
  820. case fw_daughter_board:
  821. /* We can boot device if upper board update was failed. */
  822. break;
  823. #endif
  824. default:
  825. break;
  826. }
  827. printf("CRC check: Fail\r\n");
  828. HTTP_RET_UPLOAD_ERROR();
  829. }
  830. }
  831. pbuf_free(p);
  832. } else {
  833. /* Bad HTTP requests */
  834. printf("Bad HTTP request\r\n");
  835. pbuf_free(p);
  836. close_conn(pcb, hs);
  837. }
  838. } else {
  839. pbuf_free(p);
  840. close_conn(pcb, hs);
  841. }
  842. } else if (err == ERR_OK && p == NULL) {
  843. /* Received empty frame */
  844. printf("Received empty frame\r\n");
  845. close_conn(pcb, hs);
  846. }
  847. return ERR_OK;
  848. }
  849. /**
  850. * @brief callback function on TCP connection setup ( on port 80)
  851. * @param arg: pointer to an argument structure to be passed to callback function
  852. * @param pcb: pointer to a tcp_pcb structure
  853. * &param err: Lwip stack error code
  854. * @retval err
  855. */
  856. static err_t http_accept(void *arg, struct tcp_pcb *pcb, err_t err)
  857. {
  858. struct http_state *hs;
  859. (void)err;
  860. (void)arg;
  861. /* Allocate memory for the structure that holds the state of the connection */
  862. hs = mem_malloc(sizeof(struct http_state));
  863. if (hs == NULL) {
  864. return ERR_MEM;
  865. }
  866. /* Initialize the structure. */
  867. hs->file = NULL;
  868. hs->left = 0;
  869. /* Tell TCP that this is the structure we wish to be passed for our
  870. callbacks. */
  871. tcp_arg(pcb, hs);
  872. /* Tell TCP that we wish to be informed of incoming data by a call
  873. to the http_recv() function. */
  874. tcp_recv(pcb, http_recv);
  875. tcp_err(pcb, conn_err);
  876. tcp_poll(pcb, http_poll, 10);
  877. return ERR_OK;
  878. }
  879. /**
  880. * @brief intialize HTTP webserver
  881. * @param none
  882. * @retval none
  883. */
  884. void IAP_httpd_init(void)
  885. {
  886. struct tcp_pcb *pcb;
  887. /*create new pcb*/
  888. pcb = tcp_new();
  889. /* bind HTTP traffic to pcb */
  890. tcp_bind(pcb, IP_ADDR_ANY, 80);
  891. /* start listening on port 80 */
  892. pcb = tcp_listen(pcb);
  893. /* define callback function for TCP connection setup */
  894. tcp_accept(pcb, http_accept);
  895. /* Set block receive and prog timeout */
  896. timer_AddFunction(BLOCK_PROG_TIMEOUT, &ProgTimeout_Handler);
  897. timer_Stop(&ProgTimeout_Handler);
  898. }
  899. /**
  900. * @brief Opens a file defined in fsdata.c ROM filesystem
  901. * @param name : pointer to a file name
  902. * @param file : pointer to a fs_file structure
  903. * @retval 1 if success, 0 if fail
  904. */
  905. static int fs_open(char *name, struct fs_file *file)
  906. {
  907. struct fsdata_file_noconst *f;
  908. for (f = (struct fsdata_file_noconst *)FS_ROOT; f != NULL; f = (struct fsdata_file_noconst *)f->next) {
  909. if (!strcmp(name, f->name)) {
  910. file->data = f->data;
  911. file->len = f->len;
  912. return 1;
  913. }
  914. }
  915. return 0;
  916. }
  917. /**
  918. * @brief sends file from flash FS
  919. * @param filename: pointer to the file name to send
  920. * @param pnonmatch: pointer to the If-Non_Match value
  921. * @param pcb: pointer to a tcp_pcb struct
  922. * @param hs: pointer to a http_state struct
  923. * @param file: pointer to a fs_file struct
  924. * @retval
  925. */
  926. bool send_file(char *filename, char *pnonmatch, struct tcp_pcb *pcb, struct http_state *hs, struct fs_file *file)
  927. {
  928. int res = 0;
  929. char etag[MAX_ETAG_LEN];
  930. char *petag = NULL;
  931. res = fs_open(filename, file);
  932. if (res == 0) {
  933. return false;
  934. }
  935. /* Find Etag value */
  936. uint8_t etag_len = Parse_Header(file->data, file->len, Etag, 6, etag);
  937. if (etag_len < MAX_ETAG_LEN && etag_len > 0) {
  938. printf("Etag: %s\r\n", etag);
  939. petag = etag;
  940. }
  941. /* Compare Etag and If-Non-Match fields */
  942. if (pnonmatch && petag && (strcmp(pnonmatch, petag) == 0)) {
  943. /* Send 304 code */
  944. sprintf(sendBuf, HTTP_304_NOT_MODIFIED);
  945. printf(sendBuf);
  946. hs->file = sendBuf;
  947. hs->left = strlen(sendBuf);
  948. } else {
  949. /* Send file */
  950. printf("%s\r\n\r\n", filename);
  951. hs->file = file->data;
  952. hs->left = file->len;
  953. }
  954. send_data(pcb, hs);
  955. tcp_sent(pcb, http_sent);
  956. return true;
  957. }
  958. /**
  959. * @brief
  960. * @retval None
  961. */
  962. void send_index_page(struct tcp_pcb *pcb, struct http_state *hs, struct pbuf *p, bool upload)
  963. {
  964. char buf[32];
  965. /* Send cookie */
  966. strcpy(sendBuf, "HTTP/1.1 200 OK\r\nContent-Type:text/html\r\n");
  967. strcat(sendBuf, "Set-Cookie: upload=");
  968. sprintf(buf, "%d", (unsigned char)upload);
  969. strcat(sendBuf, buf);
  970. strcat(sendBuf, "\r\nSet-Cookie: wrtmr=");
  971. sprintf(buf, "%d", timer_GetCountdown(&ProgTimeout_Handler) / 1000);
  972. strcat(sendBuf, buf);
  973. strcat(sendBuf, "\r\nSet-Cookie: updtmr=");
  974. sprintf(buf, "%d", update_timeout);
  975. strcat(sendBuf, buf);
  976. strcat(sendBuf, "\r\nSet-Cookie: file1=");
  977. #ifdef SLAVEBRD_ENABLE
  978. strcat(sendBuf, DAUGHTER_FW_NAME);
  979. #else
  980. strcat(sendBuf, "NONE");
  981. #endif
  982. strcat(sendBuf, "\r\nSet-Cookie: file2=");
  983. strcat(sendBuf, MAIN_FW_NAME);
  984. strcat(sendBuf,
  985. "\r\n\r\n<!DOCTYPE html><html lang="
  986. "><head><meta \
  987. http-equiv=\"refresh\" content=\"0;url=/upload.html\"/></head></html>\r\n\r\n");
  988. htmlpage = LoginPage;
  989. hs->file = sendBuf;
  990. hs->left = strlen(sendBuf);
  991. pbuf_free(p);
  992. send_data(pcb, hs);
  993. tcp_sent(pcb, http_sent);
  994. }
  995. /**
  996. * @brief Extract the Content_Length data from HTML data
  997. * @param data : pointer on receive packet buffer
  998. * @param len : buffer length
  999. * @retval size : Content_length in numeric format
  1000. */
  1001. static uint32_t Parse_Content_Length(char *data, uint32_t len)
  1002. {
  1003. uint32_t i = 0, size = 0, S = 1;
  1004. int32_t j = 0;
  1005. char sizestring[6], *ptr;
  1006. uint32_t ContentLengthOffset = 0;
  1007. /* find Content-Length data in packet buffer */
  1008. for (i = 0; i < len; i++) {
  1009. if (strncmp((char *)(data + i), Content_Length, 16) == 0) {
  1010. ContentLengthOffset = i + 16;
  1011. break;
  1012. }
  1013. }
  1014. /* read Content-Length value */
  1015. if (ContentLengthOffset) {
  1016. i = 0;
  1017. ptr = (char *)(data + ContentLengthOffset);
  1018. while (*(ptr + i) != 0x0d && (i < len - ContentLengthOffset)) {
  1019. sizestring[i] = *(ptr + i);
  1020. i++;
  1021. ContentLengthOffset++;
  1022. }
  1023. if (i > 0) {
  1024. /* transform string data into numeric format */
  1025. for (j = i - 1; j >= 0; j--) {
  1026. size += (sizestring[j] - 0x30) * S;
  1027. S = S * 10;
  1028. }
  1029. }
  1030. }
  1031. return size;
  1032. }
  1033. /**
  1034. * @brief Extract the custom field data from HTML data
  1035. * @param data : pointer on receive packet buffer
  1036. * @param len : buffer length
  1037. * @param field : field name
  1038. * @param flen : field name length
  1039. * @retval value : pointer for field data
  1040. */
  1041. static uint32_t Parse_Header(char *data, uint32_t len, const char *field, uint32_t flen, char *value)
  1042. {
  1043. uint32_t i = 0, size = 0;
  1044. char *ptr;
  1045. uint32_t Offset = 0;
  1046. /* Find field name in data buffer */
  1047. for (i = 0; i < len; i++) {
  1048. if (strncmp((char *)(data + i), field, flen) == 0) {
  1049. Offset = i + flen;
  1050. break;
  1051. }
  1052. }
  1053. /* Copy Field value */
  1054. if (Offset) {
  1055. i = 0;
  1056. ptr = (char *)(data + Offset);
  1057. while (*(ptr + i) != 0x0d && (i < len - Offset)) {
  1058. value[i] = *(ptr + i);
  1059. i++;
  1060. }
  1061. value[i] = '\0';
  1062. size = i;
  1063. }
  1064. return size;
  1065. }
  1066. /**
  1067. * @brief
  1068. * @retval None
  1069. */
  1070. char *Parce_Boundary(const char *data, uint32_t len, char *dst, uint8_t dstlen)
  1071. {
  1072. char *ptr = NULL;
  1073. char *boundary = NULL;
  1074. uint8_t i = 0;
  1075. for (uint32_t j = 0; j < len; j++) {
  1076. if (strncmp((char *)(data + j), "boundary=", 9) == 0) {
  1077. boundary = (char *)data + j + 9;
  1078. break;
  1079. }
  1080. }
  1081. if (!boundary) return NULL;
  1082. *dst++ = '-';
  1083. *dst++ = '-';
  1084. ptr = boundary;
  1085. while ((*ptr != 0x0d) && (i < dstlen - 4)) {
  1086. *dst++ = *ptr++;
  1087. i++;
  1088. }
  1089. //*dst++ = '-';
  1090. //*dst++ = '-';
  1091. *dst = '\0';
  1092. if (i > 0)
  1093. return boundary;
  1094. else
  1095. return NULL;
  1096. }
  1097. static bool Parse_Filename(const char *data, uint32_t len, fw_type_t *fw_type, uint32_t *fw_size)
  1098. {
  1099. /* Parse packet for the filename field */
  1100. uint32_t FilenameOffset = 0;
  1101. char filename[FILENAME_MAX_LEN];
  1102. for (uint32_t i = 0; i < len; i++) {
  1103. if (strncmp((char *)(data + i), "filename=", 9) == 0) {
  1104. FilenameOffset = i + 10;
  1105. break;
  1106. }
  1107. }
  1108. if (FilenameOffset) {
  1109. uint32_t i = 0;
  1110. while ((*(data + FilenameOffset + i) != 0x22) &&
  1111. (i < FILENAME_MAX_LEN) &&
  1112. (FilenameOffset + i <= len)) {
  1113. filename[i] = *(data + FilenameOffset + i);
  1114. i++;
  1115. }
  1116. filename[i] = 0x0;
  1117. printf("File: %s\r\n", filename);
  1118. /* Decide which FW is uploaded */
  1119. if (strncmp(filename, MAIN_FW_NAME, 16) == 0) {
  1120. *fw_type = fw_main_board;
  1121. *fw_size = MAIN_FW_SIZE;
  1122. printf("Updating main board FW..\r\n");
  1123. }
  1124. #ifdef SLAVEBRD_ENABLE
  1125. else if (strncmp(filename, DAUGHTER_FW_NAME, 16) == 0) {
  1126. *fw_type = fw_daughter_board;
  1127. *fw_size = DB_FW_SIZE;
  1128. printf("Updating daughter FW..\r\n");
  1129. }
  1130. #endif
  1131. else {
  1132. *fw_type = fw_unknown;
  1133. }
  1134. return true;
  1135. }
  1136. return false;
  1137. }
  1138. /**
  1139. * @brief
  1140. * @retval None
  1141. */
  1142. bool GetFileName(char *inStr, char *fileName, uint8_t *fileNameLen)
  1143. {
  1144. char *beginValue = NULL;
  1145. char *endValue = NULL;
  1146. int len = 0;
  1147. char *strPtr = NULL;
  1148. strPtr = strstr(inStr, "GET");
  1149. if (strPtr == NULL) {
  1150. strPtr = strstr(inStr, "POST");
  1151. }
  1152. if (strPtr == NULL) {
  1153. *fileNameLen = 0;
  1154. return false;
  1155. } else {
  1156. beginValue = strpbrk(strPtr, "/");
  1157. endValue = strpbrk(beginValue, " ");
  1158. if (endValue == NULL) {
  1159. *fileNameLen = 0;
  1160. return false;
  1161. }
  1162. len = endValue - beginValue;
  1163. if (len < HTTP_FNAME_LEN) {
  1164. strncpy(fileName, beginValue, len);
  1165. *fileNameLen = len;
  1166. fileName[len] = '\0';
  1167. return true;
  1168. } else {
  1169. return false;
  1170. }
  1171. }
  1172. }
  1173. /**
  1174. * @brief writes received data in flash
  1175. * @param ptr: data pointer
  1176. * @param len: data length
  1177. * @retval none
  1178. */
  1179. void IAP_HTTP_writedata(char *ptr, uint32_t len)
  1180. {
  1181. uint32_t count, i = 0, j = 0;
  1182. /* check if any left bytes from previous packet transfer*/
  1183. /* if it is the case do a concat with new data to create a 32-bit word */
  1184. if (LeftBytes) {
  1185. while (LeftBytes <= 3) {
  1186. if (len > (j + 1)) {
  1187. LeftBytesTab[LeftBytes++] = *(ptr + j);
  1188. } else {
  1189. LeftBytesTab[LeftBytes++] = 0xFF;
  1190. }
  1191. j++;
  1192. }
  1193. FLASH_If_Write(&FlashWriteAddress, (u32 *)(LeftBytesTab), 1);
  1194. LeftBytes = 0;
  1195. /* update data pointer */
  1196. ptr = (char *)(ptr + j);
  1197. len = len - j;
  1198. }
  1199. /* write received bytes into flash */
  1200. count = len / 4;
  1201. /* check if remaining bytes < 4 */
  1202. i = len % 4;
  1203. if (i > 0) {
  1204. if (TotalReceived != size) {
  1205. /* store bytes in LeftBytesTab */
  1206. LeftBytes = 0;
  1207. for (; i > 0; i--)
  1208. LeftBytesTab[LeftBytes++] = *(char *)(ptr + len - i);
  1209. } else
  1210. count++;
  1211. }
  1212. FLASH_If_Write(&FlashWriteAddress, (u32 *)ptr, count);
  1213. }
  1214. uint32_t ReturnFlashWriteAddress(void)
  1215. {
  1216. return FlashWriteAddress;
  1217. }
  1218. #ifdef SLAVEBRD_ENABLE
  1219. /**
  1220. * @brief Connect stm32
  1221. */
  1222. bool IAP_HTTP_stmConnect(void)
  1223. {
  1224. bool ok = true;
  1225. stmRebootForFlash();
  1226. /* Connect */
  1227. ok = stmConnect();
  1228. if (!ok) {
  1229. printf("Error: device not detected.\n");
  1230. return false;
  1231. } else
  1232. printf("Device connected\n");
  1233. /* Get params */
  1234. ok = stmGetDevParams();
  1235. if (!ok) {
  1236. printf("Error: Device not supported.\n");
  1237. return false;
  1238. }
  1239. /* Erase */
  1240. printf("Erasing.. ");
  1241. ok = stmEraseFW();
  1242. if (ok)
  1243. printf("OK\n");
  1244. else {
  1245. printf("Erase error!\n");
  1246. return false;
  1247. }
  1248. stm32addr = DB_CPU_FLASH_FIRST_PAGE_ADDRESS;
  1249. return true;
  1250. }
  1251. /**
  1252. * @brief Prog received data to connected stm32 on uart
  1253. * @param ptr: data pointer
  1254. * @param len: data length
  1255. * @retval none
  1256. */
  1257. void IAP_HTTP_stmProg(char *ptr, uint32_t len)
  1258. {
  1259. uint32_t count, i, j = 0;
  1260. /* check if any left bytes from previous packet transfer*/
  1261. /* if it is the case do a concat with new data to create a 32-bit word */
  1262. if (LeftBytes) {
  1263. while (LeftBytes <= 3) {
  1264. if (len > (j + 1)) {
  1265. LeftBytesTab[LeftBytes++] = *(ptr + j);
  1266. } else {
  1267. LeftBytesTab[LeftBytes++] = 0xFF;
  1268. }
  1269. j++;
  1270. }
  1271. stmProg(&stm32addr, (uint8_t *)(LeftBytesTab), 4);
  1272. LeftBytes = 0;
  1273. /* update data pointer */
  1274. ptr = (char *)(ptr + j);
  1275. len = len - j;
  1276. }
  1277. /* write received bytes into flash */
  1278. count = len / 4;
  1279. /* check if remaining bytes < 4 */
  1280. i = len % 4;
  1281. if (i > 0) {
  1282. if (TotalReceived != size) {
  1283. /* store bytes in LeftBytesTab */
  1284. LeftBytes = 0;
  1285. for (; i > 0; i--) {
  1286. LeftBytesTab[LeftBytes++] = *(char *)(ptr + len - i);
  1287. }
  1288. } else {
  1289. count++;
  1290. }
  1291. }
  1292. stmProg(&stm32addr, (uint8_t *)ptr, count * 4);
  1293. }
  1294. #endif
  1295. void ProgTimeout_Handler()
  1296. {
  1297. /* If connection was broken during update,
  1298. * abort process, erase main board flash and restart IAP */
  1299. printf("Program timeout. Seems that connection was broken. Reboot...\r\n");
  1300. SET_FWINVALID_FLAG();
  1301. #ifdef LCD_ENABLE
  1302. LCD_PrintAligned(5, alignCENTER, "Таймаут обновления");
  1303. LCD_PrintAligned(7, alignCENTER, "Перезагрузка..");
  1304. #endif
  1305. switch (fw_type) {
  1306. case fw_main_board:
  1307. /* Erase flash */
  1308. FLASH_If_Erase(USER_FLASH_FIRST_PAGE_ADDRESS);
  1309. break;
  1310. #ifdef SLAVEBRD_ENABLE
  1311. case fw_daughter_board:
  1312. /*TODO Should we erase upper board here? */
  1313. break;
  1314. #endif
  1315. default:
  1316. break;
  1317. }
  1318. #ifdef SLAVEBRD_ENABLE
  1319. /* Reboot daughter board */
  1320. stmReboot();
  1321. #endif
  1322. /* Self reboot */
  1323. NVIC_SystemReset();
  1324. }
  1325. static void PeriodicHandle(uint8_t progress)
  1326. {
  1327. (void)progress;
  1328. #ifdef LCD_ENABLE
  1329. LCD_PrintBar(7, progress);
  1330. #endif
  1331. /* Handle periodic timers for LwIP */
  1332. LwIP_Periodic_Handle(0);
  1333. }
  1334. /* Get Cookie parameter value */
  1335. bool GetCookieValue(char *inStr, char *paramName, char *paramValue, uint8_t *paramLen)
  1336. {
  1337. char *beginValue = 0;
  1338. char *endValue = 0;
  1339. char *endValueTemp = 0;
  1340. int len = 0;
  1341. char *strPtr = strstr(inStr, paramName);
  1342. if (strPtr != NULL) {
  1343. beginValue = strpbrk(strPtr, "=");
  1344. endValue = strpbrk(strPtr, ";");
  1345. endValueTemp = strpbrk(strPtr, "\r");
  1346. if (endValueTemp != 0 && endValueTemp < endValue) {
  1347. endValue = endValueTemp;
  1348. }
  1349. if (endValue == 0) {
  1350. endValue = strpbrk(strPtr, "\n");
  1351. }
  1352. len = endValue - beginValue - 1;
  1353. *endValue = '0';
  1354. *beginValue = '0';
  1355. if (paramValue && paramLen) {
  1356. strncpy(paramValue, beginValue + 1, len);
  1357. *paramLen = len;
  1358. }
  1359. return true;
  1360. } else {
  1361. return false;
  1362. }
  1363. }
  1364. /* Check if Cookie is set or not */
  1365. bool CookieIsSet(char *inStr, uint16_t inLen, char *paramName)
  1366. {
  1367. static char CookieBuf[COOKIES_MAX_LEN];
  1368. if (!inStr) return false;
  1369. char *CookiePtr = lwip_strnstr(inStr, "Cookie:", inLen);
  1370. if (CookiePtr) {
  1371. char *paramPtr = lwip_strnstr(CookiePtr, paramName, inLen - (inStr - CookiePtr));
  1372. if (paramPtr) {
  1373. strncpy(CookieBuf, paramPtr, sizeof(CookieBuf));
  1374. if (GetCookieValue(CookieBuf, paramName, NULL, NULL)) {
  1375. return true;
  1376. }
  1377. }
  1378. }
  1379. return false;
  1380. }
  1381. /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/