conversejs / converse.js

Web-based XMPP/Jabber chat client written in JavaScript
http://conversejs.org
Mozilla Public License 2.0
3.06k stars 763 forks source link

Converse chatroom crashes and goes blank and in infinite mode when xmpp server restarts or internet goes off during chat. #1962

Closed FaizanZahid closed 4 years ago

FaizanZahid commented 4 years ago

Describe the bug Converse crashes, when:

  1. client internet goes away and comes back.
  2. my prosody xmpp server restarts.
  3. when my user's mobile screen goes on standby and they stay idle for long.

In all above scenario i want my converse JS to keep chatroom resume and keep chat active, without any PAGE RELOADs.

To Reproduce Steps to reproduce the behavior:

  1. Go to any converse chatroom page
  2. Chat normally
  3. restart my prosody xmpp server
  4. i get following errors in JS console of client, and the whole page doing in infinite loading and converse chat never loads. i have to manually refresh the page to re initliaze converse chatroom. See screenshots.

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem. image

Even my psodoy is back online immediately after restart but converse keeps showing these errors and does not auto reconnect or reload the page. QuotaExceededError: The quota has been exceeded. converse.js:2884 ERROR: converse.js:2656:361 ERROR: WebSocket stream error: system-shutdown - Received SIGTERM converse.js:2656:361 ERROR: The quota has been exceeded. 4 converse.js:2656:361 uncaught exception: Object ERROR: U@https://talkwithstranger.com/js/converse/6.0.1/converse.js:632:492 url@https://talkwithstranger.com/js/converse/6.0.1/converse.js:603:675 e/fi.result@https://talkwithstranger.com/js/converse/6.0.1/converse.js:400:538 o</s.Backbone</t.sync@https://talkwithstranger.com/js/converse/6.0.1/converse.js:620:2215 le.patch/e.sync@https://talkwithstranger.com/js/converse/6.0.1/converse.js:2650:339 sync@https://talkwithstranger.com/js/converse/6.0.1/converse.js:595:1228 destroy@https://talkwithstranger.com/js/converse/6.0.1/converse.js:603:559 close/<@https://talkwithstranger.com/js/converse/6.0.1/converse.js:2742:950 close@https://talkwithstranger.com/js/converse/6.0.1/converse.js:2742:926 close@https://talkwithstranger.com/js/converse/6.0.1/converse.js:2824:391 converse.js:2656:361 2020-04-09T13:00:56.351Z INFO: SASL authentication succeeded. converse.js:2656:655 QuotaExceededError: The quota has been exceeded. converse.js:2884 ERROR: Websocket closed unexpectedly converse.js:2656:361 ERROR: The quota has been exceeded. 6 converse.js:2656:361 2020-04-09T13:05:41.541Z INFO: SASL authentication succeeded. converse.js:2656:655 QuotaExceededError: The quota has been exceeded. converse.js:2884 ERROR: Websocket closed unexpectedly converse.js:2656:361 ERROR: The quota has been exceeded. 6 converse.js:2656:361 2020-04-09T13:07:41.841Z INFO: SASL authentication succeeded. converse.js:2656:655 QuotaExceededError: The quota has been exceeded. converse.js:2884 ERROR: Websocket closed unexpectedly converse.js:2656:361 ERROR: The quota has been exceeded.

Environment (please complete the following information):

Additional context Ideally when xmpp restarts, converse js should try to reconnect to the last/current room of chatroom and when server is back it should resume the same chat without FULL PAGE RELOAD.

How can i do this?

jcbrand commented 4 years ago

I see you have a bunch of QuotaExceeded errors, which seems to indicate that your localStorage is full. That might be the cause of the problem.

Generally Converse.js does properly reconnect when the server restarts.

FaizanZahid commented 4 years ago

@jcbrand thanks for responding.. i checked the storage of LS, but that doesn't seem to be the issue. I even cleared my local storage and testing on multiple devices, and face the same issue.

I tested it again and found that if i stay idle on the chat page for some minutes or when the internet disconnects and comes back, OR if nobody is in a room or every1 has left a room and i stay on the page idle for few min, or if my phone goes to standby mode and i come back to chat again, or when my internet resumes after disconnection, in all these cases i get this below error in JS console.

ERROR: Websocket closed unexpectedly

My question is, how can i detect the state of the converse websocket in my own JS code, as you can see this error is coming on line # 2656, 2597 etc, see screenshot below please, image

What would be the code to access the current websocket object on my page and access its status if its connected, closed, or something else? Depending on the value, i can either:

  1. inform the user your internet has disconnected
  2. refresh current page after few seconds when internet is back
  3. if websocket gives this error , ERROR: Websocket closed unexpectedly i can wait for few seconds and do a page reload, that will reconnect converse and resume the chat in last room.

I have tried modifying the converse.js file to detect websocket state, but it doesn't seem to be normal JS and the syntax looks weird to me. Thats why i want to detect the websocket state in my own JS logic to provide a better UX to users if their websocket closes.

Below screenshot shows exact line where this error comes, i just want to know how to check the websocket current state and what r the available states in my own js code, not in converse js code, after converse is initliazed. image

Please see this url, if you want to see and let me know if there are any configs issues with my client side code or prosody config? https://talkwithstranger.com/randomchat

jcbrand commented 4 years ago

After the ERROR: Websocket closed unexpectedly error, there is warning: Disconnect was called because: authentication failed.

What that probably means is that Converse.js tries to reconnect, but the credentials are wrong. If you fix that, then it'll most likely reconnect properly.

FaizanZahid commented 4 years ago

Hey, thanks for replying. Yes i see this warning, but i m not sure what is causing this warning. As i am only using anonymous login as authentication, what do you think is wrong with my converse or prosody config?

My converse config file:

// converse initialization
function converseInit() {
    converse.initialize({
        debug: true,
        view_mode: "fullscreen",
        domain_placeholder: "accounts.talkwithstranger.com",
        registration_domain: "accounts.talkwithstranger.com",
        allow_registration: true,
        default_domain: "accounts.talkwithstranger.com",
        bosh_service_url: "https://accounts.talkwithstranger.com/http-bind",
        authentication: "anonymous",
        allow_contact_requests: false,
        allow_bookmarks: true,
        nickname: "abcd",
        keepalive: true, //Determines whether Converse will attempt to keep you logged in across page loads. if true , this keeps the same room even after refresh in random chat, good for reconnection, this will restore previous session
        auto_login: true, //This option can be used to let Converse automatically log the user in as soon as the page loads.
        auto_reconnect: true, //Automatically reconnect to the XMPP server if the connection drops unexpectedly.
        allow_logout: false,
        // "locked_muc_nickname": true,
        // "theme": "concord",
        muc_nickname_from_jid: true,
        whitelisted_plugins: [
            "content",
            "canned",
            "info",
            "screencast",
            "vmsg",
            "directory",
            "search",
            "jitsimeet",
            "audioconf",
            "http-auth",
            "converse-download-dialog",
            "fastpath",
            "browsertab",
            "location",
            "settings",
            "stickers",
        ],
        enable_smacks: true, //Determines whether XEP-0198 Stream Management support is turned on or not. Recommended to set to true if a websocket connection is used. Please see the websocket_url configuration setting.
        muc_show_join_leave: true, //Determines whether Converse will show info messages inside a chatroom whenever a user joins or leaves it.
        show_client_info: false, //Specifies whether the info icon is shown on the controlbox which when clicked opens an “About” modal with more information about the version of Converse being used.
        singleton: false, //If set to true, then only one chat (one-on-one or groupchat) will be allowed. this also hides any extra options on the page
        auto_focus: true, //If set to true, the textarea for composing chat messages will automatically become focused as soon as a chat is opened.
        idle_presence_timeout: 900, //The amount of seconds after which the user is considered to be idle and an idle presence according to XEP-0319 is sent.

        show_controlbox_by_default: false,
        blacklisted_plugins: [
            //   "converse-carbons",
            //   "converse-bookmarks",
            // "converse-omemo",
            "converse-register",
            "converse-controlbox",
        ],
        discover_connection_methods: true,

        auto_register_muc_nickname: true, //Determines whether Converse should automatically register a user’s nickname when they enter a groupchat.
        allow_muc: false, //Allow multi-user chat (muc) in chatrooms. Setting this to false will remove the Chatrooms tab from the control box.
        jid: "accounts.talkwithstranger.com", //The Jabber ID or “JID” of the current user. The JID uniquely identifies a user on the XMPP network. It looks like an email address, but it’s used for instant messaging instead
        // "auto_join_rooms": [
        //     'cat@random.accounts.talkwithstranger.com',
        // ],
        auto_join_rooms: [{
            jid: room + "@random.accounts.talkwithstranger.com",
            nick: username + " [" + (Math.floor(Math.random() * 2000 + 1) + "]"),
        }, ],
        loglevel: "debug",
        sticky_controlbox: false,
        notification_icon: "https://talkwithstranger.com/images/misc/favicon16.png",
        websocket_url: "wss://accounts.talkwithstranger.com/xmpp-websocket",

        notify_all_room_messages: [room + "@random.accounts.talkwithstranger.com"], //By default, sound and desktop notifications will only be made when you are mentioned in a room. If you set this setting to true, then you will be notified of all messages received in a room. You can also pass an array of room JIDs to this option, to only apply it to certain rooms.
    });
}

Here is my prosody config file,

-- Documentation for bundled modules can be found at: https://prosody.im/doc/modules
modules_enabled = {

    -- Generally required
        "roster"; -- Allow users to have a roster. Recommended ;)
        "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in.
        "tls"; -- Add support for secure TLS on c2s/s2s connections
        "dialback"; -- s2s dialback support
        "disco"; -- Service discovery
        "conversejs";

        -- TWS specific
        "log_auth";
        "firewall";

    -- Not essential, but recommended
        "carbons"; -- Keep multiple clients in sync
        "pep"; -- Enables users to publish their avatar, mood, activity, playing music and more
        "private"; -- Private XML storage (for room bookmarks, etc.)
        "blocklist"; -- Allow users to block communications with other users
        "vcard4"; -- User profiles (stored in PEP)
        "vcard_legacy"; -- Conversion between legacy vCard and PEP Avatar, vcard

    -- Nice to have
        "version"; -- Replies to server version requests
        "uptime"; -- Report how long server has been running
        "time"; -- Let others know the time here on this server
        "ping"; -- Replies to XMPP pings with pongs
        "register"; -- Allow users to register on this server using a client and change passwords
        --"mam"; -- Store messages in an archive and allow users to access it
        --"csi_simple"; -- Simple Mobile optimizations
        --"mod_http_upload"; --This module implements XEP-0363, versions 0.2 and 0.3, which let clients upload files over HTTP.

    -- Admin interfaces
        "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands
        "admin_telnet"; -- Opens telnet console interface on localhost port 5582

    -- HTTP modules
        "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP"
        "websocket"; -- XMPP over WebSockets
        "http_files"; -- Serve static files from a directory over HTTP

    -- Other specific functionality
        --"limits"; -- Enable bandwidth limiting for XMPP connections
        --"groups"; -- Shared roster support
        --"server_contact_info"; -- Publish contact information for this service
        --"announce"; -- Send announcement to all online users
        --"welcome"; -- Welcome users who register accounts
        --"watchregistrations"; -- Alert admins of registrations
        --"motd"; -- Send a message to users when they log in
        --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots.
        --"proxy65"; -- Enables a file transfer proxy service which clients behind NAT can use
}

-- These modules are auto-loaded, but should you want
-- to disable them then uncomment them here:
modules_disabled = {
    -- "offline"; -- Store offline messages
    -- "c2s"; -- Handle client connections
    -- "s2s"; -- Handle server-to-server connections
    -- "posix"; -- POSIX functionality, sends server to background, enables syslog, etc.
}

-- Disable account creation by default, for security
-- For more information see https://prosody.im/doc/creating_accounts
allow_registration = true

-- Force clients to use encrypted connections? This option will
-- prevent clients from authenticating unless they are using encryption.

c2s_require_encryption = true

-- Force servers to use encrypted connections? This option will
-- prevent servers from authenticating unless they are using encryption.

s2s_require_encryption = true

-- Force certificate authentication for server-to-server connections?

s2s_secure_auth = true

-- If you proxy WebSocket connections trough a HTTP proxy or server that handles HTTPS, you can set consider_websocket_secure = true to tell Prosody not to worry about the connections being unencrypted.
consider_websocket_secure = true;

consider_bosh_secure = true;
cross_domain_bosh = true;
cross_domain_websocket = true;

log_auth_ips = "all";

-- Some servers have invalid or self-signed certificates. You can list
-- remote domains here that will not be required to authenticate using
-- certificates. They will be authenticated using DNS instead, even
-- when s2s_secure_auth is enabled.

--s2s_insecure_domains = { "insecure.example" }

-- Even if you disable s2s_secure_auth, you can still require valid
-- certificates for some domains by specifying a list here.

--s2s_secure_domains = { "jabber.org" }

-- Required for init scripts and prosodyctl
pidfile = "/var/run/prosody/prosody.pid"

-- Select the authentication backend to use. The 'internal' providers
-- use Prosody's configured data storage to store the authentication data.

-- authentication = "internal_hashed"
authentication = "anonymous"

-- Select the storage backend to use. By default Prosody uses flat files
-- in its configured data directory, but it also supports more backends
-- through modules. An "sql" backend is included by default, but requires
-- additional dependencies. See https://prosody.im/doc/storage for more info.

--storage = "sql" -- Default is "internal"

-- For the "sql" backend, you can uncomment *one* of the below to configure:
--sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename.
--sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }
--sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" }

