우당탕탕 개발일지

[RFC 3261] CHAPTER 12. Dialogs 본문

Network/SIP

[RFC 3261] CHAPTER 12. Dialogs

YUDENG 2026. 2. 1. 20:25

CHAPTER 12. Dialogs

 

Dialog는 두 UA 간에 일정 시간 동안 유지되는 peer-to-peer SIP 관계를 나타낸다.

  • 메세지 순서를 유지하고, request의 올바른 라우팅을 가능하게 하며, SIP 메세지를 해석하기 위한 context를 제공한다.
    → context는 dialog 상태 정보 (Call-ID, local / remote tag 등)

 

dialog는 각 UA에서 Call-ID, local tag, remote tag로 식별된다.

→ local/remote tag는 각각From/To 헤더의 tag 값 (UA 관점에 따라 local / remote가 달라짐)

  • UA의 local tag는 상대 UA의 remote tag와 같다.
  • → 같은 dialog에 참여하는 각 UA가 인식하는 dialog ID는 서로 다르다.
  • tag는 고유한 dialog ID를 생성하기 위한 용도로 사용되며, 단순한 식별용 문자열이기 때문에 별도의 의미를 해석하지는 않는다.

 

dialog ID는 모든 response 또는 To 필드에 tag가 있는 request와 연관되어 있다.
→ 초기 INVITE response의 To 필드에는 tag가 포함되어 있음. → To에 tag가 들어가면서 dialog로 묶임.

  • 같은 메세지라도 보는 관점이 UAC인지 UAS인지에 따라 dialog ID 계산 규칙이 달라진다.
    → dialog ID 구성 요소(local tag, remote tag)에 어떤 tag 값을 집어넣는지 달라진다.
    • UAC의 경우,
      • dialog ID의 Call-ID는 메세지의 Call-ID
      • remote tag는 메세지의 To 필드 tag (= Target)
      • local tag는 메세지의 From 필드 tag (= Me)
    • UAS의 경우,
      • dialog ID의 Call-ID는 메세지의 Call-ID
      • remote tag는 메세지의 From 필드 tag
      • local tag는 메세지의 To 필드 tag
    → 해당 규칙은 request와 response 모두 UAC/UAS 관점에 따라 동일하게 적용한다.

 

dialog는 이후 메세지 전송에 필요한 특정 상태 정보를 포함한다. 

  • dialog ID
  • (local / remote) sequence number
  • (local / remote) URI
  • remote target
  • secure의 여부
  • route set
    • 상대방에게 request를 보내기 위해 거쳐야 할 서버 목록

 

  • dialog는 provisional response(1xx)가 생성되었을 때 (101~199) early 상태로 생성될 수 있으며, final response(2xx)를 받으면, confirmed 상태로 전환이 된다.
    • 즉, 세션이 확정되기 전까지 dialog는 존재할 수 있다.
  • 이외의 response이거나 아예 response가 도착하지 않으면, early dialog는 종료된다.
<예시>

1. UAC가 INVITE를 전송하고 UAC가 응답
2. UAC가 180 Ringing response를 보냄 → 이때 dialog가 만들어짐. 하지만 아직 통화는 시작되지 않았기 때문에 Early dialog 상태
3. 나중에 UAS가 200 OK response를 보내면 → Confirmed dialog 상태

(12.1) Creation of a Dialog

해당 12절에서는 메소드와 무관한 dialog 상태 생성 과정을 설명한다. INVITE 메소드에 특화된 dialog 상세 내용은 13절에서 다룬다.
구분 Section 12 (Dialogs) Section 13 (INVITE-specific Dialogs)
주제 dialog의 일반 개념 및 생성/유지/종료 규칙 INVITE 요청으로 생성된 dialog의 특별한 처리
적용 범위 메서드 전반 (re-INVITE, SUBSCRIBE 등 확장 포함) INVITE 요청한정된 세부 절차
다루는 내용 - dialog ID 구성
- route set
- target refresh 등
- INVITE 수신 이후의 응답 처리 흐름
- ACK 처리 (확정과 예외)
- 세션 관리와 타이머 처리

 

  • dialog는 특정 request에 대해 non-failure response(단, 1xx ~ 2xx)가 생성될 때 만들어진다.
    • request가 INVITE 일 것
    • To 헤더에 tag가 포함된 2xx 또는 101~199 response 일 것
  • non-final response(1xx)로 생성된 dialog는 early 상태에 있고, 이를 early dialog라고 부른다.
    → dialog가 생성은 되었지만 아직 확정되지 않은 상태

