Home Documentations Displaying items by tag: documentation

Member Area

Donation

Poll

Is JsRS easy to setup?
 
Displaying items by tag: documentation
Monday, 26 July 2010 20:13

VI. Server

Most of the time, you won’t touching the server unless you wanted to do some major customization. The server simply forward the message and control the heartbeat connection of each client.

 

a. Adding custom server functions

Open up the /Server/Function.php. The functions which declared as public are able to be called by the client. To define your own server function, just add it like this:

class Jsrs_Server_Function
{
   // Existing function here...
   
   // New function here...
   public function myFunction(Jsrs_Server_Message_Client $msg, Jsrs_Server_Connection $connection, $params = array())
   {
       // Your function body here.
       // Send back your result through the $connection object.
       $connection->send($messageObject);
   }
}


The first parameter must be the client’s message object. Please refer to the API for details about what you can do with the Jsrs_Server_Message_Client object.

The second parameter will be the client’s connection object. This object hold the connection resources that allowed you to send message back to the client.

The last parameter is the function’s parameters passed by the client. It is optional. The parameter is an associative array. If the client did not specify the key of the value, the index of the array will be numeric in ascending order starting from 0. Eg: $params[0], $params[1], ....

 

Customizing server function required extensive knowledge on how JsRS works. It is better for you to familar with the whole framework before doing the customization.

 

b. Function APIs

Below is the list of functions available from the server. Please note that the parameters is the required parameter from the client.

Function’s name Parameter(s) Description Result
connect N/A Connect and register the client to the server. Event: onConnected(newClient, clientId)
disconnect N/A Disconnect the client and it’s connections. Event: onDisconnected()
getConnectedClients N/A Get a list of all connected client. Result:
array(
“result” => array(
“id” => <id>,
“info” => array()
)
)
listen N/A Listening on the server. There will be no immediate result send back. It will hold the connection until there is a message for this client or expired.
replyCallback i.) message_id - The ID used to reference for the callback message.
ii.) result - The result value that going to send back.
To return the result back to the sender. Boolean. True upon successful.
plus Array of numbers. Eg: array(1, 2, 5, 23,...) This is a test function to do a summation of all the numbers provided in the database. Result:
array(
“result” => <number>
)
Published in Version 1.0
Monday, 26 July 2010 20:00

V. Proxy Controlling

a. What is a proxy

The proxy is the middleman between your client and the server. It gives you the ability to control what your client can do. The proxy is a PHP file. Your client (JavaScript) will send a HTTP request to this proxy and call the remote function on the other client through the XHR(Ajax) transport.

 

The proxy file will place within your application so that it can access your session data to determine the client’s ID. At current stage, the proxy only supports PHP application.

 

b. Extending proxy class

By default, there a file called proxy.php which already extended the proxy class (Jsrs_Proxy_Abstract) with the class name, “Standard”. The only function you need to override is the “_getClient” function.

 

This function is used to determine the type of client should be instantiate when the request was made. Because the proxy will be called by your client (JavaScript), you can determine the type of client by checking the session. For example Administrator, Author, Member or Normal User.

You can determine by using your session data:

protected function _getClient()
{
   switch ($_SESSION['user_type']) {
       "admin":
           return "Jsrs_Proxy_Client_Admin";
       "author":
           return "Jsrs_Proxy_Client_Author";
       "member":
           return "Jsrs_Proxy_Client_Member";
       default:
           return "Jsrs_Proxy_Client_User";
   }
}


The function is accessing the session data and determines the user’s type. Of course, this might different depends on your application. The function must return either the full class name or the client object itself. The client object must be child class from Jsrs_Proxy_Client_Abstract. Read on the next section on defining user’s type.

You can override the default property that defined in the Jsrs_Proxy_Abstract class too:

class Standard extends Jsrs_Proxy_Abstract
{
   protected $_host = "192.168.0.1";
   protected $_port = 12345;
   protected $_defaultPermissive = "denied";
}


If your JsRS server was hosted in another server, you might want to replace it with the IP address or the host name. You can change the listening port number if your server is listening at different port number. The $_defaultPermissive is to determine whether a message should be rejecting if the permission function was not defined (eg: sfPlus, cfSayHello). If you set to “denied”, means any server or client remote function that without defining the permission control function, will be rejected. By default, this value is “allowed”.

 

c. Defining the user's type

You might need to define the types of user that connected to your live application. By defining the user’s type, you can set the permission of each function for each type of user. By default, the “Standard” user class was defined for you. You must define at least 1 user type in order to run JsRS. For instance you wished to define a member user type:

class Jsrs_Proxy_Client_Member extends Jsrs_Proxy_Client_Abstract
{
    public function cfRedirect()
    {
        return false;
    }

    public function sfPlus()
    {
        return false;
    }
}



You should save this class file as Member.php under /proxy/client/. This proxy will prevent the Member type of user to call a remote function name “redirect”. Note the prefix in front of the function. “cf” is refer to client function, while “sf” is refer to server function. The users with Member type are NOT able to call the server function “plus” too. Any non-false value returned will allowed the message being pass through the proxy and send to the server. Throwing an exception will caused the message being reject:

public function sfPlus()
{
   throw new Jsrs_Proxy_Exception(“Message here”, “Title here”, 100);
}

 

Throwing the proxy exception (Jsrs_Proxy_Exception) will invoke the exception handler in the client (exceptionHandler). You can throw any other exception object such as RuntimeException or Exception, these exceptional objects will NOT invoke the exceptionHandler function in the client script.

Beside of controlling the remote function, you can control the event received too:

public function onClientConnected($client)
{
   if (false === in_array($client[“id”], $friendList)) {
       return false;
   }
}


The function above will check whether the connected client is actually in the friend list or not. If not, it will not send the event to the client (JavaScript) and thus, the “onClientConnected” event will NOT fired. Put this function inside your client class to control the event happened.

Note: For those functions that did not defined in your client class, by default, the message will be received or sent through. You can change this behavior by overriding the default value of $_defaultPermissive to “denied” in the Jsrs_Proxy_Abstract class.

d. Helpers

i. Introduction

The Helper class is to reduce the needs of extending your client class in order to perform some custom functionality. Most of the time, you might focus on the client class file (Jsrs_Proxy_Client_Class). For some client remote function, you might want to check the permission based on the MySQL database. Building the database connection on each client class is very troublesome neither extending your client class is a good idea too. What the Helper class can offer you is to allow you to define a class that access to the MySQL database and call it from your client class like this:

class Jsrs_Proxy_Client_Member extends Jsrs_Proxy_Client_Abstract
{
     public function cfSayHello()
     {
         return $this->_helper->IsAdmin($_SESSION[“user_id”]);
     }
}

 

You can use this helper “IsAdmin” on any client class with the same statement. Please be careful with the helper name, the first character must be capital letter and the name must be exactly same as the Helper class file.

 

The $_helper object is defined in the Jsrs_Proxy_Client_Abstract. You don’t have to worry about it. Just call it directly to get your result.

ii. The ServerBorker helper

By default, there is one helper class, “ServerBroker”. You can use this to invoke any server’s function without connecting to the server. The result returned is in array format. To call the function, you need at least one parameter which is the server’s function name. The second parameter has to be an array which represents your parameter. The parameter array can be an associative array. Example:

array(
    "parameter1" => "value1",
    "parameter2" => "value2"
)

 

To make a server function call, do this:

$result = $this->_helper->ServerBroker("plus", array(8, 50, 30));

The $result will return you an associative array with this value:

array(
    "result" => 88
)


Notice on how the parameter being passed. You have to put all the value in the array and pass the array in the second parameter of the Helper class.

iii. Creating your own Helper class

You must place your Helper class under /Proxy/Helper and your Helper class must inherit from Jsrs_Proxy_Helper_Abstract. You have to override the “run” method in order to perform your custom task. The “run” function is the default function when calling a Helper class:

$this->_helper->HelperClassName();
// Equivalent to Jsrs_Proxy_Helper_HelperClassName::run()

 

For instance you want to define a MySQL database accessing Helper, you created a Helper class file named Jsrs_Proxy_Helper_IsAdmin.php in /Proxy/Helper:

class Jsrs_Proxy_Helper_IsAdmin extends Jsrs_Proxy_Helper_Abstract
{
    public function run()
    {
        // Do your SQL connection and Query and return the Result.
    }
}

 

You can always extends your Helper class. For example you have few Helper class that needs to access to MySQL database, you can create a MySQL Helper class that will automatically connect to the database once the Helper class was called. Then you will extends those Helper that needs to access the database from this parent class.

Published in Version 1.0
Sunday, 25 July 2010 23:28

IV. Client-side scripting

a. Instantiation and initialization

Just like any client-server application, you need to connect to the server in order to utilize the services. But this time, you will connect it in JavaScript. First include the JsRS library to your html file. Put this line in your head section.

<head>
  […]
  <script language="JavaScript" type="text/javascript" src="/javascript/jsrs.js"></script>
</head>

Now you need to instantiate a socket object from the JsRS library. You can put this code right after the opening <body> tag or you can wrap it up within a function and call it later (onclick from a button).

<script language="JavaScript" type="text/javascript">
var socket = new Jsrs({
    "proxy" : "Proxy/proxy.php",
    "cf" : {
        "functionName" : function(client, param1, param2) {
            // Your remote function body here.
        }
    },
    "events" : {
        "onConnected" : function(newClient, clientId) {
            // When you’ve successfully connected.
        },
        "onDisconnected" : function() {
            // When you’ve disconnected unexpectedly.
        },
        "onClientConnected" : function(client) {
            // When a new client connected.
            // client["id"] will return you the ID.
        },
        "onClientDisconnected" : function(client) {
            // When a client disconnected.
            // client["id"] will return you the ID.
        }
    }
});
socket.connect();
</script>

The codes above will instantiate the socket object and initialize it with the proxy path, the event handler and the remote function or the common function.

The functions that stored in the "events" object is used to handle when a certain event is fired. For example the "onConnected" function will be called when the connection was successfully established. The parameters inside the event function is passed by the server. The first parameter (newClient) is a boolean value to determine whether you are a new client or not. Because in some case, a user might open few tab or window of a same browser. JsRS is able tell that they are the same client through their session’s ID or client’s ID (Depends on your application). The second parameter (clientId) is the ID of the client that connected to the server. It is like a IP address.

For functions that stored in "cf" is the remote functions. Those are the functions that able to call by other clients. For your understanding, those function inside "cf" is like an event. They must be call by other client in order to run the function.

 

b. Basic remote scripting

Before you calling a remote function, you must define it. You can define the remote function either during the initialization or runtime:
Initialization:

var socket = new Jsrs({
    "cf" : {
        "sayHello" : function(client, message) {
            alert(client["id"] + " has sent you a message: " + message);
        }
    }
});

Runtime:

socket.cf.sayHello = function(client, message) {
    alert(client["id"] + " has sent you a message: " + message);
};

Both are having the same result. Once you have defined the remote function, you can call it using the client remote calling function, "callCF".
Note: The first parameter is always the client’s (sender) object. The basic element is "id". You may get more info of the client through the "info" property. Eg: client["info"].

i. Client remote function

Calling a remote function is very simple. You have to specify the recipient’s ID and the function name.

socket.callCF(client, funcName, [[params], callback]);

The third and fourth parameters are optional. You must provide array for the first parameter even though there is only one recipient. Example:

socket.callCF([12], "sayHello", ["Hi there!"]);


Same goes to the function’s parameters, the third one. You must provide array even though it is only one parameter for the function. The acceptable parameter types are object, string, number and array.

The code above will call the remote client with the ID: 12 to invoke the remote function "sayHello" and passed the string "Hi there!" to the second parameter.

ii. Server remote function

Under certain circumstances, you might want to retrieve information from the server. Please refer to the Server’s APIs for more details. It is very similar to calling a client remote function:

socket.callSF(funcName, [[params], callback]);

 

You have to specify the function’s name that you want to call on the server. Example:

socket.callSF("plus", [10, 70], function(result) {
 alert("The result is: " + result);
});

The function "plus" is a test function from the server which take the parameters passed by you and do a summation. The returned result will be 80. If the message was successfully passed, you should received an alert message, "The result is 80".
Note: The function parameter has to be an array even though it’s only has one parameter.

 

c. Getting remote clients

Without the client’s ID, you can’t do any remote scripting. It is depend on what application you are writing and it will affect on how you store your client’s ID. I will explain how you going to get the client’s ID but I ain’t going to talk about how you store it.

There are two way you can get the connected clients: (1) Calling server functions, (2) Event functions.
Currently, there is one server function named: "getConnectedClients". This will return you a list of clients with their ID and info. With this, you can get the connected clients. Again, depends on your application on where you want to store them.

socket.callSF("getConnectedClients", function(clients) {
    for (var i in clients) {
        var client = clients[i];
        var clientId = client["id"];
        var clientInfo = client["info"];  // This is optional and might different depend on your application.
    }
});


The second way is the event. Through the event, you can get the newly connected client. Jsrs::events::onClientConnected allowed you to handle when there are new clients connected. With this, you can update the list of connected clients in your application (JavaScript). Of course, you might need to keep track of disconnected clients, Jsrs::events.onClientDisconnected allowed you to handle when there is a client disconnected from the server. Please refer to the API for more details.

 

d. Returning data from remote function

In section b. ii., you know how to get the result from the server’s function. You can do the same thing for client. Meaning you send a remote function call to a specific client and ask the client to process and send back the data. For example you wanted to know the client’s name. You might need to define the remote function first:

socket.cf.getName = function(client, sendResult) {
     var name = prompt(client["id"] + " is asking your name.", "");
    if (name) {
        sendResult(name);
    }
};

The remote function above will prompt the user (using prompt function) and get the input as the result (user’s name) and then send back to the sender using the sendResult function.

If you are defining a remote function that required a callback, the last parameter is always a function for you to send back your result. Don’t get confused, lets read on first.

Now you’ve defined the remote function, it is time to call it:

socket.sendCF([12], "getName", function(clientName, client) {
     alert("The client's name ("+ client["id"] +") is: " + clientName);
});

The first and second parameters are the client’s ID and the remote function’s name respectively. Because the remote function do not required any parameter, so we skipped it. The third parameter will be your callback function.

The callback function will be invoked once the recipient processed and return back the result using "sendResult" function. The execution context within the callback function is the Jsrs instance. Meaning this.proxy will return you the proxy URL.

 

e. Event handlers

Event handlers allowed you to catch any events happened. Below is the list of event handlers:

Event’s name Parameter(s) Description
onConnected i.) newClient - To check whether you are a new client or a existing client (open new tab or window).
ii.) clientId - Your connected client’s ID.
It is happened when you’ve successfully connected to the server.
onDisconnected N/A When you get disconnected from the server.
onClientConnected i.) client - The client’s object that connected to the server. It is happened only once when the client is newly connected to the server.
onClientDisconnected i.) client - The client’s object that disconnected from the server. It is happened when none of the client connection are connected to the server.
onExpired N/A When the client’s connection expired. This is to keep the heartbeat connection stay alive.
Published in Version 1.0
Sunday, 25 July 2010 21:10

