📄 main.c
字号:
/* * jabberd - Jabber Open Source Server * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney, * Ryan Eatmon, Robert Norris * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA */#include "router.h"static sig_atomic_t router_shutdown = 0;static sig_atomic_t router_logrotate = 0;void router_signal(int signum){ router_shutdown = 1;}void router_signal_hup(int signum){ router_logrotate = 1;}/** store the process id */static void _router_pidfile(router_t r) { char *pidfile; FILE *f; pid_t pid; pidfile = config_get_one(r->config, "pidfile", 0); if(pidfile == NULL) return; pid = getpid(); if((f = fopen(pidfile, "w+")) == NULL) { log_write(r->log, LOG_ERR, "couldn't open %s for writing: %s", pidfile, strerror(errno)); return; } if(fprintf(f, "%d", pid) < 0) { log_write(r->log, LOG_ERR, "couldn't write to %s: %s", pidfile, strerror(errno)); return; } fclose(f); log_write(r->log, LOG_INFO, "process id is %d, written to %s", pid, pidfile);}/** pull values out of the config file */static void _router_config_expand(router_t r){ char *str, *ip, *mask, *name, *target; config_elem_t elem; int i; alias_t alias; r->id = config_get_one(r->config, "id", 0); if(r->id == NULL) r->id = "router"; r->log_type = log_STDOUT; if(config_get(r->config, "log") != NULL) { if((str = config_get_attr(r->config, "log", 0, "type")) != NULL) { if(strcmp(str, "file") == 0) r->log_type = log_FILE; else if(strcmp(str, "syslog") == 0) r->log_type = log_SYSLOG; } } if(r->log_type == log_SYSLOG) { r->log_facility = config_get_one(r->config, "log.facility", 0); r->log_ident = config_get_one(r->config, "log.ident", 0); if(r->log_ident == NULL) r->log_ident = "jabberd/router"; } else if(r->log_type == log_FILE) r->log_ident = config_get_one(r->config, "log.file", 0); r->local_ip = config_get_one(r->config, "local.ip", 0); if(r->local_ip == NULL) r->local_ip = "0.0.0.0"; r->local_port = j_atoi(config_get_one(r->config, "local.port", 0), 5347); r->local_secret = config_get_one(r->config, "local.secret", 0); r->local_pemfile = config_get_one(r->config, "local.pemfile", 0); r->io_max_fds = j_atoi(config_get_one(r->config, "io.max_fds", 0), 1024); elem = config_get(r->config, "io.limits.bytes"); if(elem != NULL) { r->byte_rate_total = j_atoi(elem->values[0], 0); if(r->byte_rate_total != 0) { r->byte_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 5); r->byte_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5); } } elem = config_get(r->config, "io.limits.connects"); if(elem != NULL) { r->conn_rate_total = j_atoi(elem->values[0], 0); if(r->conn_rate_total != 0) { r->conn_rate_seconds = j_atoi(j_attr((const char **) elem->attrs[0], "seconds"), 5); r->conn_rate_wait = j_atoi(j_attr((const char **) elem->attrs[0], "throttle"), 5); } } str = config_get_one(r->config, "io.access.order", 0); if(str == NULL || strcmp(str, "deny,allow") != 0) r->access = access_new(0); else r->access = access_new(1); elem = config_get(r->config, "io.access.allow"); if(elem != NULL) { for(i = 0; i < elem->nvalues; i++) { ip = j_attr((const char **) elem->attrs[i], "ip"); mask = j_attr((const char **) elem->attrs[i], "mask"); if(ip == NULL) continue; if(mask == NULL) mask = "255.255.255.255"; access_allow(r->access, ip, mask); } } elem = config_get(r->config, "io.access.deny"); if(elem != NULL) { for(i = 0; i < elem->nvalues; i++) { ip = j_attr((const char **) elem->attrs[i], "ip"); mask = j_attr((const char **) elem->attrs[i], "mask"); if(ip == NULL) continue; if(mask == NULL) mask = "255.255.255.255"; access_deny(r->access, ip, mask); } } /* aliases */ elem = config_get(r->config, "aliases.alias"); if(elem != NULL) for(i = 0; i < elem->nvalues; i++) { name = j_attr((const char **) elem->attrs[i], "name"); target = j_attr((const char **) elem->attrs[i], "target"); if(name == NULL || target == NULL) continue; alias = (alias_t) malloc(sizeof(struct alias_st)); memset(alias, 0, sizeof(struct alias_st)); alias->name = name; alias->target = target; alias->next = r->aliases; r->aliases = alias; }}static int _router_sx_sasl_callback(int cb, void *arg, void **res, scod_t sd, void *cbarg) { router_t r = (router_t) cbarg; sx_t s; scod_cb_creds_t creds; char *pass; switch(cb) { case sx_sasl_cb_GET_REALM: s = (sx_t) arg; strcpy((char *) res, "jabberd-router"); break; case sx_sasl_cb_GET_PASS: creds = (scod_cb_creds_t) arg; log_debug(ZONE, "sx sasl callback: get pass (authnid=%s, realm=%s)", creds->authnid, creds->realm); *res = xhash_get(r->users, creds->authnid); if(*res == NULL) return 1; return 0; case sx_sasl_cb_CHECK_PASS: creds = (scod_cb_creds_t) arg; log_debug(ZONE, "sx sasl callback: check pass (authnid=%s, realm=%s)", creds->authnid, creds->realm); pass = xhash_get(r->users, creds->authnid); if(pass == NULL || strcmp(creds->pass, pass) != 0) return 1; return 0; case sx_sasl_cb_CHECK_AUTHZID: creds = (scod_cb_creds_t) arg; if(creds->authzid[0] == '\0') strcpy(creds->authzid, creds->authnid); if(strcmp(creds->authnid, creds->authzid) != 0) { log_debug(ZONE, "authnid '%s' doesn't match authzid '%s'", creds->authnid, creds->authzid); return 1; } return 0; default: break; } return 0;}int main(int argc, char **argv){ router_t r; char *config_file; int optchar;#ifdef POOL_DEBUG time_t pool_time = 0;#endif#ifdef HAVE_UMASK umask((mode_t) 0027);#endif srand(time(NULL));#ifdef HAVE_WINSOCK2_H/* get winsock running */ { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* !!! tell user that we couldn't find a usable winsock dll */ return 0; } }#endif jabber_signal(SIGINT, router_signal); jabber_signal(SIGTERM, router_signal);#ifdef SIGHUP jabber_signal(SIGHUP, router_signal_hup);#endif#ifdef SIGPIPE jabber_signal(SIGPIPE, SIG_IGN);#endif r = (router_t) malloc(sizeof(struct router_st)); memset(r, 0, sizeof(struct router_st)); /* load our config */ r->config = config_new(); config_file = CONFIG_DIR "/router.xml"; /* cmdline parsing */ while((optchar = getopt(argc, argv, "Dc:h?")) >= 0) { switch(optchar) { case 'c': config_file = optarg; break; case 'D':#ifdef DEBUG set_debug_flag(1);#else printf("WARN: Debugging not enabled. Ignoring -D.\n");#endif break; case 'h': case '?': default: fputs( "router - jabberd router (" VERSION ")\n" "Usage: router <options>\n" "Options are:\n" " -c <config> config file to use [default: " CONFIG_DIR "/router.xml]\n"#ifdef DEBUG " -D Show debug output\n"#endif , stdout); config_free(r->config); free(r); return 1; } } if(config_load(r->config, config_file) != 0) { fputs("router: couldn't load config, aborting\n", stderr); config_free(r->config); free(r); return 2; } _router_config_expand(r); r->log = log_new(r->log_type, r->log_ident, r->log_facility); log_write(r->log, LOG_NOTICE, "starting up"); _router_pidfile(r); user_table_load(r); r->aci = aci_load(r); r->conn_rates = xhash_new(101); r->pc = prep_cache_new(); r->components = xhash_new(101); r->routes = xhash_new(101); r->log_sinks = xhash_new(101); r->dead = jqueue_new(); r->sx_env = sx_env_new();#ifdef HAVE_SSL if(r->local_pemfile != NULL) { r->sx_ssl = sx_env_plugin(r->sx_env, sx_ssl_init, r->local_pemfile, NULL); if(r->sx_ssl == NULL) log_write(r->log, LOG_ERR, "failed to load SSL pemfile, SSL disabled"); }#endif /* get sasl online */ r->sx_sasl = sx_env_plugin(r->sx_env, sx_sasl_init, _router_sx_sasl_callback, (void *) r, sd_flag_GET_PASS); if(r->sx_sasl == NULL) { log_write(r->log, LOG_ERR, "failed to initialise SASL context, aborting"); exit(1); } r->mio = mio_new(r->io_max_fds); r->fd = mio_listen(r->mio, r->local_port, r->local_ip, router_mio_callback, (void *) r); if(r->fd < 0) { log_write(r->log, LOG_ERR, "[%s, port=%d] unable to listen (%s)", r->local_ip, r->local_port, strerror(errno)); exit(1); } log_write(r->log, LOG_NOTICE, "[%s, port=%d] listening for incoming connections", r->local_ip, r->local_port, strerror(errno)); while(!router_shutdown) { mio_run(r->mio, 5); if(router_logrotate) { log_write(r->log, LOG_NOTICE, "reopening log ..."); log_free(r->log); r->log = log_new(r->log_type, r->log_ident, r->log_facility); log_write(r->log, LOG_NOTICE, "log started"); router_logrotate = 0; } /* cleanup dead sx_ts */ while(jqueue_size(r->dead) > 0) sx_free((sx_t) jqueue_pull(r->dead));#ifdef POOL_DEBUG if(time(NULL) > pool_time + 60) { pool_stat(1); pool_time = time(NULL); }#endif } log_write(r->log, LOG_NOTICE, "shutting down"); /* * !!! issue remote shutdowns to each service, so they can clean up. * we'll need to mio_run() until they all disconnect, so that * the the last packets (eg sm presence unavailables) can get to * their destinations */ /* !!! walk r->services and free contents */ /* !!! walk r->servers and close conns */ /* !!! walk r->conn_rates and free */ prep_cache_free(r->pc); mio_free(r->mio); access_free(r->access); log_free(r->log); config_free(r->config); free(r);#ifdef POOL_DEBUG pool_stat(1);#endif#ifdef HAVE_WINSOCK2_H WSACleanup();#endif return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -