2019年3月30日 星期六

hotplug2

hotplug2 是輕巧版的 udev,在 OpenWrt 已經由 procd 取代。

程式 /sbin/hotplug2 會常駐,連結到 netlink socket 讀取 uevent,變數拿來跟每個規則比對,符合的就執行對應的指令。

規則比對有 "==" 及 "!=" 檢查字串是否相等、"~~" 及 "!~" 執行正規表示式比對、"is set" 及 "is unset" 檢查有無此變數。每個規則可以有多項比對用「,」隔開,接著是以 { } 包起來的指令。指令也可以有多個,可執行的指令有:
  • print <text>:印訊息
  • print-event [rule label]:印出整個 event。If the rule label is provided, it is printed along with the rule.
  • setenv <key> <value>:設定環境變數
  • remove <file>:移除檔案
  • chown <owner> <file>:改變檔案的擁有者
  • chgrp <group> <file>:改變檔案的群組
  • chmod <mode> <file>:改變檔案的存取模式
  • run <command>:使用 system() 執行 shell 指令
  • exec <command> [arg1 [arg2 [... [argn]]]]:直接執行指令
  • mknod <filepath> <mode>:建立 device node (使用 MAJOR, MINOR 及 SUBSYSTEM 變數)
  • load-firmware <firmware directory>:載入存在 <firmware directory> 的韌體,需要 FIRMWARE 變數
  • serialize [socket:]:
  • next-event:跳到下個 event,也就是不比對接下來的規則。
  • branch-event [success]:如果上個指令執行失敗 (或成功),跳到下個 event。
  • branch-rule [success]:如果上個指令執行失敗 (或成功),跳出此規則,繼續比對接下來的規則。
最後三個是流程控制。

OpenWrt preinit 時,規則是 /etc/hotplug2-init.rules,如果是按鍵 (SUBSYSTEM == button) 就「kill -USR1 1」。

在 init 的 boot 時,規則會改設為 /etc/hotplug2-init.rules,會再包含 /etc/hotplug2-platform.rules 及 /etc/hotplug2-common.rules。這些規則有一部分會去執行 /sbin/hotplug-call,第一個參數是 SUBSYSTEM 變數值或 firmware,會去執行 /etc/hotplug.d/$1/ 下所有的程式

preinit 時, 如果沒有 devfs,則執行
/sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --no-persistent --set-coldplug-cmd /sbin/udevtrigger
/sbin/hotplug2 --set-worker /lib/hotplug2/worker_fork.so --set-rules-file /etc/hotplug2-init.rules --persistent &
在 init 的 boot
/sbin/hotplug2 --override --persistent --set-rules-file /etc/hotplug2.rules --set-coldplug-cmd /sbin/udevtrigger --max-children 1 >/dev/null 2>&1 &
疑問:
  • hotplug 跟 hotplug2 的關係?
參考來源:
  1. https://wiki.openwrt.org/doc/techref/hotplug
  2. hotplug2 原始碼
  3. OpenWrt 原始碼
延伸閱讀:
  • devtmpfs
  • devfs
  • udev
  • mdev (busybox 的簡化版 udev)
  • hotplug ()

2019年3月24日 星期日

OpenWrt procd

OpenWrt 使用 procd 取代傳統 Linux 使用的 init 及 udev。

procd 原始碼除了套件 procd 外,還包括套件 procd-ujail、procd-seccomp、procd-nand、procd-nand-firstboot。procd 套件包括二進位程式 init、procd、askfirst、udevtrigger,shell 指令檔 reload_config 和 procd.sh,以及 hotplug json 檔 hotplug-preinit.json 和 hotplug.json。


在 OpenWrt 開機,Linux 最後會執行腳本 /etc/preinit註1 開始 userspace 的動作,但現在一開始就先插隊執行 /sbin/init,然後才執行原本的 /etc/preinit,最後交棒給 procd 繼續執行,變成:/sbin/init → /etc/preinit → /sbin/procd。

註: 在 OpenWrt 開機,Linux 最後會執行腳本 /etc/preinit (`try_to_run_init_process("/etc/preinit")`@init/main.c → do_execve()@fs/exec.c), 執行時會檢查檔案開頭決定何種執行檔,腳本需要以 #! 開頭 (load_script()@fs/binfmt_script.c),/etc/preinit 使用的直譯器是 busybox sh

init

一開始 PREINIT 沒設,執行 init 取代自己
[ -z "$PREINIT" ] && exec /sbin/init
  1. `ulog_open(ULOG_KMSG, LOG_DAEMON, "init")`: 設定 log 方式
  2. SIGTERM、SIGUSR1、SIGUSR2 的處置是 sa_shutdown
  3. `early()`:掛載檔案系統及設定環境變數
  4. `cmdline()`:讀取 Linux 指令行參數 init_debug 設定 debug 等級。
  5. `watchdog_init(1)`:初始化 watchdog,使用 /dev/watchdog
  6. fork() 執行 `/sbin/kmodloader /etc/modules-boot.d/` 載入一些 kernel 模組,並等候結束
  7. fork() 執行 `/sbin/procd -h /etc/hotplug-preinit.json` 處理事件
    • 載入韌體:使用 /sbin/hotplug-call
    • failsafe 按鍵:執行 /etc/rc.button/failsafe 產生 /tmp/failsafe_button
  8. fork() 執行 `PREINIT=1 /bin/sh /etc/preinit`,執行 /etc/preinit 原本該跑的腳本,結束時執行
    1. 如果 hotplug-preinit.json 還在跑,殺了他。
    2. 如果檔案 /tmp/sysupgrade 存在,就一直睡吧不往下執行了 (等候 reboot 嗎?) 
    3. 清掉環境變數 INITRAMFS、PREINIT
    4. 設環境變數 WDTFD 交出 watchdog file descriptor
    5. 交接除錯等級
    6. 改為繼續執行 /sbin/procd

procd

procd 其實可看成是兩個程式,有加 -h 參數是當作 hotplug daemon (hotplug_run()),否則
  1. 繼承除錯等級或重設,並設定 log 方式
  2. `setsid()`:建立新 session 並成為 process goup leader,且成為 process group 唯一的成員,使用 process ID 作為 session ID 及 process group ID,回傳 session ID。no controlling terminal。如果已經是 process group leader,則回傳 -1 且 errno 為 EPERM。
  3. `procd_signal()`:signal 的處置
    • SIGTERM、SIGINT、SIGUSR1、SIGUSR2:sa_shutdown
    • SIGSEGV、SIGBUS:sa_crash
    • SIGHUP、SIGKILL、SIGSTOP:sa_dummy
  4. 如果不是第 1 個 process,一秒後連結到 ubus,否則進入以下 state
  5. STATE_EARLY
    1. 設定 watchdog timeout
    2. hotplug(/etc/hotplug.json) 事件處理
    3. fork() 執行 `udevtrigger`,結束 ... 進入下個 state
  6. STATE_UBUS
    1. 重開 /dev/console stdin/stdout/stderr
    2. ubus timeout:ubus 連上後最後進入下個 state
    3. service_start_early()
  7. STATE_INIT
    1. LOG("- init -\n");
    2. `procd_inittab()`:讀取 inittab 建立 actions 列表 (id:run-level:action:process)
      • process 切出 argv
      • 除了 sysinit 及 shutdown 外,可以有多個
    3. `procd_inittab_run("respawn")`:
    4. `procd_inittab_run("askconsole")`
    5. `procd_inittab_run("askfirst")`
    6. `procd_inittab_run("sysinit")`:依序執行 /etc/rc.d/ 下 S 開始的腳本中的 boot() 部份
    7. `ulog_open(ULOG_SYSLOG, LOG_DAEMON, "procd")`:切換到 syslog
  8. STATE_RUNNING:沒做什麼事,只是 log 完成 init
  9. STATE_SHUTDOWN:shutdown 時進入,依序執行 /etc/rc.d/ 下 K 開始的腳本中的 shutdown() 部份
  10. STATE_HALT
