Skip to content

Implement SIP Call Transfer (Blind & Attended Transfer - RFC 3515 / RFC 3891) #49

Description

@thorsager

📌 Summary

Implement full support for Blind (Unattended) and Attended (Consultative) call transfers within the SIP-PBX B2BUA core engine. This feature will enable call center agents to seamlessly route ongoing active calls to other internal agents or external PSTN numbers using industry-standard SIP signaling (REFER, NOTIFY, and the Replaces header).


🎯 User Stories

  • As a Call Center Agent (Transferor): I want to instantly forward an active caller to another extension without consulting the target agent first (Blind Transfer).
  • As a Call Center Agent (Transferor): I want to place a caller on hold, call another agent to consult, and then complete the transfer to bridge the caller with the second agent (Attended Transfer).
  • As a PBX Administrator: I want all call transfers to adhere strictly to RFC 3515 and RFC 3891 so that third-party SIP hardphones and softphones (Yealink, Polycom, Linphone, Cisco, etc.) work natively without proprietary workarounds.

⚙️ Functional & Technical Requirements

1. Blind Transfer Support (RFC 3515)

  • Handle incoming in-dialog REFER requests from the Transferor.
  • Extract and validate the target SIP URI from the Refer-To header.
  • Establish an implicit event subscription (Event: refer).
  • Initiate a new outbound INVITE from the PBX to the Transfer Target (Agent C).
  • Send status updates via NOTIFY with message/sipfrag bodies back to the Transferor:
    • 100 Trying
    • 180 Ringing
    • 200 OK
  • Re-anchor media (RTP audio stream) between Transferee (Caller) and Target upon answer.
  • Automatically terminate the Transferor's call leg with a BYE after successful bridge.

2. Attended Transfer Support (RFC 3891)

  • Support parsing and processing of the Replaces header embedded inside the Refer-To URI parameters:
    Refer-To: <sip:agentC@pbx.domain?Replaces=Call-ID-AC%3Bto-tag%3D...%3Bfrom-tag%3D...>
  • Match existing consultation dialog using the Call-ID, To-Tag, and From-Tag parameters.
  • Issue an in-dialog INVITE with Replaces or perform internal B2BUA dialog replacement.
  • Re-negotiate SDP parameters (a=sendrecv) to route media directly between Transferee and Target.
  • Send 200 OK in NOTIFY to Transferor and terminate both original consultation legs (BYE).

3. Error Handling & Edge Cases

  • Transfer Failure / Rejection: If the target is busy, rejects the call, or times out:
    • Send appropriate NOTIFY body (e.g., 486 Busy Here or 503 Service Unavailable).
    • Keep the original caller on hold and allow the Transferor agent to resume the call seamlessly.
  • Malformed Headers: Reject unparseable REFER or Replaces parameters with 400 Bad Request.
  • Permission & Routing: Verify that the Transfer Target passes PBX dialplan permission checks before placing the outbound leg.

📐 SIP Call Flow References

Blind Transfer Flow

 Transferor (Agent A)        PBX Core (B2BUA)          Target (Agent C)
       |                          |                        |
       |--- REFER (Refer-To: C) ->|                        |
       |<-- 202 Accepted ---------|                        |
       |                          |--- INVITE ------------>|
       |<-- NOTIFY (100 Trying) --|                        |
       |<-- NOTIFY (180 Ringing) -|<-- 180 Ringing --------|
       |<-- NOTIFY (200 OK) ------|<-- 200 OK -------------|
       |--- BYE ----------------->|                        |

Attended Transfer Flow

 Transferor (Agent A)        PBX Core (B2BUA)          Target (Agent C)
       |                          |                        |
       |-- (Call 1 Active) ------>|                        |
       |-- re-INVITE (Hold) ----->|                        |
       |-- INVITE (New Call) ---->|                        |
       |                          |--- INVITE ------------>|
       |                          |<-- 200 OK -------------|
       |<-- 200 OK ---------------|                        |
       |================ Consult with Agent C =============|
       |                          |                        |
       |-- REFER ---------------->|                        |
       |   (Refer-To: C?Replaces) |                        |
       |<-- 202 Accepted ---------|                        |
       |                          |--- INVITE (Replaces) ->|
       |                          |<-- 200 OK -------------|
       |<-- NOTIFY (200 OK) ------|                        |
       |--- BYE ----------------->|                        |

✅ Acceptance Criteria & Testing Plan

Automated / Unit Tests

  • sip_parser_test: Unit tests for Refer-To URI parameter extraction and RFC 3891 Replaces tag parsing.
  • dialog_state_test: Unit test for state transition of B2BUA legs during replacement.

Integration Tests (SIPp Scenarios)

  • Scenario 1: Successful Blind Transfer execution with message/sipfrag validation.
  • Scenario 2: Successful Attended Transfer with active call replacement.
  • Scenario 3: Failed transfer recovery (Target line busy -> Transferor retrieves original call).

Interoperability Testing

  • Verify functionality with Yealink T4x / T5x series phones.
  • Verify functionality with Linphone / MicroSIP softphones.

🔗 Specifications & Standards

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions