int close_vorbis_stream(void * datasource) { http_session_t * session = (http_session_t *) datasource; session->fdec->is_stream = 0; httpc_close(session); httpc_del(session); return 0; }
/** http client tcp err callback */ static void httpc_tcp_err(void *arg, err_t err) { httpc_state_t* req = (httpc_state_t*)arg; if (req != NULL) { /* pcb has already been deallocated */ req->pcb = NULL; httpc_close(req, HTTPC_RESULT_ERR_CLOSED, 0, err); } }
void pause_vorbis_stream(decoder_t * dec) { vorbis_pdata_t * pd = (vorbis_pdata_t *)dec->pdata; char flush_dest; httpc_close(pd->session); if (pd->session->type == HTTPC_SESSION_STREAM) { /* empty vorbis decoder ringbuffer */ while (rb_read_space(pd->rb)) rb_read(pd->rb, &flush_dest, sizeof(char)); } }
/** http client tcp poll callback */ static err_t httpc_tcp_poll(void *arg, struct altcp_pcb *pcb) { /* implement timeout */ httpc_state_t* req = (httpc_state_t*)arg; LWIP_UNUSED_ARG(pcb); if (req != NULL) { if (req->timeout_ticks) { req->timeout_ticks--; } if (!req->timeout_ticks) { return httpc_close(req, HTTPC_RESULT_ERR_TIMEOUT, 0, ERR_OK); } } return ERR_OK; }
/** http client tcp connected callback */ static err_t httpc_tcp_connected(void *arg, struct altcp_pcb *pcb, err_t err) { err_t r; httpc_state_t* req = (httpc_state_t*)arg; LWIP_UNUSED_ARG(pcb); LWIP_UNUSED_ARG(err); /* send request; last char is zero termination */ r = altcp_write(req->pcb, req->request->payload, req->request->len - 1, TCP_WRITE_FLAG_COPY); if (r != ERR_OK) { /* could not write the single small request -> fail, don't retry */ return httpc_close(req, HTTPC_RESULT_ERR_MEM, 0, r); } /* everything written, we can free the request */ pbuf_free(req->request); req->request = NULL; altcp_output(req->pcb); return ERR_OK; }
/** DNS callback * If ipaddr is non-NULL, resolving succeeded and the request can be sent, otherwise it failed. */ static void httpc_dns_found(const char* hostname, const ip_addr_t *ipaddr, void *arg) { httpc_state_t* req = (httpc_state_t*)arg; err_t err; httpc_result_t result; LWIP_UNUSED_ARG(hostname); if (ipaddr != NULL) { err = httpc_get_internal_addr(req, ipaddr); if (err == ERR_OK) { return; } result = HTTPC_RESULT_ERR_CONNECT; } else { LWIP_DEBUGF(HTTPC_DEBUG_WARN_STATE, ("httpc_dns_found: failed to resolve hostname: %s\n", hostname)); result = HTTPC_RESULT_ERR_HOSTNAME; err = ERR_ARG; } httpc_close(req, result, 0, err); }
/** http client tcp recv callback */ static err_t httpc_tcp_recv(void *arg, struct altcp_pcb *pcb, struct pbuf *p, err_t r) { httpc_state_t* req = (httpc_state_t*)arg; LWIP_UNUSED_ARG(r); if (p == NULL) { httpc_result_t result; if (req->parse_state != HTTPC_PARSE_RX_DATA) { /* did not get RX data yet */ result = HTTPC_RESULT_ERR_CLOSED; } else if ((req->hdr_content_len != HTTPC_CONTENT_LEN_INVALID) && (req->hdr_content_len != req->rx_content_len)) { /* header has been received with content length but not all data received */ result = HTTPC_RESULT_ERR_CONTENT_LEN; } else { /* receiving data and either all data received or no content length header */ result = HTTPC_RESULT_OK; } return httpc_close(req, result, req->rx_status, ERR_OK); } if (req->parse_state != HTTPC_PARSE_RX_DATA) { if (req->rx_hdrs == NULL) { req->rx_hdrs = p; } else { pbuf_cat(req->rx_hdrs, p); } if (req->parse_state == HTTPC_PARSE_WAIT_FIRST_LINE) { u16_t status_str_off; err_t err = http_parse_response_status(req->rx_hdrs, &req->rx_http_version, &req->rx_status, &status_str_off); if (err == ERR_OK) { /* don't care status string */ req->parse_state = HTTPC_PARSE_WAIT_HEADERS; } } if (req->parse_state == HTTPC_PARSE_WAIT_HEADERS) { u16_t total_header_len; err_t err = http_wait_headers(req->rx_hdrs, &req->hdr_content_len, &total_header_len); if (err == ERR_OK) { struct pbuf *q; /* full header received, send window update for header bytes and call into client callback */ altcp_recved(pcb, total_header_len); if (req->conn_settings) { if (req->conn_settings->headers_done_fn) { err = req->conn_settings->headers_done_fn(req, req->callback_arg, req->rx_hdrs, total_header_len, req->hdr_content_len); if (err != ERR_OK) { return httpc_close(req, HTTPC_RESULT_LOCAL_ABORT, req->rx_status, err); } } } /* hide header bytes in pbuf */ q = pbuf_free_header(req->rx_hdrs, total_header_len); p = q; req->rx_hdrs = NULL; /* go on with data */ req->parse_state = HTTPC_PARSE_RX_DATA; } } } if ((p != NULL) && (req->parse_state == HTTPC_PARSE_RX_DATA)) { req->rx_content_len += p->tot_len; if (req->recv_fn != NULL) { /* directly return here: the connection migth already be aborted from the callback! */ return req->recv_fn(req->callback_arg, pcb, p, r); } else { altcp_recved(pcb, p->tot_len); pbuf_free(p); } } return ERR_OK; }