| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <assert.h> |
| #include <stddef.h> |
| |
| #include <httpd.h> |
| #include <http_core.h> |
| #include <http_connection.h> |
| #include <http_log.h> |
| |
| #include "h2_private.h" |
| #include "h2.h" |
| #include "h2_mplx.h" |
| #include "h2_session.h" |
| #include "h2_bucket_eoc.h" |
| |
| typedef struct { |
| apr_bucket_refcount refcount; |
| h2_session *session; |
| } h2_bucket_eoc; |
| |
| static apr_status_t bucket_cleanup(void *data) |
| { |
| h2_session **psession = data; |
| |
| if (*psession) { |
| /* |
| * If bucket_destroy is called after us, this prevents |
| * bucket_destroy from trying to destroy the pool again. |
| */ |
| *psession = NULL; |
| } |
| return APR_SUCCESS; |
| } |
| |
| static apr_status_t bucket_read(apr_bucket *b, const char **str, |
| apr_size_t *len, apr_read_type_e block) |
| { |
| (void)b; |
| (void)block; |
| *str = NULL; |
| *len = 0; |
| return APR_SUCCESS; |
| } |
| |
| apr_bucket * h2_bucket_eoc_make(apr_bucket *b, h2_session *session) |
| { |
| h2_bucket_eoc *h; |
| |
| h = apr_bucket_alloc(sizeof(*h), b->list); |
| h->session = session; |
| |
| b = apr_bucket_shared_make(b, h, 0, 0); |
| b->type = &h2_bucket_type_eoc; |
| |
| return b; |
| } |
| |
| apr_bucket * h2_bucket_eoc_create(apr_bucket_alloc_t *list, h2_session *session) |
| { |
| apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); |
| |
| APR_BUCKET_INIT(b); |
| b->free = apr_bucket_free; |
| b->list = list; |
| b = h2_bucket_eoc_make(b, session); |
| if (session) { |
| h2_bucket_eoc *h = b->data; |
| apr_pool_pre_cleanup_register(session->pool, &h->session, bucket_cleanup); |
| } |
| return b; |
| } |
| |
| static void bucket_destroy(void *data) |
| { |
| h2_bucket_eoc *h = data; |
| |
| if (apr_bucket_shared_destroy(h)) { |
| h2_session *session = h->session; |
| apr_bucket_free(h); |
| if (session) { |
| h2_session_eoc_callback(session); |
| /* all is gone now */ |
| } |
| } |
| } |
| |
| const apr_bucket_type_t h2_bucket_type_eoc = { |
| "H2EOC", 5, APR_BUCKET_METADATA, |
| bucket_destroy, |
| bucket_read, |
| apr_bucket_setaside_noop, |
| apr_bucket_split_notimpl, |
| apr_bucket_shared_copy |
| }; |
| |