/* * The data structure and constant defintions for DotSlash Apache module * * (c) Columbia University, 2004-2006, All Rights Reserved. * Author: Weibin Zhao */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_main.h" #include "http_protocol.h" #include "http_request.h" #include "util_script.h" #include "http_connection.h" #include "scoreboard.h" #include "mod_proxy.h" #include "mod_cache.h" #include "apr_strings.h" #include /* basic system data types */ #include #include /* basic socket definitions */ #include #include /* for Unix domain sockets */ #include /* sockaddr_in{} and other Internet defns */ #include /* inet(3) functions */ #include #include /* for nonblocking */ #include #include #include #include #include #include /* gethostname */ #include #define SA struct sockaddr #define DOTS_OUT_FILTER "DOTS_OUT_FILTER" #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) /* default file access permissions for new files */ #define write_lock(fd, offset, whence, len) \ lock_reg(fd, F_SETLK, F_WRLCK, offset, whence, len) #define MAXNAME 128 #define MAXLINE 1024 /* max text line length */ #define MAXURL 2048 #define MAXADDR 46 /* IPv4/IPv6 address: xxx.xxx.xxx.xxx */ #define MAXPEER 32 /* max number of dotslash peers */ #define MAXPROXYURL 32 /* max number of proxy URLs */ #define MAXREDIRECTURL 32 /* max number of redirect URLs */ #define Default_MaxDataRate 1000 /* in kB/sec */ #define Default_MaxDreqRate 50 /* in reqs/sec for dynamic content */ #define Default_ControlInterval 1 /* in seconds */ #define Default_ControlTTL 3 /* #CIs for consecutive ctrls */ #define Default_RescueIdleTTL 300 /* release rescue servers */ #define Default_OriginIdleTTL 300 /* shutdown origin servers */ #define Default_PastOriginTTL 3600 /* remove PastOrig */ #define Default_KeepAliveTTL 60 /* rescue server sends KeepAlive */ #define Default_DotsdPort 9877 /* Dotsd server port */ #define Default_SrvlocPort 427 /* Service discovery server port */ #define Default_DiscoverTTL 120 #define Default_RegisterTTL 120 #define Default_RedirectOverhead 358 /* TCP/IP/Ethernet headers */ #define Default_AccountingScale 0.8 #define Default_alpha 0.5 /* for moving average filter */ #define Default_gamma 0.9 /* for inc redirect rate/capacity */ #define Default_cpu_upper_thd 0.7 #define Default_cpu_lower_thd 0.45 #define Default_link_upper_thd 0.75 #define Default_link_lower_thd 0.5 #define Default_alias_pool_size 0 #define QC_MAX_ROW 8192 /* a row in database */ #define QC_MAX_OBJ 1000*1024 /* max result set for MySQL */ #define QC_MISS 0 #define QC_CONF1 1 #define QC_CONF2 2 #define QC_OK 3 #define DBR_NC 4 #define DBW_NC 5 #define DBR_QC 6 #define DBW_QC 7 #define DBW_OFF 8 #define QC_NSTAT 9 typedef enum { S_Normal, S_SOS, S_Rescue } dots_status_t; // server status typedef enum { C_Rescue, C_Origin, C_PastOrig } dots_ctype_t; // connection type typedef enum { A_OK = 200, A_BadReq = 400, A_Reject = 403, A_NotFound = 404, A_TokenInvalid = 406, A_Expired = 410 } dots_rcode_t; // reply code typedef enum { Open_Community = 1, Closed_Community = 2, Insurance_Community = 3 } dots_community_t; // community type typedef struct dots_cpu { unsigned long long idle __attribute__ ((aligned (8))); unsigned long long user __attribute__ ((packed)); unsigned long long nice __attribute__ ((packed)); unsigned long long system __attribute__ ((packed)); float load; } dots_cpu_t; // cpu load monitor typedef struct dots_link { unsigned long long out __attribute__ ((aligned (8))); float load; struct timeval ts; } dots_link_t; // outbound link load monitor typedef struct { unsigned long long num_reply __attribute__ ((aligned (8))); unsigned long long num_redirect __attribute__ ((packed)); unsigned long long num_rescue __attribute__ ((packed)); unsigned long long num_proxy __attribute__ ((packed)); unsigned long long reply_bytes __attribute__ ((packed)); unsigned long long cpu_uticks __attribute__ ((packed)); /* used ticks */ unsigned long long cpu_aticks __attribute__ ((packed)); /* all ticks */ int redi_msg_size; /* size of the first HTTP redirect message */ int redi_msg_body; /* body len of the first HTTP redirect message */ int redi_msg_alen; /* accounting len of the 1st HTTP redirect message */ float cpu_load; float link_load; int curr; dots_cpu_t cpu[2]; dots_link_t link[2]; } dots_ometer_t; // outbound link load and cpu load meter typedef struct dots_pnode dots_pnode_t; struct dots_pnode { int type; /* rescue, origin, pastorig */ int sockfd; char *candidate; int msg_seqno; int set_done; char req_cmd[32]; int req_seqno; char orig_serv[MAXNAME]; char orig_ip[MAXADDR]; int orig_port; char resc_serv[MAXNAME]; char resc_ip[MAXADDR]; int resc_port; // dns round robin int dns_rr_added; // query result cache int qcache_ttl; // cpu workload int redi_rate; /* requests/sec, changed */ float cpu_lw; /* 1.0/(redi_rate*ControlInterval) */ float cpu_lf; /* for WRR */ int num_resc; /* number of rescues */ // link workload int redi_data_rate; /* kB/sec, changed */ float link_lw; /* 1.0/(redi_data_rate*ControlInterval*1000) */ float link_lf; /* foe WRR */ int resc_bytes; /* rescue volume in bytes */ // for C_Rescue int ka_timeout; /* timeout TTL for receive keep alive */ int recv_ka_ttl; /* receiving keep alive */ // for C_Origin int rate_update_ttl; /* interval for consecutive rate update */ int orig_idle_ttl; /* for changing C_Origin to C_PastOrig */ int ka_interval; /* the interval for sending keep alive */ int send_ka_ttl; /* sending keep alive */ // for C_PastOrig int pastorig_ttl; /* for releasing C_PastOrig */ dots_pnode_t *next; }; // for peer node information in shared memory typedef struct { int number; /* number of redirected URLs */ char path[MAXREDIRECTURL][MAXURL]; int fsize[MAXREDIRECTURL]; /* file size */ int count[MAXREDIRECTURL]; /* reference count */ } redirect_urls_t; // record redirected URLs and file size typedef struct { int status; /* Normal, SOS, Rescue */ int qcache_on; /* whether QCache is on in Normal status */ int qcache_ttl; /* for turn off QCache in Normal status */ float redi_prob; /* redirect probability [0, 1] */ int need_resc_cap; /* need to allocate more rescue capacity */ int no_resc_cap; /* no more rescue capacity */ int alloc_ttl; /* for alloc rescue servers */ int prob_update_ttl; /* for update redi_prob */ int resc_idle_ttl; /* for release all rescue servers */ dots_pnode_t heap[MAXPEER]; dots_pnode_t *pused; dots_pnode_t *pfree; redirect_urls_t rurls; } dots_ptable_t; typedef enum { CS_Ready, CS_Used, CS_Busy } dots_cs_status_t; // candidate server status typedef struct { char name[MAXNAME]; char ip[MAXADDR]; int port; int link_rate; double cpu_rate; dots_cs_status_t status; } dots_cnode_t; // for rescue server candidates typedef struct { int count; /* num of candidates */ int nfree; /* num of unused candidates */ dots_cnode_t entry[MAXPEER]; /* list of candidates */ } dots_ctable_t; typedef struct { int dotsd_running; int alias_alloc_num; int alias_reg_num; int srvloc_port; char srvloc_server[MAXNAME]; char my_ip[MAXADDR]; dots_ometer_t ometer; dots_ptable_t ptable; dots_ctable_t ctable; unsigned long long qcstat[QC_NSTAT] __attribute__ ((aligned (8))); } dots_shm_t; typedef struct dots_unode dots_unode_t; struct dots_unode { char url[MAXURL]; /* proxy url */ int done; /* proxy done */ int nwait; /* number of threads waiting for broadcast */ pthread_mutex_t mutex; pthread_cond_t cond; dots_unode_t *next; }; typedef struct { dots_unode_t heap[MAXPROXYURL]; dots_unode_t *uused; dots_unode_t *ufree; } dots_utable_t; typedef struct { int is_reset; /* is it a reset */ int is_redirect; /* is it an HTTP redirect */ char redirect_uri[MAXURL]; /* uri for HTTP redirect, "" otherwise */ int is_rescue; /* is it a rescue */ int is_dynamic; /* is it dynamic content for rescue */ char key[MAXNAME]; /* key for cache purpose */ int in_utable; /* is it in URL control table */ int is_proxy; /* is it a reverse proxy */ dots_unode_t *proxy_node; /* concurrency control for reverse proxy */ char *orig_serv; /* orig_serv cannot be used for reverse proxy */ char *orig_ip; /* orig_ip for reverse proxy */ int orig_port; /* orig_port for reverse proxy */ int qcache_ttl; int qcache_bypass; } dots_request_rec; // per request information for mod_dots typedef struct { apr_off_t curr_reply_len; /* length of current reply so far */ } dots_conn_rec; // per connection information for mod_dots int MaxDataRate; /* in kB/sec */ int MaxDreqRate; /* in reqs/sec */ int ControlInterval; /* Time inetrval for control */ int RescueIdleTTL; /* release rescue servers */ int OriginIdleTTL; /* shutdown origin servers */ int PastOriginTTL; /* remove PastOrig */ int KeepAliveTTL; /* keep alive from rescue server to origin server */ int CommunityType; /* support different types of mutual-aid communities */ int ApachePort; /* Apache server port */ int DotsdPort; /* Dotslash daemon port */ char DotsdPidFile[MAXNAME]; int DotsdPidFileSet; char SrvlocServer[MAXNAME]; int SrvlocServerSet; char ScriptRoot[MAXNAME]; int ScriptRootSet; char QCacheServer[MAXNAME]; int QCacheServerSet; int QCacheTTL; /* expiration time for QCache (in seconds) */ int SrvlocPort; /* Service directory port */ int DiscoverTTL; /* TTL for service discovery */ int RegisterTTL; /* TTL for service registration */ int RedirectOverhead; /* Un-accounted Ethernet/IP/TCP header */ float AccountingScale; /* acounting scale (<1.0) for HTTP redirects */ int alias_pool_size; int alias_alloc_num; int alias_reg_num; int cpu_monitor; float cpu_upper_thd; float cpu_lower_thd; float cpu_optload; float link_upper_thd; float link_lower_thd; float link_optload; float dots_alpha; float dots_gamma; dots_shm_t *shmptr; dots_ometer_t *ometer; dots_ptable_t *ptable; dots_ctable_t *ctable; dots_utable_t *utable; apr_shm_t *dots_shm; apr_proc_mutex_t *ometer_mutex, *ptable_mutex, *htable_mutex, *qcstat_mutex; pthread_mutex_t ctable_mutex, utable_mutex; int srvloc_set; int srvloc_sockfd; struct sockaddr_in srvloc_servaddr; char shm_fname[MAXNAME]; char ometer_mutex_fname[MAXNAME], ptable_mutex_fname[MAXNAME]; char htable_mutex_fname[MAXNAME], qcstat_mutex_fname[MAXNAME]; char my_fullname[MAXNAME], my_hostname[MAXNAME], my_ip[MAXADDR]; char my_aliasbase[MAXNAME], ddns_server[MAXNAME], my_staticname[MAXNAME]; int my_aliasbase_set, ddns_server_set, my_staticname_set; int dns_rr_set, dns_tsig_set; char my_tsigkey[MAXNAME], my_tsigsecret[MAXNAME], ddns_script[MAXNAME]; int my_tsigkey_set, my_tsigsecret_set, ddns_script_set; char *get_token(char *buf, int *ptr); /************************** * For calling SLP client * **************************/ void slp_register(char *hostname, int dotsd_port, int link_rate, float cpu_rate); void slp_discover(int min_link, float min_cpu); /************************************************ * For calling DDNS (dynamic DNS update) client * ************************************************/ #define DNS_ADD 1 #define DNS_DEL 2 /* * "op" can be DNS_ADD or DNS_DEL * add or delete an address RR for "name" with "ip" from DNS * Two usages: * (1) add/delete an alias with its IP * (2) add/delete an IP for an existing name --> DNS round robin */ int dns_update(int op, char *name, char *ip);