-- Archiving configuration
-- If mod_mam is enabled, Prosody will store a copy of every message. This
-- is used to synchronize conversations between multiple clients, even if
-- they are offline. This setting controls how long Prosody will keep
-- messages in the archive before removing them.

archive_expires_after = "1w" -- Remove archived messages after 1 week

-- You can also configure messages to be stored in-memory only. For more
-- archiving options, see https://prosody.im/doc/modules/mod_mam

-- Logging configuration
-- For advanced logging see https://prosody.im/doc/logging
log = {
    info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging
    error = "/var/log/prosody/prosody.err";
    -- "*syslog"; -- Uncomment this for logging to syslog
    -- "*console"; -- Log to the console, useful for debugging with daemonize=false
}

-- Uncomment to enable statistics
-- For more info see https://prosody.im/doc/statistics
statistics = "internal"

-- Certificates
-- Every virtual host and component needs a certificate so that clients and
-- servers can securely verify its identity. Prosody will automatically load
-- certificates/keys from the directory specified here.
-- For more information, including how to use 'prosodyctl' to auto-import certificates
-- (from e.g. Let's Encrypt) see https://prosody.im/doc/certificates

-- Location of directory to find certificates in (relative to main config file):
certificates = "certs"

-- HTTPS currently only supports a single certificate, specify it here:
--https_certificate = "/etc/prosody/certs/localhost.crt"

-- Settings to see if tws nginx server can handle file uploads
http_default_host = "accounts.talkwithstranger.com"
http_external_url = "https://accounts.talkwithstranger.com/"
trusted_proxies = { "127.0.0.1", "::1" }

http_paths = {
    bosh = "/http-bind"; -- Serve BOSH at /http-bind
    files = "/var/www/accounts.talkwithstranger.com/upload/"; -- Serve files from the base URL
}

----------- Virtual hosts -----------
-- You need to add a VirtualHost entry for each domain you wish Prosody to serve.
-- Settings under each VirtualHost entry apply *only* to that host.

VirtualHost "localhost"
-- "jid" should be the name of a VirtualHost in an anonymous authentication scenario
VirtualHost "accounts.talkwithstranger.com"
    -- Enable anonymous login:
    authentication = "anonymous"
    -- Allow anonymous users to access remote servers:
    allow_anonymous_s2s = true
    enabled = true  
        ssl = {
            key = "/path-to-ssl-key";
            certificate = "/path-to/pem"; }

disco_items = {
    { "uploads.accounts.talkwithstranger.com" },
}
------ Components ------
-- You can specify components to add hosts that provide special services,
-- like multi-user conferences, and transports.
-- For more information on components, see https://prosody.im/doc/components

---Set up a MUC (multi-user chat) room server on conference.example.com:
Component "random.accounts.talkwithstranger.com" "muc"
    name = "TalkWithStranger Random Chatrooms"
    restrict_room_creation = false
    muc_room_default_public = true

--Component "uploads.accounts.talkwithstranger.com" "http_upload"
--  http_upload_quota = 500000000 -- 500MB for user quota
--  http_upload_expire_after = 60 * 60 * 24 * 7 -- a week in seconds
--  http_upload_file_size_limit = 10000000 -- 10 MB
--  http_upload_path =  "/var/www/accounts.talkwithstranger.com/upload"

--- Store MUC messages in an archive and allow users to access it
--modules_enabled = { "muc_mam" }

---Set up an external component (default component port is 5347)
--
-- External components allow adding various services, such as gateways/
-- transports to other networks like ICQ, MSN and Yahoo. For more info
-- see: https://prosody.im/doc/components#adding_an_external_component
--
--Component "gateway.example.com"
--  component_secret = "password"

consider_bosh_secure = true;
cross_domain_bosh = true;

conversejs_options = {
    debug = true;
    view_mode = "fullscreen";
}

Can you please check my client and server configs and suggest me what am i doing wrong? I am anonymously logging in my users and want them to chat with new people by creating new converse room on every next click or page load. What is wrong with my current authentication which is causing these ERROR: Websocket closed unexpectedly ?

I m a newbie in converse js and your help will be a life saver for me. @jcbrand

Thanks in adv for your help.

jcbrand commented 4 years ago

Anonymous login doesn't work well with websocket because you can't resume a session when the connection drops.

The Error: Websocket closed unexpectedly error can happen at any time (e.g. when the wifi drops) and isn't necessarily due to your setup.

You'll need to use BOSH instead of websocket in order to have resumeable sessions.

This issue tracker isn't for general support. If you have further questions like this, then please join our chatroom: xmpp:discuss@conference.converse.js.org

jcbrand commented 4 years ago

Here's a weblink: https://inverse.chat/?room=discuss@conference.conversejs.org