view src/core/ngx_resolver.h @ 4576:876e6b0814a5

Fixed signed integer overflows in timer code (ticket #145). Integer overflow is undefined behaviour in C and this indeed caused problems on Solaris/SPARC (at least in some cases). Fix is to subtract unsigned integers instead, and then cast result to a signed one, which is implementation-defined behaviour and used to work. Strictly speaking, we should compare (unsigned) result with the maximum value of the corresponding signed integer type instead, this will be defined behaviour. This will require much more changes though, and considered to be overkill for now.
author Maxim Dounin <mdounin@mdounin.ru>
date Fri, 06 Apr 2012 23:46:09 +0000
parents d620f497c50f
children 07dd5bd222ac
line wrap: on
line source


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


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


#ifndef _NGX_RESOLVER_H_INCLUDED_
#define _NGX_RESOLVER_H_INCLUDED_


#define NGX_RESOLVE_A         1
#define NGX_RESOLVE_CNAME     5
#define NGX_RESOLVE_PTR       12
#define NGX_RESOLVE_MX        15
#define NGX_RESOLVE_TXT       16
#define NGX_RESOLVE_DNAME     39

#define NGX_RESOLVE_FORMERR   1
#define NGX_RESOLVE_SERVFAIL  2
#define NGX_RESOLVE_NXDOMAIN  3
#define NGX_RESOLVE_NOTIMP    4
#define NGX_RESOLVE_REFUSED   5
#define NGX_RESOLVE_TIMEDOUT  NGX_ETIMEDOUT


#define NGX_NO_RESOLVER       (void *) -1

#define NGX_RESOLVER_MAX_RECURSION    50


typedef struct {
    ngx_connection_t         *connection;
    struct sockaddr          *sockaddr;
    socklen_t                 socklen;
    ngx_str_t                 server;
    ngx_log_t                 log;
} ngx_udp_connection_t;


typedef struct ngx_resolver_ctx_s  ngx_resolver_ctx_t;

typedef void (*ngx_resolver_handler_pt)(ngx_resolver_ctx_t *ctx);


typedef struct {
    ngx_rbtree_node_t         node;
    ngx_queue_t               queue;

    /* PTR: resolved name, A: name to resolve */
    u_char                   *name;

    u_short                   nlen;
    u_short                   qlen;

    u_char                   *query;

    union {
        in_addr_t             addr;
        in_addr_t            *addrs;
        u_char               *cname;
    } u;

    u_short                   naddrs;
    u_short                   cnlen;

    time_t                    expire;
    time_t                    valid;

    ngx_resolver_ctx_t       *waiting;
} ngx_resolver_node_t;


typedef struct {
    /* has to be pointer because of "incomplete type" */
    ngx_event_t              *event;
    void                     *dummy;
    ngx_log_t                *log;

    /* ident must be after 3 pointers */
    ngx_int_t                 ident;

    /* simple round robin DNS peers balancer */
    ngx_array_t               udp_connections;
    ngx_uint_t                last_connection;

    ngx_rbtree_t              name_rbtree;
    ngx_rbtree_node_t         name_sentinel;

    ngx_rbtree_t              addr_rbtree;
    ngx_rbtree_node_t         addr_sentinel;

    ngx_queue_t               name_resend_queue;
    ngx_queue_t               addr_resend_queue;

    ngx_queue_t               name_expire_queue;
    ngx_queue_t               addr_expire_queue;

    time_t                    resend_timeout;
    time_t                    expire;
    time_t                    valid;

    ngx_uint_t                log_level;
} ngx_resolver_t;


struct ngx_resolver_ctx_s {
    ngx_resolver_ctx_t       *next;
    ngx_resolver_t           *resolver;
    ngx_udp_connection_t     *udp_connection;

    /* ident must be after 3 pointers */
    ngx_int_t                 ident;

    ngx_int_t                 state;
    ngx_int_t                 type;
    ngx_str_t                 name;

    ngx_uint_t                naddrs;
    in_addr_t                *addrs;
    in_addr_t                 addr;

    ngx_resolver_handler_pt   handler;
    void                     *data;
    ngx_msec_t                timeout;

    ngx_uint_t                quick;  /* unsigned  quick:1; */
    ngx_uint_t                recursion;
    ngx_event_t              *event;
};


ngx_resolver_t *ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names,
    ngx_uint_t n);
ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r,
    ngx_resolver_ctx_t *temp);
ngx_int_t ngx_resolve_name(ngx_resolver_ctx_t *ctx);
void ngx_resolve_name_done(ngx_resolver_ctx_t *ctx);
ngx_int_t ngx_resolve_addr(ngx_resolver_ctx_t *ctx);
void ngx_resolve_addr_done(ngx_resolver_ctx_t *ctx);
char *ngx_resolver_strerror(ngx_int_t err);


#endif /* _NGX_RESOLVER_H_INCLUDED_ */