src/stream/ngx_stream_return_module.c - nginx source code

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Roman Arutyunyan
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_stream.h>


  8. typedef struct {
  9.     ngx_stream_complex_value_t   text;
  10. } ngx_stream_return_srv_conf_t;


  11. typedef struct {
  12.     ngx_chain_t                 *out;
  13. } ngx_stream_return_ctx_t;


  14. static void ngx_stream_return_handler(ngx_stream_session_t *s);
  15. static void ngx_stream_return_write_handler(ngx_event_t *ev);

  16. static void *ngx_stream_return_create_srv_conf(ngx_conf_t *cf);
  17. static char *ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);


  18. static ngx_command_t  ngx_stream_return_commands[] = {

  19.     { ngx_string("return"),
  20.       NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1,
  21.       ngx_stream_return,
  22.       NGX_STREAM_SRV_CONF_OFFSET,
  23.       0,
  24.       NULL },

  25.       ngx_null_command
  26. };


  27. static ngx_stream_module_t  ngx_stream_return_module_ctx = {
  28.     NULL,                                  /* preconfiguration */
  29.     NULL,                                  /* postconfiguration */

  30.     NULL,                                  /* create main configuration */
  31.     NULL,                                  /* init main configuration */

  32.     ngx_stream_return_create_srv_conf,     /* create server configuration */
  33.     NULL                                   /* merge server configuration */
  34. };


  35. ngx_module_t  ngx_stream_return_module = {
  36.     NGX_MODULE_V1,
  37.     &ngx_stream_return_module_ctx,         /* module context */
  38.     ngx_stream_return_commands,            /* module directives */
  39.     NGX_STREAM_MODULE,                     /* module type */
  40.     NULL,                                  /* init master */
  41.     NULL,                                  /* init module */
  42.     NULL,                                  /* init process */
  43.     NULL,                                  /* init thread */
  44.     NULL,                                  /* exit thread */
  45.     NULL,                                  /* exit process */
  46.     NULL,                                  /* exit master */
  47.     NGX_MODULE_V1_PADDING
  48. };


  49. static void
  50. ngx_stream_return_handler(ngx_stream_session_t *s)
  51. {
  52.     ngx_str_t                      text;
  53.     ngx_buf_t                     *b;
  54.     ngx_connection_t              *c;
  55.     ngx_stream_return_ctx_t       *ctx;
  56.     ngx_stream_return_srv_conf_t  *rscf;

  57.     c = s->connection;

  58.     c->log->action = "returning text";

  59.     rscf = ngx_stream_get_module_srv_conf(s, ngx_stream_return_module);

  60.     if (ngx_stream_complex_value(s, &rscf->text, &text) != NGX_OK) {
  61.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  62.         return;
  63.     }

  64.     ngx_log_debug1(NGX_LOG_DEBUG_STREAM, c->log, 0,
  65.                    "stream return text: \"%V\"", &text);

  66.     if (text.len == 0) {
  67.         ngx_stream_finalize_session(s, NGX_STREAM_OK);
  68.         return;
  69.     }

  70.     ctx = ngx_pcalloc(c->pool, sizeof(ngx_stream_return_ctx_t));
  71.     if (ctx == NULL) {
  72.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  73.         return;
  74.     }

  75.     ngx_stream_set_ctx(s, ctx, ngx_stream_return_module);

  76.     b = ngx_calloc_buf(c->pool);
  77.     if (b == NULL) {
  78.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  79.         return;
  80.     }

  81.     b->memory = 1;
  82.     b->pos = text.data;
  83.     b->last = text.data + text.len;
  84.     b->last_buf = 1;

  85.     ctx->out = ngx_alloc_chain_link(c->pool);
  86.     if (ctx->out == NULL) {
  87.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  88.         return;
  89.     }

  90.     ctx->out->buf = b;
  91.     ctx->out->next = NULL;

  92.     c->write->handler = ngx_stream_return_write_handler;

  93.     ngx_stream_return_write_handler(c->write);
  94. }


  95. static void
  96. ngx_stream_return_write_handler(ngx_event_t *ev)
  97. {
  98.     ngx_connection_t         *c;
  99.     ngx_stream_session_t     *s;
  100.     ngx_stream_return_ctx_t  *ctx;

  101.     c = ev->data;
  102.     s = c->data;

  103.     if (ev->timedout) {
  104.         ngx_connection_error(c, NGX_ETIMEDOUT, "connection timed out");
  105.         ngx_stream_finalize_session(s, NGX_STREAM_OK);
  106.         return;
  107.     }

  108.     ctx = ngx_stream_get_module_ctx(s, ngx_stream_return_module);

  109.     if (ngx_stream_top_filter(s, ctx->out, 1) == NGX_ERROR) {
  110.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  111.         return;
  112.     }

  113.     ctx->out = NULL;

  114.     if (!c->buffered) {
  115.         ngx_log_debug0(NGX_LOG_DEBUG_STREAM, c->log, 0,
  116.                        "stream return done sending");
  117.         ngx_stream_finalize_session(s, NGX_STREAM_OK);
  118.         return;
  119.     }

  120.     if (ngx_handle_write_event(ev, 0) != NGX_OK) {
  121.         ngx_stream_finalize_session(s, NGX_STREAM_INTERNAL_SERVER_ERROR);
  122.         return;
  123.     }

  124.     ngx_add_timer(ev, 5000);
  125. }


  126. static void *
  127. ngx_stream_return_create_srv_conf(ngx_conf_t *cf)
  128. {
  129.     ngx_stream_return_srv_conf_t  *conf;

  130.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_stream_return_srv_conf_t));
  131.     if (conf == NULL) {
  132.         return NULL;
  133.     }

  134.     return conf;
  135. }


  136. static char *
  137. ngx_stream_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  138. {
  139.     ngx_stream_return_srv_conf_t *rscf = conf;

  140.     ngx_str_t                           *value;
  141.     ngx_stream_core_srv_conf_t          *cscf;
  142.     ngx_stream_compile_complex_value_t   ccv;

  143.     if (rscf->text.value.data) {
  144.         return "is duplicate";
  145.     }

  146.     value = cf->args->elts;

  147.     ngx_memzero(&ccv, sizeof(ngx_stream_compile_complex_value_t));

  148.     ccv.cf = cf;
  149.     ccv.value = &value[1];
  150.     ccv.complex_value = &rscf->text;

  151.     if (ngx_stream_compile_complex_value(&ccv) != NGX_OK) {
  152.         return NGX_CONF_ERROR;
  153.     }

  154.     cscf = ngx_stream_conf_get_module_srv_conf(cf, ngx_stream_core_module);

  155.     cscf->handler = ngx_stream_return_handler;

  156.     return NGX_CONF_OK;
  157. }