view src/core/ngx_string.h @ 8122:106328a70f4e

Added warning about redefinition of listen socket protocol options. The "listen" directive in the http module can be used multiple times in different server blocks. Originally, it was supposed to be specified once with various socket options, and without any parameters in virtual server blocks. For example: server { listen 80 backlog=1024; server_name foo; ... } server { listen 80; server_name bar; ... } server { listen 80; server_name bazz; ... } The address part of the syntax ("address[:port]" / "port" / "unix:path") uniquely identifies the listening socket, and therefore is enough for name-based virtual servers (to let nginx know that the virtual server accepts requests on the listening socket in question). To ensure that listening options do not conflict between virtual servers, they were allowed only once. For example, the following configuration will be rejected ("duplicate listen options for 0.0.0.0:80 in ..."): server { listen 80 backlog=1024; server_name foo; ... } server { listen 80 backlog=512; server_name bar; ... } At some point it was, however, noticed, that it is sometimes convenient to repeat some options for clarity. In nginx 0.8.51 the "ssl" parameter was allowed to be specified multiple times, e.g.: server { listen 443 ssl backlog=1024; server_name foo; ... } server { listen 443 ssl; server_name bar; ... } server { listen 443 ssl; server_name bazz; ... } This approach makes configuration more readable, since SSL sockets are immediately visible in the configuration. If this is not needed, just the address can still be used. Later, additional protocol-specific options similar to "ssl" were introduced, notably "http2" and "proxy_protocol". With these options, one can write: server { listen 443 ssl backlog=1024; server_name foo; ... } server { listen 443 http2; server_name bar; ... } server { listen 443 proxy_protocol; server_name bazz; ... } The resulting socket will use ssl, http2, and proxy_protocol, but this is not really obvious from the configuration. To emphasize such misleading configurations are discouraged, nginx now warns as long as the "listen" directive is used with options different from the options previously used if this is potentially confusing. In particular, the following configurations are allowed: server { listen 8401 ssl backlog=1024; server_name foo; } server { listen 8401 ssl; server_name bar; } server { listen 8401 ssl; server_name bazz; } server { listen 8402 ssl http2 backlog=1024; server_name foo; } server { listen 8402 ssl; server_name bar; } server { listen 8402 ssl; server_name bazz; } server { listen 8403 ssl; server_name bar; } server { listen 8403 ssl; server_name bazz; } server { listen 8403 ssl http2; server_name foo; } server { listen 8404 ssl http2 backlog=1024; server_name foo; } server { listen 8404 http2; server_name bar; } server { listen 8404 http2; server_name bazz; } server { listen 8405 ssl http2 backlog=1024; server_name foo; } server { listen 8405 ssl http2; server_name bar; } server { listen 8405 ssl http2; server_name bazz; } server { listen 8406 ssl; server_name foo; } server { listen 8406; server_name bar; } server { listen 8406; server_name bazz; } And the following configurations will generate warnings: server { listen 8501 ssl http2 backlog=1024; server_name foo; } server { listen 8501 http2; server_name bar; } server { listen 8501 ssl; server_name bazz; } server { listen 8502 backlog=1024; server_name foo; } server { listen 8502 ssl; server_name bar; } server { listen 8503 ssl; server_name foo; } server { listen 8503 http2; server_name bar; } server { listen 8504 ssl; server_name foo; } server { listen 8504 http2; server_name bar; } server { listen 8504 proxy_protocol; server_name bazz; } server { listen 8505 ssl http2 proxy_protocol; server_name foo; } server { listen 8505 ssl http2; server_name bar; } server { listen 8505 ssl; server_name bazz; } server { listen 8506 ssl http2; server_name foo; } server { listen 8506 ssl; server_name bar; } server { listen 8506; server_name bazz; } server { listen 8507 ssl; server_name bar; } server { listen 8507; server_name bazz; } server { listen 8507 ssl http2; server_name foo; } server { listen 8508 ssl; server_name bar; } server { listen 8508; server_name bazz; } server { listen 8508 ssl backlog=1024; server_name foo; } server { listen 8509; server_name bazz; } server { listen 8509 ssl; server_name bar; } server { listen 8509 ssl backlog=1024; server_name foo; } The basic idea is that at most two sets of protocol options are allowed: the main one (with socket options, if any), and a shorter one, with options being a subset of the main options, repeated for clarity. As long as the shorter set of protocol options is used, all listen directives except the main one should use it.
author Maxim Dounin <mdounin@mdounin.ru>
date Sat, 28 Jan 2023 01:29:45 +0300
parents 2ffefe2f892e
children
line wrap: on
line source


