📄 control-proto.c
字号:
{ svz_socket_t *xsock; char *id; char linet[64]; char rinet[64]; svz_server_t *server; svz_sock_printf (sock, "\r\n%s", "Proto Id RecvQ SendQ " "Local Foreign\r\n"); /* go through all the socket list */ svz_sock_foreach (xsock) { /* get type of socket */ id = "None"; if (xsock->flags & SOCK_FLAG_LISTENING) id = "Listener"; else if ((server = svz_server_find (xsock->cfg)) != NULL) id = server->name; else if (xsock->flags & SOCK_FLAG_COSERVER) id = "Co-Server"; /* print local and remote end of the connection */ sprintf (linet, "%s:%u", svz_inet_ntoa (xsock->local_addr), ntohs (xsock->local_port)); sprintf (rinet, "%s:%u", svz_inet_ntoa (xsock->remote_addr), ntohs (xsock->remote_port)); /* gather all information from above */ svz_sock_printf (sock, "%-16s %4d %6d %6d %-20s %-20s\r\n", id, xsock->id, xsock->recv_buffer_fill, xsock->send_buffer_fill, linet, rinet); } svz_sock_printf (sock, "\r\n"); return flag;}#if ENABLE_HTTP_PROTO/* * HTTP cache statistics. The following displayed information is a * visual representation of the http cache structures. */intctrl_stat_cache (svz_socket_t *sock, int flag, char *arg){ int n, total, files; char *p; http_cache_entry_t *cache; svz_sock_printf (sock, "\r\n%s", "File " "Size Usage Hits Recent Ready\r\n"); files = total = n = 0; /* go through each cache entry */ for (cache = http_cache_first; cache; cache = cache->next, n++) { files++; total += cache->size; p = cache->file; p += strlen (cache->file); while (*p != '/' && *p != '\\' && p != cache->file) p--; if (p != cache->file) p++; svz_sock_printf (sock, "%-30s %6d %6d %5d %6d %-5s\r\n", p, cache->size, cache->usage, cache->hits, n, cache->ready ? "Yes" : "No"); } /* print cache summary */ svz_sock_printf (sock, "\r\nTotal : %d byte in %d cache entries\r\n\r\n", total, files); return flag;}/* * Free all HTTP cache entries. */intctrl_kill_cache (svz_socket_t *sock, int flag, char *arg){ svz_sock_printf (sock, "%d HTTP cache entries reinitialized.\r\n", http_cache_entries); http_free_cache (); http_alloc_cache (http_cache_entries); return flag;}#endif /* ENABLE_HTTP_PROTO *//* * Show all Co-Server instances statistics. */intctrl_stat_coservers (svz_socket_t *sock, int flag, char *arg){ int n; svz_coserver_t *coserver; /* go through all internal coserver instances */ svz_array_foreach (svz_coservers, coserver, n) { svz_sock_printf (sock, "\r\ninternal %s coserver:\r\n", svz_coservertypes[coserver->type].name); svz_sock_printf (sock, " socket id : %d\r\n" " %s %d\r\n" " requests : %d\r\n", coserver->sock->id,#ifndef __MINGW32__ "process id :", coserver->pid,#else /* __MINGW32__ */ "thread id :", coserver->tid,#endif /* __MINGW32__ */ coserver->busy); } svz_sock_printf (sock, "\r\n"); return flag;}/* * Server and Co-Server instance statistics. */intctrl_stat_all (svz_socket_t *sock, int flag, char *arg){ int n; svz_server_t **server; /* go through all server instances */ svz_hash_foreach_value (svz_servers, server, n) { svz_sock_printf (sock, "\r\n%s (%s):\r\n", server[n]->description, server[n]->name); if (server[n]->info_server) { svz_sock_printf (sock, "%s\r\n", server[n]->info_server (server[n])); } } /* show coserver statistics */ ctrl_stat_coservers (sock, flag, arg); return flag;}/* * Shutdown a specified network connection. This might even be used to * kill your own (the control client's) connection, coservers and servers. * So you want to be *very* careful with this command. */intctrl_kill_id (svz_socket_t *sock, int flag, char *arg){ int id; svz_socket_t *xsock; id = atoi (arg); if ((xsock = svz_sock_find (id, -1)) == NULL) { svz_sock_printf (sock, "no such connection: %d\r\n", id); return flag; } svz_sock_schedule_for_shutdown (xsock); svz_sock_printf (sock, "scheduled socket id %d for shutdown\r\n", id); return flag;}/* * Shutdown all network connections except listening, control connections, * coservers and sockets with the priority flag set. */intctrl_killall (svz_socket_t *sock, int flag, char *arg){ svz_socket_t *xsock; int n = 0; svz_sock_foreach (xsock) { if (xsock != sock && !(xsock->flags & (SOCK_FLAG_LISTENING | SOCK_FLAG_COSERVER | SOCK_FLAG_PRIORITY))) { svz_sock_schedule_for_shutdown (xsock); n++; } } svz_sock_printf (sock, "killed %d network connections\r\n", n); return flag;}/* * Restart coservers. */intctrl_restart (svz_socket_t *sock, int type, char *arg){ svz_coserver_t *coserver; int n; /* find an appropriate coserver to kill */ svz_array_foreach (svz_coservers, coserver, n) { if (coserver->type == type) { svz_coserver_destroy (type); svz_coserver_create (type); svz_sock_printf (sock, "internal %s coserver restarted\r\n", svz_coservertypes[type].name); return 0; } } /* start a new internal coserver if there has none found */ svz_coserver_create (type); svz_sock_printf (sock, "internal %s coserver invoked\r\n", svz_coservertypes[type].name); return 0;}/* * This structure defines the calling conventions for the various * control protocol commands. */struct{ char *command; /* the complete command string */ int (*func)(svz_socket_t *, int, char *); /* callback routine */ int flag; /* second argument */}ctrl[] ={ { CTRL_CMD_HELP, ctrl_help, 0 }, { CTRL_CMD_QUIT, ctrl_quit, -1 }, { CTRL_CMD_EXIT, ctrl_quit, -1 }, { CTRL_CMD_BYE, ctrl_quit, -1 }, { CTRL_CMD_STAT_COSERVER, ctrl_stat_coservers, 0 }, { CTRL_CMD_STAT_CON, ctrl_stat_con, 0 }, { CTRL_CMD_STAT_ID, ctrl_stat_id, 0 }, { CTRL_CMD_STAT_ALL, ctrl_stat_all, 0 },#if ENABLE_HTTP_PROTO { CTRL_CMD_STAT_CACHE, ctrl_stat_cache, 0 }, { CTRL_CMD_KILL_CACHE, ctrl_kill_cache, 0 },#endif { CTRL_CMD_STAT, ctrl_stat, 0 }, { CTRL_CMD_KILLALL, ctrl_killall, 0 }, { CTRL_CMD_KILL_ID, ctrl_kill_id, 0 }, { CTRL_CMD_RESTART_RDNS, ctrl_restart, COSERVER_REVERSE_DNS }, { CTRL_CMD_RESTART_IDENT, ctrl_restart, COSERVER_IDENT }, { CTRL_CMD_RESTART_DNS, ctrl_restart, COSERVER_DNS }, { NULL, NULL, 0 }};/* * The ctrl_handle_request routine gets called by the check_request * routine of the control protocol. */intctrl_handle_request (svz_socket_t *sock, char *request, int len){ static char last_request[CTRL_RECV_BUFSIZE]; static int last_len; int n; int ret = 0; int l; /* search through if there is an input line */ while (request[len - 1] == '\r' || request[len - 1] == '\n') len--; /* password given ? */ if (!(sock->userflags & CTRL_FLAG_PASSED)) { /* * check here the control protocol password */ if (len <= 2) return -1;#if ENABLE_CRYPT && HAVE_CRYPT request[len] = '\0'; if (svz_config.password == NULL || !strcmp (crypt (request, svz_config.password), svz_config.password))#else if (svz_config.password == NULL || (!memcmp (request, svz_config.password, len) && (unsigned) len >= strlen (svz_config.password)))#endif { sock->userflags |= CTRL_FLAG_PASSED; svz_sock_printf (sock, "Login ok.\r\n%s", CTRL_PROMPT); } else return -1; } /* yes, already logged in */ else if (len > 0) { /* repeat last command */ if (!memcmp (request, "/\r\n", 3)) { memcpy (request, last_request, len = last_len); } /* go through all commands */ n = 0; while (ctrl[n].command != NULL) { l = strlen (ctrl[n].command); if (!memcmp (request, ctrl[n].command, l)) { /* save this command for repetition */ memcpy (last_request, request, last_len = len); /* execute valid command and give the prompt */ ret = ctrl[n].func (sock, ctrl[n].flag, &request[l + 1]); svz_sock_printf (sock, "%s", CTRL_PROMPT); return ret; } n++; } l = 0; while (l < len && request[l] >= ' ') l++; request[l] = 0; svz_sock_printf (sock, "no such command: %s\r\n", request); svz_sock_printf (sock, "%s", CTRL_PROMPT); } else { svz_sock_printf (sock, "%s", CTRL_PROMPT); } return ret;}/* * Depending on the systems this routine gets the cpu load. * Returns -1 if an error occurred. * Linux -- /proc/stat * HP-Unix -- pstat_getdynamic() * Solaris -- kstat_read() */static intctrl_get_cpu_state (void){ int n;#if HAVE_LIBKSTAT static kstat_ctl_t *kc; static kstat_t *ksp = NULL; static cpu_stat_t cs;#elif HAVE_PROC_STAT FILE *f; static char stat[STAT_BUFFER_SIZE];#elif HAVE_PSTAT struct pst_dynamic stats;#elif HAVE_SYSGET struct sysinfo_cpu info; sgt_cookie_t cookie;#endif#if HAVE_TIMES struct tms proc_tms;#endif n = (cpu_state.index + 1) & 1;#if HAVE_TIMES cpu_state.ptotal[n] = times (&proc_tms); cpu_state.proc[n][0] = proc_tms.tms_utime; cpu_state.proc[n][1] = proc_tms.tms_stime; cpu_state.proc[n][2] = proc_tms.tms_cutime; cpu_state.proc[n][3] = proc_tms.tms_cstime;#else /* not HAVE_TIMES */ cpu_state.ptotal[n] = cpu_state.ptotal[cpu_state.index] + (CLOCKS_PER_SEC * CTRL_LOAD_UPDATE); cpu_state.proc[n][0] = clock ();#endif /* not HAVE_TIMES */#if HAVE_LIBKSTAT /* Solaris */ if (ksp == NULL) { kc = kstat_open (); for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) if (strncmp (ksp->ks_name, "cpu_stat", 8) == 0) break; } else { if (kstat_read (kc, ksp, &cs) == -1) { svz_snprintf (cpu_state.info, STAT_BUFFER_SIZE, "kstat_read() failed"); return -1; } cpu_state.cpu[n][0] = cs.cpu_sysinfo.cpu[CPU_USER]; cpu_state.cpu[n][1] = cs.cpu_sysinfo.cpu[CPU_KERNEL]; cpu_state.cpu[n][2] = cs.cpu_sysinfo.cpu[CPU_WAIT]; cpu_state.cpu[n][3] = cs.cpu_sysinfo.cpu[CPU_IDLE]; }#elif HAVE_PROC_STAT /* Linux */ /* open the statistics file */ if ((f = svz_fopen (cpu_state.cpufile, "r")) == NULL) { svz_snprintf (cpu_state.info, STAT_BUFFER_SIZE, "%s not available", cpu_state.cpufile); return -1; } /* find the appropriate cpu statistics line */ while (fgets (stat, STAT_BUFFER_SIZE, f)) { if (4 == sscanf (stat, cpu_state.cpuline, &cpu_state.cpu[n][0], &cpu_state.cpu[n][1], &cpu_state.cpu[n][2], &cpu_state.cpu[n][3])) { svz_fclose (f); return 0; } } /* cpu line not found */ svz_snprintf (cpu_state.info, STAT_BUFFER_SIZE, "cpu line not found in %s", cpu_state.cpufile); svz_fclose (f);#elif HAVE_PSTAT /* HP Unix */ pstat_getdynamic (&stats, sizeof (struct pst_dynamic), 1, 0); cpu_state.cpu[n][0] = stats.psd_cpu_time[0]; cpu_state.cpu[n][1] = stats.psd_cpu_time[1]; cpu_state.cpu[n][2] = stats.psd_cpu_time[2]; cpu_state.cpu[n][3] = stats.psd_cpu_time[3];#elif HAVE_SYSGET /* Irix */ SGT_COOKIE_INIT (&cookie); sysget (SGT_SINFO_CPU, (char *) &info, sizeof (info), SGT_READ, &cookie); cpu_state.cpu[n][0] = info.cpu[CPU_USER]; cpu_state.cpu[n][1] = info.cpu[CPU_KERNEL]; cpu_state.cpu[n][2] = info.cpu[CPU_WAIT]; cpu_state.cpu[n][3] = info.cpu[CPU_IDLE]; #endif return 0;}/* * Within the CTRL_IDLE function the server gets the CPU * load. This procedure differs on different platforms. */#define PROC_DIFF(x) (c->proc[n][x] - c->proc[old][x])#define CPU_DIFF(x) (c->cpu[n][x] - c->cpu[old][x])intctrl_idle (svz_socket_t *sock){ int n, old, ret; unsigned long all; cpu_state_t *c = &cpu_state; old = c->index; n = (c->index + 1) & 1; /* get status of the cpu and process */ ret = ctrl_get_cpu_state (); /* calculate process specific info */ all = c->ptotal[n] - c->ptotal[old]; if (all != 0) { svz_snprintf (c->pinfo, STAT_BUFFER_SIZE, PROC_FORMAT, PROC_DIFF (0) * 100 / all, PROC_DIFF (0) * 1000 / all % 10, PROC_DIFF (1) * 100 / all, PROC_DIFF (1) * 1000 / all % 10, PROC_DIFF (2) * 100 / all, PROC_DIFF (2) * 1000 / all % 10, PROC_DIFF (3) * 100 / all, PROC_DIFF (3) * 1000 / all % 10); } if (ret != -1) { /* calculate cpu specific info */ c->total[n] = c->cpu[n][0] + c->cpu[n][1] + c->cpu[n][2] + c->cpu[n][3]; all = c->total[n] - c->total[old]; if (all != 0) { svz_snprintf (c->info, STAT_BUFFER_SIZE, c->cpuinfoline, CPU_DIFF (0) * 100 / all, CPU_DIFF (0) * 1000 / all % 10, CPU_DIFF (1) * 100 / all, CPU_DIFF (1) * 1000 / all % 10, CPU_DIFF (2) * 100 / all, CPU_DIFF (2) * 1000 / all % 10, CPU_DIFF (3) * 100 / all, CPU_DIFF (3) * 1000 / all % 10); } } c->index = n; sock->idle_counter = CTRL_LOAD_UPDATE; return 0;}int have_ctrl = 1;#else /* ENABLE_CONTROL_PROTO */int have_ctrl = 0; /* shut up compiler */#endif /* ENABLE_CONTROL_PROTO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -