src/http/modules/ngx_http_flv_module.c - nginx-1.7.10

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */

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


  8. static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

  9. static ngx_command_t  ngx_http_flv_commands[] = {

  10.     { ngx_string("flv"),
  11.       NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
  12.       ngx_http_flv,
  13.       0,
  14.       0,
  15.       NULL },

  16.       ngx_null_command
  17. };


  18. static u_char  ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0";


  19. static ngx_http_module_t  ngx_http_flv_module_ctx = {
  20.     NULL,                          /* preconfiguration */
  21.     NULL,                          /* postconfiguration */

  22.     NULL,                          /* create main configuration */
  23.     NULL,                          /* init main configuration */

  24.     NULL,                          /* create server configuration */
  25.     NULL,                          /* merge server configuration */

  26.     NULL,                          /* create location configuration */
  27.     NULL                           /* merge location configuration */
  28. };


  29. ngx_module_t  ngx_http_flv_module = {
  30.     NGX_MODULE_V1,
  31.     &ngx_http_flv_module_ctx,      /* module context */
  32.     ngx_http_flv_commands,         /* module directives */
  33.     NGX_HTTP_MODULE,               /* module type */
  34.     NULL,                          /* init master */
  35.     NULL,                          /* init module */
  36.     NULL,                          /* init process */
  37.     NULL,                          /* init thread */
  38.     NULL,                          /* exit thread */
  39.     NULL,                          /* exit process */
  40.     NULL,                          /* exit master */
  41.     NGX_MODULE_V1_PADDING
  42. };


  43. static ngx_int_t
  44. ngx_http_flv_handler(ngx_http_request_t *r)
  45. {
  46.     u_char                    *last;
  47.     off_t                      start, len;
  48.     size_t                     root;
  49.     ngx_int_t                  rc;
  50.     ngx_uint_t                 level, i;
  51.     ngx_str_t                  path, value;
  52.     ngx_log_t                 *log;
  53.     ngx_buf_t                 *b;
  54.     ngx_chain_t                out[2];
  55.     ngx_open_file_info_t       of;
  56.     ngx_http_core_loc_conf_t  *clcf;

  57.     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
  58.         return NGX_HTTP_NOT_ALLOWED;
  59.     }

  60.     if (r->uri.data[r->uri.len - 1] == '/') {
  61.         return NGX_DECLINED;
  62.     }

  63.     rc = ngx_http_discard_request_body(r);

  64.     if (rc != NGX_OK) {
  65.         return rc;
  66.     }

  67.     last = ngx_http_map_uri_to_path(r, &path, &root, 0);
  68.     if (last == NULL) {
  69.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  70.     }

  71.     log = r->connection->log;

  72.     path.len = last - path.data;

  73.     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
  74.                    "http flv filename: \"%V\"", &path);

  75.     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);

  76.     ngx_memzero(&of, sizeof(ngx_open_file_info_t));

  77.     of.read_ahead = clcf->read_ahead;
  78.     of.directio = clcf->directio;
  79.     of.valid = clcf->open_file_cache_valid;
  80.     of.min_uses = clcf->open_file_cache_min_uses;
  81.     of.errors = clcf->open_file_cache_errors;
  82.     of.events = clcf->open_file_cache_events;

  83.     if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
  84.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  85.     }

  86.     if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
  87.         != NGX_OK)
  88.     {
  89.         switch (of.err) {

  90.         case 0:
  91.             return NGX_HTTP_INTERNAL_SERVER_ERROR;

  92.         case NGX_ENOENT:
  93.         case NGX_ENOTDIR:
  94.         case NGX_ENAMETOOLONG:

  95.             level = NGX_LOG_ERR;
  96.             rc = NGX_HTTP_NOT_FOUND;
  97.             break;

  98.         case NGX_EACCES:
  99. #if (NGX_HAVE_OPENAT)
  100.         case NGX_EMLINK:
  101.         case NGX_ELOOP:
  102. #endif

  103.             level = NGX_LOG_ERR;
  104.             rc = NGX_HTTP_FORBIDDEN;
  105.             break;

  106.         default:

  107.             level = NGX_LOG_CRIT;
  108.             rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
  109.             break;
  110.         }

  111.         if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
  112.             ngx_log_error(level, log, of.err,
  113.                           "%s \"%s\" failed", of.failed, path.data);
  114.         }

  115.         return rc;
  116.     }

  117.     if (!of.is_file) {

  118.         if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
  119.             ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  120.                           ngx_close_file_n " \"%s\" failed", path.data);
  121.         }

  122.         return NGX_DECLINED;
  123.     }

  124.     r->root_tested = !r->error_page;

  125.     start = 0;
  126.     len = of.size;
  127.     i = 1;

  128.     if (r->args.len) {

  129.         if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) {

  130.             start = ngx_atoof(value.data, value.len);

  131.             if (start == NGX_ERROR || start >= len) {
  132.                 start = 0;
  133.             }

  134.             if (start) {
  135.                 len = sizeof(ngx_flv_header) - 1 + len - start;
  136.                 i = 0;
  137.             }
  138.         }
  139.     }

  140.     log->action = "sending flv to client";

  141.     r->headers_out.status = NGX_HTTP_OK;
  142.     r->headers_out.content_length_n = len;
  143.     r->headers_out.last_modified_time = of.mtime;

  144.     if (ngx_http_set_etag(r) != NGX_OK) {
  145.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  146.     }

  147.     if (ngx_http_set_content_type(r) != NGX_OK) {
  148.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  149.     }

  150.     if (i == 0) {
  151.         b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
  152.         if (b == NULL) {
  153.             return NGX_HTTP_INTERNAL_SERVER_ERROR;
  154.         }

  155.         b->pos = ngx_flv_header;
  156.         b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1;
  157.         b->memory = 1;

  158.         out[0].buf = b;
  159.         out[0].next = &out[1];
  160.     }


  161.     b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
  162.     if (b == NULL) {
  163.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  164.     }

  165.     b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
  166.     if (b->file == NULL) {
  167.         return NGX_HTTP_INTERNAL_SERVER_ERROR;
  168.     }

  169.     r->allow_ranges = 1;

  170.     rc = ngx_http_send_header(r);

  171.     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
  172.         return rc;
  173.     }

  174.     b->file_pos = start;
  175.     b->file_last = of.size;

  176.     b->in_file = b->file_last ? 1: 0;
  177.     b->last_buf = (r == r->main) ? 1 : 0;
  178.     b->last_in_chain = 1;

  179.     b->file->fd = of.fd;
  180.     b->file->name = path;
  181.     b->file->log = log;
  182.     b->file->directio = of.is_directio;

  183.     out[1].buf = b;
  184.     out[1].next = NULL;

  185.     return ngx_http_output_filter(r, &out[i]);
  186. }


  187. static char *
  188. ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  189. {
  190.     ngx_http_core_loc_conf_t  *clcf;

  191.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
  192.     clcf->handler = ngx_http_flv_handler;

  193.     return NGX_CONF_OK;
  194. }