static void ICACHE_FLASH_ATTR tcp_receive_cb(void *arg, char *pData, unsigned short len) { HttpdConnData c; char bfr[100] = { 0 }; struct espconn *conn = (struct espconn*) arg; httpdParseHeader(pData, &c); TESTP("URL=%s\n", c.url); if (httpSetupMode && os_strncmp(c.url, "/setup", 5) == 0) { if (httpdFindArg(c.getArgs, "Action", bfr, sizeof(bfr)) >= 0) { TESTP("Action=%s\n", bfr); if (os_strncmp(bfr, "Update", 6) == 0) { if (httpdFindArg(c.getArgs, "MQTThost", bfr, sizeof(bfr)) >= 0) { TESTP("MQTThost=%s\n", bfr); if (7 < os_strlen(bfr) && os_strlen(bfr) < sizeof(sysCfg.mqtt_host)) { os_strcpy(sysCfg.mqtt_host, bfr); } } if (httpdFindArg(c.getArgs, "MQTTport", bfr, sizeof(bfr)) >= 0) { TESTP("MQTTport=%s\n", bfr); if (1 <= os_strlen(bfr) && os_strlen(bfr) <= 4) { sysCfg.mqtt_port = atoi(bfr); } } if (httpdFindArg(c.getArgs, "MQTTuser", bfr, sizeof(bfr)) >= 0) { TESTP("MQTTuser=%s\n", bfr); if (0 <= os_strlen(bfr) && os_strlen(bfr) < sizeof(sysCfg.mqtt_user)) { os_strcpy(sysCfg.mqtt_user, bfr); } } if (httpdFindArg(c.getArgs, "MQTTpass", bfr, sizeof(bfr)) >= 0) { TESTP("MQTTpass=%s\n", bfr); if (0 <= os_strlen(bfr) && os_strlen(bfr) < sizeof(sysCfg.mqtt_pass)) { os_strcpy(sysCfg.mqtt_pass, bfr); } } if (httpdFindArg(c.getArgs, "DevPrefix", bfr, sizeof(bfr)) >= 0) { TESTP("DevPrefix=%s\n", bfr); if (2 <= os_strlen(bfr) && os_strlen(bfr) < sizeof(sysCfg.deviceID_prefix)) { os_strcpy(sysCfg.deviceID_prefix, bfr); os_sprintf(sysCfg.device_id, "%s%lx", sysCfg.deviceID_prefix, system_get_chip_id()); } } if (httpdFindArg(c.getArgs, "reboot", bfr, sizeof(bfr)) >= 0) { TESTP("reboot=%s\n", bfr); if (strcmp(bfr, "yes") == 0) { reboot = true; } } CFG_dirty(); } } replyOK(conn); } else { replyFail(conn); } }
//Callback called when there's data available on a socket. static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short len) { debugConn(arg, "httpdRecvCb"); struct espconn* pCon = (struct espconn *)arg; HttpdConnData *conn = (HttpdConnData *)pCon->reverse; if (conn == NULL) return; // aborted connection char sendBuff[MAX_SENDBUFF_LEN]; httpdSetOutputBuffer(conn, sendBuff, sizeof(sendBuff)); //This is slightly evil/dirty: we abuse conn->post->len as a state variable for where in the http communications we are: //<0 (-1): Post len unknown because we're still receiving headers //==0: No post data //>0: Need to receive post data //ToDo: See if we can use something more elegant for this. for (int x = 0; x<len; x++) { if (conn->post->len<0) { //This byte is a header byte. if (conn->priv->headPos != MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++] = data[x]; conn->priv->head[conn->priv->headPos] = 0; //Scan for /r/n/r/n. Receiving this indicate the headers end. if (data[x] == '\n' && (char *)os_strstr(conn->priv->head, "\r\n\r\n") != NULL) { //Indicate we're done with the headers. conn->post->len = 0; conn->post->multipartBoundary = NULL; //Reset url data conn->url = NULL; //Iterate over all received headers and parse them. char *p = conn->priv->head; while (p<(&conn->priv->head[conn->priv->headPos - 4])) { char *e = (char *)os_strstr(p, "\r\n"); //Find end of header line if (e == NULL) break; //Shouldn't happen. e[0] = 0; //Zero-terminate header httpdParseHeader(p, conn); //and parse it. p = e + 2; //Skip /r/n (now /0/n) } //If we don't need to receive post data, we can send the response now. if (conn->post->len == 0) { httpdProcessRequest(conn); } } } else if (conn->post->len != 0) { //This byte is a POST byte. conn->post->buff[conn->post->buffLen++] = data[x]; conn->post->received++; if (conn->post->buffLen >= conn->post->buffSize || conn->post->received == conn->post->len) { //Received a chunk of post data conn->post->buff[conn->post->buffLen] = 0; //zero-terminate, in case the cgi handler knows it can use strings //Send the response. httpdProcessRequest(conn); conn->post->buffLen = 0; } } } }
//Callback called when there's data available on a socket. static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short len) { int x; char *p, *e; char sendBuff[MAX_SENDBUFF_LEN]; HttpdConnData *conn=httpdFindConnData(arg); if (conn==NULL) return; conn->priv->sendBuff=sendBuff; conn->priv->sendBuffLen=0; for (x=0; x<len; x++) { if (conn->postLen<0) { //This byte is a header byte. if (conn->priv->headPos!=MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++]=data[x]; conn->priv->head[conn->priv->headPos]=0; //Scan for /r/n/r/n if (data[x]=='\n' && (char *)os_strstr(conn->priv->head, "\r\n\r\n")!=NULL) { //Indicate we're done with the headers. conn->postLen=0; //Reset url data conn->url=NULL; //Find end of next header line p=conn->priv->head; while(p<(&conn->priv->head[conn->priv->headPos-4])) { e=(char *)os_strstr(p, "\r\n"); if (e==NULL) break; e[0]=0; httpdParseHeader(p, conn); p=e+2; } //If we don't need to receive post data, we can send the response now. if (conn->postLen==0) { httpdSendResp(conn); } } } else if (conn->priv->postPos!=-1 && conn->postLen!=0 && conn->priv->postPos <= conn->postLen) { //This byte is a POST byte. conn->postBuff[conn->priv->postPos++]=data[x]; if (conn->priv->postPos>=conn->postLen) { //Received post stuff. conn->postBuff[conn->priv->postPos]=0; //zero-terminate conn->priv->postPos=-1; os_printf("Post data: %s\n", conn->postBuff); //Send the response. httpdSendResp(conn); break; } } } xmitSendBuff(conn); }
//Callback called when there's data available on a socket. static void ICACHE_FLASH_ATTR httpdRecvCb(void *arg, char *data, unsigned short len) { int x; char *p, *e; char sendBuff[MAX_SENDBUFF_LEN]; HttpdConnData *conn=httpdFindConnData(arg); if (conn==NULL) return; conn->priv->sendBuff=sendBuff; conn->priv->sendBuffLen=0; for (x=0; x<len; x++) { if (conn->post->len<0) { //This byte is a header byte. if (conn->priv->headPos!=MAX_HEAD_LEN) conn->priv->head[conn->priv->headPos++]=data[x]; conn->priv->head[conn->priv->headPos]=0; //Scan for /r/n/r/n if (data[x]=='\n' && (char *)os_strstr(conn->priv->head, "\r\n\r\n")!=NULL) { //Indicate we're done with the headers. conn->post->len=0; //Reset url data conn->url=NULL; //Find end of next header line p=conn->priv->head; while(p<(&conn->priv->head[conn->priv->headPos-4])) { e=(char *)os_strstr(p, "\r\n"); if (e==NULL) break; e[0]=0; httpdParseHeader(p, conn); p=e+2; } //If we don't need to receive post data, we can send the response now. if (conn->post->len==0) { httpdProcessRequest(conn); } } } else if (conn->post->len!=0) { //This byte is a POST byte. conn->post->buff[conn->post->buffLen++]=data[x]; conn->post->received++; if (conn->post->buffLen >= conn->post->buffSize || conn->post->received == conn->post->len) { //Received a chunk of post data conn->post->buff[conn->post->buffLen]=0; //zero-terminate, in case the cgi handler knows it can use strings //Send the response. httpdProcessRequest(conn); conn->post->buffLen = 0; } } } }
void GSwifi::httpdRecvData (int cid, char c) { switch (_httpd[cid].mode) { case HTTPDMODE_REQUEST: #ifndef CFG_ENABLE_RTOS if (_con[cid].buf == NULL) { _con[cid].buf = new CircBuffer<char>(CFG_DATA_SIZE); } #endif _httpd[cid].buf = _con[cid].buf; if (_httpd[cid].buf != NULL) { _httpd[cid].buf->flush(); } _httpd[cid].keepalive = 0; if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { if (_httpd[cid].buf != NULL) { _httpd[cid].buf->queue(c); } _httpd[cid].mode = HTTPDMODE_REQUEST_STR; } break; case HTTPDMODE_REQUEST_STR: switch (c) { case 0: case 0x0d: // CR break; case 0x0a: // LF if (httpdParseRequest(cid)) { _httpd[cid].mode = HTTPDMODE_REQUEST_STR; } else { _httpd[cid].mode = HTTPDMODE_HEADER; } _httpd[cid].enter = 0; break; default: if (_httpd[cid].buf != NULL) { _httpd[cid].buf->queue(c); } break; } break; case HTTPDMODE_HEADER: switch (c) { case 0: case 0x0d: // CR break; case 0x0a: // LF // if (_httpd[cid].buf != NULL && _httpd[cid].buf->available() == 0) { // if ((_httpd[cid].enter == 0x0d && c == 0x0a) || (_httpd[cid].enter == 0x0a && c == 0x0a)) { if (_httpd[cid].enter == 0x0a && c == 0x0a) { if (_httpd[cid].buf != NULL) { _httpd[cid].buf->flush(); } #ifdef CFG_ENABLE_WEBSOCKET if (_httpd[cid].websocket) { INFO("MODE_WEBSOCKET_BEGIN"); _httpd[cid].mode = HTTPDMODE_WEBSOCKET_BEGIN; } else #endif if (_httpd[cid].length) { INFO("MODE_BODY"); _httpd[cid].mode = HTTPDMODE_BODY; } else { INFO("MODE_ENTER"); _httpd[cid].mode = HTTPDMODE_ENTER; _con[cid].received = true; } } // break; // } _httpd[cid].enter = c; httpdParseHeader(cid); break; default: if (_httpd[cid].buf != NULL) { _httpd[cid].buf->queue(c); } _httpd[cid].enter = 0; break; } break; case HTTPDMODE_BODY: if (_httpd[cid].buf != NULL) { _httpd[cid].buf->queue(c); if (_httpd[cid].buf->available() >= _httpd[cid].length) { _httpd[cid].mode = HTTPDMODE_ENTER; _con[cid].received = true; } } break; #ifdef CFG_ENABLE_WEBSOCKET case HTTPDMODE_WEBSOCKET: case HTTPDMODE_WEBSOCKET_MASK: case HTTPDMODE_WEBSOCKET_BODY: wsRecvData(cid, c); break; #endif } }
/************************************************ * name: httpdRecvCb * parameters: ptArgument - connection data * pbData - data available * cbDataLength - data length * return value: none * purpose: callback when data available on a socket ************************************************/ static void ICACHE_FLASH_ATTR httpdRecvCb(void * ptArgument, char * pbData, unsigned short cbDataLength) { /* initialization */ int iIndex = 0; char * pbTmpHeader = NULL; char * pbEndOfHeader = NULL; char pbSendBuffer[HTTPD_MAX_SEND_BUFFER_LENGTH] = { 0 }; HttpdConnection * ptConnection = NULL; ptConnection = httpdFindConnData(ptArgument); if (NULL == ptConnection) { return; } ptConnection->ptPrivate->pbSendBuffer = pbSendBuffer; ptConnection->ptPrivate->cbSendBufferLength = 0; for (iIndex = 0; iIndex < cbDataLength; iIndex++) { if (0 > ptConnection->ptPost->cbPostLength) { /* header byte */ if (HTTPD_MAX_HEADER_LENGTH != ptConnection->ptPrivate->cbHeaderLength) { ptConnection->ptPrivate->pbHeader[ptConnection->ptPrivate->cbHeaderLength++]=pbData[iIndex]; } ptConnection->ptPrivate->pbHeader[ptConnection->ptPrivate->cbHeaderLength] = 0; /* scan for /r/n/r/n */ if (((*NEWLINE_SYMBOL_STRING) == pbData[iIndex]) && (NULL != (char *)os_strstr(ptConnection->ptPrivate->pbHeader, "\r\n\r\n"))) { /* indicate we're done with the headers */ ptConnection->ptPost->cbPostLength = 0; /* reset url data */ ptConnection->pszUrl = NULL; /* find end of next header line */ pbTmpHeader = ptConnection->ptPrivate->pbHeader; while (pbTmpHeader < (&ptConnection->ptPrivate->pbHeader[ptConnection->ptPrivate->cbHeaderLength-4])) { pbEndOfHeader = (char *)os_strstr(pbTmpHeader, "\r\n"); if (NULL == pbEndOfHeader) { break; } pbEndOfHeader[0] = 0; httpdParseHeader(pbTmpHeader, ptConnection); pbTmpHeader = pbEndOfHeader + 2; } /* if receive post data unncessary send the response */ if (0 == ptConnection->ptPost->cbPostLength) { httpdProcessRequest(ptConnection); } } } else if (0 != ptConnection->ptPost->cbPostLength) { /* this is a POST byte */ ptConnection->ptPost->pbBuffer[ptConnection->ptPost->cbBufferLength++] = pbData[iIndex]; ptConnection->ptPost->cbReceived++; if ((ptConnection->ptPost->cbBufferLength >= ptConnection->ptPost->cbMaxBufferSize) || (ptConnection->ptPost->cbReceived == ptConnection->ptPost->cbPostLength)) { /* received a chunk of post data */ /* zero-terminate, in case the cgi handler knows it can use strings */ ptConnection->ptPost->pbBuffer[ptConnection->ptPost->cbBufferLength] = 0; /* send the response */ httpdProcessRequest(ptConnection); ptConnection->ptPost->cbBufferLength = 0; } } } }