/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */


#ifndef _NGX_STRING_H_INCLUDED_
#define _NGX_STRING_H_INCLUDED_


#include <ngx_config.h>
#include <ngx_core.h>


typedef struct {
    size_t      len;
    u_char     *data;
} ngx_str_t;


typedef struct {
    ngx_str_t   key;
    ngx_str_t   value;
} ngx_keyval_t;


typedef struct {
    unsigned    len:28;

    unsigned    valid:1;
    unsigned    no_cacheable:1;
    unsigned    not_found:1;
    unsigned    escape:1;

    u_char     *data;
} ngx_variable_value_t;


#define ngx_string(str)     { sizeof(str) - 1, (u_char *) str }
#define ngx_null_string     { 0, NULL }
#define ngx_str_set(str, text)                                               \
    (str)->len = sizeof(text) - 1; (str)->data = (u_char *) text
#define ngx_str_null(str)   (str)->len = 0; (str)->data = NULL


#define ngx_tolower(c)      (u_char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
#define ngx_toupper(c)      (u_char) ((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)

void ngx_strlow(u_char *dst, u_char *src, size_t n);


#define ngx_strncmp(s1, s2, n)  strncmp((const char *) s1, (const char *) s2, n)


/* msvc and icc7 compile strcmp() to inline loop */
#define ngx_strcmp(s1, s2)  strcmp((const char *) s1, (const char *) s2)


#define ngx_strstr(s1, s2)  strstr((const char *) s1, (const char *) s2)
#define ngx_strlen(s)       strlen((const char *) s)

size_t ngx_strnlen(u_char *p, size_t n);

#define ngx_strchr(s1, c)   strchr((const char *) s1, (int) c)

static ngx_inline u_char *
ngx_strlchr(u_char *p, u_char *last, u_char c)
{
    while (p < last) {

        if (*p == c) {
            return p;
        }

        p++;
    }

    return NULL;
}


/*
 * msvc and icc7 compile memset() to the inline "rep stos"
 * while ZeroMemory() and bzero() are the calls.
 * icc7 may also inline several mov's of a zeroed register for small blocks.
 */
#define ngx_memzero(buf, n)       (void) memset(buf, 0, n)
#define ngx_memset(buf, c, n)     (void) memset(buf, c, n)

void ngx_explicit_memzero(void *buf, size_t n);


#if (NGX_MEMCPY_LIMIT)

void *ngx_memcpy(void *dst, const void *src, size_t n);
#define ngx_cpymem(dst, src, n)   (((u_char *) ngx_memcpy(dst, src, n)) + (n))

#else

/*
 * gcc3, msvc, and icc7 compile memcpy() to the inline "rep movs".
 * gcc3 compiles memcpy(d, s, 4) to the inline "mov"es.
 * icc8 compile memcpy(d, s, 4) to the inline "mov"es or XMM moves.
 */
#define ngx_memcpy(dst, src, n)   (void) memcpy(dst, src, n)
#define ngx_cpymem(dst, src, n)   (((u_char *) memcpy(dst, src, n)) + (n))

#endif


#if ( __INTEL_COMPILER >= 800 )

/*
 * the simple inline cycle copies the variable length strings up to 16
 * bytes faster than icc8 autodetecting _intel_fast_memcpy()
 */

static ngx_inline u_char *
ngx_copy(u_char *dst, u_char *src, size_t len)
{
    if (len < 17) {

        while (len) {
            *dst++ = *src++;
            len--;
        }

        return dst;

    } else {
        return ngx_cpymem(dst, src, len);
    }
}

#else

#define ngx_copy                  ngx_cpymem

#endif


#define ngx_memmove(dst, src, n)  (void) memmove(dst, src, n)
#define ngx_movemem(dst, src, n)  (((u_char *) memmove(dst, src, n)) + (n))


