Asterisk
  1. Asterisk
  2. ASTERISK-27147

Either asterisk or pjproject isn't re-using tcp connections (again)

    Details

    • Type: Bug Bug
    • Status: Closed
    • Severity: Major Major
    • Resolution: Fixed
    • Affects Version/s: 13.17.0, 14.6.0, GIT
    • Target Release Version/s: 13.18.0, 14.7.0, 15.1.0
    • Component/s: Resources/res_pjsip
    • Security Level: None
    • Labels:
      None

      Description

      Last year we submitted patches to pjproject to fix not re-using tcp connections. It looks like it's broke again.

      Asterisk A and B have a "trunk" between them. A registers to B.
      After A registers, there is 1 open TCP connection between them.
      B sends a call to A.
      Instead of re-using the existing connection, B establishes a new cconnection back to A.
      Now there are 2 tcp connections open.

      If A were behind a firewall that didn't allow inbound new connections, there'd be an issue.

      1. client_pjsip_wizard.conf
        2 kB
        George Joseph
      2. client_pjsip.conf
        0.9 kB
        George Joseph
      3. server_pjsip_wizard.conf
        2 kB
        George Joseph
      4. server_pjsip.conf
        0.8 kB
        George Joseph

        Issue Links

          Activity

          Hide
          Richard Mudgett added a comment -

          The connections are being reused. We're just not telling the other side the right contact address and port for there to be only one connection. When Asterisk A registers with Asterisk B then the connection on A is IP-A:random-port (say port 56789) to IP-B:5060. Asterisk A says contact it at IP-A:5060. So when B wants to send A a call, it has no connection to A at IP-A:5060. It does have one for IP-A:56789 but it wasn't told to use that address as a contact address. When A responds to the INVITE it sends the responses over the incoming transport. When A later sends a request to B (say a COLP UPDATE), it uses B's contact address which is IP-B:5060. Asterisk A does find such a connection created by the registration and uses it. However, this isn't the connection that B sent the original INVITE over. This call is now using two different connections. I'd think that if A had registered with a contact address of IP-A:56789 then B would use that existing connection and then there would be only one connection being used.

          With rewrite_contact enabled only on A's side, when A sends the UPDATE request in the scenario above, it sends the UPDATE to the source address of the connection created by the incoming INVITE instead of where the contact header stated. The register connection isn't used for the call.

          With rewrite_contact enabled only on B's side, the above scenario only uses one connection and B doesn't create a new connection.

          The rewrite_contact option is intended for B's server side situation. However, it does have some potential benefit on A's client side situation. The benefit is if B initiates a call with A because B doesn't have the rewrite_contact functionality or its not enabled. Asterisk A will reuse the connection established by the incoming call for the duration of the call.

          A problem does crop up on B's side with rewrite_contact enabled. If the TCP connection gets disconnected or if B is restarted then the rewritten register contact for A is now invalid and won't go away until it expires. If B tries to send a call to A using the invalid connection then A is not likely to see the request. Asterisk A either won't be listening on that port for new connections or a NAT/firewall will block it.

          A problem also crops up on A's side when the TCP connection gets disconnected. Now A cannot receive incoming calls from B until it normally attempts to re-register. If B also has max_contacts=1 set and remove_existing=no then the invalid register contact on B will cause A's register attempts to be rejected. Asterisk A may give up registration attempts until manually prodded to resume.

          Show
          Richard Mudgett added a comment - The connections are being reused. We're just not telling the other side the right contact address and port for there to be only one connection. When Asterisk A registers with Asterisk B then the connection on A is IP-A:random-port (say port 56789) to IP-B:5060. Asterisk A says contact it at IP-A:5060. So when B wants to send A a call, it has no connection to A at IP-A:5060. It does have one for IP-A:56789 but it wasn't told to use that address as a contact address. When A responds to the INVITE it sends the responses over the incoming transport. When A later sends a request to B (say a COLP UPDATE), it uses B's contact address which is IP-B:5060. Asterisk A does find such a connection created by the registration and uses it. However, this isn't the connection that B sent the original INVITE over. This call is now using two different connections. I'd think that if A had registered with a contact address of IP-A:56789 then B would use that existing connection and then there would be only one connection being used. With rewrite_contact enabled only on A's side, when A sends the UPDATE request in the scenario above, it sends the UPDATE to the source address of the connection created by the incoming INVITE instead of where the contact header stated. The register connection isn't used for the call. With rewrite_contact enabled only on B's side, the above scenario only uses one connection and B doesn't create a new connection. The rewrite_contact option is intended for B's server side situation. However, it does have some potential benefit on A's client side situation. The benefit is if B initiates a call with A because B doesn't have the rewrite_contact functionality or its not enabled. Asterisk A will reuse the connection established by the incoming call for the duration of the call. A problem does crop up on B's side with rewrite_contact enabled. If the TCP connection gets disconnected or if B is restarted then the rewritten register contact for A is now invalid and won't go away until it expires. If B tries to send a call to A using the invalid connection then A is not likely to see the request. Asterisk A either won't be listening on that port for new connections or a NAT/firewall will block it. A problem also crops up on A's side when the TCP connection gets disconnected. Now A cannot receive incoming calls from B until it normally attempts to re-register. If B also has max_contacts=1 set and remove_existing=no then the invalid register contact on B will cause A's register attempts to be rejected. Asterisk A may give up registration attempts until manually prodded to resume.
          Hide
          Ross Beer added a comment -

          When the connection disconnects, should any BLF/MWI subscriptions be removed also?

          Show
          Ross Beer added a comment - When the connection disconnects, should any BLF/MWI subscriptions be removed also?
          Hide
          Richard Mudgett added a comment -

          Ross Beer That should not be necessary. The contact should be remade soon anyway.

          Show
          Richard Mudgett added a comment - Ross Beer That should not be necessary. The contact should be remade soon anyway.
          Hide
          Ross Beer added a comment -

          If the phone goes offline for some other reason and stays offline, won't the BLF/MWI persist?

          When a voicemail is left or BLF state change happen, wouldn't Asterisk attempt to contact the endpoint in the same way as calling the endpoint would? This would fail as per the above description.

          Show
          Ross Beer added a comment - If the phone goes offline for some other reason and stays offline, won't the BLF/MWI persist? When a voicemail is left or BLF state change happen, wouldn't Asterisk attempt to contact the endpoint in the same way as calling the endpoint would? This would fail as per the above description.
          Hide
          Richard Mudgett added a comment -

          Ross Beer Yes the subscription will persist because it is supposed to persist even across Asterisk restarts. Yes any subsequent notify will fail until the endpoint re-registers because there is no valid contact address. These are two separate things. It would be bad to cancel any subscriptions because of a temporary unreachable condition.

          Show
          Richard Mudgett added a comment - Ross Beer Yes the subscription will persist because it is supposed to persist even across Asterisk restarts. Yes any subsequent notify will fail until the endpoint re-registers because there is no valid contact address. These are two separate things. It would be bad to cancel any subscriptions because of a temporary unreachable condition.
          Hide
          Friendly Automation added a comment -

          Change 6225 merged by Jenkins2:
          res_pjsip: Fix prune_on_boot to remove only contacts for the host.

          https://gerrit.asterisk.org/6225

          Show
          Friendly Automation added a comment - Change 6225 merged by Jenkins2: res_pjsip: Fix prune_on_boot to remove only contacts for the host. https://gerrit.asterisk.org/6225
          Hide
          Friendly Automation added a comment -

          Change 6226 merged by Jenkins2:
          res_pjsip: Fix prune_on_boot to remove only contacts for the host.

          https://gerrit.asterisk.org/6226

          Show
          Friendly Automation added a comment - Change 6226 merged by Jenkins2: res_pjsip: Fix prune_on_boot to remove only contacts for the host. https://gerrit.asterisk.org/6226
          Hide
          Friendly Automation added a comment -

          Change 6227 merged by Jenkins2:
          res_pjsip: Fix prune_on_boot to remove only contacts for the host.

          https://gerrit.asterisk.org/6227

          Show
          Friendly Automation added a comment - Change 6227 merged by Jenkins2: res_pjsip: Fix prune_on_boot to remove only contacts for the host. https://gerrit.asterisk.org/6227
          Hide
          Friendly Automation added a comment -

          Change 6228 merged by Joshua Colp:
          res_pjsip: Fix prune_on_boot to remove only contacts for the host.

          https://gerrit.asterisk.org/6228

          Show
          Friendly Automation added a comment - Change 6228 merged by Joshua Colp: res_pjsip: Fix prune_on_boot to remove only contacts for the host. https://gerrit.asterisk.org/6228

            People

            • Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development