📄 control-proto.c
字号:
/* * control-proto.c - control protocol implementation * * Copyright (C) 2000, 2001 Stefan Jahn <stefan@lkcc.org> * * This 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, or (at your option) * any later version. * * This software 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 package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: control-proto.c,v 1.57 2001/08/12 10:59:04 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#if ENABLE_CONTROL_PROTO#define _GNU_SOURCE#include <stdio.h>#include <string.h>#include <time.h>#ifdef __MINGW32__# include <winsock2.h>#endif#ifndef __MINGW32__# include <sys/types.h># include <netinet/in.h>#endif#if HAVE_LIBKSTAT# include <kstat.h># include <sys/sysinfo.h>#elif HAVE_PSTAT# include <sys/pstat.h>#elif HAVE_SYSGET# include <sys/sysget.h># include <sys/sysinfo.h>#endif#if HAVE_TIMES# include <sys/times.h>#endif#include "libserveez.h"#include "control-proto.h"#if ENABLE_HTTP_PROTO# include "http-server/http-cache.h"#endif/* * The control server instance configuration. */ctrl_config_t ctrl_config ={ 0 /* nothing */};/* * Definition of the configuration items processed by the configuration * language. */svz_key_value_pair_t ctrl_config_prototype [] ={ SVZ_REGISTER_END ()};/* * Definition of the control protocol server. */svz_servertype_t ctrl_server_definition ={ "control protocol server", /* long server description */ "control", /* short server description */ NULL, /* global initializer */ ctrl_init, /* instance initializer */ ctrl_detect_proto, /* protocol detection routine */ ctrl_connect_socket, /* connection routine */ ctrl_finalize, /* instance finalization routine */ NULL, /* global finalizer */ ctrl_info_client, /* client info */ ctrl_info_server, /* server info */ NULL, /* server timer */ NULL, /* handle request callback */ &ctrl_config, /* default configuration */ sizeof (ctrl_config), /* size of the configuration */ ctrl_config_prototype /* configuration prototypes */};/* * Within the ctrl_idle() function this structure gets filled with * the appropriate data. */cpu_state_t cpu_state;/* * Server instance initializer. This is currently used for binding the * server to a given port configuration. */intctrl_init (svz_server_t *server){ ctrl_config_t *cfg = server->cfg; return 0;}/* * Server instance finalizer. */intctrl_finalize (svz_server_t *server){ return 0;}/* * Server info callback. */char *ctrl_info_server (svz_server_t *server){ static char info[128]; ctrl_config_t *cfg = server->cfg; sprintf (info, " nothing to be configured, yet"); return info;}/* * Client info callback. */char *ctrl_info_client (svz_server_t *server, svz_socket_t *sock){ static char info[128]; sprintf (info, "This is a control connection client."); return info;}/* * This function gets called for new sockets which are not yet * identified. It returns a non-zero value when the content in * the receive buffer looks like the control protocol. */intctrl_detect_proto (svz_server_t *server, svz_socket_t *sock){ int ret = 0; /* accept both CRLF and CR */ if (sock->recv_buffer_fill >= 2 && sock->recv_buffer[0] == '\r' && sock->recv_buffer[1] == '\n') { ret = 2; } else if (sock->recv_buffer_fill >= 1 && sock->recv_buffer[0] == '\n') { ret = 1; } /* control protocol detected */ if (ret) { if (ret < sock->recv_buffer_fill) { memmove (sock->recv_buffer, sock->recv_buffer + ret, sock->recv_buffer_fill - ret); } sock->recv_buffer_fill -= ret;#if ENABLE_DEBUG svz_log (LOG_DEBUG, "control protocol client detected\n");#endif return -1; } return 0;}/* * When ctrl_detect_proto has identified a client connection being * a control protocol connection you have to call the following * routine. */intctrl_connect_socket (svz_server_t *server, svz_socket_t *sock){ svz_sock_resize_buffers (sock, CTRL_SEND_BUFSIZE, CTRL_RECV_BUFSIZE); sock->check_request = svz_sock_check_request; sock->handle_request = ctrl_handle_request; sock->boundary = CTRL_PACKET_DELIMITER; sock->boundary_size = CTRL_PACKET_DELIMITER_LEN; sock->idle_func = ctrl_idle; sock->idle_counter = CTRL_LOAD_UPDATE;#if HAVE_PROC_STAT cpu_state.cpufile = CPU_FILE_NAME; cpu_state.cpuline = CPU_LINE_FORMAT;#elif HAVE_LIBKSTAT /* not HAVE_PROC_STAT */#else /* neither HAVE_PROC_STAT nor HAVE_LIBKSTAT */ strcpy (cpu_state.info, CPU_FORMAT);#endif cpu_state.cpuinfoline = CPU_FORMAT; /* send welcome message */ svz_sock_printf (sock, "%s", CTRL_PASSWD); return 0;}/* * Quit command. If the client sends this command the control protocol * connection will be closed immediately. */intctrl_quit (svz_socket_t *sock, int flag, char *arg){ return flag;}/* * Help screen. Here you will get all the available commands of the * control protocol. These depend on the features the current version * of Serveez implements. */intctrl_help (svz_socket_t *sock, int flag, char *arg){ svz_sock_printf (sock, "\r\n available commands:\r\n" " * help - this help screen\r\n" " * quit - quit this control connection\r\n" " * restart ident - restart the ident coserver\r\n" " * restart reverse dns - restart reverse DNS lookup coserver\r\n" " * restart dns - restart the DNS lookup coserver\r\n" " * killall - shutdown all client connections\r\n" " * kill id NUM - shutdown connection NUM\r\n" " * stat - general statistics\r\n" " * stat SERVER - SERVER's statistic\r\n" " * stat coserver - coserver statistics\r\n" " * stat con - connection statistics\r\n" " * stat id NUM - NUM's connection info\r\n" " * stat all - server and coserver state\r\n"#if ENABLE_HTTP_PROTO " * stat cache - http cache statistics\r\n" " * kill cache - free all http cache entries\r\n"#endif /* ENABLE_HTTP_PROTO */ "\r\n"); return flag;}/* * ID's connection info. This function displays a given socket id's * socket structure. */intctrl_stat_id (svz_socket_t *sock, int flag, char *arg){ int id, n; svz_socket_t *xsock; char proto[128]; svz_server_t *server; svz_coserver_t *coserver; /* Find the appropriate client or server connection. */ 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_printf (sock, "\r\nconnection id %d (version %d) " "statistics\r\n\r\n", id, xsock->version); /* * Process general socket structure's flags. Uppercase words refer * to set bits and lowercase to unset bits. */ svz_sock_printf (sock, " flags : %s %s %s %s %s %s %s\r\n" " %s %s %s %s %s %s %s\r\n", xsock->flags & SOCK_FLAG_INBUF ? "INBUF" : "inbuf", xsock->flags & SOCK_FLAG_OUTBUF ? "OUTBUF" : "outbuf", xsock->flags & SOCK_FLAG_CONNECTED ? "CONNECTED" : "connected", xsock->flags & SOCK_FLAG_LISTENING ? "LISTENING" : "listening", xsock->flags & SOCK_FLAG_KILLED ? "KILLED" : "killed", xsock->flags & SOCK_FLAG_NOFLOOD ? "flood" : "FLOOD", xsock->flags & SOCK_FLAG_CONNECTING ? "CONNECTING" : "connecting", xsock->flags & SOCK_FLAG_INITED ? "INITED" : "inited", xsock->flags & SOCK_FLAG_COSERVER ? "COSERVER" : "coserver", xsock->flags & SOCK_FLAG_PIPE ? "PIPE" : "pipe", xsock->flags & SOCK_FLAG_FILE ? "FILE" : "file", xsock->flags & SOCK_FLAG_SOCK ? "SOCK" : "sock", xsock->flags & SOCK_FLAG_ENQUEUED ? "ENQUEUED" : "enqueued", xsock->flags & SOCK_FLAG_PRIORITY ? "PRIORITY" : "priority"); svz_sock_printf (sock, " protocol : "); /* process connection type server flags */ if (xsock->flags & SOCK_FLAG_LISTENING) { /* a listening server */ strcpy (proto, "server: "); if (xsock->proto & PROTO_TCP) strcat (proto, "tcp "); if (xsock->proto & PROTO_UDP) strcat (proto, "udp "); if (xsock->proto & PROTO_ICMP) strcat (proto, "icmp "); if (xsock->proto & PROTO_PIPE) strcat (proto, "pipe "); if (xsock->proto & PROTO_RAW) strcat (proto, "raw "); svz_sock_printf (sock, "%s\r\n", proto); svz_array_foreach (xsock->data, server, n) { svz_sock_printf (sock, " %d. %s (%s)\r\n", n + 1, server->name, server->description); } } /* process client info */ else { /* usual client */ if ((server = svz_server_find (xsock->cfg)) != NULL) { char *info; svz_sock_printf (sock, "%s client\r\n", server->name); if (server->info_client && (info = server->info_client (server, xsock)) != NULL) { svz_sock_printf (sock, " %s\r\n", info); } } /* coserver */ else if (xsock->flags & SOCK_FLAG_COSERVER) { coserver = xsock->data; svz_sock_printf (sock, "internal %s coserver\r\n", svz_coservertypes[coserver->type].name); } /* unidentified */ else { svz_sock_printf (sock, "not yet identified\r\n"); } } /* print all previously collected statistics of this connection */ if (xsock->flags & SOCK_FLAG_SOCK) svz_sock_printf (sock, " sock fd : %d\r\n", xsock->sock_desc); if (xsock->flags & SOCK_FLAG_FILE) svz_sock_printf (sock, " file fd : %d\r\n", xsock->file_desc); if (xsock->flags & SOCK_FLAG_PIPE) svz_sock_printf (sock, " pipe fd : %d (recv), %d (send)\r\n", xsock->pipe_desc[READ], xsock->pipe_desc[WRITE]); if (xsock->flags & SOCK_FLAG_PIPE) { if (xsock->send_pipe) svz_sock_printf (sock, " foreign : %s\r\n", xsock->send_pipe); if (xsock->recv_pipe) svz_sock_printf (sock, " local : %s\r\n", xsock->recv_pipe); } if (xsock->flags & SOCK_FLAG_SOCK) { svz_sock_printf (sock, " foreign : %s:%u\r\n", svz_inet_ntoa (xsock->remote_addr), ntohs (xsock->remote_port)); svz_sock_printf (sock, " local : %s:%u\r\n", svz_inet_ntoa (xsock->local_addr), ntohs (xsock->local_port)); } svz_sock_printf (sock, " sendbuf : %d (size), %d (fill), %s (last send)\r\n" " recvbuf : %d (size), %d (fill), %s (last recv)\r\n" " idle : %d\r\n"#if ENABLE_FLOOD_PROTECTION " flood : %d (points), %d (limit)\r\n"#endif /* ENABLE_FLOOD_PROTECTION */ " avail : %s\r\n\r\n", xsock->send_buffer_size, xsock->send_buffer_fill, svz_time (xsock->last_send), xsock->recv_buffer_size, xsock->recv_buffer_fill, svz_time (xsock->last_recv), xsock->idle_counter,#if ENABLE_FLOOD_PROTECTION xsock->flood_points, xsock->flood_limit,#endif /* ENABLE_FLOOD_PROTECTION */ xsock->unavailable ? "no" : "yes"); return flag;}/* * General statistics about Serveez. Here we display all the information * we could get from the system and the process itself. * Furthermore we check if the command is something about a certain * server and give information about it if so. */intctrl_stat (svz_socket_t *sock, int flag, char *arg){ svz_server_t *server; char *p; /* find an appropriate server instance */ p = arg; while (*p && *p != '\r' && *p != '\n') p++; if (*p) *p = '\0'; if ((server = svz_hash_get (svz_servers, arg)) != NULL) { svz_sock_printf (sock, "\r\n%s (%s):\r\n", server->description, server->name); if (server->info_server && (p = server->info_server (server)) != NULL) { svz_sock_printf (sock, "%s\r\n", p); } svz_sock_printf (sock, "\r\n"); return flag; } /* print a standard output */ svz_sock_printf (sock, "\r\nThis is %s version %s running since %s.\r\n", svz_library, svz_version, svz_time (svz_config.start)); /* display compile time feature list */ svz_sock_printf (sock, "Features : FOO"#ifdef ENABLE_AWCS_PROTO " AWCS"#endif#ifdef ENABLE_HTTP_PROTO " HTTP"#endif#ifdef ENABLE_IRC_PROTO " IRC"#endif#if ENABLE_CONTROL_PROTO " CTRL"#endif#if ENABLE_SNTP_PROTO " SNTP"#endif#if ENABLE_GNUTELLA " NUT"#endif#if ENABLE_TUNNEL " TUNNEL"#endif#if ENABLE_FAKEIDENT " IDENTD"#endif "\r\n"); /* second feature line */ svz_sock_printf (sock, " " " IDENT" " REVERSE-DNS" " DNS"#ifdef ENABLE_FLOOD_PROTECTION " FLOOD"#endif#ifdef ENABLE_DEBUG " DEBUG"#endif#if defined (__MINGW32__) || defined (__CYGWIN__) " WIN32"#endif "\r\n"); /* display system and process information */ svz_sock_printf (sock, "Os : %s\r\n", svz_sys_version ()); svz_sock_printf (sock, "Sys-Load : %s\r\n", cpu_state.info); svz_sock_printf (sock, "Proc-Load : %s\r\n", cpu_state.pinfo); /* show general state */ svz_sock_printf (sock, "\r\n * %d connected sockets (hard limit is %d)\r\n", svz_sock_connections, svz_config.max_sockets); svz_sock_printf (sock, " * uptime is %s\r\n", svz_uptime (time (NULL) - svz_config.start));#if ENABLE_DEBUG svz_sock_printf (sock, " * %d bytes of memory in %d blocks allocated\r\n", svz_allocated_bytes, svz_allocated_blocks);#endif /* ENABLE_DEBUG */ svz_sock_printf (sock, "\r\n"); return flag;}/* * Connection statistics. This function displays basic information about * each socket structure currently within the socket list. */intctrl_stat_con (svz_socket_t *sock, int flag, char *arg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -