goahead content-length为0时的问题
gohead問題描述
UI將獲取掃描無線列表的接口formWifiApScan,由get換成了POST,此時無法獲取到數據,通過抓包分析,為webserver未正常及時返回數據,同時看到content-lengthy為0。
?
分析過程
今天晚上又與李權跟了一下這個問題,之前良明遇到過,了解了個大概,但還是沒完全弄清楚,借這個機會,一起深挖了一下。結果為:處理空懸,未調用注冊的回調處理,如果沒有超時結束,那么將一直處于此狀態,而非循環。
幾個問題:對于goahead協議狀態處理還是不深,socketGets 這個函數返回值沒有弄清楚。
websReadEvent關鍵狀態機函數
wp->state這個值是狀態處理的核心:
#define WEBS_BEGIN 0x1 /* Beginning state */
此狀態為新建一個wp時的初始狀態
#define WEBS_HEADER 0x2 /* Ready to read first line */
讀到第一行http協議時,進入到websParseFirst函數,然后轉為此狀態 ,此狀態會調用socketGets 來讀取全部的http頭部。
?
#define WEBS_POST 0x4 /* POST without content */
注釋不準,應該為POST without content-length,
此狀態不會明確調用 websUrlHandlerRequest處理,但會在讀取完上傳數據后再進行回調,因此需要瀏覽器先主動關閉發送數據端,然后觸發到eof,即沒有數據了,goahead會進行處理,然后把需要的數據再回傳瀏覽器, 估計這種用法較少。
#define WEBS_POST_CLEN 0x8 /* Ready to read content for POST */
很常用,有明確的長度
POST request with content specified by a content length
#define WEBS_PROCESSING 0x10 /* Processing request */
此狀態標識為處理中,websUrlHandlerRequest 中用到,但很少有請求分2次處理,因此較少用此狀態。
?
關鍵函數:socketGets
此函數為一行一行的解析http頭,>0時,表示解析成功, == 0 時表示頭部解析完成,
<0時,表示未完整解析 或 未讀到數據,這個函數也雜,狀態多,問題也多(正如之前 ITB A6 goahead那篇日志分析)。
一般http協議頭都有很多行,那么此函數會多次在狀態機中被調用 ,處理于WEBS_HEADER狀態。
當協議頭讀完時,也就是\r\nr\n時,會返回0,進一步調用處理
?
?
經過這里時,wp-state基本會切換 (處理cgi時不會切換,前面的WEBS_POST狀態)。
?
?
好了,本次的問題也就在這里了,經過上面這么長鋪墊,這就好理解了。
websParseRequest函數會把http協議會中的數據(除了第一行,見上面解析),一次性的處理,
對于content-length的處理如下,如果clen==0時,就不設置 WEBS_CLEN標識,但實際上,協議中未說 為0時代碼長度不確定,而是就是沒有數據,如注釋中描述,為了避免攻擊,則將clen=0,
但是關鍵在于,不設置 WEBS_CLEN狀態,則無法進入到 WEBS_POST_CLEN狀態機,于是產生了問題。
websGetInput 返回 0 Return 0 to get more data, 如注釋所述。 再次調用 websGetInput 函數時,由于本來就是沒有數據,又是非阻塞的,所以socketGets返回-1,同時web瀏覽器又沒有關閉發送連接,所以進不了eof,如下else就什么 也沒做 (HP_FIX還是這么有緣),最后return -1(不會調處理函數)
?
再回到websReadEvent函數 wp->state = WEBS_POST;這個狀態處理不了(前面提到它依賴于瀏覽器關閉發送連接,才能進入處理,設置eof)。
到了這里,只有等著瀏覽器超時了,今天用谷歌瀏覽器測,應該10秒左右會發送FIN(不確定是否為js中設置的),然后收到后 select觸發處理,進入到websUrlHandlerRequest 函數回調,最后在websDone中寫socket出錯...
數據無法發出去。 或發出去一截,應該是時間差,因為會收到對方的reset。
?
修改方案
建議同良明,在websParseRequest函數中,將conten-length的處理:對于<=0時,也設置
wp->flags |= WEBS_CLEN;
以保證狀態切換為WEBS_POST_CLEN
補充
對于如上Crash這種情況,又是一個坑,因為當conten-length為0時,再次進入狀態機時,text是為空的,在goahead 2.5上已經fix了這個問題,對text有判空處理,但是在AC18(從AC6上移植的,應該與2.5這個版本接近)卻沒有,
昨天晚上驗證時,UI對于POST請求,沒有跟?random,數據,因此query[0] 是‘\0’,不會進入到對text的處理, 所以驗證很happy,
但是今天UI應加了?random,結果query是有值的,而text沒有判空處理,所以大面積Http Crash,
雖然是一起坑,但是還是 goahead本身對協議處理弱...
總結
以上是生活随笔為你收集整理的goahead content-length为0时的问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: openssl 证书管理
- 下一篇: ecos无线驱动掉线问题解决方案分析