//Callback called when the data on a socket has been successfully sent. static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) { debugConn(arg, "httpdSentCb"); 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)); if (conn->cgi == NULL) { //Marked for destruction? //os_printf("Closing 0x%p/0x%p->0x%p\n", arg, conn->conn, conn); espconn_disconnect(conn->conn); // we will get a disconnect callback return; //No need to call httpdFlush. } int r = conn->cgi(conn); //Execute cgi fn. if (r == HTTPD_CGI_DONE) { conn->cgi = NULL; //mark for destruction. } if (r == HTTPD_CGI_NOTFOUND || r == HTTPD_CGI_AUTHENTICATED) { DBG("%sERROR! Bad CGI code %d\n", connStr, r); conn->cgi = NULL; //mark for destruction. } httpdFlush(conn); }
static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { debugConn(arg, "httpdDisconCb"); struct espconn* pCon = (struct espconn *)arg; HttpdConnData *conn = (HttpdConnData *)pCon->reverse; if (conn == NULL) return; // aborted connection httpdRetireConn(conn); }
static void ICACHE_FLASH_ATTR httpdDisconCb(void *arg) { debugConn(arg, "httpdDisconCb"); HttpdConnData *conn = httpdFindConnData(arg); if (conn == NULL) return; if (conn->cgi != NULL) conn->cgi(conn); // free cgi data httpdRetireConn(conn); }
//Callback called when the data on a socket has been successfully sent. static void ICACHE_FLASH_ATTR httpdSentCb(void *arg) { debugConn(arg, "httpdSentCb"); int r; HttpdConnData *conn=httpdFindConnData(arg); char sendBuff[MAX_SENDBUFF_LEN]; if (conn==NULL) return; conn->priv->sendBuff=sendBuff; conn->priv->sendBuffLen=0; if (conn->cgi==NULL) { //Marked for destruction? //os_printf("Closing 0x%p/0x%p->0x%p\n", arg, conn->conn, conn); espconn_disconnect(conn->conn); //httpdRetireConn(conn); // can't call this, we will get a diconnect callback! return; //No need to call xmitSendBuff. } r=conn->cgi(conn); //Execute cgi fn. if (r==HTTPD_CGI_DONE) { conn->cgi=NULL; //mark for destruction. } if (r==HTTPD_CGI_NOTFOUND || r==HTTPD_CGI_AUTHENTICATED) { os_printf("%s ERROR! CGI fn returns code %d after sending data! Bad CGI!\n", connStr, r); conn->cgi=NULL; //mark for destruction. } xmitSendBuff(conn); }
// Callback indicating a failure in the connection. "Recon" is probably intended in the sense // of "you need to reconnect". Sigh... Note that there is no DisconCb after ReconCb static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { debugConn(arg, "httpdReconCb"); struct espconn* pCon = (struct espconn *)arg; HttpdConnData *conn = (HttpdConnData *)pCon->reverse; if (conn == NULL) return; // aborted connection DBG("%s***** reset, err=%d\n", connStr, err); httpdRetireConn(conn); }
// Callback indicating a failure in the connection. "Recon" is probably intended in the sense // of "you need to reconnect". Sigh... static void ICACHE_FLASH_ATTR httpdReconCb(void *arg, sint8 err) { debugConn(arg, "httpdReconCb"); HttpdConnData *conn = httpdFindConnData(arg); os_printf("%s reset, err=%d\n", connStr, err); if (conn == NULL) return; conn->conn = NULL; // don't tr to send anything, the SDK crashes... if (conn->cgi != NULL) conn->cgi(conn); // free cgi data httpdRetireConn(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; } } } }
static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { debugConn(arg, "httpdConnectCb"); struct espconn *conn = arg; // Find empty conndata in pool int i; for (i = 0; i<MAX_CONN; i++) if (connData[i].conn == NULL) break; //DBG("Con req, conn=%p, pool slot %d\n", conn, i); if (i == MAX_CONN) { os_printf("%sHTTP: conn pool overflow!\n", connStr); espconn_disconnect(conn); return; } #if 0 int num = 0; for (int j = 0; j<MAX_CONN; j++) if (connData[j].conn != NULL) num++; DBG("%sConnect (%d open)\n", connStr, num + 1); #endif connData[i].priv = &connPrivData[i]; connData[i].conn = conn; conn->reverse = connData+i; connData[i].priv->headPos = 0; esp_tcp *tcp = conn->proto.tcp; os_sprintf(connData[i].priv->from, "%d.%d.%d.%d:%d", tcp->remote_ip[0], tcp->remote_ip[1], tcp->remote_ip[2], tcp->remote_ip[3], tcp->remote_port); connData[i].post = &connPostData[i]; connData[i].post->buff = NULL; connData[i].post->buffLen = 0; connData[i].post->received = 0; connData[i].post->len = -1; connData[i].startTime = system_get_time(); espconn_regist_recvcb(conn, httpdRecvCb); espconn_regist_reconcb(conn, httpdReconCb); espconn_regist_disconcb(conn, httpdDisconCb); espconn_regist_sentcb(conn, httpdSentCb); espconn_set_opt(conn, ESPCONN_REUSEADDR | ESPCONN_NODELAY); }
static void ICACHE_FLASH_ATTR httpdConnectCb(void *arg) { debugConn(arg, "httpdConnectCb"); struct espconn *conn=arg; int i; //Find empty conndata in pool for (i=0; i<MAX_CONN; i++) if (connData[i].conn==NULL) break; //os_printf("Con req, conn=%p, pool slot %d\n", conn, i); if (i==MAX_CONN) { os_printf("%s Aiee, conn pool overflow!\n", connStr); espconn_disconnect(conn); return; } int num = 0; for (int j=0; j<MAX_CONN; j++) if (connData[j].conn != NULL) num++; os_printf("%s Connect (%d open)\n", connStr, num+1); connData[i].priv=&connPrivData[i]; connData[i].conn=conn; connData[i].remote_port = conn->proto.tcp->remote_port; os_memcpy(connData[i].remote_ip, conn->proto.tcp->remote_ip, 4); connData[i].priv->headPos=0; connData[i].post=&connPostData[i]; connData[i].post->buff=NULL; connData[i].post->buffLen=0; connData[i].post->received=0; connData[i].post->len=-1; connData[i].startTime = system_get_time(); espconn_regist_recvcb(conn, httpdRecvCb); espconn_regist_reconcb(conn, httpdReconCb); espconn_regist_disconcb(conn, httpdDisconCb); espconn_regist_sentcb(conn, httpdSentCb); espconn_set_opt(conn, ESPCONN_REUSEADDR|ESPCONN_NODELAY); }