2

使用 agsXMPP 连接到 Google Cloud Messaging XMPP API,以便向 Android 设备发送通知。

连接建立正常,但在 SASL 启动时,在发送 PLAIN auth 元素后,服务器停止响应,并在再过 20 秒后关闭连接。

Base64 解码文档页面 ( http://developer.android.com/google/gcm/ccs.html ) 中的 auth 示例显示以下登录值:

126200347933@projects.gcm.android.com12620034793@projects-ga-.android.comAIzaSyB3rcZNkfnqKdFb9mhzCBiYpORDA2JWWtw

agsXMPP 是(我认为正确)对字符串进行编码的地方,给出如下内容:

[项目ID]\40gcm.googleapis.com[**API*KEY*PASSWORD**]

请注意我的版本中的\40而不是 Google 示例中的@ - 这会有所不同吗?

我期待成功或失败消息,根本没有响应很难调试。这可能是造成某些失败的原因,还是 Google 的 XMPP 实施没有提供正确的响应。

更新:

我在下面回答,基本上,是的,Google 无法处理编码的 @ 字符,因为它不支持 XMPP 扩展。

4

1 回答 1

2

经过更多测试,我在 agsXMPP 中添加了一个新的 SaslFactory 机制,并将其绑定为使用不带编码的用户名(扩展名http://xmpp.org/extensions/xep-0106.html的一部分,Google 不支持),然后在 SaslStartEvent - 指定我想使用该机制而不是内置的普通机制。- 现在连接将正常继续。

xmpp = new XmppClientConnection();
xmpp.UseSSL = true;
xmpp.UseStartTLS = false;
xmpp.Server = "gcm.googleapis.com";
xmpp.ConnectServer = "gcm.googleapis.com";
xmpp.Port = 5235;
/* Other connection settings /*

SaslFactory.AddMechanism("MyPLAINMechanism", typeof(MyPlainMechanismClass));

xmpp.OnSaslStart += (sender, args) =>
                                {
                                   args.Auto = false;
                                   args.Mechanism = "MyPLAINMechanism";
                                   args.ExtentedData = new GcmPlainSaslExtendedData
                                                          {
                                                             Username = "MY UNENCODED USERNAME"
                                                          };
                                };

然后我们定义MyPlainMechanismClass继承自 agsXMPP 中的 Mechanism 的,源代码与原始的 PlainSaslMechanism 相同,除了输入用户名的行 - 您可以使用ExtendedDataargs 上的属性传入未编码的用户名。

public class MyPlainMechanismClass: Mechanism
   {
      private XmppClientConnection m_XmppClient = null;

      public GcmPlainSaslMechanism()
      {
      }

      public override void Init(XmppClientConnection con)
      {
         m_XmppClient = con;

         // <auth mechanism="PLAIN" xmlns="urn:ietf:params:xml:ns:xmpp-sasl">$Message</auth>
         m_XmppClient.Send(new agsXMPP.protocol.sasl.Auth(agsXMPP.protocol.sasl.MechanismType.PLAIN, Message()));
      }

      public override void Parse(Node e)
      {
         // not needed here in PLAIN mechanism
      }


      private string Message()
      {
         // NULL Username NULL Password
         StringBuilder sb = new StringBuilder();

         //sb.Append( (char) 0 );
         //sb.Append(this.m_XmppClient.MyJID.Bare);

         sb.Append((char)0);
         //sb.Append(this.Username);
         sb.Append(((GcmPlainSaslExtendedData) this.ExtentedData).Username);
         sb.Append((char)0);
         sb.Append(this.Password);

         byte[] msg = Encoding.UTF8.GetBytes(sb.ToString());
         return Convert.ToBase64String(msg, 0, msg.Length);
      }
   }

ExtendedData我们用来传递自定义参数的自定义对象,例如本例中的未编码用户名。

       public class GcmPlainSaslExtendedData : agsXMPP.Sasl.ExtendedData
       {
          public string Username { get; set; }
       }
于 2013-07-17T10:44:03.003 回答