UA는 아래 설명된 방식에 따라 dialog ID 구성 요소에 값을 할당해야 한다. (MUST)

 

 

(12.1.1) UAS behavior

UAS는 dialog를 생성하는 response(예: INVITE에 대한 2xx)를 보낼 때, 반드시 해당 request의 Record-Route 헤더 필드 값을 response에 그대로 복사해야 한다. (MUST)

  • Record-Route 헤더의 URI, URI 파라미터, UAS가 알지 못하는 파라미터까지 포함한 전체 헤더 파라미터를 포함한다.
  • 이 값들의 순서는 request와 동일하게 유지해야 한다. (MUST)

 

UAS는 반드시 reponse에 Contact 헤더 필드를 추가해야 한다. (MUST)

  • Contact 헤더 필드는 UAS가 후속 request(예: ACK)를 받을 URI를 명시한다.
    • 일반적으로, URI의 host 부분은 IP 주소나 FQDN 이다.
    • URI는 반드시 SIP / SIPS URI 형식이어야 한다. (MUST)
  • 다음 중 하나라도 SIPS URI가 있다면, response의 Contact 헤더도 반드시 SIPS URI여야 한다. (MUST)
    • Request-URI / Record-Route 헤더 최상단 / Contact 헤더
  • Contact URI는 글로벌 범위를 가지는 것이 권장된다. (SHOULD)
    • 이는 INVITE에만 국한되지 않으며, dialog 외부 메세지에서도 사용할 수 있다.

 

이후, UAS는 dialog 상태를 생성한다.

  • 이 상태는 dialog가 종료될 때까지 반드시 유지되어야 한다. (MUST)

또한, request가 TLS로 전달되었고, Request-URI가 SIPS URI를 포함하고 있는 경우, dialog의 secure flag를 TRUE로 설정해야 한다.

 

route set은 반드시 request의 Record-Route 헤더에 포함된 URI 전체 목록을 순서대로, 그리고 모든 URI 파라미터를 그대로 유지한 채로 설정해야 한다. (MUST)

  • UAS는 request에 Record-Route 헤더가 없다면, route set은 반드시 빈 리스트로 설정해야 한다. (MUST)
  • Early Dialog 상태에서 UAS는 수신한 request에 포함된 Record-Route를 매번 새 route set으로 overwrite 해야한다.
  • UAS가 2xx Response 를 전송하면 Dialog는 Confirmed 상태가 되며, 해당 시점의 route set은 최종 route set으로 확정된다.
  • Confirmed Dialog 이후에는 route set을 변경하면 안된다.

 

remote target은 반드시 request의 Contact 헤더 URI로 설정해야 한다. (MUST)

remote sequence number는 반드시 request의 CSeq 헤더에 있는 sequence number 값으로 설정해야 한다. (MUST)

  • local sequence number는 초기에 비어있어야 한다. (MUST)

 

dialog ID의 Call-ID는 request의 Call-ID로 설정해야 한다.

dialog ID의 local/remote tag는 다음과 같이 설정해야 한다. (MUST)

  • remote tag는 request의 From 헤더 tag
  • local tag는 request에 대한 response의 To 헤더 tag

 

UAS는 From 필드에 tag가 없는 request도 수신할 수 있도록 준비되어 있어야 하며, 해당 경우 tag 값은 null로 간주해야 한다. (MUST)

RFC 3261 버전에서는 tag를 기반으로 dialog를 구분하지만 RFC 2543 버전에서는 URI만으로 dialog를 구분했기에 하위 호환성을 위해서 URI를 그대로 둔다.

 

local/remote URI는 다음과 같이 설정해야 한다. (MUST)

  • remote URI는 request의 From 헤더 URI
  • local URI는 request의 To 헤더 URI

 

(12.1.2) UAC behavior

UAC는 dialog를 생성할 수 있는 request(예: INVITE)를 보낼 때, 반드시 글로벌 범위의 SIP/SIPS URI를 request의 Contact 헤더에 포함시켜 보내야 한다. (MUST)
→ Contact URI : 이후 ACK, re-INVITE, BYE를 받을 주소

→ 글로벌 범위 = outside of a dialog

  • request에 Request-URI 또는 Route 헤더 값이 SIPS URI라면, Contact 헤더도 SIPS URI로 설정해야 한다. (MUST)

 

UAC가 dialog를 생성하는 response를 받으면, dialog 상태를 구성한다.

  • 이 상태는 dialog가 종료될 때까지 유지해야 한다. (MUST)

 

request가 TLS로 전송되었고, Request-URI가 SIPS URI인 경우, dialog의 secure flag를 TRUE로 설정해야 한다.

 

route set은 반드시 response의 Record-Route 헤더에 포함된 URI 전체 목록을 역순으로, 그리고 모든 URI 파라미터를 그대로 유지한 채로 설정해야 한다. (MUST)

  • response에 Record-Route 헤더가 없다면, UAC는 route set은 반드시 빈 리스트로 설정해야 한다. (MUST)
  • Early Dialog 상태에서 UAC는 Provisional Response(1xx)에 포함된 Record-Route를 매번 새 route set으로 overwrite 해야한다.
  • 2xx Response 를 수신하면 Dialog는 Confirmed 상태가 되며, 최종 route set으로 확정된다.
  • Confirmed Dialog 이후에는 route set을 변경해서는 안된다.

 

remote target은 반드시 response의 Contact 헤더 URI로 설정해야 한다. (MUST)

local sequence number는 request의 CSeq 헤더에 있는 sequence number 값으로 설정해야 한다. (MUST)

  • remote sequence number는 초기에는 비어있어야 한다.(MUST)
  • → dialog 내부에서 UAS가 request를 보낼 때 설정됨

 

dialog ID의 Call-ID 값은 request의 Call ID와 동일해야 한다. (MUST)

dialog ID는 다음과 같이 설정되어야 한다. (MUST)

  • local tag = request의 From 헤더 tag
  • remote tag = response의 To 헤더 tag

 

UAC는 To 필드에 tag가 없는 response를 받으면, 해당 tag를 null로 간주해야 한다. (MUST)

RFC 3261 버전에서는 tag를 기반으로 dialog를 구분하지만 RFC 2543 버전에서는 URI만으로 dialog를 구분했기에 하위 호환성을 위해서 URI를 그대로 둔다.

 

local/remote URI는 다음과 같이 설정해야 한다. (MUST)

  • remote URI는 response의 To 헤더 URI
  • local URI는 response의 From 헤더 URI

(12.2) Requests within a Dialog - dialog 내부에서의 request 처리

 

두 UA 사이에서 dialog가 생성되면, 양쪽은 필요시 새로운 트랜잭션을 시작할 수 있다. (MAY)

  • request를 보내는 쪽은 UAC 역할을, 받는 쪽은 UAS 역할을 받는다.
    • dialog를 처음 생성할 때의 UA 역할과 다를 수 있다.
      → 즉, 트랜잭션 단위로 역할이 바뀐다.

 

dialog 내부에서 보내는 request도 Record-RouteContact 헤더를 포함할 수 있다. (MAY)

  • 이러한 request는 confirmed dialog가 생성될 때 정해진 route set은 변경하지 못하지만, remote target URI는 갱신할 수 있다.
    • route set을 변경하면 RFC 2543과 호환되는 시스템에 호환성 문제가 발생할 수 있다.

 

target refresh request

  • dialog의 remote target URI를 갱신할 수 있는 request를 지칭한다.
    • target refresh request가 아닌 요청은 remote target URI를 변경할 수 없다.
  • INVITE로 생성된 dialog의 경우, 현재 RFC 3261에서 정의된 유일한 target refresh request는 re-INVITE 이다. (14절 참조)
    • ACK는 target refresh request가 아니다.

 

(12.2.1) UAC Behavior

(12.2.1.1) Generating the Request

dialog 내부에서의 request는 dialog에 저장된 상태 요소를 기반으로 구성된다.

request의 To 헤더는 다음과 같이 설정해야 한다. (MUST)

  • URI는 dialog state의 remote URI로 설정
  • tag는 dialog ID의 remote tag로 설정

request의 From 헤더는 다음과 같이 설정해야 한다. (MUST)

  • URI는 dialog state의 local URI로 설정
  • tag는 dialog ID의 local tag로 설정

 

remote 또는 local tag가 null이면, 해당 To/From 헤더에서 tag 파라미터는 생략되어야 한다. (MUST)

→ dialog 생성 전인 경우, To 헤더의 tag는 생략되어야 함.

RFC 3261 버전에서는 tag를 기반으로 dialog를 구분하지만 RFC 2543 버전에서는 URI만으로 dialog를 구분했기에 하위 호환성을 위해서 URI를 그대로 둔다.

 

request의 Call-ID는 dialog의 Call-ID로 설정해야 한다. (MUST)

dialog 내 request는 반드시 CSeq 번호가 1씩 증가하면서 연속적으로 유지되어야 한다. (MUST)

  • ACK와 CANCEL은 예외로 기존 request의 CSeq 번호와 동일하다.
  • CSeq 번호가 비어있다면, (8.1.1.5 절) 가이드에 따라 초기 값을 생성해야 한다.
  • CSeq 헤더의 메소드는 request의 메소드와 일치해야 한다.

 

request의 Call-ID는 dialog의 Call-ID로 설정해야 한다. (MUST)

dialog 내 request는 반드시 CSeq 번호가 1씩 증가하면서 연속적으로 유지되어야 한다. (MUST)

  • ACK와 CANCEL은 예외로 기존 request의 CSeq 번호와 동일하다.
  • CSeq 번호가 비어있다면, (8.1.1.5 절) 가이드에 따라 초기 값을 생성해야 한다.
  • CSeq 헤더의 메소드는 request의 메소드와 일치해야 한다.

 

UAC는 remote target과 route set을 사용해 request의 Request-URI와 Route 헤더를 구성한다.

1 ) route set이 비어있다면,

  • Request-URI를 remote target URI으로 설정 (MUST)
  • Route 헤더를 추가하면 안된다. (MUST NOT)

2 ) route set의 첫 번째 URI가 lr 파라미터를 포함하고 있다면,

  • Request-URI를 remote target URI 으로 설정 (MUST)
  • Route 헤더에 피라미터를 포함한 route set의 모든 값을 순서대로 추가 (MUST)

3 ) route set의 첫 번째 URI에 lr 파라미터가 없다면, → strict routing

  • Request-URI를 route set의 첫 번째 URI로 설정
    • 단, Request-URI에서 쓸 수 없는 파라미터는 제거하고 사용
  • Route 헤더에 route set의 값을 순서대로 추가하고, remote target URI를 마지막에 추가한다.

 

예시 ) remote target: sip:user@remoteua

