void vtuPerspective(double m[4][4], double fovy, double aspect, double zNear, double zFar) { double sine, cotangent, deltaZ; double radians = fovy / 2.0 * 3.14159265358979323846 / 180.0; deltaZ = zFar - zNear; sine = sin(radians); if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) vt_fatal("Error: perspectve matrix is degenerate"); cotangent = cos(radians) / sine; m[0][0] = cotangent / aspect; m[1][1] = cotangent; m[2][2] = -(zFar + zNear) / deltaZ; m[2][3] = -1.0; m[3][2] = -2.0 * zNear * zFar / deltaZ; }
int main (int argc, char *argv[]) { cfg_t *cfg; char *prog; char *config_file = "/etc/valiant/valiant.conf"; vt_context_t *ctx; vt_dict_type_t *types[7]; vt_error_t err; vt_thread_pool_t *pool; vt_stats_t *stats, *new_stats; if ((prog = strrchr (argv[0], '/'))) prog++; else prog = argv[0]; /* parse command line options */ int c; char *short_opts = "c:hV"; struct option long_opts[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {"config-file", required_argument, NULL, 'c'} }; for (; (c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != EOF; ) { switch (c) { case 'c': config_file = optarg; break; case 'h': help (prog); break; /* never reached */ case 'V': version (prog); break; /* never reached */ default: usage (prog); break; /* never reached */ } } /* it's important that wathchdog is initialized before any threads are created because it sets the calling threads signal mask to ignore all signals */ vt_watchdog_init (); /* parse configuration file */ if (! (cfg = vt_cfg_parse (config_file))) return 1; types[0] = vt_dict_dnsbl_type (); types[1] = vt_dict_hash_type (); types[2] = vt_dict_pcre_type (); types[3] = vt_dict_rhsbl_type (); types[4] = vt_dict_spf_type (); types[5] = vt_dict_str_type (); types[6] = NULL; if (! (ctx = vt_context_create (types, cfg, &err))) vt_fatal ("cannot create context: %d", err); cfg_free (cfg); // drop priveleges // fprintf (stderr, "%s (%d)\n", __func__, __LINE__); // create workers // create stats printer stats = vt_stats_create (ctx->dicts, ctx->ndicts, &err); vt_stats_thread (stats); vt_worker_arg_t warg; warg.context = ctx; warg.stats = stats; if (! (pool = vt_thread_pool_create ((void *)&warg, ctx->max_threads, &vt_worker, &err))) return EXIT_FAILURE; vt_thread_pool_set_max_idle_threads (pool, ctx->max_idle_threads); vt_thread_pool_set_max_queued (pool, ctx->max_tasks); vt_debug ("created thread pool"); /* open socket that we will listen on */ struct sockaddr_storage their_addr; socklen_t addr_size; struct addrinfo hints, *res; int sock, conn; //vt_worker_arg_t *arg; int *task; memset (&hints, 0, sizeof (hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; getaddrinfo (NULL, ctx->port, &hints, &res); sock = socket (res->ai_family, res->ai_socktype, res->ai_protocol); bind(sock, res->ai_addr, res->ai_addrlen); listen(sock, 10); fd_set fds; struct timeval tv; int dead, ret; cfg_t *new_cfg; vt_context_t *new_ctx; vt_thread_pool_t *new_pool; tv.tv_sec = VT_SELECT_TIMEOUT_SECONDS; tv.tv_usec = VT_SELECT_TIMEOUT_MICROSECONDS; for (dead = 0; ! dead; ) { FD_ZERO (&fds); FD_SET (sock, &fds); ret = select (sock+1, &fds, NULL, NULL, &tv); /* always check if we received a signal or not */ switch (vt_watchdog_signal ()) { case SIGTERM: /* terminate */ dead = 1; break; case SIGHUP: /* reload */ new_cfg = NULL; new_ctx = NULL; new_pool = NULL; vt_debug ("%s:%d", __func__, __LINE__); if (! (new_cfg = vt_cfg_parse (config_file))) { vt_error ("%s: could not parse %s: reload aborted", __func__, config_file); goto failure_reload; } vt_debug ("%s:%d", __func__, __LINE__); if (! (new_ctx = vt_context_create (types, new_cfg, &err))) { vt_error ("%s: could not create context: reload aborted", __func__); goto failure_reload; } vt_debug ("%s:%d", __func__, __LINE__); cfg_free (new_cfg); new_cfg = NULL; new_stats = vt_stats_create (new_ctx->dicts, new_ctx->ndicts, &err); vt_stats_thread (stats); warg.context = new_ctx; warg.stats = new_stats; new_pool = vt_thread_pool_create ((void *)&warg, new_ctx->max_threads, &vt_worker, &err); vt_debug ("%s:%d", __func__, __LINE__); if (! new_pool) { vt_error ("%s: could not create workers: reload aborted", __func__); goto failure_reload; } vt_thread_pool_set_max_idle_threads (new_pool, new_ctx->max_idle_threads); vt_thread_pool_set_max_queued (new_pool, new_ctx->max_tasks); vt_debug ("%s:%d", __func__, __LINE__); vt_stats_destroy (stats, NULL); vt_cleanup (pool, ctx, 1); ctx = new_ctx; pool = new_pool; stats = new_stats; break; failure_reload: vt_error ("%s:%d", __func__, __LINE__); if (new_cfg) cfg_free (new_cfg); if (new_ctx) (void)vt_context_destroy (new_ctx, NULL); if (new_pool) (void)vt_thread_pool_destroy (new_pool, NULL); break; } if (ret < 0) { if (errno != EINTR) vt_fatal ("%s: select: %s", __func__, strerror (errno)); /* ignore */ } else if (ret > 0) { if ((conn = accept (sock, (struct sockaddr *)&their_addr, &addr_size)) < 0) vt_fatal ("%s: accept: %s", __func__, strerror (errno)); if (! (task = calloc (1, sizeof (int)))) vt_fatal ("%s: calloc: %s", __func__, strerror (errno)); *task = conn; vt_thread_pool_push (pool, (void *)task, &err); // FIXME: handle more errors etc! } } // terminate (void)close (sock); // probably needs to be done differently! // vt_cleanup (pool, ctx, 0); // 0. close socket // if there is one... etc! // 1. kill work force // 2. kill context // 3. exit /* cleanup workers and context */ //vt_thread_pool_destroy (workers, &err); /* remove pid file */ // IMPLEMENT return EXIT_SUCCESS; }