Added spdylay_session_on_ctrl_recv_parse_error_callback.

This callback function is invoked when the received frame data could not
be parsed correctly.
Added debug output using this callback to spdycat.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-05-09 21:55:21 +09:00
parent b7429e7c2d
commit 171bede1fa
5 changed files with 93 additions and 0 deletions

View File

@ -348,6 +348,8 @@ int run(char **uris, int n)
callbacks.on_ctrl_recv_callback = on_ctrl_recv_callback3;
callbacks.on_data_recv_callback = on_data_recv_callback;
callbacks.on_ctrl_send_callback = on_ctrl_send_callback3;
callbacks.on_ctrl_recv_parse_error_callback =
on_ctrl_recv_parse_error_callback;
} else {
callbacks.on_ctrl_recv_callback = on_ctrl_recv_callback2;
callbacks.on_ctrl_send_callback = on_ctrl_send_callback2;

View File

@ -407,6 +407,34 @@ void on_ctrl_recv_callback
fflush(stdout);
}
namespace {
const char* spdylay_strerror(int error_code)
{
return "UNKNOWN";
};
} // namespace
void on_ctrl_recv_parse_error_callback(spdylay_session *session,
spdylay_frame_type type,
const uint8_t *head,
size_t headlen,
const uint8_t *payload,
size_t payloadlen,
int error_code, void *user_data)
{
size_t i;
print_timer();
printf(" recv %s frame: Parse error [%s]\n", ctrl_names[type-1],
spdylay_strerror(error_code));
print_frame_attr_indent();
printf("Header dump: ");
for(i = 0; i < headlen; ++i) {
printf("%02X ", head[i]);
}
printf("\n");
fflush(stdout);
}
void on_ctrl_send_callback
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data)

View File

@ -85,6 +85,14 @@ void on_ctrl_recv_callback
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data);
void on_ctrl_recv_parse_error_callback(spdylay_session *session,
spdylay_frame_type type,
const uint8_t *head,
size_t headlen,
const uint8_t *payload,
size_t payloadlen,
int error_code, void *user_data);
void on_ctrl_send_callback
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame,
void *user_data);

View File

@ -957,6 +957,27 @@ typedef void (*spdylay_on_stream_close_callback)
typedef void (*spdylay_on_request_recv_callback)
(spdylay_session *session, int32_t stream_id, void *user_data);
/**
* @functypedef
*
* Callback function invoked when the received control frame octets
* could not be parsed correctly. The |type| indicates the type of
* received control frame. The |head| is the pointer to the header of
* the received frame. The |headlen| is the length of the
* |head|. According to the SPDY spec, the |headlen| is always 8. In
* other words, the |head| is the first 8 bytes of the received frame.
* The |payload| is the pointer to the data portion of the received
* frame. The |payloadlen| is the length of the |payload|. This is
* the data after the length field. The |error_code| is one of the
* error code defined in :enum:`spdylay_error` and indicates the
* error.
*/
typedef void (*spdylay_on_ctrl_recv_parse_error_callback)
(spdylay_session *session, spdylay_frame_type type,
const uint8_t *head, size_t headlen,
const uint8_t *payload, size_t payloadlen,
int error_code, void *user_data);
#define SPDYLAY_MAX_SCHEME 255
#define SPDYLAY_MAX_HOSTNAME 255
@ -1117,6 +1138,11 @@ typedef struct {
* certificate.
*/
spdylay_get_credential_cert get_credential_cert;
/**
* Callback function invoked when the received control frame octets
* could not be parsed correctly.
*/
spdylay_on_ctrl_recv_parse_error_callback on_ctrl_recv_parse_error_callback;
} spdylay_session_callbacks;
/**
@ -1375,6 +1401,9 @@ int spdylay_session_send(spdylay_session *session);
* invalid,
* :member:`spdylay_session_callbacks.on_invalid_ctrl_recv_callback`
* is invoked.
* 3.4. If the received frame could not be unpacked correctly,
* :member:`spdylay_session_callbacks.on_ctrl_recv_parse_error_callback`
* is invoked.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:

View File

@ -2004,6 +2004,23 @@ int spdylay_session_on_headers_received(spdylay_session *session,
return r;
}
static void spdylay_session_handle_parse_error(spdylay_session *session,
spdylay_frame_type type,
int error_code)
{
if(session->callbacks.on_ctrl_recv_parse_error_callback) {
session->callbacks.on_ctrl_recv_parse_error_callback
(session,
type,
session->iframe.headbuf,
sizeof(session->iframe.headbuf),
session->iframe.buf,
session->iframe.len,
error_code,
session->user_data);
}
}
/* For errors, this function only returns FATAL error. */
static int spdylay_session_process_ctrl_frame(spdylay_session *session)
{
@ -2038,6 +2055,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
SPDYLAY_PROTOCOL_ERROR);
spdylay_frame_syn_stream_free(&frame.syn_stream);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2064,6 +2082,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
SPDYLAY_PROTOCOL_ERROR);
spdylay_frame_syn_reply_free(&frame.syn_reply);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2077,6 +2096,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
r = spdylay_session_on_rst_stream_received(session, &frame);
spdylay_frame_rst_stream_free(&frame.rst_stream);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2090,6 +2110,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
r = spdylay_session_on_settings_received(session, &frame);
spdylay_frame_settings_free(&frame.settings);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2105,6 +2126,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
r = spdylay_session_on_ping_received(session, &frame);
spdylay_frame_ping_free(&frame.ping);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2118,6 +2140,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
r = spdylay_session_on_goaway_received(session, &frame);
spdylay_frame_goaway_free(&frame.goaway);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2144,6 +2167,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
SPDYLAY_PROTOCOL_ERROR);
spdylay_frame_headers_free(&frame.headers);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2157,6 +2181,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
r = spdylay_session_on_window_update_received(session, &frame);
spdylay_frame_window_update_free(&frame.window_update);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;
@ -2170,6 +2195,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
r = spdylay_session_on_credential_received(session, &frame);
spdylay_frame_credential_free(&frame.credential);
} else if(spdylay_is_non_fatal(r)) {
spdylay_session_handle_parse_error(session, type, r);
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
}
break;