sysinit 跟 shutdown 都是執行 /etc/rc.d/ 下的腳本,這些腳本通常是依所要執行的順序連結到 /etc/init.d/ 下的腳本,在 inittab 可能的內容如下:
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
在 procd 會用 glob() 取出所有 /etc/rc.d/S* 的檔案,全部加到 libubox runqueue 去執行。

askfirst

用在 inittab

udevtrigger

...

procd.sh

共用腳本函數,當 init 腳本使用 procd 方式時 (USE_PROCD=1) 使用。

OpenWrt 的 init 腳本通常透過 /etc/rc.common 執行,在開機時是執行 shell function  boot(),而 boot() 預設是執行 start()。在傳統方式,由 init 腳本提供 start() 功能,但當使用 procd 方式時則改提供 start_service()。
oldprocd
start()start_service() 至少要提供 json command 的部份
stop()已採用 procd_kill 停止程式,stop_service()
reload()如有 reload_service() 則執行,不然執行 start()
running()
trace()
使用 procd 方式的特別之處
  • 所有引數會打包成 json 格式,透過 ubus 送給 procd
    • command
    • respawn
    • ...
  • service_triggers() 可用 procd_add_reload_trigger() 登記哪些設定檔改變後執行 reload_config 需要重新執行。可用 procd_add_network_trigger() 登記網路改變作為重啟的 trigger

範例:package/network/services/dnsmasq

詳情見 OpenWrt package/base-files/files/etc/rc.common。
rc.common 會載入 /lib/functions.sh (一些共同的函數,包括 config_ 開頭的函數)、/lib/config/uci.sh (uci_ 開頭存取 uci 的函數)、及 /lib/functions/service.sh (使用 busybox start-stop-daemon 提供 service_ 開頭的函數)。

reload_config

configd 完成前的臨時替代方案,
檢查設定有改變則呼叫 `ubus call service event { "type": "config.change", "data": { "package": "設定檔名" }}`

開機時會產生設定檔的 MD5 checksum 存在記憶體,更改設定後執行 reload_config 會自動重啟相關的程式。

hotplug-preinit.json 及 hotplug.json。

...

延伸閱讀


/sbin/procd (不設 INITRAMFS,不設 PREINIT)
│ hotplug(/etc/hotplug.json)
├→ udevtrigger
│ubus_connect()...service_init, /etc/inittab
│? /sbin/ubus
├respawn→
├askconsole→
├askfirst→/sbin/askfirst
sysinit⇄用 runqueue 一次跑一個 /etc/rc.d/S* boot,pipe STDOUT/STDERR

hotplug_run() 每次事件發生時
exec→
load-firmware→

libubox uloop
libubox blob, blobmsg
json_script_init
ubus
service
ustream

延伸閱讀:http://data.pavlix.net/installfest/2014/openwrt-software.pdf

2019年3月17日 星期日

行動電話世代

行動電話的世代

1G:類比語音。

2G:數位語音。

  • GSM 系統採用電路交換的語音通道來打電話和傳送簡訊。2G 架構包括基地台子系統 (Base Station Subsystem, BSS) 和 網路子系統(Network SubSystem, NSS)。BSS 由基地台接收站 (Base Transceiver Station, BTS) 以及基地台控制器 (Base Station Controller, BSC) 所組成,負責無線傳輸的排程以及 MAC 的控制訊息。NSS 主要元件為無線交換機中心 (Mobile Switching Center, MSC),負責接入公共交換電話網路(PSTN)。
  • GPRS 系統提供封包交換功能來上網,但仍使用語音通道傳送資料封包,所以速度很慢。2.5G 架構在 GSM 架構加上 GPRS 核心網路,主要由 SGSN (Serving GPRS Support Node) 和 GGSN(Gateway GPRS Support Node) 所組成,負責 IP 網路資料傳遞。BSC 會依據收到的資料決定要傳送到 NSS 或是 GPRS 核心網路。
3G:行動上網。UMTS (Universal Mobile Telecommunications System, 通用行動通訊系統) 由 3GPP 基於 GSM 發展,使用新的 W-CDMA 無線介面等構成的通用無線接入網 (GRAN) 連入不同的骨幹網路 (電路交換或封包交換),如網際網路、ISDN、GSM 或者 UMTS網路,可以用更快的速度上網。
  • 2006 出現智慧型手機

4G:完全 IP 封包化,行動寬頻上網。

  • 4G (2008)
  • 4G LTE (2010)
  • LTE Advanced:引進 CA、MIMO,1Gbps
  • LTE Advanced Pro: >3Gbps, < 2ms 延遲。引進 Full Dimension Massive MIMO、低速低功耗網路。

4G LTE 的傳輸是使用 IP 分封交換 (Packet Switching),不同於 2G / 3G 所使用的電路交換 (Circuit Switched) 傳輸方式。
語音通話服務可以透過 CSFB、SGLTE 或 VoLTE 等方法來達到 。

* CSFB (Circuit Switched Fallback):上網用 4G,語音切回 3G
* SGLTE (Simultaneous GSM and LTE):同時使用 4G 及 GSM (較耗電)
* SVLTE (Simultaneous Voice and LTE):同時使用 4G 及 CDMA (較耗電)
* SRVCC (Single Radio Voice Call Continuity):3GPP 標準,話音通話在 VoLTE 跟 2G/3G 之間切換時能維持通話連續性,在 LTE 覆蓋率不佳的環境可確保通話不中斷。

### VoLTE [[教學]何謂VoLTE?認識新一代高品質語音通話服務]

5G:三大面向:大容量 (達 20Gbps),低延遲 (<1ms),大量低價 IoT 連結。M2M
  • 應用:更高畫質的影片、更快的檔案傳輸、可靠的即時控制應用...
  • Band Steering (頻段引導):引導使用較好的頻段
  • Client Steering (裝置引導):引導使用較好的 AP
  • Seamless Roaming (無縫漫遊):毫秒切換 AP
世代系統名稱調變方式多工方式通道頻寬資料傳輸率頻譜效率
2GGSMGMSKFDMA/TDMA200KHz9.6K/14.4K0.05/0.07
2.5GGPRSGMSKFDMA/TDMA200KHz9.6K/115K0.05/0.58
2.75GEDGE8PSKFDMA/TDMA200KHz384K/384K1.92/1.92
3GW-CDMAQPSKFDMA/CDMA5MHz64K/2M0.01/0.40
3.5GHSDPA16QAMFDMA/CDMA5MHz384K/14.4M0.08/2.88
3.75GHSUPAQPSKFDMA/CDMA5MHz5.76M/14.4M1.15/2.88
4GLTE64QAMFDMA/OFMA20MHz50M/100M2.5/5
4GLTE-A64QAMFDMA/OFMA100MHz500M/1G5/10
4.5GLTE-A Pro256QAM?/???/3G (32CA)?/?
「頻譜效率」(Spectrum efficiency) 是單位頻寬 (Hz) 有多少資料傳輸率 (bps)。

調變技術 (Modulation)

2G 以後是採用數位調變,用不同波形 (symbol) 的類比電磁波 (包括用振幅大小、頻率高低、相位不同等) 來代表 0 與 1 的數位訊號。數位調變的優點包括可以偵錯與除錯、壓縮與解壓縮、加密與解密、更好的抗雜訊能力等。

多工技術 (Multiplex)

