2018年3月22日 星期四

ATH-AR3BT

指示燈
  • 紅藍閃爍
  • 紅燈慢閃
  • 藍燈慢閃
  • 紅燈閃爍:電量不足,會發出 2 次嗶嗶聲。
  • 紅燈:micro USB 充電,藍牙連線會中止
  • 藍燈:充滿約 5 小時,可聽 30 小時
藍牙配對
  • v4.1
  • A2DP、AVRCP、HFP、HSP
  • AAC, AptX 編碼
  • NFC
耳罩
  • Ø40mm 驅動單元
  • 可折疊

內建麥克風
音樂播放或接聽來電等功能操作。
立體聲插座,電力耗盡可用有線方式聽。
190g

https://eu.audio-technica.com/resources/ATH/ATH-AR3BT_UM_V2_132312851_10L_web_170210.pdf

2017/08/28 NT$3450-648
其它
智慧型手機用附麥克風導線 AT338iS

SIP and ABNF

SIP 規範 RFC 3261 §25 提到 SIP 訊息格式用 ABNF 描述。ABNF (Augmented Backus–Naur Form, 擴充巴科斯範式, RFC 2234RFC 4234RFC 5234) 改良自 BNF (Backus–Naur Form),是一種用來描述通訊協定中一系列數值格式的語言。

ABNF 規範是一些如下推導規則的集合,以 crlf 換行結束
rule = definition ;comment crlf
  • rule:規則名稱,不分大小寫,以字母開始
  • definition:規則定義,可能包含一個或多個規則名稱、或數值的組合。
  • comment:需要的話,「;」開始為註解。
為了便於觀看,每條規則靠左對齊。當一個規則需要多行時,第二行開始縮排。

規則最後解析成一串值,值可用「%」表示法,二進位前置「%b」、十進位前置「%d」、十六進位前置「%x」。多個值串接可用一個前置,後面好幾個數字用「.」連接。一串值也可以用類似 C 語言字串前後加「"」表示,但在 ABNF 的字串是不分大小寫的。如果要分大小寫需要使用「%」表示法。

定義中使用的 Operator,依照 Precedence 高低
  • Value Range Alternatives (範圍):%c##-##
  • Repetition (重複)
    • *Rule:Rule 重複 0 次以上,* 前後可分別加上數字表示最少及最多的重複次數。
    • nRule:n 是數字,重複 n 次
  • Sequence Group (群組):(Rule1 Rule2)
  • Optional Sequence (選擇性的):[RULE]
  • Concatenation (串接):Rule1 Rule2
  • Alternatives (或者):Rule1 / Rule2
  • Incremental Alternatives (新增或者):Rule1 =/ Rule2

基本規則

US ASCII coded 字元集定義在 ANSI X3.4-1986,等同於國際標準 ISO 646。
DIGIT=%x30-39; 0-9,數字
ALPHA=%x41-5A / %x61-7A; A-Z / a-z,英文字母
alphanum=ALPHA / DIGIT; 英文字母和數字
一些規則採自 RFC 2396 但更新為 RFC 2234 相容,包括:
reserved=";" / "/" / "?" / ":" / "@" / "&" / "=" / "+" / "$" / ",";
unreserved=alphanum / mark
mark="-" / "_" / "." / "!" / "~" / "*" / "'" / "(" / ")";mark 意思?
escaped="%" HEXDIG HEXDIG
HEXDIG=DIGIT / "A" / "B" / "C" / "D" / "E" / "F";十六進位數字不分大小寫
LHEX=DIGIT / %x61-66;十六進位數字限制小寫。
ASCII 中的可列印字元,除了 reserved (10 字元)、unreserved (71 字元)、%、和 SP 外,剩下 "#[\]^`{|}<> 12 字元。
SWS 是選擇性的 LWS,一般用在 token 和 separators 間。
LF   = %x0A              ;linefeed
CR   = %x0D              ;carriage return
CRLF = CR LF             ;換行

HTAB = %x09              ;horizontal tab
SP   = %x20
WSP  = SP / HTAB         ;white space
LWS  = [*WSP CRLF] 1*WSP ;linear whitespace
                         ;方便拆行顯示,語意和一個 SP 一樣。
                         ;一個或連續 WSP,前面可有一個換行,換行前可有連續 WSP。
                         ;接收或轉送可取代為 SP (和 HTTP/1.1 行為一致)。
SWS  = [LWS]             ;sep whitespace,選擇性的 LWS。
信頭的名稱和值。 規則 TEXT-UTF8-TRIM 用在描述性的欄位內容,並不打算給訊息解析器解釋,字元來自 UTF-8 字元集,不能是「quoted-string」,其中開頭和結束 LWS 是無意義的。
TEXT-UTF8-TRIM  =  1*TEXT-UTF8char *(*LWS TEXT-UTF8char)
TEXT-UTF8char   =  %x21-7E / UTF8-NONASCII
UTF8-NONASCII   =  %xC0-DF 1UTF8-CONT /
                   %xE0-EF 2UTF8-CONT /
                   %xF0-F7 3UTF8-CONT /
                   %xF8-Fb 4UTF8-CONT /
                   %xFC-FD 5UTF8-CONT
UTF8-CONT       =  %x80-BF

TEXT-UTF8-TRIM 只在 LWS 使用 CRLF 作為折行,LWS 會換成一個 SP 來解釋。

註:HTTP 使用 ISO 8859-1 字元集,以 ASCII 為基礎,在空置的 0xA0-0xFF 加入 96 個字母及符號,藉以供使用附加符號的拉丁字母語言使用。

許多 SIP 欄位包含來自「token」的字元,用 LWS 或「separators 」分隔的字。除非特別提到,「token」是不分大小寫 (case-insensitive)。在參數值如需要用到這些分隔字元,必須在「quoted-string」裡面。「word」特別用在 Call-ID,可使用「token」和大部分分隔字元。
token       =  1*(alphanum / "-" / "." / "!" / "%" / "*"
               / "_" / "+" / "`" / "'" / "~" )
DQUOTE      =  %x22 ; " (Double Quote)
separators  =  "(" / ")" / "<" / ">" / "@" /
               "," / ";" / ":" / "\" / DQUOTE /
               "/" / "[" / "]" / "?" / "=" /
               "{" / "}" / SP / HTAB
word        =  1*(alphanum / "-" / "." / "!" / "%" / "*" /
               "_" / "+" / "`" / "'" / "~" /
               "(" / ")" / "<" / ">" /
               ":" / "\" / DQUOTE /
               "/" / "[" / "]" / "?" /
               "{" / "}" )
當分隔字元用在 token 間,這些字元前後常可以允許 whitespace:
STAR    =  SWS "*" SWS ; 星號
SLASH   =  SWS "/" SWS ; slash
EQUAL   =  SWS "=" SWS ; 等號
LPAREN  =  SWS "(" SWS ; 左括號, %x28
RPAREN  =  SWS ")" SWS ; 右括號, %x29
RAQUOT  =  ">" SWS     ; 左角括號
LAQUOT  =  SWS "<"     ; 右角括號
SEMI    =  SWS ";" SWS ; 分號
LDQUOT  =  SWS DQUOTE  ; 雙引號開始
RDQUOT  =  DQUOTE SWS  ; 雙引號結束

comment 的內容用 () 括號包起來,只用在少數 header 欄位值。
其它欄位,括號是參數值的一部分。
comment  =  LPAREN *(ctext / quoted-pair / comment) RPAREN
ctext    =  %x21-27 / %x2A-5B / %x5D-7E / UTF8-NONASCII
            / LWS ; 所有字元,除了左右括號和反斜線。
用雙引號 quoted 的文字串解析為單一字,裡面的雙引號和反斜線要 escaped。
quoted-string = SWS DQUOTE *(qdtext / quoted-pair ) DQUOTE
qdtext        = LWS / %x21 / %x23-5B / %x5D-7E
                / UTF8-NONASCII ; 不含雙引號和反斜線。
backslash 字元 ("\") 只用在「quoted-string」和「comment 」作單字元 quoting 機制。為避免與折行和 header separation 衝突,CR 和 LF 不能用此機制 escaped。
註:HTTP/1.1 可以 escape CR 和 LF。
quoted-pair = "\" (%x00-09 / %x0B-0C
              / %x0E-7F) ; 不含 CR 和 LF
任何字元用在 message-body
OCTET = %x00-FF ; 8 bits of data
註:規則名稱雖然不分大小寫,特殊基本規則多用大寫。
alphanum
! ' * - . _ ~
unreservedtokenword
( )unreservedsepword
$ &reserved--
+reservedtokenword
, ; = @reservedsep-
/ : ?reservedsepword
" <> [] {} \-sepword
# ^ |---
% `-tokenword
SP, HTAB-sep-
  • unreserved 和 reserved 沒有重疊。在有些欄位,unreserved 會擴充,例如 user-unreserved (擴充只取自 reserved?)。word 包含全部 unreserved。
  • token 則不含 unreserved 的 (),但多了 % 和 `、及 reserved 中的 +。
  • token 和 separators 沒有重疊。

URI 格式

SIP-message = Request / Response ; SIP 訊息 只有兩種,Request 和 Response。
Request     = Request-Line *( message-header ) CRLF [ message-body ]
Response    = Status-Line *( message-header ) CRLF [ message-body ]

message-header  =  (Accept
                /  Accept-Encoding
                /  Accept-Language
                /  Alert-Info
                /  Allow
                /  Authentication-Info
                /  Authorization
                /  Call-ID
                /  Call-Info
                /  Contact
                /  Content-Disposition
                /  Content-Encoding
                /  Content-Language
                /  Content-Length
                /  Content-Type
                /  CSeq
                /  Date
                /  Error-Info
                /  Expires
                /  From
                /  In-Reply-To
                /  Max-Forwards
                /  MIME-Version
                /  Min-Expires
                /  Organization
                /  Priority
                /  Proxy-Authenticate
                /  Proxy-Authorization
                /  Proxy-Require
                /  Record-Route
                /  Reply-To
                /  Require
                /  Retry-After
                /  Route
                /  Server
                /  Subject
                /  Supported
                /  Timestamp
                /  To
                /  Unsupported
                /  User-Agent
                /  Via
                /  Warning
                /  WWW-Authenticate
                /  extension-header) CRLF

INVITEm           =  %x49.4E.56.49.54.45 ; INVITE in caps
ACKm              =  %x41.43.4B ; ACK in caps
OPTIONSm          =  %x4F.50.54.49.4F.4E.53 ; OPTIONS in caps
BYEm              =  %x42.59.45 ; BYE in caps
CANCELm           =  %x43.41.4E.43.45.4C ; CANCEL in caps
REGISTERm         =  %x52.45.47.49.53.54.45.52 ; REGISTER in caps
Method            =  INVITEm / ACKm / OPTIONSm / BYEm
                     / CANCELm / REGISTERm ; 以上是大寫的 method 名稱,實際上不分大小寫。
                     / extension-method
extension-method  =  token
Response          =  Status-Line
                     *( message-header )
                     CRLF
                     [ message-body ]

Accept         =  "Accept" HCOLON
                   [ accept-range *(COMMA accept-range) ]
accept-range   =  media-range *(SEMI accept-param)
media-range    =  ( "*/*"
                  / ( m-type SLASH "*" )
                  / ( m-type SLASH m-subtype )
                  ) *( SEMI m-parameter )
accept-param   =  ("q" EQUAL qvalue) / generic-param
qvalue         =  ( "0" [ "." 0*3DIGIT ] )
                  / ( "1" [ "." 0*3("0") ] )
generic-param  =  token [ EQUAL gen-value ]
gen-value      =  token / host / quoted-string

Accept-Encoding  =  "Accept-Encoding" HCOLON
                     [ encoding *(COMMA encoding) ]
encoding         =  codings *(SEMI accept-param)
codings          =  content-coding / "*"
content-coding   =  token

Accept-Language  =  "Accept-Language" HCOLON
                     [ language *(COMMA language) ]
language         =  language-range *(SEMI accept-param)
language-range   =  ( ( 1*8ALPHA *( "-" 1*8ALPHA ) ) / "*" )

Alert-Info   =  "Alert-Info" HCOLON alert-param *(COMMA alert-param)
alert-param  =  LAQUOT absoluteURI RAQUOT *( SEMI generic-param )

Allow  =  "Allow" HCOLON [Method *(COMMA Method)]

Authorization     =  "Authorization" HCOLON credentials
credentials       =  ("Digest" LWS digest-response)
                     / other-response
digest-response   =  dig-resp *(COMMA dig-resp)
dig-resp          =  username / realm / nonce / digest-uri
                      / dresponse / algorithm / cnonce
                      / opaque / message-qop
                      / nonce-count / auth-param
username          =  "username" EQUAL username-value
username-value    =  quoted-string
digest-uri        =  "uri" EQUAL LDQUOT digest-uri-value RDQUOT
digest-uri-value  =  request-uri ; Equal to request-uri as specified
                     by HTTP/1.1
message-qop       =  "qop" EQUAL qop-value
cnonce            =  "cnonce" EQUAL cnonce-value
cnonce-value      =  nonce-value
nonce-count       =  "nc" EQUAL nc-value
nc-value          =  8LHEX
dresponse         =  "response" EQUAL request-digest
request-digest    =  LDQUOT 32LHEX RDQUOT
auth-param        =  auth-param-name EQUAL
                     ( token / quoted-string )
auth-param-name   =  token

other-response    =  auth-scheme LWS auth-param
                     *(COMMA auth-param)
auth-scheme       =  token

Authentication-Info  =  "Authentication-Info" HCOLON ainfo
                        *(COMMA ainfo)
ainfo                =  nextnonce / message-qop
                         / response-auth / cnonce
                         / nonce-count
nextnonce            =  "nextnonce" EQUAL nonce-value
response-auth        =  "rspauth" EQUAL response-digest
response-digest      =  LDQUOT *LHEX RDQUOT

Call-ID  =  ( "Call-ID" / "i" ) HCOLON callid
callid   =  word [ "@" word ]

Call-Info   =  "Call-Info" HCOLON info *(COMMA info)
info        =  LAQUOT absoluteURI RAQUOT *( SEMI info-param)
info-param  =  ( "purpose" EQUAL ( "icon" / "info"
               / "card" / token ) ) / generic-param

delta-seconds      =  1*DIGIT

Content-Disposition   =  "Content-Disposition" HCOLON
                         disp-type *( SEMI disp-param )
disp-type             =  "render" / "session" / "icon" / "alert"
                         / disp-extension-token
disp-param            =  handling-param / generic-param
handling-param        =  "handling" EQUAL
                         ( "optional" / "required"
                         / other-handling )
other-handling        =  token

disp-extension-token  =  token

Content-Encoding  =  ( "Content-Encoding" / "e" ) HCOLON
                     content-coding *(COMMA content-coding)

Content-Language  =  "Content-Language" HCOLON
                     language-tag *(COMMA language-tag)
language-tag      =  primary-tag *( "-" subtag )
primary-tag       =  1*8ALPHA
subtag            =  1*8ALPHA

