You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
3.8 KiB
198 lines
3.8 KiB
5 years ago
|
|
||
|
/*
|
||
|
* Copyright (C) Roman Arutyunyan
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <ngx_config.h>
|
||
|
#include <ngx_core.h>
|
||
|
#include <nginx.h>
|
||
|
#include "ngx_rtmp_proxy_protocol.h"
|
||
|
|
||
|
|
||
|
static void ngx_rtmp_proxy_protocol_recv(ngx_event_t *rev);
|
||
|
|
||
|
|
||
|
void
|
||
|
ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *s)
|
||
|
{
|
||
|
ngx_event_t *rev;
|
||
|
ngx_connection_t *c;
|
||
|
|
||
|
c = s->connection;
|
||
|
rev = c->read;
|
||
|
rev->handler = ngx_rtmp_proxy_protocol_recv;
|
||
|
|
||
|
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
|
||
|
"proxy_protocol: start");
|
||
|
|
||
|
if (rev->ready) {
|
||
|
/* the deferred accept(), rtsig, aio, iocp */
|
||
|
|
||
|
if (ngx_use_accept_mutex) {
|
||
|
ngx_post_event(rev, &ngx_posted_events);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
rev->handler(rev);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ngx_add_timer(rev, s->timeout);
|
||
|
|
||
|
if (ngx_handle_read_event(rev, 0) != NGX_OK) {
|
||
|
ngx_rtmp_finalize_session(s);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
static void
|
||
|
ngx_rtmp_proxy_protocol_recv(ngx_event_t *rev)
|
||
|
{
|
||
|
u_char buf[107], *p, *pp, *text;
|
||
|
size_t len;
|
||
|
ssize_t n;
|
||
|
ngx_err_t err;
|
||
|
ngx_int_t i;
|
||
|
ngx_addr_t addr;
|
||
|
ngx_connection_t *c;
|
||
|
ngx_rtmp_session_t *s;
|
||
|
|
||
|
c = rev->data;
|
||
|
s = c->data;
|
||
|
|
||
|
if (c->destroyed) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (rev->timedout) {
|
||
|
ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
|
||
|
"proxy_protocol: recv: client timed out");
|
||
|
c->timedout = 1;
|
||
|
ngx_rtmp_finalize_session(s);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (rev->timer_set) {
|
||
|
ngx_del_timer(rev);
|
||
|
}
|
||
|
|
||
|
n = recv(c->fd, (char *) buf, sizeof(buf), MSG_PEEK);
|
||
|
|
||
|
err = ngx_socket_errno;
|
||
|
|
||
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0, "recv(): %d", n);
|
||
|
|
||
|
if (n == -1) {
|
||
|
|
||
|
if (err == NGX_EAGAIN) {
|
||
|
ngx_add_timer(rev, s->timeout);
|
||
|
|
||
|
if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
|
||
|
ngx_rtmp_finalize_session(s);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ngx_rtmp_finalize_session(s);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
p = buf;
|
||
|
|
||
|
if (n <= 8 && ngx_strncmp(p, "PROXY ", 6) != 0) {
|
||
|
goto bad_header;
|
||
|
}
|
||
|
|
||
|
n -= 6;
|
||
|
p += 6;
|
||
|
|
||
|
ngx_memzero(&addr, sizeof(ngx_addr_t));
|
||
|
|
||
|
if (n >= 7 && ngx_strncmp(p, "UNKNOWN", 7) == 0) {
|
||
|
n -= 7;
|
||
|
p += 7;
|
||
|
goto skip;
|
||
|
}
|
||
|
|
||
|
if (n < 5 || ngx_strncmp(p, "TCP", 3) != 0
|
||
|
|| (p[3] != '4' && p[3] != '6') || p[4] != ' ')
|
||
|
{
|
||
|
goto bad_header;
|
||
|
}
|
||
|
|
||
|
n -= 5;
|
||
|
p += 5;
|
||
|
|
||
|
pp = ngx_strlchr(p, p + n, ' ');
|
||
|
|
||
|
if (pp == NULL) {
|
||
|
goto bad_header;
|
||
|
}
|
||
|
|
||
|
if (ngx_parse_addr(s->connection->pool, &addr, p, pp - p) != NGX_OK) {
|
||
|
goto bad_header;
|
||
|
}
|
||
|
|
||
|
n -= pp - p;
|
||
|
p = pp;
|
||
|
|
||
|
skip:
|
||
|
|
||
|
for (i = 0; i + 1 < n; i++) {
|
||
|
if (p[i] == CR && p[i + 1] == LF) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (i + 1 >= n) {
|
||
|
goto bad_header;
|
||
|
}
|
||
|
|
||
|
n = p - buf + i + 2;
|
||
|
|
||
|
if (c->recv(c, buf, n) != n) {
|
||
|
goto failed;
|
||
|
}
|
||
|
|
||
|
if (addr.socklen) {
|
||
|
text = ngx_palloc(s->connection->pool, NGX_SOCKADDR_STRLEN);
|
||
|
|
||
|
if (text == NULL) {
|
||
|
goto failed;
|
||
|
}
|
||
|
|
||
|
len = ngx_sock_ntop(addr.sockaddr,
|
||
|
#if (nginx_version >= 1005003)
|
||
|
addr.socklen,
|
||
|
#endif
|
||
|
text, NGX_SOCKADDR_STRLEN, 0);
|
||
|
if (len == 0) {
|
||
|
goto failed;
|
||
|
}
|
||
|
|
||
|
c->sockaddr = addr.sockaddr;
|
||
|
c->socklen = addr.socklen;
|
||
|
c->addr_text.data = text;
|
||
|
c->addr_text.len = len;
|
||
|
|
||
|
ngx_log_debug1(NGX_LOG_DEBUG_RTMP, c->log, 0,
|
||
|
"proxy_protocol: remote_addr:'%V'", &c->addr_text);
|
||
|
}
|
||
|
|
||
|
ngx_rtmp_handshake(s);
|
||
|
|
||
|
return;
|
||
|
|
||
|
bad_header:
|
||
|
|
||
|
ngx_log_error(NGX_LOG_INFO, c->log, 0, "proxy_protocol: bad header");
|
||
|
|
||
|
failed:
|
||
|
|
||
|
ngx_rtmp_finalize_session(s);
|
||
|
}
|