图涂途凃 发表于 2017-12-5 15:33:24

修改官方F107 HTTP IAP程序实现IE10+/Firefox/Chrome/Opera升级APP程序

本帖最后由 图涂途凃 于 2017-12-27 21:36 编辑

下面是之前出现的问题

最近在做 F107 的 IAP 程序,参考的官方“STM32F107 通过以太网实现在应用中编程 (IAP)”AN3226 应用笔记,程序也是官方的。
TFTP 升级没有问题,但是 HTTP 在使用时发现了问题:
      用 Mozilla Firefox 下载程序时,可以正常下载(下载文件170KB左右)。
      用 Google Chrome 下载程序时,出现 TCP ZeroWindow 等警告,导致下载程序不成功。
      用 Wireshark 抓包,左边为 Mozilla Firefox 抓包,右边为 Google Chrome 抓包


官方文档只提到了“注: 请注意,该软件已用下列 web 客户端测试:MSIE6, MSIE8 和 Mozilla Firefox 3.6。”
本人不太懂浏览器的差异,只发现了 Firefox 和 Chrome 发送的第一个包有差异
Firefox 发送的第一个包有 1460 bytes:


POST /upload.cgi HTTP/1.1
Host: 192.168.6.80
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:57.0) Gecko/20100101 Firefox/57.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://192.168.6.80/checklogin.cgi
Content-Type: multipart/form-data; boundary=---------------------------120212674612530
Content-Length: 175008
Connection: keep-alive
Upgrade-Insecure-Requests: 1


-----------------------------120212674612530
Content-Disposition: form-data; name="datafile"; filename="XXXX_XXXXX-XXXX_V1.0.1D1.img"
Content-Type: application/octet-stream




`hE0HF|P e$9}`GIEQJ}RUJ!q HGP HGHGIQrpGpG L M%`O      LO%pLOU%`b0LOU%`0pG0LOU%`0pGr      ( 8I      h`HG]HI
xp
HI
h`h 0      NbpG ^ d 5S T l @      *;;RpG+IpG"F
FFF FFx;IR FB)pG"R



Chrome 发送的第一个包有 593 bytes,第二个包才有 1460 bytes:


POST /upload.cgi HTTP/1.1
Host: 192.168.6.80
Connection: keep-alive
Content-Length: 175000
Cache-Control: max-age=0
Origin: http://192.168.6.80
Upgrade-Insecure-Requests: 1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqus0XTxRI7M3Lx3S
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://192.168.6.80/checklogin.cgi
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9


/* 上面是第一个包,下面是第二个包 */


------WebKitFormBoundaryD9iR35Ndh4OOGeNI
Content-Disposition: form-data; name="datafile"; filename="XXXX_XXXXX-XXXX_V1.0.1D1.img"
Content-Type: application/octet-stream




`hE0HF|P e$9}`GIEQJ}RUJ!q HGP HGHGIQrpGpG L M%`O      LO%pLOU%`b0LOU%`0pG0LOU%`0pGr      ( 8I      h`HG]HI
xp
HI
h`h 0      NbpG ^ d 5S T l @      *;;RpG+IpG"F
FFF FFx;IR FB)pG"R\\B+@0F F
R -5ARB *AD_#-P      OBR<@pPp@pI      IAqP@PaB"ApGA@C@"JaVV@B 9@P@@I @@*) C0E0B!@


A@}4BdI,0 pGO#BC@OAQBOAOoP(D0-OF F!A#EA@F!FF



后来在查找原因时,发现火狐浏览器升级也不成功!!!

分析抓到的包发现原来是浏览器正准备发数据时,设备回复了一个断开连接的 FIN 包!Google Chrome 也是同样的问题!


查到原因是:浏览器发了一个“GET /favicon.ico”的请求,这个请求是加载网页左上角的小图标的,这样就对“GET /”请求的程序产生影响,程序判断为接收异常从而断开连接。这个可以具体去看代码,不再详细指出。

