From 3f083851446d5d3fa012800cdee5be23bd5541b7 Mon Sep 17 00:00:00 2001 From: Roman Arutyunyan Date: Wed, 12 Sep 2012 14:58:31 +0400 Subject: [PATCH] added common evaluation code --- ngx_rtmp_eval.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++ ngx_rtmp_eval.h | 37 ++++++++++ 2 files changed, 221 insertions(+) create mode 100644 ngx_rtmp_eval.c create mode 100644 ngx_rtmp_eval.h diff --git a/ngx_rtmp_eval.c b/ngx_rtmp_eval.c new file mode 100644 index 0000000..f940e02 --- /dev/null +++ b/ngx_rtmp_eval.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2012 Roman Arutyunyan + */ + + +#include "ngx_rtmp_eval.h" + + +#define NGX_RTMP_EVAL_BUFLEN 16 + + +static void +ngx_rtmp_eval_session_str(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e, + ngx_str_t *ret) +{ + *ret = *(ngx_str_t *) ((u_char *) s + e->offset); +} + + +static void +ngx_rtmp_eval_connection_str(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e, + ngx_str_t *ret) +{ + *ret = *(ngx_str_t *) ((u_char *) s->connection + e->offset); +} + + +ngx_rtmp_eval_t ngx_rtmp_eval_session[] = { + + { ngx_string("app"), + ngx_rtmp_eval_session_str, + offsetof(ngx_rtmp_session_t, app) }, + + { ngx_string("flashver"), + ngx_rtmp_eval_session_str, + offsetof(ngx_rtmp_session_t, flashver) }, + + { ngx_string("swfurl"), + ngx_rtmp_eval_session_str, + offsetof(ngx_rtmp_session_t, swf_url) }, + + { ngx_string("tcurl"), + ngx_rtmp_eval_session_str, + offsetof(ngx_rtmp_session_t, tc_url) }, + + { ngx_string("pageurl"), + ngx_rtmp_eval_session_str, + offsetof(ngx_rtmp_session_t, page_url) }, + + { ngx_string("addr"), + ngx_rtmp_eval_connection_str, + offsetof(ngx_connection_t, addr_text) }, + + ngx_rtmp_null_eval +}; + + +static void +ngx_rtmp_eval_append(ngx_rtmp_session_t *s, ngx_buf_t *b, + void *data, size_t len) +{ + size_t buf_len; + + if (b->last + len > b->end) { + buf_len = 2 * (b->last - b->pos) + len; + + b->start = ngx_palloc(s->connection->pool, buf_len); + if (b->start == NULL) { + return; + } + + b->last = ngx_cpymem(b->start, b->pos, b->last - b->pos); + b->pos = b->start; + b->end = b->start + buf_len; + } + + b->last = ngx_cpymem(b->last, data, len); +} + + +static void +ngx_rtmp_eval_append_var(ngx_rtmp_session_t *s, ngx_buf_t *b, + ngx_rtmp_eval_t *e, ngx_str_t *name) +{ + ngx_uint_t k; + ngx_str_t v; + + for (k = 0; e->handler; ++k, ++e) { + if (e->name.len == name->len && + ngx_memcmp(e->name.data, name->data, name->len) == 0) + { + e->handler(s, e, &v); + ngx_rtmp_eval_append(s, b, v.data, v.len); + } + } +} + + +ngx_int_t +ngx_rtmp_eval(ngx_rtmp_session_t *s, ngx_str_t *in, ngx_rtmp_eval_t *e, + ngx_str_t *out) +{ + u_char c, *p;; + ngx_str_t name; + ngx_buf_t b; + ngx_uint_t n; + + enum { + NORMAL, + ESCAPE, + NAME, + SNAME + } state = NORMAL; + + b.pos = b.last = b.start = ngx_palloc(s->connection->pool, + NGX_RTMP_EVAL_BUFLEN); + if (b.pos == NULL) { + return NGX_ERROR; + } + + b.end = b.pos + NGX_RTMP_EVAL_BUFLEN; + + for (n = 0; n < in->len; ++n) { + p = &in->data[n]; + c = *p; + + switch (state) { + case SNAME: + if (c != '}') { + continue; + } + + name.len = p - name.data; + ngx_rtmp_eval_append_var(s, &b, e, &name); + + state = NORMAL; + + continue; + + case NAME: + if (c == '{' && name.data == p) { + ++name.data; + state = SNAME; + continue; + } + if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + continue; + } + + name.len = p - name.data; + ngx_rtmp_eval_append_var(s, &b, e, &name); + + case NORMAL: + switch (c) { + case '$': + name.data = p + 1; + state = NAME; + continue; + case '\\': + state = ESCAPE; + continue; + } + + case ESCAPE: + ngx_rtmp_eval_append(s, &b, &c, 1); + state = NORMAL; + break; + + } + } + + if (state == NAME) { + name.len = p - name.data; + ngx_rtmp_eval_append_var(s, &b, e, &name); + } + + c = 0; + ngx_rtmp_eval_append(s, &b, &c, 1); + + out->data = b.pos; + out->len = b.last - b.pos - 1; + + return NGX_OK; +} diff --git a/ngx_rtmp_eval.h b/ngx_rtmp_eval.h new file mode 100644 index 0000000..fae2502 --- /dev/null +++ b/ngx_rtmp_eval.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2012 Roman Arutyunyan + */ + + +#ifndef _NGX_RTMP_EVAL_H_INCLUDED_ +#define _NGX_RTMP_EVAL_H_INCLUDED_ + +#include "ngx_rtmp.h" + + +typedef struct ngx_rtmp_eval_s ngx_rtmp_eval_t; + + +typedef void (* ngx_rtmp_eval_pt)(ngx_rtmp_session_t *s, ngx_rtmp_eval_t *e, + ngx_str_t *ret); + + +struct ngx_rtmp_eval_s { + ngx_str_t name; + ngx_rtmp_eval_pt handler; + ngx_uint_t offset; +}; + + +#define ngx_rtmp_null_eval { ngx_null_string, NULL, 0 } + + +/* standard session eval variables */ +extern ngx_rtmp_eval_t ngx_rtmp_eval_session[]; + + +ngx_int_t ngx_rtmp_eval(ngx_rtmp_session_t *s, ngx_str_t *in, + ngx_rtmp_eval_t *e, ngx_str_t *out); + + +#endif /* _NGX_RTMP_EVAL_H_INCLUDED_ */