요약

  • RFC 3261은 SIP 다이얼로그를 Call-ID, 로컬 태그, 리모트 태그로 식별했습니다. 각 단말은 자신의 기여를 로컬로 보기 때문에 태그의 역할은 피어 쪽에서 뒤바뀝니다.
  • 포크된 INVITE 하나가 여러 개의 조기 또는 확정 다이얼로그를 만들 수 있었습니다. 이들은 발신자의 Call-ID와 태그를 공유하면서, 각 응답자가 서로 다른 To 태그를 제공해 서로 다른 다이얼로그 이름을 완성했습니다.
  • 다이얼로그는 이후 트랜잭션에 걸쳐 시퀀스, 경로, 대상 상태를 운반했습니다. 식별자는 맥락을 상관시켰지만, 사람을 인증하거나 미디어 스트림을 식별하거나, 인간의 한 번의 “통화”가 반드시 하나의 다이얼로그라는 보장을 하지는 않았습니다.

하나의 초대가 여러 관계로 돌아왔다

인터넷 전화는 단수처럼 들리는 단어 하나를 물려받았습니다:call(통화). 발신자는 한 주소를 고르고, 하나의 초대를 보내고, 한 번의 대화를 기대했습니다. 그러나 그 아래 네트워크는 이미 훨씬 덜 단정했습니다. 프록시는 그 INVITE를 데스크 전화기, 소프트 클라이언트, 게이트웨이에 동시에 보낼 수 있었습니다. 하나 이상의 목적지가 벨이 울릴 수 있었습니다. 하나 이상이 응답할 수 있었습니다. 발신 측 사용자 에이전트는 이후의 ACK, 업데이트, BYE가 어느 응답 피어에 속하는지 알아야 했습니다.

트랜잭션 식별자가 그 부담을 질 수는 없었습니다. 최초의 INVITE 트랜잭션의 임무는 해당 교환이 진행되는 동안 한 요청과 그 재전송, 응답을 상관시키는 것이었습니다. 성공적인 응답은 더 긴 문제를 열었습니다. 새 요청은 새 트랜잭션을 시작했습니다. 어느 단말이든 발신자가 될 수 있었습니다. 설정 과정에서 학습한 경로가 경로에 남아 있어야 할 수도 있었습니다. 관계가 계속되는 동안 장치는 새 연락 주소를 알릴 수 있었습니다.

따라서 SIP는 하나의 메시지 교환이 아니라 기억되는 맥락에 대한 이름을 필요로 했습니다.

최초의 표준 트랙 버전인 1999년 3월의RFC 2543은 이 지속 관계를call leg(통화 레그)라고 불렀습니다. 레그는 Call-ID, To, From으로 식별했습니다. RFC 2543은 이미 포크 문제를 이해하고 있었습니다. 요청이 여러 사용자 에이전트 서버에 도달할 수 있을 때, 각 응답에는 To 태그가 필요했고 발신자는 그것으로 응답자들을 구분할 수 있었습니다. 따라서 하나의 INVITE에 대한 여러 응답은 서로 다른 call leg를 나타낼 수 있었습니다.

그러나 그 구성은 여전히 주소 필드에 역사를 담고 있었습니다. From 태그는 선택 사항이었습니다. 경로 구성은 충분히 규정되어 있지 않았습니다. “call”과 “call leg”라는 용어는 프로토콜 상태 기계 대신 애플리케이션 이야기를 세우도록 부추겼습니다. 3년 뒤 SIP 2.0은 이 경계를 훨씬 더 날카롭게 만들었습니다.

발신자는 이름의 절반만 제공했다

2002년 6월에 공표된RFC 3261은 call leg를 다이얼로그로 대체했습니다. 그 정의는 의도적으로 절제되어 있었습니다: 일정 시간 지속되는, 두 사용자 에이전트 사이의 피어 투 피어 SIP 관계. 다이얼로그는 메시지에 해석적 맥락을 부여하고, 각 방향으로 요청을 순서화하며, 피어 사이의 새 요청을 경로 지정하는 데 필요한 정보를 공급했습니다.