將電磁波給不同的使用者使用,常見的包括下列 4 種:
  • 分時多工接取 (TDMA):依照「時間先後」區分。
  • 分頻多工接取 (FDMA):依照「頻率範圍不同」區分。
  • 分碼多工接取 (CDMA):用不同的碼加密資料後傳送,只有有特定碼的接收端以不同的密碼來分辨要接收的訊號。
  • 正交分頻多工 (OFDM):使用彼此頻率「正交」的 FDMA。LTE / LTE-A、無線區域網路 (IEEE802.11a/g/n)、數位電視 (DTV)、數位音訊廣播 (DAB) 都有使用。
通常同時使用兩種以上的多工技術來增加資料傳輸率,滿足每個人都要使用的需求。

參考來源

http://technews.tw/2015/10/12/3g、4g、5g-meaning-part-two

2019年2月16日 星期六

SIP INFO

SIP Method INFO 是在 Dialog 內交換訊息。

傳統 SIP INFO 定義在 RFC 2976,運用在一些標準或私訂的應用 (legacy INFO usage):
  • RFC 3372 在 SIP 信體放 ISDN User Part (ISUP) 訊息,ITU-T 和 3GPP 也有類似規範。
  • ECMA-355 在 SIP 信體放 QSIG。
  • 作為 Media Server Control Markup Language (MSCML) (RFC 5022) 的傳送機制,使用 Require 信頭欄位的一個 option-tag 來確保接收端了解 INFO 內容。
  • 作為 Media Server Markup Language (MSML) (RFC 5707) 的傳送機制。
  • 請求快速影片更新,目前基於 RTCP 的標準機制定義在 RFC 5168。
  • 傳送 DTMF 音,所有機制都是私訂未標準化。

傳統 INFO 無法表示支援哪些應用和傳送的資訊是哪種,通常需要靜態設定,而有相容互通問題。

RFC 6086 導入 Info Package 機制,新增兩個信頭欄位 -- Recv-Info 和 Info-Package。Recv-Info 告訴對方可接受哪些 Info Package。Info-Package 信頭欄位用在 INFO 請求來表示使用哪一個 Info Package。沒有 Info-Package 的 INFO 請求則使用傳統 SIP INFO。另有 Info Package 規範定義如何應用,名稱可以註冊到 IANA。

Info Package 機制

Info-Package 信頭欄位參數

INFO 請求信體可放應用的資訊,可以是單一 MIME 類型或 multipart [RFC5621 "Message Body Handling in the SIP"]。Info Package 的 INFO 請求的信體由 Content-Disposition 信頭欄位值的 Info-Package 標示。Info Package 的 INFO 回應不能有信體。

沒定義傳送順序機制,可依賴 CSeq 信頭欄位偵測順序是否正確。如果特定應用需要額外傳送順序機制,在關聯的 Info Package 定義。

2019年2月15日 星期五

SIP 回應碼

SIP 回應碼 (Response Code, Status-Code) 用在 SIP 回應的頭行 (狀態行、Status-Line) 第 2 個欄位,有 3 位數字。回應碼分成暫時回應 (Provisional Response) 和最後回應 (Final Response)。依第 1 位數字分類:
回應碼分類說明
1xx暫時回應 (SIP transaction 進行中)收到請求,還在處理中。
2xx最後回應
(結束 SIP transaction)
Success請求成功。
3xxFailRedirection請改洽新位址。
4xxRequest Error特定 Server 的回應請求失敗,可能語法有誤或無法在此 server 提供。
5xxServer Error有效的請法無法在此 server 提供。
6xxGlobal Failure請求無法在任何 server 提供。

回應碼適用大部分 HTTP/1.1 回應碼,6xx 類是 SIP 新增,完整列表可見 IANA SIP 參數 登記的回應碼。每個回應碼會有對應的預設 Reason-Phrase。

UAC 必須能處理每個 class 的 x00 和 183,不認得的最後回應 MUST 當作同 class 的 x00 處理,不認得的暫時回應當作 183 Session Progress 處理。[RFC3261 8.1.3.2]

Provisional 1xx

