[asterisk-commits] oej: branch oej/codename-pineapple r47624 - in
/team/oej/codename-pineapple/c...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Tue Nov 14 14:27:21 MST 2006
Author: oej
Date: Tue Nov 14 15:27:21 2006
New Revision: 47624
URL: http://svn.digium.com/view/asterisk?view=rev&rev=47624
Log:
Moving around stuff
Added:
team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c (with props)
Modified:
team/oej/codename-pineapple/channels/Makefile
team/oej/codename-pineapple/channels/chan_sip3.c
team/oej/codename-pineapple/channels/sip3/Makefile
team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
team/oej/codename-pineapple/channels/sip3/sip3_parse.c
team/oej/codename-pineapple/channels/sip3/sip3_refer.c
team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c
team/oej/codename-pineapple/channels/sip3/sip3_utils.c
team/oej/codename-pineapple/channels/sip3/sip3funcs.h
Modified: team/oej/codename-pineapple/channels/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/Makefile?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/Makefile (original)
+++ team/oej/codename-pineapple/channels/Makefile Tue Nov 14 15:27:21 2006
@@ -16,7 +16,7 @@
SIP3_MODULES=chan_sip3.o sip3/sip3_network.o sip3/sip3_subscribe.o sip3/sip3_refer.o sip3/sip3_domain.o \
sip3/sip3_callerid.o sip3/sip3_auth.o sip3/sip3_sdprtp.o sip3/sip3_config.o \
sip3/sip3_cliami.o sip3/sip3_dialog.o sip3/sip3_services.o sip3/sip3_compose.o \
- sip3/sip3_parse.o sip3/sip3_utils.o
+ sip3/sip3_parse.o sip3/sip3_utils.o sip3/sip3_pokedevice.o
ifeq ($(OSARCH),OpenBSD)
PTLIB=-lpt_OpenBSD_x86_r
Modified: team/oej/codename-pineapple/channels/chan_sip3.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/chan_sip3.c?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/chan_sip3.c (original)
+++ team/oej/codename-pineapple/channels/chan_sip3.c Tue Nov 14 15:27:21 2006
@@ -474,7 +474,6 @@
/*--- Dialog management */
static int auto_congest(void *nothing);
-static int update_call_counter(struct sip_dialog *fup, int event);
static void list_route(struct sip_route *route);
static void build_route(struct sip_dialog *p, struct sip_request *req, int backwards);
static enum check_auth_result register_verify(struct sip_dialog *p, struct sockaddr_in *sin,
@@ -502,9 +501,6 @@
/*--- Device monitoring and Device/extension state handling */
static int cb_extensionstate(char *context, char* exten, int state, void *data);
static int sip_devicestate(void *data);
-static int sip_poke_noanswer(void *data);
-static int sip_poke_peer(struct sip_peer *peer);
-static void sip_poke_all_peers(void);
/*--- Applications, functions, CLI and manager command helpers */
GNURK int sip_notify(int fd, int argc, char *argv[]);
@@ -524,11 +520,8 @@
/*--- Device object handling */
static struct sip_peer *temp_peer(const char *name);
-static int update_call_counter(struct sip_dialog *fup, int event);
-static int sip_poke_peer(struct sip_peer *peer);
static struct sip_peer *temp_peer(const char *name);
static void register_peer_exten(struct sip_peer *peer, int onoff);
-static int sip_poke_peer_s(void *data);
static enum parse_register_result parse_register_contact(struct sip_dialog *pvt, struct sip_peer *p, struct sip_request *req);
/* Realtime device support */
@@ -561,7 +554,6 @@
/*------Response handling functions */
static void handle_response_invite(struct sip_dialog *p, int resp, char *rest, struct sip_request *req);
static void handle_response_refer(struct sip_dialog *p, int resp, char *rest, struct sip_request *req);
-static void handle_response_peerpoke(struct sip_dialog *p, int resp, struct sip_request *req);
static void handle_response(struct sip_dialog *p, int resp, char *rest, struct sip_request *req);
/*------ T38 Support --------- */
@@ -807,7 +799,7 @@
/*! \brief Destroy device object from memory */
GNURK void sip_destroy_device(struct sip_peer *device)
{
- logdebug(3, "Destroying SIP %s %s\n", device->type & SIP_USER ? "user" : "peer", device->name);
+ logdebug(3, "Destroying SIP device %s\n", device->name);
//if (option_debug > 2)
//ast_log(LOG_DEBUG, "Destroying SIP %s %s\n", device->type & SIP_USER ? "user" : "peer", device->name);
@@ -1203,7 +1195,7 @@
* -1 on rejection of call
*
*/
-static int update_call_counter(struct sip_dialog *fup, int event)
+GNURK int update_call_counter(struct sip_dialog *fup, int event)
{
char name[256];
int outgoing = ast_test_flag(&fup->flags[0], SIP_OUTGOING);
@@ -1694,8 +1686,7 @@
break;
case AST_CONTROL_BUSY:
if (ast->_state != AST_STATE_UP) {
- transmit_response(p, "486 Busy Here", &p->initreq);
- ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
+ transmit_final_response(p, "486 Busy Here", &p->initreq, XMIT_RELIABLE);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
break;
}
@@ -1703,8 +1694,7 @@
break;
case AST_CONTROL_CONGESTION:
if (ast->_state != AST_STATE_UP) {
- transmit_response(p, "503 Service Unavailable", &p->initreq);
- ast_set_flag(&p->flags[0], SIP_ALREADYGONE);
+ transmit_final_response(p, "503 Service Unavailable", &p->initreq, XMIT_RELIABLE);
ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
break;
}
@@ -2423,167 +2413,6 @@
return send_request(p, &req, init ? XMIT_CRITICAL : XMIT_RELIABLE, p->ocseq);
}
-/*! \brief Used in the SUBSCRIBE notification subsystem */
-GNURK int transmit_state_notify(struct sip_dialog *p, int state, int full, int timeout)
-{
- char tmp[4000], from[256], to[256];
- char *t = tmp, *c, *mfrom, *mto;
- size_t maxbytes = sizeof(tmp);
- struct sip_request req;
- char hint[AST_MAX_EXTENSION];
- char *statestring = "terminated";
- const struct cfsubscription_types *subscriptiontype;
- enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN;
- char *pidfstate = "--";
- char *pidfnote= "Ready";
-
- memset(from, 0, sizeof(from));
- memset(to, 0, sizeof(to));
- memset(tmp, 0, sizeof(tmp));
-
- switch (state) {
- case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE):
- statestring = (global.notifyringing) ? "early" : "confirmed";
- local_state = NOTIFY_INUSE;
- pidfstate = "busy";
- pidfnote = "Ringing";
- break;
- case AST_EXTENSION_RINGING:
- statestring = "early";
- local_state = NOTIFY_INUSE;
- pidfstate = "busy";
- pidfnote = "Ringing";
- break;
- case AST_EXTENSION_INUSE:
- statestring = "confirmed";
- local_state = NOTIFY_INUSE;
- pidfstate = "busy";
- pidfnote = "On the phone";
- break;
- case AST_EXTENSION_BUSY:
- statestring = "confirmed";
- local_state = NOTIFY_CLOSED;
- pidfstate = "busy";
- pidfnote = "On the phone";
- break;
- case AST_EXTENSION_UNAVAILABLE:
- statestring = "confirmed";
- local_state = NOTIFY_CLOSED;
- pidfstate = "away";
- pidfnote = "Unavailable";
- break;
- case AST_EXTENSION_ONHOLD:
- break;
- case AST_EXTENSION_NOT_INUSE:
- default:
- /* Default setting */
- break;
- }
-
- subscriptiontype = find_subscription_type(p->subscribed);
-
- /* Check which device/devices we are watching and if they are registered */
- if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) {
- /* If they are not registered, we will override notification and show no availability */
- if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
- local_state = NOTIFY_CLOSED;
- pidfstate = "away";
- pidfnote = "Not online";
- }
- }
-
- ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from));
- c = get_in_brackets(from);
- if (strncmp(c, "sip:", 4)) {
- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
- return -1;
- }
- mfrom = strsep(&c, ";"); /* trim ; and beyond */
-
- ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
- c = get_in_brackets(to);
- if (strncmp(c, "sip:", 4)) {
- ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
- return -1;
- }
- mto = strsep(&c, ";"); /* trim ; and beyond */
-
- reqprep(&req, p, SIP_NOTIFY, 0, TRUE);
-
-
- add_header(&req, "Event", subscriptiontype->event);
- add_header(&req, "Content-Type", subscriptiontype->mediatype);
- switch(state) {
- case AST_EXTENSION_DEACTIVATED:
- if (timeout)
- add_header(&req, "Subscription-State", "terminated;reason=timeout");
- else {
- add_header(&req, "Subscription-State", "terminated;reason=probation");
- add_header(&req, "Retry-After", "60");
- }
- break;
- case AST_EXTENSION_REMOVED:
- add_header(&req, "Subscription-State", "terminated;reason=noresource");
- break;
- default:
- if (p->expiry)
- add_header(&req, "Subscription-State", "active");
- else /* Expired */
- add_header(&req, "Subscription-State", "terminated;reason=timeout");
- }
- switch (p->subscribed) {
- case XPIDF_XML:
- case CPIM_PIDF_XML:
- ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
- ast_build_string(&t, &maxbytes, "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n");
- ast_build_string(&t, &maxbytes, "<presence>\n");
- ast_build_string(&t, &maxbytes, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom);
- ast_build_string(&t, &maxbytes, "<atom id=\"%s\">\n", p->exten);
- ast_build_string(&t, &maxbytes, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto);
- ast_build_string(&t, &maxbytes, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed");
- ast_build_string(&t, &maxbytes, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline");
- ast_build_string(&t, &maxbytes, "</address>\n</atom>\n</presence>\n");
- break;
- case PIDF_XML: /* Eyebeam supports this format */
- ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
- ast_build_string(&t, &maxbytes, "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \nxmlns:pp=\"urn:ietf:params:xml:ns:pidf:person\"\nxmlns:es=\"urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status\"\nxmlns:ep=\"urn:ietf:params:xml:ns:pidf:rpid:rpid-person\"\nentity=\"%s\">\n", mfrom);
- ast_build_string(&t, &maxbytes, "<pp:person><status>\n");
- if (pidfstate[0] != '-')
- ast_build_string(&t, &maxbytes, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate);
- ast_build_string(&t, &maxbytes, "</status></pp:person>\n");
- ast_build_string(&t, &maxbytes, "<note>%s</note>\n", pidfnote); /* Note */
- ast_build_string(&t, &maxbytes, "<tuple id=\"%s\">\n", p->exten); /* Tuple start */
- ast_build_string(&t, &maxbytes, "<contact priority=\"1\">%s</contact>\n", mto);
- if (pidfstate[0] == 'b') /* Busy? Still open ... */
- ast_build_string(&t, &maxbytes, "<status><basic>open</basic></status>\n");
- else
- ast_build_string(&t, &maxbytes, "<status><basic>%s</basic></status>\n", (local_state != NOTIFY_CLOSED) ? "open" : "closed");
- ast_build_string(&t, &maxbytes, "</tuple>\n</presence>\n");
- break;
- case DIALOG_INFO_XML: /* SNOM subscribes in this format */
- ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
- ast_build_string(&t, &maxbytes, "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" version=\"%d\" state=\"%s\" entity=\"%s\">\n", p->dialogver++, full ? "full":"partial", mto);
- if ((state & AST_EXTENSION_RINGING) && global.notifyringing)
- ast_build_string(&t, &maxbytes, "<dialog id=\"%s\" direction=\"recipient\">\n", p->exten);
- else
- ast_build_string(&t, &maxbytes, "<dialog id=\"%s\">\n", p->exten);
- ast_build_string(&t, &maxbytes, "<state>%s</state>\n", statestring);
- ast_build_string(&t, &maxbytes, "</dialog>\n</dialog-info>\n");
- break;
- case NONE:
- default:
- break;
- }
-
- if (t > tmp + sizeof(tmp))
- ast_log(LOG_WARNING, "Buffer overflow detected!! (Please file a bug report)\n");
-
- add_header_contentLength(&req, strlen(tmp));
- add_line(&req, tmp);
-
- return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
-}
-
/*! \brief Notify user of messages waiting in voicemail
\note - Notification only works for registered peers with mailbox= definitions
in sip.conf
@@ -2629,30 +2458,6 @@
if (!p->initreq.headers) /* Initialize first request before sending */
initialize_initreq(p, req);
return send_request(p, req, XMIT_UNRELIABLE, p->ocseq);
-}
-
-/*! \brief Notify a transferring party of the status of transfer */
-GNURK int transmit_notify_with_sipfrag(struct sip_dialog *p, int cseq, char *message, int terminate)
-{
- struct sip_request req;
- char tmp[BUFSIZ/2];
-
- reqprep(&req, p, SIP_NOTIFY, 0, TRUE);
- snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
- add_header(&req, "Event", tmp);
- add_header(&req, "Subscription-state", terminate ? "terminated;reason=noresource" : "active");
- add_header(&req, "Content-Type", "message/sipfrag;version=2.0");
- add_header(&req, "Allow", ALLOWED_METHODS);
- add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
-
- snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
- add_header_contentLength(&req, strlen(tmp));
- add_line(&req, tmp);
-
- if (!p->initreq.headers)
- initialize_initreq(p, &req);
-
- return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
}
/*! \brief Transmit text with SIP MESSAGE method */
@@ -2839,16 +2644,6 @@
ASTOBJ_UNREF(peer, sip_destroy_device); /* Remove from memory */
}
- return 0;
-}
-
-/*! \brief Poke peer (send qualify to check if peer is alive and well) */
-static int sip_poke_peer_s(void *data)
-{
- struct sip_peer *peer = data;
-
- peer->pokeexpire = -1;
- sip_poke_peer(peer);
return 0;
}
@@ -4834,55 +4629,6 @@
}
}
-
-/*! \brief Handle qualification responses (OPTIONS) */
-static void handle_response_peerpoke(struct sip_dialog *p, int resp, struct sip_request *req)
-{
- struct sip_peer *peer = p->relatedpeer;
- int statechanged, is_reachable, was_reachable;
- int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps);
-
- /*
- * Compute the response time to a ping (goes in peer->lastms.)
- * -1 means did not respond, 0 means unknown,
- * 1..maxms is a valid response, >maxms means late response.
- */
- if (pingtime < 1) /* zero = unknown, so round up to 1 */
- pingtime = 1;
-
- /* Now determine new state and whether it has changed.
- * Use some helper variables to simplify the writing
- * of the expressions.
- */
- was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms;
- is_reachable = pingtime <= peer->maxms;
- statechanged = peer->lastms == 0 /* yes, unknown before */
- || was_reachable != is_reachable;
-
- peer->lastms = pingtime;
- peer->call = NULL;
- if (statechanged) {
- const char *s = is_reachable ? "Reachable" : "Lagged";
-
- ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n",
- peer->name, s, pingtime, peer->maxms);
- ast_device_state_changed("SIP/%s", peer->name);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
- "Peer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
- peer->name, s, pingtime);
- }
-
- if (peer->pokeexpire > -1)
- ast_sched_del(sched, peer->pokeexpire);
-
- /* Try again eventually */
- peer->pokeexpire = ast_sched_add(sched,
- is_reachable ? global.default_qualifycheck_ok: global.default_qualifycheck_notok,
- sip_poke_peer_s, peer);
-
- dialogstatechange(p, DIALOG_STATE_TERMINATED);
- ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
-}
/*! \brief Handle SIP response in dialogue */
/* XXX only called by handle_request */
@@ -6845,87 +6591,6 @@
return 0;
}
-/*! \brief React to lack of answer to Qualify poke */
-static int sip_poke_noanswer(void *data)
-{
- struct sip_peer *peer = data;
-
- peer->pokeexpire = -1;
- if (peer->lastms > -1) {
- ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms);
- manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1);
- }
- if (peer->call)
- sip_destroy(peer->call);
- peer->call = NULL;
- peer->lastms = -1;
- ast_device_state_changed("SIP/%s", peer->name);
- /* Try again quickly */
- peer->pokeexpire = ast_sched_add(sched, global.default_qualifycheck_notok, sip_poke_peer_s, peer);
- return 0;
-}
-
-/*! \brief Check availability of peer, also keep NAT open
-\note This is done with the interval in qualify= configuration option
- Default is 2 seconds */
-static int sip_poke_peer(struct sip_peer *peer)
-{
- struct sip_dialog *p;
-
- if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
- /* IF we have no IP, or this isn't to be monitored, return
- imeediately after clearing things out */
- if (peer->pokeexpire > -1)
- ast_sched_del(sched, peer->pokeexpire);
- peer->lastms = 0;
- peer->pokeexpire = -1;
- peer->call = NULL;
- return 0;
- }
- if (peer->call > 0) {
- if (sipdebug)
- ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
- sip_destroy(peer->call);
- }
- if (!(p = peer->call = sip_alloc(NULL, NULL, FALSE, SIP_OPTIONS)))
- return -1;
-
- p->sa = peer->addr;
- p->recv = peer->addr;
- ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
- ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
-
- /* Send OPTIONs to peer's fullcontact */
- if (!ast_strlen_zero(peer->fullcontact))
- ast_string_field_set(p, fullcontact, peer->fullcontact);
-
- if (!ast_strlen_zero(peer->tohost))
- ast_string_field_set(p, tohost, peer->tohost);
- else
- ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr));
-
- /* Recalculate our side, and recalculate Call ID */
- if (sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
- p->ourip = sipnet.__ourip;
- build_via(p, FALSE);
- build_callid_pvt(p);
-
- if (peer->pokeexpire > -1)
- ast_sched_del(sched, peer->pokeexpire);
- p->relatedpeer = peer;
- ast_set_flag(&p->flags[0], SIP_OUTGOING);
-#ifdef VOCAL_DATA_HACK
- ast_copy_string(p->peername, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->peername));
- transmit_invite(p, SIP_INVITE, FALSE, 2);
-#else
- transmit_invite(p, SIP_OPTIONS, FALSE, 2);
-#endif
- gettimeofday(&peer->ps, NULL);
- peer->pokeexpire = ast_sched_add(sched, DEFAULT_QUALIFY_MAXMS * 2, sip_poke_noanswer, peer);
-
- return 0;
-}
-
/*! \brief Part of PBX channel interface
\note
\par Return values:---
@@ -7340,28 +7005,6 @@
return -1;
}
-/*! \brief 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?
-*/
-static void sip_poke_all_peers(void)
-{
- int ms = 0;
-
- if (!sipcounters.static_peers) /* No peers, just give up */
- return;
-
- ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do {
- ASTOBJ_WRLOCK(iterator);
- if (iterator->pokeexpire > -1)
- ast_sched_del(sched, iterator->pokeexpire);
- ms += 100;
- iterator->pokeexpire = ast_sched_add(sched, ms, sip_poke_peer_s, iterator);
- ASTOBJ_UNLOCK(iterator);
- } while (0)
- );
-}
-
/*! \brief Reload module */
GNURK int sip_do_reload(enum channelreloadreason reason)
{
Modified: team/oej/codename-pineapple/channels/sip3/Makefile
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/Makefile?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/Makefile (original)
+++ team/oej/codename-pineapple/channels/sip3/Makefile Tue Nov 14 15:27:21 2006
@@ -3,7 +3,7 @@
#
all: sip3_refer.o sip3_subscribe.o sip3_network.o sip3_domain.o sip3_callerid.o sip3_auth.o \
sip3_sdprtp.o sip3_config.o sip3_cliami.o sip3_dialog.o sip3_services.o \
- sip3_compose.o sip3_parse.o sip3_utils.o
+ sip3_compose.o sip3_parse.o sip3_utils.o sip3_pokedevice.o
%.o: %.c sip3funcs.h sip3.h
$(CC) $(CFLAGS) -c -o $@ $<
Modified: team/oej/codename-pineapple/channels/sip3/sip3_dialog.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_dialog.c?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_dialog.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_dialog.c Tue Nov 14 15:27:21 2006
@@ -117,7 +117,6 @@
/*! \brief A per-thread temporary pvt structure */
AST_THREADSTORAGE_CUSTOM(ts_temp_pvt, temp_pvt_init, temp_pvt_cleanup);
-
/*! \brief Protect the SIP dialog list (of sip_dialog's) */
AST_MUTEX_DEFINE_STATIC(dialoglock);
@@ -125,7 +124,7 @@
void dialoglist_lock(void)
{
ast_mutex_lock(&dialoglock);
- if (option_debug > 3)
+ if (sipdebug && option_debug > 4)
ast_log(LOG_DEBUG, "=== SIP dialog list: LOCKED\n");
}
@@ -133,7 +132,7 @@
void dialoglist_unlock(void)
{
ast_mutex_unlock(&dialoglock);
- if (option_debug > 3)
+ if (sipdebug && option_debug > 4)
ast_log(LOG_DEBUG, "=== SIP dialog list: UNLOCKED\n");
}
@@ -142,6 +141,13 @@
*/
void dialog_lock(struct sip_dialog *dialog, int state)
{
+ if (!dialog) {
+ ast_log(LOG_ERROR, "-DIALOGLOCK- Trying to %s non-existing dialog. Giving up.\n", state ? "lock" : "unlock");
+ return;
+ }
+ if (sipdebug && option_debug > 4)
+ ast_log(LOG_DEBUG, "-DIALOGLOCK- %s dialog %s\n", state ? " locking" : "unlocking", dialog->callid ? dialog->callid : "<no callid>");
+
if (state)
ast_mutex_lock(&dialog->lock);
else
@@ -198,12 +204,15 @@
/*! \brief Transmit final response to a request and close dialog
Set dialog state to TERMINATED to avoid problems
+ At some point, after debugging, we can remove the reliable flag. Only responses to INVITEs are sent reliably
*/
int transmit_final_response(struct sip_dialog *dialog, const char *msg, const struct sip_request *req, enum xmittype reliable)
{
int res;
/* If this is a final response to an INVITE */
+ if (reliable == XMIT_RELIABLE && req->method != SIP_INVITE)
+ ast_log(LOG_WARNING, "Transmitting RELIABLE response to %s - Call ID %s (?? BUG ?? ) \n", sip_method2txt(req->method), dialog->callid);
res = __transmit_response(dialog, msg, req, reliable);
sip_scheddestroy(dialog, -1); /* Destroy by using T1 timer if available */
dialogstatechange(dialog, DIALOG_STATE_TERMINATED);
@@ -253,7 +262,7 @@
}
/*! \brief Pretend to ack all packets - nothing to do with SIP_ACK (the method)
- * maybe the lock on p is not strictly necessary but there might be a race */
+ * maybe the lock on p is not strictly necessary but there might be a race */
GNURK void __sip_pretend_ack(struct sip_dialog *dialog)
{
struct sip_request *cur = NULL;
@@ -302,6 +311,11 @@
{
struct sip_dialog *cur, *prev = NULL;
struct sip_request *cp;
+
+ if (ast_test_flag(&dialog->flags[0], SIP_INC_COUNT)) /* This dialog has incremented call count */
+ update_call_counter(dialog, DEC_CALL_LIMIT); /* Since it was forgotten, decrement call count */
+ if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_INC_RINGING)) /* This dialog has incremented ring count */
+ update_call_counter(dialog, DEC_CALL_RINGING); /* Since it was forgotten, decrement ring count */
if (sip_debug_test_pvt(dialog) || option_debug > 2)
ast_verbose("Really destroying SIP dialog '%s' Method: %s\n", dialog->callid, sip_method2txt(dialog->method));
Modified: team/oej/codename-pineapple/channels/sip3/sip3_parse.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_parse.c?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_parse.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_parse.c Tue Nov 14 15:27:21 2006
@@ -184,6 +184,13 @@
/*! \brief return text string for sip method */
char *sip_method2txt(int method)
{
+ int max = sizeof(sip_methods) / sizeof(sip_methods[0]);
+
+ if (method > max || method < 0) {
+ if (option_debug > 3)
+ ast_log(LOG_DEBUG, "Unknown SIP method %d given to this function. Strange... \n", method);
+ return "<unknown>";
+ }
return sip_methods[method].text;
}
Added: team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c?view=auto&rev=47624
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c (added)
+++ team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c Tue Nov 14 15:27:21 2006
@@ -1,0 +1,255 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 1999 - 2006, Digium, Inc.
+ * and Edvina AB, Sollentuna, Sweden (chan_sip3 changes/additions)
+ *
+ * Mark Spencer <markster at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief SIP qualification subsystem - poking around on the network
+ * Version 3 of chan_sip
+ *
+ * \author Mark Spencer <markster at digium.com>
+ * \author Olle E. Johansson <oej at edvina.net> (all the chan_sip3 changes)
+ *
+ * See Also:
+ * \arg \ref AstCREDITS
+ *
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#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/lock.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/acl.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"
+
+/*! \brief Poke peer (send qualify to check if peer is alive and well) */
+int sip_poke_peer_s(void *data)
+{
+ struct sip_peer *peer = data;
+
+ peer->pokeexpire = -1;
+ sip_poke_peer(peer);
+ return 0;
+}
+
+/*! \brief Handle qualification responses (OPTIONS) */
+void handle_response_peerpoke(struct sip_dialog *p, int resp, struct sip_request *req)
+{
+ struct sip_peer *peer = p->relatedpeer;
+ int statechanged, is_reachable, was_reachable;
+ int pingtime = ast_tvdiff_ms(ast_tvnow(), peer->ps);
+
+ /*
+ * Compute the response time to a ping (goes in peer->lastms.)
+ * -1 means did not respond, 0 means unknown,
+ * 1..maxms is a valid response, >maxms means late response.
+ */
+ if (pingtime < 1) /* zero = unknown, so round up to 1 */
+ pingtime = 1;
+
+ /* Now determine new state and whether it has changed.
+ * Use some helper variables to simplify the writing
+ * of the expressions.
+ */
+ was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms;
+ is_reachable = pingtime <= peer->maxms;
+ statechanged = peer->lastms == 0 /* yes, unknown before */
+ || was_reachable != is_reachable;
+
+ peer->lastms = pingtime;
+ peer->call = NULL;
+ if (statechanged) {
+ const char *s = is_reachable ? "Reachable" : "Lagged";
+
+ ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n",
+ peer->name, s, pingtime, peer->maxms);
+ ast_device_state_changed("SIP/%s", peer->name);
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
+ "Peer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
+ peer->name, s, pingtime);
+ }
+
+ if (peer->pokeexpire > -1)
+ ast_sched_del(sched, peer->pokeexpire);
+
+ /* Try again eventually */
+ peer->pokeexpire = ast_sched_add(sched,
+ is_reachable ? global.default_qualifycheck_ok: global.default_qualifycheck_notok,
+ sip_poke_peer_s, peer);
+
+ dialogstatechange(p, DIALOG_STATE_TERMINATED);
+ ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);
+}
+
+/*! \brief React to lack of answer to Qualify poke */
+int sip_poke_noanswer(void *data)
+{
+ struct sip_peer *peer = data;
+
+ peer->pokeexpire = -1;
+ if (peer->lastms > -1) {
+ ast_log(LOG_NOTICE, "Peer '%s' is now UNREACHABLE! Last qualify: %d\n", peer->name, peer->lastms);
+ manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "Peer: SIP/%s\r\nPeerStatus: Unreachable\r\nTime: %d\r\n", peer->name, -1);
+ }
+ if (peer->call)
+ sip_destroy(peer->call);
+ peer->call = NULL;
+ peer->lastms = -1;
+ ast_device_state_changed("SIP/%s", peer->name);
+ /* Try again quickly */
+ peer->pokeexpire = ast_sched_add(sched, global.default_qualifycheck_notok, sip_poke_peer_s, peer);
+ return 0;
+}
+
+/*! \brief Check availability of peer, also keep NAT open
+\note This is done with the interval in qualify= configuration option
+ Default is 2 seconds */
+int sip_poke_peer(struct sip_peer *peer)
+{
+ struct sip_dialog *p;
+
+ if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
+ /* IF we have no IP, or this isn't to be monitored, return
+ imeediately after clearing things out */
+ if (peer->pokeexpire > -1)
+ ast_sched_del(sched, peer->pokeexpire);
+ peer->lastms = 0;
+ peer->pokeexpire = -1;
+ peer->call = NULL;
+ return 0;
+ }
+ if (peer->call > 0) {
+ if (sipdebug)
+ ast_log(LOG_NOTICE, "Still have a QUALIFY dialog active, deleting\n");
+ sip_destroy(peer->call);
+ }
+ if (!(p = peer->call = sip_alloc(NULL, NULL, FALSE, SIP_OPTIONS)))
+ return -1;
+
+ p->sa = peer->addr;
+ p->recv = peer->addr;
+ ast_copy_flags(&p->flags[0], &peer->flags[0], SIP_FLAGS_TO_COPY);
+ ast_copy_flags(&p->flags[1], &peer->flags[1], SIP_PAGE2_FLAGS_TO_COPY);
+
+ /* Send OPTIONs to peer's fullcontact */
+ if (!ast_strlen_zero(peer->fullcontact))
+ ast_string_field_set(p, fullcontact, peer->fullcontact);
+
+ if (!ast_strlen_zero(peer->tohost))
+ ast_string_field_set(p, tohost, peer->tohost);
+ else
+ ast_string_field_set(p, tohost, ast_inet_ntoa(peer->addr.sin_addr));
+
+ /* Recalculate our side, and recalculate Call ID */
+ if (sip_ouraddrfor(&p->sa.sin_addr, &p->ourip))
+ p->ourip = sipnet.__ourip;
+ build_via(p, FALSE);
+ build_callid_pvt(p);
+
+ if (peer->pokeexpire > -1)
+ ast_sched_del(sched, peer->pokeexpire);
+ p->relatedpeer = peer;
+ ast_set_flag(&p->flags[0], SIP_OUTGOING);
+#ifdef VOCAL_DATA_HACK
+ ast_copy_string(p->peername, "__VOCAL_DATA_SHOULD_READ_THE_SIP_SPEC__", sizeof(p->peername));
+ transmit_invite(p, SIP_INVITE, FALSE, 2);
+#else
+ transmit_invite(p, SIP_OPTIONS, FALSE, 2);
+#endif
+ gettimeofday(&peer->ps, NULL);
+ peer->pokeexpire = ast_sched_add(sched, DEFAULT_QUALIFY_MAXMS * 2, sip_poke_noanswer, peer);
+
+ return 0;
+}
+
+/*! \brief 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?
+*/
+void sip_poke_all_peers(void)
+{
+ int ms = 0;
+
+ if (!sipcounters.static_peers) /* No peers, just give up */
+ return;
+
+ ASTOBJ_CONTAINER_TRAVERSE(&devicelist, 1, do {
+ ASTOBJ_WRLOCK(iterator);
+ if (iterator->pokeexpire > -1)
+ ast_sched_del(sched, iterator->pokeexpire);
+ ms += 100;
+ iterator->pokeexpire = ast_sched_add(sched, ms, sip_poke_peer_s, iterator);
+ ASTOBJ_UNLOCK(iterator);
+ } while (0)
+ );
+}
+
Propchange: team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/oej/codename-pineapple/channels/sip3/sip3_pokedevice.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: team/oej/codename-pineapple/channels/sip3/sip3_refer.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_refer.c?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_refer.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_refer.c Tue Nov 14 15:27:21 2006
@@ -978,3 +978,26 @@
return res;
}
+/*! \brief Notify a transferring party of the status of transfer */
+GNURK int transmit_notify_with_sipfrag(struct sip_dialog *p, int cseq, char *message, int terminate)
+{
+ struct sip_request req;
+ char tmp[BUFSIZ/2];
+
+ reqprep(&req, p, SIP_NOTIFY, 0, TRUE);
+ snprintf(tmp, sizeof(tmp), "refer;id=%d", cseq);
+ add_header(&req, "Event", tmp);
+ add_header(&req, "Subscription-state", terminate ? "terminated;reason=noresource" : "active");
+ add_header(&req, "Content-Type", "message/sipfrag;version=2.0");
+ add_header(&req, "Allow", ALLOWED_METHODS);
+ add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
+
+ snprintf(tmp, sizeof(tmp), "SIP/2.0 %s\r\n", message);
+ add_header_contentLength(&req, strlen(tmp));
+ add_line(&req, tmp);
+
+ if (!p->initreq.headers)
+ initialize_initreq(p, &req);
+
+ return send_request(p, &req, XMIT_RELIABLE, p->ocseq);
+}
Modified: team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c
URL: http://svn.digium.com/view/asterisk/team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c?view=diff&rev=47624&r1=47623&r2=47624
==============================================================================
--- team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c (original)
+++ team/oej/codename-pineapple/channels/sip3/sip3_subscribe.c Tue Nov 14 15:27:21 2006
@@ -129,3 +129,165 @@
}
return &subscription_types[0];
}
+
+/*! \brief Used in the SUBSCRIBE notification subsystem */
+GNURK int transmit_state_notify(struct sip_dialog *p, int state, int full, int timeout)
+{
+ char tmp[4000], from[256], to[256];
+ char *t = tmp, *c, *mfrom, *mto;
+ size_t maxbytes = sizeof(tmp);
+ struct sip_request req;
+ char hint[AST_MAX_EXTENSION];
+ char *statestring = "terminated";
+ const struct cfsubscription_types *subscriptiontype;
+ enum state { NOTIFY_OPEN, NOTIFY_INUSE, NOTIFY_CLOSED } local_state = NOTIFY_OPEN;
+ char *pidfstate = "--";
+ char *pidfnote= "Ready";
+
+ memset(from, 0, sizeof(from));
+ memset(to, 0, sizeof(to));
+ memset(tmp, 0, sizeof(tmp));
+
+ switch (state) {
+ case (AST_EXTENSION_RINGING | AST_EXTENSION_INUSE):
+ statestring = (global.notifyringing) ? "early" : "confirmed";
+ local_state = NOTIFY_INUSE;
+ pidfstate = "busy";
+ pidfnote = "Ringing";
+ break;
+ case AST_EXTENSION_RINGING:
+ statestring = "early";
+ local_state = NOTIFY_INUSE;
+ pidfstate = "busy";
+ pidfnote = "Ringing";
+ break;
+ case AST_EXTENSION_INUSE:
+ statestring = "confirmed";
+ local_state = NOTIFY_INUSE;
+ pidfstate = "busy";
+ pidfnote = "On the phone";
+ break;
+ case AST_EXTENSION_BUSY:
+ statestring = "confirmed";
+ local_state = NOTIFY_CLOSED;
+ pidfstate = "busy";
+ pidfnote = "On the phone";
+ break;
+ case AST_EXTENSION_UNAVAILABLE:
+ statestring = "confirmed";
+ local_state = NOTIFY_CLOSED;
+ pidfstate = "away";
+ pidfnote = "Unavailable";
+ break;
+ case AST_EXTENSION_ONHOLD:
+ break;
+ case AST_EXTENSION_NOT_INUSE:
+ default:
+ /* Default setting */
+ break;
+ }
+
+ subscriptiontype = find_subscription_type(p->subscribed);
+
+ /* Check which device/devices we are watching and if they are registered */
+ if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, p->context, p->exten)) {
+ /* If they are not registered, we will override notification and show no availability */
+ if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
+ local_state = NOTIFY_CLOSED;
+ pidfstate = "away";
+ pidfnote = "Not online";
+ }
+ }
+
+ ast_copy_string(from, get_header(&p->initreq, "From"), sizeof(from));
+ c = get_in_brackets(from);
+ if (strncmp(c, "sip:", 4)) {
+ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
+ return -1;
+ }
+ mfrom = strsep(&c, ";"); /* trim ; and beyond */
+
+ ast_copy_string(to, get_header(&p->initreq, "To"), sizeof(to));
+ c = get_in_brackets(to);
+ if (strncmp(c, "sip:", 4)) {
+ ast_log(LOG_WARNING, "Huh? Not a SIP header (%s)?\n", c);
+ return -1;
+ }
+ mto = strsep(&c, ";"); /* trim ; and beyond */
+
+ reqprep(&req, p, SIP_NOTIFY, 0, TRUE);
+
+
+ add_header(&req, "Event", subscriptiontype->event);
+ add_header(&req, "Content-Type", subscriptiontype->mediatype);
+ switch(state) {
+ case AST_EXTENSION_DEACTIVATED:
+ if (timeout)
+ add_header(&req, "Subscription-State", "terminated;reason=timeout");
+ else {
+ add_header(&req, "Subscription-State", "terminated;reason=probation");
+ add_header(&req, "Retry-After", "60");
+ }
+ break;
+ case AST_EXTENSION_REMOVED:
+ add_header(&req, "Subscription-State", "terminated;reason=noresource");
+ break;
+ default:
+ if (p->expiry)
+ add_header(&req, "Subscription-State", "active");
+ else /* Expired */
+ add_header(&req, "Subscription-State", "terminated;reason=timeout");
+ }
+ switch (p->subscribed) {
+ case XPIDF_XML:
+ case CPIM_PIDF_XML:
+ ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\"?>\n");
+ ast_build_string(&t, &maxbytes, "<!DOCTYPE presence PUBLIC \"-//IETF//DTD RFCxxxx XPIDF 1.0//EN\" \"xpidf.dtd\">\n");
+ ast_build_string(&t, &maxbytes, "<presence>\n");
+ ast_build_string(&t, &maxbytes, "<presentity uri=\"%s;method=SUBSCRIBE\" />\n", mfrom);
+ ast_build_string(&t, &maxbytes, "<atom id=\"%s\">\n", p->exten);
+ ast_build_string(&t, &maxbytes, "<address uri=\"%s;user=ip\" priority=\"0.800000\">\n", mto);
+ ast_build_string(&t, &maxbytes, "<status status=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "open" : (local_state == NOTIFY_INUSE) ? "inuse" : "closed");
+ ast_build_string(&t, &maxbytes, "<msnsubstatus substatus=\"%s\" />\n", (local_state == NOTIFY_OPEN) ? "online" : (local_state == NOTIFY_INUSE) ? "onthephone" : "offline");
+ ast_build_string(&t, &maxbytes, "</address>\n</atom>\n</presence>\n");
+ break;
+ case PIDF_XML: /* Eyebeam supports this format */
+ ast_build_string(&t, &maxbytes, "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n");
+ ast_build_string(&t, &maxbytes, "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" \nxmlns:pp=\"urn:ietf:params:xml:ns:pidf:person\"\nxmlns:es=\"urn:ietf:params:xml:ns:pidf:rpid:status:rpid-status\"\nxmlns:ep=\"urn:ietf:params:xml:ns:pidf:rpid:rpid-person\"\nentity=\"%s\">\n", mfrom);
+ ast_build_string(&t, &maxbytes, "<pp:person><status>\n");
+ if (pidfstate[0] != '-')
+ ast_build_string(&t, &maxbytes, "<ep:activities><ep:%s/></ep:activities>\n", pidfstate);
+ ast_build_string(&t, &maxbytes, "</status></pp:person>\n");
+ ast_build_string(&t, &maxbytes, "<note>%s</note>\n", pidfnote); /* Note */
+ ast_build_string(&t, &maxbytes, "<tuple id=\"%s\">\n", p->exten); /* Tuple start */
+ ast_build_string(&t, &maxbytes, "<contact priority=\"1\">%s</contact>\n", mto);
+ if (pidfstate[0] == 'b') /* Busy? Still open ... */
+ ast_build_string(&t, &maxbytes, "<status><basic>open</basic></status>\n");
+ else
[... 97 lines stripped ...]
More information about the asterisk-commits
mailing list