Design Doc - Atlogys Technical Consulting

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]

    [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:

    [email protected]

    - 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:

    [email protected]

    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