Commit Graph

160 Commits

Author SHA1 Message Date
Corey Farrell
2c4db2a3d5 res_pjsip_pubsub: Fix multiple leaks on failure to append vectors.
Change-Id: I68ece0073ea79667ca41eb10405f516f1d30d482
2017-11-07 22:38:16 -05:00
Joshua Colp
36fedea8c1 res_pjsip_pubsub: Ensure remote URI contains URI only.
This change makes it so that any user of the pubsub
API that requests the remote URI receives only the URI.
Previously the entire string was returned, which could
contain a display name.

ASTERISK-27290

Change-Id: If1d0cd6630f0a264856d31d2a67933109187a017
2017-11-06 13:02:43 -05:00
Corey Farrell
0991874430 res_pjsip_pubsub: Resolve potential crash in allocate_subscription.
When allocate_subscription fails to initialize fields of the new sub it
calls destroy_subscription.

Change-Id: I5b79c915ec216dc00c13c1e4172137864a4bec85
2017-10-27 14:50:14 -04:00
Corey Farrell
4760b2445c res_pjsip_pubsub: Prevent unload except during shutdown.
Prevent unload of the module as certain pjsip initialization functions
cannot be reversed.  This required a reorder of the module_load so that
the non-reversable pjsip functions are not called until all potential
errors have been ruled out.

ASTERISK-24483

Change-Id: Iee900f20bdd6ee1bfe23efdec0d87765eadce8a7
2017-10-19 11:20:52 -04:00
Sean Bright
ebd0a4bebf res_pjsip: Use ast_sip_is_content_type() where appropriate
Change-Id: If3ab0d73d79ac4623308bd48508af2bfd554937d
2017-09-22 10:05:23 -05:00
George Joseph
b748038230 res_pjsip_pubsub: Check for Content-Type header in rx_notify_request
pubsub_on_rx_notify_request wasn't checking for a null
Content-Type header before checking that it was
application/simple-message-summary.

ASTERISK-27279
Reported by: Ross Beer

Change-Id: Iec2a6c4d2e74af37ff779ecc9fd35644c5c4ea52
2017-09-19 13:52:17 -05:00
George Joseph
446d48fd49 res_pjsip: Add handling for incoming unsolicited MWI NOTIFY
A new endpoint parameter "incoming_mwi_mailbox" allows Asterisk to
receive unsolicited MWI NOTIFY requests and make them available to
other modules via the stasis message bus.

res_pjsip_pubsub has a new handler "pubsub_on_rx_mwi_notify_request"
that parses a simple-message-summary body and, if
endpoint->incoming_mwi_account is set, calls ast_publish_mwi_state
with the voice-message counts from the message.

Change-Id: I08bae3d16e77af48fcccc2c936acce8fc0ef0f3c
2017-09-13 09:24:28 -05:00
George Joseph
65ed2ea311 res_pjsip_pubsub: Fix reference to released endpoint
destroy_subscription was attempting to get the id of the
subscription tree's endpoint after we'd already called ao2_cleanup
on it causing a segfault.

Moved the cleanup until after the debug statement and since
endpoint could also be NULL at this point, check for that as well.

ASTERISK-27057 #close
Reported-by: Ryan Smith

Change-Id: Ice0a7727f560cf204d870a774c6df71e159b1678
2017-06-14 11:16:54 -05:00
George Joseph
747beb1ed1 modules: change module LOAD_FAILUREs to LOAD_DECLINES
In all non-pbx modules, AST_MODULE_LOAD_FAILURE has been changed
to AST_MODULE_LOAD_DECLINE.  This prevents asterisk from exiting
if a module can't be loaded.  If the user wishes to retain the
FAILURE behavior for a specific module, they can use the "require"
or "preload-require" keyword in modules.conf.

A new API was added to logger: ast_is_logger_initialized().  This
allows asterisk.c/check_init() to print to the error log once the
logger subsystem is ready instead of just to stdout.  If something
does fail before the logger is initialized, we now print to stderr
instead of stdout.

Change-Id: I5f4b50623d9b5a6cb7c5624a8c5c1274c13b2b25
2017-04-12 15:57:21 -06:00
George Joseph
5013d8f5d3 res_pjsip: Symmetric transports
A new transport parameter 'symmetric_transport' has been added.

When a request from a dynamic contact comes in on a transport with
this option set to 'yes', the transport name will be saved and used
for subsequent outgoing requests like OPTIONS, NOTIFY and INVITE.
It's saved as a contact uri parameter named 'x-ast-txp' and will
display with the contact uri in CLI, AMI, and ARI output.  On the
outgoing request, if a transport wasn't explicitly set on the
endpoint AND the request URI is not a hostname, the saved transport
will be used and the 'x-ast-txp' parameter stripped from the
outgoing packet.

