Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:52 2007

Asterisk developer's documentation :: Codename Pineapple


sip3_pokedevice.c File Reference


Detailed Description

SIP qualification subsystem - poking around on the network Version 3 of chan_sip.

Author:
Mark Spencer <markster@digium.com>

Olle E. Johansson <oej@edvina.net> (all the chan_sip3 changes)

See Also:

Definition in file sip3_pokedevice.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_pokedevice.c:

Go to the source code of this file.

Functions

void handle_response_peerpoke (struct sip_dialog *p, int resp, struct sip_request *req)
 Handle qualification responses (OPTIONS).
void sip_poke_all_peers (void)
 Send a poke to all known peers Space them out 100 ms apart XXX We might have a cool algorithm for this or use random - any suggestions?
int sip_poke_noanswer (void *data)
 React to lack of answer to Qualify poke.
int sip_poke_peer (struct sip_device *peer)
 Check availability of peer, also keep NAT open.
int sip_poke_peer_s (void *data)
 Poke peer (send qualify to check if peer is alive and well).


Function Documentation

void handle_response_peerpoke struct sip_dialog p,
int  resp,
struct sip_request req
 

Handle qualification responses (OPTIONS).

Definition at line 103 of file sip3_pokedevice.c.

References ast_device_state_changed(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag, sip_device::call, sip_globals::default_qualifycheck_notok, sip_globals::default_qualifycheck_ok, DIALOG_STATE_TERMINATED, dialogstatechange(), EVENT_FLAG_SYSTEM, sip_dialog::flags, global, sip_device::lastms, LOG_NOTICE, manager_event, sip_device::maxms, sip_device::pokeexpire, sip_device::ps, sip_dialog::relatedpeer, s, SIP_NEEDDESTROY, and sip_poke_peer_s().

00104 {
00105    struct sip_device *peer = p->relatedpeer;
00106    int statechanged, is_reachable, was_reachable;
00107    int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps);
00108       
00109    if (!peer)
00110       return;
00111 
00112    /*
00113     * Compute the response time to a ping (goes in peer->lastms.)
00114     * -1 means did not respond, 0 means unknown,
00115     * 1..maxms is a valid response, >maxms means late response.
00116     */
00117    if (pingtime < 1) /* zero = unknown, so round up to 1 */
00118       pingtime = 1;
00119 
00120    /* Now determine new state and whether it has changed.
00121     * Use some helper variables to simplify the writing
00122     * of the expressions.
00123     */
00124    was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms;
00125    is_reachable = pingtime <= peer->maxms;
00126    statechanged = peer->lastms == 0 /* yes, unknown before */
00127       || was_reachable != is_reachable;
00128 
00129    peer->lastms = pingtime;
00130    peer->call = NULL;
00131    if (statechanged) {
00132       const char *s = is_reachable ? "Reachable" : "Lagged";
00133 
00134       ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n",
00135          peer->name, s, pingtime, peer->maxms);
00136       ast_device_state_changed("SIP/%s", peer->name);
00137       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
00138          "Peer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
00139          peer->name, s, pingtime);
00140    }
00141 
00142    if (peer->pokeexpire > -1)
00143       ast_sched_del(sched, peer->pokeexpire);
00144 
00145    /* Try again eventually */
00146    peer->pokeexpire = ast_sched_add(sched,
00147       is_reachable ? global.default_qualifycheck_ok: global.default_qualifycheck_notok,
00148       sip_poke_peer_s, peer);
00149 
00150    dialogstatechange(p, DIALOG_STATE_TERMINATED);
00151    ast_set_flag(&p->flags[0], SIP_NEEDDESTROY); 
00152 }

void sip_poke_all_peers void   ) 
 

Send a poke to all known peers Space them out 100 ms apart XXX We might have a cool algorithm for this or use random - any suggestions?

Definition at line 239 of file sip3_pokedevice.c.

References ast_sched_add(), ast_sched_del(), ASTOBJ_CONTAINER_TRAVERSE, ASTOBJ_UNLOCK, ASTOBJ_WRLOCK, devicelist, sip_poke_peer_s(), sipcounters, and channel_counters::static_peers.

00240 {
00241    int ms = 0;
00242    
00243    if (!sipcounters.static_peers)   /* No peers, just give up */
00244       return;
00245 
00246    ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do {
00247       ASTOBJ_WRLOCK(iterator);
00248       if (iterator->pokeexpire > -1)
00249          ast_sched_del(sched, iterator->pokeexpire);
00250       ms += 100;
00251       iterator->pokeexpire = ast_sched_add(sched, ms, sip_poke_peer_s, iterator);
00252       ASTOBJ_UNLOCK(iterator);
00253    } while (0)
00254    );
00255 }

int sip_poke_noanswer void *  data  ) 
 

React to lack of answer to Qualify poke.

Definition at line 155 of file sip3_pokedevice.c.

