(SIP) Transport

Network 2020. 3. 18. 15:49 Posted by Vispera

Network Transport Layer를 통해 실제 요청과 응답의 전송을 담당한다.

TCP와 같은 연결 지향형의 관점에서 요청과 응답을 위해 어떤 연결을 사용할 것인지 결정한다.

Transport layer는 지속적인 연결을 관리하는 역할을 한다. (TCP, SCTP, TLS)

 

Client와 Server가 서로 Transport function들을 공유하기 위해 (같은) 연결들을 생성한다.

이 연결들은 종단의 주소, 포트, 프로토콜로 구성된 튜플로 구분된다. (인덱싱 된다.)

 

어떤 연결이 Transport layer에 의해 생성되면(열리면), 

인덱스는 목적지 IP 주소, 포트 #, 프로토콜로 정해진다.

 

어떤 연결이 Transport layer에 의해 승인되면, 

이 인덱스는 발신 IP 주소, 포트 #, 프로토콜로 정해진다.

이 포트 #는 종종 수명이 짧다. (일시적이다.)

-> 이 연결은 종종 재사용되지 않는다.

 

연결은 최종 메시지를 보냈거나 받고 난 후 일정 시간 동안 유지하는 것을 권장한다.

이 지속 시간은 적어도 [ UA가 필요한 동작을 위해 사용한 가장 오래 걸리는 시간(64 * T1) ]과 같아야 한다.

Transaction을 시작과 종료 상태로 진행하기 위한 것이다.

이렇게 되면 모든 연결들이 Transaction들을 잘 완성할 수 있도록 한다.

 

하지만, Timer C와 같이 매우 큰 값을 사용하는 TU를 가진 UA가 있다면, 이 지속 시간은 매우 커질 것이다.

UA를 위한 TCP 의무화는 실질적인 변화이다. -> 더 큰 메시지를 다루기 위해서이다.

 

1. Clients

1) 요청 보내기

Client의 Transport layer에서는 요청을 보내고 응답을 받는 역할을 한다.

 

요청의 path MTU가

200 bytes 미만 이거나 1300 bytes 초과, 또는 path MTU가 미정이면

네트워크 혼잡 제어를 위해 Transport Protocol은 TCP(Reliable Transport)로 결정된다.

* path MTU : 경로마다 달라지는 최소 MTU, 고정된 값 X

* MTU : 한 번에 보낼 수 있는 최대 패킷 크기(byte)

메시지의 Top Via Header의 Transport Protocol을 바꾼다. (UDP -> TCP)

이 변경은 UDP를 통해 전송되는 메시지의 단편화를 방지하고, 

크기가 큰 메시지들을 위한 네트워크 트래픽 제어를 수월하게 한다.

하지만, 최대 Datagram 패킷 크기까지의 메시지만 처리 가능해야 한다.

UDP일 경우, 65,536 bytes이다. (IP와 UDP Header 모두 포함한 전체 크기)

 

* 200 byte를 가진 버퍼

메시지 크기와 MTU 사이에 존재

SIP 응답은 요청보다 크기가 클 수 있다는 사실에 부응하고 있다.

-> Record-Route Header를 INVITE 응답에 추가하게 되면 발생

 

만약 UA가  이러한 메시지 크기 제약 때문에 TCP 또는 UDP를 통해 요청을 보냈을 때, 

연결을 설립하려는 시도로 지원되지 않는 ICMP Protocol을 생성하거나 TCP가 초기화 된다면, 

UDP를 통해 요청을 재전송해야 한다.

이것은 단지 TCP를 지원하지 않는 Compliant implementation으로서

하위 호환성(Backwards compatibility)을 지원할 뿐이다.

 

* Multicast

Client가 요청을 Multicast로 보내려고 할 때, 

"maddr" parameter를 Via Header에 추가해야 한다. -> 목적지의 Multicast 주소를 포함해야 한다.

그리고 IPv4를 위해 TTL 값을 1로하여 Header에 추가해야 한다.

IPv6 Multicast에 대해서는 정해져 있지 않다.

 

이 규칙들은 SIP Multicast의 의도적으로 제한하도록 한다.

-> 주요 함수들이 "single-hop-discovery-like" 서비스를 제공하기 때문이다.

동일한 서버들의 그룹으로 요청을 보내면, 

이 서버들 중 하나가 응답을 처리하도록 되어 있다. -> 여러 홉에 연결되어 있는 모든 서버들이 응답하지 않는다.

이 동작 방법은 Register에서 가장 유용하다.

 

그래서 사실상, Client Transaction 은 첫 번째 응답을 받아 처리하고, 