* config_transport was modified to accept and store the new parameter.

* config_transport/transport_apply was updated to store the transport
  name in the pjsip_transport->info field using the pjsip_transport->pool
  on UDP transports.

* A 'multihomed_on_rx_message' function was added to
  pjsip_message_ip_updater that, for incoming requests, retrieves the
  transport name from pjsip_transport->info and retrieves the transport.
  If transport->symmetric_transport is set, an 'x-ast-txp' uri parameter
  containing the transport name is added to the incoming Contact header.

* An 'ast_sip_get_transport_name' function was added to res_pjsip.
  It takes an ast_sip_endpoint and a pjsip_sip_uri and returns a
  transport name if endpoint->transport is set or if there's an
  'x-ast-txp' parameter on the uri and the uri host is an ipv4 or
  ipv6 address.  Otherwise it returns NULL.

* An 'ast_sip_dlg_set_transport' function was added to res_pjsip
  which takes an ast_sip_endpoint, a pjsip_dialog, and an optional
  pjsip_tpselector.  It calls ast_sip_get_transport_name() and if
  a non-NULL is returned, sets the selector and sets the transport
  on the dialog.  If a selector was passed in, it's updated.

* res_pjsip/ast_sip_create_dialog_uac and ast_sip_create_dialog_uas
  were modified to call ast_sip_dlg_set_transport() instead of their
  original logic.

* res_pjsip/create_out_of_dialog_request was modified to call
  ast_sip_get_transport_name() and pjsip_tx_data_set_transport()
  instead of its original logic.

* Existing transport logic was removed from endpt_send_request
  since that can only be called after a create_out_of_dialog_request.

* res_pjsip/ast_sip_create_rdata was converted to a wrapper around
  a new 'ast_sip_create_rdata_with_contact' function which allows
  a contact_uri to be specified in addition to the existing
  parameters.  (See below)

* res_pjsip_pubsub/internal_pjsip_evsub_send_request was eliminated
  since all it did was transport selection and that is now done in
  ast_sip_create_dialog_uac and ast_sip_create_dialog_uas.

* 'contact_uri' was added to subscription_persistence.  This was
  necessary because although the parsed rdata contact header has the
  x-ast-txp parameter added (if appropriate),
  subscription_persistence_update stores the raw packet which
  doesn't have it.  subscription_persistence_recreate was then
  updated to call ast_sip_create_rdata_with_contact with the
  persisted contact_uri so the recreated subscription has the
  correct transport info to send the NOTIFYs.

* res_pjsip_session/internal_pjsip_inv_send_msg was eliminated since
  all it did was transport selection and that is now done in
  ast_sip_create_dialog_uac.

* pjsip_message_ip_updater/multihomed_on_tx_message was updated
  to remove all traces of the x-ast-txp parameter from the
  outgoing headers.

NOTE:  This change does NOT modify the behavior of permanent
contacts specified on an aor.  To do so would require that the
permanent contact's contact uri be updated with the x-ast-txp
parameter and the aor sorcery object updated.  If we need to
persue this, we need to think about cloning permanent contacts into
the same store as the dynamic ones on an aor load so they can be
updated without disturbing the originally configured value.

You CAN add the x-ast-txp parameter to a permanent contact's uri
but it would be much simpler to just set endpoint->transport.

Change-Id: I4ee1f51473da32ca54b877cd158523efcef9655f
2017-03-16 09:49:07 -06:00
George Joseph
fb68db87b1 res_pjsip_pubsub: Remove unneeded endpoint unref
When a subscription was being recreated and the endpoint wasn't
found, we were trying to unref the endpoint.  This was causing
FRACKs.  Removed the unref.

ASTERISK-26823 #close

Change-Id: If86d2aecff8fe853c7f38a1bfde721fcef3cd164
2017-02-27 20:09:36 -06:00
George Joseph
4bdf5d329f res_pjsip_pubsub: Correctly implement persisted subscriptions
This patch fixes 2 original issues and more that those 2 exposed.

* When we send a NOTIFY, and the client either doesn't respond or
  responds with a non OK, pjproject only calls our
  pubsub_on_evsub_state callback, no others.  Since
  pubsub_on_evsub_state (which does the sub_tree cleanup) does not
  expect to be called back without the other callbacks being called
  first, it just returns leaving the sub_tree orphaned.  Now
  pubsub_on_evsub_state checks the event for PJSIP_EVENT_TSX_STATE
  which is what pjproject will set to tell us that it was the
  transaction that timed out or failed and not the subscription
  itself timing our or being terminated by the client. If is
  TSX_STATE, pubsub_on_evsub_state now does the proper cleanup
  regardless of the state of the subscription.

* When a client renews a subscription, we don't update the
  persisted subscription with the new expires timestamp.  This causes
  subscription_persistence_recreate to prune the subscription if/when
  asterisk restarts.  Now, pubsub_on_rx_refresh calls
  subscription_persistence_update to apply the new expires timestamp.
  This exposed other issues however...

* When creating a dialog from rdata (which sub_persistence_recreate
  does from the packet buffer) there must NOT be a tag on the To
  header (which there will be when a client refreshes a
  subscription).  If there is one, pjsip_dlg_create_uas will fail.
  To address this, subscription_persistence_update now accepts a flag
  that indicates that the original packet buffer must not be updated.
  New subscribes don't set the flag and renews do.  This makes sure
  that when the rdata is recreated on asterisk startup, it's done
  from the original subscribe packet which won't have the tag on To.

* When creating a dialog from rdata, we were setting the dialog's
  remote (SUBSCRIBE) cseq to be the same as the local (NOTIFY) cseq.
  When the client tried to resubscribe after a restart with the
  correct cseq, we'd reject the request with an Invalid CSeq error.

* The acts of creating a dialog and evsub by themselves when
  recreating a subscription does NOT restart pjproject's subscription
  timer.  The result was that even if we did correctly recreate the
  subscription, we never removed it if the client happened to go away
  or send a non-OK response to a NOTIFY.  However, there is no
  pjproject function exposed to just set the timer on an evsub that
  wasn't created by an incoming subscribe request.  To address this,
  we create our own timer using ast_sip_schedule_task.  This timer is
  used only for re-establishing subscriptions after a restart.

  An earlier approach was to add support for setting pjproject's
  timer (via a pjproject patch) and while that patch is still included
  here, we don't use that call at the moment.

While addressing these issues, additional debugging was added and
some existing messages made more useful.  A few formatting changes
were also made to 'pjsip show scheduled tasks' to make displaying
the subscription timers a little more friendly.

ASTERISK-26696
ASTERISK-26756

Change-Id: I8c605fc1e3923f466a74db087d5ab6f90abce68e
2017-02-15 13:11:46 -06:00
Richard Mudgett
0ea3c371c5 res_pjsip_pubsub.c: Implement "pjsip show subscriptions" commands.
ASTERISK-23828 #close

Change-Id: Ifb8a3b61f447aedc58a8e6b36a810f7566018567
2017-01-23 18:07:04 -06:00
zuul
697fde39ac Merge "res_pjsip_pubsub.c: Fix incorrect message string wrapping." 2017-01-23 14:07:49 -06:00
Joshua Colp
e2da0021b9 Merge "res_pjsip_pubsub.c: Fix AMI event list counts." 2017-01-23 11:10:25 -06:00
Richard Mudgett
ef9164b9ca res_pjsip_pubsub.c: Fix AMI event list counts.
Fix the AMI PJSIPShowSubscriptionsInbound, PJSIPShowSubscriptionsOutbound,
and PJSIPShowResourceLists actions event counts.  The reported counts may
not necessarily be accurate depending on what happens.

The subscriptions count would be wrong if Asterisk ever has outbound
subscriptions.

The resource list count could be wrong if a list were added or removed
during the AMI action being processed.

Change-Id: I4344301827523fa174960a42c413fd19abe4aed5
2017-01-20 12:39:41 -06:00
Richard Mudgett
ab858295a2 res_pjsip_pubsub.c: Fix incorrect message string wrapping.
Change-Id: Id771e6fe56d89ce365ddcbb423f820af97211120
2017-01-20 12:37:19 -06:00
Richard Mudgett
6d648185bc res_pjsip_pubsub.c: Eliminate trivial SCOPED_LOCK usage.
Change-Id: Ie0b69a830385452042fa19e7d267c6790ec6b6be
2017-01-20 12:33:56 -06:00
Richard Mudgett
bb196323f9 res_pjsip: Fix tdata leaks in off nominal paths.
Change-Id: Ie83e06e88c2d60157775263b07e40b61718ac97b
2016-11-10 17:15:59 -05:00
Richard Mudgett
ba362822f3 res_pjsip: Add ignore_uri_user_options option.
This implements the chan_sip legacy_useroption_parsing option but with a
better name.

* Made the caller-id number and redirecting number strings obtained from
incoming SIP URI user fields always truncated at the first semicolon.
People don't care about anything after the semicolon showing up on their
displays even though the RFC allows the semicolon.

ASTERISK-26316 #close
Reported by: Kevin Harwell

Change-Id: Ib42b0e940dd34d84c7b14bc2e90d1ba392624f62
2016-09-09 17:13:02 -05:00
Alexei Gradinari
81ea024d93 res_pjsip_pubsub: fixed a bug when pjsip_tx_data_dec_ref is called twice.
This patch removed call of pjsip_tx_data_dec_ref in send_notify
if send_request failed.
The pjsip_dlg_send_request deletes the message on error by itself.

It seems this patch fixes next issues:
ASTERISK-26199
ASTERISK-26166
ASTERISK-26174

Change-Id: I8b05917c93d993f95d604c042ace5f1a5500f59a
2016-07-21 11:29:15 -04:00
Matt Jordan
c49833653b res/res_pjsip_pubsub: Add additional debug statements
When something very sad and wrong occurs, it's challenging sometimes to
figure out why. This patch adds some additional debug statements on
off-nominal paths to try and make debugging easier.

Change-Id: I7bffb73cc733b6f80193a23340881db4a102b640
2016-07-13 09:11:46 -05:00
George Joseph
b57cd01404 res_pjsip_pubsub: Address SEGV when attempting to terminate a subscription
Occasionally under load we'll attempt to send a final NOTIFY on a
subscription that's already been terminated and a SEGV will occur
down in pjproject's evsub_destroy function.  This is a result of a
race condition between all the paths that can generate a notify
and/or destroy the underlying pjproject evsub object:

 * The client can send a SUBSCRIBE with Expires: 0.
 * The client can send a SUBSCRIBE/refresh.
 * The subscription timer can expire.
 * An extension state can change.
 * An MWI event can be generated.
 * The pjproject transaction timer (timer_b) can expire.

Normally when our pubsub_on_evsub_state is called with a terminate,
we push a task to the serializer and return at which point the dialog
is unlocked.  This is usually not a problem because the task runs
immediately and locks the dialog again.  When the system is heavily
loaded though, there may be a delay between the unlock and relock
during which another event may occur such as the subscription timer
or timer_b expiring, an extension state change, etc.  These may also
cause a terminate to be processed and if so, we could cause pjproject
to try to destroy the evsub structure twice.  There's no way for us to
tell that the evsub was already destroyed and the evsub's group lock
can't tolerate this and SEGVs.

The remedy is twofold.

 * A patch has been submitted to Teluu and added to the bundled
   pjproject which adds add/decrement operations on evsub's group lock.

 * In res_pjsip_pubsub:
   * configure.ac and pjproject-bundled's configure.m4 were updated
     to check for the new evsub group lock APIs.
   * We now add a reference to the evsub group lock when we create
     the subscription and remove the reference when we clean up the
     subscription.  This prevents evsub from being destroyed before
     we're done with it.
   * A state has been added to the subscription tree structure so
     termination progress can be tracked through the asyncronous tasks.
   * The pubsub_on_evsub_state callback has been split so it's not doing
     double duty.  It now only handles the final cleanup of the
     subscription tree.  pubsub_on_rx_refresh now handles both client
     refreshes and client terminates.  It was always being called for
     both anyway.
   * The serialized_on_server_timeout task was removed since
     serialized_pubsub_on_rx_refresh was almost identical.
   * Missing state checks and ao2_cleanups were added.
   * Some debug levels were adjusted to make seeing only off-nominal
     things at level 1 and nominal or progress things at level 2+.

ASTERISK-26099 #close
Reported-by: Ross Beer.

Change-Id: I779d11802cf672a51392e62a74a1216596075ba1
2016-06-21 13:50:24 -05:00
Richard Mudgett
5b7b16a87f res_pjsip_pubsub.c: Recreate subscriptions using distributor serializer.
* Resolves potential reentrancy problems if system restarted in the middle
of subscription message transactions.

* Fixes memory leak recreating persistent subscriptions when the
subscription resource tree could not be created.

ASTERISK-26088
Reported by:  Richard Mudgett

Change-Id: I71e34d7ae8ed35a694f1030e820e2548c48697be
2016-06-09 10:32:06 -05:00
Richard Mudgett
c2ae49249c res_pjsip_pubsub.c: Use distributor serializer for incoming subscriptions.
We must continue using the serializer that the original SUBSCRIBE came in
on for the dialog.  There may be retransmissions already enqueued in the
original serializer that can result in reentrancy and message sequencing
problems.  The "sip_transaction Unable to register SUBSCRIBE transaction
(key exists)" message is a notable symptom of this issue.

Outgoing subscriptions still create the pjsip/pubsub/<endpoint>
serializers for their dialogs.

ASTERISK-26088
Reported by:  Richard Mudgett

Change-Id: I18b00bb74a56747b2c8c29543a82440b110bf0b0
2016-06-09 10:32:06 -05:00
Joshua Colp
d03e170ae7 res_pjsip_pubsub: Use common datastores container API.
This migrates res_pjsip_pubsub over to using the newly
introduce common datastores management API instead of using
its own implementations for both subscriptions and
publications.

As well the extension state data now provides a generic
datastores container instead of a subscription. This allows
the dialog-info+xml body generator to work for both
subscriptions and publications.

ASTERISK-25999 #close

Change-Id: I773f9e4f35092da0f653566736a8647e8cfebef1
2016-05-09 10:40:36 -03:00
Joshua Colp
bc19d9a2b0 Merge "res_pjsip_exten_state: Check if body generator is available." 2016-04-29 14:33:01 -05:00
Joshua Colp
d57847a7c7 Merge "res_pjsip_pubsub.c: Fix body generator registration race." 2016-04-29 13:33:43 -05:00
Richard Mudgett
0b5292525c res_pjsip_exten_state: Check if body generator is available.
When starting the extension state publishers, check if the requested
message body generator is available.  If not available give error message
and skip starting that publisher.

* res_pjsip_pubsub.c: Create new API if type/subtype generator
registered.

* res_pjsip_exten_state.c: Use new body generator API for validation.

ASTERISK-25922

Change-Id: I4ad69200666e3cc909d4619e3c81042d7f9db25c
2016-04-28 17:14:44 -05:00
Richard Mudgett
3af83ea2fb res_pjsip_pubsub.c: Add useful information to some messages.
Change-Id: Ia0b2e15773894c599e5c5748bbc70e99f434192a
2016-04-28 17:05:20 -05:00
Richard Mudgett
8e1b663b87 res_pjsip_pubsub.c: Fix body generator registration race.
Change-Id: Id8752073ef06472a2fd96080f4009fac42843e67
2016-04-28 17:02:08 -05:00
George Joseph
e2524fcee3 res_pjsip_mwi: Add voicemail extension and mwi_subscribe_replaces_unsolicited
res_pjsip_mwi was missing the chan_sip "vmexten" functionality which adds
the Message-Account header to the MWI NOTIFY.  Also, specifying mailboxes
on endpoints for unsolicited mwi and on aors for subscriptions required
that the admin know in advance which the client wanted.  If you specified
mailboxes on the endpoint, subscriptions were rejected even if you also
specified mailboxes on the aor.

Voicemail extension:
* Added a global default_voicemail_extension which defaults to "".
* Added voicemail_extension to both endpoint and aor.
* Added ast_sip_subscription_get_dialog for support.
* Added ast_sip_subscription_get_sip_uri for support.

When an unsolicited NOTIFY is constructed, the From header is parsed, the
voicemail extension from the endpoint is substituted for the user, and the
result placed in the Message-Account field in the body.

When a subscribed NOTIFY is constructed, the subscription dialog local uri
is parsed, the voicemail_extension from the aor (looked up from the
subscription resource name) is substituted for the user, and the result
placed in the Message-Account field in the body.

If no voicemail extension was defined, the Message-Account field is not added
to the NOTIFY body.

mwi_subscribe_replaces_unsolicited:
* Added mwi_subscribe_replaces_unsolicited to endpoint.

The previous behavior was to reject a subscribe if a previous internal
subscription for unsolicited MWI was found for the mailbox.  That remains the
default.  However, if there are mailboxes also set on the aor and the client
subscribes and mwi_subscribe_replaces_unsolicited is set, the existing internal
subscription is removed and replaced with the external subscription.  This
allows an admin to configure mailboxes on both the endpoint and aor and allows
the client to select which to use.

ASTERISK-25865 #close
Reported-by: Ross Beer

Change-Id: Ic15a9415091760539c7134a5ba3dc4a6a1217cea
2016-03-30 13:23:54 -05:00
George Joseph
d2eb65f71e res_pjsip: Strip spaces from items parsed from comma-separated lists
Configurations like "aors = a, b, c" were either ignoring everything after "a"
or trying to look up " b".  Same for mailboxes,  ciphers, contacts and a few
others.

To fix, all the strsep(&copy, ",") calls have been wrapped in ast_strip.  To
facilitate this, ast_strip, ast_skip_blanks and ast_skip_nonblanks were
updated to handle null pointers.

In some cases, an ast_strlen_zero() test was added to skip consecutive commas.