Content-Length  =  ( "Content-Length" / "l" ) HCOLON 1*DIGIT
Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type
media-type       =  m-type SLASH m-subtype *(SEMI m-parameter)
m-type           =  discrete-type / composite-type
discrete-type    =  "text" / "image" / "audio" / "video"
                    / "application" / extension-token
composite-type   =  "message" / "multipart" / extension-token
extension-token  =  ietf-token / x-token
ietf-token       =  token
x-token          =  "x-" token
m-subtype        =  extension-token / iana-token
iana-token       =  token

m-parameter      =  m-attribute EQUAL m-value
m-attribute      =  token
m-value          =  token / quoted-string

CSeq  =  "CSeq" HCOLON 1*DIGIT LWS Method

Date          =  "Date" HCOLON SIP-date
SIP-date      =  rfc1123-date
rfc1123-date  =  wkday "," SP date1 SP time SP "GMT"
date1         =  2DIGIT SP month SP 4DIGIT
                 ; day month year (e.g., 02 Jun 1982)
time          =  2DIGIT ":" 2DIGIT ":" 2DIGIT
                 ; 00:00:00 - 23:59:59
wkday         =  "Mon" / "Tue" / "Wed"
                 / "Thu" / "Fri" / "Sat" / "Sun"
month         =  "Jan" / "Feb" / "Mar" / "Apr"
                 / "May" / "Jun" / "Jul" / "Aug"
                 / "Sep" / "Oct" / "Nov" / "Dec"

Error-Info  =  "Error-Info" HCOLON error-uri *(COMMA error-uri)
error-uri   =  LAQUOT absoluteURI RAQUOT *( SEMI generic-param )

Expires     =  "Expires" HCOLON delta-seconds

In-Reply-To  =  "In-Reply-To" HCOLON callid *(COMMA callid)

Max-Forwards  =  "Max-Forwards" HCOLON 1*DIGIT

MIME-Version  =  "MIME-Version" HCOLON 1*DIGIT "." 1*DIGIT

Min-Expires  =  "Min-Expires" HCOLON delta-seconds

Organization  =  "Organization" HCOLON [TEXT-UTF8-TRIM]

Priority        =  "Priority" HCOLON priority-value
priority-value  =  "emergency" / "urgent" / "normal"
                   / "non-urgent" / other-priority
other-priority  =  token

Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))

                       / other-challenge
other-challenge     =  auth-scheme LWS auth-param
                       *(COMMA auth-param)
digest-cln          =  realm / domain / nonce
                        / opaque / stale / algorithm
                        / qop-options / auth-param
realm               =  "realm" EQUAL realm-value
realm-value         =  quoted-string
domain              =  "domain" EQUAL LDQUOT URI
                       *( 1*SP URI ) RDQUOT
URI                 =  absoluteURI / abs-path
nonce               =  "nonce" EQUAL nonce-value
nonce-value         =  quoted-string
opaque              =  "opaque" EQUAL quoted-string
stale               =  "stale" EQUAL ( "true" / "false" )
algorithm           =  "algorithm" EQUAL ( "MD5" / "MD5-sess"
                       / token )
qop-options         =  "qop" EQUAL LDQUOT qop-value
                       *("," qop-value) RDQUOT
qop-value           =  "auth" / "auth-int" / token

Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials

Proxy-Require  =  "Proxy-Require" HCOLON option-tag
                  *(COMMA option-tag)
option-tag     =  token

Require       =  "Require" HCOLON option-tag *(COMMA option-tag)

Retry-After  =  "Retry-After" HCOLON delta-seconds
                [ comment ] *( SEMI retry-param )

retry-param  =  ("duration" EQUAL delta-seconds)
                / generic-param

Server           =  "Server" HCOLON server-val *(LWS server-val)
server-val       =  product / comment
product          =  token [SLASH product-version]
product-version  =  token

Subject  =  ( "Subject" / "s" ) HCOLON [TEXT-UTF8-TRIM]