재전송과 같은 다른 응답들은 지켜본다. -> 모두 같은 Via Branch ID를 가지고 있기 때문이다.

 

Multicast를 위해 Client Transport는 요청을 보낸 같은 Multicast group과 포트에서 응답들을 받을 준비를 해야 한다.

 

* "sent-by" value

이 field는 특정 환경에서 응답을 보내기 위해 사용되어 진다. (Server Transport에서 다룸)

요청이 보내지기 전에 Client Transport는 Via Header field에 반드시 "sent-by" field 값을 추가해야 한다.

[ IP 주소 + 포트 번호 ] -> IP 주소는 FQDN을 권장한다.

ex) james@uangel.com:5067

    proxy1@uangel.com:5060

 

포트 번호가 없으면 Default 포트 번호를 사용한다.

- UDP, TCP, SCTP : 5060

- TLS : 5061

 

* Reliable Transport에서 응답은 보통 요청을 받은 연결로 보내진다.

그래서 Client Transport는 요청을 보낼 때 사용되어진 연결로 응답을 받을 준비를 하고 있어야 한다.

 

에러가 발생할 수 있는 상황은 Server가 응답을 보내기 위해 새로운 연결을 생성할 때이다.

이 상황을 처리하기 위해서 Transport layer는 "sent-by" field에 요청을 보낸 소스 IP 주소와 포트 번호를 가진 incoming connection을 받을 준비를 해야 한다.

또한, Client는 Server가 정한 주소와 포트를 가진 incoming connection을 받을 준비를 해야 한다.

 

* Unreliable Transport에서 Client Transport는 Via의 

"sent-by" field에 요청을 보낸 소스 IP 주소와 포트 번호를 가진 응답들을 받을 준비를 하고 있어야 한다.

게다가 Reliable Transport와 마찬가지로, 특정 상황에서 응답은 어디로든 보내질 것이다.

그렇다면 Client는 서버가 정한 주소와 포트를 가진 incoming connection을 받을 준비를 해야 한다.

 

만약 요청이 현재 열려 있는 연결에 IP 주소와 포트 번호, 프로토콜로 정해진 채로 보내진다면, 

이 연결은 요청을 보내도록 사용되어지는 것을 권장한다.

하지만 다른 연결들은 이에 상관 없이 계속 열려있거나 사용된다.

 

만약 요청이 Multicast를 사용해서 보내진다면, 

group 주소, 포트 #, TTL(Transport user가 제공하는)로 정해져서 보내진다.

 

만약 요청이 Unreliable Transport를 사용한 Unicast로 보내질 때, 

IP 주소, 포트 번호(Transport user가 제공하는)로 정해져서 보내진다.

 

2) 응답 받기

응답을 받으면 Client Transport는 최상위 Via Header Field 값을 확인한다.

"sent-by" value가 Client Transport가 요청에 추가한 값과 다르면 이 응답을 조용히(?) 버린다.

Client Transport는 Matching Procedure를 수행해서 현재 수행 중인 Transaction에 맞는 응답을 찾아 준다.

그래서 해당 Transaction으로 응답을 보낸다.

못찾으면 곧바로 Core(TU)로 전달되고 해당 응답은 Core에서 처리 된다.

-> 이 응답들을 Stray response라고 한다.

 

2. Servers

1) 요청 받기

Server와 통신할 목적으로 만들어진 SIP 또는 SIPS URI를 동시에 나눠 가진 

DNS lookup의 결과로 조합된 IP 주소, 포트, Transport를 가진 요청을 받을 준비가 되어 있어야 한다.

 

* 동시에 나눠 가진다. (Handing out)

- REGISTER Request에 있는 Contact Header Field

- Redirect 응답

- 요청 또는 응답에 있는 Record-Route Field

에 URI를 넣는 것을 말한다.

 

* Public interface에서 SIP Port의 default는

- TCP, UDP : 5060

- TLS : 5061

 

* UDP를 위해 Server가 listen하고 있는 어떤 포트와 interface든

TCP를 위해 항상 같은 포트와 interface에서 listen 해야 한다.

이유 : 메시지 크기가 매우 크면 UDP 보다는 TCP로 보내야 하기 때문이다.

<- UDP는 메시지 크기 제한 있음(65,536 bytes)

 

Server는 UDP를 위해 특정 주소나 포트에서 listen할 필요가 없다.

TCP를 위해 요청을 받은 같은 주소와 포트에 listen하고 있기 때문이다.

 

Server Transport가 어떤 Transport에서 요청을 받을 때,  최상위 Via Field Value를 확인하다.

