Upload
skrishatguru
View
223
Download
0
Embed Size (px)
Citation preview
7/30/2019 Design Doc - Atlogys Technical Consulting
1/46
Chat Service Integration in Guru Web Platform
Design DocumentVersion 2.0
Developed for
Guru.com
August 7th
, 2012
Developed by
Automated Logical Software Pvt. Ltd.Atlogys Technical ConsultingR-8, Nehru EnclaveNew Delhi, India 110019
Strictly Confidential
7/30/2019 Design Doc - Atlogys Technical Consulting
2/46
Versions
Date Author Change Summary Version
27/07/2012 Ritika Garga Original Document HLV
_ v1.0
1
07/08/2012 Ritika Garga Complete detailed
Design Doc
2
References
# Document Name Description Author Date Shared
1 Our Understanding
Atlogys Technical
Consulting.pdf
This lists the R&D done by us till date ad gives
you a preliminary look into the technical
solution.
Atlogys 11/06/2012
2 Updated Chatv1.1.doc
(BRS) (From Sharepoint)
Updated doc - Describes all features desired
from chat service on server and client side
Guru 16/07/2012
3 Updated Chat HTML
Mockups (FromSharepoint)
Html, css, js for the chat UI can run locally on
machine
Guru 16/07/2012
4 Chat UI Mocks Link http://dl.dropbox.com/u/26268356/Guru/HTM
L/Chat/Chat.html#
Guru 9/07/2012
5 Guru Architecture
High Level (Visio)
Guru.com web setup and overall design
architecture
Guru 28/05/2012
6 Guru-Architecture.docx 2 pager on guru overall code structure from
Shrinivas Narayani
Guru 27/07/2012
7 GuruRPGuide.docx Information on OpenId usage at guru.com Guru
8 ChatBRS_v1.2.docx Post Consolidation of all Q&A from Atlogys Guru 3/08/20129 Updated Chat HTML
Mockups (From
Sharepoint)
Post Consolidation of all Q&A from Atlogys
enable/disable settings in dropdown added.
Guru 3/08/2012
7/30/2019 Design Doc - Atlogys Technical Consulting
3/46
1. Introduction
The document describes the overall architecture & high level design (for both server and client)
suggested for integration of chat component into the existing web platform - Guru.com. In doing so, the
document throws light on various components involved, their role & interaction amongst the other
components of the proposed design.
2. Terms, Definitions, Acronyms used
XMPP: Extensible Messaging & Presence Protocol also called Jabber
MUC: Multi user chat
JSJAC: JavaScript Jabber Client API
Strophe/ Strophe.js: A JavaScript based Jabber Client API
Jetty: An embedded Java web container used by Openfire server
BOSH: Bidirectional Streams Over Synchronous HTTP
CORS: Cross Origin Resource Sharing
AJAX: Asynchronous JavaScript & XML
UCL :- User Control (We can place this user control on any aspx page)
CPH:- Content place holder (We can put user controls, aspx pages inside content placeholder)
Client or Web client: The module comprised of web pages that is interpreted & executed by web
browser & which is used by an end-user to login into the Guru.com website as well as chat component.
3. Scope
Integrating the Openfire server with the webserver (ASP.NET also having ColdFusion pages) of the
guru.com platform along with providing for a uniform and identical embedding of the html based web
chat client in the site.
The document excludes the multi-user chat (MUC) & focuses solely on the chat messages exchangedbetween any two users - one of them freelancer & other an employer.
However, if & when the MUC functionality needs to be implanted, the current design will work with
little or no change.
7/30/2019 Design Doc - Atlogys Technical Consulting
4/46
3.1 Chat Features
The features and functionality to be added in the chat client are as per the updated document #8
(ChatBRS_v1.2)of the References table above.
These were also listed in sections 1.1.1 and sections 1.1.2 of document #1 in the References table.
4. Chat Engine
The chat engine consists of the chat server and chat client.
4.1 Chat Server
After exploring many options for chat servers (both opensource and commercial), we have decided to go
ahead with the Java based OpenSource OpenFire server which is XMPP based.
Openfire is a real time collaboration (RTC) server licensed under the Open Source Apache License. It
uses the only widely adopted open protocol for instant messaging, XMPP (also called Jabber).
The reasons for selection of OpenFire were elaborated in document #1 of references table above.
4.1.1 Features of OpenFire:
It supports the following features:
User-friendly web-based installation and administration panel
Shared groups for easy roster deploying
Plugin interface
SSL/TLS support
Offline Messages support Server-to-Server connectivity
Database connectivity for storing messages and user details (including the embedded HSQL
database and support for MySQL, PosgreSQL and other databases)
LDAP integration
Platform independent (with the installers for different platforms)
Integration with Spark IM client
Legacy transports support (with the discontinued Kraken plugin, and planned support for
Spectrum IM)
Connection manager for load balancing
Clustering support (current open-source Clustering plugin only works with the commercialOracle Coherence software)
Message archiving-logging
Content filtering, packet rules
7/30/2019 Design Doc - Atlogys Technical Consulting
5/46
The proprietary extension to Openfire allows multiple server instances to work together in one clustered
environment. This extension is now open source as well (but depends on Oracle Coherence, a
commercial product).
4.1.2 Chat Server Hardware and Deployment
The OpenFire chat server application will reside on a dedicated Linux machine.
The Linux box will be connected to guru.com main server through intranet.
It will run on a URL like chat.guru.com.
It will use Mysql database.
The deployment configuration/stack for Openfire server should be
Openfire 3.7.1 (containing embedded Jetty app server/container)
64 bit Java Runtime Environment (preferably Oracle & by default itsbundled with Openfire setup)
64 bit Linux server box
X86-64 architecture
The following hardware will suffice:o 8 GB of RAM,
o 64 bit processor with 2 cores
o If its a dedicated Openfire machine then we can use almost 70-80% of RAM for JVM
heap.
o OpenFire uses Apache Mina where we can configure the thread pool to handle the
desired number of total requests.
4.1.3 Inside Openfire
Openfire will have following components:
1. The Jetty is embeddable web container that serves the static content as well as servlet/JSP &which can be spawned from the source code as & when needed. Internally, Openfire does this &
spawns 2 instances of Jetty.
a. One running on port 9090 over which you access the web based admin UI. It also acts as
a container for plug-in deployment.
b. Second running on port 7070. The HttpBindSevlet is deployed here & is the server side
end point of BOSH.
7/30/2019 Design Doc - Atlogys Technical Consulting
6/46
2. HttpBindServlet: is the servlet that provides the server side BOSH interface. It allows the web
clients to connect to Openfire server & exchange IMs. Its deployed in Jetty & binds to port
7070.
4.1.4 Server SSL and Configuring the Binding Ports
In OpenFire, the 7443 port allows a BOSH client to connect to HttpBindServlet over SSL.
When the XMPP client needs to connect to server, the client opens a stream (indicated by
element) to the server. The client & server negotiate the stream features like Transport Layer Security
(TLS).
When the client is connecting over port 7070 and TLS is being used, then the channel is encrypted end
to end without changing the port. So there is an end-to-end transport layer encrypted channel between
client & server on port 7070.
Whereas, in case of SSL, the encryption happens over a separate & dedicated port i.e. 7443.
1. In any case, the server needs to establish its identity to the client & prove that it is indeed who it
claims to be. So the chat server will need the certificates. Openfire has self-signed certificates which we
can use to begin with. However, actual asymmetric RSA (private-public key pair) certificates will need to
be purchased from VeriSign etc. for the production deployment of openfire.
2. Sometimes, the users/clients that need to access the Guru chat component are placed behind
firewalls (outbound firewall within their network). Their network admin might restrict access to port
7070 or 7443. In such a case, the HttpBindServlet running on OpenFire, and to which web browser will
make CORS Ajax requests, can be updated to listen on ports 80 or 443.
4.2 Client Side
Client side chat application will communicate with the OpenFire server using XMPP over BOSH.
[WebSockets is another desired channel considered as an alternate to BOSH but this is not well
supported by many browsers (like only works on IE10 preview edition).
Furthermore, the reliability needs to be tested for openfire support of websockets on non 80 ports (i.e.
Whether openfire can support the WebSocket handling in stand-alone setup i.e. sans any proxy. The
plug-in for enabling WebSocket support is present at: http://code.google.com/p/openfire-websockets/
).
Please refer to the Theory (heading #18 ) the end of this document for clarity on BOSH, webSockets etc.
Since we will be sending requests from a web browser, we will use the JavaScript XMPP libraries like
sthrope.js or JsJAc.js which provide implementations of XMPP over BOSH. Essentially what they do is
that - the XMPP specific XML is wrapped in payload of HTTP POST.
7/30/2019 Design Doc - Atlogys Technical Consulting
7/46
Any one of these two libraries can be used since both are very well documented and widely used
libraries for XMPP communication.
We prefer using JsJac.js for purposes of this project.
The function calls inside the JsJac library will communicate with OpenFire and fetch information like chat
contacts list, chat messages, favorite contacts, offline messages etc. which are stored in OpenFire
Database.
The .NET application (guru.com) will change its presenter code on all .aspx and .cfm pages to output the
chat UI and chat related JavaScript which will makes calls to the functions inside the JsJac.js library. The
returned XML from JsJac.js will be parsed by the chat related JavaScript on the clients browser to
extract the chat messages and information which will then be rendered inside the chat html windows.
Such client side code must be added by the .NET server application to all its client side pages.
Please note that as per heading # 16 (section 5), this is being added in div 2 via a chat.ascx user control
(of the Main.aspx/Main.cfm pages).
The web chat client will also fetch some information directly from the guru.com servers like profile
images, names and screen names (or company names) of all contacts in the chat list, along with the
logged in users chat settings (discussed in detail below).
5. Basic Control Flow
1. Web user logs onto guru.com and creates a session with the guru .net application.
2. Upon successful authentication with guru.com, the web client sends a request to log into openfire
directly using JsJac/sthrope.js client JavaScript library.
3. Openfire check for user authentication with guru openId provider.
4. When OpenID confirms the user to be a valid logged in user in the system, and after OpenFire
validates the user in its own database, the web client establishes a successful connection with OpenFire
and creates a session (XMPP over BOSH socket) with OpenFire.
3. The web client then requests openfire to get its chat contact list, favorite contacts, recent messages,
favorite contacts etc.
4. For all contacts received, the web client asks guru.com server to send their respective profile names,images and screen names (or company names).
5. The web chat client asks guru.com to send the chat user settings of the logged in user.
6. The chat UI which includes both the chat related html and JavaScript receives the necessary
information from 3,4,5 to render the chat windows as desired.
7/30/2019 Design Doc - Atlogys Technical Consulting
8/46
NOTE: Please note that this Chat UI must be outputted by guru .net application on all its aspx and cfm
pages. The chat related JavaScript here uses JsJac.js library to perform step 3 and REST calls to guru.com
to do 4. It must know how to parse xml received in 3.
7. On the backend, there is also communication between OpenFire (with HTTPBindServlet in Jetty) and
Guru using REST API calls. This uses a mix of push and pull techniques. Openfire till pull the list of allregistered users from guru.com. Guru.com will push information to Openfire on trigger events like user
addition, user deletion, new message exchange between two users etc (discussed in detail below).
This control flow is shown in the diagram below:
*NOTE: Instead of Json, we will use XML throughout for consistency.
7/30/2019 Design Doc - Atlogys Technical Consulting
9/46
6. Communication between Web Client and OpenFireIn the following text to come, proxy is referred to as a rule based software component that shall pass
the HTTP requests originating from web client to Openfire server. This proxy can be a web server like
Apache or Nginx or IIS that can run on dedicated server or which can be configured to accommodate the
rules for the proxy passes.
6.1 METHOD OF COMMUNICATION
Scenario 1: Without HTTP Proxy
(Direct communication between web client and OpenFire )
We plan to use CORS to achieve communication between web client hosted on domain:port
guru.com:80 and openfire server hosted on domain:port chat.guru.ccom:7070.
The requests are directly sent to a HTTP binding servlet that runs in Jetty container listening at port 7070or 7443 (for SSL).
CORS support exists on all browsers that we need to launch this feature on. Precisely, this includes:
Gecko 1.9.1 (Firefox 3.5,[3] SeaMonkey 2.0[4]) and above.
WebKit (Initial revision uncertain, Safari 4 and above,[1] Google Chrome 3 and above,
possibly earlier)[5]
MSHTML/Trident 4.0 (Internet Explorer 8) provides partial support via the XDomainRequest
object.[1]
Presto-based browsers (Opera) implement CORS as ofOpera 12.00[6] and Opera Mobile 12,
but not Opera Mini.[7]
Please refer to Theory section at end for more information on CORS (vs. document.domain vs. JsonP)
Scenario 2: With Proxy
The native XMPP communication is socket or stream based & happens over TCP port no: 5222/5223. But
while connecting from the web client, some browsers dont allow to make requests to the above ports.
So, we place an HTTP proxy or a connection manager in between client & Openfire server. This proxy
receives the request on standard port 80 & passes them to a HTTP binding servlet that runs in Jettycontainer listening at port 7070/7443. All the chat & other XMPP communication is achieved by
wrapping XML stanzas in the payload of HTTP POST requests. This is the implementation for: XEP-0124 &
XEP-0206. [ Now achieved by sthrope.js OR JsJac.js ]
It will pass the requests originating from web client to the BOSH servlet listening on port 7070. The
context path for the concerned servlet is /http-bind/. So, the proxy pass will be made to /http-bind/
from the proxy server.
There are 2 possibilities on configuring the proxy server:
7/30/2019 Design Doc - Atlogys Technical Consulting
10/46
Option 1: Using Apache/NginX between web client & Openfire
Web client => Apache (or Nginx) as Proxy => Openfire
In this case, the requests received on proxys port 80 of the nature:
*/http-bind/ will be passed to /:7070/http-bind/
The proxy server will run on chat.guru.com:80 and it will talk to server at chat.guru.com:7070 and the
client will be on www.guru.com:80
If this approach is employed, then the web chat related files (html+js) have to reside on this proxy to
abide by the same-origin policy. But the rest of files are being served from Guru.com web server. So, we
wont recommend this approach.
Or
We Use CORS to move the proxy on chat.guru.com and then communicate with it.
In either case, the following has to be considered when deploying a proxy:
For scalability & exact number of concurrent requests that can be handled, we need to look on various
factors. For e.g. in case of Apache, its dependent on:
1. Max number of processes that can be spawned
2. Max number of threads that can be spawned per process
3. Max time duration for which the connection will be kept open/alive before being closed.
4. Whats being served by the Apache- simple JS, HTML will server more requests than say an app
using PHP module.5. In case of proxy to Openfire, the connection has to remain open till the HttpBindServlet on
Openfire processes & sends back the response. Also, as the proxy will be part of BOSH system, it
will be sitting on reasonable number of requests/connections so as to push the data
immediately on availability. If say N number of users are concurrently logged into the
Guru.com & thereby into chat, my guess is- proxy will be sitting on N connections at any time.
Its because to achieve BOSH functionality & need to push data on client connection hold by
proxy. The memory consumed on each connection to proxy will be minimal (sufficient enough
for a single thread stack + socket+ other data structures if any as its the proxy pass & actual
content will be served by Openfire.)
Typically, Apache will be able to serve few hundred requests.
Option 2: Using IIS on Guru.com as proxy
Web client => IIS (Proxy+Guru.com web server) => Openfire
In this case, IIS needs to be configured to act as proxy & pass */http-bind/ requests to /:7070/http-bind/.
The web chat files will reside on this proxy, which is also hosting rest of Guru.com site. If the same origin
7/30/2019 Design Doc - Atlogys Technical Consulting
11/46
policy is to be considered, then option #2 looks feasible. We will recommend this approach.
This approach also fits with the current scalability setup of the Guru.com web servers.
Recommended Approach:
In Scenario 2, we recommend Option 2. But overall, we recommend Scenario 1.
Hence, we will go ahead with Scenario 1 Without Proxy.
6.1.1 Implementing CORS
1. Modify HttpBindServlet
When the browsers have capability to send the cross domain Ajax requests, they need the support from
the server to which they need to make the request. In this case, the web page originating fromGuru.com needs to send the Ajax request to chat.guru.com. In this case, chat.guru.com needs to trust &
accept requests from guru.com.
To achieve this, we need to enable CORS for the HttpBindServlet. It needs to be modified with the
following code snippets:
response.addHeader("Access-Control-Allow-Origin", "guru.com");
response.addHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
response.addHeader("Access-Control-Allow-Headers", "Content-Type");
response.addHeader("Access-Control-Max-Age", "86400");
Here 86400 is the time for which the preflighted requests will be cached by the browser while doing
CORS.
2. Enable Pre-flighted requests
The Openfire server needs to be provisioned for handling OPTIONS request and it should be able to
set the Access-Control related headers in the response. So add doOptions method
in HttpBindServlet and add Access-Control related headers to the response.
This is required for chrome and safari.
Please read more on Pre-flighted Requests for CORS in heading 18 in this document below.
7/30/2019 Design Doc - Atlogys Technical Consulting
12/46
6.2 MEANS OF COMMUNICATION
Using Sthrope.js / JsJac.js
To send each request, user needs to create a sTrophe.Builder object to generate formatted XML that will
be sent to OpenFire. Each time these requests are sent to retrieve any application data, user must pass aunique ID (called JID jabber ID) as one of the parameters.
Below piece of code (pseudo code) can be used for that:
Strophe.Builder = function (name, attrs)
Create a Strophe.Builder object.
The attributes should be passed in object notation. For examplevar b = new Builder('message',
{to: '[email protected]',from: '[email protected]',
type: set,
})
In the below example creating stanza using $iq (where iq will be as root element of the XML
generated (i.e. another approach of creating request/response xml)
Building XML Request to send
var stanza = $iq ({to: [email protected] ,from: [email protected],
type: 'set',id: 'JabberID'})
Building child element into stranza
$iq.c('query', {xmlns: 'jabber:iq:register'})
$iq.c('ChatMessage', chatcontrol.Text)
$iq.tree();
To send request generated by sTrophe.Builder below piece of code can be usedsendIQ: function (elem)
con.sendIQ(stanza);
Retrieving XML Response
var stanza = $iq (
{ to: [email protected] ,
from: [email protected],
type: 'get',
7/30/2019 Design Doc - Atlogys Technical Consulting
13/46
id: 'JabberID'
})
Building child element into stanza
$iq.c('query', {xmlns: 'jabber:iq:register'})$iq.c('ChatMessage', chatcontrol.ResponseText)
Also, everytime a request is sent to server sTrophe.Flush function should be called to flus the queue.
7/30/2019 Design Doc - Atlogys Technical Consulting
14/46
7. High level design & architecture
This shows the request flow pattern with Scenario 1 [ From section 6 above ]
Web browser
Web pages from
Guru.com
Chat UI/ Controls
JsJaC or Stropje.js
Guru.com
Web server
chat.guru.com
Openfire server
Jetty
Plugins
OpenIdAuthPlugin
UserServicePlugin
Archive Plugin
HttpBindServlet
OpenID Auth Server
MySQL
C
A
C
H
Eer logs
ru.com
Details
including:
OpenID
identifier,
server to
connect to,
JID etc aresent back to
client
Login to Openfire, chat,
block/unblock contact &exchange all XMPP data
over BOSH
Pull
+
Push
- User data
including JID,roster etc.
- Transcripts or
Archives of
chats
7/30/2019 Design Doc - Atlogys Technical Consulting
15/46
8. AuthenticationWhen the user logs into the guru.com site, the web server will also now send the following additional
response params in the current response.
1.
JID (Jabber User ID) for user to log in to chat module. The Jabber Id(JID) is the one with which XMPP
server identifies the user/client or a server in an XMPP system. Its of the form:
[node@]domain[/resource]
So, listed below are all the valid JIDs:
chat.guru.com
[email protected]/spark
For more details, refer http://tools.ietf.org/html/rfc6122#section-2
2.
The domain and/or location of the chat server to connect to This is chat.guru.com
Upon receiving this, the web client prepares itself to log into the chat module. To do so, it uses
JavaScript based Jabber/XMPP client API (Strophe, JsJac etc.).
Please note that as stated earlier, all the messages, presence etc. exchanged between client & Openfire
server would be XMPP over BOSH. That will be taken care by JavaScript XMPP library like- Strophe.
So, when user logs in, the following XML will be contained in HTTP POST request (shown sans
element):
The server will send the response wrapped in HTTP POST like:
7/30/2019 Design Doc - Atlogys Technical Consulting
16/46
version='1.0'
xml:lang='en'
xmlns='jabber:client'
xmlns:stream='http://etherx.jabber.org/streams'>
JID and Salt
On guru.com, when it gets an authentication request from username shrinivas to login, it will generate
the JID as follows and then pass it to the web client. This JID will also be stored on guru.com
We will take the username, hash it with a private salt and append @chat.guru.com to create the JID on
the fly. The JIDs will not be stored on guru.com. We will use a MD5 (Sha1) algorithm for this.
e.g. For username shrinivas, the returned JID will be:
[email protected] (where sXF45raniva23s is created on the fly using a secret salt only
known to guru.com)
The salt is being added to prevent username tampering so that ellen cannot get leos chat data when
both ellen and leo are logged into the system at the same time.
Please note that the web client is never sending the plain username to openfire. Since all calls are in
JavaScript, usernames can be easily tampered with. Hence the client will Only send hashed (obfuscated)
Jabber IDs that can only be encrypted/de-crypted by the Openfire and Guru (openID) servers (which
maintain the private keys).
OpenID
Before completing the authentication, the openfire will send the JID to guru openID which must state
whether this is a valid logged in user or not. OpenID will map the JID to the username and check if this
user is logged in or not at that time. If openID authenticates, then openfire will check if this JID is a valid
user in its database and if so, it will also map it with its username for extra authenticity. If both are
positive, then a session is created between openfire and web client.
Upon successful authentication, two autonomous sessions are created one with Guru and another
with OpenFire.
Storage Pre-requisites for Authentication:
The Jabber ID and username are stored in Openfire
The Jabber ID and username are also stored in guru.com
Authentication Architecture Diagram:
7/30/2019 Design Doc - Atlogys Technical Consulting
17/46
1. Client Signs-in to his/her guru.com account (over http/https).
2. Guru.com authorizes him/her and renders the guru page and chat client as well as sets the user-
specific parameters (profile ID, authentication string etc.) for connecting to openfire (over
http/https)
3. The chat client using the parameters set by guru.com tries to connect with openfire server (Over
XMPP).
4. Guru tries to authenticate the passed credential with the openfire (over http/https.)
5. Gurus OpenID server sends its response for authentication back to openfire (over http/https.)
6. In case of OK response from OpenID server, openfire establishes a XMPP session with the client.
Logout
1. When the user explicitly logs out of Guru.com site, then the web client shall first logout the user
from Openfire server. Upon finishing this, it shall logout from the Guru.com server.
7/30/2019 Design Doc - Atlogys Technical Consulting
18/46
2. When the user is logged out due to session timeout on Guru.com, Guru.com shall also end the
users session on Openfire.
9. OpenFire Plugins
The Openfire server will be having 3 plug-ins:
1. OpenIDAuthPlugin: Pulls from web & OpenId servers
It implements the Plugin & PacketInterceptor interfaces. It will intercept the login packet, & then send
the login request to OpenId auth server. When the OpenId server returns with AUTHENTICATED
response, then the Openfire server checks whether concerned user exists in its database. Upon,
successfully authenticating with server, the plug-in can ask the web-server to get the most recent roster
for the logged in user. From this roster, it will make the chat contact graph for the user and store it in
openfire database. It will be persisted in the Openfires user DB.
This might also need partial or complete rewriting of Openfires Authentication Manager because, bydefault, Openfire has support for database & LDAP based user authentication. The authentication
manager takes care of this. In this case, the authentication mechanism needs to query OpenId server.
Once OpenId server responds in affirmative, then Openfire will crosscheck the concerned user in its DB.
To achieve this functionality, we will need to modify parts of the plugin.
2.UserServicePlugin or UserAdminPlugin: Accepts push as well as pulls from web server with REST calls
It implements Plugin interface.
The plug-in basically provides the trigger/event based interface for the web server along with the
regular admin API exposed with REST calls.
On its deployment, the plug-in make the request to web server to get all the users & stores their data
into the Openfire DB.
The REST API calls are mentioned later in the document.
3.TranscriptsPlugin: Exposes pull to web server & possibly to web client as well
It implements the Plugin interface.
This plug-in will be doing 3 things:
a.
Construct & Monitor the cache
The plug-in will construct an LRU cache for caching the transcripts exchanged between users in memory.
DB will back this cache.
7/30/2019 Design Doc - Atlogys Technical Consulting
19/46
Transcripts (a.k.a Archives) are a bunch of IMs exchanged between two users. The archives will be
stored in the MySQL DB of Openfire. When user A & B initiate the chat, a relevant object say- Transcript
will be instantiated in cache. Once LRU cache finds this object as stale or exceeding certain max limit put
on size of transcript it will be evicted from cache & will be persisted in the DB.
The Openfire provides a Monitoring plug-in to persist the transcripts. If it aligns with the requirementsthen it will be used instead of custom cache.
For cache size, since we will use a dedicated machine for Openfire server, we shall be able to keep it
at-least of JVM heap size available to Openfire.
b.
The plug-in will serve REST calls from either web server or client or both to let them query about &
retrieve the transcripts shared between two users.
c.
It will provide all chat messages exchanged between two users over a specific date range. This will alsobe used to fetch the 50 most recent chats of a user, account for sorting etc.
Openfire already takes on the responsibility of storing the offline messages. So we may club the results
from two tables with appropriate segregation & send it back to web client.
10. Expectations from the OpenFire Server
10.1 Data to be Persisted
Contact list with user status of each member
User status of logged in member
o Green Online
o Red Busy
o Orange Idle; any user not using the application for 15 minutes will be considered as
idle
o Gray Offline. When a user is offline, their entire contact information is displayed as
grayed out and disabled.
Ability to set/change status of logged in user
Most recent chats (conversations) [ list of recent chats] Chat details for each conversation or of a particular conversation
Conversation history
Offline chats
List of Favorite contacts (ability to mark a contact as favorite)
Mark/Unmark a contact as favorite
Chat message history grouped by date
7/30/2019 Design Doc - Atlogys Technical Consulting
20/46
Ability to send files, save files.
View files sent/saved.
Blocked user list
Some major tables will be:
ofUser
ofRoster
ofOffline
ofPresence
Roster information is stored as follows in openFire.
Here, sher has 2 contacts in his roster- admin & leo.
10.2 APIs to be exposed
1.
Openfire will provide Rest APIs for trigger based events.
[ To be invoked by Guru.com server ]
Guru.com will make push calls to send information to OpenFire when the following events occur:
i. New employer/freelancer account added on guru
ii. An employer/freelancer account deleted on guru
iii. New contact to be added into the chat-contact list
iv. Contact to be deleted from chat-contact list.
1.1 addUser
This call is made when a new user signs up on guru.com.
Request parameters: username/userId, firstName, lastName, role.
Response: The API shall respond back with the status of the operation using an HTTP response code and
accordingly exceptions must be handled at gurus end.
When the operation succeeds, the user is persisted in the Openfire DB.
7/30/2019 Design Doc - Atlogys Technical Consulting
21/46
1.2 deleteUser
This call is made when a user is deleted from the guru.com web platform.
Request parameters: username/userId
Response: The API shall respond back with the status of the operation using an HTTP response code and
accordingly exceptions must be handled at gurus end.
1.3 addChatContact:
Invoked when employer exchanges message with a new freelancer or vice-versa (for both send and
receive)
Request parameters: username/userId, to whose roster the contact should be added, the
username/userId of the contact to be added, contactFirstName, contactLastName, role of person being
added.
Response: The API shall respond back with the status of the operation using an HTTP response code and
accordingly exceptions must be handled at gurus end.
We will first check if the contact is already in the roster of the user currently logged in. When the
operation succeeds, the contact is added to the users roster in Openfire DB.
If the user is already logged into chat at that time, we will propagate the new contact to client in real
time. The openfire plug-in will send back a XMPP stanza to the concerned users containing the contact
details of other. The web client will process this packet & update the roster in real -time.
1.4 deleteChatContact:
Invoked when employer deletes all message with a new freelancer or vice-versa (in the guru messaging
system).
Request parameters: username/userId, from whose roster the contact should be deleted, the
username/userId of the contact to be deleted.
Response: The API shall respond back with the status of the operation using an HTTP response code and
accordingly exceptions must be handled at gurus end.
When the operation succeeds, the contact is deleted from the users roster in Openfire DB.
Here we show the sample flowchart for addChatContact
7/30/2019 Design Doc - Atlogys Technical Consulting
22/46
7/30/2019 Design Doc - Atlogys Technical Consulting
23/46
Here we show the sample flowchart for deleteChatContact
7/30/2019 Design Doc - Atlogys Technical Consulting
24/46
2.
Openfire will provide API calls to be invoked by web client for doing authentication and creating session
with OpenFire.
[ To be invoked by web client ]
// explained in section on Authentication above.
Sample JS Api call pseudo Code:
Call sTrphone.connect function of Strophe.Connection object and pass JID to that function to connect to
OpenFire/Bosh server.
connect: function ( jid, callback, wait, hold)
Code snippet:
var con = new Strophe.Connection(jabber-server.com);
var conStatus Int;
con.connect(JabberID, password, onJabberConnected);
function onJabberConnected(status)
{
if (status === Strophe.Status.CONNECTED)
{
conStatus = 1;
}
else if (status === Strophe.Status.DISCONNECTED)
{
conStatus = 0;
}
}
3.
Must provide apis to provide chat related data directly to the web client.
[ To be invoked by the web client ]
These will include but not limited to API calls for requests like:
a. Filter users by their chat status only give all offline, only show all busy etc.
b. Ability to block/unblock a userc. View messages with user
d. Show all chat messages for this user grouped by date also mark the new messages
(these are the ones which have not been read yet) from 7 days to 2 years
e. Get Latest 50 chats
f. Get all chat messages for user X which are new (not read yet).
g. Save the content of chat on client side
7/30/2019 Design Doc - Atlogys Technical Consulting
25/46
h. Sign out of chat
i. etc
e.g.
getTranscripts()
Request parameters: username1, username2, startDate, endDate
Response: The API shall respond back with the list of transcripts exchanged between two concerned users
between the time duration mentioned by startDate & endDate.
Each Transcript can have following property:
timeStamp/date
text (actual messages exchanged between the user1 & user2)
10.3 Other Expectations
1.
Must make request to OpenId to authenticate user (using plugin as stated above)
2.
Chat Roster Management Apis -
a. Pull from Guru.com by making requests to guru.com
i. Populating the initial database on OpenFire side with existing user accounts.
ii. Pull from guru.com the chat contact list of the user which has just authenticated
with openfire.
3.
Designing and implementing database schemas for the openfire usage and storing all
information as desired.
11. Expectations from Guru web serverWhile interacting with the Openfire server, the Guru web server is assumed to take on following
responsibilities:
11.1 Data to be persisted:
Guru.com server will need to store following things in its DB:
1.
The web server must provide the users JID to the web client, which will be later, used for Openfire
authentication. The web server may store the JID in its DB.
- The chat domain of the Openfire server.
7/30/2019 Design Doc - Atlogys Technical Consulting
26/46
For e.g. if use with username freelancer is logs into the Guru.com web server & chat domain is
chat.guru.com then the JID generated for user can be:
- For enhanced security & reduced chances of getting tampered, web server will add salt to JID or take a
hash of it when sending to web client.
2.
Chat related UI settings like:
Was user on recent chats OR favorites OR all chats?
Sound is off or on?
Was the user logged into chat or not ?
11.2 API to be exposed
1.
The web server shall provide the REST API to retrieve all Registered Users.
[ Invoked by OpenFire on its initial deployment]
Web server will send both usernames and JIDs to openfire.
getAllRegisteredUsers()
Response: The API shall respond back with the list of all the users. The response can be in the XMl format.
When the operation succeeds, all the users are persisted in the Openfire DB.
2.
The web server shall provide the API to retrieve the chat configuration settings for a logged in user.
[ Invoked by web client ]
3.
It will also provide an API to save the updated chat configuration, which will be retrieved for subsequent
user visits to the site.
[ Invoked by web client ]
4.
The web server will support a call that gives chat roster list of each user
[ Invoked by Openfire upon authentication with each user ]
The API call can look as follows:
7/30/2019 Design Doc - Atlogys Technical Consulting
27/46
getRoster()
Request parameters: username/userId for whom to retrieve the roster
Response: The API shall respond back with the complete & most recent contact list for the conc erned user. The list
is constructed from the internal messaging policy employed by Guru.com server.
Each contact item from list can have following properties:
contactUsername/userId
contactFirstName
contactLastName
If the call is being made first time for this user by Openfire, it will persist the roster in its own table. Else, it will do a
sync to check roster and update it if required.
5.The web server shall provide an API to retrieve contact details like image, company/screen name for
each contact present in the roster of a logged in user.
[ Invoked by web client ]
The API call may look like:
getContactInfo()
Request parameters: JabberID (received from OpenFire)
Response: The API shall respond with all the info pertaining to the concerned user like:
firstName
lastName
contactImageUrl
contactRole etc.
screen name / company name.
11.3 Other Expectations
1. The web server upon successful authentication of user shall provide all the necessary data to theclient to login to openfire (like JID, location of chat server).
2. The web server will invoke the REST API calls exposed by Openfire on trigger based events that
happen inside guru.com - like new message exchange, new account created etc. [Explained in section
10.2 above].
7/30/2019 Design Doc - Atlogys Technical Consulting
28/46
12. Expectations from OpenId ModuleThe OpenId server shall expose a REST API that will accept the JabberID & validate its authenticity. It will
map the jabber ID to the userID and then check if the concerned user is valid & currently logged in on
Guru.com server. It can return the boolean status along with any extra data queried.
Openfire server will act as Relying Party and Guru.com will act as Provider Party. The communicationshall take place in conformance with the Guru.com OpenId Relying party guide document.
For e.g. if user named freelancer is logging into the Guru.com, then Openfire will send the
authentication request to Guru.com (which is Open Id provider) with Open Id as:
And the Guru.com will provide the response like:
openid.claimed_id: http://qa.guru.com/user.aspx/[email protected]
Upon receiving the affirmative response from OpenId server, Openfire will verify that the concerned
user exists in its DB. If the user exists, the user is successfully authenticated on chat.guru.com. Openfire
can also map this JabberID back to username and make sure it is the same for added authenticity.
13. Expectations from Web client
1. The web client should be able to communicate with Openfire server using BOSH over XMPP.
2. In essence it should be able to exchange the XML stanzas for XMPP communication wrapped in HTTP
or over stream. It shall be able to form the XML stanzas & parse the responses.
3. Using CORS (bot normal and pre-flighted), the web client shall take on the responsibility of directly
making calls to the Openfire plug-ins. The call can be like retrieving the transcripts over yesterday etc.
4. The web client shall call guru web server to retrieve the chat configuration saved in users previous
visit to site. Upon receiving such data, it shall appropriately render the web pages.
5. Once the web client gets the roster from openfire, it will get contact details of each user in the roster
from guru.com.
6. It will get authentication response parameters from guru.com and initiate session with openfire.
7. It will initiate logout from openfire when guru.com logs out.
7/30/2019 Design Doc - Atlogys Technical Consulting
29/46
14. Scalability and Performance1. Openfire has support for up to 20,000 concurrent users per server.
2. As per the information sent by Guru, they receive at any given time around 400 active concurrent
connections on any of their web servers. Since they have 4 servers, they can at-peak have 1600 live
active users at any point of time.
Besides 1600 active connections, OpenFire will also receive requests from guru (on trigger events) and
many requests from web client per active logged in user.
We assume a factor of N requests per logged in user where N needs to be determined.
The total simultaneous requests thus can be 1600 * N
3. OpenFire uses Apache Mina where we can configure the thread pool to handle the desired number of
total requests.
4. We can also deploy multiple server instances of OpenFire for scaling.
15. Experimental Setup Donea. OpenFire server is running at
http://78.47.223.136
b. We have integrated a Chat Web Client Goto
http://78.47.223.136/webchat/webclient.html
Select HTTP Binding
Enter details like:
HTTP Base= /http-bind/
Jabber Server = atlogys-openfire
The two user accounts created are:
ritika / ritika123
rajiv / rajiv123
Please login as each user in 2 separate browser windows and chat with each other.
Client uses direct CORS for communication with support for pre-flighted requests enabled on Openfire.
Previous Experiment:
Also did experiment with proxy
The client used BOSH functionality with Apache set as proxy in between client & Openfire server. It has
7/30/2019 Design Doc - Atlogys Technical Consulting
30/46
the version of JsJac library used at that time of development. (Scenario 2, Option 1)
16. UI Integration of Chat on Guru.com Web PagesThis section discusses the various approaches considered for rendering the chat window on guru webpages. The following conditions must be met:
1. The chat window should render identically on all pages whether .aspx or .cfm
2. The chat window should not refresh, and it must stay in the same location when user goes from one
.aspx page to the other, from one .cfm page to the other, or from an aspx page to a cfm page or vice-
versa.
3. The chat window must render as per the shared HTML mocks as referenced in Item # 3 and #9 in the
references table above.
16.1 Recommended Solution: Deep Linking
The idea is to use Ajax to only refresh the Non Chat related HTML on the page while the chat html
remains unchanged. And also use Ajax Crawling techniques like #! to make the Ajax URLs SEO friendly
and book-markable.
This approach is explained in detail in the following sections.
Section 1:
Currently, a typical page on guru (whether .cfm or .aspx) look as follows.
7/30/2019 Design Doc - Atlogys Technical Consulting
31/46
If we add the chat html in a div somewhere inside the body of this page, our goal is to ensure that it
does not refresh as we click on a link on this page (to goto another page). However, clicking on a new
link will re-load the entire html as shown above, thereby also refreshing the chat div.
We solve the problem as explained below in section2.
Section 2:
The current content of all existing pages (for each page) will be rendered inside div1.
Chat html will be rendered in div2.
Any links in div 1 (like header, footer links, nav bar links etc) will make Ajax calls to the guru.com web
server and only reload the content of div1 (Plus also update head for things like css, js files, meta info
etc). We will update the URL using #! To show the ajax click to the browser and user.
Section 3
1. The following url re-writing rules will be added to guru:
Original New
http://www.guru.com/myadmin.cfm http://www.guru.com/Main.cfm/#!myadmin
http://www.guru.com/PaymentReminder.cfm http://www.guru.com/Main.cfm/#!PaymentReminder
7/30/2019 Design Doc - Atlogys Technical Consulting
32/46
http://www.guru.com/xyz.cfm http://www.guru.com/Main.cfm/#!xyz
Original New
http://www.guru.com/Messages.aspx http://www.guru.com/Main.aspx/#!Messages
http://www.guru.com/Payments.aspx http://www.guru.com/Main.aspx/#!Payments
http://www.guru.com/xyz.aspx http://www.guru.com/Main.aspx/#!xyz
2. SiteMap
All new urls under New column of table above will get added to sitemap.xml for crawling
purposes.
Please see section on crawling and indexing below.
3. URL Handler Rules:
The following additional url handler rules need to be added on the IIS server:
Ajax requests to #!Messages.aspx get directed to the current (already existing) handler for
emp/shared/Messages.aspx
Ajax requests to #!PaymentReminder.cfm get directed to the handler for
emp/shared/PaymentReminder.cfm
And so on
// Please note that these url schemas and redirect handlers can be further optimized. This can be donepost initial discussion with Guru.
Section 4:
1.
Next we will update all existing .aspx and .cfm pages inside the
Guru / Websites / marketplace / emp[pro] folders such that they give the
headless and bodyless (without the< head> and tags) html content only.
We will remove the basicTags like , and .
This is because the content returned by them must be rendered inside Div1 only.
This is called the reducedHTML.
This is just a minor modification.
7/30/2019 Design Doc - Atlogys Technical Consulting
33/46
E.g. Lets consider Messages.aspx . It uses
emp/shared/EmployerBase.master to render the basicTags like , , .
MESSAGES.ASPX
The emp/shared/EmployerBase.Master inturn looks like:
// SNIPPED //
// SNIPPED //
7/30/2019 Design Doc - Atlogys Technical Consulting
34/46
This will be changed so it now looks like:
// SNIPPED //
// SNIPPED //
2.
Furthermore, we must modify any GET/POST calls from inside the BODY section of these pages (or any
direct anchor links) to NOW be in ajax. E.g. If the Messages.aspx page has a link to Payments.aspx page,
instead of being a regular request, this will NOW be an ajax request to #!Payments.aspx page (which in
turn as per modifications proposed in this section 3 will only give the desired reducedHTML).
We will do so by adding tab=rel to all links present inside of any cfm or aspx page
7/30/2019 Design Doc - Atlogys Technical Consulting
35/46
Payments
There will be JavaScript which says that when any link with tab=rel is clicked, send an Ajax request and
update content of div 1 only. Then modify browser url seen by user to appropriate format depending on
whether browser is html5 supported or not (Just like as seen on facebook).
3.
Note, this example assumes pages in the MVP architecture Only. For legacy guru code where pages are
not in MVP, we will first confirm them into MVP and then make the changes as proposed in these
sections.
Section 5
Add a new handler for Main.aspx and Main.cfm.
The main goal of this page is to spit out the , , tags with the 2 divs. It will load chat
html in div2 and it will have javascript which will then load content in div 1 via an ajax request to the
appropriate page.
e.g. here is the sample code received when request is sent to:
guru.com/Main.aspx/#!xyz is sent.
/* The section below only gives bare bones pseudo-code for high level understanding */
1.
2.
// This is the function that registers ajax request for all links inside div1// that have tab=rel.$(function(){
$("a[rel='tab']").click(function(e){pageurl = $(this).attr('href'); //gets xyz.aspxurl = get stuff before . //gets xyz
extension = get stuff post . //gets aspxsendAjaxRequest(url, extension, true);return false;
});});
// This is the function invoked in Main.aspx (or main.cfm) after it getsloaded to fetch page content for div1.function makeRequest() {
source = window.location; // gets guru.com/Main.aspx/#!xyz
7/30/2019 Design Doc - Atlogys Technical Consulting
36/46
url = extract text post / from source // gets #!xyz or xyz depending onbrowserif (url . beginsWith(#!) { // in case of non html5 browsers
url = url.post(#!) // gets everything post #!}extension = extract extension of Main in source //gets aspxsendAjaxRequest(url, extension);
}
// Makes the ajax request and gets the content, replaces it in div1, head,updates browser url.function sendAjaxRequest(url, extension) {1. send ajax request to (#! + url + extension)// This makes request to #!xyz.aspx. As per URL handler registered in section 3, thisgets sent to emp/shared/xyz.aspx. As per section 4, client gets reducedHTML
2. Render the from reducedHTML in head above (part 1)3. Render the rest of the html received in div 1.4. If (nonHtml5 supported Browser) {
5. Change url in address bar to be guru.com/Main + extension + /#! +url;} else {
6. window.history.pushState(guru.com/Main + extension + / + url ;);}
}
Chat html
This is a simple master page which loads two divs. The first div after loading on client side, gets its
content from ajax. It also updates head section for the page requested to load the css, js files required
by this page in particular.
Inside div1, if user clicks on any link like payments, it sends an
ajax call to #!payments.aspx which is then handled as seen in section 3.
The url of the browser is then updated to be
a) Guru.com/Main.aspx/#!Payments (for Non html5 browsers)
Or to
b) Guru.com/Main.aspx/Payments (for html5 browsers)
7/30/2019 Design Doc - Atlogys Technical Consulting
37/46
Thus users can bookmarks both links of type a or b.
The JavaScript function makeRequest above can handle both kinds of urls.
Javascript Libraries:
Please note that the JavaScript code shown above is just pseudo code. The actual code will use deep
linking libraries like swfadress etc. We will use appropriate libraries
SWFAddress.onChange = function () {var url = window.location.pathname + "home/" + SWFAddress.getValue();$.ajax({ type: "GET", url: url, dataType: "html", success: function (result) {
$("#dvMainContent").html(result);}});
SWFAddress Library Please see for more details:
http://www.asual.com/jquery/address/docs/#
IMPORTANT NOTE:
The contains css, js and meta tags specific to the page being rendered. Now, if pages will be
rendered using ajax, we must update the links, cs files and meta info on the section using
javascript.
** It would be best to refactor the existing code for rendering information in tag in a moremodular manner so it can be streamlined and easily updated with Javascript.
Alternate to be discussed with Guru
In section 4, instead of sending reducedHTML, we can send the same HTML (as guru sends now) w/o any
modification. Then in section 5, the javascript function can parse out the and
information and render it in div 1 and as explained above.
This depends on re-factoring complexity at Guru and legacy code which needs to be discussed.
URL Naming Convention:
Please note that the new urls can be further optimized. The current format is being proposed for basic
understanding. We can choose to use the same or optimize it. Lets discuss.
Section 6
7/30/2019 Design Doc - Atlogys Technical Consulting
38/46
Ajax Crawling
One common problem with ajax is that urls are not crawlable by search engines. Furthermore, the
browser back, history buttons will not honor such urls. Users cant bookmark or email them either.
Google has recently proposed a strategy for making ajax urls crawlable. All major sites like Facebook are
using this technique. This requires adding #! Into the URL which is specially treated by crawlers like the
googleBot.
Please see this specification from Google:
https://developers.google.com/webmasters/ajax-crawling/docs/getting-started?hl=es
In html5 browsers, this has been made part of the standard spec. It is called onpopstate.
Please see this for more information on Html5.
http://spoiledmilk.com/blog/html5-changing-the-browser-url-without-refreshing-page
Section 7
Control Flow
1. User logs in as employer.
2. User is redirected to
http://www.guru.com/Main.cfm/#!myadmin
3. The code as shown in section 5 is invoked. Div 1 loads and div2 loads with the chat html in it.
4. the body upon loading Div 1 upon loading makes ajax call to #!myadmin.cfm which is handled by the
current handler for /myadmin.cfm.
5. As per the modifications proposed in section 3, the reducedHTML is returned which is loaded in head
and div1. So Div1 now shows the current myadmin.cfm page as seen on guru.com.
6. The page will look as follows:
Div 1 (myadmin)
Header
Nav Bar
link A
Div 2 (chat)
7/30/2019 Design Doc - Atlogys Technical Consulting
39/46
7. If user clicks on LinkA, then as per section 3, this sends an ajax request to
/#!linkA.aspx and the returned HTML is rendered in div 1 only without refreshing the chat window.
8. Depending on whether the users browser is HTML5 compatible or not, the url in the address bar is
updated to:
http://www.guru.com/Main.aspx/#!linkA
OR
http://www.guru.com/Main.aspx/linkA
Section 8
Bookmarking
Lets suppose a user bookmarks a URL like
http://www.guru.com/Main.cfm/#!myadmin
or
they bookmark something like
http://www.guru.com/Main.cfm/myadmin
When they copy paste this url in the browser, then section 5 will get invoked and things will work as
explained in section 5.
Section 9
Old URLs.
Lets suppose users find on old urls in their browser history or bookmarks like:
http://www.guru.com/Messages.aspx
As per the url re-write urls, this will get re-directed to
http://www.guru.com/Main.aspx/#!Messages
Then section 5 will get invoked and things will work as expected.
7/30/2019 Design Doc - Atlogys Technical Consulting
40/46
Section 10:
How will SEO work?
1. We will add the new urls to sitemap.xml as mentioned in section 3.
2. When the crawler sends a request like
http://www.guru.com/Main.aspx/#!Messages,
the guru web server will receive something like
http://www.guru.com/Main.aspx/_escaped_fragment_Messages from the crawler.
(This is as per the google defined specs under:
https://developers.google.com/webmasters/ajax-crawling/docs/getting-started?hl=es )
3. The output now will need to be an HTML snapshot rather than the regular page.
The web server will give the output as identified in section 5 above.
4. This will then be passed through a headless browser like HtmlUnit on the web server.
5. The output of the headless browser will be the html snapshot given to the crawler.
NOTE: A crawler like googleBOT, unlike a browser, cannot execute JavaScript. Thus we must return an
HTML snapshot to the crawler using a headless browser like HtmlUnit.
Please note that An HTML snapshot is all the content that appears on the page after the JavaScript has
been executed.
Thus the headless browser will make then ajax call for div1 and give the final page to the crawler for
indexing.
7/30/2019 Design Doc - Atlogys Technical Consulting
41/46
Alternate approaches that were considered and rejected for various reasons
Solution 1: User Control with Update Panel
Create a Chat folder under User Controls of Marketplace website.
Create Chat.ascx User Control under Chat folder. Add a new content place holder cph2 in the following master pages under emp/shared &
pro/shared:o EmployerBase.Master.master
o EmployerMaster.master
o FreelancerMaster.Master
o FreelancerBase.Master
Note the following master pages of legacy code also need to be considered:o EmpEditMasterPage.Master,EmployerBaseMasterPage.master,FreelancerBaseMasterPage.maste
r,FreelancerEditMasterPage.master,FreelancerSTMasterPage.master,FreelancerSTMasterPage.m
aster
Add Chat.ascx under the cph2
All the existing pages of GURU.com (the way they are) will reside in content place holder cph1.
Create an Update Panel upl1 that will contain cph1.
Create an Update Panel upl2 that will be contain cph2.
The updatePanel will prevent the page refresh of the chat window as user works on guru.com.
Concerns:
When user will navigate from one master page to another master page whole page will be refreshed.
In other words, when I click on a link, then if both the source and target page use the same master page,
the chat window will not be refreshed. However, if the source and target page use separate master
pages, then the chat window will get refreshed.
Gurus Scenario:
a) emp/Messages.aspx --> uses emp/shared/EmployerBase.masterb) emp/Payments.aspx --> uses emp/shared/EmployerMaster.master
This means that when user will go fromGuru.com/Messages.aspx TO guru.com/Payments.aspxThe chat window will refresh.
c) emp/modify_account.aspx uses MarketPlace/MasterPages/EmployerBaseMasterPage.masterd) emp/ChangeUsernamePass.aspx --> uses
MarketPlace/MasterPages/EmployerBaseMasterPage.master
This means that when user will go from
Guru.com/modify_account.aspx TO guru.com/ChangeUsernamePass.aspx,
The chat window will NOT refresh.
Further Analysis
We tried creating a parent-to-all top level master page which could be used by all aspx pages.
This way all aspx pages would have the same top level master page and hence the chat should never
7/30/2019 Design Doc - Atlogys Technical Consulting
42/46
refresh.
However, on experimentation, we realized that because of the nesting of separate inner layer master
pages, the chat window still kept getting refreshed.
Hence this approach was rejected.
Solution 2: User Control with HTML Frames (NOT RECOMMENDED)
o Create one top level HTML page (e.g. index.htm) under the root folder of Marketplace
website.
o This page will contain 2 frames. In one frame, render the current guru.com pages. In the
2nd frame, render the web chat client. Both frames will point to guru.com domain.
o Create Chat.ascx User Control under Chat folder.
o Add content place holder cph2 in the following master pages in emp/shared and
pro/shared:o EmployerBase.Master.master
o EmployerMaster.master
o FreelancerMaster.Master
o FreelancerBase.MasterNote the following master pages of legacy code also need to be considered:
o EmpEditMasterPage.Master, EmployerBaseMasterPage.master,
FreelancerBaseMasterPage.master, FreelancerEditMasterPage.master,
FreelancerSTMasterPage.master, FreelancerSTMasterPage.master
o Add Chat.ascx under the cph2.
o Let all existing pages of GURU.Com reside in cph1.
o Put all existing web site pages in Iframe 1 and web chat client in Iframe 2. Use Jquery to
distinguish calls for which Iframe and refresh accordingly.
o This way across master pages, the chat window will not refresh.
Concerns:While implementing the Iframe concept to prevent page refresh across the pages and
Master pages, the user browser URL will remain the same.
Iframes are also Not recommended for SEO purposes.
17. Chat Module on Guru1. We will add new Module called Chat in guru websites marketplace. This Chat module will contains all
the view pages and Chatcontroller.cs class
2. View pages will communicate with ChatController.cs
3. Chatcontroller.cs file will communicate with ChatService under
\GuruFramework\Guru.Services.Hosts.Web\ChatService.svc.
7/30/2019 Design Doc - Atlogys Technical Consulting
43/46
4. We will create new WCF service ChatService.svc. This service will contain all the method that
requires communication with open fire (between guru and openfire).
18. Theory (and definitions for FUN Learning)XMPP
The Extensible Messaging and Presence Protocol (XMPP) is an application profile of the Extensible
Markup Language (XML) that enables the near-real-time exchange of structured yet extensible data
between any two or more network entities. XMPP provides a technology for the asynchronous, end-to-
end exchange of structured data by means of direct, persistent XML streams among a distributed
network of globally addressable, presence-aware clients and servers.
XMPP vs. REST
Because this architectural style involves ubiquitous knowledge of network availability and a conceptually
unlimited number of concurrent information transactions in the context of a given client-to-server or
server-to-server session, we label it "Availability for Concurrent Transactions" (ACT) to distinguish it
from the "Representational State Transfer" [REST] architectural style familiar from the World Wide
Web.
XMPP, therefore, is more relevant for applications like IM and chat.
XMPP Transportation
The original and "native" transport protocol for XMPP is Transmission Control Protocol (TCP), using
open-ended XML streams over long-lived TCP connections. This native XMPP communication is socket or
stream based & happens over TCP port no: 5222/5223.However, web clients (or browsers) need HTTP
for communication so in such situations XMPP has to be wrapped in HTTP payloads.
(Via HTTP)
As an alternative to the TCP transport, the XMPP community has also developed an HTTP transport
for web clients as well as users behind restricted firewalls. In such scenarios the TCP port used by
XMPP is blocked, and the server can listen on the normal HTTP port or one with an HTTP binding.
Various websites use this to allow people to sign in to XMPP server via a browser.
Originally, XMPP could use HTTP in two ways:
polling
binding
BOSH
This specification defines how the Bidirectional-streams Over Synchronous HTTP (BOSH)
technology can be used to transport XMPP stanzas. The result is an HTTP binding for XMPP
7/30/2019 Design Doc - Atlogys Technical Consulting
44/46
communications that is useful in situations where a device or client is unable to maintain a long-
lived TCP connection to an XMPP server.
With BOSH, the client uses HTTP long polling to receive messages as soon as they are sent. This
push model of notification is more efficient than polling, where many of the polls return no new
data.The IANA-registered port for BOSH is actually 5280, not 80.
There are JavaScript libraries like sthrope.js and JsJac.js that do XMPP over BOSH.
Bosh (vs. Ajax)
Bosh is implemented using Ajax only.
BOSH is designed to transport any data efficiently and with minimal latency in both
directions. For applications that require both "push" and "pull" semantics, BOSH is
significantly more bandwidth-efficient and responsive than most other bidirectional
HTTP-based transport protocols and the techniques now commonly known as "Ajax".
However, just like AJAX, BOSH is also restricted by the same origin policy of the browser.
(Via WebSockets)
A perhaps more efficient transport for real-time messaging is WebSocket, a web technology
providing for bi-directional, full-duplex communications channels over a single TCPconnection.
Experimental implementations of XMPP over WebSocket exist, and a (now-expired) Internet-
Draft documenting this approach was published at the IETF but not yet standardized.
WebSockets is a HTML5 feature and it is only supported by latest browsers like Firefox 6 (named
MozWebSocket), Google Chrome 14 and Internet Explorer 10 developer preview.
There are JavaScript libraries that do XMPP over websockets.
Other things to study: COMET, Reverse HTTP etc.
Same Origin Policy
The policy permits scripts running on pages originating from the same site to access each other's
methods and properties with no specific restrictions, but prevents access to most methods and
properties across pages on different sites.
Ways to get around SOP:
Additional document.domain logic
An important extension to the same origin policy implemented for JavaScript DOM access (but
not for most of the other flavors of same-origin checks) is that two sites sharing a common top-
level domain may opt to communicate despite failing the "same host" check by each setting
7/30/2019 Design Doc - Atlogys Technical Consulting
45/46
their respective document.domain DOM property to the same qualified, right-hand fragment of
their current host name.
For example, if http://en.example.com/ and http://fr.example.com/ both
set document.domain to "example.com", they would be from that point on considered same-
origin for the purpose of DOM manipulation.
CORS
Cross-origin resource sharing (CORS) is a web browser technology specification which defines
ways for a web server to allow its resources to be accessed by a web page from a different
domain.[1] Such access would otherwise be forbidden by the same origin policy. CORS defines a
way in which the browser and the server can interact to determine whether or not to allow the
cross-origin request.[2] It is a compromise that allows greater flexibility, but is more secure than
simply allowing all such requests.
CORS is supported by all browsers based on the following layout engines:
Gecko 1.9.1 (Firefox 3.5,[3] SeaMonkey 2.0[4]) and above.
WebKit (Initial revision uncertain, Safari 4 and above,[1] Google Chrome 3 and above,
possibly earlier)[5]
MSHTML/Trident 4.0 (Internet Explorer 8) provides partial support via the XDomainRequest
object.[1]
Presto-based browsers (Opera) implement CORS as ofOpera 12.00[6] and Opera Mobile 12,
but not Opera Mini.[7]
JsonP
CORS can be used as a modern alternative to the JSONP pattern. While JSONP supports only the
GET request method, CORS also supports other types of HTTP requests. Using CORS enables a
web programmer to use regular XMLHttpRequest, which supports better error handling than
JSONP. On the other hand, JSONP works on legacy browsers which preclude CORS support.
CORS is supported by most modern web browsers. Also, whilst JSONP can cause XSS issues
where the external site is compromised, CORS allows websites to manually parse responses to
ensure security.[2][1
Web Sockets
WebSocket is a web technology providing for bi-directional, full-duplex communications channels over a
single TCP connection. The WebSocket API is being standardized by theW3C, and the WebSocket
protocol has been standardized by the IETF as RFC 6455.[1]
7/30/2019 Design Doc - Atlogys Technical Consulting
46/46
WebSocket is designed to be implemented in web browsers and web servers, but it can be used by any
client or server application. WebSocket also requires web applications on the server to be able to
support it.
The WebSocket protocol makes possible more interaction between a browser and a web site, facilitating
live content and the creation of real-time games. This is made possible by providing a standardized way
for the server to send content to the browser without being solicited by the client, and allowing for
messages to be passed back and forth while keeping the connection open. In this way a two-way (bi-
directional) ongoing conversation can take place between a browser and the server. A similar effect has
been achieved in non-standardized ways using stop-gap technologies such as Comet.
In addition, the communications are done over the regular TCP port number 80, which is of benefit for
those environments which block non-standard Internet connections using a firewall.
Preflighted Requests with CORS
While making CROS Ajax requests, browsers can proceed in one of the following two ways:
a.
Make the POST, GET etc requests directly to the different domain. (These are generally called
simple requests & don't negotiate much about the headers.)
b.
Make what is called as "Preflighted" request before making the actual POST, GET requests. The http
method with which this request is made is - OPTIONS. This preflighted request is like handshaking &
agrees upon the specific http methods, headers to be exchanged between browser & server.
Once this preflighted request is successful, the browser caches this till the time mentioned by
server (with header "Access-Control-Max-Age") and can make the GET, POST directly without
making the OPTIONS request again for that time period.
Browsers like Firefox and IE (version 9) use option a. They directly made POST requests.
Browsers like Safari and Chrome use option b.
More Information:
https://developer.mozilla.org/en/HTTP_access_control
http://www.bennadel.com/blog/2327-Cross-Origin-Resource-Sharing-CORS-AJAX-Requests-
Between-jQuery-And-Node-js.htm