我的雲端生活網 - Life+

Showing posts with label 微程式資訊股份有限公司. Show all posts
Showing posts with label 微程式資訊股份有限公司. Show all posts

Sunday, December 16, 2007

[微程式-技術研討會] 12月份研討會 主講人 ZNUL [XMPP RFC3920 10-~15章]

Xmpp Rfc3920 10-~15章 研討會報告

10. 伺服器處理XML節的規則 (Server Rules for Handling XML Stanzas)
相容的伺服器實做必須(MUST)確保兩個實體之間的XML節按次序處理. 除了按次序處理的需求之外, 每個伺服器實作將包含它自己的遞送樹"delivery tree"以處理它接收到的節.這個樹決定一個節是否需要路由到其他域, 在內部處理, 還是遞送到和一個已連接的節點相關的資源. 以下規則適用:
________________________________________
10.1. 沒有'to'地址 (No 'to' Address)
如果這個節沒有'to'屬性, 伺服器應該(SHOULD)為發送它的實體處理這個節. 因為所有從其他伺服器收到的節必須(MUST)擁有'to'屬性, 這個規則僅適用於從一個連接到這台伺服器的已註冊實體(如一個用戶端)收到的節,如果這個伺服器收到一個沒有'to'屬性的出席資訊節, 伺服器應該(SHOULD)向那些訂閱了這個發送實體的出席資訊的所有實體廣播它, 如果可能的話(即時消息和出席資訊應用程式中出席資訊廣播的語義定義在XMPP-IM). 如果伺服器接收到一個IQ類型為 "get" 或 "set" 且沒有'to'屬性的節並且它理解這個節的名字空間下的內容, 它必須(MUST)為這個發送實體處理節(在這裏"處理"的含義是由相關的名字空間的語義所決定的)或返回一個錯誤給發送實體.
#c to s 可以不用有 to 屬性 ,因為c to s 預設的 to 即是 server
#若是出席訊息<presence>沒有to屬性,即為廣播給所有訂閱者,rfc3921第五章說明如下:
(5.1.1初始化出席資訊 :
建立起一個會話之後, 一個用戶端應該(SHOULD)發送初始化出席資訊給伺服器來通知它的通信可用性.如這裏定義的, 初始化出席資訊節 (1) 必須(MUST) 不擁有'to'屬性(這表示它是由伺服器代替用戶端發送的廣播) 並且 (2) 必須(MUST) 不擁有'type'屬性).
________________________________________
10.2. 外部域 (Foreign Domain) (s to s)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身或其子域配置的主機名不匹配, 伺服器應該(SHOULD)路由這個節到外部域(取決於本地服務規定或安全策略關於域間通信的規定).有兩種可能的情況:
- 一個伺服器to伺服器之間的流已經存在於兩個域之間: 發送者的伺服器透過這個已存在的流為這個外部域路由(轉送)這個節到授權伺服器 - 兩個域之間沒有伺服器to伺服器之間的流: 發送者伺服器 (1) 解析這個外部域的主機名(定義在伺服器間的通信Server-to-Server Communications (第十四章第四節)), (2) 在兩個域之間進行伺服器到伺服器的流協商(定義在 Use of TLS (第五章) 和 Use of SASL (第六章)), 然後 (3) 通過這個新建的流為外部域路由(轉送)這個節到授權伺服器
如果路由(轉送)到接收者的伺服器不成功, 發送者的伺服器必須(MUST)返回一個錯誤給發送者; 如果接收者的伺服器聯繫上了但是從接收者的伺服器遞送到接收者不成功, 接收者伺服器必須(MUST)透過發送者的伺服器返回一個錯誤給發送者.
________________________________________
10.3. 子域 (Subdomain) (?)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名的一個子功能變數名稱匹配,伺服器必須(MUST)自己處理這個節或路由這個節到專門負責這個子域的特定服務(如果子域被配置了),或者返回一個錯誤給發送者(如果子域沒有配置).
________________________________________
10.4. 純粹的域或特定的資源 (Mere Domain or Specific Resource)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名本身匹配,並且'to'屬性中的JID類型是<domain> 或 <domain/resource>, 伺服器(或其中定義的資源)必須(MUST)根據節的類型適當的處理這個節或返回一個錯誤節給發送者.
________________________________________
10.5. 同一域中的節點 (Node in Same Domain)
如果'to'屬性中的JID的域ID部分的主機名和伺服器自身配置的主機名本身匹配,並且'to'屬性中的JID類型是<node@domain> 或 <node@domain/resource>, 伺服器應該(SHOULD)遞送這個節到'to'屬性中的JID所指明的預定的接收者. 以下規則適用:
1. 如果這個JID包含一個資源ID(例如, 格式是<node@domain/resource>)並且存在一個連接的資源符合這個全JID, 接收者伺服器應該(SHOULD)遞送這個節給正確符合這個資源ID的流或會話.
2. 如果這個JID包含一個資源ID(例如, 格式是<node@domain/resource>)並且不存在一個連接的資源符合這個全JID, 接收者伺服器應該(SHOULD)返回一個<service-unavailable/> 節錯誤給發送者.
3. 如果這個JID的格式是<node@domain>並且存在至少一個此節點的連接資源, 接收伺服器應該( SHOULD)遞送這個節給至少其中一個已連接的資源, 依據應用程式定義的規則(一系列即時消息和出席資訊應用程式的遞送規則定義在XMPP-IM).
@Rfc3921第11章 伺服器處理XML節的規則有詳細的說明如下:
如果JID的格式是<user@domain>並且這個用戶至少有一個可用的資源, 接收者的伺服器必須(MUST)遵守以下規則:
1. 對於消息(message)節, 伺服器應該(SHOULD)遞送這個節給高優先順序的可用資源(如果這個資源沒有提供<priority/>元素的值, 伺服器應該(SHOULD)認為它提供的值為零). 如果兩個或更多的可用資源有相同的優先順序, 伺服器可以(MAY)使用一些其他的規則(例如, 最近的連接時間, 最近的活動時間, 或由一些<show/>值的層次所定義的最高的可用性) 來從它們中間選擇,或可以(MAY)遞送這個消息到所有這些資源. 無論如何, 伺服器不能(MUST NOT)遞送這個節到一個優先順序為負數的可用資源; 如果唯一的一個可用資源的優先順序是負數, 伺服器應該(SHOULD)當成沒有可用資源一樣處理這個消息(定義在後面). 另外, 伺服器不能(MUST NOT)重寫'to'屬性(換言之, 它必須(MUST)讓它保持<user@domain>而不是改成<user@domain/resource>).
2. 對於類型不是"probe"(探測)的出席資訊節, 伺服器必須(MUST)遞送這個節給所有可用的資源;對於出席資訊調查, 伺服器應該(SHOULD)基於定義在 出席資訊調查Presence Probes (第五章第一節第三小節)的規則來應答. 另外, 伺服器不能(MUST NOT)重寫'to'屬性(換言之, 它必須(MUST)保持<user@domain>而不是改為<user@domain/resource>).
3. 對於IQ節, 伺服器本身必須(MUST)代替用戶應答一個IQ result或一個IQ error, 並且不能(MUST NOT)遞送這個IQ節給任何可用的資源. 具體來說, 如果合格的名字空間的語義定義了一個伺服器可以提供的應答, 伺服器必須(MUST)代替用戶應答這個節; 如果沒有, 伺服器必須(MUST)應答一個<service-unavailable/>節錯誤.
<presence from='juliet@example.com/balcony'>
<priority>13</priority> => whose value is an integer between -128 and +127. rfc3921 2.2.2.3
</presence>
<presence from='juliet@example.com/balcony'>
<show>away</show> => chat dnd xa rfc3921 2.2.2.1
</presence>
________________________________________

11. XMPP中的XML用法 (XML Usage within XMPP)
________________________________________
11.1. 限制 (Restrictions)
XMPP是一個簡單的流式XML元素的專用協定用於接近即時地交換結構化資訊. 因為XMPP不需要任意的解析和所有的XML文檔, 所以XMPP不需要支援[XML]的所有功能. 特殊的, 適用以下限制.
關於XML生成, 一個XMPP實作不能(MUST NOT)在XML流中注入以下任何東西:
o 注釋 (第二章第五節[XML]) ,如 <!--XXX-->
o 處理指令(第二章第六節 同上) , target content parent
o 內部或外部的 DTD 子集 (第二章第八節 同上)
o 內部或外部的實體參考 (第四章第二節 同上) 除了預定實體以外(第四章第六節 同上)
o 字元資料或屬性值包含和預定實體列表中吻合的未逸出的unescaped字元(第四章第六節 同上); 這些字元必須(MUST)逸出 ,如 & < > …
關於XML處理, 如果一個XMPP實現接收到這些受限的XML資料,它必須(MUST)忽略這些資料.
________________________________________




11.2. XML 命名空間的名字和前綴詞 (XML Namespace Names and Prefixes)
XML名字空間[XML-NAMES]為所有XMPP相容的XML建立資料所有權的嚴格界限. 這個名字空間的基本功能是把結構上混合在一起的XML元素區分出不同的辭彙. 確保XMPP相容的XML有名字空間的感知能力使得任何允許的XML可以被結構化的混合到任何XMPP資料元素中. XML名字空間的名字和首碼的規則在下一小節中.
________________________________________
11.2.1. 流命名空間 (Streams Namespace)
在所有的XML流頭中必須聲明一個流名字空間. 流名字空間必須(MUST)是 'http://etherx.jabber.org/streams'. 元素名<stream/>和它的<features/>和<error/>子元素必須(MUST)在所有實例中符合這個流名字空間首碼. 一個實作應該(SHOULD)只為這些元素生成'stream:'首碼, 並且由於歷史原因可以(MAY)只接受'stream:'首碼.
________________________________________
11.2.2. 預設命名空間 (Default Namespace)
在所有的XML流中必須聲明一個預設的流名字空間用於定義允許的流根元素的一級子元素. 這個名字空間聲明對於初始化流和應答流必須(MUST)是相同的使得雙方的流都是合格一致的. 預設的名字空間聲明適用於流和所有在流中發送的節(除非由流名字空間或回撥名字空間的首碼顯式的符合另一個名字空間).
一個伺服器實現必須(MUST)支持以下兩個預設名字空間(由於歷史原因, 一些實現可能(MAY)只支持這兩個預設名字空間):
o jabber:client -- 當流用於用戶端和伺服器的通信時聲明這個預設名字空間
o jabber:server -- 當流用於兩個伺服器間的通信時聲明這個預設名字空間
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>
一個用戶端實作必須(MUST)支持'jabber:client'預設名字空間,並且由於歷史原因可以(MAY)只支持這個預設名字空間.
如果預設名字空間是'jabber:client'或'jabber:server',一個實作不能(MUST NOT)在這個名字空間下為元素生成名字空間前綴詞. 一個實作不應該(SHOULD NOT)按照元素的內容(可能和流相反)生成不同於'jabber:client'和'jabber:server'名字空間前綴詞.
注意: 'jabber:client' 和 'jabber:server' 名字空間接近於相同但是用於不同的上下文(用戶端伺服器通信用'jabber:client' 而伺服器間通信用'jabber:server'). 這兩者之間僅有的不同在於在'jabber:client'中被發送的節中'to'和'from'屬性是可選的(OPTIONAL),而在'jabber:server'中被發送的節中它們是必需的(REQUIRED). 如果相容的實施接受一個符合'jabber:client'或'jabber:server'名字空間的流, 它必須(MUST)支援通用屬性(第九章第一節)和三個核心節類型(message, presence, 和IQ)的基本語義(第九章第二節).
________________________________________
11.2.3. 回撥名字空間 (Dialback Namespace)(?)
所有用於伺服器回撥的(第八章)元素都必須聲明一個回撥名字空間. 回撥名字空間的名字必須(MUST)是'jabber:server:dialback'. 所有符合此名字空間的元素必須(MUST)有首碼. 一個實現應該(SHOULD)只為這些元素生成'db:'首碼並且只可以(MAY)接受'db:'首碼.
________________________________________
11.3. 確認 (Validation)
除了注意'jabber:server'名字空間中關於節中'to'和'from'位址的規定,一個伺服器不需要為轉發到用戶端或其他伺服器負責檢查XML元素;一個實作可以(MAY)選擇僅提供有效資料元素但這是可選的(OPTIONAL). 用戶端不應該(SHOULD NOT)濫用發送不符合schema的資料的能力, 並且應該(SHOULD)忽略接收到的XML流中任何和schema不一致的元素或屬性值. XML流和節的有效性確認是可選的(OPTIONAL),並且在這裏提到的schemas僅用於描述的用途.
________________________________________
11.4. 文本聲明的包含 (Inclusion of Text Declaration)(?)
實現應該(SHOULD)在發送一個流標頭資訊之前發送一個文本聲明. 應用程式必須(MUST)遵守[XML]中關於環境(那裏對文本聲明做了規定)的規則.
________________________________________
11.5. 字元編碼 (Character Encoding)
Implementations MUST support the UTF-8 (RFC 3629 [UTF 8]) transformation of Universal Character Set (ISO/IEC 10646-1 [UCS2]) characters, as required by RFC 2277 [CHARSET]. Implementations MUST NOT attempt to use any other encoding.
實作必須(MUST)支援通用字元集Universal Character Set (ISO/IEC 10646-1 [UCS2])字元到UTF-8(RFC 3629 [UTF-8])的轉換, 必須符合 RFC 2277 [CHARSET]. 實作不能(MUST NOT)試圖使用任何其他的編碼.
@UTF-8為Unicode編碼的一種轉換格式,UCS2 為Unicode 雙字節編碼規範
________________________________________


