Browse Source

Merge branch 'master' of git://github.com/1and1/rtpengine

pull/194/head
Richard Fuchs 10 years ago
parent
commit
9223ed3469
6 changed files with 192 additions and 10 deletions
  1. +10
    -0
      README.md
  2. +1
    -1
      daemon/call_interfaces.c
  3. +146
    -5
      daemon/cli.c
  4. +5
    -2
      daemon/main.c
  5. +22
    -0
      daemon/str.h
  6. +8
    -2
      utils/rtpengine-ctl

+ 10
- 0
README.md View File

@ -376,6 +376,16 @@ The options are described in more detail below.
Add a prefix for every graphite line.
* --max-sessions
Limit the number of maximum concurrent sessions. Set at startup via MAX_SESSIONS in config file. Set at runtime via rtpengine-ctl util.
Setting the 'rtpengine-ctl set maxsessions 0' can be used in draining rtpengine sessions.
Enable feature: 'MAX_SESSIONS=1000'
Enable feature: 'rtpengine-ctl set maxsessions' >=0
Disable feature: 'rtpengine-ctl set maxsessions -1'
By default, the feature is disabled (i.e. maxsessions == -1).
A typical command line (enabling both UDP and NG protocols) thus may look like:
/usr/sbin/rtpengine --table=0 --interface=10.64.73.31 --interface=2001:db8::4f3:3d \


+ 1
- 1
daemon/call_interfaces.c View File

