boost::tuple<boost::tribool, const char *> request_parser::parse( http_request &request, const char *begin, const char *end) { while (begin != end) { const char *line_end; if (*begin == '\n' && m_line.size() > 0 && m_line[m_line.size() - 1] == '\r') { line_end = begin; } else { line_end = find_crlf(begin, end); } m_line.append(begin, line_end); if (line_end == end) return boost::make_tuple(boost::tribool(boost::indeterminate), end); begin = line_end + 1; auto result = parse_line(request, m_line); if (result || !result) return boost::make_tuple(result, begin); m_line.resize(0); } return boost::make_tuple(boost::tribool(boost::indeterminate), end); }
/** * handle_receive: splits incomming lines from irc at \r\n and * sends them to process_incomming_data. Incomplete lines is stored and * merged in buffer over several recv's if necessary. * @param watcher * @param events_flags */ void Client::handle_receive(ev::io &watcher, int events_flags) { char recv_buffer[MAX_BUFFER_SIZE]; int size = recv(socketFd, &recv_buffer, MAX_BUFFER_SIZE, 0); if (size > 0) { if (buffer_size + size > MAX_BUFFER_SIZE) { std::cout << "Error: buffer overflow" << std::endl; buffer_size = 0; return; } memcpy(buffer + buffer_size, recv_buffer, size); size = buffer_size + size; buffer[size] = '\0'; int offset; while ((offset = find_crlf(buffer, size)) > 1) { buffer[offset - 2] = '\0'; std::string line = buffer; process_incomming_data(line); memmove(buffer, buffer + offset, size - offset); size = size - offset; } } buffer_size = size; }
/** Constroi e atribui o header HTTP ao 'buf' (respeitando 'bufsize'). * * A mensagem e construida de acordo com os parametros. * @todo Remover valores arbitrarios dos buffers. * @return O numero de caracteres efetivamente atribuidos a 'buf' ou * -1 em erro. */ int http_build_header(struct c_handler* h) { int n; //~ char last_modif[BUFFER_SIZE]; //LIDAR COM O TEMPO!!!!!! //strftime (timebuf) n = snprintf(h->answer_header, h->answer_header_size, "%s %d %s\r\n" "Server: %s\r\n" "Content-Type: %s\r\n" "Content-Length: %d\r\n" //~ "Last-Modified: %s" "Connection: close\r\n" "\r\n", PROTOCOL, h->filestatus, h->filestatusmsg, PACKAGE_NAME, h->filetype, h->filesize); if (!find_crlf(h->answer_header)) return -1; return n; }
static void parse_request_header(struct http_request *r, char *src, int max_len) { int i = 0; char *curr_line = NULL; int curr_line_len = 0; int content_length = 0; while(i < max_len) { curr_line = &src[i]; curr_line_len = find_crlf(curr_line, max_len-i); if(curr_line_len < 0) { i = -1; break; } if(curr_line_len == 0) { i += 2; break; } if(curr_line_len > 16 && (!strncmp(curr_line, "Content-Length: ", 16))) { int cls_len = curr_line_len-16; char *cls = alloca(cls_len+1); cls[cls_len] = '\0'; memcpy(cls, &curr_line[16], cls_len); content_length = atoi(cls); } i += curr_line_len+2; } if(i <= 0 || i > max_len) { r->length = -1; } else { r->header_length = i; r->length = i + content_length; } }
void serf_util_readline( const char **data, apr_size_t *len, int acceptable, int *found) { const char *start; const char *cr; const char *lf; int want_cr; int want_crlf; int want_lf; /* If _only_ CRLF is acceptable, then the scanning needs a loop to * skip false hits on CR characters. Use a separate function. */ if (acceptable == SERF_NEWLINE_CRLF) { find_crlf(data, len, found); return; } start = *data; cr = lf = NULL; want_cr = acceptable & SERF_NEWLINE_CR; want_crlf = acceptable & SERF_NEWLINE_CRLF; want_lf = acceptable & SERF_NEWLINE_LF; if (want_cr || want_crlf) { cr = memchr(start, '\r', *len); } if (want_lf) { lf = memchr(start, '\n', *len); } if (cr != NULL) { if (lf != NULL) { if (cr + 1 == lf) *found = want_crlf ? SERF_NEWLINE_CRLF : SERF_NEWLINE_CR; else if (want_cr && cr < lf) *found = SERF_NEWLINE_CR; else *found = SERF_NEWLINE_LF; } else if (cr == start + *len - 1) { /* the CR occurred in the last byte of the buffer. this could be * a CRLF split across the data boundary. * ### FIX THIS LOGIC? does caller need to detect? */ *found = want_crlf ? SERF_NEWLINE_CRLF_SPLIT : SERF_NEWLINE_CR; } else if (want_cr) *found = SERF_NEWLINE_CR; else /* want_crlf */ *found = SERF_NEWLINE_NONE; } else if (lf != NULL) *found = SERF_NEWLINE_LF; else *found = SERF_NEWLINE_NONE; switch (*found) { case SERF_NEWLINE_LF: *data = lf + 1; break; case SERF_NEWLINE_CR: case SERF_NEWLINE_CRLF: case SERF_NEWLINE_CRLF_SPLIT: *data = cr + 1 + (*found == SERF_NEWLINE_CRLF); break; case SERF_NEWLINE_NONE: *data += *len; break; default: /* Not reachable */ return; } *len -= *data - start; }
/* * Function: pop_getline * * Purpose: Get a line of text from the connection and return a * pointer to it. The carriage return and linefeed at the end of * the line are stripped, but periods at the beginnings of lines * are NOT dealt with in any special way. * * Arguments: * server The server from which to get the line of text. * * Returns: The number of characters in the line, which is returned in * LINE, not including the final null. A return value of 0 * indicates a blank line. A negative return value indicates an * error (in which case the contents of LINE are undefined. In * case of error, an error message is copied into pop_error. * * Notes: The line returned is overwritten with each call to pop_getline. * * Side effects: Closes the connection on error. * * THE RETURNED LINE MAY CONTAIN EMBEDDED NULLS! */ static int pop_getline (popserver server, char **line) { #define GETLINE_ERROR "Error reading from server: " int ret; int search_offset = 0; if (server->data) { char *cp = find_crlf (server->buffer + server->buffer_index, server->data); if (cp) { int found; int data_used; found = server->buffer_index; data_used = (cp + 2) - server->buffer - found; *cp = '\0'; /* terminate the string to be returned */ server->data -= data_used; server->buffer_index += data_used; if (pop_debug) /* Embedded nulls will truncate this output prematurely, but that's OK because it's just for debugging anyway. */ fprintf (stderr, "<<< %s\n", server->buffer + found); *line = server->buffer + found; return (data_used - 2); } else { memmove (server->buffer, server->buffer + server->buffer_index, server->data); /* Record the fact that we've searched the data already in the buffer for a CRLF, so that when we search below, we don't have to search the same data twice. There's a "- 1" here to account for the fact that the last character of the data we have may be the CR of a CRLF pair, of which we haven't read the second half yet, so we may have to search it again when we read more data. */ search_offset = server->data - 1; server->buffer_index = 0; } } else { server->buffer_index = 0; } while (1) { /* There's a "- 1" here to leave room for the null that we put at the end of the read data below. We put the null there so that find_crlf knows where to stop when we call it. */ if (server->data == server->buffer_size - 1) { server->buffer_size += GETLINE_INCR; server->buffer = (char *)realloc (server->buffer, server->buffer_size); if (! server->buffer) { strcpy (pop_error, "Out of memory in pop_getline"); pop_trash (server); return (-1); } } ret = RECV (server->file, server->buffer + server->data, server->buffer_size - server->data - 1, 0); if (ret < 0) { snprintf (pop_error, ERROR_MAX, "%s%s", GETLINE_ERROR, strerror (errno)); pop_trash (server); return (-1); } else if (ret == 0) { strcpy (pop_error, "Unexpected EOF from server in pop_getline"); pop_trash (server); return (-1); } else { char *cp; server->data += ret; server->buffer[server->data] = '\0'; cp = find_crlf (server->buffer + search_offset, server->data - search_offset); if (cp) { int data_used = (cp + 2) - server->buffer; *cp = '\0'; server->data -= data_used; server->buffer_index = data_used; if (pop_debug) fprintf (stderr, "<<< %s\n", server->buffer); *line = server->buffer; return (data_used - 2); } /* As above, the "- 1" here is to account for the fact that we may have read a CR without its accompanying LF. */ search_offset += ret - 1; } } /* NOTREACHED */ }
void ICACHE_FLASH_ATTR web_fini(const uint8 * fname) { struct buf_fini *p = (struct buf_fini *) os_zalloc(sizeof(struct buf_fini)); if(p == NULL) { #if DEBUGSOO > 1 os_printf("Error mem!\n"); #endif return; } TCP_SERV_CONN * ts_conn = &p->ts_conn; WEB_SRV_CONN * web_conn = &p->web_conn; web_conn->bffiles[0] = WEBFS_INVALID_HANDLE; web_conn->bffiles[1] = WEBFS_INVALID_HANDLE; web_conn->bffiles[2] = WEBFS_INVALID_HANDLE; web_conn->bffiles[3] = WEBFS_INVALID_HANDLE; ts_conn->linkd = (uint8 *)web_conn; ts_conn->sizeo = FINI_BUF_SIZE; ts_conn->pbufo = p->buf; rom_strcpy(ts_conn->pbufo, (void *)fname, MAX_FILE_NAME_SIZE); #if DEBUGSOO > 1 os_printf("Run ini file: %s\n", ts_conn->pbufo); #endif if(!web_inc_fopen(ts_conn, ts_conn->pbufo)) { #if DEBUGSOO > 1 os_printf("file not found!\n"); #endif return; } if(fatCache.flags & WEBFS_FLAG_ISZIPPED) { #if DEBUGSOO > 1 os_printf("\nError: file is ZIPped!\n"); #endif web_inc_fclose(web_conn); return; } user_uart_wait_tx_fifo_empty(1,1000); while(1) { web_conn->msgbufsize = ts_conn->sizeo; web_conn->msgbuflen = 0; uint8 *pstr = web_conn->msgbuf = ts_conn->pbufo; if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да #if DEBUGSOO > 2 os_printf("rcb "); #endif if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn); if(CheckSCB(SCB_RETRYCB)) break; // повторить ещё раз? да. } uint16 len = WEBFSGetArray(web_conn->webfile, pstr, FINI_BUF_SIZE); #if DEBUGSOO > 3 os_printf("ReadF[%u]=%u\n", web_conn->webfile, len); #endif if(len) { // есть байты в файле pstr[len] = '\0'; int sslen = 0; while(pstr[sslen] == '\n' || pstr[sslen] == '\r') sslen++; if(sslen == 0) { int nslen = find_crlf(pstr, len); if(nslen != 0) { pstr[nslen] = '\0'; // закрыть string calback-а while((nslen < len) && (pstr[nslen] == '\n' || pstr[nslen] == '\r')) nslen++; #if DEBUGSOO > 3 os_printf("String:%s\n", pstr); #endif if(!os_memcmp((void*)pstr, "inc:", 4)) { // "inc:file_name" if(!web_inc_fopen(ts_conn, &pstr[4])) { #if DEBUGSOO > 1 os_printf("file not found!"); #endif }; } else web_int_callback(ts_conn); }; sslen = nslen; }; // откат файла WEBFSStubs[web_conn->webfile].addr -= len; WEBFSStubs[web_conn->webfile].bytesRem += len; // передвинуть указатель в файле на считанные байты с учетом маркера, без добавки длины для передачи WEBFSStubs[web_conn->webfile].addr += sslen; WEBFSStubs[web_conn->webfile].bytesRem -= sslen; } else if(web_inc_fclose(web_conn)) { if(web_conn->web_disc_cb != NULL) web_conn->web_disc_cb(web_conn->web_disc_par); return; } } }