There was also an attempt to ast_free an ast_strdupa'd string in
ast_sip_for_each_aor which was causing a SEGV.  I removed it.

Although this issue was reported for realtime, the issue was in the res_pjsip
modules so all config mechanisms were affected.

ASTERISK-25829 #close
Reported-by: Mateusz Kowalski

Change-Id: I0b22a2cf22a7c1c50d4ecacbfa540155bec0e7a2
2016-03-07 13:16:41 -06:00
George Joseph
ba8adb4ce3 res_pjsip/config_transport: Allow reloading transports.
The 'reload' mechanism actually involves closing the underlying
socket and calling the appropriate udp, tcp or tls start functions
again.  Only outbound_registration, pubsub and session needed work
to reset the transport before sending requests to insure that the
pjsip transport didn't get pulled out from under them.

In my testing, no calls were dropped when a transport was changed
for any of the 3 transport types even if ip addresses or ports were
changed. To be on the safe side however, a new transport option was
added (allow_reload) which defaults to 'no'.  Unless it's explicitly
set to 'yes' for a transport, changes to that transport will be ignored
on a reload of res_pjsip.  This should preserve the current behavior.

Change-Id: I5e759850e25958117d4c02f62ceb7244d7ec9edf
2016-02-19 18:57:55 -06:00
Joshua Colp
5c400a0fed res_pjsip_pubsub: Move where the subscription is stored to after initialized.
A problem arose when testing the AMI subscription listing actions where it
was possible for a subscription that had not been fully initialized to be
listed. This was problematic as the underlying listing code would crash.

This change makes it so the subscription tree is fully set up before it is
added to the list of subscriptions. This ensures that when the listing actions
get the subscription it is valid.

ASTERISK-25738 #close

Change-Id: Iace2b13641c31bbcc0d43a39f99aba1f340c0f48
2016-02-15 13:01:54 -06:00
Mark Michelson
b073244c51 res_pjsip_pubsub: Prevent crash from AMI command on freed subscription.
A test recently uncovered that running an ill-timed AMI command to show
inbound subscriptions could cause a crash since Asterisk will try to
operate on a freed subscription.

The fix for this is to remove the subscription tree from the list of
subscriptions at the time that we are sending our final NOTIFY request
out. This way, as the subscription is in the process of dying, it is
inaccessible from AMI.

Change-Id: Ic0239003d8d73e04c47c12dd2a7e23867e5b5b23
2016-01-25 16:58:39 -06:00
Richard Mudgett
0bca2a5c26 res_pjsip: Create human friendly serializer names.
PJSIP name formats:
pjsip/aor/<aor>-<seq> -- registrar thread pool serializer
pjsip/default-<seq> -- default thread pool serializer
pjsip/messaging -- messaging thread pool serializer
pjsip/outreg/<registration>-<seq> -- outbound registration thread pool
serializer
pjsip/pubsub/<endpoint>-<seq> -- pubsub thread pool serializer
pjsip/refer/<endpoint>-<seq> -- REFER thread pool serializer
pjsip/session/<endpoint>-<seq> -- session thread pool serializer
pjsip/websocket-<seq> -- websocket thread pool serializer

Change-Id: Iff9df8da3ddae1132cb2ef65f64df0c465c5e084
2016-01-08 22:11:45 -06:00
Joshua Colp
b522a5e30f res_pjsip_pubsub: Fix assertion when UAS dialog creation fails.
When compiled with assertions enabled one will occur when destroying
the subscription tree when UAS dialog creation fails. This is because
the code assumes that a dialog will always exist on a subscription
tree when in reality during this specific scenario it won't.

This change makes it so a dialog is not removed from the subscription
tree if it is not present.

ASTERISK-25505 #close

Change-Id: Id5c182b055aacc5e66c80546c64804ce19218dee
2015-10-29 08:33:08 -05:00
Mark Michelson
7f9823ff57 res_pjsip_pubsub: Prevent sending NOTIFY on destroyed dialog.
A certain situation can result in our attempting to send a NOTIFY on a
destroyed dialog. Say we attempt to send a NOTIFY to a subscriber, but
that subscriber has dropped off the network. We end up retransmitting
that NOTIFY until the appropriate SIP timer says to destroy the NOTIFY
transaction. When the pjsip evsub code is told that the transaction has
been terminated, it responds in kind by alerting us that the
subscription has been terminated, destroying the subscription, and then
removing its reference to the dialog, thus destroying the dialog.

