The core file of WeChat chat is jsjac. js.
After reading this file, we can basically run webim. Let's talk about jsjac:
Jsjac is called jsjac-Javascript. Jabber Client library, which is a client library written in JavaScript.
Its purpose is to facilitate the implementation of the Web-based Jabber/XMPP client.
Jsjac features:
1. Object-oriented Interfaces
2. Communication uses the httprequest object, that is, Ajax technology.
3. Good compatibility: It is compatible with most ajax/JS frameworks, such as prototype, mootools, jquery, dojo and Yui! And so on
1. login operation
In index.html, only front-end verification is performed and no connection is made to the openfire server.
/* * check if user want's to register new account and things */function loginCheck(form) {if (form.jid.value == '') {alert("You need to supply a username");return false;}if (form.pass.value == '') {alert("You need to supply a password");return false;}if (document.getElementById('tr_server').style.display != 'none') {var val = document.getElementById('server').value;if (val == '') {alert("You need to supply a jabber server");return false;}JABBERSERVER = val;}jid = form.jid.value + "@" + JABBERSERVER + "/";if (form.res.value != '')jid += form.res.value;elsejid += DEFAULTRESOURCE;if (!isValidJID(jid))return false;if (jwchats[jid] && !jwchats[jid].closed) {jwchats[jid].focus();return false;}pass = form.pass.value;register = form.register.checked;prio = form.prio[form.prio.selectedIndex].value;connect_port = form.connect_port.value;connect_host = form.connect_host.value;connect_secure = form.connect_secure.checked;jwchats[jid] = window.open('jwchat.html', makeWindowName(jid),'width=620,height=590,resizable=yes');return false;}
After the verification is passed, connect to the jwchat.html file and use the init () method to connect to the server.
/************************************************************************ * ****** INIT ******* ************************************************************************ */var con, Debug, srcW;function init() { /* initialise debugger */ if (!Debug || typeof(Debug) == 'undefined' || !Debug.start) { if (typeof(Debugger) != 'undefined'){ Debug = new Debugger(DEBUG_LVL,'jwchat' + cutResource(jid));} else { Debug = new Object(); Debug.log = function() {}; Debug.start = function() {}; } } if (DEBUG && (!USE_DEBUGJID || DEBUGJID == cutResource(jid))) Debug.start(); Debug.log("jid: "+jid+"\npass: "+pass,2); /* get some refs to static elements */ statusLed = frames["jwc_main"].document.getElementById('statusLed'); statusMsg = frames["jwc_main"].document.getElementById('statusMsg'); fmd = frames["jwc_main"].iRoster.document; /* set title */ document.title = "JointSky Messenger - " + nick; /* set nick */ frames["jwc_main"].document.getElementById('myNickname').innerHTML = nick; /* set unit 2012.8.8 dml@wip Notice:This value should be catch from userInfo which is stored in openfire*/ frames["jwc_main"].document.getElementById('unit').innerHTML = "(ch)"; /* init empty roster */ roster = new Roster(); /* *** * create new connection */ var oArg = {oDbg: Debug, httpbase: HTTPBASE, timerval: timerval}; if (BACKEND_TYPE == 'binding') con = new JSJaCHttpBindingConnection(oArg); else con = new JSJaCHttpPollingConnection(oArg); /* register handlers */ con.registerHandler('iq',handleIQSet); con.registerHandler('presence',handlePresence); con.registerHandler('message',handleMessage); con.registerHandler('message',handleMessageError); con.registerHandler('ondisconnect',handleDisconnect); con.registerHandler('onconnect',handleConnected); con.registerHandler('onerror',handleConError); /* connect to remote */ oArg = {domain:JABBERSERVER,username:jid.substring(0,jid.indexOf('@')),resource:jid.substring(jid.indexOf('/')+1),pass:pass,register:register} if (BACKEND_TYPE == 'binding') { if (opener.connect_port && !isNaN(opener.connect_port)) oArg.port = opener.connect_port; if (opener.connect_host && opener.connect_host != '') oArg.host = opener.connect_host; if (opener && opener.connect_secure) oArg.secure = true; } con.connect(oArg);}
It is clear that the connection operation is completed by jsjachttpbindingconnection or jsjachttppollingconnection (jsjac. JS is an object-oriented interface, so you can understand these two methods according to OO ideas)
Jsjachttpbindingconnection source code:
function JSJaCHttpBindingConnection(oArg) { this.base = JSJaCConnection; this.base(oArg); this._hold = JSJACHBC_MAX_HOLD; this._inactivity = 0; this._last_requests = new Object(); this._last_rid = 0; this._min_polling = 0; this._pause = 0; this._wait = JSJACHBC_MAX_WAIT; this.connect = JSJaCHBCConnect; this.disconnect = JSJaCHBCDisconnect; this.inherit = JSJaCHBCInherit; this.isPolling = function() { return (this._hold == 0) }; this.setPollInterval = function(timerval) { if (!timerval || isNaN(timerval)) { this.oDbg.log("Invalid timerval: " + timerval, 1); return - 1; } if (!this.isPolling()) this._timerval = 100; else if (this._min_polling && timerval < this._min_polling * 1000) this._timerval = this._min_polling * 1000; else if (this._inactivity && timerval > this._inactivity * 1000) this._timerval = this._inactivity * 1000; else this._timerval = timerval; return this._timerval; }; this._getRequestString = JSJaCHBCGetRequestString; this._getFreeSlot = function() { for (var i = 0; i < this._hold + 1; i++) if (typeof(this._req[i]) == 'undefined' || typeof(this._req[i].r) == 'undefined' || this._req[i].r.readyState == 4) return i; return - 1; } this._getHold = function() { return this._hold; } this._getStreamID = JSJaCHBCGetStreamID; this._getSuspendVars = function() { return ('host,port,secure,_rid,_last_rid,_wait,_min_polling,_inactivity,_hold,_last_requests,_pause').split(','); } this._handleInitialResponse = JSJaCHBCHandleInitialResponse; this._prepareResponse = JSJaCHBCPrepareResponse; this._reInitStream = JSJaCHBCReInitStream; this._resume = function() { if (this._pause == 0 && this._rid >= this._last_rid) this._rid = this._last_rid - 1; this._process(); this._inQto = setInterval("oCon._checkInQ();", JSJAC_CHECKINQUEUEINTERVAL); this._interval = setInterval("oCon._checkQueue()", JSJAC_CHECKQUEUEINTERVAL); } this._setHold = function(hold) { if (!hold || isNaN(hold) || hold < 0) hold = 0; else if (hold > JSJACHBC_MAX_HOLD) hold = JSJACHBC_MAX_HOLD; this._hold = hold; return this._hold; }; this._setupRequest = JSJaCHBCSetupRequest; this._suspend = function() { if (this._pause == 0) return; var slot = this._getFreeSlot(); this._req[slot] = this._setupRequest(false); var reqstr = "<body pause='" + this._pause + "' xmlns='http://jabber.org/protocol/httpbind' sid='" + this._sid + "' rid='" + this._rid + "'"; if (JSJAC_HAVEKEYS) { reqstr += " key='" + this._keys.getKey() + "'"; if (this._keys.lastKey()) { this._keys = new JSJaCKeys(hex_sha1, this.oDbg); reqstr += " newkey='" + this._keys.getKey() + "'"; } } reqstr += ">"; while (this._pQueue.length) { var curNode = this._pQueue[0]; reqstr += curNode; this._pQueue = this._pQueue.slice(1, this._pQueue.length); } reqstr += "</body>"; var abortTimerID = setTimeout("oCon._req[" + slot + "].r.abort();", 5000); this.oDbg.log("Disconnecting: " + reqstr, 4); this._req[slot].r.send(reqstr); clearTimeout(abortTimerID); }}
Jsjachttppollingconnection source code:
function JSJaCHttpPollingConnection(oArg) { this.base = JSJaCConnection; this.base(oArg); JSJACPACKET_USE_XMLNS = false; this.connect = JSJaCHPCConnect; this.disconnect = JSJaCHPCDisconnect; this.isPolling = function() { return true; }; this._getFreeSlot = function() { if (typeof(this._req[0]) == 'undefined' || typeof(this._req[0].r) == 'undefined' || this._req[0].r.readyState == 4) return 0; else return - 1; } this._getRequestString = JSJaCHPCGetRequestString; this._getStreamID = JSJaCHPCGetStream; this._getSuspendVars = function() { return new Array(); } this._prepareResponse = JSJaCHPCPrepareResponse; this._reInitStream = JSJaCHPCReInitStream; this._resume = function() { this._process(this._timerval); this._interval = setInterval("oCon._checkQueue()", JSJAC_CHECKQUEUEINTERVAL); this._inQto = setInterval("oCon._checkInQ();", JSJAC_CHECKINQUEUEINTERVAL); } this._setupRequest = JSJaCHPCSetupRequest; this._suspend = function() {};}
When logging on, you need to analyze the oarg Parameter
var oArg = {oDbg: Debug, httpbase: HTTPBASE, timerval: timerval};
Among them, debug is a debugger instance, and there is a declaration in Init ()
Debug = new Debugger(DEBUG_LVL,'jwchat ' + cutResource(jid));}
Debugger in debugger. js
function Debugger(lvl,id) {this.lvl = lvl || 0;if (this.lvl > DEBUGGER_MAX_LEVEL)this.lvl = DEBUGGER_MAX_LEVEL;this.id = id || '';this.debugMsgs = new Array();this.log = DebugLog;this.setLevel = DebugSetLevel;this.start = DebugStart;this.stop = DebugStop;
Httpbase and timerval are set in config. JS, which can be set as needed by the project.
As described above, open the openfire server, run login http: // 127.0.0.1: 9090/user-summary.jsp, the online user list to view the information shows that the login is normal.
It should be noted that the service will automatically prompt a connection timeout if the service remains static for about 5-6 minutes. In this case, you need to modify the org. jivesoftware. openfire. NiO. clientconnectionhandler class and XMPP. Client. Idle attribute.
@ Overrideint getmaxidletime () {// sets the default timeout value to 6 minutes. // return jiveglobals. getintproperty ("XMPP. client. idle ", 6*60*1000)/1000; // set the timeout time to 30 minutes return jiveglobals. getintproperty ("XMPP. client. idle ", 30*60*1000)/1000 ;}
Alternatively, enter URL: http: // 127.0.0.1: 9090/client-connections-settings.jsp to set
Alternatively, directly modify the idle value in the ofproperty table.