暫時回應 (Provisional Response),表示還在進行中,要再等最後回應。

如果預期還要 200 ms 以上才會有結果,先送 1xx 回應。 可包括信體,如含 session 描述。

1xx 回應並不會可靠地傳送,不會讓 UAC 送 ACK。使用 PRACK 可可靠傳送暫時回應。

100 Trying

嘗試中。表示下一站 Proxy 已經收到請求,一些未知的動作正在進行中 (例如:資料庫查詢中),和其它暫時的回應一樣會停止 UAC 重傳 INVITE。但不同於其它暫時的回應,stateful proxy 不回送 100 Trying。

180 Ringing

振鈴中。被叫端用戶正在響鈴,一般主叫端需要產生回鈴音。

一般不含 SDP,需要主叫端自己產生回鈴音。

181 Call Is Being Forwarded

轉接中。可用來表示呼叫已經轉送到不同的目的地。

182 Queued

排隊等候中。被叫暫時 unavailable,server 決定 queue the call。當被叫 available,再回適當最後回應。Reason-Phrase 可提供更多等候細節,例如「5 calls queued; expected waiting time is 15 minutes」,可發多次 182 更新等候狀態。

183 Session Progress

呼叫進行中 。不清楚被叫是否正在響鈴或是其它狀態,可在 Reason-Phrase 信頭欄位、或信體提供更多資訊。

UAC 必須能處理 183,不認得的暫時回應當作 183 處理。[RFC3261 8.1.3.2]

一般會含 SDP,在接通前建立不收費的 early-media,由局端提供音訊,可能應用:

  • 彩鈴,可能是不同的回鈴音、或音樂。(該用 180?)
  • 錯誤語音,「您撥的號碼錯誤,請察明後再撥」、「您撥的號碼通話中,請稍後再撥」等。
  • IVR。

early-media 需要 INVITE 提供 SDP early-offer 才能送到主叫端,如果 INVITE 沒提供 SDP 呢?回 503?

P-Early-Media header

https://thanhloi2603.wordpress.com/2017/08/05/sip-180-vs-183-vs-early-media/

待讀:https://www.ietf.org/archive/id/draft-ietf-sip-183-00.txt

Successful 2xx

請求成功。

200 OK

請求成功,附帶回傳的資訊視請求使用的 method。

204 No Notification

成功,但沒有其它 Notification,用在 SUBSCRIBE。

Redirection 3xx

提供可能滿足呼叫的用戶新位址或服務。

300 Multiple Choices

多重選擇

301 Moved Permanently

已永久遷移。受話端不再使用 Request-URI 上的位址,應該改嘗試 Contact 信頭欄位給的新位址。
發話端應該更新自己紀錄的相關資料 (如電話簿),改用新位址。

302 Moved Temporarily

暫時遷移。

305 Use Proxy

請改用代理伺服器存取。UAS 回應要求的資源必須透過給定在 Contact 欄位的 proxy 存取。

380 Alternative Service

有另外的服務。呼叫失敗,但可用說明在訊息體的另外服務。

Request Failure 4xx

來自特定 server 失敗的回應 (到其它 server 可能成功)。UAC 不應該重試沒修改的相同請求。

400 Bad Request

不當請求。請求由於 syntax 錯誤而無法處理。Reason-Phrase 應該要指出 syntax 問題細節,例如「Missing Call-ID header field」。

401 Unauthorized

未授權

402 Payment Required

要求付費

403 Forbidden

禁止

404 Not Found

用戶找不到。

405 Method Not Allowed

方法不允許。Request-URI 指定的位址不允許請求的 method 。必須包含 Allow 信頭欄位列出指定的位址允許的 method。

406 Not Acceptable

不可接受

407 Proxy Authentication Required

需要代理伺服器授權

408 Request Timeout

呼叫超時:在預定時間內無法找到用戶

410 Gone

已消失:用戶曾經存在,但已從此處消失

413 Request Entity Too Large

請求實體過大