<sip:proxy1>,<sip:proxy2>,<sip:proxy3;lr>,<sip:proxy4>
 METHOD sip:proxy1
 Route: <sip:proxy2>,<sip:proxy3;lr>,<sip:proxy4>,<sip:user@remoteua>
  • 첫 번째 URI는 lr 파라미터가 없음 즉, strict routing이므로 Request-URI를 첫 번째 URI로 설정한다.
  • remote target은 Route헤더의 마지막에 추가한다.
  • strict router(= proxy1)가 메세지를 받았을 때, Request-URI를 자신의 주소로 바꾸는데, 이때 Route 헤더의 마지막 값을 다시 Request-URI로 반환하여 보존할 수 있다.

 

target refresh

  • dialog의 remote target URI를 갱신할 수 있는 request를 지칭한다.
    • target refresh request가 아닌 요청은 remote target URI를 변경할 수 없다.

dialog에서 target refresh request(예: re-INVITE)의 경우, UAC는 Contact 헤더를 포함해야 한다. (SHOULD)

  • 또한, 변경이 없더라도 이전 request와 동일한 URI를 사용해야 한다. (SHOULD)
  • secure flag가 TRUE인 경우, Contact URI는 반드시 SIPS URI여야 한다. (MUST)

 

나머지 request 구성 방식은 (8.1.1절 - request 생성)을 따른다.

  • request를 구성하면, 전송 보낼 서버의 주소를 계산하고 (8.1.2절 - dialog 외부에서의 request) 방식으로 request를 전송한다.
더보기

8.1.2절 - outside of a dialog request

목적지 결정 방법
- route set의 첫 URI가 strict routing인 경우,목적지는 Request-URI로 설정해야 한다. (MUST)
- strict routing이 아닌 경우,
    - Route 헤더가 있는 경우, Route의 첫 번째 URI를 목적지로 사용한다.
    - Route 헤더가 없는 경우, Request-URI를 목적지로 사용한다.

 

(12.2.1.2) Processing the Responses

UAC는 response를 Transaction Layer로부터 수신한다.

  • Transaction Layer가 timeout을 반환하면, UAC는 408(Request Timeout) response로 간주하고 처리해야 한다.
  • → TU는 성공/실패 response를 받아야 로직을 계속 수행할 수 있기에, 408로 명확히 실패 처리

 

dialog에서 3xx resopnse를 받았다면, UAC는 out-dialog request에서 3xx response를 받은 경우와 동일하게 처리 한다. (8.1.3.4절 참고)

→ outside of a dialog REGISTER 종류 - REGISTER, 초기 INVITE

  • 단, UAC가 대체 URI로 시도하더라도, request의 Route 헤더는 기존 dialog의 route set을 기반으로 구성해야 한다.
    → 초기 프록시 경로를 유지하며 redirect만 수행하기 위한 메커니즘

 

UAC가 target refresh request에 대해 2xx response를 수신한 경우,

→ 여기서 target refresh request = re-INVITE, UPDATE

  • response에 Contact 헤더가 존재한다면, 반드시 dialog의 remote target URI를 해당 Contact URI로 교체해야 한다. (MUST)

 

dialog에서 request에 대해 481(Call/Transaction Does Not Exist) 또는 408(Request Timeout) response를 받았다면, UAC는 dialog를 종료하는 것이 바람직하다. (SHOULD)

UAC가 아무런 response도 받지 못한 경우에도, dialog를 종료해야 한다. (SHOULD)

  • 해당 경우, Client Transaction가 TU에게 timeout임을 알려준다.
INVITE로 시작된 dialog는 BYE request를 통해 종료한다.
더보기

8.2절 - outside of a dialog UAS Behavior

처리 단계
- 시작: 인증(Authentication)
- 다음: 메서드 검사(Method validation)
- 이후: 헤더 필드 확인(Header checks)
- 기타: Require/Supported 검사, URI 검증, 응답 전송 등

 

(12.2.2) UAS Behavior

dialog 내부에서의 request는 다른 request와 마찬가지로 원자적(automic)이다.

  • UAS가 request를 수락하면, 해당 request와 관련된 모든 상태 변경이 수행되야 하고,
  • UAS가 request를 거부하면, 어떠한 상태 변경도 수행되서는 안된다.

