mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-02 02:18:31 +00:00
+ move output_format variables in the http section of the file;
+ more comments on struct mansession and global variables; + small improvements to the session matching code so it supports multiple sessions from the same IP git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@45597 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -83,26 +83,14 @@ struct eventqent {
|
|||||||
char eventdata[1]; /* really variable size, allocated by append_event() */
|
char eventdata[1]; /* really variable size, allocated by append_event() */
|
||||||
};
|
};
|
||||||
|
|
||||||
enum output_format {
|
|
||||||
FORMAT_RAW,
|
|
||||||
FORMAT_HTML,
|
|
||||||
FORMAT_XML,
|
|
||||||
};
|
|
||||||
|
|
||||||
static char *contenttype[] = {
|
|
||||||
[FORMAT_RAW] = "plain",
|
|
||||||
[FORMAT_HTML] = "html",
|
|
||||||
[FORMAT_XML] = "xml",
|
|
||||||
};
|
|
||||||
|
|
||||||
static int enabled = 0;
|
static int enabled = 0;
|
||||||
static int portno = DEFAULT_MANAGER_PORT;
|
static int portno = DEFAULT_MANAGER_PORT;
|
||||||
static int asock = -1;
|
static int asock = -1; /* the accept socket */
|
||||||
static int displayconnects = 1;
|
static int displayconnects = 1;
|
||||||
static int timestampevents = 0;
|
static int timestampevents = 0;
|
||||||
static int httptimeout = 60;
|
static int httptimeout = 60;
|
||||||
|
|
||||||
static pthread_t t;
|
static pthread_t accept_thread_ptr; /* the accept thread */
|
||||||
static int block_sockets = 0;
|
static int block_sockets = 0;
|
||||||
static int num_sessions = 0;
|
static int num_sessions = 0;
|
||||||
|
|
||||||
@@ -121,17 +109,19 @@ AST_THREADSTORAGE(astman_append_buf, astman_append_buf_init);
|
|||||||
|
|
||||||
/*! \brief Descriptor for an AMI session, either a regular one
|
/*! \brief Descriptor for an AMI session, either a regular one
|
||||||
* or one over http.
|
* or one over http.
|
||||||
|
* For AMI sessions, the entry is created upon a connect, and destroyed
|
||||||
|
* with the socket.
|
||||||
*/
|
*/
|
||||||
struct mansession {
|
struct mansession {
|
||||||
pthread_t t; /*! Execution thread */
|
pthread_t ms_t; /*! Execution thread, basically useless */
|
||||||
ast_mutex_t __lock; /*! Thread lock -- don't use in action callbacks, it's already taken care of */
|
ast_mutex_t __lock; /*! Thread lock -- don't use in action callbacks, it's already taken care of */
|
||||||
/* XXX need to document which fields it is protecting */
|
/* XXX need to document which fields it is protecting */
|
||||||
struct sockaddr_in sin; /*! socket address */
|
struct sockaddr_in sin; /*! address we are connecting from */
|
||||||
int fd; /*! descriptor used for output. Either the socket (AMI) or a temporary file (HTTP) */
|
int fd; /*! descriptor used for output. Either the socket (AMI) or a temporary file (HTTP) */
|
||||||
int inuse; /*! Whether an HTTP (XXX or AMI ?) manager is in use */
|
int inuse; /*! number of HTTP sessions using this entry */
|
||||||
int needdestroy; /*! Whether an HTTP session should be destroyed */
|
int needdestroy; /*! Whether an HTTP session should be destroyed */
|
||||||
pthread_t waiting_thread; /*! Whether an HTTP session has someone waiting on events */
|
pthread_t waiting_thread; /*! Whether an HTTP session has someone waiting on events */
|
||||||
unsigned long managerid; /*! Unique manager identifer */
|
unsigned long managerid; /*! Unique manager identifer, 0 for AMI sessions */
|
||||||
time_t sessiontimeout; /*! Session timeout if HTTP */
|
time_t sessiontimeout; /*! Session timeout if HTTP */
|
||||||
struct ast_dynamic_str *outputstr; /*! Output from manager interface */
|
struct ast_dynamic_str *outputstr; /*! Output from manager interface */
|
||||||
char username[80]; /*! Logged in username */
|
char username[80]; /*! Logged in username */
|
||||||
@@ -511,7 +501,7 @@ static struct ast_cli_entry cli_manager[] = {
|
|||||||
static void unuse_eventqent(struct eventqent *e)
|
static void unuse_eventqent(struct eventqent *e)
|
||||||
{
|
{
|
||||||
if (ast_atomic_dec_and_test(&e->usecount) && e->next)
|
if (ast_atomic_dec_and_test(&e->usecount) && e->next)
|
||||||
pthread_kill(t, SIGURG);
|
pthread_kill(accept_thread_ptr, SIGURG);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_session(struct mansession *s)
|
static void free_session(struct mansession *s)
|
||||||
@@ -532,6 +522,7 @@ static void free_session(struct mansession *s)
|
|||||||
static void destroy_session(struct mansession *s)
|
static void destroy_session(struct mansession *s)
|
||||||
{
|
{
|
||||||
AST_LIST_LOCK(&sessions);
|
AST_LIST_LOCK(&sessions);
|
||||||
|
ast_verbose("destroy session %lx\n", s->managerid);
|
||||||
AST_LIST_REMOVE(&sessions, s, list);
|
AST_LIST_REMOVE(&sessions, s, list);
|
||||||
AST_LIST_UNLOCK(&sessions);
|
AST_LIST_UNLOCK(&sessions);
|
||||||
|
|
||||||
@@ -1938,6 +1929,8 @@ static void *accept_thread(void *ignore)
|
|||||||
AST_LIST_LOCK(&sessions);
|
AST_LIST_LOCK(&sessions);
|
||||||
AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
|
AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, s, list) {
|
||||||
if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
|
if (s->sessiontimeout && (now > s->sessiontimeout) && !s->inuse) {
|
||||||
|
ast_verbose("destroy session[2] %lx now %lu to %lu\n",
|
||||||
|
s->managerid, now, s->sessiontimeout);
|
||||||
AST_LIST_REMOVE_CURRENT(&sessions, list);
|
AST_LIST_REMOVE_CURRENT(&sessions, list);
|
||||||
ast_atomic_fetchadd_int(&num_sessions, -1);
|
ast_atomic_fetchadd_int(&num_sessions, -1);
|
||||||
if (s->authenticated && (option_verbose > 1) && displayconnects) {
|
if (s->authenticated && (option_verbose > 1) && displayconnects) {
|
||||||
@@ -2010,7 +2003,7 @@ static void *accept_thread(void *ignore)
|
|||||||
s->eventq = s->eventq->next;
|
s->eventq = s->eventq->next;
|
||||||
AST_LIST_UNLOCK(&sessions);
|
AST_LIST_UNLOCK(&sessions);
|
||||||
ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
|
ast_atomic_fetchadd_int(&s->eventq->usecount, 1);
|
||||||
if (ast_pthread_create_background(&s->t, &attr, session_do, s))
|
if (ast_pthread_create_background(&s->ms_t, &attr, session_do, s))
|
||||||
destroy_session(s);
|
destroy_session(s);
|
||||||
}
|
}
|
||||||
pthread_attr_destroy(&attr);
|
pthread_attr_destroy(&attr);
|
||||||
@@ -2189,15 +2182,31 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse
|
|||||||
* then fed back to the client over the original socket.
|
* then fed back to the client over the original socket.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum output_format {
|
||||||
|
FORMAT_RAW,
|
||||||
|
FORMAT_HTML,
|
||||||
|
FORMAT_XML,
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *contenttype[] = {
|
||||||
|
[FORMAT_RAW] = "plain",
|
||||||
|
[FORMAT_HTML] = "html",
|
||||||
|
[FORMAT_XML] = "xml",
|
||||||
|
};
|
||||||
|
|
||||||
|
/* locate an http session in the list using the cookie as a key */
|
||||||
static struct mansession *find_session(unsigned long ident)
|
static struct mansession *find_session(unsigned long ident)
|
||||||
{
|
{
|
||||||
struct mansession *s;
|
struct mansession *s;
|
||||||
|
|
||||||
|
if (ident == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
AST_LIST_LOCK(&sessions);
|
AST_LIST_LOCK(&sessions);
|
||||||
AST_LIST_TRAVERSE(&sessions, s, list) {
|
AST_LIST_TRAVERSE(&sessions, s, list) {
|
||||||
ast_mutex_lock(&s->__lock);
|
ast_mutex_lock(&s->__lock);
|
||||||
if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) {
|
if (s->sessiontimeout && (s->managerid == ident) && !s->needdestroy) {
|
||||||
s->inuse++;
|
ast_atomic_fetchadd_int(&s->inuse, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&s->__lock);
|
ast_mutex_unlock(&s->__lock);
|
||||||
@@ -2408,25 +2417,26 @@ static char *generic_http_callback(enum output_format format,
|
|||||||
for (v = params; v; v = v->next) {
|
for (v = params; v; v = v->next) {
|
||||||
if (!strcasecmp(v->name, "mansession_id")) {
|
if (!strcasecmp(v->name, "mansession_id")) {
|
||||||
sscanf(v->value, "%lx", &ident);
|
sscanf(v->value, "%lx", &ident);
|
||||||
ast_verbose("session is <%lx>\n", ident);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(s = find_session(ident))) {
|
if (!(s = find_session(ident))) {
|
||||||
/* Create new session */
|
/* Create new session.
|
||||||
|
* While it is not in the list we don't need any locking
|
||||||
|
*/
|
||||||
if (!(s = ast_calloc(1, sizeof(*s)))) {
|
if (!(s = ast_calloc(1, sizeof(*s)))) {
|
||||||
*status = 500;
|
*status = 500;
|
||||||
goto generic_callback_out;
|
goto generic_callback_out;
|
||||||
}
|
}
|
||||||
memcpy(&s->sin, requestor, sizeof(s->sin));
|
s->sin = *requestor;
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
s->waiting_thread = AST_PTHREADT_NULL;
|
s->waiting_thread = AST_PTHREADT_NULL;
|
||||||
s->send_events = 0;
|
s->send_events = 0;
|
||||||
ast_mutex_init(&s->__lock);
|
ast_mutex_init(&s->__lock);
|
||||||
ast_mutex_lock(&s->__lock);
|
ast_mutex_lock(&s->__lock);
|
||||||
s->inuse = 1;
|
s->inuse = 1;
|
||||||
s->managerid = rand() | (unsigned long)s;
|
s->managerid = rand() | 1; /* make sure it is non-zero */
|
||||||
AST_LIST_LOCK(&sessions);
|
AST_LIST_LOCK(&sessions);
|
||||||
AST_LIST_INSERT_HEAD(&sessions, s, list);
|
AST_LIST_INSERT_HEAD(&sessions, s, list);
|
||||||
/* Hook into the last spot in the event queue */
|
/* Hook into the last spot in the event queue */
|
||||||
@@ -2438,14 +2448,7 @@ static char *generic_http_callback(enum output_format format,
|
|||||||
ast_atomic_fetchadd_int(&num_sessions, 1);
|
ast_atomic_fetchadd_int(&num_sessions, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset HTTP timeout. If we're not yet authenticated, keep it extremely short */
|
|
||||||
time(&s->sessiontimeout);
|
|
||||||
if (!s->authenticated && (httptimeout > 5))
|
|
||||||
s->sessiontimeout += 5;
|
|
||||||
else
|
|
||||||
s->sessiontimeout += httptimeout;
|
|
||||||
ast_mutex_unlock(&s->__lock);
|
ast_mutex_unlock(&s->__lock);
|
||||||
|
|
||||||
memset(&m, 0, sizeof(m));
|
memset(&m, 0, sizeof(m));
|
||||||
{
|
{
|
||||||
char tmp[80];
|
char tmp[80];
|
||||||
@@ -2542,6 +2545,10 @@ static char *generic_http_callback(enum output_format format,
|
|||||||
ast_build_string(&c, &len, "</table></body>\r\n");
|
ast_build_string(&c, &len, "</table></body>\r\n");
|
||||||
|
|
||||||
ast_mutex_lock(&s->__lock);
|
ast_mutex_lock(&s->__lock);
|
||||||
|
/* Reset HTTP timeout. If we're not authenticated, keep it extremely short */
|
||||||
|
s->sessiontimeout = time(NULL) + ((s->authenticated || httptimeout < 5) ? httptimeout : 5);
|
||||||
|
ast_verbose("die in %d seconds\n",
|
||||||
|
(int)(s->sessiontimeout - time(NULL)) );
|
||||||
if (s->needdestroy) {
|
if (s->needdestroy) {
|
||||||
if (s->inuse == 1) {
|
if (s->inuse == 1) {
|
||||||
if (option_debug)
|
if (option_debug)
|
||||||
@@ -2831,7 +2838,7 @@ int init_manager(void)
|
|||||||
fcntl(asock, F_SETFL, flags | O_NONBLOCK);
|
fcntl(asock, F_SETFL, flags | O_NONBLOCK);
|
||||||
if (option_verbose)
|
if (option_verbose)
|
||||||
ast_verbose("Asterisk Management interface listening on port %d\n", portno);
|
ast_verbose("Asterisk Management interface listening on port %d\n", portno);
|
||||||
ast_pthread_create_background(&t, NULL, accept_thread, NULL);
|
ast_pthread_create_background(&accept_thread_ptr, NULL, accept_thread, NULL);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user