The problem is that when we get told that the subscription is being
terminated, we detect that we have not sent a terminating NOTIFY
request, so we queue up such a NOTIFY to be sent out. By the time that
queued NOTIFY gets sent, the dialog has been destroyed, so attempting to
send that NOTIFY can result in a crash.

The fix being introduced here is actually a reintroduction of something
the pubsub code used to employ. We hold a reference to the dialog and
wait to decrement our reference to the dialog until our subscription
tree object is destroyed. This way, we can send messages on the dialog
even if the PJSIP evsub code wants to terminate earlier than we would
like.

In doing this, some NULL checks for subscription tree dialogs have been
removed since NULL dialogs are no longer actually possible.

Change-Id: I013f43cddd9408bb2a31b77f5db87a7972bfe1e5
2015-10-22 16:18:08 -05:00
Mark Michelson
e9e4bc9ece res_pjsip_pubsub: Ensure dialog lock balance.
When sending a NOTIFY, we lock the dialog and then unlock the dialog
when finished. A recent change made it so that the subscription tree's
dialog pointer will be set NULL when sending the final NOTIFY request
out. This means that when we attempt to unlock the dialog, we pass a
NULL pointer to pjsip_dlg_dec_lock(). The result is that the dialog
remains locked after we think we have unlocked it. When a response to
the NOTIFY arrives, the monitor thread attempts to lock the dialog, but
it cannot because we never released the dialog lock. This results in
Asterisk being unable to process incoming SIP traffic any longer.

The fix in this patch is to use a local pointer to save off the pointer
value of the subscription tree's dialog when locking and unlocking the
dialog. This way, if the subscription tree's dialog pointer is NULLed
out, the local pointer will still have point to the proper place and the
dialog lock will be unlocked as we expect.

Change-Id: I7ddb3eaed7276cceb9a65daca701c3d5e728e63a
2015-10-22 16:18:08 -05:00
Mark Michelson
b96267f7a3 res_pjsip_pubsub: Prevent crashes on final NOTIFY.
The SIP dialog is removed from the subscription tree when the final
NOTIFY is sent. However, after the final NOTIFY is sent, the persistence
update function still attempts to access the cseq from the dialog,
resulting in a crash.

This fix removes the subscription persistence at the same time that the
dialog is removed from the subscription tree. This way, there is no
attempt to update persistence when the subscription is being destroyed.

Change-Id: Ibb46977a6cef9c51dc95f40f43446e3d11eed5bb
2015-10-22 16:18:08 -05:00
Mark Michelson
386cd7b2b0 res_pjsip_pubsub: Remove serializer when sending final NOTIFY.
There have been crashes seen where a taskprocessor's listener is NULL
unexpectedly.

Looking at backtraces, the problem was specifically seen in PJSIP
serializers.

Subscriptions make the mistake of removing a serializer from a dialog
during subscription tree destruction. Since subscription trees are
reference-counted, guaranteeing the circumstances behind the destruction
are not possible. This makes it so that the dialog serializer can be
removed while not holding the dialog lock. This makes it possible for
the distributor to get a pointer to the dialog serializer and have that
serializer get freed out from under it.

The fix for this is to remove the serializer from a subscription dialog
when sending the final NOTIFY. This guarantees that the serializer is
removed with the dialog lock held. By doing this, we guarantee that if
the distributor gains access to the dialog's serializer, it will not be
possible for the serializer to get freed by another thread.

Change-Id: I21f5dac33529f65cec45679bdace60670800ff66
2015-10-22 16:17:47 -05:00
Mark Michelson
0b63d011c9 res_pjsip_pubsub: Fix crash on destruction of empty subscription tree.
If an old persistent subscription is recreated but then immediately
destroyed because it is out of date, the subscription tree will have no
leaf subscriptions on it. This was resulting in a crash when attempting
to destroy the subscription tree.

A simple NULL check fixes this problem.

Change-Id: I85570b9e2bcc7260a3fe0ad85904b2a9bf36d2ac
2015-10-22 15:39:58 -05:00
Mark Michelson
ac0194dad6 res_pjsip_pubsub: Solidify lifetime and ownership of objects.
There have been crashes and general instability seen in the pubsub code,
so this patch introduces three changes to increase the stability.