@ -752,7 +752,7 @@ out:
const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, const char* addr,
const struct sockaddr_in6 *sin)
{
if (m->conf.max_sessions>0) {
if (m->conf.max_sessions>=0) {
rwlock_lock_r(&m->hashlock);
if (g_hash_table_size(m->callhash) >= m->conf.max_sessions) {
rwlock_unlock_r(&m->hashlock);


+ 146
- 5
daemon/cli.c View File

@ -104,6 +104,38 @@ static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m
g_list_free(list);
}
static void cli_incoming_list_maxsessions(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen=0;
/* don't lock anything while reading the value */
printlen = snprintf(replybuffer,(outbufend-replybuffer), "Maximum sessions configured on rtpengine: %d\n", m->conf.max_sessions);
ADJUSTLEN(printlen,outbufend,replybuffer);
return ;
}
static void cli_incoming_list_maxopenfiles(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen=0;
struct rlimit rlim;
pid_t pid = getpid();
if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "Fail getting rtpengine configured limits; cat /proc/%u/limits\n", pid);
ADJUSTLEN(printlen,outbufend,replybuffer);
return ;
}
if (rlim.rlim_cur == RLIM_INFINITY) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "Maximum open-files configured on rtpengine: infinite; cat /proc/%u/limits\n", pid);
ADJUSTLEN(printlen,outbufend,replybuffer);
} else {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "Maximum open-files configured on rtpengine: %lld; cat /proc/%u/limits\n", (long long) rlim.rlim_cur, pid);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
return ;
}
static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
str callid;
struct call* c=0;
@ -212,6 +244,84 @@ static void cli_incoming_list_callid(char* buffer, int len, struct callmaster* m
obj_put(c);
}
static void cli_incoming_set_maxopenfiles(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen = 0;
unsigned int open_files_num;
str open_files;
pid_t pid;
// limit the minimum number of open files to avoid rtpengine freeze for low open_files_num values
unsigned int min_open_files_num = (1 << 16);
if (len<=1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
open_files.s = buffer;
open_files.len = len;
open_files_num = str_to_ui(&open_files, -1);
if (open_files_num == -1) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; not an unsigned integer\n", open_files.len, open_files.s);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else if (open_files_num < min_open_files_num) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; can't set it under %u\n", open_files.len, open_files.s, min_open_files_num);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else if (rlim(RLIMIT_NOFILE, open_files_num) == -1){
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting open_files to %.*s; errno = %d\n", open_files.len, open_files.s, errno);
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
} else {
pid = getpid();
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting open_files to %.*s; cat /proc/%u/limits\n", open_files.len, open_files.s, pid);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
}
static void cli_incoming_set_maxsessions(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen = 0;
int maxsessions_num;
int err = 0x80000000;
int disabled = -1;
str maxsessions;
if (len<=1) {
printlen = snprintf(replybuffer,(outbufend-replybuffer), "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
maxsessions.s = buffer;
maxsessions.len = len;
maxsessions_num = str_to_i(&maxsessions, err);
if (maxsessions_num == err) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %.*s; not an integer\n", maxsessions.len, maxsessions.s);
ADJUSTLEN(printlen,outbufend,replybuffer);
} else if (maxsessions_num < disabled) {
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Fail setting maxsessions to %d; either positive or -1 values allowed\n", maxsessions_num);
ADJUSTLEN(printlen,outbufend,replybuffer);
} else if (maxsessions_num == disabled) {
/* don't lock anything while writing the value - only this command modifies its value */
m->conf.max_sessions = maxsessions_num;
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d; disable feature\n", maxsessions_num);
ADJUSTLEN(printlen,outbufend,replybuffer);
} else {
/* don't lock anything while writing the value - only this command modifies its value */
m->conf.max_sessions = maxsessions_num;
printlen = snprintf (replybuffer,(outbufend-replybuffer), "Success setting maxsessions to %d\n", maxsessions_num);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
return;
}
static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
GHashTableIter iter;
gpointer key, value;
@ -223,6 +333,8 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
static const char* LIST_SESSIONS = "sessions";
static const char* LIST_SESSION = "session";
static const char* LIST_TOTALS = "totals";
static const char* LIST_MAX_OPEN_FILES = "maxopenfiles";
static const char* LIST_MAX_SESSIONS = "maxsessions";
if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
@ -233,7 +345,7 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
if (len>=strlen(LIST_NUMSESSIONS) && strncmp(buffer,LIST_NUMSESSIONS,strlen(LIST_NUMSESSIONS)) == 0) {
rwlock_lock_r(&m->hashlock);
printlen = snprintf(replybuffer, outbufend-replybuffer, "Current Sessions on rtpengine:%i\n", g_hash_table_size(m->callhash));
printlen = snprintf(replybuffer, outbufend-replybuffer, "Current sessions running on rtpengine: %i\n", g_hash_table_size(m->callhash));
ADJUSTLEN(printlen,outbufend,replybuffer);
rwlock_unlock_r(&m->hashlock);
} else if (len>=strlen(LIST_SESSIONS) && strncmp(buffer,LIST_SESSIONS,strlen(LIST_SESSIONS)) == 0) {
@ -256,12 +368,39 @@ static void cli_incoming_list(char* buffer, int len, struct callmaster* m, char*
cli_incoming_list_callid(buffer+strlen(LIST_SESSION), len-strlen(LIST_SESSION), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_TOTALS) && strncmp(buffer,LIST_TOTALS,strlen(LIST_TOTALS)) == 0) {
cli_incoming_list_totals(buffer+strlen(LIST_TOTALS), len-strlen(LIST_TOTALS), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_MAX_SESSIONS) && strncmp(buffer,LIST_MAX_SESSIONS,strlen(LIST_MAX_SESSIONS)) == 0) {
cli_incoming_list_maxsessions(buffer+strlen(LIST_MAX_SESSIONS), len-strlen(LIST_MAX_SESSIONS), m, replybuffer, outbufend);
} else if (len>=strlen(LIST_MAX_OPEN_FILES) && strncmp(buffer,LIST_MAX_OPEN_FILES,strlen(LIST_MAX_OPEN_FILES)) == 0) {
cli_incoming_list_maxopenfiles(buffer+strlen(LIST_MAX_OPEN_FILES), len-strlen(LIST_MAX_OPEN_FILES), m, replybuffer, outbufend);
} else {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'list' command", buffer);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
}
static void cli_incoming_set(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
int printlen=0;
static const char* SET_MAX_OPEN_FILES = "maxopenfiles";
static const char* SET_MAX_SESSIONS = "maxsessions";
if (len<=1) {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s\n", "More parameters required.");
ADJUSTLEN(printlen,outbufend,replybuffer);
return;
}
++buffer; --len; // one space
if (len>=strlen(SET_MAX_OPEN_FILES) && strncmp(buffer,SET_MAX_OPEN_FILES,strlen(SET_MAX_OPEN_FILES)) == 0) {
cli_incoming_set_maxopenfiles(buffer+strlen(SET_MAX_OPEN_FILES), len-strlen(SET_MAX_OPEN_FILES), m, replybuffer, outbufend);
} else if (len>=strlen(SET_MAX_SESSIONS) && strncmp(buffer,SET_MAX_SESSIONS,strlen(SET_MAX_SESSIONS)) == 0) {
cli_incoming_set_maxsessions(buffer+strlen(SET_MAX_SESSIONS), len-strlen(SET_MAX_SESSIONS), m, replybuffer, outbufend);
} else {
printlen = snprintf(replybuffer, outbufend-replybuffer, "%s:%s\n", "Unknown 'set' command", buffer);
ADJUSTLEN(printlen,outbufend,replybuffer);
}
}
static void cli_incoming_terminate(char* buffer, int len, struct callmaster* m, char* replybuffer, const char* outbufend) {
str termparam;
struct call* c=0;
@ -334,9 +473,9 @@ static void cli_incoming(int fd, void *p, uintptr_t u) {
struct cli *cli = (void *) p;
socklen_t sinl;
static const int BUFLENGTH = 4096*1024;
char replybuffer[BUFLENGTH];
char* outbuf = replybuffer;
const char* outbufend = replybuffer+BUFLENGTH;
char replybuffer[BUFLENGTH];
char* outbuf = replybuffer;
const char* outbufend = replybuffer+BUFLENGTH;
static const int MAXINPUT = 1024;
char inbuf[MAXINPUT];
int inlen = 0, readbytes = 0;
@ -374,12 +513,14 @@ next:
static const char* LIST = "list";
static const char* TERMINATE = "terminate";
static const char* SET = "set";
if (strncmp(inbuf,LIST,strlen(LIST)) == 0) {
cli_incoming_list(inbuf+strlen(LIST), inlen-strlen(LIST), cli->callmaster, outbuf, outbufend);
} else if (strncmp(inbuf,TERMINATE,strlen(TERMINATE)) == 0) {
cli_incoming_terminate(inbuf+strlen(TERMINATE), inlen-strlen(TERMINATE), cli->callmaster, outbuf, outbufend);
} else if (strncmp(inbuf,SET,strlen(SET)) == 0) {
cli_incoming_set(inbuf+strlen(SET), inlen-strlen(SET), cli->callmaster, outbuf, outbufend);
} else {
sprintf(replybuffer, "%s:%s\n", "Unknown or incomplete command:", inbuf);
}


+ 5
- 2
daemon/main.c View File

@ -72,7 +72,7 @@ static int timeout;
static int silent_timeout;
static int port_min = 30000;
static int port_max = 40000;
static int max_sessions = 0;
static int max_sessions = -1;
static u_int32_t redis_ip;
static u_int16_t redis_port;
static int redis_db = -1;
@ -149,7 +149,7 @@ static void resources(void) {
int tryv;
rlim(RLIMIT_CORE, RLIM_INFINITY);
for (tryv = ((1<<16) - 1); tryv && rlim(RLIMIT_NOFILE, tryv) == -1; tryv >>= 1)
for (tryv = ((1<<20) - 1); tryv && rlim(RLIMIT_NOFILE, tryv) == -1; tryv >>= 1)
;
rlim(RLIMIT_DATA, RLIM_INFINITY);
@ -530,6 +530,9 @@ no_kernel:
mc.interfaces = &interfaces;
mc.port_min = port_min;
mc.port_max = port_max;
if (max_sessions < -1) {
max_sessions = -1;
}
mc.max_sessions = max_sessions;
mc.timeout = timeout;
mc.silent_timeout = silent_timeout;


+ 22
- 0
daemon/str.h View File

@ -63,6 +63,8 @@ INLINE int str_str(const str *s, const char *sub);
INLINE void str_swap(str *a, str *b);
/* parses a string into an int, returns default if conversion fails */
INLINE int str_to_i(str *s, int def);
/* parses a string uinto an int, returns default if conversion fails */
INLINE uint str_to_ui(str *s, int def);
/* asprintf() analogs */
#define str_sprintf(fmt, a...) __str_sprintf(STR_MALLOC_PADDING fmt, a)
@ -243,6 +245,26 @@ INLINE void str_swap(str *a, str *b) {
}
INLINE int str_to_i(str *s, int def) {
char c, *ep;
long ret;
int maxint = 0x7FFFFFFF;
int minint = 0x80000000;
if (s->len <= 0)
return def;
c = s->s[s->len];
s->s[s->len] = '\0';
ret = strtol(s->s, &ep, 10);
s->s[s->len] = c;
if (ep == s->s)
return def;
if (ret > maxint)
return def;
if (ret < minint)
return def;
return ret;
}
INLINE unsigned int str_to_ui(str *s, int def) {
char c, *ep;
long ret;
if (s->len <= 0)


+ 8
- 2
utils/rtpengine-ctl View File

@ -62,8 +62,10 @@ sub showusage {
print "\n";
print " Supported commands are:\n";
print "\n";
print " list [ numsessions | sessions | session <callid> | totals ]\n";
print " numsessions : prints the number of sessions\n";
print " list [ numsessions | maxsessions | maxopenfiles | sessions | session <callid> | totals ]\n";
print " numsessions : print the number of sessions\n";
print " maxsessions : print the number of allowed sessions\n";
print " maxopenfiles : print the number of allowed open files\n";
print " sessions : print one-liner session information\n";
print " session <callid> : print detail about one session\n";
print " totals : print total statistics\n";
@ -72,6 +74,10 @@ sub showusage {
print " all : terminates all current sessions\n";
print " <callid> : session is immediately terminated\n";
print "\n";
print " set [ maxopenfiles <uint> | maxsessions <int> ]\n";
print " maxsessions <int> : set the max nr of allowed sessions\n";
print " maxopenfiles <uint> : set the max nr of allowed open files\n";
print "\n";
print "\n";
print " Return Value:\n";
print " 0 on success with ouput from server side, other values for failure.\n";


Loading…
Cancel
Save