/* Find the value of the URL parameter with the specified name */ static ngx_int_t find_arg(ngx_pool_t *pool, ngx_str_t name, ngx_str_t args, ngx_str_t *value) { u_char *start = args.data; u_char *end = start + args.len; size_t name_len = name.len; while (start < end) { if (start + name_len + 1 < end) { /* if enough room for "name=" */ if ((ngx_strncmp(name.data, start, name_len) == 0) && (start[name_len] == (u_char)'=')) { u_char *arg_end; u_char *unescaped; start += (name_len + 1); /* skip past the "name=" */ arg_end = ngx_strlchr(start, end, (u_char)'&'); /* find terminating '&' */ if (arg_end == NULL) { arg_end = end; } unescaped = (u_char *)ngx_palloc(pool, arg_end - start); value->data = unescaped; ngx_unescape_uri(&unescaped, &start, arg_end - start, NGX_UNESCAPE_URI); value->len = unescaped - value->data; return NGX_OK; } } start = ngx_strlchr(start, end, (u_char)'&'); if (start == NULL) { break; } start++; } value->data = NULL; value->len = 0; return NGX_DECLINED; }
static char *ngx_tcp_set_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_tcp_core_srv_conf_t *cscf = conf; if (cf->args->nelts < 3){ return NGX_CONF_ERROR; } if(cscf->redirect == NULL){ cscf->redirect = ngx_array_create(cf->pool,8,sizeof(ngx_redirect_t)); if(cscf->redirect == NULL){ ngx_conf_log_error(NGX_LOG_ALERT, cf, 0, "TCP redirect, can not get array for redirect"); return NGX_CONF_ERROR; } } ngx_redirect_t* t = ngx_array_push(cscf->redirect); if(t == NULL){ ngx_conf_log_error(NGX_LOG_ALERT, cf, 0, "TCP redirect, can not get elt for redirect"); return NGX_CONF_ERROR; } ngx_str_t *value=cf->args->elts; u_char *p,*q; p=value[1].data; q=value[1].data + value[1].len; if(ngx_strlchr(p,q,'[')!= NULL){ //with format of ipv6 #if(NGX_HAVE_INET6) struct in6_addr anyaddr=IN6ADDR_ANY_INIT; //TODO: need test for ipv6 if(ngx_parse_host_port6(cf->log, &value[1],&(t->host6),&(t->port),anyaddr)!=NGX_CONF_OK) return NGX_CONF_ERROR; #endif }else{ if(ngx_parse_host_port(cf->log, &value[1],&(t->host),&(t->port),INADDR_ANY)!=NGX_CONF_OK) return NGX_CONF_ERROR; } p = value[2].data; q = value[2].data + value[2].len; if(ngx_strlchr(p,q,'[')!= NULL){ //with format of ipv6 #if (NGX_HAVE_INET6) struct in6_addr loopaddr=IN6ADDR_LOOPBACK_INIT; if(ngx_parse_host_port6(cf->log, &value[2],&(t->redirect_host6),&(t->redirect_port),loopaddr)!=NGX_CONF_OK) return NGX_CONF_ERROR; #endif }else{ if(ngx_parse_host_port(cf->log, &value[2],&(t->redirect_host),&(t->redirect_port),INADDR_LOOPBACK)!=NGX_CONF_OK) return NGX_CONF_ERROR; } ngx_conf_log_error(NGX_LOG_DEBUG, cf, 0, "TCP set redirect %s -> %s",value[1].data,value[2].data); return NGX_CONF_OK; }
ngx_int_t nchan_parse_compound_msgid(nchan_msg_id_t *id, ngx_str_t *str, ngx_int_t expected_tag_count) { //parse url-unescaped compound msgid u_char *split, *last; ngx_int_t time; uint8_t len; //"<msg_time>:<msg_tag>" last = str->data + str->len; if((split = ngx_strlchr(str->data, last, ':')) != NULL) { len = 1; } else { len = 0; //placate dumb GCC warning } if(split) { time = ngx_atoi(str->data, split - str->data); split += len; if(time != NGX_ERROR) { id->time = time; return nchan_parse_msg_tag(split, last, id, expected_tag_count); } else { return NGX_ERROR; } } return NGX_DECLINED; }
void ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args) { u_char ch, *p, *last; p = uri->data; last = p + uri->len; args->len = 0; while (p < last) { ch = *p++; if (ch == '?') { args->len = last - p; args->data = p; uri->len = p - 1 - uri->data; if (ngx_strlchr(p, last, '\0') != NULL) { r->zero_in_uri = 1; } return; } if (ch == '\0') { r->zero_in_uri = 1; continue; } } }
static ngx_int_t nchan_subscriber_get_msg_id(ngx_http_request_t *r, nchan_msg_id_t *id) { static ngx_str_t last_event_id_header = ngx_string("Last-Event-ID"); ngx_str_t *last_event_id; ngx_str_t *if_none_match; if((last_event_id = nchan_get_header_value(r, last_event_id_header)) != NULL) { u_char *split, *last; ngx_int_t time; //"<msg_time>:<msg_tag>" last = last_event_id->data + last_event_id->len; if((split = ngx_strlchr(last_event_id->data, last, ':')) != NULL) { time = ngx_atoi(last_event_id->data, split - last_event_id->data); split++; if(time != NGX_ERROR) { id->time = time; nchan_parse_msg_tag(split, last, id); return NGX_OK; } } } if_none_match = nchan_subscriber_get_etag(r); id->time=(r->headers_in.if_modified_since == NULL) ? 0 : ngx_http_parse_time(r->headers_in.if_modified_since->value.data, r->headers_in.if_modified_since->value.len); if(if_none_match==NULL) { int i; for(i=0; i< NCHAN_MULTITAG_MAX; i++) { id->tag[i]=0; } id->tagcount=1; } else { nchan_parse_msg_tag(if_none_match->data, if_none_match->data + if_none_match->len, id); } return NGX_OK; }
ngx_int_t ngx_http_request_parser_get_method_params(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value) { u_char *p, *last; if (r->args.len == 0) { return NGX_DECLINED; } p = r->args.data; last = p + r->args.len; for (/* void */; p < last; p++) { if (p + len > last) { return NGX_DECLINED; } if (ngx_strncasecmp(p, name, len) != 0) { continue; } if (p == r->args.data || *(p - 1) == '&' || (p + len) == last || *(p + len) == '&' || *(p + len) == '=') { if ((p + len) < last && *(p + len) == '=') { value->data = p + len + 1; p = ngx_strlchr(p, last, '&'); if (p == NULL) { p = r->args.data + r->args.len; } value->len = p - value->data; } else { value->len = 0; } return NGX_OK; } } return NGX_DECLINED; }
static ngx_int_t ngx_captcha_get_request_parameter_value( ngx_http_request_t *r, u_char *buffer, ngx_str_t *name, ngx_str_t *value ) { u_char *p = NULL; u_char *v = NULL; u_char *last = NULL; value->data = NULL; value->len = 0; if ( buffer == NULL ) { return NGX_ERROR; } ngx_log_debug( NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "searching for %s (%d)", name->data, name->len ); last = buffer + ngx_strlen( buffer ) ; for ( p = buffer; p < last; p++ ) { // we need '=' after name, so drop one char from last p = ngx_strlcasestrn(p, last - 1, name->data, name->len - 1); if ( p == NULL ) { return NGX_ERROR; } if ((p == buffer || *(p - 1) == '&') && *(p + name->len) == '=') { size_t val_len = 0; size_t dst_len = 0; v = p + name->len + 1; p = ngx_strlchr(p, last, '&'); if (p == NULL) { p = last; } val_len = (p-v); /* Allocate buffer for request parameter value */ value->data = ngx_pcalloc(r->pool, val_len + 1); if ( value->data == NULL ) { ngx_log_debug( NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "--->> BOOOM" ); return NGX_ERROR; } /* Unescape parameter value */ dst_len = (size_t)value->data; ngx_unescape_uri(&value->data, &v, val_len, NGX_UNESCAPE_URI); dst_len = (size_t) value->data - dst_len; *(value->data) = '\0'; value->data -= dst_len; value->len = dst_len; return NGX_OK; } } return ( (value->data == NULL) ? NGX_ERROR: NGX_OK ); }
static ngx_http_google_ctx_t * ngx_http_google_create_ctx(ngx_http_request_t * r) { ngx_http_google_loc_conf_t * glcf; glcf = ngx_http_get_module_loc_conf(r, ngx_http_google_filter_module); ngx_http_google_ctx_t * ctx; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_google_ctx_t)); if (!ctx) return NULL; ctx->host = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->host) return NULL; ctx->pass = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->pass) return NULL; ctx->arg = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->arg) return NULL; ctx->domain = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->domain) return NULL; ctx->uri = &r->unparsed_uri; ctx->host = &r->headers_in.host->value; ctx->lang = &glcf->language; ctx->type = ngx_http_google_type_main; ngx_str_t domain = *ctx->host; u_char * last = domain.data + domain.len, * find; if ((find = ngx_strlchr(domain.data, last, ':'))) { domain.len = find - domain.data; } ctx->domain->len = domain.len + 1; ctx->domain->data = ngx_pcalloc(r->pool, ctx->domain->len); if (!ctx->domain->data) return NULL; ngx_snprintf(ctx->domain->data, ctx->domain->len, ".%V", &domain); if (ngx_inet_addr(domain.data, domain.len) != INADDR_NONE) { ctx->domain->data++; ctx->domain->len --; } // default language if (!ctx->lang->len) { ngx_str_set(ctx->lang, "zh-CN"); } ctx->robots = (ctx->uri->len == 11 && !ngx_strncmp(ctx->uri->data, "/robots.txt", 11)); #if (NGX_HTTP_SSL) ngx_http_ssl_srv_conf_t * sscf; sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (sscf->enable == 1) ctx->ssl = 1; #endif return ctx; }
static ngx_http_upstream_srv_conf_t * ngx_http_lua_upstream_find_upstream(lua_State *L, ngx_str_t *host) { u_char *port; size_t len; ngx_int_t n; ngx_uint_t i; ngx_http_upstream_srv_conf_t **uscfp, *uscf; ngx_http_upstream_main_conf_t *umcf; umcf = ngx_http_lua_upstream_get_upstream_main_conf(L); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; if (uscf->host.len == host->len && ngx_memcmp(uscf->host.data, host->data, host->len) == 0) { return uscf; } } port = ngx_strlchr(host->data, host->data + host->len, ':'); if (port) { port++; n = ngx_atoi(port, host->data + host->len - port); if (n < 1 || n > 65535) { return NULL; } /* try harder with port */ len = port - host->data - 1; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; if (uscf->port && uscf->port == n && uscf->host.len == len && ngx_memcmp(uscf->host.data, host->data, len) == 0) { return uscf; } } } return NULL; }
static njs_ret_t ngx_http_js_ext_next_arg(njs_vm_t *vm, njs_value_t *value, void *obj, void *next) { ngx_str_t **e = next; size_t len; u_char *p, *start, *end; ngx_str_t *entry; entry = *e; if (entry->len == 0) { return NJS_DONE; } start = entry->data; end = start + entry->len; p = ngx_strlchr(start, end, '='); if (p == NULL) { return NJS_ERROR; } len = p - start; p++; p = ngx_strlchr(p, end, '&'); if (p) { entry->data = &p[1]; entry->len = end - entry->data; } else { entry->len = 0; } return njs_string_create(vm, value, start, len, 0); }
ngx_array_t * ngx_http_dyups_parse_path(ngx_http_request_t *r) { u_char *p, *last, *end; ngx_str_t *str; ngx_array_t *array; array = ngx_array_create(r->pool, 8, sizeof(ngx_str_t)); if (array == NULL) { return NULL; } p = r->uri.data + 1; last = r->uri.data + r->uri.len; while(p < last) { end = ngx_strlchr(p, last, '/'); str = ngx_array_push(array); if (str == NULL) { return NULL; } if (end) { str->data = p; str->len = end - p; } else { str->data = p; str->len = last - p; } p += str->len + 1; } #if NGX_DEBUG ngx_str_t *arg; ngx_uint_t i; arg = array->elts; for (i = 0; i < array->nelts; i++) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "res[%i]:%V", i, &arg[i]); } #endif return array; }
static void http_field(void *data, const signed char *field, size_t flen, const signed char *value, size_t vlen) { u_char *last; ngx_str_t *str; ngx_tcp_session_t *s = data; ngx_tcp_websocket_ctx_t *wctx; wctx = ngx_tcp_get_module_ctx(s, ngx_tcp_websocket_module); #if (NGX_DEBUG) ngx_str_t str_field, str_value; str_field.data = (u_char *) field; str_field.len = flen; str_value.data = (u_char *) value; str_value.len = vlen; ngx_log_debug2(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "%V: %V", &str_field, &str_value); #endif if ((flen == (sizeof("Host") - 1)) && (ngx_strncasecmp((u_char *)"Host", (u_char *)field, flen) == 0)) { /*trim the port part from host string*/ last = ngx_strlchr((u_char *)value, (u_char *)value + vlen, (u_char)':'); if (last) { vlen = last - (u_char *)value; } str = &wctx->host; str->len = vlen; str->data = ngx_palloc(s->connection->pool, vlen); if (str->data == NULL) { return; } ngx_memcpy(str->data, (u_char *)value, vlen); ngx_log_debug1(NGX_LOG_DEBUG_TCP, s->connection->log, 0, "true host: %V", str); } }
void ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args) { u_char *p, *last; last = uri->data + uri->len; p = ngx_strlchr(uri->data, last, '?'); if (p) { uri->len = p - uri->data; p++; args->len = last - p; args->data = p; } else { args->len = 0; } }
static ngx_int_t nchan_parse_compound_msgid(nchan_msg_id_t *id, ngx_str_t *str){ u_char *split, *last; ngx_int_t time; //"<msg_time>:<msg_tag>" last = str->data + str->len; if((split = ngx_strlchr(str->data, last, ':')) != NULL) { time = ngx_atoi(str->data, split - str->data); split++; if(time != NGX_ERROR) { id->time = time; nchan_parse_msg_tag(split, last, id); return NGX_OK; } else { return NGX_ERROR; } } return NGX_DECLINED; }
ngx_int_t ngx_http_tfs_parse_tair_server_addr_info(ngx_http_tfs_tair_server_addr_info_t *info, u_char *addr, uint32_t len, void *pool, uint8_t shared_memory) { u_char *temp, *p; ssize_t info_size; ngx_int_t i; p = addr; for (i = 0; i < NGX_HTTP_TFS_TAIR_SERVER_ADDR_PART_COUNT; i++) { temp = ngx_strlchr(p, p + len, ';'); if (temp == NULL) { return NGX_ERROR; } info_size = temp - p; if (shared_memory) { info->server[i].data = ngx_slab_alloc_locked((ngx_slab_pool_t *)pool, info_size); } else { info->server[i].data = ngx_pcalloc((ngx_pool_t *)pool, info_size); } if (info->server[i].data == NULL) { return NGX_ERROR; } info->server[i].len = info_size; memcpy(info->server[i].data, p, info_size); p += info_size + 1; len -= (info_size + 1); if (len <= 0) { return NGX_ERROR; } } info->area = ngx_atoi(p, len); if (info->area == NGX_ERROR) { return NGX_ERROR; } return NGX_OK; }
void ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args) { syslog(LOG_INFO, "[%s:%s:%d]\n", __FILE__, __func__, __LINE__); u_char *p, *last; last = uri->data + uri->len; p = ngx_strlchr(uri->data, last, '?'); if (p) { uri->len = p - uri->data; p++; args->len = last - p; args->data = p; } else { args->len = 0; } }
ngx_int_t ngx_http_arg(ngx_http_request_t *r, u_char *name, size_t len, ngx_str_t *value) { syslog(LOG_INFO, "[%s:%s:%d]\n", __FILE__, __func__, __LINE__); u_char *p, *last; if (r->args.len == 0) { return NGX_DECLINED; } p = r->args.data; last = p + r->args.len; for ( /* void */ ; p < last; p++) { /* we need '=' after name, so drop one char from last */ p = ngx_strlcasestrn(p, last - 1, name, len - 1); if (p == NULL) { return NGX_DECLINED; } if ((p == r->args.data || *(p - 1) == '&') && *(p + len) == '=') { value->data = p + len + 1; p = ngx_strlchr(p, last, '&'); if (p == NULL) { p = r->args.data + r->args.len; } value->len = p - value->data; return NGX_OK; } } return NGX_DECLINED; }
static ngx_int_t ngx_http_google_request_parse_redirect(ngx_http_request_t * r, ngx_http_google_ctx_t * ctx) { ctx->uri->data += 2; ctx->uri->len -= 2; u_char * last = ctx->uri->data + ctx->uri->len; u_char * slash = ngx_strlchr(ctx->uri->data, last, '/'); ctx->pass->data = ctx->uri->data; ctx->pass->len = ctx->uri->len; if (slash) { ctx->uri->data = slash; ctx->uri->len = last - slash; ctx->pass->len = slash - ctx->pass->data; } return NGX_OK; }
//获取get值 static ngx_int_t ngx_http_get_value(ngx_http_request_t *r, ngx_str_t *get_var, ngx_array_t *get_values) { ngx_str_t *v, arg; u_char *p, *pos, *last; v = ngx_array_push(get_values); if (v == NULL) { return NGX_ERROR; } arg.len = get_var->len + 1; arg.data = ngx_palloc(r->pool, arg.len + 1); ngx_memzero(arg.data, sizeof(arg.data)); pos = ngx_copy(arg.data, get_var->data, get_var->len); last = ngx_copy(pos, "=", strlen("=")); p = ngx_strlcasestrn(r->args.data, r->args.data + r->args.len - 1, arg.data, arg.len); pos = p + arg.len; //*(r->args.data + r->args.len - 1) = '\0'; //fprintf(stderr, "%s", r->args.data); last = ngx_strlchr(pos, r->args.data + r->args.len - 1, '&'); v->data = ngx_palloc(r->pool, last - pos); v->len = last - pos; last = ngx_copy(v->data, pos, v->len); fprintf(stderr, "test%s", "lijianwei"); return NGX_OK; }
static ngx_int_t ngx_lua_http_btt_parse_args(ngx_http_request_t *r, ngx_btt_ctx_t *ctx) { size_t nlen, vlen; u_char *p, *last, *name, *val, *dst, *src; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua http btt parse args"); if (r->args.len == 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid uri \"%V\"", &r->args); return NGX_ERROR; } p = r->args.data; last = p + r->args.len; for ( /* void */ ; p < last; p++) { name = p; p = ngx_strlchr(p, last, '&'); if (p == NULL) { p = last; } val = ngx_strlchr(name, p, '='); if (val == NULL) { val = p; } nlen = val - name; vlen = (++val < p) ? p - val : 0; dst = ngx_pnalloc(r->pool, vlen); if (dst == NULL) { return NGX_ERROR; } src = val; val = dst; ngx_unescape_uri(&dst, &src, vlen, 0); vlen = dst - val; ngx_log_debug4(NGX_LOG_ALERT, r->connection->log, 0, "%*s=%*s", nlen, name, vlen, val); /* * BT Client: * * BitComet: localip, natmapped, port_type * NetTransport: supportcrypto * uTorrent: corrupt * XunLei: ip */ switch (nlen) { case 2: if (ngx_strncmp(name, "ip", nlen) == 0) { ctx->internal_ip = ngx_inet_addr(val, vlen); if (ctx->internal_ip == INADDR_NONE) { goto invalid; } break; } break; case 3: if (ngx_strncmp(name, "key", nlen) == 0) { ngx_memcpy(ctx->key, val, vlen); break; } break; case 4: if (ngx_strncmp(name, "port", nlen) == 0) { ctx->internal_port = (in_port_t) ngx_atoi(val, vlen); if (ctx->internal_port == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "left", nlen) == 0) { ctx->left = ngx_atoof(val, vlen); if (ctx->left == NGX_ERROR) { goto invalid; } break; } break; case 5: if (ngx_strncmp(name, "event", nlen) == 0) { if (ngx_strncmp(val, "none", sizeof("none") - 1) == 0) { ctx->event = NGX_BTT_EVENT_NONE; } else if (ngx_strncmp(val, "completed", sizeof("completed") - 1) == 0) { ctx->event = NGX_BTT_EVENT_COMPLETED; } else if (ngx_strncmp(val, "started", sizeof("started") - 1) == 0) { ctx->event = NGX_BTT_EVENT_STARTED; } else if (ngx_strncmp(val, "stopped", sizeof("stopped") - 1) == 0) { ctx->event = NGX_BTT_EVENT_STOPPED; } else { goto invalid; } break; } break; case 7: if (ngx_strncmp(name, "peer_id", nlen) == 0) { ngx_memcpy(ctx->peer_id, val, vlen); break; } if (ngx_strncmp(name, "localip", nlen) == 0) { ctx->internal_ip = ngx_inet_addr(val, vlen); if (ctx->internal_ip == INADDR_NONE) { goto invalid; } break; } if (ngx_strncmp(name, "numwant", nlen) == 0) { ctx->numwant = ngx_atoi(val, vlen); if (ctx->numwant == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "compact", nlen) == 0) { ctx->compact = ngx_atoi(val, vlen); if (ctx->compact == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "corrupt", nlen) == 0) { ctx->corrupt = ngx_atoi(val, vlen); if (ctx->corrupt == NGX_ERROR) { goto invalid; } break; } break; case 8: if (ngx_strncmp(name, "uploaded", nlen) == 0) { ctx->uploaded = ngx_atoof(val, vlen); if (ctx->uploaded == NGX_ERROR) { goto invalid; } break; } break; case 9: if (ngx_strncmp(name, "info_hash ", nlen) == 0) { ngx_memcpy(ctx->info_hash, val, vlen); break; } if (ngx_strncmp(name, "natmapped ", nlen) == 0) { ctx->natmapped = ngx_atoi(val, vlen); if (ctx->natmapped == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "port_type", nlen) == 0) { ngx_memcpy(ctx->port_type, val, vlen); break; } break; case 10: if (ngx_strncmp(name, "downloaded", nlen) == 0) { ctx->downloaded = ngx_atoof(val, vlen); if (ctx->downloaded == NGX_ERROR) { goto invalid; } break; } if (ngx_strncmp(name, "no_peer_id ", nlen) == 0) { ctx->no_peer_id = ngx_atoi(val, vlen); if (ctx->no_peer_id == NGX_ERROR) { goto invalid; } break; } break; case 13: if (ngx_strncmp(name, "supportcrypto", nlen) == 0) { ctx->supportcrypto = ngx_atoi(val, vlen); if (ctx->supportcrypto == NGX_ERROR) { goto invalid; } break; } break; default: break; } } return NGX_OK; invalid: ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "invalid value \"%*s\" of the key \"%*s\"", nlen, name, vlen, val); return NGX_ERROR; }
static char * ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_core_srv_conf_t *cscf = conf; size_t len, off; in_port_t port; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; struct sockaddr *sa; ngx_mail_listen_t *ls; ngx_mail_module_t *module; struct sockaddr_in *sin; ngx_mail_core_main_conf_t *cmcf; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.listen = 1; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in \"%V\" of the \"listen\" directive", u.err, &u.url); } return NGX_CONF_ERROR; } cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); ls = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { sa = (struct sockaddr *) ls[i].sockaddr; if (sa->sa_family != u.family) { continue; } switch (sa->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: off = offsetof(struct sockaddr_in6, sin6_addr); len = 16; sin6 = (struct sockaddr_in6 *) sa; port = ntohs(sin6->sin6_port); break; #endif #if (NGX_HAVE_UNIX_DOMAIN) case AF_UNIX: off = offsetof(struct sockaddr_un, sun_path); len = sizeof(((struct sockaddr_un *) sa)->sun_path); port = 0; break; #endif default: /* AF_INET */ off = offsetof(struct sockaddr_in, sin_addr); len = 4; sin = (struct sockaddr_in *) sa; port = ntohs(sin->sin_port); break; } if (ngx_memcmp(ls[i].sockaddr + off, u.sockaddr + off, len) != 0) { continue; } if (port != u.port) { continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; } ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_mail_listen_t)); ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) ls->ipv6only = 1; #endif if (cscf->protocol == NULL) { for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_MAIL_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->protocol == NULL) { continue; } for (i = 0; module->protocol->port[i]; i++) { if (module->protocol->port[i] == u.port) { cscf->protocol = module->protocol; break; } } } } for (i = 2; i < cf->args->nelts; i++) { if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; } if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) struct sockaddr *sa; u_char buf[NGX_SOCKADDR_STRLEN]; sa = (struct sockaddr *) ls->sockaddr; if (sa->sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { ls->ipv6only = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid ipv6only flags \"%s\"", &value[i].data[9]); return NGX_CONF_ERROR; } ls->bind = 1; } else { len = ngx_sock_ntop(sa, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ipv6only is not supported " "on addr \"%*s\", ignored", len, buf); } continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "bind ipv6only is not supported " "on this platform"); return NGX_CONF_ERROR; #endif } if (ngx_strcmp(value[i].data, "ssl") == 0) { #if (NGX_MAIL_SSL) ls->ssl = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"ssl\" parameter requires " "ngx_mail_ssl_module"); return NGX_CONF_ERROR; #endif } if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[i].data[13], "on") == 0) { ls->so_keepalive = 1; } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { ls->so_keepalive = 2; } else { #if (NGX_HAVE_KEEPALIVE_TUNABLE) u_char *p, *end; ngx_str_t s; end = value[i].data + value[i].len; s.data = value[i].data + 13; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepidle = ngx_parse_time(&s, 1); if (ls->tcp_keepidle == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepintvl = ngx_parse_time(&s, 1); if (ls->tcp_keepintvl == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; if (s.data < end) { s.len = end - s.data; ls->tcp_keepcnt = ngx_atoi(s.data, s.len); if (ls->tcp_keepcnt == NGX_ERROR) { goto invalid_so_keepalive; } } if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0 && ls->tcp_keepcnt == 0) { goto invalid_so_keepalive; } ls->so_keepalive = 1; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"so_keepalive\" parameter accepts " "only \"on\" or \"off\" on this platform"); return NGX_CONF_ERROR; #endif } ls->bind = 1; continue; #if (NGX_HAVE_KEEPALIVE_TUNABLE) invalid_so_keepalive: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid so_keepalive value: \"%s\"", &value[i].data[13]); return NGX_CONF_ERROR; #endif } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log) { ngx_fd_t fd; #if !(NGX_HAVE_OPENAT) fd = ngx_open_file(name->data, mode, create, access); if (fd == NGX_INVALID_FILE) { of->err = ngx_errno; of->failed = ngx_open_file_n; return NGX_INVALID_FILE; } return fd; #else u_char *p, *cp, *end; ngx_fd_t at_fd; ngx_str_t at_name; if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) { fd = ngx_open_file(name->data, mode, create, access); if (fd == NGX_INVALID_FILE) { of->err = ngx_errno; of->failed = ngx_open_file_n; return NGX_INVALID_FILE; } return fd; } p = name->data; end = p + name->len; at_name = *name; if (of->disable_symlinks_from) { cp = p + of->disable_symlinks_from; *cp = '\0'; at_fd = ngx_open_file(p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); *cp = '/'; if (at_fd == NGX_INVALID_FILE) { of->err = ngx_errno; of->failed = ngx_open_file_n; return NGX_INVALID_FILE; } at_name.len = of->disable_symlinks_from; p = cp + 1; } else if (*p == '/') { at_fd = ngx_open_file("/", NGX_FILE_SEARCH|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); if (at_fd == NGX_INVALID_FILE) { of->err = ngx_errno; of->failed = ngx_openat_file_n; return NGX_INVALID_FILE; } at_name.len = 1; p++; } else { at_fd = NGX_AT_FDCWD; } for ( ;; ) { cp = ngx_strlchr(p, end, '/'); if (cp == NULL) { break; } if (cp == p) { p++; continue; } *cp = '\0'; if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) { fd = ngx_openat_file_owner(at_fd, p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0, log); } else { fd = ngx_openat_file(at_fd, p, NGX_FILE_SEARCH|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW, NGX_FILE_OPEN, 0); } *cp = '/'; if (fd == NGX_INVALID_FILE) { of->err = ngx_errno; of->failed = ngx_openat_file_n; goto failed; } if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%V\" failed", &at_name); } p = cp + 1; at_fd = fd; at_name.len = cp - at_name.data; } if (p == end) { /* * If pathname ends with a trailing slash, assume the last path * component is a directory and reopen it with requested flags; * if not, fail with ENOTDIR as per POSIX. * * We cannot rely on O_DIRECTORY in the loop above to check * that the last path component is a directory because * O_DIRECTORY doesn't work on FreeBSD 8. Fortunately, by * reopening a directory, we don't depend on it at all. */ fd = ngx_openat_file(at_fd, ".", mode, create, access); goto done; } if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER && !(create & (NGX_FILE_CREATE_OR_OPEN|NGX_FILE_TRUNCATE))) { fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log); } else { fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access); } done: if (fd == NGX_INVALID_FILE) { of->err = ngx_errno; of->failed = ngx_openat_file_n; } failed: if (at_fd != NGX_AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%V\" failed", &at_name); } return fd; #endif }
static char * ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_mail_core_srv_conf_t *cscf = conf; ngx_str_t *value; ngx_url_t u; ngx_uint_t i, m; ngx_mail_listen_t *ls; ngx_mail_module_t *module; ngx_mail_core_main_conf_t *cmcf; cscf->listen = 1; value = cf->args->elts; ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.listen = 1; if (ngx_parse_url(cf->pool, &u) != NGX_OK) { if (u.err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in \"%V\" of the \"listen\" directive", u.err, &u.url); } return NGX_CONF_ERROR; } cmcf = ngx_mail_conf_get_module_main_conf(cf, ngx_mail_core_module); ls = cmcf->listen.elts; for (i = 0; i < cmcf->listen.nelts; i++) { if (ngx_cmp_sockaddr(&ls[i].sockaddr.sockaddr, ls[i].socklen, (struct sockaddr *) &u.sockaddr, u.socklen, 1) != NGX_OK) { continue; } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate \"%V\" address and port pair", &u.url); return NGX_CONF_ERROR; } ls = ngx_array_push(&cmcf->listen); if (ls == NULL) { return NGX_CONF_ERROR; } ngx_memzero(ls, sizeof(ngx_mail_listen_t)); ngx_memcpy(&ls->sockaddr.sockaddr, &u.sockaddr, u.socklen); ls->socklen = u.socklen; ls->backlog = NGX_LISTEN_BACKLOG; ls->wildcard = u.wildcard; ls->ctx = cf->ctx; #if (NGX_HAVE_INET6) ls->ipv6only = 1; #endif if (cscf->protocol == NULL) { for (m = 0; cf->cycle->modules[m]; m++) { if (cf->cycle->modules[m]->type != NGX_MAIL_MODULE) { continue; } module = cf->cycle->modules[m]->ctx; if (module->protocol == NULL) { continue; } for (i = 0; module->protocol->port[i]; i++) { if (module->protocol->port[i] == u.port) { cscf->protocol = module->protocol; break; } } } } for (i = 2; i < cf->args->nelts; i++) { if (ngx_strcmp(value[i].data, "bind") == 0) { ls->bind = 1; continue; } if (ngx_strncmp(value[i].data, "backlog=", 8) == 0) { ls->backlog = ngx_atoi(value[i].data + 8, value[i].len - 8); ls->bind = 1; if (ls->backlog == NGX_ERROR || ls->backlog == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid backlog \"%V\"", &value[i]); return NGX_CONF_ERROR; } continue; } if (ngx_strncmp(value[i].data, "ipv6only=o", 10) == 0) { #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY) size_t len; u_char buf[NGX_SOCKADDR_STRLEN]; if (ls->sockaddr.sockaddr.sa_family == AF_INET6) { if (ngx_strcmp(&value[i].data[10], "n") == 0) { ls->ipv6only = 1; } else if (ngx_strcmp(&value[i].data[10], "ff") == 0) { ls->ipv6only = 0; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid ipv6only flags \"%s\"", &value[i].data[9]); return NGX_CONF_ERROR; } ls->bind = 1; } else { len = ngx_sock_ntop(&ls->sockaddr.sockaddr, ls->socklen, buf, NGX_SOCKADDR_STRLEN, 1); ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "ipv6only is not supported " "on addr \"%*s\", ignored", len, buf); } continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "bind ipv6only is not supported " "on this platform"); return NGX_CONF_ERROR; #endif } if (ngx_strcmp(value[i].data, "ssl") == 0) { #if (NGX_MAIL_SSL) ls->ssl = 1; continue; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"ssl\" parameter requires " "ngx_mail_ssl_module"); return NGX_CONF_ERROR; #endif } if (ngx_strncmp(value[i].data, "so_keepalive=", 13) == 0) { if (ngx_strcmp(&value[i].data[13], "on") == 0) { ls->so_keepalive = 1; } else if (ngx_strcmp(&value[i].data[13], "off") == 0) { ls->so_keepalive = 2; } else { #if (NGX_HAVE_KEEPALIVE_TUNABLE) u_char *p, *end; ngx_str_t s; end = value[i].data + value[i].len; s.data = value[i].data + 13; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepidle = ngx_parse_time(&s, 1); if (ls->tcp_keepidle == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; p = ngx_strlchr(s.data, end, ':'); if (p == NULL) { p = end; } if (p > s.data) { s.len = p - s.data; ls->tcp_keepintvl = ngx_parse_time(&s, 1); if (ls->tcp_keepintvl == (time_t) NGX_ERROR) { goto invalid_so_keepalive; } } s.data = (p < end) ? (p + 1) : end; if (s.data < end) { s.len = end - s.data; ls->tcp_keepcnt = ngx_atoi(s.data, s.len); if (ls->tcp_keepcnt == NGX_ERROR) { goto invalid_so_keepalive; } } if (ls->tcp_keepidle == 0 && ls->tcp_keepintvl == 0 && ls->tcp_keepcnt == 0) { goto invalid_so_keepalive; } ls->so_keepalive = 1; #else ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the \"so_keepalive\" parameter accepts " "only \"on\" or \"off\" on this platform"); return NGX_CONF_ERROR; #endif } ls->bind = 1; continue; #if (NGX_HAVE_KEEPALIVE_TUNABLE) invalid_so_keepalive: ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid so_keepalive value: \"%s\"", &value[i].data[13]); return NGX_CONF_ERROR; #endif } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the invalid \"%V\" parameter", &value[i]); return NGX_CONF_ERROR; } return NGX_CONF_OK; }
/* fork from ngx_http_arg. * read argument(s) with name arg_name and length arg_len into value variable, * if multi flag is set, multi arguments with name arg_name will be read and * stored in an ngx_array_t struct, this can be operated by directives in * array-var-nginx-module */ static ngx_int_t ngx_http_form_input_arg(ngx_http_request_t *r, u_char *arg_name, size_t arg_len, ngx_str_t *value, ngx_flag_t multi) { u_char *p, *v, *last, *buf; ngx_chain_t *cl; size_t len = 0; ngx_array_t *array = NULL; ngx_str_t *s; ngx_buf_t *b; if (multi) { array = ngx_array_create(r->pool, 1, sizeof(ngx_str_t)); if (array == NULL) { return NGX_ERROR; } value->data = (u_char *)array; value->len = sizeof(ngx_array_t); } else { ngx_str_set(value, ""); } /* we read data from r->request_body->bufs */ if (r->request_body == NULL || r->request_body->bufs == NULL) { dd("empty rb or empty rb bufs"); return NGX_OK; } if (r->request_body->bufs->next != NULL) { /* more than one buffer...we should copy the data out... */ len = 0; for (cl = r->request_body->bufs; cl; cl = cl->next) { b = cl->buf; if (b->in_file) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "form-input: in-file buffer found. aborted. " "consider increasing your client_body_buffer_size " "setting"); return NGX_OK; } len += b->last - b->pos; } dd("len=%d", (int) len); if (len == 0) { return NGX_OK; } buf = ngx_palloc(r->pool, len); if (buf == NULL) { return NGX_ERROR; } p = buf; last = p + len; for (cl = r->request_body->bufs; cl; cl = cl->next) { p = ngx_copy(p, cl->buf->pos, cl->buf->last - cl->buf->pos); } dd("p - buf = %d, last - buf = %d", (int) (p - buf), (int) (last - buf)); dd("copied buf (len %d): %.*s", (int) len, (int) len, buf); } else { dd("XXX one buffer only"); b = r->request_body->bufs->buf; if (ngx_buf_size(b) == 0) { return NGX_OK; } buf = b->pos; last = b->last; } for (p = buf; p < last; p++) { /* we need '=' after name, so drop one char from last */ p = ngx_strlcasestrn(p, last - 1, arg_name, arg_len - 1); if (p == NULL) { return NGX_OK; } dd("found argument name, offset: %d", (int) (p - buf)); if ((p == buf || *(p - 1) == '&') && *(p + arg_len) == '=') { v = p + arg_len + 1; dd("v = %d...", (int) (v - buf)); dd("buf now (len %d): %.*s", (int) (last - v), (int) (last - v), v); p = ngx_strlchr(v, last, '&'); if (p == NULL) { dd("& not found, pointing it to last..."); p = last; } else { dd("found &, pointing it to %d...", (int) (p - buf)); } if (multi) { s = ngx_array_push(array); if (s == NULL) { return NGX_ERROR; } s->data = v; s->len = p - v; dd("array var:%.*s", (int) s->len, s->data); } else { value->data = v; value->len = p - v; dd("value: [%.*s]", (int) value->len, value->data); return NGX_OK; } } } #if 0 if (multi) { value->data = (u_char *) array; value->len = sizeof(ngx_array_t); } #endif return NGX_OK; }
static char * ngx_rtmp_relay_push_pull(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value, v, n; ngx_rtmp_relay_app_conf_t *racf; ngx_rtmp_relay_target_t *target, **t; ngx_url_t *u; ngx_uint_t i; u_char *p; value = cf->args->elts; racf = ngx_rtmp_conf_get_module_app_conf(cf, ngx_rtmp_relay_module); t = ngx_array_push(value[0].data[3] == 'h' ? &racf->pushes /* push */ : &racf->pulls /* pull */ ); if (t == NULL) { return NGX_CONF_ERROR; } target = ngx_pcalloc(cf->pool, sizeof(*target)); if (target == NULL) { return NGX_CONF_ERROR; } *t = target; target->tag = &ngx_rtmp_relay_module; target->data = target; u = &target->url; u->default_port = 1935; u->uri_part = 1; u->url = value[1]; if (ngx_strncasecmp(u->url.data, (u_char *) "rtmp://", 7) == 0) { u->url.data += 7; u->url.len -= 7; } if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in url \"%V\"", u->err, &u->url); } return NGX_CONF_ERROR; } value += 2; for (i = 2; i < cf->args->nelts; ++i, ++value) { p = ngx_strlchr(value->data, value->data + value->len, '='); if (p == NULL) { return "key=value expected"; } if (p == value->data + value->len - 1) { continue; } n.data = value->data; n.len = p - value->data; v.data = p + 1; v.len = value->data + value->len - p - 1; #define NGX_RTMP_RELAY_STR_PAR(name, var) \ if (n.len == sizeof(#name) - 1 \ && ngx_strncasecmp(n.data, (u_char *)#name, n.len) == 0) \ { \ target->var = v; \ continue; \ } #define NGX_RTMP_RELAY_NUM_PAR(name, var) \ if (n.len == sizeof(#name) - 1 \ && ngx_strncasecmp(n.data, (u_char *)#name, n.len) == 0) \ { \ target->var = ngx_atoi(v.data, v.len); \ continue; \ } NGX_RTMP_RELAY_STR_PAR(app, app); NGX_RTMP_RELAY_STR_PAR(name, name); NGX_RTMP_RELAY_STR_PAR(tcUrl, tc_url); NGX_RTMP_RELAY_STR_PAR(pageUrl, page_url); NGX_RTMP_RELAY_STR_PAR(swfUrl, swf_url); NGX_RTMP_RELAY_STR_PAR(flashVer, flash_ver); NGX_RTMP_RELAY_STR_PAR(playPath, play_path); NGX_RTMP_RELAY_NUM_PAR(live, live); NGX_RTMP_RELAY_NUM_PAR(start, start); NGX_RTMP_RELAY_NUM_PAR(stop, stop); #undef NGX_RTMP_RELAY_STR_PAR #undef NGX_RTMP_RELAY_NUM_PAR return "unsuppored parameter"; } return NGX_CONF_OK; }
static ngx_int_t ngx_rtmp_cmd_connect(ngx_rtmp_session_t *s, ngx_rtmp_connect_t *v) { ngx_rtmp_core_srv_conf_t *cscf; ngx_rtmp_core_app_conf_t **cacfp; ngx_uint_t n; ngx_rtmp_header_t h; u_char *p; static double trans; static double capabilities = NGX_RTMP_CAPABILITIES; static double object_encoding = 0; static ngx_rtmp_amf_elt_t out_obj[] = { { NGX_RTMP_AMF_STRING, ngx_string("fmsVer"), NGX_RTMP_FMS_VERSION, 0 }, { NGX_RTMP_AMF_NUMBER, ngx_string("capabilities"), &capabilities, 0 }, }; static ngx_rtmp_amf_elt_t out_inf[] = { { NGX_RTMP_AMF_STRING, ngx_string("level"), "status", 0 }, { NGX_RTMP_AMF_STRING, ngx_string("code"), "NetConnection.Connect.Success", 0 }, { NGX_RTMP_AMF_STRING, ngx_string("description"), "Connection succeeded.", 0 }, { NGX_RTMP_AMF_NUMBER, ngx_string("objectEncoding"), &object_encoding, 0 } }; static ngx_rtmp_amf_elt_t out_elts[] = { { NGX_RTMP_AMF_STRING, ngx_null_string, "_result", 0 }, { NGX_RTMP_AMF_NUMBER, ngx_null_string, &trans, 0 }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, out_obj, sizeof(out_obj) }, { NGX_RTMP_AMF_OBJECT, ngx_null_string, out_inf, sizeof(out_inf) }, }; if (s->connected) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: duplicate connection"); return NGX_ERROR; } cscf = ngx_rtmp_get_module_srv_conf(s, ngx_rtmp_core_module); ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: app='%s' flashver='%s' swf_url='%s' " "tc_url='%s' page_url='%s' acodecs=%uD vcodecs=%uD " "object_encoding=%ui", v->app, v->flashver, v->swf_url, v->tc_url, v->page_url, (uint32_t)v->acodecs, (uint32_t)v->vcodecs, (ngx_int_t)v->object_encoding); trans = v->trans; /* fill session parameters */ s->connected = 1; ngx_memzero(&h, sizeof(h)); h.csid = NGX_RTMP_CSID_AMF_INI; h.type = NGX_RTMP_MSG_AMF_CMD; #define NGX_RTMP_SET_STRPAR(name) \ s->name.len = ngx_strlen(v->name); \ s->name.data = ngx_palloc(s->connection->pool, s->name.len); \ ngx_memcpy(s->name.data, v->name, s->name.len) NGX_RTMP_SET_STRPAR(app); NGX_RTMP_SET_STRPAR(flashver); NGX_RTMP_SET_STRPAR(swf_url); NGX_RTMP_SET_STRPAR(tc_url); NGX_RTMP_SET_STRPAR(page_url); #undef NGX_RTMP_SET_STRPAR p = ngx_strlchr(s->app.data, s->app.data + s->app.len, '?'); if (p) { s->app.len = (p - s->app.data); } s->acodecs = v->acodecs; s->vcodecs = v->vcodecs; /* find application & set app_conf */ cacfp = cscf->applications.elts; for(n = 0; n < cscf->applications.nelts; ++n, ++cacfp) { if ((*cacfp)->name.len == s->app.len && ngx_strncmp((*cacfp)->name.data, s->app.data, s->app.len) == 0) { /* found app! */ s->app_conf = (*cacfp)->app_conf; break; } } if (s->app_conf == NULL) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "connect: application not found: '%V'", &s->app); return NGX_ERROR; } object_encoding = v->object_encoding; return ngx_rtmp_send_ack_size(s, cscf->ack_window) != NGX_OK || ngx_rtmp_send_bandwidth(s, cscf->ack_window, NGX_RTMP_LIMIT_DYNAMIC) != NGX_OK || ngx_rtmp_send_chunk_size(s, cscf->chunk_size) != NGX_OK || ngx_rtmp_send_amf(s, &h, out_elts, sizeof(out_elts) / sizeof(out_elts[0])) != NGX_OK ? NGX_ERROR : NGX_OK; }
static ngx_rtmp_relay_ctx_t * ngx_rtmp_relay_create_remote_ctx(ngx_rtmp_session_t *s, ngx_str_t* name, ngx_rtmp_relay_target_t *target) { ngx_rtmp_relay_ctx_t *rctx; ngx_rtmp_addr_conf_t *addr_conf; ngx_rtmp_conf_ctx_t *addr_ctx; ngx_rtmp_session_t *rs; ngx_rtmp_relay_app_conf_t *racf; ngx_peer_connection_t *pc; ngx_connection_t *c; ngx_pool_t *pool; ngx_int_t rc; ngx_str_t v, *uri; u_char *first, *last, *p; racf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_relay_module); pool = NULL; pool = ngx_create_pool(4096, racf->log); if (pool == NULL) { return NULL; } rctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_relay_ctx_t)); if (rctx == NULL) { goto clear; } if (ngx_rtmp_relay_copy_str(pool, &rctx->name, name) != NGX_OK || ngx_rtmp_relay_copy_str(pool, &rctx->url, &target->url.url) != NGX_OK) { goto clear; } rctx->tag = target->tag; rctx->data = target->data; #define NGX_RTMP_RELAY_STR_COPY(to, from) \ if (ngx_rtmp_relay_copy_str(pool, &rctx->to, &target->from) != NGX_OK) { \ goto clear; \ } NGX_RTMP_RELAY_STR_COPY(app, app); NGX_RTMP_RELAY_STR_COPY(tc_url, tc_url); NGX_RTMP_RELAY_STR_COPY(page_url, page_url); NGX_RTMP_RELAY_STR_COPY(swf_url, swf_url); NGX_RTMP_RELAY_STR_COPY(flash_ver, flash_ver); NGX_RTMP_RELAY_STR_COPY(play_path, play_path); rctx->live = target->live; rctx->start = target->start; rctx->stop = target->stop; #undef NGX_RTMP_RELAY_STR_COPY if (rctx->app.len == 0 || rctx->play_path.len == 0) { /* parse uri */ uri = &target->url.uri; first = uri->data; last = uri->data + uri->len; if (first != last && *first == '/') { ++first; } if (first != last) { /* deduce app */ p = ngx_strlchr(first, last, '/'); if (rctx->app.len == 0 && first != p) { v.data = first; v.len = p - first; if (ngx_rtmp_relay_copy_str(pool, &rctx->app, &v) != NGX_OK) { goto clear; } } /* deduce play_path */ ++p; if (rctx->play_path.len == 0 && p != last) { v.data = p; v.len = last - p; if (ngx_rtmp_relay_copy_str(pool, &rctx->play_path, &v) != NGX_OK) { goto clear; } } } } rctx->relay = 1; pc = ngx_pcalloc(pool, sizeof(ngx_peer_connection_t)); if (pc == NULL) { goto clear; } /* copy log to keep shared log unchanged */ rctx->log = *racf->log; pc->log = &rctx->log; pc->get = ngx_rtmp_relay_get_peer; pc->free = ngx_rtmp_relay_free_peer; pc->name = &target->url.host; pc->socklen = target->url.socklen; pc->sockaddr = (struct sockaddr *)ngx_palloc(pool, pc->socklen); if (pc->sockaddr == NULL) { goto clear; } ngx_memcpy(pc->sockaddr, &target->url.sockaddr, pc->socklen); rc = ngx_event_connect_peer(pc); if (rc != NGX_OK && rc != NGX_AGAIN ) { ngx_log_debug0(NGX_LOG_DEBUG_RTMP, racf->log, 0, "relay: connection failed"); goto clear; } c = pc->connection; c->pool = pool; c->addr_text = rctx->url; addr_conf = ngx_pcalloc(pool, sizeof(ngx_rtmp_addr_conf_t)); if (addr_conf == NULL) { goto clear; } addr_ctx = ngx_pcalloc(pool, sizeof(ngx_rtmp_conf_ctx_t)); if (addr_ctx == NULL) { goto clear; } addr_conf->ctx = addr_ctx; addr_ctx->main_conf = s->main_conf; addr_ctx->srv_conf = s->srv_conf; ngx_str_set(&addr_conf->addr_text, "ngx-relay"); rs = ngx_rtmp_init_session(c, addr_conf); if (rs == NULL) { /* no need to destroy pool */ return NULL; } rs->app_conf = s->app_conf; rctx->session = rs; ngx_rtmp_set_ctx(rs, rctx, ngx_rtmp_relay_module); ngx_str_set(&rs->flashver, "ngx-local-relay"); ngx_rtmp_client_handshake(rs, 1); return rctx; clear: if (pool) { ngx_destroy_pool(pool); } return NULL; }
static ngx_int_t ngx_stream_proxy_ssl_name(ngx_stream_session_t *s) { u_char *p, *last; ngx_str_t name; ngx_stream_upstream_t *u; ngx_stream_proxy_srv_conf_t *pscf; pscf = ngx_stream_get_module_srv_conf(s, ngx_stream_proxy_module); u = s->upstream; name = pscf->ssl_name; if (name.len == 0) { name = pscf->upstream->host; } if (name.len == 0) { goto done; } /* * ssl name here may contain port, strip it for compatibility * with the http module */ p = name.data; last = name.data + name.len; if (*p == '[') { p = ngx_strlchr(p, last, ']'); if (p == NULL) { p = name.data; } } p = ngx_strlchr(p, last, ':'); if (p != NULL) { name.len = p - name.data; } if (!pscf->ssl_server_name) { goto done; } #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME /* as per RFC 6066, literal IPv4 and IPv6 addresses are not permitted */ if (name.len == 0 || *name.data == '[') { goto done; } if (ngx_inet_addr(name.data, name.len) != INADDR_NONE) { goto done; } /* * SSL_set_tlsext_host_name() needs a null-terminated string, * hence we explicitly null-terminate name here */ p = ngx_pnalloc(s->connection->pool, name.len + 1); if (p == NULL) { return NGX_ERROR; } (void) ngx_cpystrn(p, name.data, name.len + 1); name.data = p; ngx_log_debug1(NGX_LOG_DEBUG_STREAM, s->connection->log, 0, "upstream SSL server name: \"%s\"", name.data); if (SSL_set_tlsext_host_name(u->peer.connection->ssl->connection, name.data) == 0) { ngx_ssl_error(NGX_LOG_ERR, s->connection->log, 0, "SSL_set_tlsext_host_name(\"%s\") failed", name.data); return NGX_ERROR; } #endif done: u->ssl_name = name; return NGX_OK; }
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); }
static ngx_int_t ngx_http_google_response_header_location(ngx_http_request_t * r, ngx_http_google_ctx_t * ctx, ngx_str_t * v) { ngx_http_google_loc_conf_t * glcf; glcf = ngx_http_get_module_loc_conf(r, ngx_http_google_filter_module); u_char * last = v->data + v->len; ngx_uint_t add = 0; if (!ngx_strncasecmp(v->data, (u_char *)"http://", 7)) { add = 7; } else if (!ngx_strncasecmp(v->data, (u_char *)"https://", 8)) { add = 8; } else { return NGX_OK; } ngx_str_t host; host.data = v->data + add; host.len = last - host.data; ngx_str_t uri; uri.data = ngx_strlchr(host.data, last, '/'); if (uri.data) { uri .len = last - uri.data; host.len = uri.data - host.data; } else { uri.len = 0; } if (!ngx_strlcasestrn(host.data, host.data + host.len, (u_char *)"google", 6 - 1)) { // none google domains // just return back return NGX_OK; } if (!ngx_strncasecmp(host.data, (u_char *)"ipv", 3)) { ngx_str_t nuri; nuri.len = uri.len + 5; nuri.data = ngx_pcalloc(r->pool, nuri.len); if (!nuri.data) return NGX_ERROR; ngx_snprintf(nuri.data, nuri.len, "/ipv%c%V", host.data[3], &uri); uri = nuri; } else if (glcf->scholar == 1 && !ngx_strncasecmp(host.data, (u_char *)"scholar", 7)) { if (uri.len && ngx_strncasecmp(uri.data, (u_char *)"/scholar", 8)) { ngx_str_t nuri; nuri.len = uri.len + 8; nuri.data = ngx_pcalloc(r->pool, nuri.len); if (!nuri.data) return NGX_ERROR; ngx_snprintf(nuri.data, nuri.len, "/scholar%V", &uri); uri = nuri; } } ngx_str_t nv; nv.len = (ctx->ssl ? 8 : 7) + ctx->host->len + uri.len; nv.data = ngx_pcalloc(r->pool, nv.len); if (!nv.data) return NGX_ERROR; ngx_snprintf(nv.data, nv.len, "%s%V%V", ctx->ssl ? "https://" : "http://", ctx->host, &uri); *v = nv; return NGX_OK; }