주의사항

INVITE와 같이 일부 request는 동시에 여러 상태에 영향을 준다는 점에 유의해야 한다.

→ INVITE: dialog 생성 & 세션 구성 & route set 생성 & remote target 설정 등

 

UAS는 request를 Transaction Layer 로부터 수신한다.

  • request의 To 헤더에 tag가 있다면, UAS core는 해당 request의 dialog ID를 계산하여 현재 존재하는 dialog들과 비교한다.
    → dialog ID = Call-ID + local tag + remote tag
    • 일치하는 dialog ID가 있다면, mid-dialog request로 간주된다. 이 경우, UAS는 우선 (8.2절) 방식으로 처리한다.
      → mid-dialog = BYE, re-INVITE 등
    • 일치하는 dialog ID가 없다면, UAS가 crash 후 재시작된 상황일 수도 있고, 다른 UAS의 request가 잘못 전달된 것일 수 있고, 단순히 라우팅 오류로 잘못 전달된 request 일 수도 있다.

※ crash

UAS가 HW, OS 등 문제로 인해 갑작스럽게 종료되거나 재시작되는 상황

 

UAS는 To tag를 기준으로 request를 수락하거나 거부할 수 있다. (MAY)

유효한 To tag를 수용하면, crash가 발생하더라도 dialog를 지속할 수 있는 복원력을 제공한다.

  • 복원 기능을 지원하고자 하는 UA는
    • 재부팅 이후에도 CSeq 값을 단조 증가시켜야 한다.
    • route set을 재구성할 수 있어야 한다.
    • 벗어난 RTP timestamp(RFC 3350)와 sequence number도 허용해야 한다.
  • dialog를 복원하지 않기를 원하는 UAS는
    • 반드시 481(Call/Transaction Does Not Exist) response를 전송하고, 해당 response를 Server Transaction에 전달해야 한다. (MUST)

 

 UAS Crash 후 재시작 ]
          ↓
[ Request 수신 (To tag 존재) ]
          ↓
[ To tag 파싱 → UAS_ID, SESSION_ID, TIMESTAMP 추출 ]
          ↓
 ┌────────────────────────────────────────────┐
 │  내가 이전에 생성한 dialog에 속하는 tag인가?       │
 └────────────────────────────────────────────┘
           │                             │
          Yes                            No
           ↓                             ↓
[ 세션 복구 시도:                      [ 481 (Call/Transaction Does Not Exist) ]
  - route set 재생성
  - CSeq 검사
  - RTP 시퀀스/타임스탬프 허용 ]
           ↓
   [ mid-dialog 요청 수용 ]

 

 

dialog 상태를 변경하지 않는 request(예: OPTIONS)는 dialog 내부에서 수신될 수 있다.

  • 해당 request들은 외부 dialog에서 수신한 request 방식으로 처리된다.

 

remote sequence number가 비어있다면, request의 CSeq number로 설정된다. (MUST)

remote sequence number가 비어있지 않다면, request의 CSeq number가 remote sequence number보다 (MUST)

  • 낮으면 500(Internal Server Error) response → 순서 오류
  • 높으면 remote CSeq를 갱신 → 정상
    • CSeq 값이 1보다 큰 간격으로 증가하는 것은 오류가 아니기 때문에 UAS는 이를 허용해야 한다.

 

UAS가 target refresh request를 수신했을 때, request에 Contact 헤더가 있을 경우,

  • dialog의 remote target URI를 반드시 해당 URI로 교체해야 한다. (MUST)

 

(12.3) Termination of a Dialog

어떤 메소드든 dialog 외부에서 보낸 request가 non-2xx fianl response를 수신하면, provisional response(1xx)를 통해 생성된 early dialog는 종료된다.

 

confirmed dialog를 종료하는 방식은 사용한 메소드에 따라 달라진다.

  • RFC 3261에서는 BYE 메소드가 세션과 그에 연관된 dialog를 종료한다.
728x90