remote-connection-failed when connecting with Face

2019-06-13 02:30发布

i am trying to integrate Facebook Chat on my jQuery Mobile and considering following architecture

But when i turn on the server ( punjab ) , and put the following necessary credential in javascript related to facebook i am getting remote-connection-failed error can anyone tell me whats missing.

JID :          XXX@chat.facebook.com
PASSWORD:      <FacebookPassword>

outgoing & incoming Request

  SENT:<body rid='1283282620' xmlns='http://jabber.org/protocol/httpbind' to='chat.facebook.com' xml:lang='en' wait='300' hold='1' content='text/xml; charset=utf-8' ver='1.6' xmpp:version='1.0' xmlns:xmpp='urn:xmpp:xbosh'/>

  RECV:<body xmlns='http://jabber.org/protocol/httpbind' type='terminate' condition='remote-connection-failed'/>

Start Server on windows XP

Python twistd.py punjab

2012-01-26 10:41:45+0530 [-] Log opened.
2012-01-26 10:41:45+0530 [-] twistd 11.1.0 (C:\Python27\python.exe 2.7.2) starti
ng up.
2012-01-26 10:41:45+0530 [-] reactor class: twisted.internet.selectreactor.Selec
tReactor.
2012-01-26 10:41:45+0530 [-] Site starting on 5280
2012-01-26 10:41:45+0530 [-] Starting factory <twisted.web.server.Site instance
at 0x013A12B0>

When i hit http://localhost:5280/http-bind I am getting XEP-0124 - BOSH

Entry Url

http://localhost/strophejs/facebook-chat-example/facebook.html

facebook.html

<html>
<head>
<script src="http://connect.facebook.net/en_US/all.js" type="text/javascript"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="strophe.min.js" type="text/javascript"></script>
<script src="facebook.js" type="text/javascript"></script>
<script>
var BOSH_SERVICE = 'http://localhost:5280/http-bind'
var connection = null;

function log(msg)
{
    $('#log').append('<div></div>').append(document.createTextNode(msg));
}

function rawInput(data)
{
    log('RECV: ' + data);
}

function rawOutput(data)
{
    log('SENT: ' + data);
}

function onConnect(status)
{
    if (status == Strophe.Status.CONNECTING) {
    log('Strophe is connecting.');
    } else if (status == Strophe.Status.CONNFAIL) {
    log('Strophe failed to connect.');
    $('#connect').get(0).value = 'connect';
    } else if (status == Strophe.Status.DISCONNECTING) {
    log('Strophe is disconnecting.');
    } else if (status == Strophe.Status.DISCONNECTED) {
    log('Strophe is disconnected.');
    $('#connect').get(0).value = 'connect';
    } else if (status == Strophe.Status.CONNECTED) {
    log('Strophe is connected.');
    connection.disconnect();
    }
}

$(document).ready(function () {
    var access_token;
    FB.init({
            appId      : 'XXXXXXXXXXX',
            status     : true,
            cookie     : true,
            xfbml      : true,
            oauth      : true,
    });

    FB.login(function (response) {
        console.log(response);
        if (response.authResponse) {
            access_token = response.authResponse.accessToken;
            console.log(access_token);
        } else {
            alert('User is logged out');
        }
    },{scope: 'email,user_online_presence,friends_online_presence,xmpp_login'});

    connection = new Strophe.Connection(BOSH_SERVICE);
    connection.rawInput = rawInput;
    connection.rawOutput = rawOutput;

    $('#connect').bind('click', function () {
    var button = $('#connect').get(0);
    if (button.value == 'connect') {
        button.value = 'disconnect';

        connection.facebookConnect($('#jid').get(0).value,
                    onConnect,
                    300,
                    1,
                    'XXXXXXXXXX' , /*app id*/
                    'XXXXXXXXXXXXXXXXXX',/*secret key*/
                    access_token);
    } else {
        button.value = 'connect';
        connection.disconnect();
    }
    });
});
</script>
</head>

<body>
<div id="fb-root"></div>
<div id='login' style='text-align: center'>
      <form name='cred'>
        <label for='jid'>JID:</label>
        <input type='text' id='jid'>
        <label for='pass'>Password:</label>
        <input type='password' id='pass'>
        <input type='button' id='connect' value='connect'>
      </form>
    </div>
    <hr>
    <div id='log'></div>
</body>
</html>

facebook.js

/*
    @author: Ruben J Garcia <rubenjgarciab@gmail.com>
    @version: 1.0

    This program is distributed under the terms of the MIT license.
    Please see the LICENSE file for details.

    Copyright 2006-2008, OGG, LLC
*/

/**
 * Split a string by string
 * @param delimiter string The boundary string.
 * @param string string The input string.
 * @param limit int[optional] If limit is set and positive, the returned array will contain
 *      a maximum of limit elements with the last
 *      element containing the rest of string.
 * 
 *      If the limit parameter is negative, all components
 *      except the last -limit are returned.
 * 
 *      If the limit parameter is zero, then this is treated as 1.
 * 
 * @returns array If delimiter is an empty string (""),
 *      explode will return false.
 *      If delimiter contains a value that is not
 *      contained in string and a negative
 *      limit is used, then an empty array will be
 *      returned. For any other limit, an array containing
 *      string will be returned.
 */
function explode(delimiter, string, limit) {
         var emptyArray = { 0: '' };

        // third argument is not required
        if ( arguments.length < 2 ||
            typeof arguments[0] == 'undefined' || typeof arguments[1] == 'undefined' ) {
            return null;
        }

        if ( delimiter === '' || delimiter === false ||
            delimiter === null ) {
            return false;
        }

        if ( typeof delimiter == 'function' || typeof delimiter == 'object' ||
            typeof string == 'function' || typeof string == 'object' ) {
                return emptyArray;    
        }

        if ( delimiter === true ) {
            delimiter = '1';
        }  

        if (!limit) {
            return string.toString().split(delimiter.toString());
        } else {
            // support for limit argument        
            var splitted = string.toString().split(delimiter.toString());
            var partA = splitted.splice(0, limit - 1);
            var partB = splitted.join(delimiter.toString());
            partA.push(partB);
            return partA;   
        }   
};

/**
 *  Handler for X-FACEBOOK-PLATFORM SASL authentication.
 *
 *  @param (XMLElement) elem - The challenge stanza.
 *
 *  @returns false to remove the handler.
 */
Strophe.Connection.prototype._sasl_challenge1_fb = function (elem)
    {
        var challenge = Base64.decode(Strophe.getText(elem));
        var nonce = "";
        var method = "";
        var version = "";

        // remove unneeded handlers
        this.deleteHandler(this._sasl_failure_handler);

        var challenges = explode("&", challenge);
        for(i=0; i<challenges.length; i++) 
        {
            map = explode("=", challenges[i]);
            switch (map[0]) 
            {
                case "nonce":
                    nonce = map[1];
                    break;
                case "method":
                    method = map[1];
                    break;
                case "version":
                    version = map[1];
                    break;
          }
        }

        var responseText = "";

        responseText += 'api_key=' + this.apiKey;
        responseText += '&call_id=' + (Math.floor(new Date().getTime()/1000));
        responseText += '&method=' + method;
        responseText += '&nonce=' + nonce;
        responseText += '&access_token=' + this.sessionKey;
        responseText += '&v=' + '1.0';
        responseText += '&sig=' + MD5.hexdigest(responseText.replace(/&/g,"")+this.secretKey);

        this._sasl_challenge_handler = this._addSysHandler(
            this._sasl_challenge2_cb.bind(this), null,
            "challenge", null, null);
        this._sasl_success_handler = this._addSysHandler(
            this._sasl_success_cb.bind(this), null,
            "success", null, null);
        this._sasl_failure_handler = this._addSysHandler(
            this._sasl_failure_cb.bind(this), null,
            "failure", null, null);

        this.send($build('response', {
            xmlns: Strophe.NS.SASL
        }).t(Base64.encode(responseText)).tree());

        return false;
};

/**
 *  Handler for initial connection request with Facebokk.
 *
 *  This handler is used to process the initial connection request
 *  response from the BOSH server. It is used to set up authentication
 *  handlers and start the authentication process.
 *
 *  SASL authentication will be attempted if available, otherwise
 *  the code will fall back to legacy authentication.
 *
 *  @param (Strophe.Request) req - The current request.
 */
Strophe.Connection.prototype._connect_fb = function (req) {
        Strophe.info("_connect_fb was called");

        this.connected = true;
        var bodyWrap = req.getResponse();
        if (!bodyWrap) { return; }

        this.xmlInput(bodyWrap);
        this.rawInput(Strophe.serialize(bodyWrap));

        var typ = bodyWrap.getAttribute("type");
        var cond, conflict;
        if (typ !== null && typ == "terminate") {
            // an error occurred
            cond = bodyWrap.getAttribute("condition");
            conflict = bodyWrap.getElementsByTagName("conflict");
            if (cond !== null) {
                if (cond == "remote-stream-error" && conflict.length > 0) {
                    cond = "conflict";
                }
                this._changeConnectStatus(Strophe.Status.CONNFAIL, cond);
            } else {
                this._changeConnectStatus(Strophe.Status.CONNFAIL, "unknown");
            }
            return;
        }

        // check to make sure we don't overwrite these if _connect_fb is
        // called multiple times in the case of missing stream:features
        if (!this.sid) {
            this.sid = bodyWrap.getAttribute("sid");
        }
        if (!this.stream_id) {
            this.stream_id = bodyWrap.getAttribute("authid");
        }
        var wind = bodyWrap.getAttribute('requests');
        if (wind) { this.window = wind; }
        var hold = bodyWrap.getAttribute('hold');
        if (hold) { this.hold = hold; }
        var wait = bodyWrap.getAttribute('wait');
        if (wait) { this.wait = wait; }

        var mechanisms = bodyWrap.getElementsByTagName("mechanism");
        var i, mech, auth_str, hashed_auth_str, xfacebook;
        if (mechanisms.length == 0) {
            // we didn't get stream:features yet, so we need wait for it
            // by sending a blank poll request
            var body = this._buildBody();
            this._requests.push(
                new Strophe.Request(body.tree(),
                                    this._onRequestStateChange.bind(this)
                                      .prependArg(this._connect_cb.bind(this)),
                                    body.tree().getAttribute("rid")));
            this._throttledRequestHandler();
            return;
        } else {
            for (i = 0; i < mechanisms.length; i++) {
                mech = Strophe.getText(mechanisms[i]);
                if (mech == 'X-FACEBOOK-PLATFORM') {
                    xfacebook = true;
                    break;
                }
            }
        }

        if (!xfacebook) {
            return;
        }

        this._changeConnectStatus(Strophe.Status.AUTHENTICATING, null);
        this._sasl_challenge_handler = this._addSysHandler(
            this._sasl_challenge1_fb.bind(this), null,
            "challenge", null, null);
        this._sasl_failure_handler = this._addSysHandler(
            this._sasl_challenge1_fb.bind(this), null,
            "failure", null, null);

        this.send($build("auth", {
            xmlns: Strophe.NS.SASL,
            mechanism: "X-FACEBOOK-PLATFORM"
        }).tree());
};

/**
 *  Starts the connection process with facebok XMPP Chat Server.
 *
 *  As the connection process proceeds, the user supplied callback will
 *  be triggered multiple times with status updates.  The callback
 *  should take two arguments - the status code and the error condition.
 *
 *  The status code will be one of the values in the Strophe.Status
 *  constants.  The error condition will be one of the conditions
 *  defined in RFC 3920 or the condition 'strophe-parsererror'.
 *
 *  Please see XEP 124 for a more detailed explanation of the optional
 *  parameters below.
 *
 *  @param (String) jid - The user's JID. It must be facebookid@chat.facebook.com,
 *      where facebook id is the number id of the facebook profile
 *  @param (Function) callback The connect callback function.
 *  @param (Integer) wait - The optional HTTPBIND wait value.  This is the
 *      time the server will wait before returning an empty result for
 *      a request.  The default setting of 60 seconds is recommended.
 *      Other settings will require tweaks to the Strophe.TIMEOUT value.
 *  @param (Integer) hold - The optional HTTPBIND hold value.  This is the
 *      number of connections the server will hold at one time.  This
 *      should almost always be set to 1 (the default).
 *  @param apiKey The API key of our Facebook Application
 *  @param secretKey The secret key of our Facebook Application
 *  @param sessionKey The actual session key for the user who we are attempting to log in
 */
Strophe.Connection.prototype.facebookConnect = function (jid, callback, wait, hold, apiKey, secretKey, sessionKey){
    this.jid = jid;
    this.connect_callback = callback;
    this.disconnecting = false;
    this.connected = false;
    this.authenticated = false;
    this.errors = 0;
    this.apiKey = apiKey;
    this.secretKey = secretKey;
    this.sessionKey = sessionKey;

    this.wait = wait || this.wait;
    this.hold = hold || this.hold;

    // parse jid for domain and resource
    this.domain = Strophe.getDomainFromJid(this.jid);

    // build the body tag
    var body = this._buildBody().attrs({
        to: this.domain,
        "xml:lang": "en",
        wait: this.wait,
        hold: this.hold,
        content: "text/xml; charset=utf-8",
        ver: "1.6",
        "xmpp:version": "1.0",
        "xmlns:xmpp": Strophe.NS.BOSH
    });

    this._changeConnectStatus(Strophe.Status.CONNECTING, null);

    this._requests.push(
        new Strophe.Request(body.tree(),
                            this._onRequestStateChange.bind(
                            this, this._connect_fb.bind(this)),
                             body.tree().getAttribute("rid")));
    this._throttledRequestHandler();
};

Please Someone suggest me the proper way to integrate Facebook Chat

2条回答
干净又极端
2楼-- · 2019-06-13 02:50

You need to check several things:

  • The error returned by punjab is remote-connection-failed. It means it could not open a connection to chat.facebook.com. Your punjab logs does not seem to match, as you do not have any attempt to connect to Facebook.
  • You might hurt cross domain problem and that might be the reason why you client does not connect to Punjab. Punjab is running on port 5280 and your client is served on port 80. It is different service and your browser might prevent connecting back to port 5280 from a client served on port 80. Check your Javascript browser log. I would expect an error there.
  • Facebook does not support standard authentication when using proxy. You will need a library that supports X-FACEBOOK-PLATFORM SASL authentication mechanism. See: http://developers.facebook.com/docs/chat/
查看更多
不美不萌又怎样
3楼-- · 2019-06-13 02:58

It's a really old question, but I just faced the same problem and posting this in case anyone faces the same problem.

I had not installed pyopenssl, and installing it fixed the problem immediately.

查看更多
登录 后发表回答