enum htmlpage
{
LoginPage,
FileUploadPage,
UploadDonePage,
ResetDonePage,
} htmlpage;


上面这个枚举类型表明了页面加载顺序
主要是收到“GET /favicon.ico”的请求会打乱加载从而导致断开连接

/* process HTTP GET requests*/
    if (strncmp(data, "GET /", 5) == 0)
      {
      if ((strncmp(data, "GET /resetmcu.cgi", 17) ==0)&&(htmlpage == UploadDonePage))
      {
          htmlpage = ResetDonePage;
          fs_open("/reset.html", &file);
          hs->file = file.data;
          hs->left = file.len;
          pbuf_free(p);

          /* send reset.html page */
          send_data(pcb, hs);   
          resetpage = 1;

          /* Tell TCP that we wish be to informed of data that has been
          successfully sent by a call to the http_sent() function. */
          tcp_sent(pcb, http_sent);
      }   
      else
      {
          /*send the login page (which is the index page) */
          htmlpage = LoginPage;
          fs_open("/index.html", &file);
          hs->file = file.data;
          hs->left = file.len;
          pbuf_free(p);

          /* send index.html page */
          send_data(pcb, hs);

          /* Tell TCP that we wish be to informed of data that has been
          successfully sent by a call to the http_sent() function. */
          tcp_sent(pcb, http_sent);
      }
      }

      else
      {
      pbuf_free(p);
      close_conn(pcb, hs);   // 罪魁祸首在这里!!!
      }
程序要加上判断“GET /favicon.ico”请求的处理。具体怎么处理我就不拿出来献丑了。。。

结果测试,支持的浏览器:IE10+/Firefox/Chrome/Opera



图涂途凃 发表于 2017-12-5 16:13:43

有小伙伴在其他的浏览器上做过测试吗?

图涂途凃 发表于 2017-12-5 19:43:09

在IE10+和火狐测试没问题,在谷歌和 Opera 上不行...

图涂途凃 发表于 2017-12-7 10:43:37

都没人回复,失望。。。