References ast_device_state_changed(), ast_log(), ast_sched_add(), sip_device::call, sip_globals::default_qualifycheck_notok, EVENT_FLAG_SYSTEM, global, sip_device::lastms, LOG_NOTICE, manager_event, sip_device::pokeexpire, sip_destroy(), and sip_poke_peer_s().

00156 {
00157    struct sip_device *peer = data;
00158    
00159    peer->pokeexpire = -1;
00160    if (peer->lastms > -1) {
00161       ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE!  Last qualify: %d\n", peer->name, peer->lastms);
00162       manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1);
00163    }
00164    if (peer->call)
00165       sip_destroy(peer->call);
00166    peer->call = NULL;
00167    peer->lastms = -1;
00168    ast_device_state_changed("SIP/%s", peer->name);
00169    /* Try again quickly */
00170    peer->pokeexpire = ast_sched_add(sched, global.default_qualifycheck_notok, sip_poke_peer_s, peer);
00171    return 0;
00172 }

int sip_poke_peer struct sip_device peer  ) 
 

Check availability of peer, also keep NAT open.

Note:
This is done with the interval in qualify= configuration option Default is 2 seconds

Definition at line 177 of file sip3_pokedevice.c.

References sip_network::__ourip, sip_device::addr, ast_copy_flags, ast_inet_ntoa(), ast_log(), ast_sched_add(), ast_sched_del(), ast_set_flag, ast_string_field_set, ast_strlen_zero(), build_callid_pvt(), build_via(), sip_device::call, DEFAULT_QUALIFY_MAXMS, sip_device::extra, FALSE, sip_dialog::flags, sip_device::flags, sip_device::lastms, LOG_NOTICE, sip_device::maxms, sip_dialog::ourip, sip_device::pokeexpire, sip_device::ps, sip_dialog::recv, sip_dialog::relatedpeer, sip_dialog::sa, sip_alloc(), sip_destroy(), SIP_FLAGS_TO_COPY, SIP_INVITE, SIP_OPTIONS, sip_ouraddrfor(), SIP_OUTGOING, SIP_PAGE2_FLAGS_TO_COPY, sip_poke_noanswer(), sipdebug, sipnet, sip_device_extra::tohost, and transmit_invite().

00178 {
00179    struct sip_dialog *p;
00180 
00181    if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
00182       /* IF we have no IP, or this isn't to be monitored, return
00183         imeediately after clearing things out */
00184       if (peer->pokeexpire > -1)
00185          ast_sched_del(sched, peer->pokeexpire);
00186       peer->lastms = 0;
00187       peer->pokeexpire = -1;
00188       peer->call = NULL;
00189       return 0;
00190    }
00191    if (peer->call > 0) {
00192       if (sipdebug)
00193          ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
00194       sip_destroy(peer->call);
00195    }
00196    if (!(p = peer->call = sip_alloc(NULL, NULL, FALSE, SIP_OPTIONS)))
00197       return -1;
00198    
00199    p->sa = peer->addr;
00200    p->recv = peer->addr;
00201    ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
00202    ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
00203 
00204    /* Send OPTIONs to peer's fullcontact */
00205    if (!ast_strlen_zero(peer->fullcontact))
00206       ast_string_field_set(p, fullcontact, peer->fullcontact);
00207 
00208    if (!ast_strlen_zero(peer->extra.tohost))
00209       ast_string_field_set(p, tohost, peer->extra.tohost);
00210    else
00211       ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr));
00212 
00213    /* Recalculate our side, and recalculate Call ID */
00214    if (sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
00215       p->ourip = sipnet.__ourip;
00216    build_via(p, FALSE);
00217    build_callid_pvt(p);
00218 
00219    if (peer->pokeexpire > -1)
00220       ast_sched_del(sched, peer->pokeexpire);
00221    p->relatedpeer = peer;
00222    ast_set_flag(&p->flags[0], SIP_OUTGOING);
00223 #ifdef VOCAL_DATA_HACK
00224    ast_copy_string(p->peername, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->peername));
00225    transmit_invite(p, SIP_INVITE, FALSE, 2);
00226 #else
00227    transmit_invite(p, SIP_OPTIONS, FALSE, 2);
00228 #endif
00229    gettimeofday(&peer->ps, NULL);
00230    peer->pokeexpire = ast_sched_add(sched, DEFAULT_QUALIFY_MAXMS * 2, sip_poke_noanswer, peer);
00231 
00232    return 0;
00233 }

int sip_poke_peer_s void *  data  ) 
 

Poke peer (send qualify to check if peer is alive and well).

Definition at line 93 of file sip3_pokedevice.c.

References sip_device::pokeexpire, and sip_poke_peer().

00094 {
00095    struct sip_device *peer = data;
00096 
00097    peer->pokeexpire = -1;
00098    sip_poke_peer(peer);
00099    return 0;
00100 }


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen