[svn-commits] oej: branch oej/pgtips-srv-and-outbound-stuff-1.8 r402707 - in /team/oej/pgti...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Tue Nov 12 04:22:02 CST 2013
Author: oej
Date: Tue Nov 12 04:21:48 2013
New Revision: 402707
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=402707
Log:
After flying around the world during October and November, I have a lot of new code to commit.
Modified:
team/oej/pgtips-srv-and-outbound-stuff-1.8/README.pgtips-srv-records
team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/chan_sip.c
team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/config_parser.c
team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/config_parser.h
team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/sip.h
team/oej/pgtips-srv-and-outbound-stuff-1.8/configs/sip.conf.sample
team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h
team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/README.pgtips-srv-records
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/README.pgtips-srv-records?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/README.pgtips-srv-records (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/README.pgtips-srv-records Tue Nov 12 04:21:48 2013
@@ -2,7 +2,7 @@
Olle E. Johansson
Project start: 2013-04-18
-Update: 2013-08-27
+Update: 2013-11-02
@@ -72,6 +72,24 @@
of incoming calls, possibly deny calls from servers that does not match.
This is NOT the expected solution.
+Solution to peer matching for inbound calls
+--------------------------------------------
+We are going to add "shadow peers" that has a special flag that forces
+the code, after matching, to use the "main peer". This is to get call limits
+and other functions to work properly. These peers will be created every
+time we do an SRV lookup and deleted and recreated when a new SRV lookup is happening
+for a peer (after TTL expired). They will only be used for matching on
+inbound calls and can not be used for outbound calls in the dialplan.
+
+The "main" peer needs to have the active IP used for calls and registrations.
+There will therefore be a shadow peer with the same IP. At failover
+the working peer's IP/port is moved to the main peer.
+
+The peer will have these as a chain of "subpeers" to make sure they are
+deleted when a peer is deleted.
+
+How this works in combination with realtime is still to be explored.
+
Failover
========
I see two situation for failover to the next host/ip in the SRV list:
@@ -88,6 +106,14 @@
We do need a function in main/srv.c to switch to the next entry and
move the "current" pointer.
+Realtime out of scope
+=====================
+For this project, realtime is out of scope. Peer match by IP
+based on SRV will not work in realtime. Sorry. Just not doable.
+You will have to create records for each SRV host and maintain them.
+Realtime is not built for this. Do NOT use it for outbound SIP
+trunks.
+
Development Notes
=================
@@ -96,6 +122,29 @@
DNSmanager can still maintain A/AAAA records if enabled, but not SRV
lists.
+
+SRV records usage
+=================
+- When Outbound proxy is used and can't be reached for initial transaction,
+ fail over to next ob proxy in srv record set (dialog SRV should be set up
+ from outbound proxy name)
+- When Peer is used DNS SRV name should be taken from peer
+- Otherwise dialstring
+
+The dialog should always look up a new DNS SRV set from DNS, not copy from
+peer.
+
+
+Only do failover for initial transactions, not within-dialog transactions,
+unless entries in the route set has a DNS name and not an IP address.
+
+Register before call
+====================
+In IMS you need to be registred before a call. For this
+- We need to set a flag on the dialog for the registration that the peer needs an update
+- When a registration state changes we need a flag on the peer to set registration status.
+- The main peer's IP need to be the one we register with. At failover for registration,
+ this needs to be handled.
Not fixed here
==============
@@ -118,10 +167,9 @@
4. Implement failover to next server in list if transaction fails.
5. Make sure we use the DNS TTL properly
6. Use SRV for outbound proxys too, with failover
-7. Add multiple IPs to the peer in an ACL list
- - Added a linked list
- - Needs to be added to peers by ip list for matching. Not done yet.
-8. Add the same IPs to the AO2object for IP matching
+7. Add multiple peers (shadowpeers), one for each SRv entry/IP address
+ - delete existing ones if needed
+8. Make sure the shadowpeers are deleted when masterpeer is deleted
9. Make sure the ACL list is updated by DNS manager
10. Change peer match by ip/port to use ACL list if available
11. Fix outbound proxy SRV support (proxy_update)
@@ -161,3 +209,4 @@
chan_sip's find_call - we do a multi-object match using an ao2_callback
to find all dialogs that match a call-id, then iterate over each object.
+
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/chan_sip.c?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/chan_sip.c (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/chan_sip.c Tue Nov 12 04:21:48 2013
@@ -1440,6 +1440,10 @@
/*--- Device object handling */
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only);
+static struct sip_peer *copy_peer(struct sip_peer *destpeer, const struct sip_peer *origpeer);
+static void shadow_peer_delete_all(struct sip_peer *masterpeer);
+static struct sip_peer *create_shadow_peer(struct sip_peer *peer, struct ast_sockaddr *addr, unsigned short tportno, const char *hostname);
+static void link_shadow_peer(struct sip_peer *masterpeer, struct sip_peer *shadowpeer, const char *hostname);
static int update_call_counter(struct sip_pvt *fup, int event);
static void sip_destroy_peer(struct sip_peer *peer);
static void sip_destroy_peer_fn(void *peer);
@@ -4573,18 +4577,20 @@
/*!
* \internal
* \brief Send SIP Request to the other part of the dialogue
- * If the xmit returns a network error (XMIT_ERROR or -1) then try with another SRV record if it exists.
+ * For out of dialog messages only:
+ * - If the xmit returns a network error (XMIT_ERROR or -1) then try with another SRV record if it exists.
* \return see \ref __sip_xmit
*/
static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittype reliable, uint32_t seqno)
{
- int res;
+ int res = 0;
/* If we have an outbound proxy, reset peer address
Only do this once.
*/
if (p->outboundproxy) {
p->sa = p->outboundproxy->ip;
+ /* We need the SRV context as well */
}
finalize_content(req);
@@ -4602,14 +4608,27 @@
append_history(p, reliable ? "TxReqRel" : "TxReq", "%s / %s - %s", ast_str_buffer(tmp.data), get_header(&tmp, "CSeq"), sip_methods[tmp.method].text);
deinit_req(&tmp);
}
- if (p->srvcon) {
+ if (p->srvcontext) {
/* We have an SRV record set. If we get transmit errors, retry on the next directly. */
- res = (reliable) ?
- __sip_reliable_xmit(p, seqno, 0, req->data, (reliable == XMIT_CRITICAL), req->method) :
- __sip_xmit(p, req->data);
- if (res == -1 || res == XMIT_ERROR) {
- ast_debug(3, "====>> SRV failover. Changing to next SRV record in the list\n");
- /* XXX SRV FAILOVER HERE XXX */
+ while (res != -1 && res != XMIT_ERROR) {
+ res = (reliable) ?
+ __sip_reliable_xmit(p, seqno, 0, req->data, (reliable == XMIT_CRITICAL), req->method) :
+ __sip_xmit(p, req->data);
+ if (res == -1 || res == XMIT_ERROR) {
+ char hostname[MAXHOSTNAMELEN];
+ unsigned short port, prio, weight;
+ ast_debug(3, "====>> SRV failover. Changing to next SRV record in the list\n");
+ /* XXX SRV FAILOVER HERE XXX */
+ /* Hmm. If this is a peer - should we use the peer srvcontext? */
+ if(ast_srv_get_next_record(p->srvcontext, &hostname, &port, &prio, &weight)) {
+ ast_log(LOG_WARNING, "No more hosts: %s\n", p->srvdomain);
+ res = -1;
+ } else {
+ ast_debug(3, "====>> SRV failover. Changing to host %s port %d\n", hostname, port);
+ /* Select IP address */
+ /* Change IP in p */
+ }
+ }
}
} else {
res = (reliable) ?
@@ -5036,6 +5055,9 @@
static void sip_destroy_peer(struct sip_peer *peer)
{
ast_debug(3, "Destroying SIP peer %s\n", peer->name);
+
+ /* Remove any shadows to this peer first */
+ shadow_peer_delete_all(peer);
/*
* Remove any mailbox event subscriptions for this peer before
@@ -5074,8 +5096,6 @@
register_peer_exten(peer, FALSE);
ast_free_ha(peer->ha);
ast_free_ha(peer->directmediaha);
-
- free_sip_host_ip(peer->srventries);
if (peer->selfdestruct)
ast_atomic_fetchadd_int(&apeerobjs, -1);
@@ -5493,10 +5513,18 @@
tmp_peer.flags[0].flags = 0;
tmp_peer.transports = transport;
p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
+ if (p->masterpeer && p->type == SIP_TYPE_PEERSHADOW) {
+ ast_debug(2, "Found shadow peer %s, replacing with master peer %s\n", p->name, p->masterpeer->name);
+ p = p->masterpeer;
+ }
if (!p) {
ast_set_flag(&tmp_peer.flags[0], SIP_INSECURE_PORT);
p = ao2_t_find(peers_by_ip, &tmp_peer, OBJ_POINTER, "ao2_find in peers_by_ip table 2"); /* WAS: p = ASTOBJ_CONTAINER_FIND_FULL(&peerl, sin, name, sip_addr_hashfunc, 1, sip_addrcmp); */
if (p) {
+ if (p->masterpeer) {
+ ast_debug(2, "Found shadow peer %s, replacing with master peer %s\n", p->name, p->masterpeer->name);
+ p = p->masterpeer;
+ }
return p;
}
}
@@ -5918,25 +5946,25 @@
* an A record lookup should be used instead of SRV.
*/
if (!hostport.port && sip_cfg.srvlookup) {
- if (dialog->srvcon) {
- ast_srv_context_free_list(dialog->srvcon);
- dialog->srvcon = ast_srv_context_new();
- }
+ if (dialog->srvcontext) {
+ ast_srv_context_free_list(dialog->srvcontext);
+ }
+ dialog->srvcontext = ast_srv_context_new();
snprintf(service, sizeof(service), "_%s._%s.%s",
get_srv_service(dialog->socket.type),
get_srv_protocol(dialog->socket.type), peername);
/* Get the srv list */
- if ((srv_ret = ast_get_srv_list(dialog->srvcon, NULL, service)) > 0) {
+ if ((srv_ret = ast_get_srv_list(dialog->srvcontext, NULL, service)) > 0) {
int rec = 1;
unsigned short port, prio, weight;
const char *srvhost;
- ast_debug(3, " ==> DNS lookup of %s returned %d entries. First %s \n", service, ast_srv_get_record_count(dialog->srvcon), hostn);
+ ast_debug(3, " ==> DNS lookup of %s returned %d entries. First %s \n", service, ast_srv_get_record_count(dialog->srvcontext), hostn);
hostn = host;
- for (rec = 0; rec < ast_srv_get_record_count(dialog->srvcon); rec++) {
- if(ast_srv_get_nth_record(dialog->srvcon, rec, &srvhost, &port, &prio, &weight)) {
+ for (rec = 0; rec < ast_srv_get_record_count(dialog->srvcontext); rec++) {
+ if(ast_srv_get_nth_record(dialog->srvcontext, rec, &srvhost, &port, &prio, &weight)) {
ast_log(LOG_WARNING, "No more SRV records for: %s\n", peername);
return -1;
}
@@ -6265,9 +6293,9 @@
p->mwi->call = NULL;
p->mwi = NULL;
}
- if (p->srvcon) { /* Free the list of SRV entries used by this dialog */
- ast_srv_context_free_list(p->srvcon);
- ast_free(p->srvcon);
+ if (p->srvcontext) { /* Free the list of SRV entries used by this dialog */
+ ast_srv_context_free_list(p->srvcontext);
+ ast_free(p->srvcontext);
}
if (dumphistory)
@@ -27711,6 +27739,9 @@
} else if (!strcasecmp(v->name, "useclientcode")) {
ast_set_flag(&mask[0], SIP_USECLIENTCODE);
ast_set2_flag(&flags[0], ast_true(v->value), SIP_USECLIENTCODE);
+ } else if (!strcasecmp(v->name, "regbeforecall")) {
+ ast_set_flag(&mask[2], SIP_PAGE3_REG_BEFORE_CALL);
+ ast_set2_flag(&flags[2], ast_true(v->value), SIP_PAGE3_REG_BEFORE_CALL);
} else if (!strcasecmp(v->name, "dtmfmode")) {
ast_set_flag(&mask[0], SIP_DTMF);
ast_clear_flag(&flags[0], SIP_DTMF);
@@ -28166,6 +28197,299 @@
}
}
+static void link_shadow_peer(struct sip_peer *masterpeer, struct sip_peer *shadowpeer, const char *hostname)
+{
+ struct sip_shadow_peer *shadow;
+
+ if (!(shadow = (struct sip_shadow_peer * ) ast_calloc(1, sizeof(*shadow)))) {
+ ast_log(LOG_ERROR,"Can't allocate memory for peer shadow. \n");
+ return;
+ }
+ shadow->delme = 0;
+ shadow->peer = shadowpeer;
+ ast_copy_string(shadow->hostname, hostname, sizeof(shadow->hostname));
+ AST_LIST_INSERT_TAIL(&masterpeer->peer_shadows, shadow, entry);
+ return;
+}
+
+/*! \brief Delete list of shadow peers */
+static void shadow_peer_delete_all(struct sip_peer *masterpeer)
+{
+ struct sip_shadow_peer *shadow;
+
+ if (AST_LIST_EMPTY(&masterpeer->peer_shadows)) {
+ return;
+ }
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&masterpeer->peer_shadows, shadow, entry) {
+ /* remove shadow peer from IP list */
+ unlink_peer_from_tables(shadow->peer);
+ ao2_t_ref(shadow->peer, -1, "Removing all shadow peers");
+ AST_LIST_REMOVE_CURRENT(entry);
+ ast_free(shadow);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+}
+
+/*! \brief Copy a peer into a new peer
+
+ \note IMPORTANT: Not all data is copied. This is written with DNS shadow peers in mind. If you use this
+ function for anything else, make sure all data that you need is copied.
+
+ Data not copied:
+ - struct sip_auth_container *auth;// Realm authentication credentials
+ - masterpeer and shadow peers
+ - struct sip_pvt *call; // Call pointer - runtime, not config
+ - socket.fd and socket.tcptls_session is not copied. - runtime, not config
+ - int lastmsgssent; - runtime, not config
+ - mailbox list
+ - struct sip_proxy *outboundproxy;// proxy for this peer
+ - struct ast_dnsmgr_entry *dnsmgr;// refresh manager for peer - runtime, not config
+ - struct srv_context *srvcontext; // SRV lookup chain for failover - runtime, not config
+ - struct timeval ps; //: Time for sending SIP OPTION in sip_pke_peer() - runtime, not config
+ - struct sip_pvt *mwipvt; // for MWI - runtime, not config
+
+ Note: This was coded on a Norwegian Boeing 737-800 that was too new for Wifi... Wifi is not installed
+ by Boeing so I was offline and coding instead of being social with my nerd friends. OEJ.
+ */
+static struct sip_peer *copy_peer(struct sip_peer *destpeer, const struct sip_peer *origpeer)
+{
+ ast_debug(2, "==> Starting to copy peer %s \n", origpeer->name);
+ /*! the unique name of this object */
+ ast_copy_string(destpeer->name, origpeer->name, sizeof(origpeer->name));
+ /*! Password for inbound auth */
+ ast_string_field_set(destpeer, secret, origpeer->md5secret);
+ /*! Remote secret (trunks, remote devices) */
+ ast_string_field_set(destpeer, md5secret, origpeer->secret);
+ /*! Default context for incoming calls */
+ ast_string_field_set(destpeer, context, origpeer->context);
+ /*! Default context for subscriptions */
+ ast_string_field_set(destpeer, subscribecontext, origpeer->subscribecontext);
+ /*! Temporary username until registration and auth username */
+ ast_string_field_set(destpeer, username, origpeer->username);
+ /*! Account code */
+ ast_string_field_set(destpeer, accountcode, origpeer->accountcode);
+ /*! If not dynamic, IP address */
+ ast_string_field_set(destpeer, tohost, origpeer->tohost);
+ /*! Extension to register (if regcontext is used) */
+ ast_string_field_set(destpeer, regexten, origpeer->regexten);
+ /*! From: user when calling this peer */
+ ast_string_field_set(destpeer, fromuser, origpeer->fromuser);
+ /*! From: domain when calling this peer */
+ ast_string_field_set(destpeer, fromdomain, origpeer->fromdomain);
+ /*! Contact registered with us (not in sip.conf) */
+ ast_string_field_set(destpeer, fullcontact, origpeer->fullcontact);
+ /*! Caller ID num */
+ ast_string_field_set(destpeer, cid_num, origpeer->cid_num);
+ /*! Caller ID name */
+ ast_string_field_set(destpeer, cid_name, origpeer->cid_name);
+ /*! Caller ID tag */
+ ast_string_field_set(destpeer, cid_tag, origpeer->cid_tag);
+ /*! Dialplan extension for MWI notify message*/
+ ast_string_field_set(destpeer, vmexten, origpeer->vmexten);
+ /*! Default language for prompts */
+ ast_string_field_set(destpeer, language, origpeer->language);
+ /*! Music on Hold class */
+ ast_string_field_set(destpeer, mohinterpret, origpeer->mohinterpret);
+ /*! Music on Hold class */
+ ast_string_field_set(destpeer, mohsuggest, origpeer->mohsuggest);
+ /*! Parkinglot */
+ ast_string_field_set(destpeer, parkinglot, origpeer->parkinglot);
+ /*! User agent in SIP request (saved from registration) */
+ ast_string_field_set(destpeer, useragent, origpeer->useragent);
+ /*! Name to place in From header for outgoing NOTIFY requests */
+ ast_string_field_set(destpeer, mwi_from, origpeer->mwi_from);
+ /*! RTP Engine to use */
+ ast_string_field_set(destpeer, engine, origpeer->engine);
+ /*! SIP Domain for SRV lookups */
+ ast_string_field_set(destpeer, srvdomain, origpeer->srvdomain);
+ /*! Mailbox to store received unsolicited MWI NOTIFY messages information in */
+ ast_string_field_set(destpeer, unsolicited_mailbox, origpeer->unsolicited_mailbox);
+
+ /*! Socket type/port used for this peer */
+ destpeer->socket.type = origpeer->socket.type;
+ destpeer->socket.port = origpeer->socket.port;
+
+ /*! Peer Registration may change the default outbound transport. */
+ destpeer->default_outbound_transport = origpeer->default_outbound_transport;
+ /*! Transports (enum sip_transport) that are acceptable for this peer */
+ destpeer->transports = origpeer->transports;
+ /*! this is a 'realtime' peer */
+ destpeer->is_realtime = origpeer->is_realtime;
+ /*! copy fromcontact from realtime */
+ destpeer->rt_fromcontact = origpeer->rt_fromcontact;
+ /*!< Dynamic Peers register with Asterisk */
+ destpeer->host_dynamic = origpeer->host_dynamic;
+ /*! Automatic peers need to destruct themselves */
+ destpeer->selfdestruct = origpeer->selfdestruct;
+ /*! moved out of ASTOBJ into struct proper; That which bears the_mark should be deleted! */
+ destpeer->the_mark = origpeer->the_mark;
+ /*! Whether to use our local configuration for frame sizes (off) */
+ destpeer->autoframing = origpeer->autoframing;
+ /*! If it's a realtime peer, are they using the deprecated "username" instead of "defaultuser" */
+ destpeer->deprecated_username = origpeer->deprecated_username;
+ /*! AMA Flags (for billing) */
+ destpeer->amaflags = origpeer->amaflags;
+ /*! Calling id presentation */
+ destpeer->callingpres = origpeer->callingpres;
+ /*! Number of calls in use */
+ destpeer->inUse = origpeer->inUse;
+ /*! Number of calls ringing */
+ destpeer->inRinging = origpeer->inRinging;
+ /*! Peer has someone on hold */
+ destpeer->onHold = origpeer->onHold;
+ /*! Limit of concurrent calls */
+ destpeer->call_limit = origpeer->call_limit;
+ /*! T.38 FaxMaxDatagram override */
+ destpeer->t38_maxdatagram = origpeer->t38_maxdatagram;
+ /*!< Level of active channels where we signal busy */
+ destpeer->busy_level = origpeer->busy_level;
+ /*! SIP Loop prevention */
+ destpeer->maxforwards = origpeer->maxforwards;
+ /*! SIP Refer restriction scheme */
+ destpeer->allowtransfer = origpeer->allowtransfer;
+ destpeer->prefs = origpeer->prefs;
+ destpeer->lastmsgssent = origpeer->lastmsgssent;
+ /*! Supported SIP options */
+ destpeer->sipoptions = origpeer->sipoptions;
+ /*! SIP_ flags */
+ destpeer->flags[0] = origpeer->flags[0];
+ destpeer->flags[1] = origpeer->flags[1];
+ destpeer->flags[2] = origpeer->flags[2];
+ /*! Maximum Bitrate for a video call */
+ destpeer->maxcallbitrate = origpeer->maxcallbitrate;
+ /*!< When to expire this peer registration */
+ destpeer->expire = origpeer->expire;
+ /*!< Codec capability */
+ destpeer->capability = origpeer->capability;
+ /*!< RTP timeout */
+ destpeer->rtptimeout = origpeer->rtptimeout;
+ /*!< RTP Hold Timeout */
+ destpeer->rtpholdtimeout = origpeer->rtpholdtimeout;
+ /*!< Send RTP packets for keepalive */
+ destpeer->rtpkeepalive = origpeer->rtpkeepalive;
+ /*! Call group */
+ destpeer->callgroup = origpeer->callgroup;
+ /*! Pickup group */
+ destpeer->pickupgroup = origpeer->pickupgroup;
+ /*! IP address of peer */
+ ast_sockaddr_copy(&destpeer->addr, &origpeer->addr);
+ /*! Whether the port should be included in the URI */
+ destpeer->portinuri = origpeer->portinuri;
+ /*! Qualification: When to expire poke (qualify= checking) */
+ destpeer->pokeexpire = origpeer->pokeexpire;
+ /*! Qualification: How long last response took (in ms), or -1 for no response */
+ destpeer->lastms = origpeer->lastms;
+ /*! Qualification: Max ms we will accept for the host to be up, 0 to not monitor */
+ destpeer->maxms = origpeer->maxms;
+ /*! Qualification: Qualification: How often to check for the host to be up */
+ destpeer->qualifyfreq = origpeer->qualifyfreq;
+ /*! Default IP address, used until registration */
+ ast_sockaddr_copy(&destpeer->defaddr, &origpeer->defaddr);
+ /*! Access control list */
+ ast_copy_ha(destpeer->ha, origpeer->ha);
+ /*! Restrict what IPs are allowed in the Contact header (for registration) */
+ ast_copy_ha(destpeer->contactha, origpeer->contactha);
+ /*! Restrict what IPs are allowed to interchange direct media with */
+ ast_copy_ha(destpeer->directmediaha, origpeer->directmediaha);
+ /*! Variables to set for channel created by user */
+ destpeer->chanvars = ast_variables_dup(origpeer->chanvars);
+ /*! The maximum T1 value for the peer */
+ destpeer->timer_t1 = origpeer->timer_t1;
+ /*! The maximum timer B (transaction timeouts) */
+ destpeer->timer_b = origpeer->timer_b;
+ /*! The From: domain port */
+ destpeer->fromdomainport = origpeer->fromdomainport;
+ /*! Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */
+ destpeer->type = origpeer->type;
+ destpeer->disallowed_methods = origpeer->disallowed_methods;
+ /* Session-Timers */
+ destpeer->stimer.st_mode_oper = origpeer->stimer.st_mode_oper;
+ destpeer->stimer.st_ref = origpeer->stimer.st_ref;
+ destpeer->stimer.st_min_se = origpeer->stimer.st_min_se;
+ destpeer->stimer.st_max_se = origpeer->stimer.st_max_se;
+ ast_cc_copy_config_params(destpeer->cc_params, origpeer->cc_params);
+
+ ast_debug(2, "==> Done copying peer %s \n", origpeer->name);
+ return destpeer;
+}
+
+static struct sip_peer *create_new_peer(int realtime)
+{
+ struct sip_peer *peer = NULL;
+
+ if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) {
+ return NULL;
+ }
+
+ if (ast_string_field_init(peer, 512)) {
+ ao2_t_ref(peer, -1, "failed to string_field_init, drop peer");
+ return NULL;
+ }
+
+ if (!(peer->cc_params = ast_cc_config_params_init())) {
+ ao2_t_ref(peer, -1, "failed to allocate cc_params for peer");
+ return NULL;
+ }
+
+ if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
+ ast_atomic_fetchadd_int(&rpeerobjs, 1);
+ } else {
+ ast_atomic_fetchadd_int(&speerobjs, 1);
+ }
+ return peer;
+}
+
+
+/* Create a shadow copy of a peer and link it in the list of shadows to the peer
+ The shadows are used only for IP/port matching on incoming calls,
+ based on multiple DNS entries
+ */
+static struct sip_peer *create_shadow_peer(struct sip_peer *peer, struct ast_sockaddr *addr, unsigned short tportno, const char *hostname)
+{
+ struct sip_peer *shadowpeer = create_new_peer(FALSE);
+ char peername[80];
+
+ if (!shadowpeer) {
+ return NULL;
+ }
+ ast_copy_string(peername, peer->name, sizeof(peername));
+ if (strlen(peername) > 60) {
+ /* Cut the long name to get room for random string */
+ peername[60] = '\0';
+ }
+ ast_string_field_build(shadowpeer, name, "%s-%08lx", peername, ast_random());
+ ast_debug(2, "Created shadow DNS peer %s for %s - based on peer %s\n", shadowpeer->name, hostname, peer->name);
+
+ shadowpeer->lastmsgssent = -1;
+ shadowpeer->ha = NULL;
+ shadowpeer->directmediaha = NULL;
+ set_peer_defaults(shadowpeer); /* Set peer defaults */
+ copy_peer(shadowpeer, peer); /* Copy the peer */
+ ast_sockaddr_copy(&shadowpeer->addr, addr); /* Set the address and family */
+ ast_sockaddr_set_port(&shadowpeer->addr, tportno); /* Set the port number */
+ shadowpeer->type = SIP_TYPE_PEERSHADOW;
+
+ /* Adding the IP to the global contact ACL */
+ if (global_dynamic_exclude_static) {
+ int ha_error = 0;
+ sip_cfg.contact_ha = ast_append_ha("deny", ast_sockaddr_stringify_addr(&addr), sip_cfg.contact_ha, &ha_error);
+ }
+ /* Add a reference to the master */
+ /* Note: Adding a ref to the master stops the master from being deleted which
+ means a catch 22. Do not add a ref here. If the master dies, the shadows will die too. */
+ shadowpeer->masterpeer = peer;
+
+ /* Link to the original peer */
+ link_shadow_link(shadowpeer, peer, hostname);
+
+ /* Add shadow peer to peer list */
+ ao2_t_link(peers_by_ip, shadowpeer, "link shadow peer into peers_by_ip table");
+
+ /* Live long and prosper */
+ return shadowpeer;
+}
+
/*! \brief Build peer from configuration (file or realtime static/dynamic) */
static struct sip_peer *build_peer(const char *name, struct ast_variable *v, struct ast_variable *alt, int realtime, int devstate_only)
{
@@ -28211,24 +28535,12 @@
if (!(peer->the_mark))
firstpass = 0;
} else {
- if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct")))
+ if (!(peer = create_new_peer(realtime))) {
return NULL;
-
- if (ast_string_field_init(peer, 512)) {
- ao2_t_ref(peer, -1, "failed to string_field_init, drop peer");
- return NULL;
- }
-
- if (!(peer->cc_params = ast_cc_config_params_init())) {
- ao2_t_ref(peer, -1, "failed to allocate cc_params for peer");
- return NULL;
- }
-
- if (realtime && !ast_test_flag(&global_flags[1], SIP_PAGE2_RTCACHEFRIENDS)) {
- ast_atomic_fetchadd_int(&rpeerobjs, 1);
+ }
+ if (realtime) {
ast_debug(3, "-REALTIME- peer built. Name: %s. Peer objects: %d\n", name, rpeerobjs);
- } else
- ast_atomic_fetchadd_int(&speerobjs, 1);
+ }
}
/* Note that our peer HAS had its reference count increased */
@@ -28793,11 +29105,8 @@
ast_debug(3, " ==> Settling on SRV entry %d (prio %d weight %d): %s\n", rec - 1, prio, weight, hostname);
- /* Now loop again and fill the ACL */
- if (peer->srventries) {
- old_sip_host_ip = peer->srventries;
- peer->srventries = NULL;
- }
+ /* Remove any shadows to this peer first */
+ shadow_peer_delete_all(peer);
for (rec = 1; rec <= ast_srv_get_record_count(peer->srvcontext); rec++) {
int res;
struct ast_sockaddr ip;
@@ -28809,15 +29118,10 @@
if (ast_sockaddr_isnull(&ip) || res ) {
ast_debug(3, " ==> Bad IP, could not resolve hostname %s to proper family. \n", hostname);
} else {
- peer->srventries = add_sip_host_ip(peer->srventries, &ip, tportno, hostname);
- //peer->srventries = ast_append_ha("p", ast_sockaddr_stringify_addr(&ip), peer->srventries, &res);
- ast_debug(3, " ==> Adding IP to peer %s srv list: %s \n", name, ast_sockaddr_stringify_addr(&ip));
+ create_shadow_peer(peer, &ip, tportno, hostname);
+ ast_debug(4, " ==> Created shadow peer for %s (%s)\n", peer->name, hostname);
}
}
- }
- if (option_debug > 3) {
- ast_debug(3, "======> List of IP matching entries for %s <============\n", name);
- host_ip_list_debug(peer->srventries);
}
} else {
int res;
@@ -28857,6 +29161,9 @@
ast_log(LOG_ERROR, "Bad or unresolved host/IP entry in configuration for peer %s, cannot add to contact ACL\n", peer->name);
}
}
+
+#ifdef SKREP
+// We need to loop through the shadow peers and add them here
if (peer->srventries != NULL) {
int ha_error = 0;
struct sip_host_ip *he = peer->srventries;
@@ -28868,6 +29175,7 @@
ast_log(LOG_ERROR, "Bad or unresolved host/IP entry in configuration for peer %s, cannot add to contact ACL\n", peer->name);
}
}
+#endif
}
} else if (peer->dnsmgr && !peer->host_dynamic) {
@@ -29184,6 +29492,7 @@
ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE); /* Default for all devices: TRUE */
ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP_YES); /* Default for all devices: Yes */
sip_cfg.peer_rtupdate = TRUE;
+ sip_cfg.ims_regcall = DEFAULT_IMS_REGCALL; /*!< Register before a call */
global_dynamic_exclude_static = 0; /* Exclude static peers */
sip_cfg.tcp_enabled = FALSE;
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/config_parser.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/config_parser.c?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/config_parser.c (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/config_parser.c Tue Nov 12 04:21:48 2013
@@ -641,7 +641,7 @@
return res;
}
-int sip_parse_host(char *line, int lineno, char **hostname, int *portnum, enum sip_transport *transport)
+int sip_parse_host(char *line, int lineno, char **hostname, unsigned short *portnum, enum sip_transport *transport)
{
char *port;
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/config_parser.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/config_parser.h?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/config_parser.h (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/config_parser.h Tue Nov 12 04:21:48 2013
@@ -41,7 +41,7 @@
* \retval 0 on success
* \retval -1 on failure
*/
-int sip_parse_host(char *line, int lineno, char **hostname, int *portnum, enum sip_transport *transport);
+int sip_parse_host(char *line, int lineno, char **hostname, unsigned short *portnum, enum sip_transport *transport);
/*!
* \brief register config parsing tests
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/sip.h?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/sip.h (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/channels/sip/include/sip.h Tue Nov 12 04:21:48 2013
@@ -58,6 +58,7 @@
#define DEFAULT_MWI_EXPIRY 3600
#define DEFAULT_REGISTRATION_TIMEOUT 20
#define DEFAULT_MAX_FORWARDS 70
+#define DEFAULT_IMS_REGCALL FALSE
#define DEFAULT_AUTHLIMIT 100
#define DEFAULT_AUTHTIMEOUT 30
@@ -359,9 +360,10 @@
#define SIP_PAGE3_SNOM_AOC (1 << 0) /*!< DPG: Allow snom aoc messages */
#define SIP_PAGE3_DIRECT_MEDIA_OUTGOING (1 << 1) /*!< DP: Only send direct media reinvites on outgoing calls */
+#define SIP_PAGE3_REG_BEFORE_CALL (1 << 2) /*!< PG: Only call peers we're registred with */
#define SIP_PAGE3_FLAGS_TO_COPY \
- (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_DIRECT_MEDIA_OUTGOING)
+ (SIP_PAGE3_SNOM_AOC | SIP_PAGE3_DIRECT_MEDIA_OUTGOING | SIP_PAGE3_REG_BEFORE_CALL)
/*@}*/
@@ -626,8 +628,9 @@
};
enum sip_peer_type {
- SIP_TYPE_PEER = (1 << 0),
- SIP_TYPE_USER = (1 << 1),
+ SIP_TYPE_PEER = (1 << 0), /*!< device used for incoming and outgoing calls */
+ SIP_TYPE_USER = (1 << 1), /*!< device used for incoming only. Match on From: username */
+ SIP_TYPE_PEERSHADOW = (1 << 2), /*!< A copy of a peer. Only trust IP/port in this structure */
};
enum t38_action_flag {
@@ -662,7 +665,7 @@
int force; /*!< If it's an outbound proxy, Force use of this outbound proxy for all outbound requests */
/* Room for a SRV record chain based on the name */
struct sip_proxy *next;
- struct srv_context *srvlist; /*!< List of DNs entries */
+ struct srv_context *srvlist; /*!< List of DNS entries */
};
/*! \brief A stupid simple linked list for storing host IPs and ports
@@ -999,6 +1002,7 @@
AST_STRING_FIELD(parkinglot); /*!< Parkinglot */
AST_STRING_FIELD(engine); /*!< RTP engine to use */
AST_STRING_FIELD(dialstring); /*!< The dialstring used to call this SIP endpoint */
+ AST_STRING_FIELD(srvdomain); /*!< The domain name used for SRV lookups. Kept for refreshes */
);
char via[128]; /*!< Via: header */
int maxforwards; /*!< SIP Loop prevention */
@@ -1150,7 +1154,7 @@
struct ast_cc_config_params *cc_params;
struct sip_epa_entry *epa_entry;
int fromdomainport; /*!< Domain port to show in from field */
- struct srv_context *srvcon; /*!< SRV record list */
+ struct srv_context *srvcontext; /*!< SRV record list */
};
/*! \brief sip packet - raw format for outbound packets that are sent or scheduled for transmission
@@ -1190,6 +1194,16 @@
unsigned int delme:1;
char *context;
char mailbox[2];
+};
+
+/*!
+ *\brief A lof shadow peers
+ */
+struct sip_shadow_peer {
+ AST_LIST_ENTRY(sip_shadow_peer) entry;
+ char hostname[MAXHOSTNAMELEN];
+ unsigned int delme:1;
+ struct sip_peer *peer;
};
/*! \brief Structure for SIP peer data, we place calls to peers if registered or fixed IP address (host)
@@ -1281,7 +1295,6 @@
struct ast_ha *ha; /*!< Access control list */
struct ast_ha *contactha; /*!< Restrict what IPs are allowed in the Contact header (for registration) */
struct ast_ha *directmediaha; /*!< Restrict what IPs are allowed to interchange direct media with */
- struct sip_host_ip *srventries; /*!< DNS Srv entries at time of peer creation */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
struct sip_pvt *mwipvt; /*!< Subscription for MWI */
struct sip_st_cfg stimer; /*!< SIP Session-Timers */
@@ -1291,6 +1304,9 @@
/*XXX Seems like we suddenly have two flags with the same content. Why? To be continued... */
enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */
+ struct sip_peer *masterpeer; /*!< If this peer is a SHADOWPEER this is the master */
+ AST_LIST_HEAD_NOLOCK(,sip_shadow_peer) peer_shadows; /*! If we are the master, this is our shadows */
+
unsigned int disallowed_methods;
struct ast_cc_config_params *cc_params;
};
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/configs/sip.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/configs/sip.conf.sample?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/configs/sip.conf.sample (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/configs/sip.conf.sample Tue Nov 12 04:21:48 2013
@@ -725,6 +725,11 @@
;register_retry_403=yes ; Treat 403 responses to registrations as if they were
; 401 responses and continue retrying according to normal
; retry rules.
+;regbeforecall=no ; When calling apeer, make sure we have a valid registration
+ ; with it first. This relates to outbound registrations only
+ ; (with the register => line above)
+ ; Settable per peer. Register= line needs to refer to peer,
+ ; not to hostname. Defaults to "no".
;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS -------------------------
; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/include/asterisk/srv.h Tue Nov 12 04:21:48 2013
@@ -90,30 +90,6 @@
unsigned int ast_srv_get_record_count(struct srv_context *context);
/*!
- * \brief Retrieve details from the next SRV record
- *
- * \details
- * After calling ast_srv_lookup, the srv_context will contain
- * the data from several records. There is a pointer to the current
- * used record in the srv_context. This function selects the
- * next record if it exists.
- * The records are sorted based on priority and secondarily based on
- * weight. See RFC 2782 for the exact sorting rules.
- *
- * \param context The context returned by ast_srv_lookup
- * \param record_num The 1-indexed record number to retrieve
- * \param[out] host The host portion of the record
- * \param[out] port The port portion of the record
- * \param[out] priority The priority portion of the record
- * \param[out] weight The weight portion of the record
- * \retval -1 Failed to retrieve information. Likely due to an out of
- * range record_num
- * \retval 0 Success
- */
-int ast_srv_get_next_record(struct srv_context *context, const char **host,
- unsigned short *port, unsigned short *priority, unsigned short *weight);
-
-/*!
* \brief Retrieve details from a specific SRV record
*
* \details
@@ -122,6 +98,8 @@
* of a specific one by asking for a specific record number. The
* records are sorted based on priority and secondarily based on
* weight. See RFC 2782 for the exact sorting rules.
+ *
+ * This function sets the "current" pointer to the selected entry.
*
* \param context The context returned by ast_srv_lookup
* \param record_num The 1-indexed record number to retrieve
@@ -135,6 +113,25 @@
*/
int ast_srv_get_nth_record(struct srv_context *context, int record_num, const char **host,
unsigned short *port, unsigned short *priority, unsigned short *weight);
+
+/*!
+ * \brief Retrieve details from the next SRV record
+ * When doing a SRV record lookup, a list is saved in the context and
+ * a pointer is set to the "current" record. This function moves the current
+ * pointer to the next entry and returns the names from that entry.
+ *
+ * \param context The context returned by ast_srv_lookup
+ * \param record_num The 1-indexed record number to retrieve
+ * \param[out] host The host portion of the record
+ * \param[out] port The port portion of the record
+ * \param[out] priority The priority portion of the record
+ * \param[out] weight The weight portion of the record
+ * \retval -1 Failed to retrieve information. Likely due to the end of the list.
+ * \retval 0 Success
+ */
+int ast_srv_get_next_record(struct srv_context *context, const char **host,
+ unsigned short *port, unsigned short *priority, unsigned short *weight);
+
/*!
* \brief Print out the complete data in the SRV list
*/
Modified: team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c?view=diff&rev=402707&r1=402706&r2=402707
==============================================================================
--- team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c (original)
+++ team/oej/pgtips-srv-and-outbound-stuff-1.8/main/srv.c Tue Nov 12 04:21:48 2013
@@ -76,6 +76,7 @@
unsigned int have_weights:1;
struct srv_entry *prev;
[... 76 lines stripped ...]
More information about the svn-commits
mailing list