Annotation of embedaddon/nginx/src/http/modules/ngx_http_flv_module.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7: #include <ngx_config.h>
! 8: #include <ngx_core.h>
! 9: #include <ngx_http.h>
! 10:
! 11:
! 12: static char *ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
! 13:
! 14: static ngx_command_t ngx_http_flv_commands[] = {
! 15:
! 16: { ngx_string("flv"),
! 17: NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
! 18: ngx_http_flv,
! 19: 0,
! 20: 0,
! 21: NULL },
! 22:
! 23: ngx_null_command
! 24: };
! 25:
! 26:
! 27: static u_char ngx_flv_header[] = "FLV\x1\x5\0\0\0\x9\0\0\0\0";
! 28:
! 29:
! 30: static ngx_http_module_t ngx_http_flv_module_ctx = {
! 31: NULL, /* preconfiguration */
! 32: NULL, /* postconfiguration */
! 33:
! 34: NULL, /* create main configuration */
! 35: NULL, /* init main configuration */
! 36:
! 37: NULL, /* create server configuration */
! 38: NULL, /* merge server configuration */
! 39:
! 40: NULL, /* create location configuration */
! 41: NULL /* merge location configuration */
! 42: };
! 43:
! 44:
! 45: ngx_module_t ngx_http_flv_module = {
! 46: NGX_MODULE_V1,
! 47: &ngx_http_flv_module_ctx, /* module context */
! 48: ngx_http_flv_commands, /* module directives */
! 49: NGX_HTTP_MODULE, /* module type */
! 50: NULL, /* init master */
! 51: NULL, /* init module */
! 52: NULL, /* init process */
! 53: NULL, /* init thread */
! 54: NULL, /* exit thread */
! 55: NULL, /* exit process */
! 56: NULL, /* exit master */
! 57: NGX_MODULE_V1_PADDING
! 58: };
! 59:
! 60:
! 61: static ngx_int_t
! 62: ngx_http_flv_handler(ngx_http_request_t *r)
! 63: {
! 64: u_char *last;
! 65: off_t start, len;
! 66: size_t root;
! 67: ngx_int_t rc;
! 68: ngx_uint_t level, i;
! 69: ngx_str_t path, value;
! 70: ngx_log_t *log;
! 71: ngx_buf_t *b;
! 72: ngx_chain_t out[2];
! 73: ngx_open_file_info_t of;
! 74: ngx_http_core_loc_conf_t *clcf;
! 75:
! 76: if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
! 77: return NGX_HTTP_NOT_ALLOWED;
! 78: }
! 79:
! 80: if (r->uri.data[r->uri.len - 1] == '/') {
! 81: return NGX_DECLINED;
! 82: }
! 83:
! 84: rc = ngx_http_discard_request_body(r);
! 85:
! 86: if (rc != NGX_OK) {
! 87: return rc;
! 88: }
! 89:
! 90: last = ngx_http_map_uri_to_path(r, &path, &root, 0);
! 91: if (last == NULL) {
! 92: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 93: }
! 94:
! 95: log = r->connection->log;
! 96:
! 97: path.len = last - path.data;
! 98:
! 99: ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
! 100: "http flv filename: \"%V\"", &path);
! 101:
! 102: clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
! 103:
! 104: ngx_memzero(&of, sizeof(ngx_open_file_info_t));
! 105:
! 106: of.read_ahead = clcf->read_ahead;
! 107: of.directio = clcf->directio;
! 108: of.valid = clcf->open_file_cache_valid;
! 109: of.min_uses = clcf->open_file_cache_min_uses;
! 110: of.errors = clcf->open_file_cache_errors;
! 111: of.events = clcf->open_file_cache_events;
! 112:
! 113: if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
! 114: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 115: }
! 116:
! 117: if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
! 118: != NGX_OK)
! 119: {
! 120: switch (of.err) {
! 121:
! 122: case 0:
! 123: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 124:
! 125: case NGX_ENOENT:
! 126: case NGX_ENOTDIR:
! 127: case NGX_ENAMETOOLONG:
! 128:
! 129: level = NGX_LOG_ERR;
! 130: rc = NGX_HTTP_NOT_FOUND;
! 131: break;
! 132:
! 133: case NGX_EACCES:
! 134: #if (NGX_HAVE_OPENAT)
! 135: case NGX_EMLINK:
! 136: case NGX_ELOOP:
! 137: #endif
! 138:
! 139: level = NGX_LOG_ERR;
! 140: rc = NGX_HTTP_FORBIDDEN;
! 141: break;
! 142:
! 143: default:
! 144:
! 145: level = NGX_LOG_CRIT;
! 146: rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
! 147: break;
! 148: }
! 149:
! 150: if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
! 151: ngx_log_error(level, log, of.err,
! 152: "%s \"%s\" failed", of.failed, path.data);
! 153: }
! 154:
! 155: return rc;
! 156: }
! 157:
! 158: if (!of.is_file) {
! 159:
! 160: if (ngx_close_file(of.fd) == NGX_FILE_ERROR) {
! 161: ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
! 162: ngx_close_file_n " \"%s\" failed", path.data);
! 163: }
! 164:
! 165: return NGX_DECLINED;
! 166: }
! 167:
! 168: r->root_tested = !r->error_page;
! 169:
! 170: start = 0;
! 171: len = of.size;
! 172: i = 1;
! 173:
! 174: if (r->args.len) {
! 175:
! 176: if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) {
! 177:
! 178: start = ngx_atoof(value.data, value.len);
! 179:
! 180: if (start == NGX_ERROR || start >= len) {
! 181: start = 0;
! 182: }
! 183:
! 184: if (start) {
! 185: len = sizeof(ngx_flv_header) - 1 + len - start;
! 186: i = 0;
! 187: }
! 188: }
! 189: }
! 190:
! 191: log->action = "sending flv to client";
! 192:
! 193: r->headers_out.status = NGX_HTTP_OK;
! 194: r->headers_out.content_length_n = len;
! 195: r->headers_out.last_modified_time = of.mtime;
! 196:
! 197: if (ngx_http_set_etag(r) != NGX_OK) {
! 198: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 199: }
! 200:
! 201: if (ngx_http_set_content_type(r) != NGX_OK) {
! 202: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 203: }
! 204:
! 205: if (i == 0) {
! 206: b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
! 207: if (b == NULL) {
! 208: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 209: }
! 210:
! 211: b->pos = ngx_flv_header;
! 212: b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1;
! 213: b->memory = 1;
! 214:
! 215: out[0].buf = b;
! 216: out[0].next = &out[1];
! 217: }
! 218:
! 219:
! 220: b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
! 221: if (b == NULL) {
! 222: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 223: }
! 224:
! 225: b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
! 226: if (b->file == NULL) {
! 227: return NGX_HTTP_INTERNAL_SERVER_ERROR;
! 228: }
! 229:
! 230: r->allow_ranges = 1;
! 231:
! 232: rc = ngx_http_send_header(r);
! 233:
! 234: if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
! 235: return rc;
! 236: }
! 237:
! 238: b->file_pos = start;
! 239: b->file_last = of.size;
! 240:
! 241: b->in_file = b->file_last ? 1: 0;
! 242: b->last_buf = (r == r->main) ? 1 : 0;
! 243: b->last_in_chain = 1;
! 244:
! 245: b->file->fd = of.fd;
! 246: b->file->name = path;
! 247: b->file->log = log;
! 248: b->file->directio = of.is_directio;
! 249:
! 250: out[1].buf = b;
! 251: out[1].next = NULL;
! 252:
! 253: return ngx_http_output_filter(r, &out[i]);
! 254: }
! 255:
! 256:
! 257: static char *
! 258: ngx_http_flv(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
! 259: {
! 260: ngx_http_core_loc_conf_t *clcf;
! 261:
! 262: clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
! 263: clcf->handler = ngx_http_flv_handler;
! 264:
! 265: return NGX_CONF_OK;
! 266: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>