III. Installation guide

a. Download

Download the latest version of JsRS from here. Once you’ve downloaded, unzip the archive to your local drive. Eg: C:\jsrs-1.0\

 

b. File structure

I always believe that the file structure will determine how complicated your software is. So I’ll try to keep the file structuring as simple as possible. Here it is:
  • /jsrs-x.y
    • /Javascript
      • Index.html
      • jsrs.js
    • /Proxy
      • /Client
        • Abstract.php
        • Standard.php
      • /Helper
        • Abstract.php
        • ServerBroker.php
      • Abstract.php
      • Exception.php
      • Helper.php
      • proxy.php
      • Services_JSON.php
    • /Server
      • /Message
      • Client.php
      • Connection.php
      • ConnectionManager.php
      • Exception.php
      • Function.php
      • Server.php
      • Services_JSON.php
    • /license.txt
    • Release Note.txt


For Proxy and Server, the class name is according to the file structure. Example Jsrs_Proxy_Client_Abstract (class name) is placed under /Proxy/Client/Abstract.php.

Note: Where the x.y is the version number. x is the major version while the y is the minor version number.

 

c. Starting the server

Alright, it's time to make the server alive! Launch your command-line interface. Depending on which platform you using, the steps are almost the same:

Windows

  • Change directory to your extracted archive, eg:
    >cd C:\jsrs-1.0\Server\
  • Execute the server using php executable file; php.exe
    >C:\php\php.exe -q Server.php
  • Note: The example given above assumes that your php executable file are located in C:\php, it could be somewhere else.
  • If the server is running, you should see a message like this:
    2010-07-26 16:45:32 JavaScript Remote Socket is Running!
  • Note: DO NOT close the windows as the server is running.
  • You can also create a batch file to start the server. This will save your time to typing the same command line each time you starting the server.
Linux
  • Change directory to your extracted archive, eg:
    $ cd /home/user/downloads/jsrs-1.0/Server
  • Execute the server using php command; php
    $ php -q Server.php
  • If the server is running, you should see a message like this:
    2010-07-26 16:45:32 JavaScript Remote Socket is Running!
  • If you would like to run the server without typing it, edit the server.php by adding the following line in the header of the file:
    #!/usr/bin/php -q
    <?php ...
  • Make the server.php executable (chmod 755) and rename it as jsrs_server then run it:
    $ ./jsrs_server

Note: For demo purposes, we want the server screen to be shown all the time so that we know what is happening. For production, please refer to the documentation on how to configure a production server.

 

d. Testing the connection

In order to test your server whether is it working or not, copy or move the “/Proxy” folder to your web directory. Eg: C:\Inetpub\wwwroot\ (windows) or /var/www/html/ (linux).

It is depending on how you setting up your application. As long the proxy file are accessible within the domain (not cross domain, eg: www.domain1.com accessing proxy on www.domain2.com).
Copy the “jsrs.js” to your web drive too.  You may want to put it under your Javascript folder. The last item is the “index.html” under “/Javascript” folder. Place it under the same directory with your JavaScript file.
Now your directory will look like this:
  • /your-web-drive
    • /Proxy
    • /Javascript
      • jsrs.js
      • index.html
    • <all your web drive’s files and folders>


Once you’ve placed all the files accordingly, go to the URL that point to your webdrive’s root directory:
http://localhost/ your-web-drive/Javascript/index.html

 

You should see a form with buttons and textbox. With your server running, click on “Connect” button. You should see the message “Connected to server with the ID: <session ID>”. Congratulation, your socket server is working!

 

To have fun with the demo, open up another browser (must be different browser), go to the same URL, and click Connect.
The moment you clicked “Connect”, you will see the client’s ID appear on the right text list. The ID is the client that connected to the server. Select the client’s ID and click on the remote function at the bottom of the textbox.

Note: Where the x.y is the version number. x is the major version while the y is the minor version number.
Published in Version 1.0
Sunday, 25 July 2010 19:57

