Samsung Electronics logo

Chord Service



Chord Service API provides application developers with a simple, high-level set of APIs that can be used to build new exciting distributed applications. Each Chord node sends a UDP broadcast message about once a second and parses broadcast messages from other nodes. The UDP broadcast messages are handled on Chord internally. Using UDP broadcast messages, all Wi-Fi nodes located in the same subnet can be discovered.

“Channel” is a key concept of Chord. Channel is a logical grouping of nodes that makes communication possible. Only nodes that join to a channel can communicate within the same channel. All nodes by default, join to a public channel. Nodes can communicate through the public channel. The public channel is a communication channel for the Chord internal. Chord recommends applications not to use the public channel for communication. An application can define and use private channels for communication. A node can join several private channels at the same time.


Starting Chord

An application that intends to use Chord Service should start by launching service provider. Through this, application can connect to the Chord Service Framework. Applications can start Chord service provider by invoking startServiceProvider() of Chord. startServiceProvider() requires InterfaceType, ChordServiceStatusChangeCallback, tmpDirectory, keepAliveTime as input parameters, and it returns ChordServiceProvider object. The ChordServiceStatusChangeCallback will be invoked when the status of service provider changes.

If you want to stop service provider, you can use stopServiceProvider().

The sample codes are as follows.

var serviceProvider = null;
var interfaceType = "WIFI_DIRECT";
var downloadPath = "/sdcard/Download";
//start chord service
function onStatusChanged(status) {
    console.log("status changed: " + status);
    //stop chord service
    try {
        webapis.chord.serviceconnector.stopServiceProvider();
    }catch(e){
        console.log("stopService err: " + e.message);
    }
}
try {
    serviceProvider = webapis.chord.serviceconnector.startServiceProvider(interfaceType, 
        onStatusChanged, downloadPath, 10000);  
} catch (e) {      
    console.log("startServiceProvider error"+ e.message);
}

Managing Channels

After the state of Chord service has changed to “STARTED”, a Chord node is created, and channel control is possible. If channel related functions are called before Chord service has started, a null value will be returned.

Channel Join and Leave

When joinChannel() is called with a specific channel name and a given listener successfully, ChordChannel instance will be returned. And data/file transmission is possible on this channel until leaveChannel() is called.

/**
  * Join a channel and leave the channel.
  */
//Define callback functions for receiving notification when the status of Chord Channel changed. 
var channelStateChangedLsnr = {

    onnodejoined: function(nodeName. channelName) {
        /* Do something, when a new Chord node joined the channel. */ 
    },
    
    onnodeleft: function(nodeName. channelName) {
        /* Do something, when a Chord node left the channel.*/ 
    },
    
    ondatareceived: function(nodeName. channelName, data, dataInfo) { 
        /* Do something, when receive data from the channels that the application joined.*/ 
    },
    
    onfilewillreceive: function(nodeName. channelName, id, file) { 
        /* Do something, when get the notification on file arrival from a sender. */
    },
    
    onfilechunkreceived: function(nodeName. channelName, id, file, offset) { 
        /* Do something, when a file data chunk arrives from the sender.*/ 
    },
    
    onfilereceived: function(nodeName. channelName, id, file, tmpFilePath) {
        /* Do something, when a file transfer is completed.*/ 
    },
    
    onfilechunksent: function(nodeName. channelName, id, file, offset, chunksize) {
        /* Do something, when a fie data chunk is sent to the recipient.*/
    },
    
    onfilesent: function(nodeName. channelName, id, file) {
        /* Do something, when a file transfer is completed. */ 
    },
    
    onfiletransfererror: function(nodeName. channelName, id, file, state) { 
        /* Do something, when an error occurs during file transfer. */
    }
};

var channel = null;

//Define callback function for receiving notification when the status of Chord Service changed. 
var serviceStateChangedLsnr = function(state) {
	//Handle different state of Chord Service.
	switch(state){
		case "STARTED":
			//Join channel.
			if (serviceProvider != null){
				channel = serviceProvider.joinChannel("com.samsung.chord.CHANNEL_A", channelStateChangedLsnr);
			}
			break;
		case "STOPPED":
			 //Do something.
			break;
						 
		case "RECONNECTED":
			 //Do something.
			break;
						 
		case "DISCONNECTED":
			 //Do something.
			break;
						 
		case "FORCETOSTOP":
			 //Do something.
			break;
						 
		case "FAILTOSTART":
			 //Do something.  
			break;			 
	}
};

var serviceProvider = null;

try {
    serviceProvider = webapis.chord.serviceconnector.startServiceProvider("WIFI", serviceStateChangedLsnr, "/sdcard/Download", 9999);
} catch (error) {
    console.log(error.name);
}

After an application joined a Chord channel, it can receive event from the channel. When another application joins the channel, onnodejoined() will be invoked, and onnodeleft() will be called when an application in the channel left.

To leave the channel after joined, execute following statement:


// Leave the channel.
serviceProvider.leaveChannel("com.samsung.chord.CHANNEL_A");

Channel Retrieve

Chord node will join public channel automatically. For an application it is possible to do data/file transmission on public channel. Public channel is used by all nodes and applications on the network. It is not recommended to use public channel as an application communication channel. Applications should certainly create private channel for application specific message communication. Below is the code snippet for channel retrieving.


/**
 * Retrieve public/private channel instance(s).
 * It is assumed that you have obtained a ChordServiceProvider instance.
 * (See section 1.1.1 Channel Join and Leave)
 */
var serviceProvider = null; 

//Retrieve public channel instance.
var publicChannel = serviceProvider.getPublicChannel();

// Retrieve a specific private channel instance that application has joined.
var myChannel = serviceProvider.getJoinedChannel(“com.samsung.chord.CHANNEL_A”);

// Retrieve all private channel instances that application has joined.
var joinedChannels = serviceProvider.getJoinedChannelList();
console.log(“The application has joined “ + joinedChannels.length + “ channels.”);

An application joins Chord channel as a ChordNode instance. Through ChordChannel instance application can get local Chord node name with getLocalNodeName(), and all of Chord nodes in the channel can be retrieved with getJoinedNodeList(). Channel name can also be retrieved with getChannelName().

To leave the channel after joined, execute following statement:


/**
 * Retrieve ChordNode  instance(s).
 * It is assumed that you have obtained a ChordServiceProvider instance.
 * (See section 1.1.1 Channel Join and Leave)  
 */

var myNodeName = serviceProvider.getLocalNodeName(); 
console.log(“My node name is “ + myNodeName);


//It is assumed that you have obtained a ChordChannel instance.
// (See section 1.1.1 Channel Join and Leave)
var nodeList = channel.getJoinedNodeList(); 

var channelName = channel.getChannelName();

Data Transmission

Since a valid ChordChannel is obtained, application can send/receive data to/from other Chord node on the network. Application can send data to a specific Chord node with sendData(). Also it can send data to all Chord nodes in the channel with sendDataAll(). When application receive message from other Chord node, ondatareceived() will be called.

Below is the code snippet for data transmission.


/**
 * Send/Receive data between Chord nodes.
 */

// Send data to a specific node.
// 1. Select the target
var nodeList = channel.getJoinedNodeList(); //It is assumed that you have obtained a ChordChannel instance.(See section 1.1.1 Channel Join and Leave)

var dstNode = null;
if (nodeList.length != 0) {
	dstNode = nodeList[0];
} 

// 2.Construct the data
var message = “Hello Chord Node!”;
var messageArray = new Array(message);
// 3.Send
channel.sendData(dstNode.nodeName, messageArray, “Message”);

// Send data to all of Chord nodes in the channel.
channel.sendDataAll(messageArray, “Message”);

Transferring file

Send file

An application can send files to the nodes on the channel by invoking sendFile(). If you want to send files to multiple users on the channel, invoke sendFile() for each node.
sendFile() requires dstNodeName, filePath, fileType, timeout as input parameters, and it returns TransferID which can be used to call the cancelFile() method.

The sample codes are as follows.


var filePath = "/sdcard/Download/sampleFile.png"; 
var fileType = "FILE_TYPE_PICTURE";
var timeout = 10000;
var transfer_ID = null;
try {		
	var nodeList = channel.getJoinedNodeList(); // It is assumed that serviceProvider object has been retrieved properly.

    if(nodeList != null && nodeList.length > 0) {
    
		for (var i = 0; i < nodeList.length; i ++) {
		
		// send file to node
		transfer_ID = channel.sendFile(nodeList[i], filePath, fileType, timeout);
		console.log("Send " + filePath + " to " + nodeArray[i].nodeName);

		// cancel send
		channel .cancelFile(transfer_ID);
    	}
    }
} catch (e) {
	console.log("transferring file error" + e.message);
}

At the begin of file sending task, a notification will be sent to the recipient and caught by onfilewillreceive(). Application can accept or reject the request by invoking acceptFile() and rejectFile().
To transfer a file between Chord nodes, it will be separated into several chunks. When a chunk of the file send successfully, both the sender and recipient will get notification through onfilechunksent() and onfilechunkreceived().
After file sending task is completed, onfilesent() registered when called joinChannel() will be invoked to notify the sender and onfilereceived() will be invoked on recipient side.

Accept file

Below are two callbacks of sendFile() at the receiver.

Parameter

Format

Example

MagnetChannelStatusChangeCallback

void onfilewillreceive(in MagnetNode srcNode, in TransferID id, in TransferFile file);

Invoked when the recipient gets a notification on file arrival from a sender.

void onfilereceived(in MagnetNode srcNode, in TransferID id, in TransferFile file, in DOMString tmpFilePath);

Invoked when a file transfer is completed.

Receiver can accept to receive the file by invoking acceptFile() and reject by invoking rejectFile().
acceptFile() is synchronous function that accept to receive file. It requires transferID, timeout, retry, chunkSize as input parameters. acceptFile() can be called once when onfilewillreceive() is called.
rejectFile() is synchronous function that reject to receive file. It can be called once onfilewillreceive() notification is received.

The sample codes are as follows.


var serviceProvider; // assume that serviceProvider object has been retrieved properly.
var channelName = "COM.SAMSUNG.EDISPLAY",
var channel = null;

var channelStatusChangeCallback = {
	onfilewillreceive: function(srcNode, id, file){
		console.log("onfilewillreceive, id: " + id +", file: " + file );
		
		//accept file
		channel.acceptFile(id);
		
		//reject file
		channel.rejectFile (id);
	},
	
	onfilereceived: function(srcNode, id, file, tmpFilePath){
		console.log("onfilereceived, id: " + id +", file: " + file.fileName+", tmpFilePath: " + tmpFilePath );
	}
};
channel = serviceProvider.joinChannel(channelName,channelStatusChangeCallback);