static void roadmap_http_async_has_data_cb (RoadMapIO *io) { HttpAsyncContext *context = (HttpAsyncContext *)io->context; RoadMapHttpAsyncCallbacks *callbacks = context->callbacks; char buffer[ROADMAP_HTTP_MAX_CHUNK + 1]; int res; if (!context->is_parsing_headers) { int read_size = context->content_length - context->download_size_current; if (read_size > ROADMAP_HTTP_MAX_CHUNK) { read_size = ROADMAP_HTTP_MAX_CHUNK; } res = roadmap_io_read(io, buffer, read_size); if (res < 0) { roadmap_log(ROADMAP_ERROR, "roadmap_http_async_has_data_cb(): error receiving http data (%d/%d)", context->download_size_current, context->content_length); } } else { /* we're still parsing headers and may have left overs to append */ int leftover_size = strlen(context->header_buffer); res = roadmap_io_read(io, buffer + leftover_size, ROADMAP_HTTP_MAX_CHUNK - leftover_size); if (res > 0) { if (leftover_size) { memcpy(buffer, context->header_buffer, leftover_size); context->header_buffer[0] = '\0'; } res = roadmap_http_async_decode_header(context, buffer, res + leftover_size); if ( context->is_parsing_headers ) { if ( res == 0 ) { /* Need more header data - keep listening. * Other res values are handled further (actually can't be positive in this state ... */ if (strlen(buffer) && (strlen(buffer) < sizeof(context->header_buffer))) strcpy(context->header_buffer, buffer); return; } } else { /* we just finished parsing the headers - check size callback for the received content length */ if (!callbacks->size(context->cb_context, context->content_length)) { res = -1; } if ( res == 0 ) { /* Size is Ok and there is no download data to process after checking the headers - keep listening * Other res values will be handled further */ return; } } } else if (res < 0) { roadmap_log (ROADMAP_ERROR, "roadmap_http_async_has_data_cb(): error receiving http header (%d)", leftover_size); } else /* res == 0 */ { roadmap_log (ROADMAP_ERROR, "roadmap_http_async_has_data_cb(): error receiving http header. Read zero bytes. (%d)", leftover_size ); res = -1; } } if (res > 0) { context->download_size_current += res; callbacks->progress (context->cb_context, buffer, res); } if ((res <= 0) || (context->download_size_current >= context->content_length)) { roadmap_main_remove_input(io); roadmap_io_close(&context->io); if ( ( res >= 0 ) && ( context->content_length > 0 ) && ( context->download_size_current == context->content_length ) ) { callbacks->done(context->cb_context, context->last_modified_buffer); } else { roadmap_log (ROADMAP_WARNING, "Http download error. Res: %d. Content length: %d. Downloaded: %d", res, context->content_length, context->download_size_current ); if ( context->content_length > 0 && context->download_size_current > context->content_length ) { roadmap_log (ROADMAP_ERROR, "Too many bytes for http download (%d/%d)", context->download_size_current, context->content_length); } callbacks->error (context->cb_context, 0, "roadmap_http_async_has_data_cb() failed" ); } /* * Context deallocation. Be aware to NULL references in "error" and "done" callbacks */ free (context); } }
int roadmap_input (RoadMapInputContext *context) { int result; int received; int is_binary = context->is_binary; char *line_start; char *data_end; /* Receive more data if available. */ if (context->cursor < (int)sizeof(context->data) - 1) { received = roadmap_io_read (context->io, context->data + context->cursor, sizeof(context->data) - context->cursor - 1); if (received < 0) { /* We lost that connection. */ roadmap_log (ROADMAP_INFO, "lost %s", context->title); return -1; } else { context->cursor += received; } } if (!is_binary) context->data[context->cursor] = 0; /* Remove the leading end of line characters, if any. * We do the same in between lines (see end of loop). */ line_start = context->data; data_end = context->data + context->cursor; if (!is_binary) { while ((line_start < data_end) && (*line_start < ' ')) ++line_start; } /* process each complete line in this buffer. */ result = 0; while (line_start < data_end) { int cur_res; char *line_end = data_end; if (!is_binary) { char *new_line; char *carriage_return; /* Find the first end of line character coming after this line. */ new_line = strchr (line_start, '\n'); carriage_return = strchr (line_start, '\r'); if (new_line == NULL) { line_end = carriage_return; } else if (carriage_return == NULL) { line_end = new_line; } else if (new_line < carriage_return) { line_end = new_line; } else { line_end = carriage_return; } if (line_end == NULL) { /* This line is not complete: shift the remaining data * to the beginning of the buffer and then stop. */ if (line_start + strlen(line_start) != data_end) { roadmap_log (ROADMAP_WARNING, "GPS input has null characters."); roadmap_input_shift_to_next_line (context, line_start + strlen(line_start) + 1); line_start = context->data; data_end = context->data + context->cursor; while ((line_start < data_end) && (*line_start < ' ')) ++line_start; continue; } else { roadmap_input_shift_to_next_line (context, line_start); } return result; } /* Process this line. */ *line_end = 0; /* Separate this line from the next. */ } if (context->logger != NULL) { context->logger (line_start); } cur_res = context->decoder (context->user_context, context->decoder_context, line_start, line_end - line_start); if (is_binary) { line_start += cur_res; context->cursor -= cur_res; if (context->cursor) { memmove (context->data, line_start, context->cursor); } return 0; } result |= cur_res; /* Move to the next line. */ line_start = line_end + 1; while ((*line_start < ' ') && (line_start < data_end)) ++line_start; } context->cursor = 0; /* The buffer is now empty. */ return result; }