12. 核心的相容性要求 (Core Compliance Requirements)
本章總結了可擴展的消息和出席資訊協定中的某些方面,為了實施的相容性,它們必須(MUST)被伺服器和用戶端支援,當然協定的其他方面也應該(SHOULD)被支持. 為了相容的目的, 我們在核心協議和即時消息協定之間劃了一個級別. 在本章中定義了所有伺服器和用戶端的相容性要求; 即時消息伺服器和用戶端的相容性要求在XMPP-IM的相關章節中定義.
________________________________________
12.1. 伺服器 (Servers)
除了所有已定義的關於安全, XML使用, 和國際化的要求之外, 一個伺服器還必須(MUST)支援以下核心協定以保證相容性:
o 在地址中應用[STRINGPREP] 的 [NAMEPREP], Nodeprep (附錄 A),和 Resourceprep (附錄 B) profiles (包括確保域ID是[IDNA]中定義的國際化功能變數名稱)
o XML流(第四章), 包括Use of TLS(第五章), Use of SASL(第六章), 和Resource Binding (第七章)
o 三個在stanza semantics(第九章第二節)中已定義的節類型(即,<message/>, <presence/>, 和<iq/>)的基本語義
o 生成錯誤的語法及相關的流, TLS, SASL, 和 XML節的語義
另外, 一個伺服器可以(MAY)支援以下核心協定:
o 伺服器回撥 (第八章)
@IDNA Internationalizing Domain Names in Applications => http://www.ietf.org/rfc/rfc3490.txt
為國際域名應用協定,將域名to ascii and to unicode的程序來達到國際化域名的應用
@STRINGPREP => rfc3454 http://www.ietf.org/rfc/rfc3454.txt
是字串辨識(比對)的標準協定,規範內容大概如下:
1. 字型的運用
2. 對於input and output字元的使用
3. 字串比對
4. unicode的標準化
5. 禁止的字元
6. 字串雙向性的問題
@NAMEPREP => rfc3491 http://www.ietf.org/rfc/rfc3491.txt
是使用在domain name system 上的協定
主要是儘可能將IDN在經過對照(Mapping)、正規化(Normalization)、禁止檢查(Prohibition)的處理後,得到一個符合IDN規格的形式。
________________________________________
12.2. 用戶端 (Clients)
一個用戶端必須(MUST)支援以下核心協定以滿足相容性:
o XML流(第四章), 包括Use of TLS(第五章), Use of SASL(第六章), 和Resource Binding (第七章)
o 三個在stanza semantics(第九章第二節)中已定義的節類型(即,<message/>, <presence/>, 和<iq/>)的基本語義
o 處理(並且, 如果可能, 生成) 錯誤的語法及相關的流, TLS, SASL, 和 XML節的語義
另外, 一個用戶端應該(SHOULD)支援以下核心協定:
o 地址的生成應用[STRINGPREP] 的 [NAMEPREP], Nodeprep (附錄 A),和 Resourceprep (附錄 B) profiles
________________________________________
13. 國際化事項 (Internationalization Considerations)
XML流在Character Encoding(第十一章第五節)中定義為必須(MUST)被編碼成UTF-8. 在Stream Attributes(第四章第四節)中特別定義了, 一個XML流應該(SHOULD)包含一個'xml:lang'屬性,它被認為是通過這個用於人類用戶解讀的流發送的任何XML字元資料的預設語言. 在 xml:lang (第九章第一節第五小節)特別定義了, 如果一個XML節是用來給人類用戶解讀,這個節應該(SHOULD)包含一個'xml:lang'屬性. 伺服器在為連接的實體路由或遞送節的時候應該(SHOULD)應用預設的'xml:lang'屬性, 並且不能(MUST NOT)修改或刪除它從其他實體收到的節的'xml:lang'屬性.
<message from='juliet@example.com' to='romeo@example.net' xml:lang='en'>
<body>Art thou not Romeo, and a Montague?</body>
</message> en 英語 zh華語 ja日語 …
________________________________________
14. 安全性事項 (Security Considerations)
________________________________________
14.1. 高安全性 (High Security)
為了XMPP通信的目的(用戶端-伺服器 和 伺服器-伺服器), "高安全性"條款談的是相互驗證和完整性檢查安全性技術的使用; 特別是, 當使用基於憑證的驗證來提供高安全性, 應該( SHOULD)建立一個帶外的信任鏈,儘管一個共用簽名憑證可能允許以前不知道的憑證在帶內建立信任關係. 參見以下第十四章第二節關於憑證確認程式. 實施必須(MUST)支持高安全性. 服務提供者應該(SHOULD)基於本地安全策略使用高安全性. ________________________________________
14.2. 憑證確認 (Certificate Validation) (?)
當一個XMPP點和另一個XMPP點安全的地通信, 它必須(MUST)確認對方終端的憑證.有三種可能的情況:
情形 #1: 點包含一個終端實體憑證,以根憑證的憑證鏈中一環出現(見[X509]中的第六章第一節).
情形 #2: 點的憑證由一個對方不知道的憑證授權.
情形 #3: 點的憑證由自己簽名.
在情形#1, 確認方必須(MUST)做以下兩點之一:
1. 根據[X509]的規則確認對方憑證.然後憑證應該(SHOULD)被對方接下來在[HTTP-TLS]中描述的規則反向確認預期的身份。但如果"xmpp"是subjectAltName擴展類型,則必須(MUST)使用憑證中的顯示的身份。如果這兩項檢查之一失敗,用戶導向的用戶端必須(MUST)通知用戶(用戶端可以(MAY)給用戶機會繼續連接)或以一個壞憑證的錯誤終止連接。自動用戶端應該(SHOULD)終止連接(以一個壞憑證錯誤)並在適當的日誌中記錄這個錯誤。自動用戶端可以(MAY)提供一個配置設置成禁止檢查,但同時必須(MUST)提供一個啟動檢查的配置。
2. 點應該(SHOULD)出示憑證給一個用戶用於批准,包括完整的憑證鏈.點必須(MUST)緩存這個憑證(或一些其他不會忘記的表達方式比如一個哈希值).在將來的連接中,點必須(MUST)展示相同的憑證並且如果改變了憑證必須(MUST)通知用戶.
在情形#2 和情形#3, 實現應該(SHOULD)執行上述第二條.
________________________________________
14.3. 用戶端-伺服器通信 (Client-to-Server Communications)
一個相容的用戶端實現必須(MUST)支持TLS和SASL用於連接到伺服器.
用於加密XML流的TLS協議(在 Use of TLS(第五章)定義)提供可信的機制幫助確保機密性和實體之間資料交換的完整性.
用於驗證XML流的SASL協定(在 Use of SASL(第六章)定義)提供可靠的機制用於確認一個連接到伺服器的用戶端確實是它自己所聲明的那個用戶端.
伺服器宣稱的DNS主機名被解析之前,用戶端-伺服器通信不能(MUST NOT)繼續進行。應該首先嘗試解析[SRV]記錄,其服務名為"xmpp-client",協議名為"tcp",整個資源記錄類似"_xmpp-client._tcp.example.com."(使用字元"xmpp-client"表示服務ID是經過IANA註冊).如果SRV查找失敗,退而求其次,將查找一個正規的IPv4/IPv6位址記錄來決定IP位址,使用"xmpp-client"埠5222,這個埠是在IANA註冊了的。
用戶端的IP位址和訪問方法不能(MUST NOT)被伺服器公開, 也不能被被任何原始伺服器之外的伺服器索取。這幫助保護用戶端的伺服器避免受到直接攻擊(譯者注:似乎應該是客戶避免受到直接攻擊,但原文如此)或被第三方知道它的身份。
@IANA => Internet Assigned Numbers Authority 網際網路號分配機構。負責對IP位址分配規劃以及對TCP/UDP公共服務的埠定義。
________________________________________
14.4. 伺服器-伺服器通信 (Server-to-Server Communications)
一個相容的伺服器實現必須(MUST)支持TLS和SASL,用於域間的通信.因為歷史原因,一個相容的實施也應該(SHOULD)支持伺服器回撥(第八章).
因為服務提供者是一個策略問題,對於任何給定域和其他域的通信中,它是可選的(OPTIONAL),伺服器之間的通信可以(MAY)被任何特定部署的管理員禁止。如果一個特殊的域允許域間的通信,它應該(SHOULD)允許高安全性。
管理員可能想在伺服器間使用SASL來通信,以確保雙方的驗證和保密性(比如在機構的私有網路).相容實施應該(SHOULD)為這個目的支援SASL.
伺服器宣稱的DNS主機名被解析之前,伺服器-伺服器通信不能(MUST NOT)繼續進行。應該首先嘗試解析[SRV]記錄,其服務名為"xmpp-server",協議名為"tcp",整個資源記錄類似"_xmpp-server._tcp.example.com."(使用字元"xmpp-server"表示服務ID是經過IANA註冊的,注意要用"xmpp-server"取代以前用的"jabber",因為以前的用法不符合[SRV]標準;希望保持向後相容的實現可以繼續查找或應答"jabber"服務ID).如果SRV查找失敗,退而求其次,將查找一個正規的IPv4/IPv6位址記錄來決定IP位址,使用"xmpp-server"埠5269,這個埠是在IANA註冊了的。
伺服器回撥防止域欺騙,從而使得偽造XML節更為困難.它和SASL和TLS不一樣,它不是一個用於驗證、安全或加密伺服器之間的流的機制, 所以只是伺服器身份的微弱確認而已。而且除非它使用了DNSSec [DNSSEC]否則它容易受到DNS中毒攻擊,即使DNS資訊是正確的,如果攻擊者劫持了遠程域,回撥也不能防止它的攻擊.需要健壯的安全性的域應該(SHOULD)使用TLS和SASL.如果伺服器間的驗證使用了SASL,回撥就不應該(SHOULD NOT)使用了,因為它是多餘的.
________________________________________
14.5. 層的次序 (Order of Layers)
協議中的層的次序必須(MUST)如下堆積:
1. TCP
2. TLS
3. SASL
4. XMPP
這個次序的原理是,[TCP]是基於連接的層,被所有使用,所以處於最上層, [TLS]經常是由作業系統層提供,[SASL]經常由應用程式層提供, XMPP則是應用程式本身.
________________________________________
14.6. 缺乏綁定到TLS的SASL通道 (Lack of SASL Channel Binding to TLS)(?)
SASL構架不提供一個機制來綁定SASL驗證到一個提供機密性和完整性保護的安全層。這一通道綁定"channel binding"的缺乏阻礙了SASL確認低層安全性所綁定的源和目標終端和SASL所驗證的結果是否一致。如果終端不一致, 低層安全性不能被信任用來保護SASL驗證的實體之間的資料傳輸。在這種情況下,一個SASL安全層進行握手的時候應該有效的忽略低層安全性的存在。
________________________________________
14.7. 強制實現的技術 (Mandatory-to-Implement Technologies)
最低要求, 所有實現必須(MUST)支持以下機制:
對於驗證: SASL [DIGEST-MD5] 機制
對於機密性: TLS (使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密碼)
對於兩者: TLS 加 SASL EXTERNAL(使用 TLS_RSA_WITH_3DES_EDE_CBC_SHA 密碼支援用戶端憑證)
________________________________________
14.8. 防火牆 (Firewalls)
使用XMPP通信通常是通過[TCP]連接到5222埠(用戶端-伺服器)或5269埠(伺服器-伺服器), 正如在IANA註冊的那樣(見 IANA Considerations (第十五章)). 使用這些廣為人知的埠允許管理員很容易的通過一般的防火牆來啟動或禁止XMPP活動.
________________________________________
14.9. 在SASL中使用base64
用戶端和伺服器都必須(MUST)確認在SASL協商中收到的任何[BASE64]資料. 一個實現必須(MUST)拒絕(不是忽略)任何非顯式允許base64字母的字串; 這有助於預防建立隱蔽通道洩漏資訊的行為。一個實現不能(MUST NOT)在非法輸入處中斷,如果那個('=')被包含在一些和最後的資料字元(如, "=AAA" or "BBBB=CCC")不同的東西裏面,必須(MUST)拒絕接下來的任何包含('=')的base64字元;這有助於防止對這個實現的緩存溢出攻擊和其他攻擊。Base 64編碼從外表看隱藏了容易辨認的資訊,例如密碼,但是不提供任何演算法機密性。Base 64編碼必須(MUST)按照RFC 3548[BASE64]第三章的定義執行。
________________________________________


