尝试使用 sleekxmpp 连接 FCM CCS 服务器时出错

Error trying to connect the FCM CCS server with sleekxmpp

我正在尝试使用能够连接 Firebase 云消息传递服务器的 sleekxmpp 1.3.1 构建一个非常简单的 python3 程序。我对以下代码有一个奇怪的 Error reading from XML stream 问题。我该如何解决?

我们可以从控制台输出中看到启用了STARTTLS。除了禁用它我没有找到其他方法from the sleekxmpp source code,但它并没有解决这个错误。

根据 google documentation,发送的第一条消息似乎有效,但 "error reading from xml stream" 仍然出现。

python代码

FCM_SERVER_URL = "fcm-xmpp.googleapis.com"
FCM_SERVER_PORT = 5236
FCM_SECRET = "XXXXXXX"
FCM_JID = "XXXXXXXX@gcm.googleapis.com"

import logging, socket
from sleekxmpp.clientxmpp import ClientXMPP

class ClientComponent(ClientXMPP):
    def __init__(self):
        ClientXMPP.__init__(self, FCM_JID, FCM_SECRET)
        self.auto_reconnect = False

        server_ip = socket.gethostbyname(FCM_SERVER_URL)
        if self.connect((server_ip, FCM_SERVER_PORT), use_tls = True, reattempt = False):
            self.process(block=True)

logging.basicConfig(level=logging.DEBUG, format='%(levelname)7s %(module)12s:%(lineno)-4s %(message)s')
ClientComponent()

控制台输出

  DEBUG         base:328  Loaded Plugin: RFC 6120: Stream Feature: STARTTLS
  DEBUG         base:328  Loaded Plugin: RFC 6120: Stream Feature: Resource Binding
  DEBUG         base:328  Loaded Plugin: RFC 3920: Stream Feature: Start Session
  DEBUG         base:328  Loaded Plugin: RFC 6121: Stream Feature: Roster Versioning
  DEBUG         base:328  Loaded Plugin: RFC 6121: Stream Feature: Subscription Pre-Approval
  DEBUG         base:328  Loaded Plugin: RFC 6120: Stream Feature: SASL
  DEBUG    xmlstream:546  Connecting to 66.102.1.188:5236
  DEBUG    xmlstream:1162 Event triggered: connected
  DEBUG statemachine:118   ==== TRANSITION disconnected -> connected
  DEBUG    xmlstream:1444 Starting HANDLER THREAD
  DEBUG    xmlstream:1662 Loading event runner
  DEBUG    xmlstream:1309 SEND (IMMED): <stream:stream to="gcm.googleapis.com" xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" xml:lang='en' version="1.0">
  ERROR    xmlstream:1492 Error reading from XML stream.
  DEBUG    xmlstream:1162 Event triggered: session_end
  DEBUG    xmlstream:1309 SEND (IMMED): </stream:stream>
  DEBUG    xmlstream:1162 Event triggered: socket_error
WARNING    xmlstream:1342 Failed to send b'</stream:stream>'
  DEBUG    xmlstream:1162 Event triggered: session_end
  DEBUG    xmlstream:1397 Waiting for 3 threads to exit.
  DEBUG    xmlstream:1375 Stopped event runner thread. 2 threads remain.
  DEBUG    xmlstream:1375 Stopped send thread. 1 threads remain.
  DEBUG    scheduler:200  Quitting Scheduler thread
  DEBUG    xmlstream:1375 Stopped scheduler thread. 0 threads remain.
  DEBUG    xmlstream:1162 Event triggered: socket_error
  DEBUG    xmlstream:1162 Event triggered: disconnected
  DEBUG statemachine:118   ==== TRANSITION connected -> disconnected
   INFO    xmlstream:720  Waiting for </stream:stream> from server
  DEBUG    xmlstream:1162 Event triggered: socket_error
  DEBUG    xmlstream:1162 Event triggered: disconnected
  DEBUG statemachine:118   ==== TRANSITION disconnected -> disconnected

我找到了答案 on the google list。将 "use_tls = True" 替换为 "use_ssl = True",效果更好。

为了完整起见,这将是一个有效实施的示例:

from sleekxmpp.clientxmpp import ClientXMPP
import logging
import socket
import json
import uuid

logging.basicConfig(level=logging.DEBUG, format="%(levelname)7s %(module)12s:%(lineno)-4s %(message)s")

FCM_SERVER_URL = "fcm-xmpp.googleapis.com"
FCM_SERVER_PORT = 5236
FCM_SERVER_KEY = "XXXXXXXXXXX" # <- Your Server Key
FCM_SENDER_ID = "XXXXXXXXXXX" # <- Your Sender ID
FCM_JID = FCM_SENDER_ID + "@gcm.googleapis.com"
FCM_SERVER_IP = socket.gethostbyname(FCM_SERVER_URL)
TOPIC = "/topics/info"

body = {
    "to": TOPIC, 
    "message_id": uuid.uuid4().hex,
    "data": { "msg": "This is the content"}
}
message = "<message><gcm xmlns='google:mobile:data'>"+json.dumps(body)+"</gcm></message>"

class Client(ClientXMPP):
    def __init__(self):
        ClientXMPP.__init__(self, FCM_JID, FCM_SERVER_KEY, sasl_mech="PLAIN")
        self.add_event_handler("session_start", self.start)
        self.auto_reconnect = False
        self.connect((FCM_SERVER_IP, FCM_SERVER_PORT), use_tls = True, use_ssl = True, reattempt = False)
        self.process(block=True)
    def start(self, event):
        self.send_raw(message)
        self.disconnect(wait=True)


Client()