2008年11月6日
#
摘要: 这部分的作用是客户端可以存放任意格式的私有xml数据到服务器上,并且在想要查看的时候取回!1.协议 - XEP-0049 - http://xmpp.org/extensions/xep-0049.html2. jabber client可以保存任意的xml数据到服务器,通过一个<iq type="set">的请求.该请求需要包含一个名称空间为jabber:iq:priva...
阅读全文
摘要: #jabber协议中如何注册一个用户?首先要与服务器建立一个连接, 在完成TLS握手之后就可以进行注册了,为什么不需要SASL握手呢?因为SASL握手只针对已经注册的用户在登陆服务器的时候使用.(修改密码和删除用户的时候需要SASL握手)下面以openfire作为服务器,注册一个用户的过程如下:(假设已经完成了TLS握手)1. ( C->S ) <stream:stream  ...
阅读全文
2008年11月3日
#
摘要: 1. websiteSSL(secure Socket Layer)TLS(transport Layer Security) - SSL3.0基础之上提出的安全通信标准,目前版本是1.0openssl 主页 -> http://www.openssl.org/openssl 中文文档 -> http://www.chinaunix.net/jh/13/478901.html
2. 如何编译O...
阅读全文
2008年10月29日
#
客户端与gtalk server建立会话的过程如下(默认中间没有错误发生):
1. ( C->S ) 连接到服务器, 发送'hello'信息.
<stream:stream to="gmail.com" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">
2. ( S->C ) 服务器回应'hello'信息
<?xml version="1.0" encoding="UTF-8"?>
<stream:stream from="gmail.com" id="A9D1B4DB24EA879C" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">
3. ( S->C ) 服务器要求TLS, SASL
<stream:features>
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"><required/></starttls>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>X-GOOGLE-TOKEN</mechanism>
</mechanisms>
</stream:features>
4. ( C->S ) 开始TLS
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
5. ( S->C ) 服务器允许继续TLS
<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
6. ( C->S ) TLS握手
客户端向服务器发起TLS握手请求, 如果握手成功, 执行#7 (可以使用openssl实现TLS的握手功能)
7. ( C->S ) TLS握手结束后, 发送新的'hello'消息
<stream:stream to="gmail.com" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">
8. ( S->C ) 服务器回应'hello'消息
<?xml version="1.0" encoding="UTF-8"?>
<stream:stream from="gmail.com" id="D38877BD862E0EE4" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">
9. ( S->C ) 服务器要求SASL
<stream:features>
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>PLAIN</mechanism>
<mechanism>X-GOOGLE-TOKEN</mechanism>
</mechanisms>
</stream:features>
10. ( C->S ) 客户端执行SASL
<auth xmlns="urn:ietf:params:xml:ns:xmpp-sasl" mechanism="PLAIN">
AHlzb25nLmxlZUBnbWFpbC5jb20AeXNvbmdAMTk4NA==
</auth>
auth的cdata的格式 '\0'+username+'\0'+password 的base64编码, username和password必须是经过认证的.
例如:
'\0' +
'ysong.lee@gmail.com' + '\0' + 123456 -> 经过base64编码处理后变为cdata
11. ( S->C ) SASL成功
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
12. ( C->S ) 客户端发送新的'hello'消息
<stream:stream to="gmail.com" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">
13. ( S->C ) 服务器回应'hello'消息
<?xml version="1.0" encoding="UTF-8"?>
<stream:stream from="gmail.com" id="00035A2B998BF4B9" version="1.0" xmlns:stream="
http://etherx.jabber.org/streams" xmlns="jabber:client">
14. ( S->C ) 服务器要求绑定资源和建立一个会话
<stream:features>
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/>
<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</stream:features>
15. ( C->S ) 客户端绑定申请一个资源
<iq type="set" id="1"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></iq>
16. ( S->C ) 服务器返回绑定资源的结果
<iq id="1" type="result">
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
<jid>ysong.lee@gmail.com/BC20B630</jid>
</bind>
</iq>
17. ( C->S ) 客户端申请建立会话
<iq type="set" id="2">
<session xmlns="urn:ietf:params:xml:ns:xmpp-session"/>
</iq>
18. ( S->C ) 服务器返回建立会话成功
<iq type="result" id="2"/>
到此, Client和Gtalk server的一个会话已经建立, 可以根据jabber协议进行其它操作. 请求联系人列表, 发消息等.
2008年10月22日
#
摘要: 1. 使用OpenSSL内置的数据结构BIO可以方便的创建安全和非安全链接,在IBM Web上的"使用OpenSSL进行安全编程"系列的三篇文章是个不错的入门:http://www.ibm.com/developerworks/cn/linux/l-openssl.htmlhttp://www.ibm.com/developerworks/cn/linux/l-openssl2.htmlhttp:...
阅读全文
2008年10月18日
#
2008年10月17日
#
主要分析gloox的connect模块,涉及的文件:
connectionbase.h
connectiondatahander.h
connectionhandler.h
connectiontcpbase.h (connectiontcpbase.cpp)
connectiontcpclient.h (connectiontcpclient.cpp)
connectiontcpserver.h (connectiontcpserver.cpp)
1. ConnectionBase抽象连接类,表示一个socket连接。3个数据成员:
server和ip - 需要连接到的目标地址和端口(在ConnectionTcpServer是要绑定的本地地址)
connectionState - 连接的当前状态 (一个三种状态disconnected | connecting | connected)
connectionDataHandler - 处理三类ConnectionBase中的三类事件 ( 数据接收 | 连接建立 | 连接断开 )
5个主要方法:
connect - 建立一个socket连接
disconnect - 断开一个socket连接
send - 发送数据,该方法直到要发送的数据全部发送完毕才返回
recv( int timeout ) - 接收数据,接收到数据或者timeout返回
receive - 把connection设置成"接收模式",也就是循环的调用recv接收数据,直到连接断开该方法返回,
该方法保证这个连接可以循环的接收数据.
注意: recv和receive的区别。
2. ConnectionDataHandler处理继承自ConnectionBase的对象的事件handlerReceivedData - 接收到数据
handlerConnect - 一个原始的套接字连接建立
handlerDisconnect - 一个原始的套接字连接断开
3. ConnectionTcpBase一个基本的TCP连接,继承自ConnectionBase数据成员
bool cancel - 表示连接是否应该断开,默认为true. (true表示连接断开)
函数disconnect也就是仅仅设置cancel为true.
在函数receive循环接收数据的逻辑中会检测cancel,如果为true,则表示连接断开,则返回,退出"接收模式"
int bufSize - buf的大小,默认是1024
char* buf - 缓冲区,大小事bufSize + 1 (在ConnectionTcpBase中并没有用到这个缓冲区,供上层使用E.g. ConnectionTcpClient的recv来接收数据)
实现的主要方法:
send - 发送数据
receive - "循环"接收数据
dataAvailable( int timeout ) - 一个私有方法,作用是测试socket上目前是否有数据可读,如果有返回true. 可以供recv调用. 避免了阻塞的调用原始套接字方法::receive或者::accept.
4. ConnectionTcpClient实现一个基本的TCP连接,继承自ConnectionTcpBase实现的主要方法
connect - 连接到目标地址,如果成功,则调用handler->handlerConnect,失败则调用handler->handlerDisconnect
recv - 接收数据,如果接收到数据,马上调用handler->handlerReceiveData,接收发生错误,表示连接断开,调用handler->handlerDisconnect
5. ConnectionHandler一个抽象类,用来接收一个客户端连接的请求,该类用于ConnectionTcpServer
只有一个接口:
handleIncomingConnection( ConnectionBase *connect ) - &connect表示新建立的连接请求,哪原始的socket做类比相当于accept返回的socket.
注意: 区别于ConnectionDataHandler用于处理一个特定连接的中的事件(数据到来,连接断开,连接建立),ConnectionListener用于XMPP Stream.
6. ConnectionTcpServer,实质上就是一个侦听socket,同原始的socket做类比就是一个调用了bind/listen之后处于侦听状态的socket.主要数据成员:
connectionHandler - 接收新到来的连接,接收到之后调用handlerIncomingConnection
主要方法:
connect - 建立套接字,绑定到本地地址,侦听bind/listen
recv - 调用accept接收一个socket连接,如果成功,则用accpet返回的socket创建一个ConnectionTCPClient,调用handlerIncomingConnection来处理新进的连接.
总结:
ConnectionTcpServer和ConnectionTcpClient的区别:
connect (client) - 连接到服务器,使connection处于可以接收数据的状态
connect(server) - 绑定到本地地址,侦听,使connection处于可以接收新连接的状态(accept)
recv(client) - 接收数据,调用connectionDataHandler->handlerReceivedData
recv(server) - 接收新连接,调用connectionHandler->handlerIncomingConnection
receive(Client) - 接收数据状态,循环接收数据,调用disconnect时退出
receive(Server) - 接收连接状态,循环接收连接,调用disconnect时退出.
所以ConnectionTcpClient有发送数据和循环接收数据的能力,ConnectionTcpServer有侦听客户端连接的能力。当有特定的事件发生的时候,会自动触发相关的handler来进行处理,如数据到来,连接建立\断开,新连接到来等等。
问题:
这种设计模式使receive处于一个无限的while循环,不断的调用select+accpet或者select+receive,是否利于send之类的方法在同一个socket上发送数据?
2008年10月16日
#
1. Enviroment
"gloox - 0.9.9.5" + "Windows Server 2008" + "VC++ 2008"
2. config.h.win
HAVE_WINTLS
HAVE_WINDNS_H
HAVE_SETSOCKOPT
默认编译的时候出错:
dns.obj : error LNK2019: unresolved external symbol
_DnsFree@8 referenced in function "public: static class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> > > __cdecl gloox::DNS::resolve(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class gloox::LogSink const &)" (
?resolve@DNS@gloox@@SA?AV?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@std@@@2@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@4@00ABVLogSink@2@@Z)
dns.obj : error LNK2019: unresolved external symbol
_DnsQuery_A@24 referenced in function "public: static class std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<struct std::pair<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const ,int> > > __cdecl gloox::DNS::resolve(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class gloox::LogSink const &)" (
?resolve@DNS@gloox@@SA?AV?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@std@@@2@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@4@00ABVLogSink@2@@Z)
tlsschannel.obj : error LNK2019: unresolved external symbol
_EncryptMessage@16 referenced in function "public: virtual bool __thiscall gloox::SChannel::encrypt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (
?encrypt@SChannel@gloox@@UAE_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
tlsschannel.obj : error LNK2019: unresolved external symbol
_DecryptMessage@16 referenced in function "public: virtual int __thiscall gloox::SChannel::decrypt(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (
?decrypt@SChannel@gloox@@UAEHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)
tlsschannel.obj : error LNK2019: unresolved external symbol
__imp__FreeCredentialsHandle@4 referenced in function "public: virtual void __thiscall gloox::SChannel::cleanup(void)" (
?cleanup@SChannel@gloox@@UAEXXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
__imp__DeleteSecurityContext@4 referenced in function "public: virtual void __thiscall gloox::SChannel::cleanup(void)" (
?cleanup@SChannel@gloox@@UAEXXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
_FreeContextBuffer@4 referenced in function "public: virtual bool __thiscall gloox::SChannel::handshake(void)" (
?handshake@SChannel@gloox@@UAE_NXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
_InitializeSecurityContextA@48 referenced in function "public: virtual bool __thiscall gloox::SChannel::handshake(void)" (
?handshake@SChannel@gloox@@UAE_NXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
_AcquireCredentialsHandleA@36 referenced in function "public: virtual bool __thiscall gloox::SChannel::handshake(void)" (
?handshake@SChannel@gloox@@UAE_NXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
_QueryContextAttributesA@12 referenced in function "private: void __thiscall gloox::SChannel::setSizes(void)" (
?setSizes@SChannel@gloox@@AAEXXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
__imp__CertFreeCertificateChain@4 referenced in function "private: void __thiscall gloox::SChannel::validateCert(void)" (
?validateCert@SChannel@gloox@@AAEXXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
__imp__CertVerifyCertificateChainPolicy@16 referenced in function "private: void __thiscall gloox::SChannel::validateCert(void)" (
?validateCert@SChannel@gloox@@AAEXXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
__imp__CertGetCertificateChain@32 referenced in function "private: void __thiscall gloox::SChannel::validateCert(void)" (
?validateCert@SChannel@gloox@@AAEXXZ)
tlsschannel.obj : error LNK2019: unresolved external symbol
__imp__CertNameToStrA@20 referenced in function "private: void __thiscall gloox::SChannel::certData(void)" (
?certData@SChannel@gloox@@AAEXXZ)
3. 加入需要的lib, 编译成功
ws2_32.lib Dnsapi.lib Secur32.lib Crypt32.lib