uv_write_t *req;
};
+static void http_stream_status_free(struct http_stream_status *stat)
+{
+ if (!stat)
+ return;
+
+ free(stat->err_msg);
+ stat->err_msg = NULL;
+ free(stat);
+}
+
+static int status_free(trie_val_t *stat, void *null)
+{
+ assert(stat);
+ http_stream_status_free(*stat);
+ return 0;
+}
+
+
/*
* Write HTTP/2 protocol data to underlying transport layer.
*/
return 0;
}
-static int http_status_remove(struct http_ctx *ctx, struct http_stream_status * stat);
-static struct http_stream_status * http_status_get(struct http_ctx *ctx, int32_t stream_id);
-
/*
* Write entire DATA frame to underlying transport layer.
*
if (ret < 0)
return NGHTTP2_ERR_CALLBACK_FAILURE;
- http_status_remove(ctx, http_status_get(ctx, frame->hd.stream_id));
-
return 0;
}
return send;
}
-/*
- * Get pointer to stream status.
- */
-static struct http_stream_status * http_status_get(struct http_ctx *ctx, int32_t stream_id)
-{
- assert(ctx);
- struct http_stream_status *stat = NULL;
-
- if (ctx->current_stream && ctx->current_stream->stream_id == stream_id)
- return ctx->current_stream;
-
-
- for (size_t idx = 0; idx < ctx->stream_status.len; ++idx) {
- stat = ctx->stream_status.at[idx];
- if (stat->stream_id == stream_id)
- return stat;
- }
- return NULL;
-}
-
-/*
- * Remove error stream status from list
- */
-static int http_status_remove(struct http_ctx *ctx, struct http_stream_status * stat)
-{
- if (!stat)
- return 0;
-
- free(stat->err_msg);
- stat->err_msg = NULL;
-
- size_t idx;
- for (idx = 0; idx < ctx->stream_status.len; ++idx) {
- if (stat->stream_id == ctx->stream_status.at[idx]->stream_id) {
- array_del(ctx->stream_status, idx);
- free(stat);
- break;
- }
- }
-
- return 0;
-}
-
/*
* Send http error status code.
*/
int ret;
int status_len;
nghttp2_data_provider prov;
- struct http_stream_status *stat = http_status_get(ctx, stream_id);
+ trie_val_t *stat_p = trie_get_try(ctx->stream_status, (char *)&stream_id, sizeof(stream_id));
- if(!stat)
+ if (!stat_p || !*stat_p)
return kr_error(EINVAL);
+ struct http_stream_status *stat = *stat_p;
prov.source.ptr = NULL;
prov.read_callback = read_callback;
static struct http_stream_status * set_error_status(struct http_ctx *ctx, int32_t stream_id, int status, const char *const status_msg)
{
- struct http_stream_status *stat = http_status_get(ctx, stream_id);
+ trie_val_t *stat_p = trie_get_ins(ctx->stream_status, (char *)&stream_id, sizeof(stream_id));
+ struct http_stream_status *stat = *stat_p;
if (stat && stat->err_status != 200)
return stat;
if (!stat)
return NULL;
- // push to end of array
- if (array_push(ctx->stream_status, stat) < 0) {
- free(stat);
- return NULL;
- }
-
+ *stat_p = stat;
stat->err_msg = NULL;
}
stat->stream_id = stream_id;
static int on_stream_close_callback(nghttp2_session *h2, int32_t stream_id,
uint32_t error_code, void *user_data)
{
+ struct http_ctx *ctx = (struct http_ctx *)user_data;
struct http_data *data;
+ struct http_stream_status *stat;
+ int ret;
data = nghttp2_session_get_stream_user_data(h2, stream_id);
if (data)
on_pkt_write(data, error_code == 0 ? 0 : kr_error(EIO));
+ ret = trie_del(ctx->stream_status, (char *)&stream_id, sizeof(stream_id), (trie_val_t *)&stat);
+ if (ret == 0)
+ http_stream_status_free(stat);
+
return 0;
}
ctx->current_method = HTTP_METHOD_NONE;
ctx->uri_path = NULL;
ctx->content_type = NULL;
- array_init(ctx->stream_status);
+ ctx->stream_status = trie_create(NULL);
nghttp2_session_server_new(&ctx->h2, callbacks, ctx);
if (!ctx)
return;
- while(ctx->stream_status.len)
- http_status_remove(ctx, ctx->stream_status.at[0]);
- array_clear(ctx->stream_status);
+ trie_apply(ctx->stream_status, status_free, NULL);
+ trie_free(ctx->stream_status);
queue_deinit(ctx->streams);
nghttp2_session_del(ctx->h2);