/* msvc and icc7 compile memcmp() to the inline loop */
#define ngx_memcmp(s1, s2, n)     memcmp(s1, s2, n)


u_char *ngx_cpystrn(u_char *dst, u_char *src, size_t n);
u_char *ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src);
u_char * ngx_cdecl ngx_sprintf(u_char *buf, const char *fmt, ...);
u_char * ngx_cdecl ngx_snprintf(u_char *buf, size_t max, const char *fmt, ...);
u_char * ngx_cdecl ngx_slprintf(u_char *buf, u_char *last, const char *fmt,
    ...);
u_char *ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args);
#define ngx_vsnprintf(buf, max, fmt, args)                                   \
    ngx_vslprintf(buf, buf + (max), fmt, args)

ngx_int_t ngx_strcasecmp(u_char *s1, u_char *s2);
ngx_int_t ngx_strncasecmp(u_char *s1, u_char *s2, size_t n);

u_char *ngx_strnstr(u_char *s1, char *s2, size_t n);

u_char *ngx_strstrn(u_char *s1, char *s2, size_t n);
u_char *ngx_strcasestrn(u_char *s1, char *s2, size_t n);
u_char *ngx_strlcasestrn(u_char *s1, u_char *last, u_char *s2, size_t n);

ngx_int_t ngx_rstrncmp(u_char *s1, u_char *s2, size_t n);
ngx_int_t ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n);
ngx_int_t ngx_memn2cmp(u_char *s1, u_char *s2, size_t n1, size_t n2);
ngx_int_t ngx_dns_strcmp(u_char *s1, u_char *s2);
ngx_int_t ngx_filename_cmp(u_char *s1, u_char *s2, size_t n);

ngx_int_t ngx_atoi(u_char *line, size_t n);
ngx_int_t ngx_atofp(u_char *line, size_t n, size_t point);
ssize_t ngx_atosz(u_char *line, size_t n);
off_t ngx_atoof(u_char *line, size_t n);
time_t ngx_atotm(u_char *line, size_t n);
ngx_int_t ngx_hextoi(u_char *line, size_t n);

u_char *ngx_hex_dump(u_char *dst, u_char *src, size_t len);


#define ngx_base64_encoded_length(len)  (((len + 2) / 3) * 4)
#define ngx_base64_decoded_length(len)  (((len + 3) / 4) * 3)

void ngx_encode_base64(ngx_str_t *dst, ngx_str_t *src);
void ngx_encode_base64url(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64(ngx_str_t *dst, ngx_str_t *src);
ngx_int_t ngx_decode_base64url(ngx_str_t *dst, ngx_str_t *src);

uint32_t ngx_utf8_decode(u_char **p, size_t n);
size_t ngx_utf8_length(u_char *p, size_t n);
u_char *ngx_utf8_cpystrn(u_char *dst, u_char *src, size_t n, size_t len);


#define NGX_ESCAPE_URI            0
#define NGX_ESCAPE_ARGS           1
#define NGX_ESCAPE_URI_COMPONENT  2
#define NGX_ESCAPE_HTML           3
#define NGX_ESCAPE_REFRESH        4
#define NGX_ESCAPE_MEMCACHED      5
#define NGX_ESCAPE_MAIL_AUTH      6

#define NGX_UNESCAPE_URI       1
#define NGX_UNESCAPE_REDIRECT  2

uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
    ngx_uint_t type);
void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type);
uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size);
uintptr_t ngx_escape_json(u_char *dst, u_char *src, size_t size);


typedef struct {
    ngx_rbtree_node_t         node;
    ngx_str_t                 str;
} ngx_str_node_t;


void ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
ngx_str_node_t *ngx_str_rbtree_lookup(ngx_rbtree_t *rbtree, ngx_str_t *name,
    uint32_t hash);


void ngx_sort(void *base, size_t n, size_t size,
    ngx_int_t (*cmp)(const void *, const void *));
#define ngx_qsort             qsort


#define ngx_value_helper(n)   #n
#define ngx_value(n)          ngx_value_helper(n)


#endif /* _NGX_STRING_H_INCLUDED_ */