First, the ownership model for subscriptions has been modified. Due to
RLS, subscriptions are stored in memory as a tree structure. Prior to my
patch, the PJSIP subscription was the owner of the subscription tree.
When the PJSIP subscription told us that it was terminating, we started
destroying the subscription tree along with all of the individual leaf
subscriptions that belong to the tree. The problem with this model is
that the two actors in play here, the PJSIP subscription and the
individual leaf subscriptions, need to have joint ownership of the
subscription tree. So now, the PJSIP subscription and the individual
leaf subscriptions each have a reference to the subscription tree. This
way, we will not actually free memory until no players are left that
care. The PJSIP subscription is a bigger stakeholder, in that if the
PJSIP subscription's reference to the subscription tree is removed, the
subscription tree instructs the leaf subscriptions to shut down and drop
their references to the subscription tree when possible. The individual
leaf subscriptions, upon being told to shut down, can drop their stasis
subscriptions or whatever they use to learn of new state, and then drop
their reference to the subscription tree once they are ready to die.

Second, the lifetime of a PJSIP subscription's reference to our
subscription tree has been altered. As I learned from doing a deep dive,
the PJSIP evsub code can tell Asterisk multiple times that the
subscription has been terminated, and not all of these times
are especially helpful. I have altered the message flow that we use for
SIP subscriptions such that we will always drop the PJSIP subscription's
reference to the subscription tree when we send the NOTIFY that
terminates a SIP subscription. This also means that we will now queue
NOTIFY requests to be sent after responding to incoming SUBSCRIBEs so
that we can have predictable state changes from the PJSIP evsub code.

Third, the synchronization of operations has been improved. PJSIP can
call into our code from a serializer thread (e.g. upon receiving an
incoming request) or from the monitor thread (e.g. when a subscription
times out). Because of this, there is the possibility of competing
threads stepping on each other. PJSIP attempts to do some
synchronization on its own by always keeping the dialog lock held when
it calls into us. However, since we end up pushing tasks into the
serializer, the result was that serialized operations were not grabbing
the dialog lock and could, as a result, step on something that was being
attempted by a different thread. Now we ensure that serialized
operations grab the dialog lock, then check for extenuating
circumstances, then proceed with their operation if they can.

Change-Id: Iff2990c40178dad9cc5f6a5c7f76932ec644b2e5
2015-10-22 15:39:58 -05:00
Mark Michelson
e47396721f res_pjsip_pubsub: Eliminate race during initial NOTIFY.
There is a slim chance of a race condition occurring where two threads
can both attempt to manipulate the same area.

Thread A can be handling an incoming initial SUBSCRIBE request. Thread A
lets the specific subscription handler know that the subscription has
been established.

At this point, Thread B may detect a state change on the subscribed
resource and queue up a notification task on Thread C, the subscription
serializer thread.

Now Thread A attempts to generate the initial NOTIFY request to send to
the subscriber at the same time that Thread C attempts to generate a
state change NOTIFY request to send to the subscriber.

The result is that Threads A and C can step on the same memory area,
resulting in a crash. The crash has been observed as happening when
attempting to allocate more space to hold the body for the NOTIFY.

The solution presented here is to queue the subscription establishment
and initial NOTIFY generation onto the subscription serializer thread
(Thread C in the above scenario). This way, there is no way that a state
change notification can occur before the initial NOTIFY is sent, and if
there is a quick succession of NOTIFYs, we can guarantee that the two
NOTIFY requests will be sent in succession.

Change-Id: I5a89a77b5f2717928c54d6efb9955e5f6f5cf815
2015-09-17 11:12:22 -05:00
Richard Mudgett
69824fdfbf res_pjsip_pubsub.c: Mark ast_sip_create_subscription() as not used.
Change-Id: I2b8db18eac36c01a5c7eb9467699124e203fd093
2015-09-10 13:16:12 -05:00
Richard Mudgett
2526659432 res_pjsip_pubsub.c: Add some notification comments.
Change-Id: Ie62ff1f4b7adc1a12fa0303f53926af249b25e20
2015-09-10 13:16:12 -05:00
Richard Mudgett
9b290dfe2f res_pjsip_pubsub.c: Set dlg_status code instead of sending SIP response.
We should not try to send a SIP response message because we may be
restoring a persistent subscription where we are not responding to a SIP
request.

Change-Id: Id89167ef90320c5563f37e632db0dda6cb9e7dec
2015-09-10 13:16:12 -05:00
Richard Mudgett
73eb132012 res_pjsip_pubsub.c: Fix off-nominal memory leak.
Fix off-nominal visited vector leak in build_resource_tree().

Change-Id: If0399c7941c9c0b1038bcfb7b9a371760977831c
2015-09-10 13:16:12 -05:00
Richard Mudgett
2b30fc2b2d res_pjsip_pubsub.c: Fix one byte buffer overrun error.
ast_sip_pubsub_register_body_generator() did not account for the null
terminator set by sprintf() in the allocated output buffer.

Change-Id: I388688a132e479bca6ad1c19275eae0070969ae2
2015-09-10 13:16:12 -05:00