"sent-by" value가 

- Host 부분이 domain name을 포함하거나 

- IP 주소(패킷 소스 주소와는 다른)를 포함할 때 

Server는 Via Header Field에 "received" 를 반드시 추가해야 한다.

이 Parameter는 패킷을 받았던 소스 주소를 반드시 포함해야 하고, 

Server Transport layer가 응답을 보내는 것을 도와줄 수 있다.

Server Transport layer는 요청이 왔던 소스 IP 주소로 응답을 보내야 한다.

ex)

INVITE sip:bob@Biloxi.com SIP/2.0

Via: SIP/2.0/UDP bobspc.biloxi.com:5060;received=192.0.2.4

-> 192.0.2.4 : 패킷을 받은 IP 주소 -> Server IP 주소

 

* Server Transport는 수신한 요청을 어떤 Server Transaction으로 보내야하는지 Transaction과 요청의 매칭을 시도한다. (by Branch Parameter)

Server Transaction을 발견하면 메시지 처리를 위해 해당 Transaction으로 전달한다.

발견 못하면 Core로 보내서 해당 요청에 대한 새로운 Server Transaction을 생성하도록 한다.

 

UAS Core가 INVITE 메시지에 대한 2xx 응답을 보낼 때, Server Transaction은 소멸된다. ("Terminated" state로 전이)

-> ACK가 Server Transport로 오면 Transaction instance가 없어서

ACK가 UAS Core로 바로 들어온다는 의미이다.

 

2) 응답 보내기

Server Transport는 응답을 어디로 보낼지 결정하기 위해서 최상위 Via Header Field를 이용한다.

아래의 4가지 규칙에 따라 동작한다.

1] 만약 UAC의 Transport Protocol이 Reliable Transport(TCP, SCTP, TLS)이면, 

  응답은 현재 유지되고 있는 연결을 통해 Transaction을 만든 (원본) 요청을 보낸 곳으로 전달된다.

  이렇게 하기 위해서는 Server Transaction과 Transport 연결이 계속해서 유지되어야 한다.

  이 연결이 더 이상 열려있지 않으면, 서버는 "received" parameter에 있는 IP 주소와 포트 번호를 바탕으로

  연결을 다시 열어야 한다. (포트 번호 명시 안되어 있으면 default port #로 연결)

  이 연결이 실패하면, 서버는 RFC 3263 에서 설명하는 과정에 따라 응답을 보내고, 

  연결을 생성하기 위해 IP 주소와 포트를 결정한다.

2) maddr parameter가 Via Header Field Value에 포함되어 있다면, 

  응답은 해당 포트(없다면 default port)와 리스트에 주어진 주소로 포워딩 되어야 한다.

  주소가 Multicast 주소이면, 응답은 "ttl" parameter에 명시된 TTL을 이용해서 보내져야 한다. (없으면 1)

3) Unreliable Unicast Transport이면, 

  최상위 Via Header에 "received" parameter가 있으면, 응답은 명시된 주소와 포트로 전달된다.

  실패하면 ICMP 메시지로 "port unreachable" 응답을 보낸다.

4) "received" parameter가 없으면, 응답을 "sent-by" value에 명시된 주소로 보내야 한다.

 

# Framing

1) Message-oriented Transport(UDP)

Content-Length Header Field가 있으면, 

메시지 바디는 이 field value 값만큼의 byte만 수용 가능하다.

-> 바디 뒤에 추가적인 byte가 붙는다면 무조건 버려진다.

-> 만약 Transport 패킷이 메시지 바디의 끝 전에 끝난다면 error로 여겨진다.

-->> Content-Length에 의해 제한되므로 메시지 원본이 전송 안된다!

이 메시지가 응답이면 버려지고, 요청이면 400 Bad Request 응답을 발행해야 한다.

Content-Length Header가 없으면 메시지 바디는 Transport 패킷의 끝에서 끝난다고 보면 된다. -> 바디 없음을 의미

 

2) Stream-oriented Transport(TCP)

Content-Length Header Field는 바디 크기를 말하고,  Stream-oriented Transport와 함께 사용되어야 한다.

-> ??? 규격 설명인데 이해 불가

 

'Network' 카테고리의 다른 글

(SIP) Transaction Timer 정리  (0) 2020.03.19
(SIP) Transaction State Machine 요약  (0) 2020.03.19
(SIP) Timer C  (0) 2020.03.18
(SIP) Server Transaction  (0) 2020.03.17
(SIP) Client Transaction의 응답 매칭 방법  (0) 2020.03.17