414 Request-URI Too Long

請求 URI 過長

415 Unsupported Media Type

不支援的媒體類型。請求的信體格式不支援,*必須* 在 Accept、Accept-Encoding、或 Accept-Language 回可接受的列表。

UAC 收到回應可再依據這些信頭欄位重試。

416 Unsupported URI Scheme

不支援的URI方案

420 Bad Extension

421 Extension Required

423 Interval Too Brief

時間間隔過短

480 Temporarily Unavailable

暫時不可使用。用戶不在 (例如沒登入、啟用「勿干擾」(do not disturb)。可加 Retry-After 表示適當的再撥時間。用戶可能有其它聯繫方式。應該在 Reason-Phrase 表示更精確原因,如為什麼用戶不在。
也可能是 redirect 或 proxy server 沒有可用的轉送位置。

481 Call/Transaction Does Not Exist

通話不存在。

482 Loop Detected

偵測到迴圈。

483 Too Many Hops

經由過多。

484 Address Incomplete

地址不全。

485 Ambiguous

模糊不清。

486 Busy Here

受話端在這忙線中。回應可加 Retry-After 說明適當的再撥時間。受話端可能有其它聯繫方式,例如 voice mail,否則該用 600 Busy Everywhere。

487 Request Terminated

請求已結束。請求已經由 BYECANCEL 結束。487 不會用在回應 CANCEL。

用在 re-INVITE 需要掛斷嗎?

488 Not Acceptable Here

此處不可接受。

491 Request Pending

已經有待處理的 re-INVITE 進行中。
RFC 3261 新增,處理雙方同時互送 re-INVITE 的碰撞 (glare) 情況。

493 Undecipherable

無法解讀。

Server Failure 5xx

500 Internal Server Error

伺服器內部錯誤。

501 Not Implemented

未實作。

502 Bad Gateway

閘道器錯誤。

503 Service Unavailable

服務不可使用。

504 Server Time-out

伺服器超時。

505 SIP Version not supported

SIP 版本不支援。

513 Message Too Large

訊息過長。

Global Failures 6xx

全域失敗。

600 Busy Everywhere

各處皆忙線中。回應可加 Retry-After 說明適當的再撥時間。如果受話端不想 reveal 拒答原因,使用 603 Decline 取代。已知沒其它其它聯繫方式 (如 voice mail),否則應該使用 486 Busy Here

603 Decline

受話端拒絕。回應可加 Retry-After 說明適當的再撥時間。已知沒其它其它聯繫方式。

604 Does Not Exist Anywhere

無處存在

606 Not Acceptable

不可接受。

參考

  1. RFC 3261 Section 21

2019年2月12日 星期二

SIP Header: Record-Route and Route

SIP 請求的過程,UAC 和每一个經過的 Proxy,攏會加一筆頂頭 Via 來紀錄自己。回應會照這Via 紀錄反過來送回。如果請求會建立 Dialog,Dialog 建立後就知道對方位址 (Contact),後續 Dialog 內請求就直送對方,免經過這些 Proxy。

Dialog 建立過程中經過的那些 Proxy 中,如果仍要參與後續 Dialog 內的 Transaction,在經手 Dialog 建立的請求時,加上一筆頂頭 Record-Route 紀錄自己。當請求到達 UAS 後,UAS 會將全部 Record-Route 按照順序紀錄成 Route Set,並複製到回應訊息。UAC 收到回應訊息時,將全部 Record-Route 依相反順序紀錄成 Route Set。之後 Dialog 內 (如 ACK、BYE、re-INVITE) 的請求,依 Route Set 順序產生 Route 信頭,並依此順序轉送。

在 Dialog 建立請求時,UAC 也可以事先設定 Route 信頭,例如 outbound proxy。

參數
  • lr (loose router):請求先照 Route 順序傳送,最後才是請求 URI。過程中 Proxy 收到後,移除應該是自己的頂頭 Route。和 loose router 相對的,是舊 SIP 的 strict routing,需要一開始把請求 URI 移為最尾的 Route,過程中一直把頂頭 Route 移到請求 URI 使用。有 lr 參數採用 loose routing,否則採用 strict routing。
  • r2=
  • ftag=
  • nat=

UAC 發請求有 Route Set 時,如果 Route Set 的第 1 个 URI 有 lr 參數,Request-URI 放 remote target URI,Route 封頭 按順序放 Route Set 並含所有參數。如果 Route Set 的第 1 个 URI 沒有 lr 參數,Request-URI 放第 1 个 Route Set 去除 Request-URI 不允許的參數,Route 封頭按順序放剩下的 Route Set 並含所有參數,最後再加上 remote target URI。

應用:

  • 作 NAT 的 proxy 需要持續作位址轉換
  • 作 accounting 的 proxy 需要知道何時 BYE 通話結束。

SIP REGISTER 可以有 Route,忽略 Record-Route。

參考來源
  1. http://lirobo.blogspot.tw/2010/10/sip-invite.html
  2. http://kamailio.org/docs/modules/stable/modules/rr.html
  3. http://tools.ietf.org/html/rfc3261

2019年2月9日 星期六

SIP Definitons

SIP 用詞定義

Dialog (對話)

兩個 UA 間持續一段時間的暫時 SIP 關係,由 INVITE transaction 建立,用一組 Call-ID、From tag、和 To tag 結合起來識別。在 RFC 2543 稱為 Call Leg。
  • 目前只有 INVITE 可以建立對話。
  • BYE transaction 結束對話。
  • Dialog 內 (in-dialog):由相同的 Call-ID、From tag、和 To tag 識別,每個 SIP 請求的 CSeq 是增加的。
    • re-INVITE (沒有 To tag 是要建立不同的 session)
    • INFO
  • out-of-dialog:沒有 To tag 就是 out-of-dialog 嗎?還是指不會建立 dialog 的 transaction?
  • REGISTER 請求不會建立 dialog,所以 Record-Route 沒作用。
SIP 訊息的部件,傳遞關於 SIP 訊息的資訊,由一系列信頭欄位組成。

Header Field (信頭欄位)

SIP 訊息裡信頭 (Header) 的部件。一個信頭欄位包含一個信頭欄位名稱和 0 個以上信頭欄位值,可重複信頭欄位名稱出現在多個信頭欄位行。一個信頭欄位行裡有多個信頭欄位值用「,」隔開。有些信頭欄位只能有一個信頭欄位值,而只會有一個信頭欄位行。

Header Field Value (信頭欄位值)

一個信頭欄位值是一個值;一個信頭欄位包含 0 個以上信頭欄位值。

Informational Response

跟 Provisional Response 相同。

Initiator, Calling Party, Caller (發話端):

雙端中為了建立一個新 session (和 dialog) 發出 INVITE 請求那一端。發話端
保有其發話端角色從送一開始 INVITE 建立 dialog 開始,直到 dialog 結束。

Invitation

一個 INVITE 請求。

Invitee, Invited User, Called Party, Callee (受話端)

雙端中為了建立一個新 session 接收 INVITE 請求那一端。受話端保有其受話端角色從收到 INVITE 開始直到建立的 dialog 結束。

Route Set

一份 proxy 位址表,傳送特定請求時按照順序經過。Route Set 可透過如 Record-Route 學習、由用戶或服務提供者人工設定、或其它非 SIP 機制等設定。

Server

一個 network element,接收請求並回送回應來提供服務。 Server 範例有 Proxy、UAS、redirect server、和 registrar。

參考來源

RFC3261 §6

SIP header Via

所有 SIP 訊息 都要有 Via,縮寫 v。一開始的 UAC 和後續途經的每個 proxy 都會疊加一個 Via 放傳送的位址,依序作為回應的路徑。 格式 sent-protocol sent-by [ ;branch= branch ][ ; 參數 ...] s...