static void ngx_rtmp_eval_append_var(void *ctx, ngx_buf_t *b, ngx_rtmp_eval_t **e, ngx_str_t *name, ngx_log_t *log) { ngx_uint_t k; ngx_str_t v; ngx_rtmp_eval_t *ee; for (; *e; ++e) { for (k = 0, ee = *e; ee->handler; ++k, ++ee) { if (ee->name.len == name->len && ngx_memcmp(ee->name.data, name->data, name->len) == 0) { ee->handler(ctx, ee, &v); ngx_rtmp_eval_append(b, v.data, v.len, log); } } } }
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; ngx_rtmp_eval_t *ee; for (; *e; ++e) { for (k = 0, ee = *e; ee->handler; ++k, ++ee) { if (ee->name.len == name->len && ngx_memcmp(ee->name.data, name->data, name->len) == 0) { ee->handler(s, ee, &v); ngx_rtmp_eval_append(s, b, v.data, v.len); } } } }
ngx_int_t ngx_rtmp_eval(void *ctx, ngx_str_t *in, ngx_rtmp_eval_t **e, ngx_str_t *out, ngx_log_t *log) { 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_alloc(NGX_RTMP_EVAL_BUFLEN, log); if (b.pos == NULL) { return NGX_ERROR; } b.end = b.pos + NGX_RTMP_EVAL_BUFLEN; name.data = NULL; 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(ctx, &b, e, &name, log); 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(ctx, &b, e, &name, log); case NORMAL: switch (c) { case '$': name.data = p + 1; state = NAME; continue; case '\\': state = ESCAPE; continue; } case ESCAPE: ngx_rtmp_eval_append(&b, &c, 1, log); state = NORMAL; break; } } if (state == NAME) { p = &in->data[n]; name.len = p - name.data; ngx_rtmp_eval_append_var(ctx, &b, e, &name, log); } c = 0; ngx_rtmp_eval_append(&b, &c, 1, log); out->data = b.pos; out->len = b.last - b.pos - 1; return NGX_OK; }