II. Requirements

The requirements are pretty much similar to a web server. Just need some extra configuration on the existing server and some privileges on the server.

  1. Any web server running PHP module. Eg: Apache or IIS.
  2. PHP 5 and above with socket enabled. Please refer to PHP Socket Manual.
  3. Privileges to execute command line in the server.
  4. At least 2 modern web browsers. (Firefox 3.0 and above, Internet Explorer 7 and above)

For the programming part, you must be able to understand basic JavaScript code and a very little knowledge of PHP code which allowed you to control the user’s permission.

 

It was tested on Windows XP Professional SP3, Apache 2.2. (with PHP5.2), Firefox 3.5, Internet Explorer 8, Google Chrome 5.0.

Published in Version 1.0
Sunday, 25 July 2010 19:31

I. Introduction

JsRS is a light-weight scripting library framework that allowed you to build a live web application easily. You don’t have to create any database table for this framework. All you need to do is define what functions you wished to be call remotely and define the permission in the proxy file, and your application is ready to go!

 

JsRS was built up in three parts, the Server, Proxy and the JavaScript. The server is like a message router that route the message from one client to another. All the message that transmitting between these parts is in JSON format.

Ordinary Live Application.JsRS Live Applications.

 

The diagram on the left shows most of the live web-based application which the client will send a request to the server (HTTP Server) through the XHR transport (Ajax) and wait for response. The request is actually a database query request. The requested page (.php, .jsp, .aspx or any server-side pages) will query the database to see if there is any new message for this client. The message will then return back to the client (JavaScript) and the client will do dispatching job. Whenever a client sending a message to another client, the message will be stored into the database and wait for the recipient to query and dispatch the message.

 

While the diagram on the right is how JsRS works. The client will send a HTTP request to the server page which is the proxy. The proxy is a middleman between the client and the server. It will send the requested message to the server using specific port number (default is 38380). The HTTP request will be hold (wait) by the proxy until there is a new message coming from the server to this client. Once the proxy got a new message from the server, it will send it back to the client immediately.

 

JsRS is a framework that allowed you to call JavaScript function remotely (browser to browser) and hence, it is necessary to manage the permission of each types of client. In other words, you need to control which JavaScript function can and cannot be called by the client based on their permission (types of client).

 

The JsRS proxy is used to control the user’s permission. The proxy is a PHP file that resides within your application and thus, it can access the user’s session data. With the session data, the proxy file is able to determine the type of user and determine the permission for each operation (JavaScript’s functions). All you have to do is define the permission for each types of user. Please refer to the documentation on how to define the permission in the proxy file.

 

Calling the JavaScript remote function is very simple. Simply specify the recipient’s ID (client’s ID) and the function name you wished to call:

socket.callCF([12], "sendInstantMessage", ["Hi, my name is Kent."]);

The client’s ID is the ID that the client used to connect to the server. By default, the session ID will be used as the client’s ID.

 

You have to define the function “sendInstantMessage” in the JavaScript so that the clients are able to handle this request. Once there is a client sending a remote call to this function, the function will be invoke and a message will appear, “Hi, my name is Kent.”. These remote functions are called the Common Functions or CF in short.

 

You can’t call the Common Functions if there are not existed in the client’s page (HTML page). You have to define the same functions (JavaScript functions) for all the pages so that they can call the functions that are common to each other.

 

Security might come into your concern when calling remote function. The Common Functions will store in a different context and is not stored in the global context. Meaning you don’t have to worry that other client are able to call the functions which is not part of the remote functions. For instance you have a function called “logout” which will destroy the user’s session and send the user back to the login page. Obviously you won’t put this as a remote function and causing the client being remote logout. Because the logout function was not defined in the remote function’s context, so this function will not be able to call remotely and your application is safe.

 

For more information, please read on the documentation.
Published in Version 1.0