@ -149,7 +149,39 @@ static struct {
{ { " restart " , " gracefully " , NULL } } ,
} ;
struct mansession {
/* In order to understand what the heck is going on with the
* mansession_session and mansession structs , we need to have a bit of a history
* lesson .
*
* In the beginning , there was the mansession . The mansession contained data that was
* intrinsic to a manager session , such as the time that it started , the name of the logged - in
* user , etc . In addition to these parameters were the f and fd parameters . For typical manager
* sessions , these were used to represent the TCP socket over which the AMI session was taking
* place . It makes perfect sense for these fields to be a part of the session - specific data since
* the session actually defines this information .
*
* Then came the HTTP AMI sessions . With these , the f and fd fields need to be opened and closed
* for every single action that occurs . Thus the f and fd fields aren ' t really specific to the session
* but rather to the action that is being executed . Because a single session may execute many commands
* at once , some sort of safety needed to be added in order to be sure that we did not end up with fd
* leaks from one action overwriting the f and fd fields used by a previous action before the previous action
* has had a chance to properly close its handles .
*
* The initial idea to solve this was to use thread synchronization , but this prevented multiple actions
* from being run at the same time in a single session . Some manager actions may block for a long time , thus
* creating a large queue of actions to execute . In addition , this fix did not address the basic architectural
* issue that for HTTP manager sessions , the f and fd variables are not really a part of the session , but are
* part of the action instead .
*
* The new idea was to create a structure on the stack for each HTTP Manager action . This structure would
* contain the action - specific information , such as which file to write to . In order to maintain expectations
* of action handlers and not have to change the public API of the manager code , we would need to name this
* new stacked structure ' mansession ' and contain within it the old mansession struct that we used to use .
* We renamed the old mansession struct ' mansession_session ' to hopefully convey that what is in this structure
* is session - specific data . The structure that it is wrapped in , called a ' mansession ' really contains action - specific
* data .
*/
struct mansession_session {
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 */
/* XXX need to document which fields it is protecting */
@ -175,12 +207,23 @@ struct mansession {
int writetimeout ; /*!< Timeout for ast_carefulwrite() */
int pending_event ; /*!< Pending events indicator in case when waiting_thread is NULL */
AST_LIST_HEAD_NOLOCK ( mansession_datastores , ast_datastore ) datastores ; /*!< Data stores on the session */
AST_LIST_ENTRY ( mansession ) list ;
AST_LIST_ENTRY ( mansession _session ) list ;
} ;
# define NEW_EVENT(m) (AST_LIST_NEXT(m->last_ev, eq_next))
/* In case you didn't read that giant block of text above the mansession_session struct, the
* ' mansession ' struct is named this solely to keep the API the same in Asterisk . This structure really
* represents data that is different from Manager action to Manager action . The mansession_session pointer
* contained within points to session - specific data .
*/
struct mansession {
struct mansession_session * session ;
FILE * f ;
int fd ;
} ;
static AST_LIST_HEAD_STATIC ( sessions , mansession ) ;
# define NEW_EVENT(m) (AST_LIST_NEXT(m->session->last_ev, eq_next))
static AST_LIST_HEAD_STATIC ( sessions , mansession_session ) ;
/*! \brief user descriptor, as read from the config file.
*
@ -428,7 +471,7 @@ static int strings_to_mask(const char *string)
static int check_manager_session_inuse ( const char * name )
{
struct mansession * session = NULL ;
struct mansession _session * session = NULL ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE ( & sessions , session , list ) {
@ -459,13 +502,13 @@ static struct ast_manager_user *get_manager_by_name_locked(const char *name)
* \ param s manager session to get parameter from .
* \ return displayconnects config option value .
*/
static int manager_displayconnects ( struct mansession * s )
static int manager_displayconnects ( struct mansession _session * s ession )
{
struct ast_manager_user * user = NULL ;
int ret = 0 ;
AST_RWLIST_RDLOCK ( & users ) ;
if ( ( user = get_manager_by_name_locked ( s - > username ) ) )
if ( ( user = get_manager_by_name_locked ( s ession - > username ) ) )
ret = user - > displayconnects ;
AST_RWLIST_UNLOCK ( & users ) ;
@ -678,7 +721,7 @@ static char *handle_showmancmds(struct ast_cli_entry *e, int cmd, struct ast_cli
/*! \brief CLI command manager list connected */
static char * handle_showmanconn ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
struct mansession * s ;
struct mansession _session * s ession ;
time_t now = time ( NULL ) ;
# define HSMCONN_FORMAT1 " %-15.15s %-15.15s %-10.10s %-10.10s %-8.8s %-8.8s %-5.5s %-5.5s\n"
# define HSMCONN_FORMAT2 " %-15.15s %-15.15s %-10d %-10d %-8d %-8d %-5.5d %-5.5d\n"
@ -698,8 +741,8 @@ static char *handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli
ast_cli ( a - > fd , HSMCONN_FORMAT1 , " Username " , " IP Address " , " Start " , " Elapsed " , " FileDes " , " HttpCnt " , " Read " , " Write " ) ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE ( & sessions , s , list ) {
ast_cli ( a - > fd , HSMCONN_FORMAT2 , s - > username , ast_inet_ntoa ( s - > sin . sin_addr ) , ( int ) ( s - > sessionstart ) , ( int ) ( now - s - > sessionstart ) , s - > fd , s - > inuse , s - > readperm , s - > writeperm ) ;
AST_LIST_TRAVERSE ( & sessions , s ession , list ) {
ast_cli ( a - > fd , HSMCONN_FORMAT2 , s ession - > username , ast_inet_ntoa ( s ession - > sin . sin_addr ) , ( int ) ( s ession - > sessionstart ) , ( int ) ( now - s ession - > sessionstart ) , s ession - > fd , s ession - > inuse , s ession - > readperm , s ession - > writeperm ) ;
count + + ;
}
AST_LIST_UNLOCK ( & sessions ) ;
@ -787,30 +830,30 @@ static void ref_event(struct eventqent *e)
/*
* destroy a session , leaving the usecount
*/
static void free_session ( struct mansession * s )
static void free_session ( struct mansession _session * s ession )
{
struct eventqent * eqe = s - > last_ev ;
struct eventqent * eqe = s ession - > last_ev ;
struct ast_datastore * datastore ;
/* Get rid of each of the data stores on the session */
while ( ( datastore = AST_LIST_REMOVE_HEAD ( & s - > datastores , entry ) ) ) {
while ( ( datastore = AST_LIST_REMOVE_HEAD ( & s ession - > datastores , entry ) ) ) {
/* Free the data store */
ast_datastore_free ( datastore ) ;
}
if ( s - > f ! = NULL )
fclose ( s - > f ) ;
ast_mutex_destroy ( & s - > __lock ) ;
ast_free ( s ) ;
if ( s ession - > f ! = NULL )
fclose ( s ession - > f ) ;
ast_mutex_destroy ( & s ession - > __lock ) ;
ast_free ( s ession ) ;
unref_event ( eqe ) ;
}
static void destroy_session ( struct mansession * s )
static void destroy_session ( struct mansession _session * s ession )
{
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_REMOVE ( & sessions , s , list ) ;
AST_LIST_REMOVE ( & sessions , s ession , list ) ;
ast_atomic_fetchadd_int ( & num_sessions , - 1 ) ;
free_session ( s ) ;
free_session ( s ession ) ;
AST_LIST_UNLOCK ( & sessions ) ;
}
@ -899,7 +942,11 @@ struct ast_variable *astman_get_variables(const struct message *m)
*/
static int send_string ( struct mansession * s , char * string )
{
return ast_careful_fwrite ( s - > f , s - > fd , string , strlen ( string ) , s - > writetimeout ) ;
if ( s - > f ) {
return ast_careful_fwrite ( s - > f , s - > fd , string , strlen ( string ) , s - > session - > writetimeout ) ;
} else {
return ast_careful_fwrite ( s - > session - > f , s - > session - > fd , string , strlen ( string ) , s - > session - > writetimeout ) ;
}
}
/*!
@ -930,7 +977,7 @@ void astman_append(struct mansession *s, const char *fmt, ...)
ast_str_set_va ( & buf , 0 , fmt , ap ) ;
va_end ( ap ) ;
if ( s - > f ! = NULL ) {
if ( s - > f ! = NULL | | s - > session - > f ! = NULL ) {
send_string ( s , ast_str_buffer ( buf ) ) ;
} else {
ast_verbose ( " fd == -1 in astman_append, should not happen \n " ) ;
@ -939,7 +986,7 @@ void astman_append(struct mansession *s, const char *fmt, ...)
/*! \note NOTE: XXX this comment is unclear and possibly wrong.
Callers of astman_send_error ( ) , astman_send_response ( ) or astman_send_ack ( ) must EITHER
hold the session lock _or_ be running in an action callback ( in which case s - > busy will
hold the session lock _or_ be running in an action callback ( in which case s - > session- > busy will
be non - zero ) . In either of these cases , there is no need to lock - protect the session ' s
fd , since no other output will be sent ( events will be queued ) , and no input will
be read until either the current action finishes or get_input ( ) obtains the session
@ -1005,10 +1052,10 @@ static int set_eventmask(struct mansession *s, const char *eventmask)
{
int maskint = strings_to_mask ( eventmask ) ;
ast_mutex_lock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
if ( maskint > = 0 )
s - > se nd_events = maskint ;
ast_mutex_unlock ( & s - > __lock) ;
s - > se ssion- > se nd_events = maskint ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return maskint ;
}
@ -1034,12 +1081,12 @@ static int authenticate(struct mansession *s, const struct message *m)
AST_RWLIST_WRLOCK ( & users ) ;
if ( ! ( user = get_manager_by_name_locked ( username ) ) ) {
ast_log ( LOG_NOTICE , " %s tried to authenticate with nonexistent user '%s' \n " , ast_inet_ntoa ( s - > s in. sin_addr ) , username ) ;
} else if ( user - > ha & & ! ast_apply_ha ( user - > ha , & ( s - > s in) ) ) {
ast_log ( LOG_NOTICE , " %s failed to pass IP ACL as '%s' \n " , ast_inet_ntoa ( s - > s in. sin_addr ) , username ) ;
ast_log ( LOG_NOTICE , " %s tried to authenticate with nonexistent user '%s' \n " , ast_inet_ntoa ( s - > s ession- > s in. sin_addr ) , username ) ;
} else if ( user - > ha & & ! ast_apply_ha ( user - > ha , & ( s - > s ession- > s in) ) ) {
ast_log ( LOG_NOTICE , " %s failed to pass IP ACL as '%s' \n " , ast_inet_ntoa ( s - > s ession- > s in. sin_addr ) , username ) ;
} else if ( ! strcasecmp ( astman_get_header ( m , " AuthType " ) , " MD5 " ) ) {
const char * key = astman_get_header ( m , " Key " ) ;
if ( ! ast_strlen_zero ( key ) & & ! ast_strlen_zero ( s - > challenge) & & user - > secret ) {
if ( ! ast_strlen_zero ( key ) & & ! ast_strlen_zero ( s - > session- > challenge) & & user - > secret ) {
int x ;
int len = 0 ;
char md5key [ 256 ] = " " ;
@ -1047,7 +1094,7 @@ static int authenticate(struct mansession *s, const struct message *m)
unsigned char digest [ 16 ] ;
MD5Init ( & md5 ) ;
MD5Update ( & md5 , ( unsigned char * ) s - > challenge, strlen ( s - > challenge ) ) ;
MD5Update ( & md5 , ( unsigned char * ) s - > session- > challenge, strlen ( s - > session - > challenge ) ) ;
MD5Update ( & md5 , ( unsigned char * ) user - > secret , strlen ( user - > secret ) ) ;
MD5Final ( digest , & md5 ) ;
for ( x = 0 ; x < 16 ; x + + )
@ -1056,24 +1103,24 @@ static int authenticate(struct mansession *s, const struct message *m)
error = 0 ;
} else {
ast_debug ( 1 , " MD5 authentication is not possible. challenge: '%s' \n " ,
S_OR ( s - > challenge, " " ) ) ;
S_OR ( s - > session- > challenge, " " ) ) ;
}
} else if ( password & & user - > secret & & ! strcmp ( password , user - > secret ) )
error = 0 ;
if ( error ) {
ast_log ( LOG_NOTICE , " %s failed to authenticate as '%s' \n " , ast_inet_ntoa ( s - > s in. sin_addr ) , username ) ;
ast_log ( LOG_NOTICE , " %s failed to authenticate as '%s' \n " , ast_inet_ntoa ( s - > s ession- > s in. sin_addr ) , username ) ;
AST_RWLIST_UNLOCK ( & users ) ;
return - 1 ;
}
/* auth complete */
ast_copy_string ( s - > username, username , sizeof ( s - > username ) ) ;
s - > readperm = user - > readperm ;
s - > writeperm = user - > writeperm ;
s - > writetimeout = user - > writetimeout ;
s - > session start = time ( NULL ) ;
ast_copy_string ( s - > session- > username, username , sizeof ( s - > session - > username ) ) ;
s - > session- > readperm = user - > readperm ;
s - > session- > writeperm = user - > writeperm ;
s - > session- > writetimeout = user - > writetimeout ;
s - > session - > session start = time ( NULL ) ;
set_eventmask ( s , astman_get_header ( m , " Events " ) ) ;
AST_RWLIST_UNLOCK ( & users ) ;
@ -1549,76 +1596,76 @@ static int action_waitevent(struct mansession *s, const struct message *m)
/* XXX maybe put an upper bound, or prevent the use of 0 ? */
}
ast_mutex_lock ( & s - > __lock) ;
if ( s - > waiting_thread ! = AST_PTHREADT_NULL )
pthread_kill ( s - > waiting_thread, SIGURG ) ;
ast_mutex_lock ( & s - > session- > __lock) ;
if ( s - > session- > waiting_thread ! = AST_PTHREADT_NULL )
pthread_kill ( s - > session- > waiting_thread, SIGURG ) ;
if ( s - > managerid) { /* AMI-over-HTTP session */
if ( s - > session- > managerid) { /* AMI-over-HTTP session */
/*
* Make sure the timeout is within the expire time of the session ,
* as the client will likely abort the request if it does not see
* data coming after some amount of time .
*/
time_t now = time ( NULL ) ;
int max = s - > session timeout - now - 10 ;
int max = s - > session - > session timeout - now - 10 ;
if ( max < 0 ) /* We are already late. Strange but possible. */
max = 0 ;
if ( timeout < 0 | | timeout > max )
timeout = max ;
if ( ! s - > se nd_events) /* make sure we record events */
s - > se nd_events = - 1 ;
if ( ! s - > se ssion- > se nd_events) /* make sure we record events */
s - > se ssion- > se nd_events = - 1 ;
}
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
/* XXX should this go inside the lock ? */
s - > waiting_thread = pthread_self ( ) ; /* let new events wake up this thread */
s - > session- > waiting_thread = pthread_self ( ) ; /* let new events wake up this thread */
ast_debug ( 1 , " Starting waiting for an event! \n " ) ;
for ( x = 0 ; x < timeout | | timeout < 0 ; x + + ) {
ast_mutex_lock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
if ( NEW_EVENT ( s ) )
needexit = 1 ;
/* We can have multiple HTTP session point to the same mansession entry.
* The way we deal with it is not very nice : newcomers kick out the previous
* HTTP session . XXX this needs to be improved .
*/
if ( s - > waiting_thread ! = pthread_self ( ) )
if ( s - > session- > waiting_thread ! = pthread_self ( ) )
needexit = 1 ;
if ( s - > needdestroy)
if ( s - > session- > needdestroy)
needexit = 1 ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
if ( needexit )
break ;
if ( s - > managerid = = 0 ) { /* AMI session */
if ( ast_wait_for_input ( s - > fd, 1000 ) )
if ( s - > session- > managerid = = 0 ) { /* AMI session */
if ( ast_wait_for_input ( s - > session- > fd, 1000 ) )
break ;
} else { /* HTTP session */
sleep ( 1 ) ;
}
}
ast_debug ( 1 , " Finished waiting for an event! \n " ) ;
ast_mutex_lock ( & s - > __lock) ;
if ( s - > waiting_thread = = pthread_self ( ) ) {
ast_mutex_lock ( & s - > session- > __lock) ;
if ( s - > session- > waiting_thread = = pthread_self ( ) ) {
struct eventqent * eqe ;
astman_send_response ( s , m , " Success " , " Waiting for Event completed. " ) ;
while ( ( eqe = NEW_EVENT ( s ) ) ) {
ref_event ( eqe ) ;
if ( ( ( s - > readperm & eqe - > category ) = = eqe - > category ) & &
( ( s - > se nd_events & eqe - > category ) = = eqe - > category ) ) {
if ( ( ( s - > session- > readperm & eqe - > category ) = = eqe - > category ) & &
( ( s - > se ssion- > se nd_events & eqe - > category ) = = eqe - > category ) ) {
astman_append ( s , " %s " , eqe - > eventdata ) ;
}
s - > last_ev = unref_event ( s - > last_ev ) ;
s - > session- > last_ev = unref_event ( s - > session - > last_ev ) ;
}
astman_append ( s ,
" Event: WaitEventComplete \r \n "
" %s "
" \r \n " , idText ) ;
s - > waiting_thread = AST_PTHREADT_NULL ;
s - > session- > waiting_thread = AST_PTHREADT_NULL ;
} else {
ast_debug ( 1 , " Abandoning event request! \n " ) ;
}
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return 0 ;
}
@ -1635,7 +1682,7 @@ static int action_listcommands(struct mansession *s, const struct message *m)
astman_start_ack ( s , m ) ;
AST_RWLIST_TRAVERSE ( & actions , cur , list ) {
if ( s - > writeperm & cur - > authority | | cur - > authority = = 0 )
if ( s - > session- > writeperm & cur - > authority | | cur - > authority = = 0 )
astman_append ( s , " %s: %s (Priv: %s) \r \n " ,
cur - > action , cur - > synopsis , authority_to_str ( cur - > authority , & temp ) ) ;
}
@ -1684,10 +1731,10 @@ static int action_login(struct mansession *s, const struct message *m)
astman_send_error ( s , m , " Authentication failed " ) ;
return - 1 ;
}
s - > authenticated = 1 ;
if ( manager_displayconnects ( s ) )
ast_verb ( 2 , " %sManager '%s' logged on from %s \n " , ( s - > managerid ? " HTTP " : " " ) , s - > username, ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " %sManager '%s' logged on from %s \n " , ( s - > managerid ? " HTTP " : " " ) , s - > username, ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
s - > session- > authenticated = 1 ;
if ( manager_displayconnects ( s - > session ) )
ast_verb ( 2 , " %sManager '%s' logged on from %s \n " , ( s - > session- > managerid ? " HTTP " : " " ) , s - > session- > username, ast_inet_ntoa ( s - > session - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " %sManager '%s' logged on from %s \n " , ( s - > session- > managerid ? " HTTP " : " " ) , s - > session- > username, ast_inet_ntoa ( s - > session - > sin . sin_addr ) ) ;
astman_send_ack ( s , m , " Authentication accepted " ) ;
return 0 ;
}
@ -1697,12 +1744,12 @@ static int action_challenge(struct mansession *s, const struct message *m)
const char * authtype = astman_get_header ( m , " AuthType " ) ;
if ( ! strcasecmp ( authtype , " MD5 " ) ) {
if ( ast_strlen_zero ( s - > challenge) )
snprintf ( s - > challenge, sizeof ( s - > challenge ) , " %ld " , ast_random ( ) ) ;
ast_mutex_lock ( & s - > __lock) ;
if ( ast_strlen_zero ( s - > session- > challenge) )
snprintf ( s - > session- > challenge, sizeof ( s - > session - > challenge ) , " %ld " , ast_random ( ) ) ;
ast_mutex_lock ( & s - > session- > __lock) ;
astman_start_ack ( s , m ) ;
astman_append ( s , " Challenge: %s \r \n \r \n " , s - > challenge) ;
ast_mutex_unlock ( & s - > __lock) ;
astman_append ( s , " Challenge: %s \r \n \r \n " , s - > session- > challenge) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
} else {
astman_send_error ( s , m , " Must specify AuthType " ) ;
}
@ -2412,7 +2459,7 @@ static int action_originate(struct mansession *s, const struct message *m)
}
} else if ( ! ast_strlen_zero ( app ) ) {
/* To run the System application (or anything else that goes to shell), you must have the additional System privilege */
if ( ! ( s - > writeperm & EVENT_FLAG_SYSTEM )
if ( ! ( s - > session- > writeperm & EVENT_FLAG_SYSTEM )
& & (
strcasestr ( app , " system " ) = = 0 | | /* System(rm -rf /)
TrySystem ( rm - rf / ) */
@ -2584,22 +2631,22 @@ static int process_events(struct mansession *s)
{
int ret = 0 ;
ast_mutex_lock ( & s - > __lock) ;
if ( s - > f ! = NULL ) {
ast_mutex_lock ( & s - > session- > __lock) ;
if ( s - > session- > f ! = NULL ) {
struct eventqent * eqe ;
while ( ( eqe = NEW_EVENT ( s ) ) ) {
ref_event ( eqe ) ;
if ( ! ret & & s - > authenticated & &
( s - > readperm & eqe - > category ) = = eqe - > category & &
( s - > se nd_events & eqe - > category ) = = eqe - > category ) {
if ( ! ret & & s - > session- > authenticated & &
( s - > session- > readperm & eqe - > category ) = = eqe - > category & &
( s - > se ssion- > se nd_events & eqe - > category ) = = eqe - > category ) {
if ( send_string ( s , eqe - > eventdata ) < 0 )
ret = - 1 ; /* don't send more */
}
s - > last_ev = unref_event ( s - > last_ev ) ;
s - > session- > last_ev = unref_event ( s - > session - > last_ev ) ;
}
}
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return ret ;
}
@ -2924,26 +2971,26 @@ static int process_message(struct mansession *s, const struct message *m)
ast_debug ( 1 , " Manager received command '%s' \n " , action ) ;
if ( ast_strlen_zero ( action ) ) {
ast_mutex_lock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
astman_send_error ( s , m , " Missing action in request " ) ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return 0 ;
}
if ( ! s - > authenticated & & strcasecmp ( action , " Login " ) & & strcasecmp ( action , " Logoff " ) & & strcasecmp ( action , " Challenge " ) ) {
ast_mutex_lock ( & s - > __lock) ;
if ( ! s - > session- > authenticated & & strcasecmp ( action , " Login " ) & & strcasecmp ( action , " Logoff " ) & & strcasecmp ( action , " Challenge " ) ) {
ast_mutex_lock ( & s - > session- > __lock) ;
astman_send_error ( s , m , " Permission denied " ) ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return 0 ;
}
if ( ! allowmultiplelogin & & ! s - > authenticated & & user & &
if ( ! allowmultiplelogin & & ! s - > session- > authenticated & & user & &
( ! strcasecmp ( action , " Login " ) | | ! strcasecmp ( action , " Challenge " ) ) ) {
if ( check_manager_session_inuse ( user ) ) {
sleep ( 1 ) ;
ast_mutex_lock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
astman_send_error ( s , m , " Login Already In Use " ) ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return - 1 ;
}
}
@ -2952,7 +2999,7 @@ static int process_message(struct mansession *s, const struct message *m)
AST_RWLIST_TRAVERSE ( & actions , tmp , list ) {
if ( strcasecmp ( action , tmp - > action ) )
continue ;
if ( s - > writeperm & tmp - > authority | | tmp - > authority = = 0 )
if ( s - > session- > writeperm & tmp - > authority | | tmp - > authority = = 0 )
ret = tmp - > func ( s , m ) ;
else
astman_send_error ( s , m , " Permission denied " ) ;
@ -2963,9 +3010,9 @@ static int process_message(struct mansession *s, const struct message *m)
if ( ! tmp ) {
char buf [ 512 ] ;
snprintf ( buf , sizeof ( buf ) , " Invalid/unknown command: %s. Use Action: ListCommands to show available commands. " , action ) ;
ast_mutex_lock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
astman_send_error ( s , m , buf ) ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
}
if ( ret )
return ret ;
@ -2991,16 +3038,16 @@ static int process_message(struct mansession *s, const struct message *m)
static int get_input ( struct mansession * s , char * output )
{
int res , x ;
int maxlen = sizeof ( s - > inbuf) - 1 ;
char * src = s - > inbuf;
int maxlen = sizeof ( s - > session- > inbuf) - 1 ;
char * src = s - > session- > inbuf;
/*
* Look for \ r \ n within the buffer . If found , copy to the output
* buffer and return , trimming the \ r \ n ( not used afterwards ) .
*/
for ( x = 0 ; x < s - > inlen; x + + ) {
for ( x = 0 ; x < s - > session- > inlen; x + + ) {
int cr ; /* set if we have \r */
if ( src [ x ] = = ' \r ' & & x + 1 < s - > inlen & & src [ x + 1 ] = = ' \n ' )
if ( src [ x ] = = ' \r ' & & x + 1 < s - > session- > inlen & & src [ x + 1 ] = = ' \n ' )
cr = 2 ; /* Found. Update length to include \r\n */
else if ( src [ x ] = = ' \n ' )
cr = 1 ; /* also accept \n only */
@ -3009,32 +3056,32 @@ static int get_input(struct mansession *s, char *output)
memmove ( output , src , x ) ; /*... but trim \r\n */
output [ x ] = ' \0 ' ; /* terminate the string */
x + = cr ; /* number of bytes used */
s - > inlen - = x ; /* remaining size */
memmove ( src , src + x , s - > inlen) ; /* remove used bytes */
s - > session- > inlen - = x ; /* remaining size */
memmove ( src , src + x , s - > session- > inlen) ; /* remove used bytes */
return 1 ;
}
if ( s - > inlen > = maxlen ) {
if ( s - > session- > inlen > = maxlen ) {
/* no crlf found, and buffer full - sorry, too long for us */
ast_log ( LOG_WARNING , " Dumping long line with no return from %s: %s \n " , ast_inet_ntoa ( s - > s in. sin_addr ) , src ) ;
s - > inlen = 0 ;
ast_log ( LOG_WARNING , " Dumping long line with no return from %s: %s \n " , ast_inet_ntoa ( s - > s ession- > s in. sin_addr ) , src ) ;
s - > session- > inlen = 0 ;
}
res = 0 ;
while ( res = = 0 ) {
/* XXX do we really need this locking ? */
ast_mutex_lock ( & s - > __lock) ;
if ( s - > pending_event) {
s - > pending_event = 0 ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
if ( s - > session- > pending_event) {
s - > session- > pending_event = 0 ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return 0 ;
}
s - > waiting_thread = pthread_self ( ) ;
ast_mutex_unlock ( & s - > __lock) ;
s - > session- > waiting_thread = pthread_self ( ) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
res = ast_wait_for_input ( s - > fd, - 1 ) ; /* return 0 on timeout ? */
res = ast_wait_for_input ( s - > session- > fd, - 1 ) ; /* return 0 on timeout ? */
ast_mutex_lock ( & s - > __lock) ;
s - > waiting_thread = AST_PTHREADT_NULL ;
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_lock ( & s - > session- > __lock) ;
s - > session- > waiting_thread = AST_PTHREADT_NULL ;
ast_mutex_unlock ( & s - > session- > __lock) ;
}
if ( res < 0 ) {
/* If we get a signal from some other thread (typically because
@ -3045,23 +3092,23 @@ static int get_input(struct mansession *s, char *output)
ast_log ( LOG_WARNING , " poll() returned error: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
ast_mutex_lock ( & s - > __lock) ;
res = fread ( src + s - > inlen, 1 , maxlen - s - > inlen, s - > f ) ;
ast_mutex_lock ( & s - > session- > __lock) ;
res = fread ( src + s - > session- > inlen, 1 , maxlen - s - > session- > inlen, s - > session - > f ) ;
if ( res < 1 )
res = - 1 ; /* error return */
else {
s - > inlen + = res ;
src [ s - > inlen] = ' \0 ' ;
s - > session- > inlen + = res ;
src [ s - > session- > inlen] = ' \0 ' ;
res = 0 ;
}
ast_mutex_unlock ( & s - > __lock) ;
ast_mutex_unlock ( & s - > session- > __lock) ;
return res ;
}
static int do_message ( struct mansession * s )
{
struct message m = { 0 } ;
char header_buf [ sizeof ( s - > inbuf) ] = { ' \0 ' } ;
char header_buf [ sizeof ( s - > session- > inbuf) ] = { ' \0 ' } ;
int res ;
for ( ; ; ) {
@ -3093,15 +3140,16 @@ static int do_message(struct mansession *s)
static void * session_do ( void * data )
{
struct ast_tcptls_session_instance * ser = data ;
struct mansession * s = ast_calloc ( 1 , sizeof ( * s ) ) ;
struct mansession_session * session = ast_calloc ( 1 , sizeof ( * session ) ) ;
struct mansession s = { . session = NULL , } ;
int flags ;
int res ;
if ( s = = NULL )
if ( s ession = = NULL )
goto done ;
s - > writetimeout = 100 ;
s - > waiting_thread = AST_PTHREADT_NULL ;
s ession - > writetimeout = 100 ;
s ession - > waiting_thread = AST_PTHREADT_NULL ;
flags = fcntl ( ser - > fd , F_GETFL ) ;
if ( ! block_sockets ) /* make sure socket is non-blocking */
@ -3110,37 +3158,38 @@ static void *session_do(void *data)
flags & = ~ O_NONBLOCK ;
fcntl ( ser - > fd , F_SETFL , flags ) ;
ast_mutex_init ( & s - > __lock ) ;
s - > send_events = - 1 ;
ast_mutex_init ( & s ession - > __lock ) ;
s ession - > send_events = - 1 ;
/* Hook to the tail of the event queue */
s - > last_ev = grab_last ( ) ;
s ession - > last_ev = grab_last ( ) ;
/* these fields duplicate those in the 'ser' structure */
s - > fd = ser - > fd ;
s - > f = ser - > f ;
s - > sin = ser - > remote_address ;
session - > fd = ser - > fd ;
session - > f = ser - > f ;
session - > sin = ser - > remote_address ;
s . session = session ;
AST_LIST_HEAD_INIT_NOLOCK ( & s - > datastores ) ;
AST_LIST_HEAD_INIT_NOLOCK ( & s ession - > datastores ) ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_INSERT_HEAD ( & sessions , s , list ) ;
AST_LIST_INSERT_HEAD ( & sessions , s ession , list ) ;
ast_atomic_fetchadd_int ( & num_sessions , 1 ) ;
AST_LIST_UNLOCK ( & sessions ) ;
astman_append ( s , " Asterisk Call Manager/%s \r \n " , AMI_VERSION ) ; /* welcome prompt */
astman_append ( & s , " Asterisk Call Manager/%s \r \n " , AMI_VERSION ) ; /* welcome prompt */
for ( ; ; ) {
if ( ( res = do_message ( s ) ) < 0 )
if ( ( res = do_message ( & s ) ) < 0 )
break ;
}
/* session is over, explain why and terminate */
if ( s - > authenticated ) {
if ( manager_displayconnects ( s ) )
ast_verb ( 2 , " Manager '%s' logged off from %s \n " , s - > username , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " Manager '%s' logged off from %s \n " , s - > username , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
if ( s ession - > authenticated ) {
if ( manager_displayconnects ( s ession ) )
ast_verb ( 2 , " Manager '%s' logged off from %s \n " , s ession - > username , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " Manager '%s' logged off from %s \n " , s ession - > username , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
} else {
if ( displayconnects )
ast_verb ( 2 , " Connect attempt from '%s' unable to authenticate \n " , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " Failed attempt from %s \n " , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_verb ( 2 , " Connect attempt from '%s' unable to authenticate \n " , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " Failed attempt from %s \n " , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
}
/* It is possible under certain circumstances for this session thread
@ -3156,7 +3205,7 @@ static void *session_do(void *data)
*/
usleep ( 1 ) ;
destroy_session ( s ) ;
destroy_session ( s ession ) ;
done :
ao2_ref ( ser , - 1 ) ;
@ -3167,19 +3216,19 @@ done:
/*! \brief remove at most n_max stale session from the list. */
static void purge_sessions ( int n_max )
{
struct mansession * s ;
struct mansession _session * s ession ;
time_t now = time ( NULL ) ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE_SAFE_BEGIN ( & sessions , s , list ) {
if ( s - > sessiontimeout & & ( now > s - > sessiontimeout ) & & ! s - > inuse ) {
AST_LIST_TRAVERSE_SAFE_BEGIN ( & sessions , s ession , list ) {
if ( s ession - > sessiontimeout & & ( now > s ession - > sessiontimeout ) & & ! s ession - > inuse ) {
AST_LIST_REMOVE_CURRENT ( list ) ;
ast_atomic_fetchadd_int ( & num_sessions , - 1 ) ;
if ( s - > authenticated & & ( VERBOSITY_ATLEAST ( 2 ) ) & & manager_displayconnects ( s ) ) {
if ( s ession - > authenticated & & ( VERBOSITY_ATLEAST ( 2 ) ) & & manager_displayconnects ( s ession ) ) {
ast_verb ( 2 , " HTTP Manager '%s' timed out from %s \n " ,
s - > username , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
s ession - > username , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
}
free_session ( s ) ; /* XXX outside ? */
free_session ( s ession ) ; /* XXX outside ? */
if ( - - n_max < = 0 )
break ;
}
@ -3222,7 +3271,7 @@ AST_THREADSTORAGE(manager_event_buf);
int __manager_event ( int category , const char * event ,
const char * file , int line , const char * func , const char * fmt , . . . )
{
struct mansession * s ;
struct mansession _session * s ession ;
struct manager_custom_hook * hook ;
struct ast_str * auth = ast_str_alloca ( 80 ) ;
const char * cat_str ;
@ -3267,18 +3316,18 @@ int __manager_event(int category, const char *event,
/* Wake up any sleeping sessions */
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE ( & sessions , s , list ) {
ast_mutex_lock ( & s - > __lock ) ;
if ( s - > waiting_thread ! = AST_PTHREADT_NULL )
pthread_kill ( s - > waiting_thread , SIGURG ) ;
AST_LIST_TRAVERSE ( & sessions , s ession , list ) {
ast_mutex_lock ( & s ession - > __lock ) ;
if ( s ession - > waiting_thread ! = AST_PTHREADT_NULL )
pthread_kill ( s ession - > waiting_thread , SIGURG ) ;
else
/* We have an event to process, but the mansession is
* not waiting for it . We still need to indicate that there
* is an event waiting so that get_input processes the pending
* event instead of polling .
*/
s - > pending_event = 1 ;
ast_mutex_unlock ( & s - > __lock ) ;
s ession - > pending_event = 1 ;
ast_mutex_unlock ( & s ession - > __lock ) ;
}
AST_LIST_UNLOCK ( & sessions ) ;
@ -3404,38 +3453,38 @@ static char *contenttype[] = {
* the value of the mansession_id cookie ( 0 is not valid and means
* a session on the AMI socket ) .
*/
static struct mansession * find_session ( uint32_t ident , int incinuse )
static struct mansession _session * find_session ( uint32_t ident , int incinuse )
{
struct mansession * s ;
struct mansession _session * s ession ;
if ( ident = = 0 )
return NULL ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE ( & sessions , s , list ) {
ast_mutex_lock ( & s - > __lock ) ;
if ( s - > managerid = = ident & & ! s - > needdestroy ) {
ast_atomic_fetchadd_int ( & s - > inuse , incinuse ? 1 : 0 ) ;
AST_LIST_TRAVERSE ( & sessions , s ession , list ) {
ast_mutex_lock ( & s ession - > __lock ) ;
if ( s ession - > managerid = = ident & & ! s ession - > needdestroy ) {
ast_atomic_fetchadd_int ( & s ession - > inuse , incinuse ? 1 : 0 ) ;
break ;
}
ast_mutex_unlock ( & s - > __lock ) ;
ast_mutex_unlock ( & s ession - > __lock ) ;
}
AST_LIST_UNLOCK ( & sessions ) ;
return s ;
return s ession ;
}
int astman_is_authed ( uint32_t ident )
{
int authed ;
struct mansession * s ;
struct mansession _session * s ession ;
if ( ! ( s = find_session ( ident , 0 ) ) )
if ( ! ( s ession = find_session ( ident , 0 ) ) )
return 0 ;
authed = ( s - > authenticated ! = 0 ) ;
authed = ( s ession - > authenticated ! = 0 ) ;
ast_mutex_unlock ( & s - > __lock ) ;
ast_mutex_unlock ( & s ession - > __lock ) ;
return authed ;
}
@ -3443,17 +3492,17 @@ int astman_is_authed(uint32_t ident)
int astman_verify_session_readpermissions ( uint32_t ident , int perm )
{
int result = 0 ;
struct mansession * s ;
struct mansession _session * s ession ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE ( & sessions , s , list ) {
ast_mutex_lock ( & s - > __lock ) ;
if ( ( s - > managerid = = ident ) & & ( s - > readperm & perm ) ) {
AST_LIST_TRAVERSE ( & sessions , s ession , list ) {
ast_mutex_lock ( & s ession - > __lock ) ;
if ( ( s ession - > managerid = = ident ) & & ( s ession - > readperm & perm ) ) {
result = 1 ;
ast_mutex_unlock ( & s - > __lock ) ;
ast_mutex_unlock ( & s ession - > __lock ) ;
break ;
}
ast_mutex_unlock ( & s - > __lock ) ;
ast_mutex_unlock ( & s ession - > __lock ) ;
}
AST_LIST_UNLOCK ( & sessions ) ;
return result ;
@ -3462,17 +3511,17 @@ int astman_verify_session_readpermissions(uint32_t ident, int perm)
int astman_verify_session_writepermissions ( uint32_t ident , int perm )
{
int result = 0 ;
struct mansession * s ;
struct mansession _session * s ession ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_TRAVERSE ( & sessions , s , list ) {
ast_mutex_lock ( & s - > __lock ) ;
if ( ( s - > managerid = = ident ) & & ( s - > writeperm & perm ) ) {
AST_LIST_TRAVERSE ( & sessions , s ession , list ) {
ast_mutex_lock ( & s ession - > __lock ) ;
if ( ( s ession - > managerid = = ident ) & & ( s ession - > writeperm & perm ) ) {
result = 1 ;
ast_mutex_unlock ( & s - > __lock ) ;
ast_mutex_unlock ( & s ession - > __lock ) ;
break ;
}
ast_mutex_unlock ( & s - > __lock ) ;
ast_mutex_unlock ( & s ession - > __lock ) ;
}
AST_LIST_UNLOCK ( & sessions ) ;
return result ;
@ -3713,7 +3762,8 @@ static struct ast_str *generic_http_callback(enum output_format format,
struct ast_variable * params , int * status ,
char * * title , int * contentlength )
{
struct mansession * s = NULL ;
struct mansession s = { . session = NULL , } ;
struct mansession_session * session = NULL ;
uint32_t ident = 0 ;
int blastaway = 0 ;
struct ast_variable * v ;
@ -3730,45 +3780,47 @@ static struct ast_str *generic_http_callback(enum output_format format,
}
}
if ( ! ( s = find_session ( ident , 1 ) ) ) {
if ( ! ( s ession = find_session ( ident , 1 ) ) ) {
/* 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 ession = ast_calloc ( 1 , sizeof ( * s ession ) ) ) ) {
* status = 500 ;
goto generic_callback_out ;
}
s - > sin = * remote_address ;
s - > fd = - 1 ;
s - > waiting_thread = AST_PTHREADT_NULL ;
s - > send_events = 0 ;
ast_mutex_init ( & s - > __lock ) ;
ast_mutex_lock ( & s - > __lock ) ;
s - > inuse = 1 ;
s ession - > sin = * remote_address ;
s ession - > fd = - 1 ;
s ession - > waiting_thread = AST_PTHREADT_NULL ;
s ession - > send_events = 0 ;
ast_mutex_init ( & s ession - > __lock ) ;
ast_mutex_lock ( & s ession - > __lock ) ;
s ession - > inuse = 1 ;
/*!\note There is approximately a 1 in 1.8E19 chance that the following
* calculation will produce 0 , which is an invalid ID , but due to the
* properties of the rand ( ) function ( and the constantcy of s ) , that
* won ' t happen twice in a row .
*/
while ( ( s - > managerid = rand ( ) ^ ( unsigned long ) s ) = = 0 ) ;
s - > last_ev = grab_last ( ) ;
AST_LIST_HEAD_INIT_NOLOCK ( & s - > datastores ) ;
while ( ( s ession - > managerid = rand ( ) ^ ( unsigned long ) s ession ) = = 0 ) ;
s ession - > last_ev = grab_last ( ) ;
AST_LIST_HEAD_INIT_NOLOCK ( & s ession - > datastores ) ;
AST_LIST_LOCK ( & sessions ) ;
AST_LIST_INSERT_HEAD ( & sessions , s , list ) ;
AST_LIST_INSERT_HEAD ( & sessions , s ession , list ) ;
ast_atomic_fetchadd_int ( & num_sessions , 1 ) ;
AST_LIST_UNLOCK ( & sessions ) ;
}
ast_mutex_unlock ( & s - > __lock ) ;
s . session = session ;
ast_mutex_unlock ( & session - > __lock ) ;
if ( ! ( out = ast_str_create ( 1024 ) ) ) {
* status = 500 ;
goto generic_callback_out ;
}
s - > fd = mkstemp ( template ) ; /* create a temporary file for command output */
s . fd = mkstemp ( template ) ; /* create a temporary file for command output */
unlink ( template ) ;
s - > f = fdopen ( s - > fd , " w+ " ) ;
s . f = fdopen ( s . fd , " w+ " ) ;
for ( x = 0 , v = params ; v & & ( x < AST_MAX_MANHEADERS ) ; x + + , v = v - > next ) {
hdrlen = strlen ( v - > name ) + strlen ( v - > value ) + 3 ;
@ -3778,19 +3830,19 @@ static struct ast_str *generic_http_callback(enum output_format format,
m . hdrcount = x + 1 ;
}
if ( process_message ( s , & m ) ) {
if ( s - > authenticated ) {
if ( manager_displayconnects ( s ) ) {
ast_verb ( 2 , " HTTP Manager '%s' logged off from %s \n " , s - > username , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
if ( process_message ( & s , & m ) ) {
if ( s ession - > authenticated ) {
if ( manager_displayconnects ( s ession ) ) {
ast_verb ( 2 , " HTTP Manager '%s' logged off from %s \n " , s ession - > username , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
}
ast_log ( LOG_EVENT , " HTTP Manager '%s' logged off from %s \n " , s - > username , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " HTTP Manager '%s' logged off from %s \n " , s ession - > username , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
} else {
if ( displayconnects ) {
ast_verb ( 2 , " HTTP Connect attempt from '%s' unable to authenticate \n " , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_verb ( 2 , " HTTP Connect attempt from '%s' unable to authenticate \n " , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
}
ast_log ( LOG_EVENT , " HTTP Failed attempt from %s \n " , ast_inet_ntoa ( s - > sin . sin_addr ) ) ;
ast_log ( LOG_EVENT , " HTTP Failed attempt from %s \n " , ast_inet_ntoa ( s ession - > sin . sin_addr ) ) ;
}
s - > needdestroy = 1 ;
s ession - > needdestroy = 1 ;
}
ast_str_append ( & out , 0 ,
@ -3800,7 +3852,7 @@ static struct ast_str *generic_http_callback(enum output_format format,
" Pragma: SuppressEvents \r \n "
" \r \n " ,
contenttype [ format ] ,
s - > managerid , httptimeout ) ;
s ession - > managerid , httptimeout ) ;
if ( format = = FORMAT_XML ) {
ast_str_append ( & out , 0 , " <ajax-response> \n " ) ;
@ -3832,12 +3884,12 @@ static struct ast_str *generic_http_callback(enum output_format format,
ast_str_append ( & out , 0 , ROW_FMT , TEST_STRING ) ;
}
if ( s - > f ! = NULL ) { /* have temporary output */
if ( s . f ! = NULL ) { /* have temporary output */
char * buf ;
size_t l = ftell ( s - > f ) ;
size_t l = ftell ( s . f ) ;
if ( l ) {
if ( ( buf = mmap ( NULL , l , PROT_READ | PROT_WRITE , MAP_SHARED , s - > fd , 0 ) ) ) {
if ( ( buf = mmap ( NULL , l , PROT_READ | PROT_WRITE , MAP_SHARED , s . fd , 0 ) ) ) {
if ( format = = FORMAT_XML | | format = = FORMAT_HTML )
xml_translate ( & out , buf , params , format ) ;
else
@ -3847,9 +3899,9 @@ static struct ast_str *generic_http_callback(enum output_format format,
} else if ( format = = FORMAT_XML | | format = = FORMAT_HTML ) {
xml_translate ( & out , " " , params , format ) ;
}
fclose ( s - > f ) ;
s - > f = NULL ;
s - > fd = - 1 ;
fclose ( s . f ) ;
s . f = NULL ;
s . fd = - 1 ;
}
if ( format = = FORMAT_XML ) {
@ -3857,26 +3909,26 @@ static struct ast_str *generic_http_callback(enum output_format format,
} else if ( format = = FORMAT_HTML )
ast_str_append ( & out , 0 , " </table></body> \r \n " ) ;
ast_mutex_lock ( & s - > __lock ) ;
ast_mutex_lock ( & s ession - > __lock ) ;
/* Reset HTTP timeout. If we're not authenticated, keep it extremely short */
s - > sessiontimeout = time ( NULL ) + ( ( s - > authenticated | | httptimeout < 5 ) ? httptimeout : 5 ) ;
s ession - > sessiontimeout = time ( NULL ) + ( ( s ession - > authenticated | | httptimeout < 5 ) ? httptimeout : 5 ) ;
if ( s - > needdestroy ) {
if ( s - > inuse = = 1 ) {
if ( s ession - > needdestroy ) {
if ( s ession - > inuse = = 1 ) {
ast_debug ( 1 , " Need destroy, doing it now! \n " ) ;
blastaway = 1 ;
} else {
ast_debug ( 1 , " Need destroy, but can't do it yet! \n " ) ;
if ( s - > waiting_thread ! = AST_PTHREADT_NULL )
pthread_kill ( s - > waiting_thread , SIGURG ) ;
s - > inuse - - ;
if ( s ession - > waiting_thread ! = AST_PTHREADT_NULL )
pthread_kill ( s ession - > waiting_thread , SIGURG ) ;
s ession - > inuse - - ;
}
} else
s - > inuse - - ;
ast_mutex_unlock ( & s - > __lock ) ;
s ession - > inuse - - ;
ast_mutex_unlock ( & s ession - > __lock ) ;
if ( blastaway )
destroy_session ( s ) ;
destroy_session ( s ession ) ;
generic_callback_out :
if ( * status ! = 200 )
return ast_http_error ( 500 , " Server Error " , NULL , " Internal Server Error (out of memory) \ n " ) ;
@ -4286,14 +4338,14 @@ int reload_manager(void)
int astman_datastore_add ( struct mansession * s , struct ast_datastore * datastore )
{
AST_LIST_INSERT_HEAD ( & s - > datastores, datastore , entry ) ;
AST_LIST_INSERT_HEAD ( & s - > session- > datastores, datastore , entry ) ;
return 0 ;
}
int astman_datastore_remove ( struct mansession * s , struct ast_datastore * datastore )
{
return AST_LIST_REMOVE ( & s - > datastores, datastore , entry ) ? 0 : - 1 ;
return AST_LIST_REMOVE ( & s - > session- > datastores, datastore , entry ) ? 0 : - 1 ;
}
struct ast_datastore * astman_datastore_find ( struct mansession * s , const struct ast_datastore_info * info , const char * uid )
@ -4303,7 +4355,7 @@ struct ast_datastore *astman_datastore_find(struct mansession *s, const struct a
if ( info = = NULL )
return NULL ;
AST_LIST_TRAVERSE_SAFE_BEGIN ( & s - > datastores, datastore , entry ) {
AST_LIST_TRAVERSE_SAFE_BEGIN ( & s - > session- > datastores, datastore , entry ) {
if ( datastore - > info ! = info ) {
continue ;
}