added proxy protocol support

This commit is contained in:
Roman Arutyunyan 2014-03-31 08:52:20 +04:00
parent 876de488b8
commit 4e780909b9
7 changed files with 211 additions and 1 deletions

2
config
View File

@ -44,6 +44,7 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
$ngx_addon_dir/ngx_rtmp_relay_module.h \
$ngx_addon_dir/ngx_rtmp_streams.h \
$ngx_addon_dir/ngx_rtmp_bitop.h \
$ngx_addon_dir/ngx_rtmp_proxy_protocol.h \
$ngx_addon_dir/hls/ngx_rtmp_mpegts.h \
$ngx_addon_dir/dash/ngx_rtmp_mp4.h \
"
@ -79,6 +80,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
$ngx_addon_dir/ngx_rtmp_log_module.c \
$ngx_addon_dir/ngx_rtmp_limit_module.c \
$ngx_addon_dir/ngx_rtmp_bitop.c \
$ngx_addon_dir/ngx_rtmp_proxy_protocol.c \
$ngx_addon_dir/hls/ngx_rtmp_hls_module.c \
$ngx_addon_dir/dash/ngx_rtmp_dash_module.c \
$ngx_addon_dir/hls/ngx_rtmp_mpegts.c \

View File

@ -544,6 +544,7 @@ found:
addr->bind = listen->bind;
addr->wildcard = listen->wildcard;
addr->so_keepalive = listen->so_keepalive;
addr->proxy_protocol = listen->proxy_protocol;
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
addr->tcp_keepidle = listen->tcp_keepidle;
addr->tcp_keepintvl = listen->tcp_keepintvl;
@ -702,6 +703,7 @@ ngx_rtmp_add_addrs(ngx_conf_t *cf, ngx_rtmp_port_t *mport,
addrs[i].conf.addr_text.len = len;
addrs[i].conf.addr_text.data = p;
addrs[i].conf.proxy_protocol = addr->proxy_protocol;
}
return NGX_OK;
@ -751,6 +753,7 @@ ngx_rtmp_add_addrs6(ngx_conf_t *cf, ngx_rtmp_port_t *mport,
addrs6[i].conf.addr_text.len = len;
addrs6[i].conf.addr_text.data = p;
addrs6[i].conf.proxy_protocol = addr->proxy_protocol;
}
return NGX_OK;

View File

@ -43,6 +43,7 @@ typedef struct {
unsigned ipv6only:2;
#endif
unsigned so_keepalive:2;
unsigned proxy_protocol:1;
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
int tcp_keepidle;
int tcp_keepintvl;
@ -54,6 +55,7 @@ typedef struct {
typedef struct {
ngx_rtmp_conf_ctx_t *ctx;
ngx_str_t addr_text;
unsigned proxy_protocol:1;
} ngx_rtmp_addr_conf_t;
typedef struct {
@ -97,6 +99,7 @@ typedef struct {
unsigned ipv6only:2;
#endif
unsigned so_keepalive:2;
unsigned proxy_protocol:1;
#if (NGX_HAVE_KEEPALIVE_TUNABLE)
int tcp_keepidle;
int tcp_keepintvl;

View File

@ -719,6 +719,11 @@ ngx_rtmp_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
#endif
}
if (ngx_strcmp(value[i].data, "proxy_protocol") == 0) {
ls->proxy_protocol = 1;
continue;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"the invalid \"%V\" parameter", &value[i]);
return NGX_CONF_ERROR;

View File

@ -7,6 +7,7 @@
#include <ngx_config.h>
#include <ngx_core.h>
#include "ngx_rtmp.h"
#include "ngx_rtmp_proxy_protocol.h"
static void ngx_rtmp_close_connection(ngx_connection_t *c);
@ -130,7 +131,12 @@ ngx_rtmp_init_connection(ngx_connection_t *c)
s->auto_pushed = unix_socket;
ngx_rtmp_handshake(s);
if (addr_conf->proxy_protocol) {
ngx_rtmp_proxy_protocol(s);
} else {
ngx_rtmp_handshake(s);
}
}

172
ngx_rtmp_proxy_protocol.c Normal file
View File

@ -0,0 +1,172 @@
/*
* Copyright (C) Roman Arutyunyan
*/
#include <ngx_config.h>
#include <ngx_core.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_connection_t *c;
c = s->connection;
c->read->handler = ngx_rtmp_proxy_protocol_recv;
ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0,
"proxy_protocol: start");
ngx_rtmp_proxy_protocol_recv(c->read);
}
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, buf, sizeof(buf), MSG_PEEK);
err = ngx_socket_errno;
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, addr.socklen, 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);
}

19
ngx_rtmp_proxy_protocol.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright (C) Roman Arutyunyan
*/
#ifndef _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_
#define _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
#include "ngx_rtmp.h"
void ngx_rtmp_proxy_protocol(ngx_rtmp_session_t *c);
#endif /* _NGX_RTMP_PROXY_PROTOCOL_H_INCLUDED_ */