From 00e3b5b89fa86ca8ffc8a3510d05a02c3657957f Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Wed, 28 Feb 2007 00:27:19 +0000 Subject: [PATCH] stats server extended: o set_loglevel o get_loglevel o DI : call function via DI API o which : get command list query_stats program extended to accept commands AmArgArray throws outofbound exception instead of assert git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@253 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- core/AmArg.h | 8 +- core/plug-in/stats/Makefile | 3 + core/plug-in/stats/StatsUDPServer.cpp | 143 +++++++++++++++++++++++++- core/plug-in/stats/query_stats.c | 129 +++++++++++++++++------ 4 files changed, 251 insertions(+), 32 deletions(-) diff --git a/core/AmArg.h b/core/AmArg.h index 18242de2..59f91522 100644 --- a/core/AmArg.h +++ b/core/AmArg.h @@ -88,6 +88,10 @@ class AmArgArray vector v; public: + struct OutOfBoundsException { + OutOfBoundsException() { } + }; + AmArgArray() : v() {} AmArgArray(const AmArgArray& a) : v(a.v) {} @@ -97,7 +101,9 @@ public: const AmArg& get(size_t idx) const { - assert(idx < v.size()); + if (idx >= v.size()) + throw OutOfBoundsException(); + // assert(idx < v.size()); return v[idx]; } diff --git a/core/plug-in/stats/Makefile b/core/plug-in/stats/Makefile index bfeb7839..9b3683b8 100644 --- a/core/plug-in/stats/Makefile +++ b/core/plug-in/stats/Makefile @@ -6,3 +6,6 @@ module_ldflags = module_cflags = include ../Makefile.app_module + +query_stats: query_stats.c Makefile + $(GPP) $(CXX_FLAGS) -o query_stats query_stats.c diff --git a/core/plug-in/stats/StatsUDPServer.cpp b/core/plug-in/stats/StatsUDPServer.cpp index 17726d05..6daf67dc 100644 --- a/core/plug-in/stats/StatsUDPServer.cpp +++ b/core/plug-in/stats/StatsUDPServer.cpp @@ -1,3 +1,31 @@ +/* + * $Id$ + * + * Copyright (C) 2002-2003 Fhg Fokus + * Copyright (C) 2007 iptego GmbH + * + * This file is part of sems, a free SIP media server. + * + * sems 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 + * + * For a license to use the ser software under conditions + * other than those described here, or to purchase support for this + * software, please contact iptel.org by e-mail at the following addresses: + * info@iptel.org + * + * sems 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, MA 02111-1307 USA + */ + #include "StatsUDPServer.h" #include "Statistics.h" #include "AmConfigReader.h" @@ -5,6 +33,8 @@ #include "AmUtils.h" #include "AmConfig.h" #include "log.h" +#include "AmPlugIn.h" +#include "AmApi.h" #include using std::string; @@ -212,8 +242,117 @@ int StatsUDPServer::execute(char* msg_buf, string& reply, if(cmd_str == "calls") reply = "Active calls: " + int2str(sc->getSize()) + "\n"; - else - reply = "Unknown command: '" + cmd_str + "'\n"; + else if (cmd_str == "which") { + reply = + "calls - number of active calls (Session Container size)\n" + "which - print available commands\n" + "set_loglevel - set log level\n" + "get_loglevel - get log level\n" + "\n" + "DI ()* - invoke DI command\n" + ; + } + else if (cmd_str.length() > 4 && cmd_str.substr(0, 4) == "set_") { + // setters + if (cmd_str.substr(4, 8) == "loglevel") { + if (!AmConfig::setLoglevel(&cmd_str.c_str()[13])) + reply= "invalid loglevel value.\n"; + else + reply= "loglevel set to "+int2str(log_level)+".\n"; + } + + else reply = "Unknown command: '" + cmd_str + "'\n"; + } + else if (cmd_str.length() > 4 && cmd_str.substr(0, 4) == "get_") { + // setters + if (cmd_str.substr(4, 8) == "loglevel") { + reply= "loglevel is "+int2str(log_level)+".\n"; + } + + else reply = "Unknown command: '" + cmd_str + "'\n"; + } + else if (cmd_str.length() > 4 && cmd_str.substr(0, 3) == "DI ") { + // Dynamic Invocation + size_t p = cmd_str.find(' ', 4); + string fact_name = cmd_str.substr(3, p-3); + if (!fact_name.length()) { + reply = "could not parse DI factory name.\n"; + return 0; + } + + size_t p2 = cmd_str.find(' ', p+1); + if (p2 == string::npos) + p2 = cmd_str.length(); + string fct_name = cmd_str.substr(p+1, p2-p-1); + p=p2+1; + if (!fct_name.length()) { + reply = "could not parse function name.\n"; + return 0; + } + try { + + AmArgArray args; + while (pgetFactory4Di(fact_name); + if(!di_f){ + reply = "could not get '" + fact_name + "' factory\n"; + return 0; + } + AmDynInvoke* di = di_f->getInstance(); + if(!di){ + reply = "could not get DI instance from factory\n"; + return 0; + } + AmArgArray ret; + di->invoke(fct_name, args, ret); + + if (ret.size()) { + reply="["; + for (unsigned int i=0;i #include #include #include #include #include +#include +#include +using std::map; +#include +using std::string; -#define MSG_BUF_SIZE 256 +#define MSG_BUF_SIZE 2048 void print_usage(const char * progname) { fprintf(stderr, - "Syntax: %s ip_address port\n", - progname + "Syntax: %s []\n" + "\n" + "where : \n" + " -s : server name|ip (default: 127.0.0.1)\n" + " -p : server port (default: 50040)\n" + " -c : command (default: calls)\n" + "\n" + "Tips: \n" + " o quote the command if it has arguments (e.g. %s -c \"set_loglevel 1\")\n" + " o \"which\" prints available commands\n" + , + progname, progname ); } +static int parse_args(int argc, char* argv[], const string& flags, + const string& options, map& args); + /* returns non-zero if error occured */ int str2i(const char* str, unsigned short* result) @@ -47,44 +66,60 @@ error_char: return -1; } -char* append_str(const char* buf, const char* str, unsigned int str_s) -{ - memcpy(buf,str,str_s); - buf += str_s; -} - int main(int argc, char** argv) { - char msg_buf[MSG_BUF_SIZE]; - char *p_buf; - int msg_size=10, sd, err; + char rcv_buf[MSG_BUF_SIZE]; + string msg_buf; + int sd, err; struct sockaddr_in addr; + + map args; - if(argc != 3){ - print_usage(argv[0]); - return -1; + if(parse_args(argc, argv, "h","spc", args)){ + print_usage(argv[0]); + return -1; } - - if(!inet_aton(argv[1],&addr.sin_addr)){ - fprintf(stderr,"'%s' is an invalid IP address\n",argv[1]); - return -1; + + string server="127.0.0.1"; + string port="50040"; + string cmd="calls"; + + for(map::iterator it = args.begin(); + it != args.end(); ++it){ + + if(it->second.empty()) + continue; + + switch( it->first ){ + case 'h': { print_usage(argv[0]); exit(1); } break; + case 's': { server=it->second; } break; + case 'p': { port=it->second; } break; + case 'c': { cmd=it->second; } break; + } + } + + if(!inet_aton(server.c_str(),&addr.sin_addr)){ + fprintf(stderr,"server '%s' is an invalid IP address\n",server.c_str()); + return -1; } - if(str2i(argv[2],&addr.sin_port) == -1){ - fprintf(stderr,"'%s' is not a valid integer\n",argv[2]); - return -1; + if(str2i(port.c_str(),&addr.sin_port) == -1){ + fprintf(stderr,"port '%s' is not a valid integer\n",port.c_str()); + return -1; } + addr.sin_family = AF_INET; addr.sin_port = htons(addr.sin_port); - /*TODO: build msg to send */ - p_buf = msg_buf; - p_buf = append_str(p_buf,"calls\n",6); + msg_buf = cmd; + printf("sending '%s\\n' to %s:%s\n", msg_buf.c_str(), + server.c_str(), port.c_str()); + + msg_buf += "\n"; - sd = socket(PF_INET,SOCK_DGRAM,0); - err = sendto(sd,msg_buf,msg_size,0, + err = sendto(sd,msg_buf.c_str(),msg_buf.length(),0, (const struct sockaddr*)&addr, sizeof(struct sockaddr_in)); @@ -92,13 +127,49 @@ int main(int argc, char** argv) fprintf(stderr,"sendto: %s\n",strerror(errno)); } else { - msg_size = recv(sd,msg_buf,MSG_BUF_SIZE,0); + int msg_size = recv(sd,rcv_buf,MSG_BUF_SIZE,0); if(msg_size == -1) fprintf(stderr,"recv: %s\n",strerror(errno)); else - printf("received:\n%.*s",msg_size-1,msg_buf); + printf("received:\n%.*s",msg_size-1,rcv_buf); } close(sd); return 0; } + + +static int parse_args(int argc, char* argv[], + const string& flags, + const string& options, + map& args) +{ + for(int i=1; i