static void spdy_cb_before_ctrl_send(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { (void)user_data; int32_t stream_id; struct Proxy *proxy; switch(type) { case SPDYLAY_SYN_STREAM: stream_id = frame->syn_stream.stream_id; proxy = spdylay_session_get_stream_user_data(session, stream_id); proxy->stream_id = stream_id; ++glob_opt.streams_opened; ++proxy->spdy_connection->streams_opened; PRINT_INFO2("opening stream: str open %i; %s", glob_opt.streams_opened, proxy->url); break; case SPDYLAY_RST_STREAM: //try to ignore duplicate RST_STREAMs //TODO this will ignore RST_STREAMs also for bogus data glob_opt.ignore_rst_stream = NULL==spdylay_session_get_stream_user_data(session, frame->rst_stream.stream_id); PRINT_INFO2("sending RST_STREAM for %i; ignore %i; status %i", frame->rst_stream.stream_id, glob_opt.ignore_rst_stream, frame->rst_stream.status_code); break; default: break; } }
static void on_ctrl_send_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { (void)user_data; char **nv; const char *name = NULL; int32_t stream_id; size_t i; switch(type) { case SPDYLAY_SYN_STREAM: nv = frame->syn_stream.nv; name = "SYN_STREAM"; stream_id = frame->syn_stream.stream_id; break; default: break; } if(name && spdylay_session_get_stream_user_data(session, stream_id)) { printf("[INFO] C ----------------------------> S (%s)\n", name); for(i = 0; nv[i]; i += 2) { printf(" %s: %s\n", nv[i], nv[i+1]); } } }
/* * The implementation of spdylay_on_stream_close_callback type. We use * this function to know the response is fully received. Since we just * fetch 1 resource in this program, after reception of the response, * we submit GOAWAY and close the session. */ static void spdy_cb_on_stream_close(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code, void *user_data) { (void)status_code; (void)user_data; struct Proxy * proxy = spdylay_session_get_stream_user_data(session, stream_id); assert(NULL != proxy); --glob_opt.streams_opened; --proxy->spdy_connection->streams_opened; PRINT_INFO2("closing stream: str opened %i; remove proxy %i", glob_opt.streams_opened, proxy->id); DLL_remove(proxy->spdy_connection->proxies_head, proxy->spdy_connection->proxies_tail, proxy); if(proxy->http_active) { proxy->spdy_active = false; } else { free_proxy(proxy); } }
/* * The implementation of spdylay_on_data_chunk_recv_callback type. We * use this function to print the received response body. */ static void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { printf("[INFO] C <---------------------------- S (DATA)\n"); printf(" %lu bytes\n", (unsigned long int)len); if(req->inflater) { while(len > 0) { uint8_t out[MAX_OUTLEN]; size_t outlen = MAX_OUTLEN; size_t tlen = len; int rv; rv = spdylay_gzip_inflate(req->inflater, out, &outlen, data, &tlen); if(rv == -1) { spdylay_submit_rst_stream(session, stream_id, SPDYLAY_INTERNAL_ERROR); break; } fwrite(out, 1, outlen, stdout); data += tlen; len -= tlen; } } else { /* TODO add support gzip */ fwrite(data, 1, len, stdout); } printf("\n"); } }
static void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { struct Request *req; char **nv; const char *name = NULL; int32_t stream_id; size_t i; switch(type) { case SPDYLAY_SYN_REPLY: nv = frame->syn_reply.nv; name = "SYN_REPLY"; stream_id = frame->syn_reply.stream_id; break; case SPDYLAY_HEADERS: nv = frame->headers.nv; name = "HEADERS"; stream_id = frame->headers.stream_id; break; default: break; } if(!name) { return; } req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { check_gzip(req, nv); printf("[INFO] C <---------------------------- S (%s)\n", name); for(i = 0; nv[i]; i += 2) { printf(" %s: %s\n", nv[i], nv[i+1]); } } }
void spdy_cb_on_ctrl_recv(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { (void)user_data; char **nv; int32_t stream_id; struct Proxy * proxy; switch(type) { case SPDYLAY_SYN_REPLY: nv = frame->syn_reply.nv; stream_id = frame->syn_reply.stream_id; break; case SPDYLAY_RST_STREAM: stream_id = frame->rst_stream.stream_id; break; case SPDYLAY_HEADERS: nv = frame->headers.nv; stream_id = frame->headers.stream_id; break; default: return; break; } proxy = spdylay_session_get_stream_user_data(session, stream_id); if(NULL == proxy) { PRINT_INFO2("received frame type %i for unkonwn stream id %i", type, stream_id); return; //DIE("no proxy obj"); } switch(type) { case SPDYLAY_SYN_REPLY: PRINT_INFO2("received headers for %s", proxy->url); http_create_response(proxy, nv); break; case SPDYLAY_RST_STREAM: PRINT_INFO2("received reset stream for %s", proxy->url); proxy->spdy_error = true; break; case SPDYLAY_HEADERS: PRINT_INFO2("received headers for %s", proxy->url); http_create_response(proxy, nv); break; default: return; break; } glob_opt.spdy_data_received = true; }
/* * The implementation of spdylay_on_stream_close_callback type. We use * this function to know the response is fully received. Since we just * fetch 1 resource in this program, after reception of the response, * we submit GOAWAY and close the session. */ static void on_stream_close_callback(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code, void *user_data) { struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { int rv; rv = spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK); if(rv != 0) { diec("spdylay_submit_goaway", rv); } } }
/* * The implementation of spdylay_before_ctrl_send_callback type. We * use this function to get stream ID of the request. This is because * stream ID is not known when we submit the request * (spdylay_submit_request). */ static void before_ctrl_send_callback(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame, void *user_data) { if(type == SPDYLAY_SYN_STREAM) { struct Request *req; int stream_id = frame->syn_stream.stream_id; req = spdylay_session_get_stream_user_data(session, stream_id); if(req && req->stream_id == -1) { req->stream_id = stream_id; printf("[INFO] Stream ID = %d\n", stream_id); } } }
static void spdy_cb_on_data_recv(spdylay_session *session, uint8_t flags, int32_t stream_id, int32_t length, void *user_data) { (void)length; (void)user_data; if(flags & SPDYLAY_DATA_FLAG_FIN) { struct Proxy *proxy; proxy = spdylay_session_get_stream_user_data(session, stream_id); proxy->done = true; PRINT_INFO2("last data frame received for %s", proxy->url); } }
/* * The implementation of spdylay_on_data_chunk_recv_callback type. We * use this function to print the received response body. */ static void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { (void)user_data; (void)flags; struct Request *req; req = spdylay_session_get_stream_user_data(session, stream_id); if(req) { printf("[INFO] C <---------------------------- S (DATA)\n"); printf(" %lu bytes\n", (unsigned long int)len); if(req->inflater) { while(len > 0) { uint8_t out[MAX_OUTLEN]; size_t outlen = MAX_OUTLEN; size_t tlen = len; int rv; rv = spdylay_gzip_inflate(req->inflater, out, &outlen, data, &tlen); if(rv == -1) { spdylay_submit_rst_stream(session, stream_id, SPDYLAY_INTERNAL_ERROR); break; } fwrite(out, 1, outlen, stdout); data += tlen; len -= tlen; } } else { /* TODO add support gzip */ fwrite(data, 1, len, stdout); //check if the data is correct //if(strcmp(RESPONSE_BODY, data) != 0) //killparent(parent, "\nreceived data is not the same"); if(len + rcvbuf_c > strlen(RESPONSE_BODY)) killparent(parent, "\nreceived data is not the same"); strcpy(rcvbuf + rcvbuf_c,(char*)data); rcvbuf_c+=len; } printf("\n"); } }
/* * The implementation of spdylay_on_data_chunk_recv_callback type. We * use this function to print the received response body. */ static void spdy_cb_on_data_chunk_recv(spdylay_session *session, uint8_t flags, int32_t stream_id, const uint8_t *data, size_t len, void *user_data) { (void)flags; (void)user_data; struct Proxy *proxy; proxy = spdylay_session_get_stream_user_data(session, stream_id); if(NULL == proxy) { PRINT_INFO("proxy in spdy_cb_on_data_chunk_recv is NULL)"); return; } if(!copy_buffer(data, len, &proxy->http_body, &proxy->http_body_size)) { //TODO handle it better? PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); return; } /* if(NULL == proxy->http_body) proxy->http_body = au_malloc(len); else proxy->http_body = realloc(proxy->http_body, proxy->http_body_size + len); if(NULL == proxy->http_body) { PRINT_INFO("not enough memory (realloc returned NULL)"); return ; } memcpy(proxy->http_body + proxy->http_body_size, data, len); proxy->http_body_size += len; */ PRINT_INFO2("received data for %s; %zu bytes", proxy->url, len); glob_opt.spdy_data_received = true; }