Supported  =  ( "Supported" / "k" ) HCOLON
              [option-tag *(COMMA option-tag)]

Timestamp  =  "Timestamp" HCOLON 1*(DIGIT)
               [ "." *(DIGIT) ] [ LWS delay ]
delay      =  *(DIGIT) [ "." *(DIGIT) ]

Unsupported  =  "Unsupported" HCOLON option-tag *(COMMA option-tag)
User-Agent  =  "User-Agent" HCOLON server-val *(LWS server-val)

Via               =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
via-parm          =  sent-protocol LWS sent-by *( SEMI via-params )

ia-params        =  via-ttl / via-maddr
                     / via-received / via-branch
                     / via-extension
via-ttl           =  "ttl" EQUAL ttl
via-maddr         =  "maddr" EQUAL host
via-received      =  "received" EQUAL (IPv4address / IPv6address)
via-branch        =  "branch" EQUAL token
via-extension     =  generic-param
sent-protocol     =  protocol-name SLASH protocol-version
                     SLASH transport
protocol-name     =  "SIP" / token
protocol-version  =  token
transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
                     / other-transport
sent-by           =  host [ COLON port ]
ttl               =  1*3DIGIT ; 0 to 255

Warning        =  "Warning" HCOLON warning-value *(COMMA warning-value)
warning-value  =  warn-code SP warn-agent SP warn-text
warn-code      =  3DIGIT
warn-agent     =  hostport / pseudonym
                  ;  the name or pseudonym of the server adding
                  ;  the Warning header, for use in debugging

arn-text      =  quoted-string
pseudonym      =  token

WWW-Authenticate  =  "WWW-Authenticate" HCOLON challenge

extension-header  =  header-name HCOLON header-value
header-name       =  token
header-value      =  *(TEXT-UTF8char / UTF8-CONT / LWS)
message-body  =  *OCTET ; 任何長度任何字元
Request-URI = SIP-URI / SIPS-URI / absoluteURI
absoluteURI = scheme ":" ( hier-part / opaque-part )
scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
  • Request-URI 較複雜一點,基本結構都會有「:」,之前的部份稱 scheme,之後依照 scheme 解釋。

Header 欄位

message-header = (Accept / Accept-Encoding / Accept-Language / Alert-Info / Allow / Authentication-Info / Authorization / Call-ID / Call-Info / Contact / Content-Disposition / Content-Encoding / Content-Language / Content-Length / Content-Type / CSeq / Date / Error-Info / Expires / From / In-Reply-To / Max-Forwards / MIME-Version / Min-Expires / Organization / Priority / Proxy-Authenticate / Proxy-Authorization / Proxy-Require / Record-Route / Reply-To / Require / Retry-After / Route / Server / Subject / Supported / Timestamp / To / Unsupported / User-Agent / Via / Warning / WWW-Authenticate / extension-header) CRLF
extension-header = header-name HCOLON header-value
  • 把各種 header 都列出來了,最終都有 CRLF。

ContactFromReply-To、和 To 的格式都是 name-addr 或 addr-spec 加上參數,另外 name-addr 也用在 Record-RouteRoute。 name-addr 含有用 angle bracket 包起來的 addr-spec,所以 addr-spec 可以看成是 name-addr 的簡化,只有在沒有 display-name 且 addr-spec 沒有 「,」、「?」、「;」時使用。「;」為了跟信頭參數的區別。

name-addr    = [ display-name ] LAQUOT addr-spec RAQUOT
display-name = *(token LWS)/ quoted-string
addr-spec    = SIP-URI / SIPS-URI / absoluteURI

angle bracket 前後可有 LWS

參考

  1. wikipedia: Augmented_Backus-Naur_Form擴充巴科斯範式
  2. RFC3966 The tel URI for Telephone Numbers obsolete RFC2806 URLs for Telephone Calls

SIP header Via

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