Androidpn XMPP JID对象xmppUsername大写被转成小写

时间:2022-05-30 14:39:10


最近在用androidpn,发现一个很诡异的问题,跟了半天才发现原因,我设置的client的xmppUsername明明有大写的(排除username.toLowerCase问题),但是到了server端就成了全小写的了。下面贴个测试方法,原因就显而易见了。


贴代码前先简单解释下JID:

在XMPP 协议中表示一个地址,由三部分组成: node domain 和resource ,其中 node 和resource是可有可无的 ,domain 是必须的
例如 : xiaoming@xiaoming.home/sleeping , xiaoming 就是node ,xiaoming.home就是domain,sleeping 就是resource。
node domain 和resource任何一部分都不能超过1023 字节 ,加上@ 和 / 一个JID 总共不能超过3071字节。
如:apn中JID as this , 869274011349223@192.168.0.177/AndroidpnClient 。

测试代码如下:

import org.xmpp.packet.JID;

public class JIDTest
{

/**
* @param args
* @see
*/
public static void main(String[] args)
{
JID jid = new JID("Node", "domain", "resource",true);
System.out.println(jid);//Node@domain/resource

JID jid_ = new JID("Node", "domain", "resource");
System.out.println(jid_);//node@domain/resource
}

}
从上面的例子就很容易找到 解决办法传入时加个true参数。在androidpn server端需要进行如下修改,org.androidpn.server.xmpp.session.ClientSession的setAuthToken方法改为:

/**
* Initialize the session with an authentication token and resource name.
*
* @param authToken the authentication token
* @param resource the resource
*/
public void setAuthToken(AuthToken authToken, String resource)
{
//update by @will_awoke 此处需要增加true参数,否则会被转成小写
setAddress(new JID(authToken.getUsername(), getServerName(), resource, true));
this.authToken = authToken;
setStatus(Session.STATUS_AUTHENTICATED);
// Add session to the session manager
sessionManager.addSession(this);
}


至于原因,参考下JID的源码,很容易知晓。源码在tinder-1.2.1.jar / org.xmpp.packet.JID,该类提供了多个构造器,其中有这样两个构造器:

public JID(String node, String domain, String resource)
{
this(node, domain, resource, false);
}

public JID(String node, String domain, String resource, boolean skipStringprep)
{ //something }
可见如果不设置skipStringprep,默认会置为false,具体实现如下:

if (skipStringprep) {
this.node = node;
this.domain = domain;
this.resource = resource;
}
else
{
if ((node != null) && (node.equals(""))) {
node = null;
}
if ((resource != null) && (resource.equals(""))) {
resource = null;
}
try
{
this.node = nodeprep(node);
this.domain = domainprep(domain);
this.resource = resourceprep(resource);
}
也即,skipStringprep == false时,会调用 

        this.node = nodeprep(node);
        this.domain = domainprep(domain);
        this.resource = resourceprep(resource);

进行转换为小写。这三个方法具体细节不再赘述。


综上,over~