comparison src/http/modules/ngx_http_flv_module.c @ 332:3a91bfeffaba NGINX_0_6_10

nginx 0.6.10 *) Feature: the "open_file_cache", "open_file_cache_retest", and "open_file_cache_errors" directives. *) Bugfix: socket leak; bug appeared in 0.6.7. *) Bugfix: a charset set by the "charset" directive was not appended to the "Content-Type" header set by $r->send_http_header(). *) Bugfix: a segmentation fault might occur in worker process if /dev/poll method was used.
author Igor Sysoev <http://sysoev.ru>
date Mon, 03 Sep 2007 00:00:00 +0400
parents 9fc4ab6673f9
children 10cc350ed8a1
comparison
equal deleted inserted replaced
331:b69d5e83bf82 332:3a91bfeffaba
58 58
59 59
60 static ngx_int_t 60 static ngx_int_t
61 ngx_http_flv_handler(ngx_http_request_t *r) 61 ngx_http_flv_handler(ngx_http_request_t *r)
62 { 62 {
63 u_char *p; 63 u_char *p, *last;
64 off_t start, len; 64 off_t start, len;
65 size_t root; 65 size_t root;
66 ngx_fd_t fd; 66 ngx_fd_t fd;
67 ngx_int_t rc; 67 ngx_int_t rc;
68 ngx_uint_t level, i; 68 ngx_uint_t level, i;
69 ngx_str_t path; 69 ngx_str_t path;
70 ngx_err_t err;
71 ngx_log_t *log; 70 ngx_log_t *log;
72 ngx_buf_t *b; 71 ngx_buf_t *b;
73 ngx_chain_t out[2]; 72 ngx_chain_t out[2];
74 ngx_file_info_t fi; 73 ngx_open_file_info_t of;
75 ngx_pool_cleanup_t *cln;
76 ngx_pool_cleanup_file_t *clnf;
77 ngx_http_core_loc_conf_t *clcf; 74 ngx_http_core_loc_conf_t *clcf;
78 75
79 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { 76 if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
80 return NGX_HTTP_NOT_ALLOWED; 77 return NGX_HTTP_NOT_ALLOWED;
81 } 78 }
93 90
94 if (rc != NGX_OK) { 91 if (rc != NGX_OK) {
95 return rc; 92 return rc;
96 } 93 }
97 94
98 if (ngx_http_map_uri_to_path(r, &path, &root, 0) == NULL) { 95 last = ngx_http_map_uri_to_path(r, &path, &root, 0);
96 if (last == NULL) {
99 return NGX_HTTP_INTERNAL_SERVER_ERROR; 97 return NGX_HTTP_INTERNAL_SERVER_ERROR;
100 } 98 }
101 99
102 log = r->connection->log; 100 log = r->connection->log;
103 101
102 path.len = last - path.data;
103
104 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, 104 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
105 "http flv filename: \"%s\"", path.data); 105 "http flv filename: \"%V\"", &path);
106 106
107 cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t)); 107 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
108 if (cln == NULL) { 108
109 return NGX_HTTP_INTERNAL_SERVER_ERROR; 109 of.test_dir = 0;
110 } 110 of.retest = clcf->open_file_cache_retest;
111 111 of.errors = clcf->open_file_cache_errors;
112 fd = ngx_open_file(path.data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0); 112 of.events = clcf->open_file_cache_events;
113 113
114 if (fd == NGX_INVALID_FILE) { 114 rc = ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool);
115 err = ngx_errno; 115
116 116 if (rc == NGX_ERROR) {
117 if (err == NGX_ENOENT 117
118 || err == NGX_ENOTDIR 118 switch (of.err) {
119 || err == NGX_ENAMETOOLONG) 119
120 { 120 case 0:
121 return NGX_HTTP_INTERNAL_SERVER_ERROR;
122
123 case NGX_ENOENT:
124 case NGX_ENOTDIR:
125 case NGX_ENAMETOOLONG:
126
121 level = NGX_LOG_ERR; 127 level = NGX_LOG_ERR;
122 rc = NGX_HTTP_NOT_FOUND; 128 rc = NGX_HTTP_NOT_FOUND;
123 129 break;
124 } else if (err == NGX_EACCES) { 130
131 case NGX_EACCES:
132
125 level = NGX_LOG_ERR; 133 level = NGX_LOG_ERR;
126 rc = NGX_HTTP_FORBIDDEN; 134 rc = NGX_HTTP_FORBIDDEN;
127 135 break;
128 } else { 136
137 default:
138
129 level = NGX_LOG_CRIT; 139 level = NGX_LOG_CRIT;
130 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; 140 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
131 } 141 break;
132 142 }
133 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
134 143
135 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { 144 if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) {
136 ngx_log_error(level, log, err, 145 ngx_log_error(level, log, of.err,
137 ngx_open_file_n " \"%s\" failed", path.data); 146 ngx_open_file_n " \"%s\" failed", path.data);
138 } 147 }
139 148
140 return rc; 149 return rc;
141 } 150 }
142 151
143 if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) { 152 fd = of.fd;
144 ngx_log_error(NGX_LOG_CRIT, log, ngx_errno, 153
145 ngx_fd_info_n " \"%s\" failed", path.data); 154 if (!of.is_file) {
146 155
147 if (ngx_close_file(fd) == NGX_FILE_ERROR) { 156 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
148 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, 157 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
149 ngx_close_file_n " \"%s\" failed", path.data); 158 ngx_close_file_n " \"%s\" failed", path.data);
150 } 159 }
151 160
152 return NGX_HTTP_INTERNAL_SERVER_ERROR;
153 }
154
155 if (!ngx_is_file(&fi)) {
156
157 if (ngx_close_file(fd) == NGX_FILE_ERROR) {
158 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
159 ngx_close_file_n " \"%s\" failed", path.data);
160 }
161
162 return NGX_DECLINED; 161 return NGX_DECLINED;
163 } 162 }
164 163
165 start = 0; 164 start = 0;
166 len = ngx_file_size(&fi); 165 len = of.size;
167 i = 1; 166 i = 1;
168 167
169 if (r->args.len) { 168 if (r->args.len) {
170 p = (u_char *) ngx_strstr(r->args.data, "start="); 169 p = (u_char *) ngx_strstr(r->args.data, "start=");
171 170
185 } 184 }
186 } 185 }
187 186
188 log->action = "sending flv to client"; 187 log->action = "sending flv to client";
189 188
190 cln->handler = ngx_pool_cleanup_file;
191 clnf = cln->data;
192
193 clnf->fd = fd;
194 clnf->name = path.data;
195 clnf->log = r->pool->log;
196
197 r->headers_out.status = NGX_HTTP_OK; 189 r->headers_out.status = NGX_HTTP_OK;
198 r->headers_out.content_length_n = len; 190 r->headers_out.content_length_n = len;
199 r->headers_out.last_modified_time = ngx_file_mtime(&fi); 191 r->headers_out.last_modified_time = of.mtime;
200 192
201 if (ngx_http_set_content_type(r) != NGX_OK) { 193 if (ngx_http_set_content_type(r) != NGX_OK) {
202 return NGX_HTTP_INTERNAL_SERVER_ERROR; 194 return NGX_HTTP_INTERNAL_SERVER_ERROR;
203 } 195 }
204 196
235 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { 227 if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
236 return rc; 228 return rc;
237 } 229 }
238 230
239 b->file_pos = start; 231 b->file_pos = start;
240 b->file_last = ngx_file_size(&fi); 232 b->file_last = of.size;
241 233
242 b->in_file = b->file_last ? 1: 0; 234 b->in_file = b->file_last ? 1: 0;
243 b->last_buf = 1; 235 b->last_buf = 1;
244 b->last_in_chain = 1; 236 b->last_in_chain = 1;
245 237