어느 쪽 사용자 에이전트에서 보든 다이얼로그 식별자는 세 구성요소를 담았습니다: Call-ID, 로컬 태그, 리모트 태그. 식별자는 방향성을 지녔습니다. 앨리스의 로컬 태그는 밥의 리모트 태그였고, 밥의 로컬 태그는 앨리스의 리모트 태그였습니다. 두 단말은 “로컬”과 “리모트”가 전 세계적으로 고정된 라벨이라고 가장하지 않으면서 두 불투명 값을 합의했습니다.

다이얼로그를 형성하는 최초 요청은 Call-ID와 From 태그를 담았습니다. RFC 3261은 이를 다이얼로그 식별자의 절반이라고 기술했습니다. 자격을 갖춘 응답이 To 태그를 추가했습니다. 발신 사용자 에이전트에게 From 태그는 로컬 태그가 되었고 응답의 To 태그는 리모트 태그가 되었습니다. 응답자 입장에서는 방향이 반대가 되었습니다.

이 역할 분담이 포크에 대한 해답이었습니다. 초대의 모든 브랜치는 발신자의 Call-ID와 From 태그를 물려받았습니다. 각 응답 단말은 자신의 To 태그를 기여했습니다. 발신자는 같은 Call-ID와 자신의 태그를 담은 여러 응답을 받으면서도, 리모트 태그가 다르기 때문에 각각의 상태를 분리해 둘 수 있었습니다.

따라서 Call-ID만으로는 의도적으로 부족했습니다. 관련된 시그널링을 묶으면서도, 모든 응답자를 하나의 피어 관계로 뭉개지는 않았습니다. 태그도 인간의 이름이 아니었습니다. RFC 3261은 생성된 태그가 전역적으로 고유하고 최소 32비트의 난수성을 지닌 암호학적으로 무작위일 것을 요구했지만, 그것을 고유한 다이얼로그 식별자를 만드는 불투명 토큰으로 기술했습니다. 무작위성은 우연한 모호성을 줄였습니다. 앨리스를 인증하거나 밥을 인가하거나 어느 표시 이름이 실제 인물을 대표한다는 것을 증명하지는 않았습니다.

벨이 울리는 동안에도 이미 이름이 있을 수 있었다

다이얼로그가 항상 최종 응답을 기다리지는 않았습니다. INVITE에 대해 To 태그를 담은 101~199의 임시 응답은조기 다이얼로그를 만들었습니다. 이제 사용자 에이전트는 초대가 아직 결론 나지 않은 동안 그 특정 응답자와 관련된 상태를 유지할 수 있었습니다. 2xx 최종 응답은 일치하는 다이얼로그를 확정 상태로 옮겼습니다. 실패 응답, 또는 그 경로에서 성공 응답이 오지 않는 경우에는 핵심 규칙에 따라 조기 다이얼로그가 끝났습니다.

포크는 이것을 단순한 용어 이상으로 만들었습니다. 발신자는 여러 조기 다이얼로그를 동시에 가질 수 있었습니다: 한 단말은 벨이 울리고, 다른 하나는 진행 상황을 알리며, 셋째는 이미 초대를 거절하고 있을 수도 있었습니다. 이 다이얼로그들은 식별자의 발신 절반을 공유했지만 응답자 태그는 서로 달랐습니다. 2xx가 두 개 이상 도착할 수도 있었고, 사용자 에이전트는 여러 확정 다이얼로그를 ACK하고 애플리케이션이 선택한 결과에 따라 해소해야 했습니다.

이 메커니즘은 신뢰성 있는 임시 응답과 나란히 있지만 그와 같지는 않습니다. PRACK과 그 RSeq/RAck 시퀀스는 중요한 임시 응답이 순서대로 수신되었는지를 답합니다. 다이얼로그 태그는 그 응답과 이후 요청이 어느 피어 맥락에 속하는지를 답합니다. 신뢰성은 조기 다이얼로그 내부에서 작동할 수 있는데, 다이얼로그가 이미 이름을 지녔기 때문입니다. 그 이름 자체를 만들지는 않습니다.

