void ngx_http_push_subscriber_cleanup(ngx_http_push_subscriber_cleanup_t *data) {
  if(data->subscriber!=NULL) { //still queued up
    ngx_http_push_subscriber_t* sb = data->subscriber;
    ngx_http_push_subscriber_del_timer(sb);
    ngx_queue_remove(&data->subscriber->queue);
    ngx_pfree(ngx_http_push_pool, data->subscriber); //was there an error? oh whatever.
  }
  if (data->rchain != NULL) {
    ngx_pfree(data->rpool, data->rchain->buf);
    ngx_pfree(data->rpool, data->rchain);
    data->rchain=NULL;
  }
  if(data->buf_use_count != NULL && --(*data->buf_use_count) <= 0) {
    ngx_buf_t                      *buf;
    ngx_pfree(ngx_http_push_pool, data->buf_use_count);
    buf=data->buf;
    if(buf->file) {
      ngx_close_file(buf->file->fd);
    }
    ngx_pfree(ngx_http_push_pool, buf);
  }
  
  if(data->channel!=NULL) { //we're expected to decrement the subscriber count
    ngx_http_push_store->lock();
    data->channel->subscribers--;
    ngx_http_push_store->unlock();
  }
}
Example #2
0
/**
 * Function to free a chain buffer.
 * This specifically releases a buffer created and populated by ironbee_body_out.
 * It is not for general-purpose use with an arbitrary chain, where it would
 * likely crash and burn.
 *
 * @param[in]  pool  The pool used to allocate buffers being released.
 * @param[in]  chain The chain buffer to free.
 */
static void free_chain(ngx_pool_t *pool, ngx_chain_t *chain)
{
    if (chain) {
        free_chain(pool, chain->next);
        if (chain->buf->last != chain->buf->pos) {
            ngx_pfree(pool, chain->buf->pos);
        }
        ngx_pfree(pool, chain->buf);
        ngx_pfree(pool, chain);
    }
}
static ngx_rtmp_sharedobject_prop_t *
ngx_rtmp_sharedobject_request_change(ngx_rtmp_session_t *s,
                                     ngx_rtmp_sharedobject_t *so,
                                     u_char *data, uint32_t len)
{
  ngx_rtmp_sharedobject_app_conf_t    *soacf;
  ngx_rtmp_sharedobject_prop_t        *prop;
  u_char                              *name, *value, *p;
  uint16_t                             sz;

  soacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_sharedobject_module);
  if (soacf == NULL) {
    return NULL;
  }

  /* read property name */
  p = (u_char*)&sz;
  p[0] = data[1];
  p[1] = data[0];

  name = ngx_pcalloc(soacf->pool, sizeof(u_char) * sz);
  ngx_memcpy(name, data+2, sz);

  /* read property value */
  value = ngx_pcalloc(soacf->pool, sizeof(u_char) * (len-sz));
  ngx_memcpy(value, data+2+sz, (len-sz));

  /* Store the property */
  prop = ngx_rtmp_sharedobject_search_prop(s, so, name);
  if (prop == NULL) {
    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "shared-object: set property '%s' in '%s'",
                   name, so->name);
    prop = ngx_pcalloc(soacf->pool, sizeof(ngx_rtmp_sharedobject_prop_t));
    prop->name      = name;
    prop->name_len  = sz;
    prop->value     = value;
    prop->value_len = len-sz;
    prop->next      = so->prop;
    so->prop        = prop;
  }
  else {
    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "shared-object: update property '%s' in '%s'",
                   name, so->name);
    ngx_pfree(soacf->pool, name);
    ngx_pfree(soacf->pool, prop->value);
    prop->value = value;
    prop->value_len = len-sz;
  }

  return prop;
}
static void ngx_http_rrd_free_graph_arg(ngx_pool_t* pool, int argc, char** argv) {
    int i;
    for (i=2;i<argc;i++) {
        /* We might try to free static data in case of ?start= but it does
         * not come from the pool so it is unlikely to cause any problem
         * besides the fact that it is in a section that is probably not even
         * writable.
         */
        ngx_pfree(pool, argv[i]);
    }
    if (argc > 0) {
        ngx_pfree(pool, argv);
    }
}
/*
 * Calculate the HMAC-SHA1 digest for a specified message with a defined key.
 *
 *	@parameters:	*pool		pool for memory allocation;
 *					*key		the hmac key;
 *					*message	the message to digest;
 *	
 *	@return	NGX_ERROR 	on error
 *			NGX_OK		on success
 */
static ngx_int_t
ngx_apikey_hamac_sha1_digest( ngx_pool_t *pool, ngx_str_t *key, ngx_str_t *message, ngx_str_t *digest ) {

	ngx_str_t	hmac_digest		= ngx_null_string;

	u_char		*last			= NULL;
	

	hmac_digest.len 	= EVP_MAX_MD_SIZE;
	hmac_digest.data = ngx_pcalloc( pool, EVP_MAX_MD_SIZE );
	if ( hmac_digest.data == NULL ) {
		ngx_log_error(NGX_LOG_ERR, pool->log, 0, "(%s) failed allocating memory", __func__ );
        return NGX_ERROR;
	}

	/*
	HMAC_CTX ctx;
	HMAC_Init( &ctx, key->data, sizeof(key->data), EVP_sha1() );
	HMAC_Update(&ctx,  message->data, sizeof(message->data));
 	HMAC_Final(&ctx, hmac_digest.data, &hmac_digest.len );		
	HMAC_cleanup(&ctx);
	*/
	
	last = HMAC (EVP_sha1 (), 
		(const void *)key->data, (int)key->len, 
		message->data, (int)message->len, 
		hmac_digest.data, (unsigned int *)&hmac_digest.len );

	if ( last == NULL ) {
		ngx_pfree( pool, hmac_digest.data );
		ngx_log_error(NGX_LOG_ERR, pool->log, 0, "(%s) failed calculating HMAC digest", __func__ );
        return NGX_ERROR;
	}
	
	digest->len  = EVP_MAX_MD_SIZE*2;
	digest->data = ngx_pcalloc( pool, digest->len + 1 );
    if ( digest->data == NULL ) {
		ngx_pfree( pool, hmac_digest.data );
		ngx_log_error(NGX_LOG_ERR, pool->log, 0, "(%s) failed allocating memory", __func__ );
        return NGX_ERROR;
	}
	
	ngx_hex_dump(digest->data, hmac_digest.data, hmac_digest.len);
	

	ngx_pfree( pool, hmac_digest.data );

	
	return NGX_OK;
}
ngx_int_t ngx_http_sticky_misc_text_sha1(ngx_pool_t *pool, struct sockaddr *in, ngx_str_t *digest)
{
	ngx_str_t str;
	if (ngx_http_sticky_misc_text_raw(pool, in, &str) != NGX_OK) {
		return NGX_ERROR;
	}

	if (ngx_http_sticky_misc_sha1(pool, (void *)str.data, str.len, digest) != NGX_OK) {
		ngx_pfree(pool, &str);
		return NGX_ERROR;
	}

	return ngx_pfree(pool, &str);
}
static void
ngx_lcb_close(lcb_io_opt_t io, lcb_socket_t sock)
{
    ngx_lcb_cookie_t cookie = io->v.v0.cookie;
    ngx_lcb_context_t *ctx = from_socket(sock);

    if (ctx->peer->connection != NULL) {
        ngx_close_connection(ctx->peer->connection);
        ctx->peer->connection = NULL;
    }
    ngx_pfree(cookie->pool, ctx->peer);
    ngx_pfree(cookie->pool, ctx->io_chains);
    ngx_pfree(cookie->pool, ctx->io_bufs);
    ngx_pfree(cookie->pool, ctx);
}
Example #8
0
void naxsi_log_offending(ngx_str_t *name, ngx_str_t *val, ngx_http_request_t *req, ngx_http_rule_t *rule,
			 enum DUMMY_MATCH_ZONE	zone, ngx_int_t target_name) {
  ngx_str_t			tmp_uri, tmp_val, tmp_name;
  ngx_str_t			empty=ngx_string("");
  
  //encode uri
  tmp_uri.len = req->uri.len + (2 * ngx_escape_uri(NULL, req->uri.data, req->uri.len,
						   NGX_ESCAPE_ARGS));
  tmp_uri.data = ngx_pcalloc(req->pool, tmp_uri.len+1);
  if (tmp_uri.data == NULL)
    return ;
  ngx_escape_uri(tmp_uri.data, req->uri.data, req->uri.len, NGX_ESCAPE_ARGS);
  //encode val
  if (val->len <= 0)
    tmp_val = empty;
  else {
    tmp_val.len = val->len + (2 * ngx_escape_uri(NULL, val->data, val->len,
						 NGX_ESCAPE_ARGS));
    tmp_val.data = ngx_pcalloc(req->pool, tmp_val.len+1);
    if (tmp_val.data == NULL)
      return ;
    ngx_escape_uri(tmp_val.data, val->data, val->len, NGX_ESCAPE_ARGS);
  }
  //encode name
  if (name->len <= 0)
    tmp_name = empty;
  else {
    tmp_name.len = name->len + (2 * ngx_escape_uri(NULL, name->data, name->len,
						   NGX_ESCAPE_ARGS));
    tmp_name.data = ngx_pcalloc(req->pool, tmp_name.len+1);
    if (tmp_name.data == NULL)
      return ;
    ngx_escape_uri(tmp_name.data, name->data, name->len, NGX_ESCAPE_ARGS);
  }
  
  ngx_log_error(NGX_LOG_ERR, req->connection->log, 0, 
		"NAXSI_EXLOG: ip=%V&server=%V&uri=%V&id=%d&zone=%s%s&var_name=%V&content=%V", 
		&(req->connection->addr_text), &(req->headers_in.server),
		&(tmp_uri), rule->rule_id, dummy_match_zones[zone], target_name?"|NAME":"", &(tmp_name), &(tmp_val));
  
  if (tmp_val.len > 0)
    ngx_pfree(req->pool, tmp_val.data);
  if (tmp_name.len > 0)
    ngx_pfree(req->pool, tmp_name.data);
  if (tmp_uri.len > 0)
    ngx_pfree(req->pool, tmp_uri.data);
  
}
static u_char *
ngx_http_drizzle_get_postponed(ngx_http_request_t *r,
        ngx_http_upstream_drizzle_peer_data_t *dp, size_t len)
{
    u_char          *p;

    dd("MEM enter");

    if (dp->cached.start == NULL) {
        goto alloc;
    }

    if ((size_t) (dp->cached.end - dp->cached.start) < len) {
        ngx_pfree(r->pool, dp->cached.start);
        goto alloc;
    }

    return dp->cached.start;

alloc:
    p = ngx_palloc(r->pool, len);
    if (p == NULL) {
        return NULL;
    }

    dp->cached.start = p;
    dp->cached.end = p + len;

    return p;
}
Example #10
0
ngx_shm_zone_t* ngx_shmap_init(ngx_conf_t *cf, ngx_str_t* name, size_t size, void* module)
{
	ngx_shmap_ctx_t* 			ctx;
	ngx_shm_zone_t             *zone;
    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_shmap_ctx_t));
    if (ctx == NULL) {
        return NULL; 
    }

    zone = ngx_shared_memory_add(cf, name, size, module);
    if (zone == NULL) {
		ngx_pfree(cf->pool, ctx);
		ctx = NULL;
        return NULL;
    }

    ctx->name = *name;
    ctx->log = &cf->cycle->new_log;


    if (zone->data) {
        ctx = zone->data;

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "lua_shared_dict \"%V\" is already defined as "
                           "\"%V\"", name, &ctx->name);
        return NULL;
    }

    zone->init = ngx_shmap_init_zone;
    zone->data = ctx;

  	return zone;
}
static u_char *
ngx_http_rds_json_get_postponed(ngx_http_request_t *r,
    ngx_http_rds_json_ctx_t *ctx, size_t len)
{
    u_char          *p;

    dd("MEM enter");

    if (ctx->cached.start == NULL) {
        goto alloc;
    }

    if ((size_t) (ctx->cached.end - ctx->cached.start) < len) {
        ngx_pfree(r->pool, ctx->cached.start);
        goto alloc;
    }

    return ctx->cached.start;

alloc:
    p = ngx_palloc(r->pool, len);
    if (p == NULL) {
        return NULL;
    }

    ctx->cached.start = p;
    ctx->cached.end = p + len;

    return p;
}
Example #12
0
static int
ngx_http_lua_ngx_encode_args(lua_State *L) {
    ngx_http_request_t          *r;
    ngx_str_t                    args;

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting 1 argument but seen %d",
                          lua_gettop(L));
    }

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    luaL_checktype(L, 1, LUA_TTABLE);

    ngx_http_lua_process_args_option(r, L, 1, &args);

    lua_pushlstring(L, (char *) args.data, args.len);

    ngx_pfree(r->pool, args.data);

    return 1;
}
static void
ngx_http_groonga_query_logger_fin(grn_ctx *ctx, void *user_data)
{
  ngx_http_groonga_query_logger_data_t *data = user_data;

  ngx_pfree(data->pool, data);
}
LIBCOUCHBASE_API
int ngx_lcb_connect(lcb_io_opt_t io,
                    lcb_socket_t sock,
                    const struct sockaddr *name,
                    unsigned int namelen)
{
    ngx_lcb_cookie_t cookie = io->v.v0.cookie;
    ngx_lcb_context_t *ctx = from_socket(sock);
    ngx_peer_connection_t *peer = ctx->peer;
    size_t len;

    peer->sockaddr = (struct sockaddr *)name;
    peer->socklen = namelen;
    /* FIXME free peer->name later */
    peer->name = ngx_pnalloc(cookie->pool, sizeof(ngx_str_t));
    if (peer->name == NULL) {
        return -1;
    }
    len = NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1;
    peer->name->data = ngx_pnalloc(cookie->pool, len);
    if (peer->name->data == NULL) {
        ngx_pfree(cookie->pool, peer->name);
        return -1;
    }
    peer->name->len = ngx_sock_ntop(peer->sockaddr, peer->name->data, len, 1);
    return 0;
}
static ngx_int_t
ngx_http_groonga_handler_process_body(ngx_http_request_t *r,
                                      ngx_http_groonga_handler_data_t *data)
{
  ngx_int_t rc;

  grn_ctx *context;

  ngx_buf_t *body;
  u_char *body_data;
  u_char *body_data_end;

  context = &(data->context);

  body = r->request_body->bufs->buf;
  if (!body) {
    ngx_http_groonga_handler_set_content_type(r, "text/plain");
    GRN_TEXT_PUTS(context, &(data->body), "must send load data as body");
    return NGX_HTTP_BAD_REQUEST;
  }

  rc = ngx_http_groonga_join_request_body_chain(r,
                                                r->request_body->bufs,
                                                &body_data,
                                                &body_data_end);
  if (rc != NGX_OK) {
    return rc;
  }

  rc = ngx_http_groonga_send_lines(context, r, body_data, body_data_end);
  ngx_pfree(r->pool, body_data);

  return rc;
}
static u_char *
ngx_http_vhost_traffic_status_display_set_server(ngx_http_request_t *r,
        ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel,
        const char *fmt, u_char *buf,
        ngx_http_vhost_traffic_status_loc_conf_t *vtscf)
{
    u_char                                  *p;
    ngx_str_t                               key;
    ngx_http_vhost_traffic_status_node_t    *vtsn;

    if (node != sentinel) {
        vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color;

        if (vtsn->stat_upstream.type == NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_NO) {
            key.len = ngx_strlen(vtsn->data) * 6;
            key.data = ngx_pcalloc(r->pool, key.len);
            if (key.data == NULL) {
                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                        "ngx_pcalloc() failed");
                key.len = ngx_strlen(vtsn->data);
                key.data = vtsn->data;
                p = NULL;
                goto just_start;
            }
            p = key.data;

#if !defined(nginx_version) || nginx_version < 1007009
            p = (u_char *) ngx_http_vhost_traffic_status_escape_json(p, vtsn->data, ngx_strlen(vtsn->data));
#else
            p = (u_char *) ngx_escape_json(p, vtsn->data, ngx_strlen(vtsn->data));
#endif

just_start:

            buf = ngx_sprintf(buf, fmt,
                    key.data, vtsn->stat_request_counter, vtsn->stat_in_bytes, vtsn->stat_out_bytes,
                    vtsn->stat_1xx_counter, vtsn->stat_2xx_counter, vtsn->stat_3xx_counter,
                    vtsn->stat_4xx_counter, vtsn->stat_5xx_counter);

            vtscf->stats.stat_request_counter += vtsn->stat_request_counter;
            vtscf->stats.stat_in_bytes += vtsn->stat_in_bytes;
            vtscf->stats.stat_out_bytes += vtsn->stat_out_bytes;
            vtscf->stats.stat_1xx_counter += vtsn->stat_1xx_counter;
            vtscf->stats.stat_2xx_counter += vtsn->stat_2xx_counter;
            vtscf->stats.stat_3xx_counter += vtsn->stat_3xx_counter;
            vtscf->stats.stat_4xx_counter += vtsn->stat_4xx_counter;
            vtscf->stats.stat_5xx_counter += vtsn->stat_5xx_counter;

            if (p != NULL) {
                ngx_pfree(r->pool, key.data);
            }
        }

        buf = ngx_http_vhost_traffic_status_display_set_server(r, node->left, sentinel, fmt, buf, vtscf);
        buf = ngx_http_vhost_traffic_status_display_set_server(r, node->right, sentinel, fmt, buf, vtscf);
    }

    return buf;
}
static void
ngx_lcb_timer_destroy(lcb_io_opt_t io, void *timer)
{
    ngx_lcb_cookie_t cookie = io->v.v0.cookie;
    ngx_event_t *tm = timer;

    ngx_pfree(cookie->pool, tm);
}
Example #18
0
static void esi_tag_start_include(ESITag *tag, ESIAttribute *attributes)
{
  ngx_int_t                      rc; 
  ngx_str_t                      uri, args;
  ngx_http_request_t            *sr;
  ESIAttribute                  *attr = attributes;
  ngx_http_request_t            *request = tag->ctx->request;
  ngx_pool_t                    *pool = request->pool;
  ngx_uint_t                     flags = 0;
  ngx_http_post_subrequest_t    *psr;
  ngx_chain_t                   *link;
  ngx_buf_t                     *buf;

  flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY;
  args.len = 0;
  args.data = NULL;

//  printf( "esi:include\n" );
  while( attr ) {
//    printf( "\t%s => %s\n", attr->name, attr->value );
    if( !ngx_strcmp( attr->name, "src" ) ) { 
      uri.len = strlen(attr->value)+1;
      uri.data =  ngx_palloc(pool, uri.len );
      ngx_memcpy( uri.data, attr->value, uri.len );
      printf( "uri: %s\n", uri.data );
    }
    attr = attr->next;
  }

  if( uri.len > 0 ) {
    psr = ngx_palloc(pool, sizeof(ngx_http_post_subrequest_t));
    if( psr == NULL ) {
      return; //return NGX_ERROR;
    }
    /* attach the handler */
    psr->handler = ngx_http_esi_stub_output;

    /* allocate a buffer */
    buf = ngx_alloc_buf(pool);
    if( buf == NULL ) {
      return; //return NGX_ERROR;
    }
    link = ngx_alloc_chain_link(pool);
    if( link == NULL ) {
      return; //return NGX_ERROR;
    }
    link->buf = buf;
    link->next = NULL;

    psr->data = link;

    rc = ngx_http_subrequest(request, &uri, &args, &sr, psr, flags);
  }

  ngx_pfree( pool, uri.data );
}
void ngx_ac_node_free(ngx_http_ac_t *ac, ngx_http_ac_node_t *n)
{
    ngx_uint_t i;
    for (i = 0; i < ac->set_size; i ++) {
        if (n->next[i] != NULL) {
            ngx_ac_node_free(ac, n->next[i]);
        }
    }
    ngx_pfree(ac->ctx->pool, n);
}
Example #20
0
void
ngx_ssl_free_buffer(ngx_connection_t *c)
{

    if (c->ssl->buf && c->ssl->buf->start) {
        if (ngx_pfree(c->pool, c->ssl->buf->start) == NGX_OK) {
            c->ssl->buf->start = NULL;
        }
    }
}
static void
ngx_http_gzip_filter_free_copy_buf(ngx_http_request_t *r,
                                   ngx_http_gzip_ctx_t *ctx)
{
    ngx_chain_t  *cl;
    for (cl = ctx->copied; cl; cl = cl->next)
    {
        ngx_pfree(r->pool, cl->buf->start);
    }
    ctx->copied = NULL;
}
Example #22
0
ngx_int_t
ngx_http_lua_complex_value(ngx_http_request_t *r, ngx_str_t *subj,
        size_t offset, ngx_int_t count, int *cap,
        ngx_http_lua_complex_value_t *val, luaL_Buffer *luabuf)
{
    size_t                            len;
    u_char                           *p;
    ngx_http_lua_script_code_pt       code;
    ngx_http_lua_script_len_code_pt   lcode;
    ngx_http_lua_script_engine_t      e;

    if (val->lengths == NULL) {
        luaL_addlstring(luabuf, (char *) &subj->data[offset], cap[0] - offset);
        luaL_addlstring(luabuf, (char *) val->value.data, val->value.len);

        return NGX_OK;
    }

    ngx_memzero(&e, sizeof(ngx_http_lua_script_engine_t));

    e.request = r;
    e.ncaptures = count * 2;
    e.captures = cap;
    e.captures_data = subj->data;

    e.ip = val->lengths;

    len = 0;

    while (*(uintptr_t *) e.ip) {
        lcode = *(ngx_http_lua_script_len_code_pt *) e.ip;
        len += lcode(&e);
    }

    p = ngx_pnalloc(r->pool, len);
    if (p == NULL) {
        return NGX_ERROR;
    }

    e.ip = val->values;
    e.pos = p;

    while (*(uintptr_t *) e.ip) {
        code = *(ngx_http_lua_script_code_pt *) e.ip;
        code((ngx_http_lua_script_engine_t *) &e);
    }

    luaL_addlstring(luabuf, (char *) &subj->data[offset], cap[0] - offset);
    luaL_addlstring(luabuf, (char *) p, len);

    ngx_pfree(r->pool, p);

    return NGX_OK;
}
static int
ngx_http_lua_ngx_req_get_uri_args(lua_State *L) {
    ngx_http_request_t          *r;
    u_char                      *buf;
    u_char                      *last;
    int                          retval;
    int                          n;
    int                          max;

    n = lua_gettop(L);

    if (n != 0 && n != 1) {
        return luaL_error(L, "expecting 0 or 1 arguments but seen %d", n);
    }

    if (n == 1) {
        max = luaL_checkinteger(L, 1);
        lua_pop(L, 1);

    } else {
        max = NGX_HTTP_LUA_MAX_ARGS;
    }

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (r == NULL) {
        return luaL_error(L, "no request object found");
    }

    ngx_http_lua_check_fake_request(L, r);

    lua_createtable(L, 0, 4);

    /* we copy r->args over to buf to simplify
     * unescaping query arg keys and values */

    buf = ngx_palloc(r->pool, r->args.len);
    if (buf == NULL) {
        return luaL_error(L, "out of memory");
    }

    ngx_memcpy(buf, r->args.data, r->args.len);

    last = buf + r->args.len;

    retval = ngx_http_lua_parse_args(r, L, buf, last, max);

    ngx_pfree(r->pool, buf);

    return retval;
}
static void ngx_http_push_subscriber_cleanup(ngx_http_push_subscriber_cleanup_t *data) {
	if(data->subscriber!=NULL) { //still queued up
		ngx_queue_remove(&data->subscriber->queue);
		ngx_pfree(ngx_http_push_pool, data->subscriber); //was there an error? oh whatever.
	}
	if(data->channel!=NULL) { //we're expected to decrement the subscriber count
		ngx_slab_pool_t            *shpool = (ngx_slab_pool_t *) ngx_http_push_shm_zone->shm.addr;
		ngx_shmtx_lock(&shpool->mutex);
		data->channel->subscribers--;
		ngx_shmtx_unlock(&shpool->mutex);
	}
}
static void
ngx_http_lua_pcre_free(void *ptr)
{
    dd("lua pcre pool is %p", ngx_http_lua_pcre_pool);

    if (ngx_http_lua_pcre_pool) {
        ngx_pfree(ngx_http_lua_pcre_pool, ptr);
        return;
    }

    fprintf(stderr, "error: lua pcre free failed due to empty pcre pool");
}
void ngx_ac_destroy(ngx_http_ac_t *ac)
{
    ngx_pool_t *tp;
    if (ac != NULL) {
        tp = ac->ctx->pool;
        if (ac->root != NULL) {
            ngx_ac_node_free(ac, ac->root);
            ac->root = NULL;
        }
        ngx_pfree(tp, ac);
    }
}
static ngx_int_t
ngx_rtmp_sharedobject_request_remove(ngx_rtmp_session_t *s,
                                     ngx_rtmp_sharedobject_t *so,
                                     u_char *name, uint32_t len)
{
  ngx_rtmp_sharedobject_app_conf_t    *soacf;
  ngx_rtmp_sharedobject_prop_t        *prop, *prev;
  u_char                              *p;

  soacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_sharedobject_module);
  if (soacf == NULL) {
    return NGX_ERROR;
  }

  for (prev = NULL, prop = so->prop;
       prop;
       prev = prop, prop = prop->next) {
    if (ngx_strncmp(prop->name, name, len) == 0)
      break;
  }

  if (prop != NULL) {
    ngx_log_debug2(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
                   "shared-object: remove property '%s' in '%s'",
                   prop->name, so->name);
    if (prev == NULL) {
      so->prop = prop->next;
    }
    else {
      prev->next = prop->next;
    }
    ngx_pfree(soacf->pool, prop->name);
    ngx_pfree(soacf->pool, prop->value);
    ngx_pfree(soacf->pool, prop);
  }

  return NGX_OK;
}
//allocates message and responds to subscriber
ngx_int_t ngx_http_push_alloc_for_subscriber_response(ngx_pool_t *pool, ngx_int_t shared, ngx_http_push_msg_t *msg, ngx_chain_t **chain, ngx_str_t **content_type, ngx_str_t **etag, time_t *last_modified) {
  if(etag != NULL && (*etag = ngx_http_push_store->message_etag(msg, pool))==NULL) {
    //oh, nevermind...
    ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate memory for Etag header");
    return NGX_ERROR;
  }
  if(content_type != NULL && (*content_type= ngx_http_push_store->message_content_type(msg, pool))==NULL) {
    //oh, nevermind...
    ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate memory for Content Type header");
    if(pool == NULL) {
      ngx_free(*etag);
    }
    else {
      ngx_pfree(pool, *etag);
    }
    return NGX_ERROR;
  }
  
  //preallocate output chain. yes, same one for every waiting subscriber
  if(chain != NULL && (*chain = ngx_http_push_create_output_chain(msg->buf, pool, ngx_cycle->log))==NULL) {
    ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate buffer chain while responding to subscriber request");
    if(pool == NULL) {
      ngx_free(*etag);
      ngx_free(*content_type);
    }
    else {
      ngx_pfree(pool, *etag);
      ngx_pfree(pool, *content_type);
    }
    return NGX_ERROR;
  }
  
  if(last_modified != NULL) {
    *last_modified = msg->message_time;
  }
  ngx_http_push_store->unlock();
  
  
  if(pool!=NULL && shared == 0 && ((*chain)->buf->file!=NULL)) {
    //close file when we're done with it
    ngx_pool_cleanup_t *cln;
    ngx_pool_cleanup_file_t *clnf;
    
    if((cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t)))==NULL) {
      ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "push module: unable to allocate buffer chain pool cleanup while responding to subscriber request");
      ngx_pfree(pool, *etag);
      ngx_pfree(pool, *content_type);
      ngx_pfree(pool, *chain);
      return NGX_ERROR;
    }
    cln->handler = ngx_pool_cleanup_file;
    clnf = cln->data;
    clnf->fd = (*chain)->buf->file->fd;
    clnf->name = (*chain)->buf->file->name.data;
    clnf->log = ngx_cycle->log;
  }
  return NGX_OK;
}
static void
ngx_http_dav_ext_output(ngx_http_request_t *r, ngx_chain_t **ll,
    ngx_int_t flags, u_char *data, ngx_uint_t len) 
{
    ngx_chain_t *cl;
    ngx_uint_t  len_int;
    ngx_buf_t   *b, *b_int /* internal buffer */;

    if (!len) {
        return; 
    }

    if (flags & NGX_HTTP_DAV_EXT_ESCAPE) {
        len_int = len + ngx_escape_html(NULL, data, len);
        b_int = ngx_create_temp_buf(r->pool, len_int);
        b_int->last = (u_char*)ngx_escape_html(b_int->pos, data, len);
        
        len = len_int + ngx_http_dav_ext_escape_html(NULL, b_int->pos, len_int);
        b = ngx_create_temp_buf(r->pool, len);
        b->last = (u_char*)ngx_http_dav_ext_escape_html(b->pos, b_int->pos, len_int);
        
        ngx_pfree(r->pool, b_int);
        
    } else if (flags & NGX_HTTP_DAV_EXT_COPY) {
        b = ngx_create_temp_buf(r->pool, len);
        b->last = ngx_cpymem(b->pos, data, len);

    } else {
        b = ngx_calloc_buf(r->pool);
        b->memory = 1;
        b->pos = data;
        b->start = data;
        b->last = b->pos + len;
        b->end = b->last;
    }

    cl = ngx_alloc_chain_link(r->pool);
    cl->buf = b;
    cl->next = NULL;

    if (*ll != NULL) {
        cl->next = (*ll)->next;
        (*ll)->next = cl;
        *ll = cl;
    } else {
        *ll = cl;
        cl->next = cl;
    }
}
static void
ngx_http_eval_discard_bufs(ngx_pool_t *pool, ngx_chain_t *in)
{
    ngx_chain_t         *cl;

    for (cl = in; cl; cl = cl->next) {
#if 0
        if (cl->buf->temporary && cl->buf->memory
                && ngx_buf_size(cl->buf) > 0) {
            ngx_pfree(pool, cl->buf->start);
        }
#endif

        cl->buf->pos = cl->buf->last;
    }
}