![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
sip3_monitor.c File Reference
Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)
Definition in file sip3_monitor.c.
#include "asterisk.h"
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <regex.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/udptl.h"
#include "asterisk/acl.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/dsp.h"
#include "asterisk/features.h"
#include "asterisk/srv.h"
#include "asterisk/astdb.h"
#include "asterisk/causes.h"
#include "asterisk/utils.h"
#include "asterisk/file.h"
#include "asterisk/astobj.h"
#include "asterisk/dnsmgr.h"
#include "asterisk/devicestate.h"
#include "asterisk/linkedlists.h"
#include "asterisk/stringfields.h"
#include "asterisk/monitor.h"
#include "asterisk/localtime.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/compiler.h"
#include "sip3.h"
#include "sip3funcs.h"
Include dependency graph for sip3_monitor.c:

Go to the source code of this file.
Functions | |
| AST_MUTEX_DEFINE_STATIC (monlock) | |
| Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical. | |
| static void | check_rtp_timeout (struct sip_dialog *dialog, time_t t) |
| Check RTP timeouts and send RTP keepalives. | |
| void * | do_sip_monitor (void *data) |
| The SIP monitoring thread. | |
| static int | does_peer_need_mwi (struct sip_device *peer) |
| Check whether peer needs a new MWI notification check. | |
| void | kill_monitor (void) |
| kill monitor thread (only at module unload) | |
| int | restart_monitor (void) |
| Start the channel monitor thread. | |
Variables | |
| static pthread_t | monitor_thread = AST_PTHREADT_NULL |
| This is the thread for the monitor which checks for input on the channels which are not currently in use. | |
|
|
Protect the monitoring thread, so only one process can kill or start it, and not when it's doing something critical.
|
|
||||||||||||
|
Check RTP timeouts and send RTP keepalives.
Definition at line 158 of file sip3_monitor.c. References ast_channel::_state, ast_channel_trylock, ast_channel_unlock, ast_log(), ast_rtp_get_bridged(), ast_rtp_get_peer(), ast_rtp_get_rtpholdtimeout(), ast_rtp_get_rtpkeepalive(), ast_rtp_get_rtptimeout(), ast_rtp_sendcng(), ast_rtp_set_rtpholdtimeout(), ast_rtp_set_rtptimeout(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, dialog_lock(), FALSE, sip_dialog::lastrtprx, sip_dialog::lastrtptx, LOG_NOTICE, sip_dialog::owner, sip_dialog::redirip, sip_dialog::rtp, TRUE, and sip_dialog::vrtp. 00159 { 00160 /* If we have no RTP or no active owner, no need to check timers */ 00161 if (!dialog->rtp || !dialog->owner) 00162 return; 00163 /* If the call is not in UP state or redirected outside Asterisk, no need to check timers */ 00164 if (dialog->owner->_state != AST_STATE_UP || dialog->redirip.sin_addr.s_addr) 00165 return; 00166 00167 /* If we have no timers set, return now */ 00168 if (ast_rtp_get_rtpkeepalive(dialog->rtp) == 0 || (ast_rtp_get_rtptimeout(dialog->rtp) == 0 && ast_rtp_get_rtpholdtimeout(dialog->rtp) == 0)) 00169 return; 00170 00171 dialog_lock(dialog, TRUE); 00172 00173 /* Check AUDIO RTP keepalives */ 00174 if (dialog->lastrtptx && ast_rtp_get_rtpkeepalive(dialog->rtp) && 00175 (t > dialog->lastrtptx + ast_rtp_get_rtpkeepalive(dialog->rtp))) { 00176 /* Need to send an empty RTP packet */ 00177 dialog->lastrtptx = time(NULL); 00178 ast_rtp_sendcng(dialog->rtp, 0); 00179 } 00180 00181 /*! \todo Check video RTP keepalives 00182 00183 Do we need to move the lastrtptx to the RTP structure to have one for audio and one 00184 for video? It really does belong to the RTP structure. 00185 */ 00186 00187 /* Check AUDIO RTP timers */ 00188 if (dialog->lastrtprx && (ast_rtp_get_rtptimeout(dialog->rtp) || ast_rtp_get_rtpholdtimeout(dialog->rtp)) && 00189 (t > dialog->lastrtprx + ast_rtp_get_rtptimeout(dialog->rtp))) { 00190 00191 /* Might be a timeout now -- see if we're on hold */ 00192 struct sockaddr_in sin; 00193 ast_rtp_get_peer(dialog->rtp, &sin); 00194 if (sin.sin_addr.s_addr || (ast_rtp_get_rtpholdtimeout(dialog->rtp) && 00195 (t > dialog->lastrtprx + ast_rtp_get_rtpholdtimeout(dialog->rtp)))) { 00196 /* Needs a hangup */ 00197 if (ast_rtp_get_rtptimeout(dialog->rtp)) { 00198 while (dialog->owner && ast_channel_trylock(dialog->owner)) { 00199 dialog_lock(dialog, FALSE); 00200 usleep(1); 00201 dialog_lock(dialog, TRUE); 00202 } 00203 if (!(ast_rtp_get_bridged(dialog->rtp))) { 00204 ast_log(LOG_NOTICE, "Disconnecting call '%s' for lack of RTP activity in %ld seconds\n", 00205 dialog->owner->name, (long) (t - dialog->lastrtprx)); 00206 /* Issue a softhangup */ 00207 ast_softhangup_nolock(dialog->owner, AST_SOFTHANGUP_DEV); 00208 } else 00209 ast_log(LOG_NOTICE, "'%s' will not be disconnected in %ld seconds because it is directly bridged to another RTP stream\n", dialog->owner->name, (long) (t - dialog->lastrtprx)); 00210 ast_channel_unlock(dialog->owner); 00211 /* forget the timeouts for this call, since a hangup 00212 has already been requested and we don't want to 00213 repeatedly request hangups 00214 */ 00215 ast_rtp_set_rtptimeout(dialog->rtp, 0); 00216 ast_rtp_set_rtpholdtimeout(dialog->rtp, 0); 00217 if (dialog->vrtp) { 00218 ast_rtp_set_rtptimeout(dialog->vrtp, 0); 00219 ast_rtp_set_rtpholdtimeout(dialog->vrtp, 0); 00220 } 00221 } 00222 } 00223 } 00224 dialog_lock(dialog, FALSE); 00225 }
|
|
|
The SIP monitoring thread.
Definition at line 249 of file sip3_monitor.c. References ast_io_add(), ast_io_change(), AST_IO_IN, ast_verbose(), FALSE, io, option_verbose, sip_network::read_id, sip_do_reload(), sip_reload_check(), sipnet, sip_network::sipsock, sipsock_read(), sipsocket_initialized(), and VERBOSE_PREFIX_1. Referenced by restart_monitor(). 00250 { 00251 int res; 00252 struct sip_dialog *sip; 00253 struct sip_device *device = NULL; 00254 time_t now; 00255 int fastrestart = FALSE; 00256 int lastpeernum = -1; 00257 int curpeernum; 00258 static int nowalkmessage = 0; 00259 00260 /* Add an I/O event to our SIP UDP socket */ 00261 if (sipsocket_initialized(&sipnet)) 00262 sipnet.read_id = ast_io_add(io, sipnet.sipsock, sipsock_read, AST_IO_IN, NULL); 00263 00264 /* From here on out, we die whenever asked */ 00265 for(;;) { 00266 /*------ Check for a reload request */ 00267 if (sip_reload_check()) { 00268 if (option_verbose > 0) 00269 ast_verbose(VERBOSE_PREFIX_1 "Reloading SIP\n"); 00270 sip_do_reload(); 00271 00272 /* Change the I/O fd of our UDP socket */ 00273 if (sipsocket_initialized(&sipnet)) 00274 sipnet.read_id = ast_io_change(io, sipnet.read_id, sipnet.sipsock, NULL, 0, NULL); 00275 } 00276 00277 /*----- Check for interfaces needing to be killed */ 00278 if (dialoglist != NULL && !fastrestart) { 00279 struct sip_dialog *nextdialog; 00280 00281 if (option_debug > 4) 00282 ast_log(LOG_DEBUG, ":: MONITOR :: Walking dialog list.\n"); 00283 dialoglist_lock(); 00284 restartsearch: 00285 now = time(NULL); 00286 /* don't scan the interface list if it hasn't been a reasonable period 00287 of time since the last time we did it (when MWI is being sent, we can 00288 get back to this point every millisecond or less) 00289 */ 00290 for (sip = dialoglist; sip; sip = nextdialog) { 00291 nextdialog = sip->next; 00292 /* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP or RTCP */ 00293 check_rtp_timeout(sip, now); 00294 00295 /* If we have sessions that needs to be destroyed, do it now */ 00296 if (ast_test_flag(&sip->flags[0], SIP_NEEDDESTROY) && !sip->packets && !sip->owner) { 00297 __sip_destroy(sip, TRUE, FALSE); 00298 //goto restartsearch; 00299 } 00300 } 00301 dialoglist_unlock(); 00302 nowalkmessage = 0; 00303 } else if (!fastrestart && sipdebug && option_debug > 4) { 00304 if (!nowalkmessage) 00305 ast_log(LOG_DEBUG, ":: MONITOR :: Empty dialog list. Pausing channel walks\n"); 00306 nowalkmessage = 1; 00307 } 00308 00309 pthread_testcancel(); 00310 00311 /*------ Wait for sched or io */ 00312 res = ast_sched_wait(sched); 00313 00314 if ((res < 0) || (res > 1000)) 00315 res = 1000; 00316 /* If we might need to send more mailboxes, don't wait long at all.*/ 00317 if (fastrestart) 00318 res = 1; 00319 00320 res = ast_io_wait(io, res); 00321 if (option_debug && res > 20) 00322 ast_log(LOG_DEBUG, "chan_sip: ast_io_wait ran %d all at once\n", res); 00323 ast_mutex_lock(&monlock); 00324 if (res >= 0) { 00325 res = ast_sched_runq(sched); /* Check for scheduled items, like retransmits */ 00326 if (option_debug && res >= 20) 00327 ast_log(LOG_DEBUG, "chan_sip: ast_sched_runq ran %d all at once\n", res); 00328 } 00329 00330 /*----- Send MWI notifications to devices - static and cached realtime peers */ 00331 if (sipcounters.peers_with_mwi > 0 ) { 00332 fastrestart = FALSE; 00333 curpeernum = 0; 00334 device= NULL; 00335 /* Find next device that needs mwi */ 00336 ASTOBJ_CONTAINER_TRAVERSE(&devicelist, !device, do { 00337 if ((curpeernum > lastpeernum) && does_peer_need_mwi(iterator)) { 00338 fastrestart = TRUE; 00339 lastpeernum = curpeernum; 00340 device = device_ref(iterator); 00341 }; 00342 curpeernum++; 00343 } while (0) 00344 ); 00345 /* Send MWI to the peer */ 00346 if (device) { 00347 ASTOBJ_WRLOCK(device); 00348 sip_send_mwi_to_peer(device); 00349 ASTOBJ_UNLOCK(device); 00350 device_unref(device); 00351 } else { 00352 /* Reset where we come from */ 00353 lastpeernum = -1; 00354 } 00355 } 00356 ast_mutex_unlock(&monlock); 00357 } 00358 /* Never reached */ 00359 return NULL; 00360 00361 }
|
|
|
Check whether peer needs a new MWI notification check.
Definition at line 228 of file sip3_monitor.c. References ast_strlen_zero(), ast_test_flag, FALSE, sip_device::flags, global, sip_mwi_mailbox::lastmsgcheck, sip_device::mailbox, sip_mwi_mailbox::mwipvt, sip_globals::mwitime, SIP_PAGE2_SUBSCRIBEMWIONLY, and TRUE. 00229 { 00230 time_t t = time(NULL); 00231 00232 if (ast_test_flag(&peer->flags[1], SIP_PAGE2_SUBSCRIBEMWIONLY) && 00233 !peer->mailbox.mwipvt) { /* We don't have a subscription */ 00234 peer->mailbox.lastmsgcheck = t; /* Reset timer */ 00235 return FALSE; 00236 } 00237 00238 if (!ast_strlen_zero(peer->mailbox.mailbox) && (t - peer->mailbox.lastmsgcheck) > global.mwitime) 00239 return TRUE; 00240 00241 return FALSE; 00242 }
|
|
|
kill monitor thread (only at module unload)
Definition at line 111 of file sip3_monitor.c. References ast_mutex_lock(), ast_mutex_unlock(), and AST_PTHREADT_STOP. 00112 { 00113 /* Kill the monitor thread */ 00114 ast_mutex_lock(&monlock); 00115 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) { 00116 pthread_cancel(monitor_thread); 00117 pthread_kill(monitor_thread, SIGURG); 00118 pthread_join(monitor_thread, NULL); 00119 } 00120 monitor_thread = AST_PTHREADT_STOP; 00121 ast_mutex_unlock(&monlock); 00122 }
|
|
|
Start the channel monitor thread.
Definition at line 126 of file sip3_monitor.c. References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create_background, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_sip_monitor(), LOG_ERROR, and LOG_WARNING. 00127 { 00128 /* If we're supposed to be stopped -- stay stopped */ 00129 if (monitor_thread == AST_PTHREADT_STOP) 00130 return 0; 00131 /* Lock the monitor lock to keep the new monitor thread under control */ 00132 ast_mutex_lock(&monlock); 00133 if (monitor_thread == pthread_self()) { 00134 ast_mutex_unlock(&monlock); 00135 ast_log(LOG_WARNING, "Cannot kill myself\n"); 00136 return -1; 00137 } 00138 if (monitor_thread != AST_PTHREADT_NULL) { 00139 /* Wake up the thread */ 00140 pthread_kill(monitor_thread, SIGURG); 00141 } else { 00142 /* Start a new monitor */ 00143 if (ast_pthread_create_background(&monitor_thread, NULL, do_sip_monitor, NULL) < 0) { 00144 ast_mutex_unlock(&monlock); 00145 ast_log(LOG_ERROR, "Unable to start monitor thread.\n"); 00146 return -1; 00147 } 00148 } 00149 00150 /* Let the monitor run by itself now */ 00151 ast_mutex_unlock(&monlock); 00152 return 0; 00153 }
|
|
|
This is the thread for the monitor which checks for input on the channels which are not currently in use.
Definition at line 103 of file sip3_monitor.c. |