같은 구분이 Via branch에도 적용됩니다. branch 값은 트랜잭션 작업을 식별하고 재전송 매칭을 지원합니다. 다이얼로그 튜플은 그 branch의 트랜잭션이 완료된 뒤에도 남아 새 트랜잭션에 걸쳐 나타납니다. 하나를 다른 것으로 취급하면 구현은 장기 상태를 너무 일찍 잊거나, 별개의 메시지 교환을 하나의 트랜잭션으로 합쳐 버리게 됩니다.

이름은 두 헤더 필드 이상을 지켰다

일단 만들어지면 다이얼로그는 이후 요청을 구성하고 해석하는 데 필요한 정보를 저장했습니다. RFC 3261은 식별자, 로컬·리모트 시퀀스 번호, 로컬·리모트 URI, 리모트 타겟, secure 플래그, 순서화된 route set을 나열했습니다.

시퀀스 번호는 각 방향에 자체 순서를 부여했습니다. 사용자 에이전트는 다이얼로그 내 새 요청을 생성할 때 자체 CSeq를 증가시켰으며, 메서드별 예외가 적용되었습니다. 피어는 리모트 값을 기억하고 더 낮은 순서 뒤바뀐 요청을 거절할 수 있었습니다. 간격이 곧 오류는 아니었습니다. 중개자가 최종 수신자에게까지 도달하지 못한 이전 시도에 도전(challenge)을 보냈을 수 있었습니다. 목적은 순서화된 증거였지 모든 정수가 나타난다는 약속이 아니었습니다.

route set은 어느 프록시가 시그널링 경로에 남기를 요청했는지를 답했습니다. 사용자 에이전트 서버는 요청의 Record-Route 값에서 이를 학습했습니다. 클라이언트는 응답에서 같은 경로를 역순으로 학습했습니다.RFC 3665는 이 규칙들을 실제 호출 흐름으로 옮겼습니다: 같은 Call-ID와 두 태그가 ACK, BYE, 응답 전반에 반복 등장하고, Route 헤더가 이후 요청에 선택된 프록시들을 옮깁니다.

리모트 타겟은 다른 질문에 답했습니다: 현재 어느 연락 주소가 피어를 대표하는가. 이는 다이얼로그 생성 때 공급된 Contact URI에서 시작했습니다. 성공적인 타겟 갱신 요청은 이를 바꿀 수 있었습니다. INVITE가 만든 다이얼로그의 경우 RFC 3261은 re-INVITE를 핵심 타겟 갱신 메서드로 정의했고, 확장은 다른 다이얼로그 유형에 대해 다른 메서드를 정의할 수 있었습니다.

이 구분은 중요했습니다. 장치는 새 다이얼로그 신원을 얻지 않고도 도달 가능한 연락처를 옮길 수 있었습니다. 리모트 타겟은 바뀌었지만 Call-ID와 태그는 바뀌지 않았습니다. route set도 고정되어 있었습니다. 새 Contact는 중개자들이 확립한 Record-Route 경로를 지울 권한이 아니었습니다.

따라서 이 세 조각은 서로 다른 세 가지 운영 질문에 답했습니다. 다이얼로그 튜플은어느 지속 맥락인지 말했습니다. route set은어느 보유된 중개자를 경유하는지 말했습니다. 리모트 타겟은현재 어느 피어 주소를 향해가는지 말했습니다. 이들의 공존은 이동성, 경로 정책, 신원 상관이 하나의 편리하지만 과부하된 문자열로 압축되는 일을 막았습니다.

다이얼로그는 미디어가 되지 않으면서 새 트랜잭션을 수용할 수 있었다

확립 후 어느 피어든 다이얼로그 안에서 새 트랜잭션을 시작할 수 있었습니다. 그 트랜잭션에서 발신자는 UAC, 수신자는 UAS였으며, 최초 INVITE 때 어느 역할을 지녔는지와 무관했습니다. 지속 관계는 한 교환의 클라이언트/서버 역할보다 오래 살 만큼 충분히 대칭적이었습니다.

미디어 협상은 다른 계층을 차지했습니다.RFC 3264는 SDP 오퍼/앤서를 스트림, 코덱, 주소, 포트를 합의하는 방법으로 정의했습니다. RFC 3264는 연속 교환을 연관시키기 위해 SIP 같은 상위 계층 맥락을 가정했습니다. 다이얼로그가 지속되는 동안 이후 오퍼는 스트림을 추가하거나, 하나를 제거하거나, 포트를 바꾸거나 다른 형식을 선택할 수 있었습니다.

따라서 확정된 SIP 다이얼로그는 오디오 패킷이 청취자에게 도달했다는 증명이 아니었습니다. RTP 소스를 지명하거나, 코덱 결과를 인증하거나, 통화 품질을 측정하지 않았습니다. 시그널링 맥락을 조직했을 뿐입니다. 미디어 세션은 그 맥락 안에서 바뀔 수 있었고, 미디어 전달의 증거는 미디어 플레인에서 와야 했습니다.

수명에도 자체 규칙이 필요했습니다.RFC 4028은 협상된 세션 타이머와 주기적 re-INVITE 또는 UPDATE 갱신을 추가했습니다. RFC 4028은 하나의 INVITE가 만든 서로 다른 다이얼로그에서 간격이 다르거나 타이머가 없을 수도 있음을 명시적으로 허용했습니다. 갱신은 기존 맥락 안의 새 트랜잭션이었습니다. 성공하면 세션이 연장되었고, 갱신 실패는 BYE로 이어질 수 있었습니다. 다이얼로그 튜플을 보유하는 것이 리모트 상태에 대한 영구 임대는 아니었습니다.

하나의 다이얼로그가 항상 하나의 애플리케이션 관계는 아니었다

확장은 마지막 모호성을 드러냈습니다. INVITE는 invite usage를 만들지만, 다이얼로그 내 SUBSCRIBE나 REFER는 같은 다이얼로그를 공유하는 추가 usages를 만들 수 있었습니다.RFC 5057은 이 결과 복잡성을 정리했습니다. 이 usages는 Call-ID, 태그, 시퀀스 상태, route set, 연락처, 리모트 타겟, secure 플래그를 공유하면서, 구독 기간 같은 usage별 상태는 유지했습니다.

따라서 한 usage의 정상 종료가 나머지를 지우지 않았습니다. BYE는 이벤트 구독이 남아 있는 동안 invite usage를 끝낼 수 있었습니다. 반대로 구독을 끝내는 것이 invite usage를 종료하지는 않았습니다. 공유 다이얼로그는 시그널링 컨테이너였지, 그 안의 모든 애플리케이션 관계가 하나의 수명을 지닌다는 주장이 아니었습니다.

RFC 6665는 이벤트 알림에 대해 이 경계를 구체적으로 만들었습니다. SUBSCRIBE와 NOTIFY는 다이얼로그 상태를 사용하지만, Event 필드가 특정 구독의 매칭에 참여합니다. 포크된 SUBSCRIBE는 각각 별도로 갱신되는 독립 다이얼로그를 확립할 수 있습니다. Call-ID/태그 튜플은 단말에 자신이 어느 공통 다이얼로그 맥락에 있는지를 알려 주지만, 그 맥락의 모든 사용에 대한 완전한 키는 아닙니다.

겉보기에 단순한 세 부분의 이름이 왜 중요했는지가 바로 여기에 있습니다. 트랜잭션이 시작되고 끝나고, 연락처가 옮겨지고, 경로가 남아 있고, 미디어가 바뀌고, 애플리케이션이 그 위에 더 많은 상태를 쌓는 동안 SIP가 피어 관계를 안정적으로 유지할 수 있게 한 것은 이 이름이었습니다. 그 강점은 모든 것을 식별한다고 주장하는 데서 온 것이 아니라, 시스템의 정확히 한 계층만을 식별하는 데서 왔습니다.