14.10. Stringprep Profiles
為了處理域ID,XMPP使用了[STRINGPREP]中的[NAMEPREP] profile; 和Nameprep有關的安全性考慮, 參考[NAMEPREP]中的相關章節.
另外, XMPP 定義了兩個[STRINGPREP]的 profiles: 用於node identifiers的Nodeprep(附錄 A)和用於resource identifiers的Resourceprep(附錄 B).
Unicode 和 ISO/IEC 10646 集有許多字元看起來相似. 在許多時候, 安全協議的使用者可能看起來吻合,比如當比較信任的第三方的名字的時候. 因為沒有很多上下文的時候不可能映射看起來相似的字元,比如知道所用的字元集, stringprep不匹配相似字串,也不因為一些字串看起來像別的字串而禁止它們.
一個節點ID可能被作為一個實體的XMPP位址的一部分. 一個通常的用途是作為一個即時消息用戶的用戶名;另一個用途是作為一個多用途聊天室的名字; 很多其他種類的實體可能使用節點ID作為他們的位址的一部分。 這些服務的安全性可能會受到國際化節點ID的不同表達的威脅;例如, 一個用戶鍵入一個單獨的國際化的節點ID可能訪問了另一個用戶的帳號資訊, 或一個用戶可能獲得訪問一個受限的聊天室或服務的訪問許可權.
一個資源ID可能被作為一個實體的XMPP位址的一部分。一個通常的用戶是即時消息用戶所連接的資源(啟動的會話)的名字; 另一個是作為多用戶聊天室的某用戶的昵稱; 許多其他種類的實體可能使用資源ID作為他們位址的一部分.這些服務的安全性可能會受到國際化資源ID的不同表達的威脅;例如, 一個用戶可能嘗試以同一個名字初始化多個會話,或一個用戶可能發送一個消息給多用戶聊天室的一個人但實際上發給了另外一個人.
________________________________________
15. IANA 事項 (IANA Considerations)
________________________________________
15.1. 用於TLS資料的XML名字空間名
XMPP中用於TLS相關資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
@IETF =>internet enginner task force(負責網際網路標準研究及制定的組織)
URI: urn:ietf:params:xml:ns:xmpp-tls
________________________________________
15.2. 用於SASL資料的XML名字空間名
XMPP中用於SASL相關資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-sasl
<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'>
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
________________________________________
15.3. 用於流錯誤的XML名字空間名
XMPP中用於流相關錯誤的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-streams
<stream:error>
<xml-not-well-formed xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
</stream:error>
________________________________________
15.4. 用於資源綁定的XML名字空間名
XMPP中用於資源綁定的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-bind
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
________________________________________
15.5. 用於節錯誤的XML名字空間名
XMPP中用於節相關錯誤資料的 URN 子名字空間定義如下. (這個名字空間的名字遵守The IETF XML Registry [XML-REG]定義的格式.)
URI: urn:ietf:params:xml:ns:xmpp-stanzas
<stanza-kind to='sender' type='error'>
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'>OPTIONAL descriptive text</text>
</error>
</stanza-kind>
________________________________________
15.6. Nodeprep Profile of Stringprep
The Nodeprep profile of stringprep是在Nodeprep(附錄 A)定義的. IANA已經在stringprep profile registry中註冊了 Nodeprep.
________________________________________
15.7. Resourceprep Profile of Stringprep
The Resourceprep profile of stringprep是在Resourceprep(附錄 B)定義的. IANA已經在stringprep profile registry中註冊了Resourceprep.
________________________________________
15.8. GSSAPI 服務名
IANA已經註冊了 "xmpp" 作為一個 GSSAPI [GSS-API] 服務名, 在SASL Definition (第六章第三節)定義
@GSSAPI => Generic Security Services Application Programming Interface
通用安全服務應用程式程介面,它提供了一個通用的認證和安全訊息傳遞介面
http://www.faqs.org/rfcs/rfc2743.html
________________________________________
15.9. 埠號
IANA已經註冊了"xmpp-client" 和 "xmpp-server" 作為[TCP]埠號5222和5269的關鍵字.
這些埠應該(SHOULD)用於用戶端-伺服器 和 伺服器-伺服器通信,但它們的使用是可選的(OPTIONAL).
________________________________________

參考資料:

Punycode => http://www.ietf.org/rfc/rfc3492.txt
http://xn--fx5a34a.xn--fiqp7jnrek3iomgb4cbweev5d.tw/IDN.pdf
http://hi.baidu.com/jabber/blog/category/Jep
http://wiki.jabbercn.org/space/start

Wednesday, October 31, 2007

[微程式-技術研討會] 10月份研討會內容 主講人 vivian

1. 繼續分享xmpp的討會
3.5 地址的確認

在SASL(見第六章)握手之後(如果必要的話,也在資料綁定(見第七章)之後,正在接收信息的實體必須(MUST)確認初始實體的ID

對於服務器間的通信,在SASL握手時,如果沒有指明授權的ID,這個初始的實體應該(SHOULD)是經過認證實體(參見簡單認證和安全層協議[SASL]中的定義)授權的ID(見第六章)

對於客戶端和服務器的通信, 在SASL握手時, 如果沒有指明授權的ID, “純JID” (<node@domain>)應該(SHOULD)是經過認證實體(參見[SASL]中的定義)授權的ID, “全JID”(<node@domain/resource>)的資源ID部份應該(SHOULD)是由客戶端和服務器在資源綁定的時候商定的(參見第七章)

4.1 XML流 / XML節概覽

XML流(XML Stream)的定義: 一個XML流乃是一個容器, 包含了2個實體之間通過網絡交換XML元素, 一個XML流乃由一個<stream>標籤開始的(該標籤需包含適當的屬性及名字空間聲明), XML流的結束則是由</stream>標籤做為結束, 在XML流的整個生命週期中, 初始化它的實體可以通過流來發送大量的XML元素, 例如:TLS協議(第5章),SASL協議(第6章)或XML節(在這裡指的是符合預設名字空間的元素, 包括<message/>,<presence/>,<iq/>元素), “初始的XML流"由初始實體(通常是一個客戶端或服務器)和接收實體(通常為一個服務器)協議, 從接收實體來看, XML流就是那個初始實體對接收實體的 “會話”, 接收實體則必需回覆一個相同的應答流給初始實體
Ex:
<stream> è xml流開始
……………………………….
……………………………….
</stream> è xml流結束
XML節(XML Stanzas)的定義 : 一個XML節是一個實體通過XML流向另一個實體發送結構化信息中的一個離散語意單位, 一個XML節乃直接存於根元素<stream/>之下, 也就是說任何XML都是從一個XML流的下一級的某個OPEN標籤(如: <presence>)開始的, 並相對應到其CLOSE標籤(如: </presence>)做為結束, 一個XML節可以包含子元素(例如: 屬性, 元素, XML字符…..等資料)以表達整個完整的信息, 然而在定義的XML只限定於<message/>,</presence>,</iq>這3個元素, 其TLS / SASL / 服務器回撥所需發送的XML元素, 則不被視為一個XML節
Ex:
<stream> è xml流開始
………. è TLS協議 (可省略)
………. è SASL協議
<presence> è xml節開始
<show/> è xml節子元素
</presence> è xml節結束
<message> è xml節開始
<body/> è xml節子元素
</message> è xml節結束
……………………………….
……………………………….
</stream> è xml流結束

XML流與XML節圖示
---------------------------- <stream> ---------------------------- <presence> <show/> </presence> ---------------------------- <message to='foo'> <body/> </message> ---------------------------- <iq to='bar'> <query/> </iq> ---------------------------- … ---------------------------- </stream> ----------------------------
4.3 流的安全

在XMPP 1.0中, 對於流的安全性可使用TLS及SASL已做為初始實體(發送初始化流 Send Default XML Stream)與接收實體(發送應答流 Response XML Stream)已做為安全傳送機制, 若XML流在被真實驗證之前, 實體不該發送任何XML節(XML Stanza), 即使當一方於流被驗證之前發送了XML節, 另一方實體則不能接受這些節的傳入, 應該返回一個<not-authorized/>的錯誤訊息及終止當前雙方TCP連結的XML流

4.4 XML流(XML Stream)的屬性
屬性 初始實體(A) à 接收實體(B) 接收實體(B) à 初始實體(A)
to 接收實體(B)的主機名稱 可忽略
from 可省略 接收實體(B)的主機名稱
id 可省略 協議key值
xml:lang 預設語言 預設語言
version xmpp 1.0 xmpp 1.0
初始實體(A)可以為客戶端或伺服器端(Client à Server Or Server à Server) 初始實體(A) è 接收實體(B) <stream:stream
xmlns='jabber:client' Or xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>接收實體(B) è 初始實體(A) <stream:stream
xmlns='jabber:client' Or xmlns='jabber:server'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123' à 協議key值
from='B.Server.com'
version='1.0'>
5.1 TLS的使用概覽
XMPP包含了一個可讓XML流被防止篡改及偷聽的安全方法, 類似SSL的觀念
TLS使用原則需在SASL使用之前被使用, TLS可以在2個網域之間確保通信之間的安全, 其TLS使用方式步驟如下(初始實體[可以為客戶端(Client)或伺服器端(Server)]稱呼為 A, 接收實體[伺服器端(Server)]稱呼為 B)

1 . A透過TCP連接, 發送一OPEN之XML流信息(需包含版本這個屬性)給B【Client à Server】 <stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>
2. B也透過TCP連接, 發送一個XML流信息(需包含版本這個屬性)給A【Server à Client】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_123' Or id='s2s_123'
from='B.Server.com'
version='1.0'>
3. B向A提議STARTTLS的範圍(包含version屬性), 包含驗證機制及其它流特性【Server à Client】<stream:features>
<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'> è TLS協議
<required/>
</starttls>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'> è SASL協議
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
4. A發出STARTTLS協議以通知B, 希望開始啟用 TLS保護XML流(XML Stream)
【Client à Server】<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>

5. B發出<proceed/>或<failure/>元素做為回應, 回應<failure/>元素者終止XML流及TCP連接
【Server à Client】<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
OR <failure xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
</stream:stream>
6. TLS協議成功, 則A需重新發送一個新OPEN的XML流信息給B(不需先行發送一個</stream>, 因為A與B必需確保原來的流在TLS協議成功後才被關閉)
【Client à Server】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:Server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
to='B.Server.com'
version='1.0'>
7. B由A接收到一個新的XML流, 也需重新發送一個新的XML流給A以做為應答, 其重新應答可包含可用特性但不可包含STARTTLS特性【Server à Client】<stream:stream
xmlns='jabber:client' 客戶端 ßà 服務器 Or xmlns='jabber:Server' 服務器 ßà 服務器
xmlns:stream='http://etherx.jabber.org/streams'
from='example.com'
id='c2s_234' Or id='s2s_234'
version='1.0'>
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
<mechanism>EXTERNAL</mechanism>
</mechanisms>
</stream:features>
6.1 SASL概覽
XMPP提供一個可以驗證XML流(XML Stream)的方法, SASL(簡單驗證安全層), 需
注意的是SASL協議時, 在XML元素中所使用的任何資料皆需被編碼成BASE64(參考RFC3548第3章), 若在使用SASL驗證機制之前明訂需使用TLS,則接收實體不可在TLS協議之前提供可用的SASL驗證清單

7. 資源綁定
初始實體(A)在與和接收實體(B)完成SASL協議之後, 若初始實體(A)想要或需要綁定一個特定的資源到XML流上, 就需採用資源綁定協議, 而資源綁定協議只適用於 [客戶端] (初始實體(A)可以為客戶端或為伺服器), 客戶端必需擁有一個相關資源ID(可由接收實體(B)或初始實體(A)程序提供), 而在XML流上的地址是一個 [全JID] (<node@domain/resource>), 在SASL協議成功後接收實體(B)需回應一個新XML流(XML Stream), 接收實體(B)若需初始實體(A)綁定一個資源, 必需在新的XML流中包含一個空的<bind/>元素 接收實體(B) è 初始實體(A), B要求A需做binding resource機制 <stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_345' from='B.Server.com' version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
</stream:features>
初始實體(A)收到接收實體(B)發送的bind通知後, 初始實體(A)需發送一個 “set” 類型的IQ節(<iq/>)給接收實體(B)來綁定一個資源到xml流中

(A) . 初始實體(A)希望接收實體(B)生成一個資源ID, 則初始實體(A)可發送一個空的<bind/>元素的 “set” 類型IQ節(<iq/>) Client à Server <iq type='set' id='bind_1'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/> è 初始實體(A)希望由接收實體(B)自行生一
個資源ID, 所以初始實體(A)送出一個空的bind元素
</iq>
(B) . 初始實體(A)自行指定資源ID, 則初始實體(A)可發送包含期望資源ID的 “set” 類型IQ節(<iq/>) Client à Server <iq type='set' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource> è 初始實體(A)自行指定期望綁定資源
</bind>
</iq>
接收實體(B)可接受初始實體(A)所提供的資源ID, 但接收實體(B)也可生成其資源ID去覆蓋它, 而在這種情況下, 接收實體(B)不可返回一個錯誤訊息給初始實體(A), 而需把其生成資源ID透過IQ節 “result” 類型返回給客戶端

當初始實體(A)自行提供綁定資源ID時, 可能會發生以下錯誤情況
1. 初始實體(A)所提供的資源ID, 接收實體(B)無法處理(例如:不符合資源字符規範) Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='modify'>
<bad-request xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
2. 初始實體(A)是不被允許綁定一個資源 Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<not-allowed xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
3. 初始實體(A)所提供的資源ID已被使用(初始實體(A)不允許同一個資源ID綁定多個連結) Server à Client <iq type='error' id='bind_2'>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
<resource>someresource</resource>
</bind>
<error type='cancel'>
<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
</error>
</iq>
9. XML節(STANZAS)
在通過TLS,SASL,BIND之後, 就可發送XML節, 在 ‘jabber:client’ 和 ‘jabber:server’命名空間中定義了3種xml節(<message/>,<presence/>,<iq/>)而這3種xml節包含了5種型態通用屬性(to、from、id、type、xml:lang)

9.2.1 信(訊)息節(<message/>)
<message/>節類型可以被視為一個”push”機制, 運用於一個發送實體發送信息給一個接收實體(例如: email中的送信), <message/>節需明定一個信息接收者屬性(to), 一個<message/>節中的 “type” 屬性是被建議的, 如果包含了 “type” 屬性它指明這個信息的會話上下文, 其 “type” 屬性必需是以下值之一 (chat, error, groupchat, headline, normal), 其type屬性說明了這個信息的類型, 一個接收端接收了一個沒有type屬性的信息, 則需將該message視為normal(normal為預設值), 一個<message/>節可以包含任何適當的命名空間的子元素, 但若<message/>節是屬於type=error類型的其子元素必需包含一個<error/>子元素, <message/>節可以包含以下子元素任何一種並且無需聲明命名空間

屬性


to
指明該信息要發送給哪一個接收實體
必要的
from


id


type
指明該信息的訊息類型(chat, error, groupchat, headline, normal)
1. 傳遞內容未包含以noraml代替
2. type=error需包含<error/>子元素
可省略
xml:lang



1. <subject/>子元素(該元素不需聲明命名空間)
Subject(信(訊)息主題)子元素包含了人可讀取的xml字符資料, 其用於指明這個信息的主題, 該子元素不可有任何屬性(但xml:lang除外), subject子元素可運用xml:lang屬性將信息主題以各種不同語言版本呈現, 但每個subject子元素xml:lang屬性值需互不相同才可以
2. <body/>子元素(該元素不需聲明命名空間)
Body(信息內容)子元素同樣也屬於人可讀取的xml字符資料, 其子元素用於表達該信(訊)息的內容, 該子元素不可有任何屬性(但xml:lang除外), body子元素可運用xml:lang屬性將信息內容以各種不同語言版本呈現, 但每個body子元素xml:lang屬性值需互不相同才可以
3. <thread>
Thread(信(訊)息追踪線索)子元素為人無法判讀的xml字符資料, 用於追踪2個實體間的會話線索

子元素
xml字符資料
屬性
資料內容
說明
subject
可被人判讀
不可有屬性(xml:lang除外)
於<message/>節可有1~N個
必需
body
可被人判讀
不可有屬性(xml:lang除外)
於<message/>節可有1~N個
必需
thread
不可被判讀
不可有屬性

必需

9.2.2 出席信(訊)息節(<presence/>)
<presence/>節可以被視為一個廣播或出版訂閱機制, 用於多個實體接收某個已訂閱實體的信息, 通常一個發送實體不應該包含 “to” 屬性來發送一個出席信息節, 而該發送實體所連接的服務器應該廣播給那些有訂閱該發送實體當前的網路可用性(例如: 離線, 線上, 離開…..等等)的其它發送實體, <presence/>節的 “type”屬性是可被選擇性使用的(未包含type屬性的出席信(訊)息節<presence/>表示發送端已在線上並可進行通信), 其<presence/>節 “type”屬性值可包含如(unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error), 一個<presence/>節可以包含任何適當命名空間的子元素, 如果<presence/>節的type=error, 必需包含一個<error/>子元素, 一個<presence/>節若沒有包含 “type” 屬性的話, 它可以包含以下任何子元素
屬性


to

不必要
from


id


type
指明該信息的訊息類型(unavailable, subscribe, subscribed, unsubscribe, unsubscribed, probe, error)
1. 傳遞內容未包含視為已在線上並可進行通信, 及可包含子元素
2. type=error需包含<error/>子元素
可省略
xml:lang



1. <show/>
該子元素是選擇性的, 該子元素所包含的xml資料不可供人所閱讀, 該子元素所要表達的是一個實體或資源的可用性狀態, 一個<presence/>節只可包含一個<show/>子元素, 而該子元素不可擁有任何屬性, 其子元素的xml資料內容可使用以下說明中之一項(away、chat、dnd、xa), 若<presence/>節沒有包含<show/>子元素則該實體的狀態被視為 “在線上” 或 “可使用”
2. <status/>
該子元素是選擇性的, 其元素的xml資料乃用來表達<show/>子元素可用性更詳細的描述說明(例如: 會議中), 而<status/>子元素也不可擁有任何屬性, 但除了xml:lang除外
3. <priority/>
該子元素是選擇性的, 該子元素的xml資料不可被人所閱讀, 其用來指明資源的優先權級別, 該值需介於-128 ~ 127之間, 一個<presence/>節只可有一個<priority/>子元素, 而該子元素也不可擁有任何屬性, 若該子元素未被提供則其優先權級別視為0

子元素
xml字符資料
屬性
資料內容
說明
show
不可被判讀
不可有屬性
away、chat、dnd、xa
於<presence/>節只可有1個
選擇性
未提供以在線上或可使用替代
status
可被人判讀
不可有屬性(xml:lang除外)
於<presence/>節可有1~N個
選擇性
priority
不可被判讀
不可有屬性
於<presence/>節只可有1個
選擇性
未提供以0替代


9.2.3 IQ節(<iq/>)
<iq/>節是一個信息請求/查詢回應(Inof/Query)的一個機制, 類似http, <iq/>節使一個實體(A)向另一個實體(B)做出請求, (B)實體回應(A)實體結果, 請求和應答的資料是被定義在一個直的子元素命名空間聲名中, 並且由請求實體用 “id”屬性來做為跟踪彼此交互行為, IQ交互乃伴隨著一個結構化的資料交換通用模式, 例如: get/result(error) 或 set/result(error)
執行iq節, 需應用以下規則
1. <iq/>節中的 “id” 屬性是必需的
2. <iq/>節中的 “type” 屬性是必需的, 其屬性只可為以下內容之一項
甲、get – 表示這個<iq/>節是一個對信息或需求的請求
乙、set – 表示這個<iq/>節提供資料, 用於設置新的值, 或取代現有的值
丙、result – 表示對這個<iq/>節的請求(get)或提供資料(set), 所給予的應答
丁、error – 應答發生錯誤, 表示對這個<iq/>節的請求(get)或提供資料(set), 所給予的錯誤應答
3. 一個實體接收到 “get” 或 “set” 類型的<iq/>節, 該實體必需回應一個 “result “ 或 “error” 類型的<iq/>節, 以做為回應, 其回應的<iq/>節其 “id”屬性需與請求(get)或提供資料(set)的<iq/>節一致
4. 一個實體接收到 “result” 或 “error” 類型的<iq/>節, 不可發發送同樣的“result” 或 “error” 類型的<iq/>節做為應答
5. 一個 “get” or “set”類型的<iq/>節必需包含一個子元素以做為指明請求或提供資料的資料來源
6. 一個 “result” 類型的<iq/>節必需包含零或一個子元素做為指明回應的資料來源
7. 一個 “error” 類型的<iq/>節必需包含當初 “get” or “set”類型<iq/>節所傳送的子元素及一個<error/>子元素以做為回應

9.3 xml節的錯誤
節錯誤的處理方式類似xml流的錯誤, 但節(stanzas)錯誤是可被恢復的, 所以節錯誤也包含了用來暗示原來發送者可用什麼方式來補求節錯誤的方法

節(stanzas)錯誤的規則
1. 接收或處理實體接收到一個節錯誤時應該返回相同類型的節給發送實體(需回應相同類型節的type屬性值需要設置為 “error”
2. 接收或處理實體返回相同類型節給發送實體時, 需包含原發送的xml資料內容, 這樣可以讓發送實體去檢查錯誤的原因
3. 返回一個相同類型的節需包含<error/>子元素
4. 如果返回一個相同類型的節type屬性不為 “error” 則不可包含<error/>子元素
<stanza-kind to='sender' type='error'>
[RECOMMENDED to include sender XML here]
<error type='error-type'>
<defined-condition xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
<text xmlns='urn:ietf:params:xml:ns:xmpp-stanzas' xml:lang='langcode'>
OPTIONAL descriptive text
</text>
[OPTIONAL application-specific condition element]
</error>
</stanza-kind>
stanza – kind如<message/>, <presence/>, <iq/>節
error – type可包含如下值之一 (cancel, continue, modify, auth, wait)
defined-condition – <bad-request/>, <conflict/>, <feature-not-implemented/>,……
<unexpected-request/>等(可參考RFC-3920中的9.3.3已定義的條件)


2. 清算運用之前研討會分享作法實作
1.如何將perl 模組安裝到私有的目錄(luke於2006/11/15分享)
目前電腦教室及清算系統都將系統會使用到的模組的source code及install分別安裝至特定目錄位置, 讓se在安裝系統時可以把系統整個tar過去及解tar後就可執行installer的安裝過程
原始分享內容截錄
A.解開perl 模組(http://www.cpan.org/)
tar zxvf mmm.tgz
perl Makefile.PL PREFIX=/usr/local/Portal/perlmods LIB=/usr/local/Portal/perlmods
make
make install

B.程式裡的模組叫用方式
一. unshift(@INC,'/usr/local/Portal/perlmods');
二. use lib '/usr/local/Portal/perlmods' ;

2.如何替perl開發的軟體撰寫installer (luke於2006/11/15分享)
電腦教室及清算系統installer的內容大都是對系統會使用到的設定檔(conf file)及建置資料庫及匯入資料至資料……等一些預設性的工作所做的編寫, se在執行完installer後即可使用該系統, 不用再花費更多人力去建置一個系統所需預設的工作

3.upgrade 系統設定及運作原理 (luke於2006/11/15分享)
卡務,電腦教室及清算系統目前皆是採用luke提供的upgrade system做為程式bug修正及版本更新的傳遞upgrade管道, 只需把已修正過程式更新至server端的upgrade目錄下,即可透過upgrade程式將server端已修正的程式自動更新至client端
原始分享內容截錄
#要做簽章的起始目錄
computer_initdir: /usr/local/computer_pkg20060704_v1
computer_exclude: [dir]storage
computer_exclude: [dir]sync
computer_exclude: [dir]upgrade
computer_exclude: [dir]WOL
computer_exclude: [dir]conf
computer_exclude: [dir]temp
computer_exclude: [dir]test
computer_exclude: [dir]backup
computer_exclude: [dir]tmp

#額外需要做簽章的檔案(需要填實際的位置)
#iniDB目錄下的檔案不做upgrade處理, 另開發3支mysql檔案需做額外簽章
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/altertbl.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/dropdb.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/iniDB/addsshtbl.mysql
computer_additional: /usr/local/computer_pkg20060704_v1/html/conf/action.conf

#執行指令
computer_cmds: /bin/chmod -R 750 /usr/local/computer/image;/bin/chown -R computer:computer /usr/local/computer/image
computer_cmds: /bin/chmod 750 /usr/local/computer/iniDB/altertbl.mysql;/bin/chmod 750 /usr/local/computer/iniDB/dropdb.mysql;/bin/chmod 750 /usr/local/computer/iniDB/addsshtbl.mysql
computer_cmds: /bin/chmod 750 /usr/local/computer/tools/addtbl.pl;
………………………………………………………………
………………………………………………………………
………………………………………………………………
#要做簽章的起始目錄
computerv2_initdir: /usr/local/computer_pkg20070302_v2

#[file] 檔案包含xx 不做簽章 [dir]目錄名稱包含yy 不做簽章
computerv2_exclude: [file].md5
computerv2_exclude: [file].bak
computerv2_exclude: [file].gz
computerv2_exclude: [file].cf
computerv2_exclude: [file].db
………………………………………………………………
………………………………………………………………
………………………………………………………………

4.Data::Dumper 的使用 (luke於2007/01/18分享)
在之前的卡務及電腦教室對於設定檔的資料, 皆是以share memory方式做為程式讀設定檔的方式, 而清算系統則是改採Data::Dumper做為設定檔讀取方式, 只要將設定檔格式先行轉換成hash(雜湊函數)方式存放於另一個檔案中, 即可以perl中以hash方式叫用設定檔內容
原始分享內容截錄
四.Data::Dumper 的使用

A.Data::Dumper 並非perl內建模組,請自行使用cpan 安裝,或是下載src回來後自行安裝

B.Data::Dumper 主要的用途是把資料結構轉換成檔案結構,反之亦然

C.
#exam3.pl
#!/usr/bin/perl
use Data::Dumper;
my %conf;
open(my $HANDLE,"system.cf");
while(<$HANDLE>){
$_=~tr/\r\n//d;
if ($_ eq ''){next;}
my ($p,$v)=split(': ',$_);
$conf{uc($p)}=$v;
}
close($HANDLE);
open(my $HANDLE2,">system.cache");
$Data::Dumper::Terse = 1;
print $HANDLE2 Dumper(\%conf);
close($HANDLE2);

#exam4.pl
#!/usr/bin/perl
use Data::Dumper;
my $conf;
my $code='';
{
local $/=undef;
open(my $HANDLE2,"system.cache");
my $cache=<$HANDLE2>;
close($HANDLE2);
$code='$conf=' . $cache;
}
print "=======my code========\n";
print $code;
print "=======================\n";
eval "$code";
foreach my $k(keys %{$conf}){
print "$k=>" . $conf->{$k}. "\n";
}

5.樣板的使用 (luke於2007/01/18分享)
在卡務及電腦教室並沒有所謂樣板的觀念在使用, 往往對於html皆是撰寫於程式中, 所以一旦畫面格式要更動修改, 皆需由rd自行修正, 容易造成rd要花多餘的時間來做這件事, 所以於清算系統則採用樣板模式, rd只需產生樣板所需的資料後套用至樣板中即可使用, 而清算所使用的方式乃是用xml及xsl做配搭, 由製作頁面的人員施作xsl, 由rd產生xml去配搭所對應的xsl再轉換成html即可將畫面顯示在web上, 一旦畫面格式有異動只需請頁面製作人員修正頁面, 若是異動(新增或刪除)部份資料, 則由rd去修正相對應的xml再告知頁面製作人員修正即可, 這樣比較有所謂的分工的觀念在裡面
目前清算系統部份取代方式乃是使用的是取代變數中的方法一
原始分享內容截錄
b.取代變數的做法

方法論一.
Step 1. 首先,我們把程式與網頁分開

參考範例:實際上的目錄規劃我們在上次的研討會提過,應該是
/usr/local/Product_Name/Function_Type

程式/網頁/設定檔
虛擬目錄
實體目錄
exam6.pl
/octopus/html/test/cgi-bin
/usr/local/octopus/html/test/cgi-bin
myhtml.htm

/usr/local/octopus/html/test/templet
system.cf

/usr/local/octopus/html/test/conf

Step 2. 使用架構去讀取外部網頁
Step 3. 使用perl 的強項regular expression 把變數做替換

#exam6.pl
#http://tcmail.program.com.tw/octopus/test/cgi-bin/exam6.pl?src=myhtml.htm
#!/usr/bin/perl
use strict;
my $buffer = $ENV{QUERY_STRING};
my %IN;
my @nv_pairs = split( /\&/, $buffer );
foreach my $nvp ( 0 .. $#nv_pairs )
{
$nv_pairs[$nvp] =~ tr/+/ /;
my ( $key, $keyword ) = split( /=/, $nv_pairs[$nvp], 2 );
$key =~ s#%(..)#pack("c",hex($1))#ge;
$key =~ tr/[A-Z]/[a-z]/;
$keyword =~ s/%(?:([0-9a-fA-F]{2})u([0-9a-fA-F]{4}))/defined($1)? chr hex($1) : chr hex($2)/ge;
$IN{$key} .= "\0" if ( defined( $IN{$key} ) );
$keyword =~ s/\`\ \"\'\>\<//gs;
$IN{$key} .= $keyword;
}

my %varhash;
$varhash{UID}='luke';
$varhash{PASSWD}='lukePASSWD';
my $htmlstr='';
{
local $/=undef;
open (my $HANDLE,"/usr/local/octopus/html/test/templet/" . $IN{src});
$htmlstr=<$HANDLE>;
close($HANDLE);
}

$htmlstr =~ s/\$([A-Z]+)/
my $value = $varhash{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;

print "Content-Type: text/html; charset=big5\r\n\r\n";
print $htmlstr ;

#myhtml.htm
<html>
<body>
這樣好多了,不是嗎? 我的變數不會跟程式碼混在一起,<br>
而且當網頁要修改時,我們不需要大費周章把程式碼翻<br>
出來,而且你看, 我這邊以一樣可以使用取代的方式讓靜<br>
態的網頁呈現動態的資訊<br><br>

比如:變數 UID 我可以置換成$UID <br>
比如:變數 PASSWD 我可以置換成$PASSWD <br>
請注意我沒有這個變數 $NOVAR 的值<br><br>
真好,不是嗎,但當我有邏輯要在網頁運行時怎麼辦??<br>
</body>
</html>

方法論二.
將程式與設定分離,使用動態的CACHE/CONFIG 來呈現樣式

#exam7.pl
#http://tcmail.program.com.tw/octopus/test/cgi-bin/exam7.pl?src=myhtml.htm
#!/usr/bin/perl
use strict;
my $buffer = $ENV{QUERY_STRING};
my %IN;
my @nv_pairs = split( /\&/, $buffer );
foreach my $nvp ( 0 .. $#nv_pairs )
{
$nv_pairs[$nvp] =~ tr/+/ /;
my ( $key, $keyword ) = split( /=/, $nv_pairs[$nvp], 2 );
$key =~ s#%(..)#pack("c",hex($1))#ge;
$key =~ tr/[A-Z]/[a-z]/;
$keyword =~ s/%(?:([0-9a-fA-F]{2})u([0-9a-fA-F]{4}))/defined($1)? chr hex($1) : chr hex($2)/ge;
$IN{$key} .= "\0" if ( defined( $IN{$key} ) );
$keyword =~ s/\`\ \"\'\>\<//gs;
$IN{$key} .= $keyword;
}

my %varhash;
$varhash{UID}='luke';
$varhash{PASSWD}='lukePASSWD';
$varhash{EXISTS}='已經有';
my $htmlstr='';
{
local $/=undef;
open (my $HANDLE,"/usr/local/octopus/html/test/templet/" . $IN{src});
$htmlstr=<$HANDLE>;
close($HANDLE);
}

$htmlstr =~ s/\$([A-Z]+)/
my $value = $varhash{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;

my %conf;
open(my $HANDLE,"/usr/local/octopus/html/test/conf/system.cf");
while(<$HANDLE>){

$_=~tr/\r\n//d;
i f ($_ eq ''){next;}
my ($p,$v)=split(': ',$_);

print "$p\t$v";
$conf{uc($p)}=$v;
}
close($HANDLE);

$htmlstr =~ s/\$([A-Z]+)/
my $value = $conf{$1};
if(!defined $value) {
$value = "\$$1"; # leave it as is
}
$value;
/ge;


print "Content-Type: text/html; charset=big5\r\n\r\n";
print $htmlstr ;

清算xml樣板套用方式 (standard.xml)
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="http://se6.program.com.tw/liquxsl/$APNAME0"?>
<liquidate>
<info>
<apname>$APNAME</apname>
<title>$TITLE</title>
<splitchk>$SPLITCHK</splitchk>
<nowpage>$NOWPAGE</nowpage>
<totalpage>$TOTALPAGE</totalpage>
<rows>$ROWS</rows>
<host>$HOST</host>
<action>$ACTION</action>
<src>$SRC</src>
<backaction>$BACKACTION</backaction>
<backsrc>$BACKSRC</backsrc>
</info>
<data>
$XMLRECORDSET
</data>
</liquidate>

6.清算對於json的運用
清算對於json的運用乃運用在角色及權限上, 將各個角色轉換成json模式存放, 再將該json檔案付予使用這個角色的權限, 並透過讀取json檔案的程式將內容讀取出來, 已做為程式在top及left的functions的顯示
清算json存放模式
Top function json檔案內容
var func0 = [
{
funcacid: '1',
funcadesc: '系統管理'
},
{
funcacid: '2',
funcadesc: '資料管理'
},
{
funcacid: '4',
funcadesc: '清算管理'
},
{
funcacid: '8',
funcadesc: '報表管理'
},
{
funcacid: '16',
funcadesc: '核銷帳務管理'
},
{
funcacid: '32',
funcadesc: '資料查詢管理'
},
];


Left function json檔案內容
var func1 = [
{
rank: '41',
funcdesc: '管理角色定義',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=roleslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
{
rank: '42',
funcdesc: '管理權限設定',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=managerslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
{
rank: '43',
funcdesc: 'IP存取設定',
rightpage: 'http://se6.program.com.tw/liquidate/parserhtml.pl?src=blackipslist.htm',
funcdescparent: '系統管理',
displaytype: '1'
},
];
讀取json的html檔案
Top Functions html原始檔案
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上頁框主功能頁</title>
<link href="../../liqu_image/css/top.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="$URL"></script>
<script type="text/javascript" src="../../liqu_image/js/frameName.js"></script>
<script type="text/javascript" src="../../liqu_image/js/topjsondata.js"></script>
<script type="text/javascript">
<!--
function initPage(){
createFun($VARIABLE);
}

window.onload = initPage;
//-->
</script>
</head>

<body>
<div class="bg01" align="center">
<div class="bgarea">
<div id="funArea" class="funArea"> </div>
</div>
</div>
<div class="locName">您現在位置:<span id="itemName"> </span></div>
</body>
</html>

Top Functions html web顯示內容
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>上頁框主功能頁</title>
<link href="../../liqu_image/css/top.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://se6.program.com.tw/liquidate/getjsondata.pl?type=eA9t"></script>
<script type="text/javascript" src="../../liqu_image/js/frameName.js"></script>
<script type="text/javascript" src="../../liqu_image/js/topjsondata.js"></script>
<script type="text/javascript">
<!--
function initPage(){
createFun(func0);
}

window.onload = initPage;
//-->
</script>
</head>

<body>
<div class="bg01" align="center">
<div class="bgarea">
<div id="funArea" class="funArea"> </div>
</div>
</div>
<div class="locName">您現在位置:<span id="itemName"> </span></div>
</body>
</html>


Monday, September 3, 2007

[微程式-技術研討會]xmpp(rfc-3920) 導讀

XMPP協定導讀


一. 什麼是jabber? 什麼是xmpp?

The Extensible Messaging and Presence Protocol (XMPP) is an open Extensible Markup Language XML [XML] protocol for near-real-time messaging, presence, and request-response services. The basic syntax and semantics were developed originally within the Jabber open-source community, mainly in 1999. In 2002, the XMPP WG was chartered with developing an adaptation of the Jabber protocol that would be suitable as an IETF instant messaging (IM) and presence technology. As a result of work by the XMPP WG, the current memo defines the core features of XMPP 1.0; the extensions required to provide the instant messaging and presence functionality defined in RFC 2779 [IMP REQS] are specified in Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence [XMPP IM].


二. Socket/XMPP 程式需注意的幾個重點

1.架構(select poll epoll AIO kqueue IOCP / Thread / Process / LWP)

2.setsockopt比較值得討論的參數
setsockopt( $listen,SOL_SOCKET,SO_REUSEADDR,1); 伺服端
setsockopt( $sockfd,SOL_SOCKET,SO_KEEPALIVE,pack("l",$SO_KEEPALIVE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPIDLE,pack( "l", $TCP_KEEPIDLE ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPCNT,pack( "l", $TCP_KEEPCNT ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_KEEPINTVL,pack( "l", $TCP_KEEPINTVL ) );
setsockopt( $sockfd,IPPROTO_TCP,TCP_NODELAY,pack( "l", 1 ) );
setsockopt( $listen, SOL_SOCKET, SO_RCVBUF, 8192 );
setsockopt( $listen, SOL_SOCKET, SO_SNDBUF, 8192 );

3.flow(read/sysread/write/syswrite buffer)

4.XML Stream (SAX/DOM)


三. XMPP (RFC-3920 導讀)

1. XMPP 協定

Rfc-3920
Rfc-3921
Rfc-3922
Rfc-3923
Rfc-4622
可參考網站
http://www.xmpp.org/rfcs/
http://www.xmpp.org/extensions/
http://wiki.jabbercn.org/space/start
http://hi.baidu.com/jabber/blog/category/Jep


2. XML STREAM

<stream>
<presence>
<show/>
</presence>
<message to='foo'>
<body/>
</message>
<iq to='bar'>
<query/>
</iq>

</stream>


3. xmpp 的主要xml 標籤

訊息傳遞:<message/>
線上資訊:<presence/>
查詢與回應:<iq/>
目前實做的功能
<query xmlns=‘http://jabber.org/protocol/disco#info’>
<identity category='server' name='MJS' type='im'/>
<feature var='http://jabber.org/protocol/disco#info'/>
<feature var='http://jabber.org/protocol/disco#items'/>
<feature var='jabber:iq:private'/>
<feature var='jabber:iq:roster'/>
<feature var='jabber:iq:time'/>
<feature var='msgoffline'/>
</query>


4. 交易

以下定義
C->S 為CLIENT 傳送資料到 SERVER,
S->C 定義為伺服器傳遞資料給CLIENT,
Cn 代表第n個client

C1->S (Part1)
<?xml version='1.0'?>
<stream:stream
to='127.0.0.1'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>

S->C1 (Part2)
<?xml version='1.0'?>
<stream:stream
from='127.0.0.1’
id='someid'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
version='1.0'>

.認證與BINDING過程…(文件稍後會解釋交易過程) ,目前server不支援tls 的交易

C1->S
<message from='luke_shei@127.0.0.1/Resource1'
to=' admin@127.0.0.1/Resource2'
xml:lang='zh-tw' id=’R1-2’><body><測試訊息></body></message>

C1->S->C2(C1傳遞資訊給SERVER ,再經由JID 的資訊傳送給C2)

C2->S
<message from=' admin@127.0.0.1/Resource2'
to=' luke_shei@127.0.0.1/Resource1'
xml:lang='zh-tw' id=’R1-2’>
<body>回應訊息</body>
</message>

C2->S->C1(C2傳遞資訊給SERVER ,再經由JID 的資訊傳送給C1)

C1->S
</stream:stream>
S->C1
</stream:stream>

4.1 from/to 屬性:

a.C->S
b.S->C
Att /Action initiating to receiving receiving to initiating
to hostname of receiver silently ignored
From silently ignored hostname of receiver
id silently ignored session key
xml:lang default language default language
version signals XMPP 1.0 support signals XMPP 1.0 support

4.2 jid(Jabber Identifier) 形式:

a.node@domain/resource
b.node@domain
ps:事實上node 指的是用後帳號,目前;我們不支援將a,b 視為同一帳號的兩個不同的資
源binding,因此; node@domain/resource1 與node@domain/resource2 再目前的
系統是視為同一帳號的登入,而目前不支援同一帳號重覆登入


5. XMPP 需注意的事項

A. 內容替換

#x22 (")
#x26 (&)
#x27 (')
#x2F (/)
#x3A (:)
#x3C (<)
#x3E (>)
#x40 (@)

B. XML為case sensitive, 包括:認證所使用的UID
C.屬性皆以 ‘ 做為分隔
D.屬性是沒有順序性的
E.文件字集應該使用UTF-8
F.同一帳號應該以登入一次為限
G. 不應該預期交易的過程是否有斷行
I.Client 要斷線前,應保持良好習慣先傳遞
<presence type="unavailable"/></stream:stream> 再執行斷線


6. 認證交易(SASL RFC-2831)

(前略) 參考前述Part1 Part2

<Server 告知Client , 目前支援的認證型態>
S->C
<stream:features>
<mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<mechanism>DIGEST-MD5</mechanism>
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>
Ps:目前規劃使用的是 DIGEST-MD5 , PLAIN是為了讓SPARK(Jabber Client可以進行測試),而jabber::component 目前使用的是另一種handshark的機制


<Client 選擇一個認證機制>
C->S
<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechani
sm='DIGEST-MD5'/>

Server 傳送challenge code
S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOX
RFUUdtMmhoIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmL
TgsYWxnb3JpdGhtPW1kNS1zZXNzCg==</challenge>
中間這字串解開base 64 後的資訊為
realm="somerealm",nonce="OA6MG9tEQGm2hh",qop="auth",
charset=utf-8,algorithm=md5-sess


Client 傳送challenge code 給server
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlY
WxtIixub25jZT0iT0E2TUc5dEVRR20yaGgiLGNub25jZT0i
T0E2TUhYaDZWcVRyUmsiLG5jPTAwMDAwMDAxLHFv
cD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5j
b20iLHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwY
TE1MjMyMWYyMTQzYWY3LGNoYXJzZXQ9dXRmLTgK
</response>
中間字串的base64解碼為
username="somenode",realm="somerealm",nonce="
OA6MG9tEQGm2hh",cnonce="OA6MHXh6VqTrRk",
nc=00000001,qop=auth,digest-uri="xmpp/example.com"
,response=d388dad90d4bbd760a152321f2143af7,charset=utf-8
<如驗證失敗 伺服器回應認證失敗>
S->C
<failure xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>
<temporary-auth-failure/>
</failure>
</stream:stream>
隨即斷線


<伺服器傳送驗證碼>

S->C
<challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>cn
NwYXV0aD1lYTQwZjYwMzM1YzQyN2I1NTI3Yjg0ZGJh
YmNkZmZmZAo=</challenge>
中間字串BASE64解碼為
rspauth=ea40f60335c427b5527b84dbabcdfffd


<CLIENT 回應驗證碼正確性>
C->S
<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>


<伺服器回應認證成功>
S->C
<success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>


<認證成功後 Client 重新初始化 xml stream>
C->S
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
to='example.com'
version='1.0'>


<伺服器回應所支援的feature>
S->C
<stream:stream
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'
id='c2s_345'
from='example.com'
version='1.0'>
<stream:features>
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'/>
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
</stream:features>


<Client 請求Binding>
C->S
<iq id="jcl_8" type="set"><bind xmlns="urn:ietf:
params:xml:ns:xmpp-bind"><resource>Exodus<
/resource>
</bind></iq>


<伺服器回應Bind 的資源>
S->C
<iq type='result' id='jcl_8'><bind xmlns='urn:ietf:params
:xml:ns:xmpp-bind'><jid>admin@127.0.0.1/Exodus<
/jid><
/bind></iq>


<Client 請求session 交易>
C->S
<iq id="jcl_9" type="set"><session xmlns="urn:ietf:params:
xml:ns:xmpp-session"/></iq>


<Server 回應 session 交易>
S->C
<iq type='result' id='jcl_9'><session xmlns='urn:ietf:params:xml:
ns:xmpp-session'></session></iq>


5.認證演算過程

A. Server 傳送challenge code
S->C
BASE64(realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",
qop="auth", algorithm=md5-sess,charset=utf-8)

B. Client 傳送challenge code 給server
以下定義
開頭為$者為變數
開頭為 $$realm_xyz 代表該變數來自於realm 的屬性,而範例的值為xyz
以下範例 chris 為一個帳號名稱
+ 代表字串相加
‘ 代表固定字串內的值
MD5 代表其內字串使用MD5做簽章但不轉成HEX CODE
MD5_HEX 代表其內字串使用MD5做簽章且轉成HEX CODE

C->S
$PASSWORD 為該USER 的密碼
$A1=(MD5(‘chris’ + ‘:’ + $$realm_elwood.innosoft.com + ‘:’ + $PASSWORD) + ‘:’ + $$nonce _OA6MG9tEQGm2hh + ‘:’ + $$conce_OA6MHXh6VqTrRk)
$A2=’AUTHENTICATE’ + ‘:’ + $$realm_jabber/elwood.innosoft.com

$response=MD5_HEX(MD5_HEX($A1)+’:’+ $$nonce_OA6MG9tEQGm2hh +’:’+ $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk+’:’+ $$qop_auth +’:’ + MD5_HEX($A2))

Base64(charset=utf-8,username="chris",realm="elwood.innosoft.com", nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk", digest-uri="jabber/elwood.innosoft.com",response=$response,qop=auth)

Server 隨即驗證 $response 如失敗則回傳失敗,否則進行下一個動作

C: 伺服器傳送驗證碼
rspauth=MD5_HEX(MD5_HEX($A1) + ‘:’ + $$nonce_OA6MG9tEQGm2hh + ’:’ + $$nc_00000001 + ’:’ + $$conce_OA6MHXh6VqTrRk + ’:’ + $$qop_auth+MD5_HEX(‘:’ + $$digest-uri _jabber/elwood.innosoft.com))

Client 應該檢驗 rspauth


七.相關資源

Jabber Client下載位置

Exodus ( http://www.jabberstudio.org/projects/exodus/releases/ )
Pandion( http://www.pandion.be/download/ )
Spaek( http://www.igniterealtime.org/downloads/download-landing.jsp?file=spark/spark_2_5_2.exe )

C 所常用的 XML parser library
http://expat.sourceforge.net/

msxml sax相關資源
http://www.perfectxml.com/msxmlSAX.asp

Monday, July 30, 2007

[微程式-技術研討會]如何使用 flash player 開發應用程式

如何使用 網頁動畫 flash player 來開發應用程式 :

決定系統配置:

策略1: Microsoft- windows+ IIS +ASP+ (access 或 ms-sql server)
策略2. L.A.M.P.: Linux+ Apache + mysql + php

當然以上只是典型搭配法, OS, http-SERVER, Programming Language,DB
皆可視實際狀況抽換之.

再到網上搜尋 adobe macromedia flash開發環境:
Ex: 上軟體王 (http://www.softking.com.tw) ,打入以上字眼搜尋即可,
下載試用版來安裝; (含flash player)

***************************************************
執行架構簡述:

1. ActionScript:--
flash 自創的一套程式語言, 可用以控制動畫行為, 並與外部網頁連接通訊;
可用 javascript call flash- public- methods, 也可從 actionScript call javascript functions. 以下將舉例示範.

2. 對XML, server side-Script, GET/POST 的支援:-- (*本次的重點*)
這是最重要的一項應用, 傳統的網頁程式流程如下:
*****
Request -> http-SERVER -> Asp,Php…(讀寫db) -> (配合XSLT, 或html 輸出)
*****

由於 flash actionScript 可讀寫 XML, 並代替asp,php輸出 流程變成:
*****
Request(click flash動畫UI ) -> actionScript-calls (GET/POST) -> http-SERVER -> Asp,Php(讀寫db) -> 輸出XML -> flash 取回xml,並反映於動畫UI 上
*****

它實現了一種 全UI ,全動畫, no HTML的網站;
以下將舉例.

3. 支援 TCP/IP socket port 通訊 --
以下將示範一個以 flash 當client-ui, 實現一個免安裝,無reload 的聊天室.

*****************************************************
macromedia flash幾個優勢:
A 跨平台:--
flash player 播放器可 plug-in 在 IE, firefox 等網頁browser 之上,
並且有發行適用於ms-windows, Linux 等os 的安裝版本,
可至官網下載: (http://www.adobe.com/)

B 安裝性/安全性/介面性:
像是 activeX- OCX元件, 但flash跨平台, 免安裝, 不會引發 browser 安全性
的限制及詢問;
又像 java applet, 但java 作動畫麻煩, 而flash 本身就是動畫軟體;

C. 介面性/互動性:
介面看起來就像傳統的desktop-AP移到了browser上; 無換頁之感;
配合上flash 先天的動畫本領, 和user 的互動會更加良好;


***************************************************************
p.s: 所用到的 actionScript 指令參考:

a. 讀取/使用 xml data:
var RecordSet =new XML();
RecordSet.onLoad=LoadOK;
RecordSet.load( theAsp);
picPath= RecordSet.firstChild.childNodes[i].childNodes[9].firstChild.nodeValue


b. 送出get/post, 並取回結果:
var registerSend=new LoadVars();
registerSend.Email=myEmail.text;
registerSend.sendAndLoad("register.asp",registerLoad,"POST");
var registerLoad =new LoadVars();
registerLoad.onLoad=LoadOK;


c. flash Socket 通訊:
var myXMLSocket = new XMLSocket();
myXMLSocket.connect(null, 7890);
myXMLSocket.onConnect=myConnect;
myXMLSocket.onClose=myClose;
myXMLSocket.onXML=myOnData;
myXMLSocket.send(talkText.text + chr(0));


d. 網頁互動:
getURL("javascript: myInit();");
document.myFlash.TGotoFrame("_root",myFrame);
document.myFlash.play();

Sunday, June 24, 2007

[微程式-技術研討會]微軟 asp.net 2.0 ajax

微軟Asp.net2.0 Ajax
一. Asp.net 2.0 Ajax
執行環境需求:
Framework 2.0
IIS
開發環境:
VS2005 C#.net (or VB.net)
微軟 Ajax 套件 (需另外下載)
1.下載套件:
http://ajax.asp.net/
於首頁 按下 Download ASP.NET AJAX v1.0

會進入下一個頁面
點下 Download ASP.NET Extensions V1.0 即可 下載

安裝完成後 開啟 VS2005
新增專案  選擇(VB 或 C#) Asp.net Ajax-Enabled Web Application

開啟後會發現 多了 1組元件在 工具箱 (Ajax Extensions)

2.介紹AJAX Extensions
ASP.NET AJAX v1.0 使用微軟自定的 Client Script Libery
1.ScriptManager控制項 – 整個 Asp.net Ajax 的核心 ,所有要使用Ajax的功能均必須使用該元件 ,負責建立User端的javascript ,使用Ajax功能時只能有一個ScriptManager控制項。
2.UpdatePanel控制項 – 與ScriptManager搭配使用後 ,可以簡單建立完成Ajax功能。
3.UpdateProgress控制項 – 與UpdatePanel 配合 ,用來顯示 非同步postback的處理狀況 ,或將非同步postback中斷。
4.Timer 控制項 – 就如同windows應用程式所使用的Timer 元件 ,可定時於page中重整 ,但時間設定太短可能會增加Server的負擔。
5.ScriptManagerProxy 控制項 – 在Asp.net Ajax的page裡只能用一個ScriptManager, 於Asp.net MasterPage(類似Html 的框架頁)會有多個Asp.net page,如果同時間有2個以上的網頁要使用Ajax功能需使用到 ScriptManager 則子版面必須使用ScriptManagerProxy

範例(一) AspNetAJAXdemo.aspx
配合 Asp.Net 2.0 的MasterPage 解說 這5大Asp.Net Ajax 控制項 的使用方式

二. Asp.Net Ajax Control Toolkit
Asp.Net Ajax Control Toolkit 為 Asp.Net Ajax 的強化套件 , 已有34項免費延伸元件可以直接使用,這件元件是由先前所介紹的那5個控制項所擴充而成
1. 下載
一樣至 http://ajax.asp.net/ 點選 Download ASP.NET AJAX v1.0 後出現以下畫面
點選 Download the ControlToolKit

2.新增至工具箱 加入索引 選擇項目  瀏覽  選擇剛剛下載的檔案裡位於 SampleWebSite\bin 中的 AjaxControlToolKit.dll



















成功後工具箱將出現34種擴充元件可以使用


列舉幾個元件進行解說
1.TextBox 自動完成 (範例 AutoComplete.aspx)
AutoCompleteExtender
屬性:TargetControlID = 要被設定的TextBox 的ID
ServiceMethod = 後端所使用的Web Service( 或PageMethod)
ServicePath = WebService 的位置 , 不設定會自動判定使用 PageMethod
MinimumPrefixLength = 至少輸入多少字元後動作
CompletionInterval = 輸入多久後執行WebService的延遲時間(毫秒)
EnableCaching = 是否啟用 Caching
CompletionSetCount = 要回傳顯示的 item數

範例重點解說:
protected void Page_Load(object sender, EventArgs e) {
//設定 TargetControlID
AutoCompleteExtender1.TargetControlID = this.TextBox1.ID;
//輸入的字元長度
AutoCompleteExtender1.MinimumPrefixLength = 1;
//啟用Caching
AutoCompleteExtender1.EnableCaching = true;
//顯示的item數
AutoCompleteExtender1.CompletionSetCount = 15; //最多15筆
AutoCompleteExtender1.ServiceMethod = "GetEmailList";
}
//pageMethod
[System.Web.Services.WebMethod]
[System.Web.Script.Services.ScriptMethod]
public static String[] GetEmailList(String prefixText,int count) {
//prefixText =輸入的字串 , count 要回傳的數目
//連結DB做過濾
String Constr = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + @"D:\研討會Ajax\SolutionExp\Example2\DB\mail.mdb";
String sql = "select Top "+ count +" * from mail where mail like '"+ prefixText.Trim() +"%' order by mail";//取得mail清單
OleDbConnection conn = new OleDbConnection(Constr);
OleDbDataAdapter da = new OleDbDataAdapter(sql, conn);
DataTable dt = new DataTable();
da.Fill(dt);
String[] data = new string[dt.Rows.Count];
for (int i = 0; i < data.Length; i++) {
DataRow row = dt.Rows[i];
data[i] = row["mail"].ToString(); //取出mail
}
return data; //回傳String Array

}

2.自由拖曳panel(範例 DragPanel.aspx)
DragPanelExtender
屬性:TargetControlID = 要被拖曳的Panel 的ID
DragHandleID = 觸發拖曳事件的panel ID
*DragHandle 和 TargetControl 可為相同panel , 如不一樣,DragHandle的panel必須建立於TargetControl的panel 中
範例重點解說:
protected void Page_Load(object sender, EventArgs e) {
DragPanelExtender1.TargetControlID = this.Panel1.ID; // 要移動的panel;
DragPanelExtender1.DragHandleID = this.Panel2.ID;//觸發移動事件的panel;
this.Panel1.Style["cursor"] = "hand"; //滑鼠移到panel2 後游標變 成 hand
}

3.可拖曳放大縮小的網頁物件(範例 ResizableControl.aspx)
ResizableControl
屬性:
TargetControllID = 要改變大小的控制項
HandleCssClass = 拖曳點CSS設定
ResizableCssClass = 拖曳中的CSS設定
MinimunWidth = 拖曳時可接受的最小寬度
MinimunHeight = 拖曳時可接受的最小高度
MaxmumWidth = 拖曳時可接受的最大寬度
MaxmumHeight = 拖曳時可接受的最大高度
OnClientResize = 拖曳後要執行的javascript
OnClientResizing = 拖曳中要執行的javascript
OnClientResizeBegin = 拖曳前要執行的 javascript
HandleOffsetX = 拖曳點於物件右下角的X座標
HandleOffsetY = 拖曳點於物件右下角的Y座標
範例重點解說:
Css
<style type="text/css">
/* ResizableControl */
.frameImage
{
/* panel(圖片)大小 */
width:180px;
height:130px;
overflow:hidden;
float:left;
padding:3px;
}

.handleImage
{
/* 可拖曳圖示 */
width:15px;
height:16px;
background-image:url(Image/HandleHand.png);
overflow:hidden;
cursor:se-resize;
}

.resizingImage
{
padding:0px;
border-style:solid;
border-width:3px;
border-color:#B4D35D;
}

Javascript 抓取物件(panel1)大小 於Lable1中顯示
<script>
function onOK(){
$get('Label1').innerHTML=$get('Panel1').style.height + ',' + $get('Panel1').style.width;
}
</script>

主要程式碼
protected void Page_Load(object sender, EventArgs e) {
//拖曳圖示
ResizableControlExtender1.HandleCssClass = "handleImage";
//拖曳中的圖示
ResizableControlExtender1.ResizableCssClass = "resiaingImage";
//設定目標控制項
ResizableControlExtender1.TargetControlID = Panel1.ID;
//javascript function OnOK
ResizableControlExtender1.OnClientResize = "onOK";
//avascript function OnOK
ResizableControlExtender1.OnClientResizing = "onOK";
//最小高度
ResizableControlExtender1.MinimumHeight = 100;
//最小寬度
ResizableControlExtender1.MinimumWidth = 100;
}

4.Asp.net 2.0 Ajax應用 電子地圖
顯示頁面:DemoMap.aspx
處理頁面:GetMap.aspx
DemoMap.asp 程式碼
Javascript 在處理 拖曳panel 座標
<script type="text/javascript">
//位移變數
var offsetX,offsetY,startX,startY;
var isMoving; //開始移動Flag

function _start(){
//設定開始移動
isMoving=true;
//紀錄起點
startX=event.x;
startY=event.y;
startY=startY+17;
}
function _move(){
//如果在移動中模式
if (isMoving==true){
//移動
offsetX=event.x-startX;
offsetY=event.y-startY;
//設定圖檔位置
$get('Image1').style.left=10+(offsetX);
$get('Image1').style.top=130+(offsetY);
}
}
function _end(){
//如果在移動中模式
if (isMoving==true){
//設定處理完畢
isMoving=false;
//計算調整位移
offsetX=-(event.x-startX);
offsetY=-(event.y-startY);
offsetY= offsetY-17;
//以計算出的位移重新載入地圖
if (offsetX!=0 && offsetY!=0)
$get('Image1').src='GetMap.aspx?offsetX='+offsetX+'&offsetY='+offsetY+'&width=500&height=500';
$get('Image1').style.left=10;
$get('Image1').style.top=110;
}
}
</script>

DemoMap.aspx.cs
此function為在CS檔中直接定義 aspx中Panel_phantom 的Style 與javascrip操作事件
private void MakePhantom() {
Panel_phantom.Style["filter"] = "alpha(opacity=1);";
Panel_phantom.Style["cursor"] = "hand";
Panel_phantom.Style["position"] = "absolute";
Panel_phantom.Style["left"] = "15";
Panel_phantom.Style["top"] = "110";
Panel_phantom.Attributes["onmousedown"] = "_start();";
Panel_phantom.Attributes["onmouseup"] = "_end();";
Panel_phantom.Attributes["onmouseleave"] = "_end();";
Panel_phantom.Attributes["onmousemove"] = "_move();";
}
MapGotoXY 為 取得物件 Image1 的圖片來源 呼叫 GetMap.aspx 加上參數處理後,輸出所要顯示的圖片區塊
private void MapGotoXY(String x, String y) {
Image1.ImageUrl = "GetMap.aspx?x=" + x + "&y=" + y + "&width=500&height=500";
txb_x.Text = x ;
txb_y.Text = y ;
//設定拖曳用的Panel機制
MakePhantom();
}//MapGotoXY
GetMap.aspx
主要處理 地圖的顯示座標
protected void Page_Load(object sender, EventArgs e) {
//Image 的x,y 座標
int x =Convert.ToInt32(Request.QueryString["x"]);
int y =Convert.ToInt32( Request.QueryString["y"]);
//移動的 x,y座標
int offsetX = Convert.ToInt32(Request.QueryString["offsetX"]);
int offsetY = Convert.ToInt32(Request.QueryString["offsetY"]);
//地圖寬高
int width = Convert.ToInt32(Request.QueryString["width"]);
int height= Convert.ToInt32(Request.QueryString["height"]);

Bitmap bmp ;
Bitmap retbmp;
//讀入檔案
String ImgPath = Path.GetDirectoryName(Request.PhysicalPath) + @"\Image\tw.jpg";
bmp = new Bitmap(ImgPath);
if (x == 0 && y == 0 && offsetX != 0 && offsetY != 0) {
x = Convert.ToInt32(Session["_LastX"]) + offsetX;
y = Convert.ToInt32(Session["_LastY"])+ offsetY;
}
//防呆
if (x < 1) x = 1;
if (y < 1) y = 1;
if (x + width > bmp.Width) x = bmp.Width - width;
if (y + height > bmp.Height) y = bmp.Height - height;

//記錄 X,Y 座標
Session["_LastX"] = x;
Session["_LastY"] = y;

//宣告 GetMap 的輸出格式
Context.Response.ContentType= "image/Jpeg";
Context.Response.BufferOutput = false;
//建立矩形
Rectangle rect = new Rectangle(x, y, width, height);
retbmp = bmp.Clone(rect, bmp.PixelFormat); //取得圖片區塊
//處理圖形品質
System.Drawing.Imaging.ImageCodecInfo[] codecs = System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
System.Drawing.Imaging.ImageCodecInfo ici = null;

//找出Encoder
foreach( System.Drawing.Imaging.ImageCodecInfo codec in codecs){
if( codec.MimeType == "image/jpeg") {
ici = codec;
}
}
//參數 - 高品質圖檔
System.Drawing.Imaging.EncoderParameters ep = new System.Drawing.Imaging.EncoderParameters();
ep.Param[0] = new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, Convert.ToInt64(100));
retbmp.Save(Context.Response.OutputStream, ici, ep); //儲存
bmp.Dispose(); //釋放
retbmp.Dispose(); //釋放
Context.Response.End();//結束
}
5. 建立 統計圖
程式碼請參考
Chart..aspx
LineChart.cs
Chart..aspx主要顯示頁
LineChart.cs 為建立統計圖-點線圖的主要程式
輸出的圖 配合拖曳標籤可以自由移動圖表(使用DragPanelExtender)
如下方圖示

6. Ajax Excel圖表
程式碼過多 請參考
Excel_Demo.aspx
ExcelTable.cs
LineChart.cs
Excel_Demo.aspx 為主要顯示頁
背後處理程式有 ExcelTable.cs 與 LineChart.cs
ExcelTable.cs 提供3個funtion
1. reDrawExcelTable – 用來建立 table物件配合Javascript讓user感覺很像Excel
2. ExportDataTable –將Table轉化成DataTable提供給LineChart.cs
使LineChart 繪製圖片
3. SetValue – 初始化設定欄位的值

下圖為執行結果


Asp.Net2.0 配合 Ajax1.0 套件可以讓開發人員短時間之內,建出效果不錯的網頁,擴充元件讓頁面上只留下元件使用的標籤,除了微軟提供出的34項免費的基本元件可以使用外,也可以自行建立擴充元件 (Extender) , 至於要如何建立自訂的擴充元件,因為該功能步驟繁雜,等待小弟研究透徹後 ,有機會再向各位解說。

Saturday, April 28, 2007

Concurrent Programming 相關報告

一. 我會接觸Erlang的緣由
1.RFID Middleware




2.jabber (xml::stream http://zh.wikipedia.org/wiki/Jabber)

3.ejabber (http://www.process-one.net/en/ )


二. 現在的商業環境(web server)所面臨的問題
1.連線的數量不斷的攀升

2.連線的時間很長
傳統上httpd 使用Prefork的方式來解決,短時間時密集連線的問題,在現在的環境愈到了嚴重的挑戰,比如: HTTP_Streaming、Server Push、COMET 這些需要長時間連線的架構,使得httpd 能夠服務的連線變少了,而fork process 最大的問題是,他所需要佔用記憶體的空間過於龐大,於是其他的伺服器架構崛起(lighthttpd ghttpd …)

The C10K problem( http://www.kegel.com/c10k.html )
It's time for web servers to handle ten thousand clients simultaneously, don't you think? After all, the web is a big place now.
And computers are big, too. You can buy a 1000MHz machine with 2 gigabytes of RAM and an 1000Mbit/sec Ethernet card for $1200 or so. Let's see - at 20000 clients, that's 50KHz, 100Kbytes, and 50Kbits/sec per client. It shouldn't take any more horsepower than that to take four kilobytes from the disk and send them to the network once a second for each of twenty thousand clients. (That works out to $0.08 per client, by the way. Those $100/client licensing fees some operating systems charge are starting to look a little heavy!) So hardware is no longer the bottleneck???


三. Concurrent Programming
1. fork
原始的程式
(程式+資料) --fork(複製一份)(程式+資料)

當程式fork 後,child 繼承原來的資料,此後彼此不相關,如果要傳遞資訊,需要使用pipe sharememory 或是 unix socket 來做資料交換

2. thread
事實上在Linux 系統下,執行緒只是一個light weight process:Linux 核心是以fork() system call 來產生一個新的行程(process),而執行緒是以clone() system call 產生的。fork()和clone()的差別只是在clone()可以指定和父行程共用的資源有哪些,當所有資源都和父行程共用時就相當於一個執行緒了。因為Thread 的使用會讓子父行程共用資源,因此非常容易引發dead lock / race condition …這類的問題

3. lightweight Threads ( http://www.defmacro.org/ramblings/concurrency.html)
Erlang process 是一個輕量級的Thread,因此他可以非常輕易的去開啟或是結束且快速在彼此做切換,因為掀開他的底層,他只是一個簡單的function罷了,process節省了大量的context switching浪費僅在一些function上做切換的動作(Erlang 的Thread 是 vm level thread)

這份文件簡單的提到了Erlang的概觀
http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks
/252.pdf


四. Erlang ( http://www.erlang.org/ )
1.以下是 about Erlang 對他自己的簡述

Erlang is a programming language which has many features more commonly associated with an operating system than with a programming language: concurrent processes, scheduling, memory management, distribution, networking, etc.
The initial open-source Erlang release contains the implementation of Erlang, as well as a large part of Ericsson's middleware for building distributed high-availability systems.
Erlang is characterized by the following features:
Concurrency - Erlang has extremely lightweight processes whose memory requirements can vary dynamically. Processes have no shared memory and communicate by asynchronous message passing. Erlang supports applications with very large numbers of concurrent processes. No requirements for concurrency are placed on the host operating system.
Distribution - Erlang is designed to be run in a distributed environment. An Erlang virtual machine is called an Erlang node. A distributed Erlang system is a network of Erlang nodes (typically one per processor). An Erlang node can create parallel processes running on other nodes, which perhaps use other operating systems. Processes residing on different nodes communicate in exactly the same was as processes residing on the same node.
Soft real-time - Erlang supports programming "soft" real-time systems, which require response times in the order of milliseconds. Long garbage collection delays in such systems are unacceptable, so Erlang uses incremental garbage collection techniques.
Hot code upgrade - Many systems cannot be stopped for software maintenance. Erlang allows program code to be changed in a running system. Old code can be phased out and replaced by new code. During the transition, both old code and new code can coexist. It is thus possible to install bug fixes and upgrades in a running system without disturbing its operation.
Incremental code loading - Users can control in detail how code is loaded. In embedded systems, all code is usually loaded at boot time. In development systems, code is loaded when it is needed, even when the system is running. If testing uncovers bugs, only the buggy code need be replaced.
External interfaces - Erlang processes communicate with the outside world using the same message passing mechanism as used between Erlang processes. This mechanism is used for communication with the host operating system and for interaction with programs written in other languages. If required for reasons of efficiency, a special version of this concept allows e.g. C programs to be directly linked into the Erlang runtime system.

2.Erlang 語言上的概觀
書籍: ( http://pragmaticprogrammer.com/titles/jaerlang/index.html )

[ Sequential Erlang ]

Exam1:

Consider the factorial function N! defined by:
N!=N*(N-1) when N>0
N!=1 when N=0

-module(math1).
-export([fac/1]).

fac(N) when N > 0 -> N * fac(N-1);
fac(0)-> 1.

Exam2:

-module(math2).
-export([sum1/1, sum2/1]).

sum1([H T]) -> H + sum1(T);
sum1([]) -> 0.

sum2(L) -> sum2(L, 0).
sum2([], N) -> N;
sum2([H T], N) -> sum2(T, H+N).

[ Concurrency Programming ]

Exam3:

-module(concurrency).

-export([start/0, say /2]).

say (What, 0) ->
done;
say (What, Times) ->
io:format("~p~n", [What]),
say_something(What, Times - 1).

start() ->
spawn(tut14, say, [hello, 3]),
spawn(tut14, say, [goodbye, 3]).

Exam4:

-module(area_server).
-export([loop/0]).

loop() ->
receive
{rectangle, Width, Ht} ->
io:format("Area of rectangle is ~p~n",[Width * Ht]),
loop();
{circle, R} ->
io:format("Area of circle is ~p~n", [3.14159 * R * R]),
loop();
Other ->
io:format("I don't know what the area of a ~p is ~n",[Other]),
loop()
end.

We can create a process which evaluates loop/0 in the shell:

Pid = spawn(area_server,loop,[]).
Pid ! {rectangle, 6, 10}.
Pid ! {circle, 23}.
Pid ! {triangle,2,4,5}.


4. Erlang –style process or event-based model for actors ( http://lambda-the-ultimate.org/node/1615 )
( http://lamp.epfl.ch/~phaller/doc/haller07coord.pdf )


Message passing
Each process has its own input queue for messages it receives. New messages received are put at the end of the queue. When a process executes a receive, the first message in the queue is matched against the first pattern in the receive, if this matches, the message is removed from the queue and the actions corresponding to the the pattern are executed.
However, if the first pattern does not match, the second pattern is tested, if this matches the message is removed from the queue and the actions corresponding to the second pattern are executed. If the second pattern does not match the third is tried and so on until there are no more pattern to test. If there are no more patterns to test, the first message is kept in the queue and we try the second message instead. If this matches any pattern, the appropriate actions are executed and the second message is removed from the queue (keeping the first message and any other messages in the queue). If the second message does not match we try the third message and so on until we reach the end of the queue. If we reach the end of the queue, the process blocks (stops execution) and waits until a new message is received and this procedure is repeated.
Of course the Erlang implementation is "clever" and minimizes the number of times each message is tested against the patterns in each receive.
五. Erlang相關資源
Website:
Open Source Erlang
http://www.erlang.org
http://www.process-one.net/en/projects/

Mail List:
Erlang-questions -- Erlang/OTP discussions
http://www.erlang.org/mailman/listinfo/erlang-questions

BOOK:
Concurrent programming in Erlang
http://www.erlang.org/download/erlang-book-part1.pdf
Programming Erlang Software for a Concurrent World
http://pragmaticprogrammer.com/titles/jaerlang/index.html

Blog Archive