<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>蓝色的华 &#187; linux</title>
	<atom:link href="http://bluehua.org/category/linux/feed" rel="self" type="application/rss+xml" />
	<link>http://bluehua.org</link>
	<description>分享所学,backup一切~</description>
	<lastBuildDate>Wed, 23 Nov 2011 08:43:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>bash拼音补齐靠谱版本</title>
		<link>http://bluehua.org/2011/09/28/1705.html</link>
		<comments>http://bluehua.org/2011/09/28/1705.html#comments</comments>
		<pubDate>Wed, 28 Sep 2011 09:11:32 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[mac]]></category>

		<guid isPermaLink="false">http://bluehua.org/?p=1705</guid>
		<description><![CDATA[之前玩ubuntu的时候写过一个，功能和代码都较丑，用的拼音库也很烂。正好为项目抓了一个靠谱的拼音库，顺便把这个bash补齐又重新实现了下，Mac上也可以用了～ 项目:http://code.google.com/p/bash-pinyin-completion/ ==特性== * 支持拼音首字母匹配和完全匹配 * 支持多音字匹配 安装 ubuntu 支持10.04,10.10,11.04版本从ppa安装，如果之前安装过那个chs-completion先卸载之。 sudo add-apt-repository ppa:emptyhua/toolbox sudo apt-get update sudo apt-get install bash-pinyin-completion 然后新开一个终端，就可以使用拼音补齐了 Mac OS X 对于mac需要先安装 bash-completion sudo port install bash-completion 然后编辑~/.bash_profile,把下面的代码贴进去 if [ -f /opt/local/etc/bash_completion ]; then . /opt/local/etc/bash_completion fi 下载源码包http://code.google.com/p/bash-pinyin-completion/downloads/list unzip bash-pinyin-completion-xxx.zip cd bash-pinyin* make sudo make install 然后新开一个终端，就可以使用拼音补齐了]]></description>
			<content:encoded><![CDATA[<p>之前玩ubuntu的时候<a href="http://forum.ubuntu.org.cn/viewtopic.php?f=21&#038;t=302712&#038;start=0">写过一个</a>，功能和代码都较丑，用的拼音库也很烂。正好为项目抓了一个靠谱的拼音库，顺便把这个bash补齐又重新实现了下，Mac上也可以用了～</p>
<p>项目:<a href="http://code.google.com/p/bash-pinyin-completion/">http://code.google.com/p/bash-pinyin-completion/</a></p>
<p>==特性==<br />
  * 支持拼音首字母匹配和完全匹配<br />
  * 支持多音字匹配</p>
<h3>安装</h3>
<h4>ubuntu</h4>
<p>支持10.04,10.10,11.04版本从ppa安装，<strong>如果之前安装过那个chs-completion先卸载之</strong>。</p>
<pre>
sudo add-apt-repository ppa:emptyhua/toolbox
sudo apt-get update
sudo apt-get install bash-pinyin-completion
</pre>
<p>然后新开一个终端，就可以使用拼音补齐了</p>
<h4>Mac OS X</h4>
<p>对于mac需要先安装 bash-completion</p>
<pre>
sudo port install bash-completion
</pre>
<p>然后编辑~/.bash_profile,把下面的代码贴进去</p>
<pre>
if [ -f /opt/local/etc/bash_completion ]; then
. /opt/local/etc/bash_completion
fi
</pre>
<p>下载源码包<a href="http://code.google.com/p/bash-pinyin-completion/downloads/list">http://code.google.com/p/bash-pinyin-completion/downloads/list</a></p>
<pre>
unzip bash-pinyin-completion-xxx.zip
cd bash-pinyin*
make
sudo make install
</pre>
<p>然后新开一个终端，就可以使用拼音补齐了</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2011/09/28/1705.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>linux中tty设备名的由来</title>
		<link>http://bluehua.org/2011/09/20/1696.html</link>
		<comments>http://bluehua.org/2011/09/20/1696.html#comments</comments>
		<pubDate>Tue, 20 Sep 2011 10:51:19 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[tty]]></category>

		<guid isPermaLink="false">http://bluehua.org/?p=1696</guid>
		<description><![CDATA[tty是teletypewriter（电传打字机）的简称，电传打字机是一种老式的通信工具，类似于传真，它有一个用于输入的键盘和用于输出接收信息的纸带打印设备。当按下按键后，电传机会把对应的键码编码成电流脉冲发送给接收方。对方收到脉冲后解码，并将对应的字符打印到纸带上。 早期的一些计算机便使用电传机来做输入输出设备。用户通过电传机向计算机输入指令，并通过纸带打印计算机的反馈结果,这便是最原始的command line interface(命令行交互)。 unix系统会为所有设备在/dev目录下生成对应的文件，电传机便被命名为/dev/tty#(#代表数字序号)。虽然现在的计算机早已经不再使用电传机做IO设备，但是tty的命名依然沿用至今。 links: http://www.linfo.org/teletype.html http://baike.baidu.com/view/1773688.htm]]></description>
			<content:encoded><![CDATA[<p>tty是teletypewriter（电传打字机）的简称，电传打字机是一种老式的通信工具，类似于传真，它有一个用于输入的键盘和用于输出接收信息的纸带打印设备。当按下按键后，电传机会把对应的键码编码成电流脉冲发送给接收方。对方收到脉冲后解码，并将对应的字符打印到纸带上。</p>
<p><a href="http://bluehua.org/wp-content/uploads/2011/09/电传打字机.jpg"><img class="alignnone size-full wp-image-1701" title="电传打字机" src="http://bluehua.org/wp-content/uploads/2011/09/电传打字机.jpg" alt="" width="200" height="150" /></a></p>
<p>早期的一些计算机便使用电传机来做输入输出设备。用户通过电传机向计算机输入指令，并通过纸带打印计算机的反馈结果,这便是最原始的command line interface(命令行交互)。</p>
<p>unix系统会为所有设备在/dev目录下生成对应的文件，电传机便被命名为/dev/tty#(#代表数字序号)。虽然现在的计算机早已经不再使用电传机做IO设备，但是tty的命名依然沿用至今。</p>
<p>links:<br />
<a href="http://www.linfo.org/teletype.html">http://www.linfo.org/teletype.html</a><br />
<a href="http://baike.baidu.com/view/1773688.htm">http://baike.baidu.com/view/1773688.htm</a></p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2011/09/20/1696.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>给力的翻译</title>
		<link>http://bluehua.org/2011/01/20/1540.html</link>
		<comments>http://bluehua.org/2011/01/20/1540.html#comments</comments>
		<pubDate>Thu, 20 Jan 2011 02:11:38 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://bluehua.org/2011/01/20/1540.html</guid>
		<description><![CDATA[一不小心发错地方了。。就放这吧 &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8211; post by Email~]]></description>
			<content:encoded><![CDATA[<p>一不小心发错地方了。。就放这吧<br />
&#8212;&#8212;&#8212;&#8212;<br />
<a href="http://bluehua.org/wp-content/uploads/2011/01/screenshot_109.png"><img src="http://bluehua.org/wp-content/uploads/2011/01/screenshot_1091.png" alt="screenshot_109.png" title="screenshot_109.png"/></a></p>
<p>&#8212;&#8212;&#8212;&#8211;<br />
post by Email~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2011/01/20/1540.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>分享个pidgin插件</title>
		<link>http://bluehua.org/2010/12/29/1518.html</link>
		<comments>http://bluehua.org/2010/12/29/1518.html#comments</comments>
		<pubDate>Wed, 29 Dec 2010 13:25:24 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[soft]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[pidgin]]></category>

		<guid isPermaLink="false">http://bluehua.org/?p=1518</guid>
		<description><![CDATA[原帖:http://bluehua.org/2010/01/12/796.html 当年我会用pidgin同时开3个IM:gtalk,qq,msn. 于是我在pidgin里建了两个情景模式 work:三个都在线，其中qq隐身 at home:msn下线。 回到家就点到at home，但msn上还是难免有些烦人的消息发给我，让我改这改那。。，凭着饥渴精神，于是我就想出了上面的点子，完全不用伤脑筋。有问题打我电话吧，至少你得先知道我手机号^_^ 好吧，出于学习的目的，现在我把它完全重写成一个标准的pidgin插件，并且支持定时功能，用ubuntu的同学如果有同样烦恼可以试下～ 用ubuntu 10.10的话可以直接从源里安装 sudo add-apt-repository ppa:emptyhua/toolbox sudo apt-get update sudo apt-get install pidgin-autostatus 旧版本麻烦点 sudo apt-get install libglib2.0-dev libnm-glib-dev libdbus-glib-1-dev network-manager-dev libgtk2.0-dev libtool pidgin-dev svn checkout http://pidgin-auto-status.googlecode.com/svn/trunk/ pidgin-autostatus cd pidgin-autostatus make sudo make install google code项目主页: http://code.google.com/p/pidgin-auto-status/ screenshot:]]></description>
			<content:encoded><![CDATA[<p>原帖:<a href="http://bluehua.org/2010/01/12/796.html">http://bluehua.org/2010/01/12/796.html</a></p>
<p>当年我会用pidgin同时开3个IM:gtalk,qq,msn. 于是我在pidgin里建了两个情景模式 work:三个都在线，其中qq隐身 at home:msn下线。 回到家就点到at home，但msn上还是难免有些烦人的消息发给我，让我改这改那。。，凭着饥渴精神，于是我就想出了上面的点子，完全不用伤脑筋。有问题打我电话吧，至少你得先知道我手机号^_^</p>
<p>好吧，出于学习的目的，现在我把它完全重写成一个标准的pidgin插件，并且支持定时功能，用ubuntu的同学如果有同样烦恼可以试下～</p>
<p>用ubuntu 10.10的话可以直接从源里安装</p>

<div class="wp_syntax"><div class="code overflow"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> add-apt-repository ppa:emptyhua<span style="color: #000000; font-weight: bold;">/</span>toolbox
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> update
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> pidgin-autostatus</pre></div></div>

<p>旧版本麻烦点</p>

<div class="wp_syntax"><div class="code overflow"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">apt-get</span> <span style="color: #c20cb9; font-weight: bold;">install</span> libglib2.0-dev libnm-glib-dev  libdbus-glib-<span style="color: #000000;">1</span>-dev network-manager-dev libgtk2.0-dev libtool pidgin-dev
<span style="color: #c20cb9; font-weight: bold;">svn</span> checkout http:<span style="color: #000000; font-weight: bold;">//</span>pidgin-auto-status.googlecode.com<span style="color: #000000; font-weight: bold;">/</span>svn<span style="color: #000000; font-weight: bold;">/</span>trunk<span style="color: #000000; font-weight: bold;">/</span> pidgin-autostatus
<span style="color: #7a0874; font-weight: bold;">cd</span> pidgin-autostatus
<span style="color: #c20cb9; font-weight: bold;">make</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #c20cb9; font-weight: bold;">make</span> <span style="color: #c20cb9; font-weight: bold;">install</span></pre></div></div>

<p>google code项目主页: <a href="http://code.google.com/p/pidgin-auto-status/">http://code.google.com/p/pidgin-auto-status/</a></p>
<p>screenshot:</p>
<p><img src="http://bluehua.org/wp-content/uploads/2010/12/screenshot_103.png" /></p>
<p><img src="http://bluehua.org/wp-content/uploads/2010/12/screenshot_106.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/12/29/1518.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>shell下批量标记mp3标签</title>
		<link>http://bluehua.org/2010/12/19/1500.html</link>
		<comments>http://bluehua.org/2010/12/19/1500.html#comments</comments>
		<pubDate>Sun, 19 Dec 2010 10:21:34 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[music]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[tag]]></category>

		<guid isPermaLink="false">http://bluehua.org/2010/12/19/1500.html</guid>
		<description><![CDATA[#设置歌手 mid3v2 -a &#34;歌手&#34; *.mp3 #设置专辑名 mid3v2 -A &#34;专辑名&#34; *.mp3 #用文件名标记mp3的title find -name &#34;*.mp3&#34; &#124; while read file;do mid3v2 -t &#34;`echo $file&#124;sed -e 's/^\.\///g' -e 's/.mp3$//g'`&#34; &#34;$file&#34;;done &#8212;&#8212;&#8212;&#8211; post by gmail~]]></description>
			<content:encoded><![CDATA[
<div class="wp_syntax"><div class="code overflow"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#设置歌手</span>
mid3v2 <span style="color: #660033;">-a</span> <span style="color: #ff0000;">&quot;歌手&quot;</span> <span style="color: #000000; font-weight: bold;">*</span>.mp3
<span style="color: #666666; font-style: italic;">#设置专辑名</span>
mid3v2 <span style="color: #660033;">-A</span> <span style="color: #ff0000;">&quot;专辑名&quot;</span> <span style="color: #000000; font-weight: bold;">*</span>.mp3
<span style="color: #666666; font-style: italic;">#用文件名标记mp3的title</span>
<span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.mp3&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #c20cb9; font-weight: bold;">read</span> <span style="color: #c20cb9; font-weight: bold;">file</span>;<span style="color: #000000; font-weight: bold;">do</span> mid3v2 <span style="color: #660033;">-t</span> <span style="color: #ff0000;">&quot;<span style="color: #780078;">`echo $file|sed -e 's/^\.\///g' -e 's/.mp3$//g'`</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$file</span>&quot;</span>;<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<p>&#8212;&#8212;&#8212;&#8211;<br />
post by gmail~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/12/19/1500.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>jabberd2源码分析:sasl认证部分</title>
		<link>http://bluehua.org/2010/12/01/1486.html</link>
		<comments>http://bluehua.org/2010/12/01/1486.html#comments</comments>
		<pubDate>Wed, 01 Dec 2010 08:57:18 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[jabberd2]]></category>
		<category><![CDATA[xmpp]]></category>

		<guid isPermaLink="false">http://bluehua.org/2010/12/01/1486.html</guid>
		<description><![CDATA[此篇为http://bluehua.org/2010/12/01/1484.html在jabberd2上的延伸。 jabberd2的sasl验证部分底层使用了第三方库,同时支持Cyrus和gsasl,configure时可以通过&#8211;with-sasl=指定一个。 认证发生在两种情况，客户端连接c2s组件，组件连接router。由于我不想再去分析一个客户端，所以c2s连接router为例分析认证过程。 先简单描述下jabberd2的启动过程: jabberd2有四个可执行文件 router:路由器 c2s:组件,负责跟客户端建立连接，注册和验证帐号 sm:组件,会话管理器 s2s:组件,负责和其他xmpp服务器通信 router做为路由器首先启动,启动后会默认监听5347,等待包处理组件连接。 c2s,sm,s2s启动，并连接router，以c2s为例,分析一下往返的xml数据(C代表c2s做为客户端，S代表router做为服务端): c2s跟router建立连接之后，大家互相寒暄一下，c2s说我吃了，router说他也吃了(互发stream头) C:&#60;?xml version='1.0'?&#62;&#60;stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xmlns:ack='http://www.xmpp.org/extensions/xep-0198.html#ns'&#62; S:&#60;?xml version='1.0'?&#62;&#60;stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' id='yqvecsv64nooedcwo2mbt6f8x08krmlpch3oazve'&#62; 之后router给出自己支持的验证方式列表,说它只支持DIGEST—MD5 S:&#60;stream:features xmlns:stream='http://etherx.jabber.org/streams'&#62;&#60;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&#62;&#60;mechanism&#62;DIGEST-MD5&#60;/mechanism&#62;&#60;/mechanisms&#62;&#60;/stream:features&#62; c2s回应说它接受DIGEST-MD5方式 C:&#60;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/&#62; router给出challenge code S:&#60;challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&#62;cmVhbG09ImphYmJlcmQtcm91dGVyIiwgbm9uY2U9Ii8xb0tDempxMXRNSUlLUHlOYTNCSHc9PSIsIHFvcD0iYXV0aCIsIGNoYXJzZXQ9dXRmLTgsIGFsZ29yaXRobT1tZDUtc2Vzcw==&#60;/challenge&#62; c2s回应: C:&#60;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&#62;dXNlcm5hbWU9ImphYmJlcmQiLCByZWFsbT0iamFiYmVyZC1yb3V0ZXIiLCBub25jZT0iLzFvS0N6anExdE1JSUtQeU5hM0JIdz09IiwgY25vbmNlPSJueFZNempncTI1VUZtTjZmdUozdEZ3PT0iLCBuYz0wMDAwMDAwMSwgcW9wPWF1dGgsIGRpZ2VzdC11cmk9ImphYmJlcmQtcm91dGVyL2lwLTEwLTEzMC0xODctMTU1IiwgcmVzcG9uc2U9Yzg5NjJlNDgwZTVlYmM0ZjFkNjZiZDhlNDBiNjZlZjIsIGNoYXJzZXQ9dXRmLTg=&#60;/response&#62; router再出一招 S:&#60;challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&#62;cnNwYXV0aD1hM2IyMGI0YzZkMzgxNmE3MzVjMWJhNTRjZTVkYmFjYQ==&#60;/challenge&#62; c2s接 C:&#60;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&#62; router说验证通过 S:&#60;success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&#62; 验证通过之后的逻辑跟这里就无关了，需要注意的是验证通过之后这个stream并没有继续利用，c2s会发一个新的stream头，和router重新开始一个stream会话。 疑问：组件和router之间为什么要有验证机制? 虽然c2s,sm,s2s都在本地运行，但是如果一个远程进程可以连接到5347端口，那么它就可以向router注册。所以验证是必要的，所以5347端口的保护也是必要的。 下面是各个阶段在代码中的体现,主要从c2s的角度分析： 在这之前你必须首先理解jabberd2的io逻辑:http://bluehua.org/2010/11/28/1479.html(虽然老大表示文采太差，但是我觉得要是画图都不行，那我实在没辙了) sasl验证逻辑主要位于:sx/sasl_gsasl.c sx/sasl_cyrus.c,这里以sasl_gsasl.c为例 先画一下sasl在jabber2中的位置 +--------------------+ [...]]]></description>
			<content:encoded><![CDATA[<p>此篇为<a href="http://bluehua.org/2010/12/01/1484.html">http://bluehua.org/2010/12/01/1484.html</a>在jabberd2上的延伸。</p>
<p>jabberd2的sasl验证部分底层使用了第三方库,同时支持Cyrus和gsasl,configure时可以通过&#8211;with-sasl=指定一个。</p>
<p>认证发生在两种情况，客户端连接c2s组件，组件连接router。由于我不想再去分析一个客户端，所以c2s连接router为例分析认证过程。</p>
<p>先简单描述下jabberd2的启动过程:<br />
jabberd2有四个可执行文件<br />
router:路由器<br />
c2s:组件,负责跟客户端建立连接，注册和验证帐号<br />
sm:组件,会话管理器<br />
s2s:组件,负责和其他xmpp服务器通信</p>
<p>router做为路由器首先启动,启动后会默认监听5347,等待包处理组件连接。</p>
<p>c2s,sm,s2s启动，并连接router，以c2s为例,分析一下往返的xml数据(C代表c2s做为客户端，S代表router做为服务端):<br />
c2s跟router建立连接之后，大家互相寒暄一下，c2s说我吃了，router说他也吃了(互发stream头)</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">C:&lt;?xml version='1.0'?&gt;&lt;stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xmlns:ack='http://www.xmpp.org/extensions/xep-0198.html#ns'&gt;
S:&lt;?xml version='1.0'?&gt;&lt;stream:stream xmlns:stream='http://etherx.jabber.org/streams' version='1.0' id='yqvecsv64nooedcwo2mbt6f8x08krmlpch3oazve'&gt;</pre></div></div>

<p>之后router给出自己支持的验证方式列表,说它只支持DIGEST—MD5</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">S:&lt;stream:features xmlns:stream='http://etherx.jabber.org/streams'&gt;&lt;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;&lt;mechanism&gt;DIGEST-MD5&lt;/mechanism&gt;&lt;/mechanisms&gt;&lt;/stream:features&gt;</pre></div></div>

<p>c2s回应说它接受DIGEST-MD5方式</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">C:&lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/&gt;</pre></div></div>

<p>router给出challenge code</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">S:&lt;challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;cmVhbG09ImphYmJlcmQtcm91dGVyIiwgbm9uY2U9Ii8xb0tDempxMXRNSUlLUHlOYTNCSHc9PSIsIHFvcD0iYXV0aCIsIGNoYXJzZXQ9dXRmLTgsIGFsZ29yaXRobT1tZDUtc2Vzcw==&lt;/challenge&gt;</pre></div></div>

<p>c2s回应:</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">C:&lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;dXNlcm5hbWU9ImphYmJlcmQiLCByZWFsbT0iamFiYmVyZC1yb3V0ZXIiLCBub25jZT0iLzFvS0N6anExdE1JSUtQeU5hM0JIdz09IiwgY25vbmNlPSJueFZNempncTI1VUZtTjZmdUozdEZ3PT0iLCBuYz0wMDAwMDAwMSwgcW9wPWF1dGgsIGRpZ2VzdC11cmk9ImphYmJlcmQtcm91dGVyL2lwLTEwLTEzMC0xODctMTU1IiwgcmVzcG9uc2U9Yzg5NjJlNDgwZTVlYmM0ZjFkNjZiZDhlNDBiNjZlZjIsIGNoYXJzZXQ9dXRmLTg=&lt;/response&gt;</pre></div></div>

<p>router再出一招</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">S:&lt;challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;cnNwYXV0aD1hM2IyMGI0YzZkMzgxNmE3MzVjMWJhNTRjZTVkYmFjYQ==&lt;/challenge&gt;</pre></div></div>

<p>c2s接</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">C:&lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&gt;</pre></div></div>

<p>router说验证通过</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">S:&lt;success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&gt;</pre></div></div>

<p>验证通过之后的逻辑跟这里就无关了，需要注意的是验证通过之后这个stream并没有继续利用，c2s会发一个新的stream头，和router重新开始一个stream会话。</p>
<p>疑问：组件和router之间为什么要有验证机制?<br />
虽然c2s,sm,s2s都在本地运行，但是如果一个远程进程可以连接到5347端口，那么它就可以向router注册。所以验证是必要的，所以5347端口的保护也是必要的。</p>
<p>下面是各个阶段在代码中的体现,主要从c2s的角度分析：<br />
在这之前你必须首先理解jabberd2的io逻辑:<a href="http://bluehua.org/2010/11/28/1479.html">http://bluehua.org/2010/11/28/1479.html</a>(虽然老大表示文采太差，但是我觉得要是画图都不行，那我实在没辙了)</p>
<p>sasl验证逻辑主要位于:sx/sasl_gsasl.c sx/sasl_cyrus.c,这里以sasl_gsasl.c为例<br />
先画一下sasl在jabber2中的位置</p>
<pre>
 +--------------------+
 |  callback(主要逻辑)|     -----
 +--------------------+     |
 |  SX(逻辑通道)      |     -----
 |  plugins     ------+-----+
 +--------------------+     +---- sasl
 |  callback          |     |
 +--------------------+     +----
 |  MIO(底层网络io)   |     |
 +--------------------+     |
</pre>
<p>sasl层以sx插件的形式被初始化,下面为c2s/main.c中注册sasl插件的部分,router中同理</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>706
707
</pre></td><td class="code"><div class="overflow"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* get sasl online */</span>
    c2s<span style="color: #339933;">-&gt;</span>sx_sasl <span style="color: #339933;">=</span> sx_env_plugin<span style="color: #009900;">&#40;</span>c2s<span style="color: #339933;">-&gt;</span>sx_env<span style="color: #339933;">,</span> sx_sasl_init<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;xmpp&quot;</span><span style="color: #339933;">,</span> _c2s_sx_sasl_callback<span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #993333;">void</span> <span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span> c2s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div</td></tr></table></div>

<p>看一下插件的初始化函数sasl_gsasl.c 906:int sx_sasl_init</p>

<div class="wp_syntax"><div class="code overflow"><pre class="c" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//注册了以下几个回调函数</span>
p<span style="color: #339933;">-&gt;</span>unload <span style="color: #339933;">=</span> _sx_sasl_unload<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//当数据送出时回调，貌似有的验证方法需要对送出的数据加密</span>
p<span style="color: #339933;">-&gt;</span>wio <span style="color: #339933;">=</span> _sx_sasl_wio<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//当读入数据时回调，就是解密读入的数据</span>
p<span style="color: #339933;">-&gt;</span>rio <span style="color: #339933;">=</span> _sx_sasl_rio<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//当一个strem建立时回调</span>
p<span style="color: #339933;">-&gt;</span>stream <span style="color: #339933;">=</span> _sx_sasl_stream<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//当声明自己都有哪些特性时回调</span>
p<span style="color: #339933;">-&gt;</span>features <span style="color: #339933;">=</span> _sx_sasl_features<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//当处理xml时回调</span>
p<span style="color: #339933;">-&gt;</span>process <span style="color: #339933;">=</span> _sx_sasl_process<span style="color: #339933;">;</span></pre></div></div>

<p>下面描述一下c2s中的主要情形<br />
&#8230;.读取配置，加载插件<br />
c2s/main.c 728行:<br />
调用_c2s_router_connect初始化与router的sx通道<br />
c2s/main.c 341行:<br />
_c2s_router_connect的最后调用sx_client_init<br />
sx/client.c 111行:<br />
sx_client_init 构造一个stream头<br />
sx/client.c 148行:<br />
sx_client_init为即将写出的头加了一个回调，_sx_client_notify_header</p>
<p>sx写出strem头(具体怎么写还是看我画的那个图),并回调_sx_client_notify_header<br />
sx/client.c 100行:<br />
_sx_client_notify_header中为xml解析注册了两个回调<br />
XML_SetElementHandler(s->expat, (void *) _sx_client_element_start, (void *) _sx_client_element_end);</p>
<p>mio层收到router回的stream头(具体怎么收到还是看我画的那个图&#8230;)<br />
c2s/c2s.c 1308行:<br />
回调到c2s_router_mio_callback<br />
sx/io.c 181行:<br />
c2s_router_mio_callback中调用sx_can_read<br />
sx/io.c 24行:<br />
sx_can_read调用_sx_process_read开始解收到的xml<br />
解析起始标签时回调到_sx_client_element_start<br />
sx/client.c 73行:<br />
_sx_client_element_start解析到router给的stream头,改写xml解析回调<br />
XML_SetElementHandler(s->expat, (void *) _sx_element_start, (void *) _sx_element_end);<br />
sx/client.c 78行:<br />
_sx_client_element_start 已经解析到router的strem头,strem建立,开始执行插件注册的strem回调<br />
中间回调到sasl注册的process回调,_sx_sasl_process,但是不是它需要的包，没有动作.</p>
<p>由于sx_sasl_init前面注册了_sx_sasl_stream回调所以<br />
_sx_sasl_stream用于在一个stream开始时确定是否已经做过sasl验证<br />
sx/sasl_gsasl.c 312行 还没有gsasl session所以执行到316行便返回了</p>
<p>之后sx_can_read解完包触发event_PACKET,回调到c2s_router_sx_callback,没有任何动作</p>
<p>之后c2s收到router的stream:features包</p>

<div class="wp_syntax"><div class="code overflow"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;stream:features</span> <span style="color: #000066;">xmlns:stream</span>=<span style="color: #ff0000;">'http://etherx.jabber.org/streams'</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;mechanisms</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">'urn:ietf:params:xml:ns:xmpp-sasl'</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;mechanism<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>DIGEST-MD5<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mechanism<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/mechanisms<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/stream:features<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>经过mio又是层层回调,来到c2s_router_sx_callback<br />
这回有动作了<br />
c2s/c2s.c 787行:确定它收到了一个stream:features,调用sx_sasl_auth,初始化一个gsasl session<br />
sx_sasl_auth(c2s->sx_sasl, s, “jabberd-router”, “DIGEST-MD5&#8243;, c2s->router_user, c2s->router_pass);<br />
router_user和router_pass均从c2s.xml里读取<br />
sx/sasl_gsasl.c 959行:sx_sasl_auth<br />
初始化一个客户端gsasl session<br />
ret = gsasl_client_start(ctx->gsasl_ctx, mech, &#038;sd);<br />
设置验证需要的数据<br />
gsasl_session_hook_set(sd, (void *) ctx);<br />
gsasl_property_set(sd, GSASL_AUTHID, user);<br />
gsasl_property_set(sd, GSASL_PASSWORD, pass);<br />
gsasl_property_set(sd, GSASL_SERVICE, appname);<br />
gsasl_property_set(sd, GSASL_HOSTNAME, hostname);<br />
//给插件回调传递句柄<br />
s->plugin_data[p->index] = (void *) sd;</p>
<p>/* build the nad */<br />
nad = nad_new();<br />
ns = nad_add_namespace(nad, uri_SASL, NULL);</p>
<p>nad_append_elem(nad, ns, “auth”, 0);<br />
nad_append_attr(nad, -1, “mechanism”, mech);<br />
if(buf != NULL) {<br />
    nad_append_cdata(nad, buf, buflen, 1);<br />
    free(buf);<br />
}</p>
<p>/* its away */<br />
sx_nad_write(s, nad);<br />
构造了一个</p>

<div class="wp_syntax"><div class="code overflow"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;auth</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">'urn:ietf:params:xml:ns:xmpp-sasl'</span> <span style="color: #000066;">mechanism</span>=<span style="color: #ff0000;">'DIGEST-MD5'</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>回应router</p>
<p>router回应</p>

<div class="wp_syntax"><div class="code overflow"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;challenge</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">'urn:ietf:params:xml:ns:xmpp-sasl'</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>cmVhbG09ImphYmJlcmQtcm91dGVyIiwgbm9uY2U9Ii8xb0tDempxMXRNSUlLUHlOYTNCSHc9PSIsIHFvcD0iYXV0aCIsIGNoYXJzZXQ9dXRmLTgsIGFsZ29yaXRobT1tZDUtc2Vzcw==<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/challenge<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>c2s接受<br />
c2s/c2s.c 1308行:<br />
回调到c2s_router_mio_callback<br />
sx/io.c 181行:<br />
c2s_router_mio_callback中调用sx_can_read<br />
sx/io.c 24行:<br />
sx_can_read调用_sx_process_read开始解收到的xml<br />
sx/io.c 142行:这次又回调到了_sx_sasl_process,这次有反应了，因为它匹配到xml中sasl的命名空间<br />
sx/sasl_gsasl.c 700行:调用_sx_sasl_server_process<br />
比较关键的一个函数，全贴出来吧<br />
啥也不解释:看<a href="http://bluehua.org/2010/12/01/1484.html">http://bluehua.org/2010/12/01/1484.html</a><br />
唯一不同就是返回的结果的时候用_sx_sasl_response包成了xml</p>

<div class="wp_syntax"><div class="code overflow"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">static</span> <span style="color: #993333;">void</span> _sx_sasl_server_process<span style="color: #009900;">&#40;</span>sx_t s<span style="color: #339933;">,</span> sx_plugin_t p<span style="color: #339933;">,</span> Gsasl_session <span style="color: #339933;">*</span>sd<span style="color: #339933;">,</span> <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>in<span style="color: #339933;">,</span> <span style="color: #993333;">int</span> inlen<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf <span style="color: #339933;">=</span> NULL<span style="color: #339933;">,</span> <span style="color: #339933;">*</span>out <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
    size_t buflen<span style="color: #339933;">,</span> outlen<span style="color: #339933;">;</span>
    <span style="color: #993333;">int</span> ret<span style="color: #339933;">;</span>
&nbsp;
    _sx_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;data from client&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* decode the response */</span>
    ret <span style="color: #339933;">=</span> gsasl_base64_from<span style="color: #009900;">&#40;</span>in<span style="color: #339933;">,</span> inlen<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>buf<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>buflen<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">==</span> GSASL_OK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        _sx_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;decoded data: %.*s&quot;</span><span style="color: #339933;">,</span> buflen<span style="color: #339933;">,</span> buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* process the data */</span>
        ret <span style="color: #339933;">=</span> gsasl_step<span style="color: #009900;">&#40;</span>sd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> buflen<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>out<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>outlen<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>buf <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> buf <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;">/* in progress */</span>
        <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">==</span> GSASL_OK <span style="color: #339933;">||</span> ret <span style="color: #339933;">==</span> GSASL_NEEDS_MORE<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            _sx_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;sasl handshake in progress (response: %.*s)&quot;</span><span style="color: #339933;">,</span> outlen<span style="color: #339933;">,</span> out<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #808080; font-style: italic;">/* encode the response */</span>
            ret <span style="color: #339933;">=</span> gsasl_base64_to<span style="color: #009900;">&#40;</span>out<span style="color: #339933;">,</span> outlen<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>buf<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>buflen<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>ret <span style="color: #339933;">==</span> GSASL_OK<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                _sx_nad_write<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">,</span> _sx_sasl_response<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> buflen<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>out <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>out<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>buf <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>out <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>out<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>buf <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* its over */</span>
    _sx_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;sasl handshake aborted; (%d): %s&quot;</span><span style="color: #339933;">,</span> ret<span style="color: #339933;">,</span> gsasl_strerror<span style="color: #009900;">&#40;</span>ret<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    _sx_nad_write<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">,</span> _sx_sasl_abort<span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>sasl_gsasl.c 611行的_sx_nad_write之后，这次处理就算结束了<br />
之后router继续给出challenge,c2s重复上面处理<br />
最后router给出结果</p>

<div class="wp_syntax"><div class="code overflow"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;success</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">'urn:ietf:params:xml:ns:xmpp-sasl'</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>重复上面，但是回调到_sx_sasl_process,处理方式就不一样了,调用了sx_client_init(s, flags, ns, to, from, version); 重新开启了一个stream</p>

<div class="wp_syntax"><div class="code overflow"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/* success */</span>
<span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>NAD_ENAME_L<span style="color: #009900;">&#40;</span>nad<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">7</span> <span style="color: #339933;">&amp;&amp;</span> strncmp<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;success&quot;</span><span style="color: #339933;">,</span> NAD_ENAME<span style="color: #009900;">&#40;</span>nad<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> NAD_ENAME_L<span style="color: #009900;">&#40;</span>nad<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    _sx_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;sasl handshake completed, resetting&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    nad_free<span style="color: #009900;">&#40;</span>nad<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* save interesting bits */</span>
    flags <span style="color: #339933;">=</span> s<span style="color: #339933;">-&gt;</span>flags<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>ns <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> ns <span style="color: #339933;">=</span> strdup<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>ns<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>req_to <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> to <span style="color: #339933;">=</span> strdup<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>req_to<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>req_from <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> from <span style="color: #339933;">=</span> strdup<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>req_from<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>req_version <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> version <span style="color: #339933;">=</span> strdup<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">-&gt;</span>req_version<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* reset state */</span>
    _sx_reset<span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    _sx_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;restarting stream with sasl layer established&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* second time round */</span>
    sx_client_init<span style="color: #009900;">&#40;</span>s<span style="color: #339933;">,</span> flags<span style="color: #339933;">,</span> ns<span style="color: #339933;">,</span> to<span style="color: #339933;">,</span> from<span style="color: #339933;">,</span> version<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* free bits */</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>ns <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>ns<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>to <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>to<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>from <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>from<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>version <span style="color: #339933;">!=</span> NULL<span style="color: #009900;">&#41;</span> free<span style="color: #009900;">&#40;</span>version<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>继续说下这个新起的stream把,它毫无疑问的回调到了sasl插件注册的_sx_sasl_stream,上次回调它什么都没做，是因为s->plugin_data[p->index]为NULL，但是前一个stream中在执行sx_sasl_auth时把一个gsasl seesion给了它,所以这次的逻辑就不一样了<br />
sx/sasl_gsasl.c 326:它会继续调用_sx_sasl_open,来校验stream是否已经通过sasl验证.如果是它最终会执行<br />
_sx_state(s, state_OPEN);<br />
_sx_event(s, event_OPEN, NULL);<br />
将这个通道的状态从state_STREAM变为 stat_OPEN,触发事件event_OPEN;</p>
<p>再看一下c2s_router_sx_callback中针对event_OPEN的处理吧</p>

<div class="wp_syntax"><div class="code overflow"><pre class="c" style="font-family:monospace;"><span style="color: #b1b100;">case</span> event_OPEN<span style="color: #339933;">:</span>
    log_write<span style="color: #009900;">&#40;</span>c2s<span style="color: #339933;">-&gt;</span>log<span style="color: #339933;">,</span> LOG_NOTICE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;connection to router established&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/* set connection attempts counter */</span>
    c2s<span style="color: #339933;">-&gt;</span>retry_left <span style="color: #339933;">=</span> c2s<span style="color: #339933;">-&gt;</span>retry_lost<span style="color: #339933;">;</span>
&nbsp;
    nad <span style="color: #339933;">=</span> nad_new<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    ns <span style="color: #339933;">=</span> nad_add_namespace<span style="color: #009900;">&#40;</span>nad<span style="color: #339933;">,</span> uri_COMPONENT<span style="color: #339933;">,</span> NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    nad_append_elem<span style="color: #009900;">&#40;</span>nad<span style="color: #339933;">,</span> ns<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;bind&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    nad_append_attr<span style="color: #009900;">&#40;</span>nad<span style="color: #339933;">,</span> <span style="color: #339933;">-</span><span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;name&quot;</span><span style="color: #339933;">,</span> c2s<span style="color: #339933;">-&gt;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    log_debug<span style="color: #009900;">&#40;</span>ZONE<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;requesting component bind for '%s'&quot;</span><span style="color: #339933;">,</span> c2s<span style="color: #339933;">-&gt;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    sx_nad_write<span style="color: #009900;">&#40;</span>c2s<span style="color: #339933;">-&gt;</span>router<span style="color: #339933;">,</span> nad<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span></pre></div></div>

<p>开始一个绑定到router的bind请求!</p>
<p>OK,验证部分到此结束。。。，其他部分分析稍候</p>
<p>&#8212;&#8212;&#8212;&#8211;<br />
post by gmail~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/12/01/1486.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>关于sasl</title>
		<link>http://bluehua.org/2010/12/01/1484.html</link>
		<comments>http://bluehua.org/2010/12/01/1484.html#comments</comments>
		<pubDate>Wed, 01 Dec 2010 05:32:40 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[sasl]]></category>

		<guid isPermaLink="false">http://bluehua.org/2010/12/01/1484.html</guid>
		<description><![CDATA[sasl(Simple Authentication and Security Layer)是一个用于网络通信协议的安全验证框架，它可以使网络协议在互相验证的阶段可以有多种验证方式可以选择。 现在实现sasl的协议主要有imap,smtp,pop,xmpp,subersion,&#8230;.。举个smtp的例子说明一下sasl的验证流程: 1 2 3 4 5 6 7 8 250-mail.example.com Hello pc.example.org [192.168.1.42], pleased to meet you 250-AUTH DIGEST-MD5 CRAM-MD5 LOGIN PLAIN AUTH LOGIN 334 VXNlcm5hbWU6 eHh4eAo= 334 UGFzc3dvcmQ6 b294eAo= 235 2.0.0 OK Authenticated]]></description>
			<content:encoded><![CDATA[<p>sasl(Simple Authentication and Security Layer)是一个用于网络通信协议的安全验证框架，它可以使网络协议在互相验证的阶段可以有多种验证方式可以选择。</p>
<p>现在实现sasl的协议主要有imap,smtp,pop,xmpp,subersion,&#8230;.。举个smtp的例子说明一下sasl的验证流程:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><div class="overflow"><pre class="text" style="font-family:monospace;">250-mail.example.com Hello pc.example.org [192.168.1.42], pleased to meet you
250-AUTH DIGEST-MD5 CRAM-MD5 LOGIN PLAIN
AUTH LOGIN 
334 VXNlcm5hbWU6
eHh4eAo=
334 UGFzc3dvcmQ6
b294eAo=
235 2.0.0 OK Authenticated</pre></div</td></tr></table></div>

<p>1 和smtp sever建立连接后,server发送欢迎信息<br />
2 server发送自己支持的验证方式DIGEST-MD5 CRAM-MD5 LOGIN PLAIN<br />
3 client择使用LOGIN<br />
4 server发送base64后的challenge code,base64解码后为Username:要求client回应一个用户名<br />
5 client回应base64后的用户名<br />
6 server发送base64后的challenge code,base64解码后为Password:要求client回应一个密码<br />
7 client回应base64后的密码<br />
8 server返回验证成功的信息 </p>
<p>很简单的流程，服务端给出选择，客户端选一个，然后根据验证方式不同进行验证流程，由于sasl仅仅是个框架，具体怎么实现是由协议决定的，比如xmpp协议的sasl验证流程</p>

<div class="wp_syntax"><div class="code overflow"><pre class="text" style="font-family:monospace;">#client与server建立链接后发出一个strem头
C:&lt;stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='example.com' version='1.0'&gt;
#server回应一个steam头
S:&lt;stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='c2s_234' from='example.com' version='1.0'&gt;
#server发送自己支持的验证方式列表
S:&lt;stream:features&gt;
     &lt;mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;
       &lt;mechanism&gt;DIGEST-MD5&lt;/mechanism&gt;
       &lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
     &lt;/mechanisms&gt;
&lt;/stream:features&gt;
#client 说它要用DIGEST-MD5做验证
C:
&lt;auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/&gt;
#server 发送challenge code
S:&lt;challenge xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;
   cmVhbG09InNvbWVyZWFsbSIsbm9uY2U9Ik9BNk1HOXRFUUdtMmhoIixxb3A9ImF1dGgi
   LGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNzCg==
&lt;/challenge&gt;
#client 回应challenge
C:
&lt;response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'&gt;
   dXNlcm5hbWU9InNvbWVub2RlIixyZWFsbT0ic29tZXJlYWxtIixub25jZT0i
   T0E2TUc5dEVRR20yaGgiLGNub25jZT0iT0E2TUhYaDZWcVRyUmsiLG5jPTAw
   MDAwMDAxLHFvcD1hdXRoLGRpZ2VzdC11cmk9InhtcHAvZXhhbXBsZS5jb20i
   LHJlc3BvbnNlPWQzODhkYWQ5MGQ0YmJkNzYwYTE1MjMyMWYyMTQzYWY3LGNo
   YXJzZXQ9dXRmLTgK
   &lt;/response&gt;
#server 回应验证结果
S:
&lt;success xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/&gt;</pre></div></div>

<p>当你实现一个协议的sasl部分时，如果你仅仅打算实现一两种验证方式，那么寥寥代码便可以搞定，但是如果希望提供尽可能多的验证方式，那么使用一些开源类库将是最好的选择。<br />
对于C语言有两个成熟的lib:Cyrus SASL和libgsasl。以gsasl为例:</p>
<p>gsasl屏蔽了具体验证的细节，你要做的仅仅是为验证流程提供必要的信息，比如：用户名，密码，验证域等等<br />
还是以上面的smtp验证为例，假设我们是client端，现在收到的server的mechlist，即验证方式列表，我们使用gsasl实现这次验证(虽然是我虚构的代码，但理论是可行的:))：</p>

<div class="wp_syntax"><div class="code overflow"><pre class="c" style="font-family:monospace;">Gsasl <span style="color: #339933;">*</span>ctx <span style="color: #339933;">=</span> NULL<span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> buffer<span style="color: #009900;">&#91;</span>BUFSIZ<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>buf<span style="color: #339933;">;</span>
Gsasl_session <span style="color: #339933;">*</span>session<span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> rc<span style="color: #339933;">;</span>
<span style="color: #993333;">char</span> <span style="color: #339933;">*</span>p<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//使用gsasl之前初始化</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>rc <span style="color: #339933;">=</span> gsasl_init <span style="color: #009900;">&#40;</span><span style="color: #339933;">&amp;</span>ctx<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> GSASL_OK<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span> <span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Cannot initialize libgsasl (%d): %s&quot;</span><span style="color: #339933;">,</span>
        rc<span style="color: #339933;">,</span> gsasl_strerror <span style="color: #009900;">&#40;</span>rc<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//创建一个使用LOGIN验证方式的客户端session</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>rc <span style="color: #339933;">=</span> gsasl_client_start <span style="color: #009900;">&#40;</span>ctx<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;LOGIN&quot;</span><span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>session<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> GSASL_OK<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">printf</span> <span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Cannot initialize client (%d): %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
       rc<span style="color: #339933;">,</span> gsasl_strerror <span style="color: #009900;">&#40;</span>rc<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//设置用户名和密码</span>
gsasl_property_set <span style="color: #009900;">&#40;</span>session<span style="color: #339933;">,</span> GSASL_AUTHID<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;username&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
gsasl_property_set <span style="color: #009900;">&#40;</span>session<span style="color: #339933;">,</span> GSASL_PASSWORD<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;password&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//假设socket_fd为我们与server已经建立连接的描述字</span>
&nbsp;
<span style="color: #666666; font-style: italic;">//告诉server我们选择使用LOGIN做验证</span>
buf <span style="color: #339933;">=</span> buffer<span style="color: #339933;">;</span>
sprintf<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;AUTH LOGIN<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
write<span style="color: #009900;">&#40;</span>socket_fd<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> strlen<span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">do</span>
 <span style="color: #009900;">&#123;</span>
   buf <span style="color: #339933;">=</span> buffer<span style="color: #339933;">;</span>
   <span style="color: #666666; font-style: italic;">//从server读取一行，</span>
   readline<span style="color: #009900;">&#40;</span>buf<span style="color: #339933;">,</span> <span style="color: #993333;">sizeof</span> <span style="color: #009900;">&#40;</span>buf<span style="color: #009900;">&#41;</span> <span style="color: #339933;">-</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> socket_fd<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #666666; font-style: italic;">//334 是多余的 </span>
   buf <span style="color: #339933;">+=</span> <span style="color: #0000dd;">4</span><span style="color: #339933;">;</span>
   <span style="color: #666666; font-style: italic;">//将challenge code 交给gsasl处理</span>
   rc <span style="color: #339933;">=</span> gsasl_step64 <span style="color: #009900;">&#40;</span>session<span style="color: #339933;">,</span> buf<span style="color: #339933;">,</span> <span style="color: #339933;">&amp;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>rc <span style="color: #339933;">==</span> GSASL_NEEDS_MORE <span style="color: #339933;">||</span> rc <span style="color: #339933;">==</span> GSASL_OK<span style="color: #009900;">&#41;</span>
     <span style="color: #009900;">&#123;</span>
       <span style="color: #666666; font-style: italic;">//将gsasl的处理结果发送给server</span>
       write<span style="color: #009900;">&#40;</span>socket_fd<span style="color: #339933;">,</span> p<span style="color: #339933;">,</span> strlen<span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       free <span style="color: #009900;">&#40;</span>p<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span>rc <span style="color: #339933;">==</span> GSASL_NEEDS_MORE<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>rc <span style="color: #339933;">!=</span> GSASL_OK<span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
   <span style="color: #000066;">printf</span> <span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Authentication error (%d): %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span>
           rc<span style="color: #339933;">,</span> gsasl_strerror <span style="color: #009900;">&#40;</span>rc<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #b1b100;">return</span><span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000066;">printf</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;success!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
gsasl_finish <span style="color: #009900;">&#40;</span>session<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
gsasl_done <span style="color: #009900;">&#40;</span>ctx<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>使用gsasl可以让我们用类似上面代码处理所有的验证方式，唯一不同的就在于使用gsasl_property_set设置不同的字段。</p>
<p>除了像上面一样直接设置验证字段,还可以通过回调函数设置,当gsasl需要某一字段时会触发回调函数</p>

<div class="wp_syntax"><div class="code overflow"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> callback <span style="color: #009900;">&#40;</span>Gsasl <span style="color: #339933;">*</span> ctx<span style="color: #339933;">,</span> Gsasl_session <span style="color: #339933;">*</span> sctx<span style="color: #339933;">,</span> Gsasl_property prop<span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
   <span style="color: #993333;">char</span> buf<span style="color: #009900;">&#91;</span>BUFSIZ<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;&quot;</span><span style="color: #339933;">;</span>
   <span style="color: #993333;">int</span> rc <span style="color: #339933;">=</span> GSASL_NO_CALLBACK<span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #b1b100;">switch</span> <span style="color: #009900;">&#40;</span>prop<span style="color: #009900;">&#41;</span>
     <span style="color: #009900;">&#123;</span>
     <span style="color: #b1b100;">case</span> GSASL_AUTHID<span style="color: #339933;">:</span>
       gsasl_property_set <span style="color: #009900;">&#40;</span>sctx<span style="color: #339933;">,</span> GSASL_AUTHID<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;username&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       rc <span style="color: #339933;">=</span> GSASL_OK<span style="color: #339933;">;</span>
       <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
     <span style="color: #666666; font-style: italic;">// .............. </span>
     <span style="color: #b1b100;">default</span><span style="color: #339933;">:</span>
       <span style="color: #000066;">printf</span> <span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Unknown property!  Don't worry.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
       <span style="color: #000000; font-weight: bold;">break</span><span style="color: #339933;">;</span>
     <span style="color: #009900;">&#125;</span>
&nbsp;
   <span style="color: #b1b100;">return</span> rc<span style="color: #339933;">;</span>
 <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//.................</span>
gsasl_callback_set <span style="color: #009900;">&#40;</span>ctx<span style="color: #339933;">,</span> callback<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>好了，不能够再详细了，我的主要目的是分析jabberd2的验证逻辑，关于gsasl的更多请参考:<a href="http://www.gnu.org/software/gsasl/manual/gsasl.html">http://www.gnu.org/software/gsasl/manual/gsasl.html</a></p>
<p>其他参考:<a href="http://wiki.jabbercn.org/index.php?title=RFC3920&#038;variant=zh-cn">http://wiki.jabbercn.org/index.php?title=RFC3920&#038;variant=zh-cn</a></p>
<p>&#8212;&#8212;&#8212;&#8211;<br />
post by gmail~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/12/01/1484.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ubuntu10.10升级日志~</title>
		<link>http://bluehua.org/2010/10/15/1447.html</link>
		<comments>http://bluehua.org/2010/10/15/1447.html#comments</comments>
		<pubDate>Fri, 15 Oct 2010 07:36:47 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://bluehua.org/2010/10/15/1447.html</guid>
		<description><![CDATA[波波同学说俺很久没更新blog了，一看时间，真的有一个多月没写啥了。。，罪过，就写写俺这次的ubuntu 10.10升级历险记吧~ ubuntu的平滑升级做的一点都不好，升级中出问题很平常，俺的这次10.10升级理所当然的遇到了些问题: 恩，包的下载和安装过程很漫长，于是就放一边没理，快下班的时候看了一下，安装进度停在cpus相关的一个包上卡住了，等了十分钟还是不动，这个时候有点想俺Ctrl+c的冲动了，但是想想估计终止之后系统就要重装了，实在不想重新配置一遍，就碰运气执行了一下 sudo /etc/init.d/cups stop，Oh year,升级进度继续了~ 更新完提示一些软件包不再需要，问要不要删除，这个时候我犯贱了，看都没看，直接点了个是，导致后面重启后的事故。。 升级完毕，重启，进不了登录界面，面对这种情况我已经很淡定了，重启，恢复模式进入命令行，aptitude search fglrx,恩，官方驱动已经没了，删掉老的配置文件sudo rm /etc/X11/xorg.conf,尝试startx,报错: Failed to load module “ati” &#8230; 一个可用的显卡驱动都没有.aptitude search xserver-xorg，果真很不靠谱，列表里的驱动竟然一个都没装，肯定也被清理了。 ping了一下网络能用，打算把官方驱动再装上，sudo apt-get install fglrx,又恢复了一份以前备份的xorg.conf, 重启,可以进入桌面，但是渲染速度慢的不能容忍，google一下，原来还没有适用当前内核的fglrx,转而安装开源驱动:sudo apt-get install xserver-xorg-video-ati, 报错,具体错误忘了记录，大体意思就是它依赖比较新的xserver-xorg-core,但是种种原因xserver-xorg-core不会被安装. 第一次遇到这种包依赖问题,又去google，发现aptitude install这个没有超级牛力的命令可以解决。果真aptitude给出各种解决依赖问题的方案：比如让您卸载掉xserver和ubuntu-desktop,这样您就不要安装显卡驱动，因为您的系统只剩命令行了。。，这次我看清了，没有输入Y,然后继续给出种种方案，最后，看到一个比较靠谱版本，忘了记下来，大体是降低xserver版本，然后安装低版本的ati开源驱动，输入Y，执行完毕，删除/etc/X11/xorg.conf 重启，顺利进入系统，特效可以开启，OVER 10.10没有太多惊喜,外观上默认主题稍有变化,建议修改一下选中颜色,不怎么好看~ &#8212;&#8212;&#8212;&#8211; post by gmail~]]></description>
			<content:encoded><![CDATA[<p>波波同学说俺很久没更新blog了，一看时间，真的有一个多月没写啥了。。，罪过，就写写俺这次的ubuntu 10.10升级历险记吧~</p>
<p>ubuntu的平滑升级做的一点都不好，升级中出问题很平常，俺的这次10.10升级理所当然的遇到了些问题:</p>
<p>恩，包的下载和安装过程很漫长，于是就放一边没理，快下班的时候看了一下，安装进度停在cpus相关的一个包上卡住了，等了十分钟还是不动，这个时候有点想俺Ctrl+c的冲动了，但是想想估计终止之后系统就要重装了，实在不想重新配置一遍，就碰运气执行了一下 sudo /etc/init.d/cups stop，Oh year,升级进度继续了~</p>
<p>更新完提示一些软件包不再需要，问要不要删除，这个时候我犯贱了，看都没看，直接点了个是，导致后面重启后的事故。。</p>
<p>升级完毕，重启，进不了登录界面，面对这种情况我已经很淡定了，重启，恢复模式进入命令行，aptitude search fglrx,恩，官方驱动已经没了，删掉老的配置文件sudo rm /etc/X11/xorg.conf,尝试startx,报错: Failed to load module “ati” &#8230; 一个可用的显卡驱动都没有.aptitude search xserver-xorg，果真很不靠谱，列表里的驱动竟然一个都没装，肯定也被清理了。</p>
<p>ping了一下网络能用，打算把官方驱动再装上，sudo apt-get install fglrx,又恢复了一份以前备份的xorg.conf, 重启,可以进入桌面，但是渲染速度慢的不能容忍，google一下，原来还没有适用当前内核的fglrx,转而安装开源驱动:sudo apt-get install xserver-xorg-video-ati, 报错,具体错误忘了记录，大体意思就是它依赖比较新的xserver-xorg-core,但是种种原因xserver-xorg-core不会被安装.<br />
第一次遇到这种包依赖问题,又去google，发现aptitude install这个没有超级牛力的命令可以解决。果真aptitude给出各种解决依赖问题的方案：比如让您卸载掉xserver和ubuntu-desktop,这样您就不要安装显卡驱动，因为您的系统只剩命令行了。。，这次我看清了，没有输入Y,然后继续给出种种方案，最后，看到一个比较靠谱版本，忘了记下来，大体是降低xserver版本，然后安装低版本的ati开源驱动，输入Y，执行完毕，删除/etc/X11/xorg.conf 重启，顺利进入系统，特效可以开启，OVER</p>
<p>10.10没有太多惊喜,外观上默认主题稍有变化,建议修改一下选中颜色,不怎么好看~</p>
<p>&#8212;&#8212;&#8212;&#8211;<br />
post by gmail~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/10/15/1447.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>速度创建一个grub启动盘</title>
		<link>http://bluehua.org/2010/08/13/1424.html</link>
		<comments>http://bluehua.org/2010/08/13/1424.html#comments</comments>
		<pubDate>Fri, 13 Aug 2010 11:36:03 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[grub4dos]]></category>
		<category><![CDATA[syslinux]]></category>

		<guid isPermaLink="false">http://bluehua.org/2010/08/13/1424.html</guid>
		<description><![CDATA[写了个shell，可以把U盘快速变成一个Grub启动盘，防灾必备~ 恩,我采用了syslinux引导grub4dos的方式，这样不用给u盘格ext分区，使用脚本之前要现确保一下U盘是fat格式,不是的话mkfs.vfat格一下，之后下载下面这个shell http://code-of-emptyhua.googlecode.com/svn/trunk/shell/mkgrubusb/bin/mkgrubusb.bin 然后运行下 #/dev/sdb4是u盘的设备号,因人而异,可用df命令查到 sudo ./mkgrubusb.bin /dev/sdb4 如果提示成功,就可以用了 &#8212;&#8212;&#8212;&#8211; post by gmail~]]></description>
			<content:encoded><![CDATA[<p>写了个shell，可以把U盘快速变成一个Grub启动盘，防灾必备~<br />
恩,我采用了syslinux引导grub4dos的方式，这样不用给u盘格ext分区，使用脚本之前要现确保一下U盘是fat格式,不是的话mkfs.vfat格一下，之后下载下面这个shell<br />
<a href="http://code-of-emptyhua.googlecode.com/svn/trunk/shell/mkgrubusb/bin/mkgrubusb.bin">http://code-of-emptyhua.googlecode.com/svn/trunk/shell/mkgrubusb/bin/mkgrubusb.bin</a><br />
然后运行下</p>

<div class="wp_syntax"><div class="code overflow"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#/dev/sdb4是u盘的设备号,因人而异,可用df命令查到</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> .<span style="color: #000000; font-weight: bold;">/</span>mkgrubusb.bin <span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>sdb4</pre></div></div>

<p>如果提示成功,就可以用了</p>
<p>&#8212;&#8212;&#8212;&#8211;<br />
post by gmail~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/08/13/1424.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>汉字转拼音的C语言版本</title>
		<link>http://bluehua.org/2010/07/30/1410.html</link>
		<comments>http://bluehua.org/2010/07/30/1410.html#comments</comments>
		<pubDate>Fri, 30 Jul 2010 15:55:07 +0000</pubDate>
		<dc:creator>冥王星2011</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[汉字转拼音]]></category>

		<guid isPermaLink="false">http://bluehua.org/2010/07/30/1410.html</guid>
		<description><![CDATA[2011.11.23日更新 请移步到:http://code.google.com/p/bash-pinyin-completion/ 更新了一个靠谱的拼音库 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; 2010.8.5日更新，svn版本12 修正了部分多音字拼音的优先级顺序 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8230;，本周接到用C的任务，搞定了一个生成头像的fastcgi程序，这个转拼音的写好了给别人用，我对C终于不是那么恐惧了~ 生成可执行文件可以直接用,多音字会用&#124;分开 $ echo 中国淫 &#124; ./hz2py zhong guo yan&#124;yao&#124;yin 编译: gcc -D HZ2PY_BINARY hz2py.c -o hz2py 源代码:http://code-of-emptyhua.googlecode.com/svn/trunk/chz2py/src/hz2py.c 可执行文件:http://code-of-emptyhua.googlecode.com/svn/trunk/bin/hz2py &#8212;&#8212;&#8212;&#8211; post by gmail~]]></description>
			<content:encoded><![CDATA[<p>2011.11.23日更新<br />
请移步到:http://code.google.com/p/bash-pinyin-completion/<br />
更新了一个靠谱的拼音库<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
2010.8.5日更新，svn版本12<br />
修正了部分多音字拼音的优先级顺序<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
&#8230;，本周接到用C的任务，搞定了一个生成头像的fastcgi程序，这个转拼音的写好了给别人用，我对C终于不是那么恐惧了~</p>
<p>生成可执行文件可以直接用,多音字会用|分开</p>

<div class="wp_syntax"><div class="code overflow"><pre class="bash" style="font-family:monospace;">$ <span style="color: #7a0874; font-weight: bold;">echo</span> 中国淫 <span style="color: #000000; font-weight: bold;">|</span> .<span style="color: #000000; font-weight: bold;">/</span>hz2py 
zhong guo yan<span style="color: #000000; font-weight: bold;">|</span>yao<span style="color: #000000; font-weight: bold;">|</span>yin</pre></div></div>

<p>编译:</p>

<div class="wp_syntax"><div class="code overflow"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-D</span> HZ2PY_BINARY hz2py.c <span style="color: #660033;">-o</span> hz2py</pre></div></div>

<p>源代码:<a href="http://code-of-emptyhua.googlecode.com/svn/trunk/chz2py/src/hz2py.c">http://code-of-emptyhua.googlecode.com/svn/trunk/chz2py/src/hz2py.c</a><br />
可执行文件:<a href="http://code-of-emptyhua.googlecode.com/svn/trunk/chz2py/bin/hz2py">http://code-of-emptyhua.googlecode.com/svn/trunk/bin/hz2py</a></p>
<p>&#8212;&#8212;&#8212;&#8211;<br />
post by gmail~</p>
]]></content:encoded>
			<wfw:commentRss>http://bluehua.org/2010/07/30/1410.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.788 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-02-05 02:31:31 -->