还是自己顶吧:
修改了官方例程一个地方
/* process POST request for file upload and incoming data packets after POST request*/
      else if (((strncmp(data, "POST /upload.cgi",16)==0)||(DataFlag >=1))&&(htmlpage == FileUploadPage))
      {
      DataOffset =0;

      /* POST Packet received */
      if (DataFlag ==0)
      {
          BrowserFlag=0;
          TotalReceived =0;
                                       
          /* parse packet for Content-length field */
          size = Parse_Content_Length(data, p->tot_len);
          /* parse packet for the octet-stream field */
          for (i=0;i<len;i++)
          {
             if (strncmp ((char*)(data+i), octet_stream, 13)==0)
             {
               DataOffset = i+16;
               break;
             }
          }
          /* case of MSIE8 : we do not receive data in the POST packet*/
          if (DataOffset==0)
          {
             DataFlag++;
             BrowserFlag = 1;
             pbuf_free(p);
             return ERR_OK;

          }
          /* case of Mozilla Firefox v3.6 : we receive data in the POST packet*/
          else
          {
            TotalReceived = len - (ContentLengthOffset + 4) - 0x5D;
          }
      }


这里官方区分了 IE 和 Firefox,经过测试,支持的浏览器:IE10+/Firefox/Chrome/Opera,Safari测试没通过。。。


希望能对以后遇到相同问题的人有帮助

shanji 发表于 2017-12-8 11:56:07

感谢分享

hpdell 发表于 2017-12-9 12:57:11

图涂途凃 发表于 2017-12-7 10:43
都没人回复,失望。。。

还是自己顶吧:


我的也还没有搞定啦,我也是移植官方的历程 lwip-iap 的

maxtch 发表于 2017-12-9 18:32:22

本帖最后由 maxtch 于 2017-12-9 18:38 编辑

其实你要把所有包按照序号全部接在一起再考虑上层协议。TCP 到了电脑端 OS 会被视作没有“包”这个概念的连续数据流,不同的浏览器不同的操作系统每次发出的数据量(TCP 窗口大小)不一样,包大小也会不一样。建议你什么时候看一下电脑端 TCP/IP 编程的过程,这样对设备端编程也会有更好地理解。至于测试,您可能必须要考虑所有主流平台和主流浏览器(Windows+IE、Windows+Edge、Chrome、Firefox、macOS+Safari、iOS+Safari)甚至要考虑 wget 和 curl。
顺带一提,如果内存允许的话建议容许接受最大 9000 字节的数据包。这是很多网络系统中 Jumbo Frame 的尺寸。Jumbo Frame 是一种相当常见的提升网络性能的方法。

hpdell 发表于 2017-12-12 12:14:45

maxtch 发表于 2017-12-9 18:32
其实你要把所有包按照序号全部接在一起再考虑上层协议。TCP 到了电脑端 OS 会被视作没有“包”这个概念的连 ...

我现在使用 官网提供的 lwip_iap 历程,目前可以使用 http 进行固件升级了,但是升级后不能够跳转到用户程序运行,目前比较纠结啊,

单独运行 用户程序是没有问题的

图涂途凃 发表于 2017-12-12 20:33:47

hpdell 发表于 2017-12-12 12:14
我现在使用 官网提供的 lwip_iap 历程,目前可以使用 http 进行固件升级了,但是升级后不能够跳转到用户 ...

更新完成后单步运行看看程序跑到那里了,官方程序是可以的

hpdell 发表于 2017-12-12 20:49:12

图涂途凃 发表于 2017-12-12 20:33
更新完成后单步运行看看程序跑到那里了,官方程序是可以的

http://bbs.armfly.com/attachment/Fid_42/42_1083_edeec4bd47a41fe.png

你好,现在最新进展情况,貌似执行了第 52 行的代码后就出现 什么The stack pointer for stack 'CSTACK' (currently 0x20022CD8) is outside the stack range (0x200003B0 to 0x200043B0)

这个是怎么回事啊 ???????????

是不是我 的 iap 程序分的太大了啊 ? 我目前分配的是 512KB。

我的app 的程序是从 0x0808 0000 开始的


maxtch 发表于 2017-12-12 21:16:48

hpdell 发表于 2017-12-12 12:14
我现在使用 官网提供的 lwip_iap 历程,目前可以使用 http 进行固件升级了,但是升级后不能够跳转到用户 ...

升级完成后直接复位?

hpdell 发表于 2017-12-12 22:04:59

maxtch 发表于 2017-12-12 21:16
升级完成后直接复位?

你好,最新 发现的问题,目前还没有解决,帮忙看看是怎么个原因造成的啊 ?

单片机使用的 是 stm32F777BIT6    2MByte-flalsh

https://www.stmcu.org.cn/module/forum/forum.php?mod=viewthread&tid=614170&extra=page%3D&page=2

在 15楼有具体描述

图涂途凃 发表于 2017-12-19 08:59:05

hpdell 发表于 2017-12-12 20:49
你好,现在最新进展情况,貌似执行了第 52 行的代码后就出现 什么The stack pointer for stack 'CSTA ...

你好,问题解决了吗?
我感觉是 APP 程序的中断向量表起始地址没有设定好,APP 程序 在 keil 上设定ROM地址,程序上也要设定中断向量表起始地址都为0x08080000.

hpdell 发表于 2017-12-19 16:27:40

本帖最后由 hpdell 于 2017-12-19 16:29 编辑

图涂途凃 发表于 2017-12-19 08:59
你好,问题解决了吗?
我感觉是 APP 程序的中断向量表起始地址没有设定好,APP 程序 在 keil 上设定ROM地 ...
你好,我的解决了
我的终于搞定了,

你可以看看 http://www.amobbs.com/forum.php ... ;extra=#pid10015507

这个帖子里面也回复了,
在 7 楼



页: [1]
查看完整版本: 修改官方F107 HTTP IAP程序实现IE10+/Firefox/Chrome/Opera升级APP程序