# Dispatcher Analysis

Dispatcher is like a proxy gateway service that provides communication between
emulator and IDE. In this scenario emulator is client, IDE is server. 

All connections are using secure web sockets for each independent service. 
Currently 4 sockets are present: Control, File, Debug and UI.

## 1) Control

Used to send commands and status messages and response. List of delta calculation
is provided.

Connection will present until user performs **Clear** operation from emulator.
This is applicable other services as well.

## 2) File

Used to transmit files from IDE to emulator. Emulator tells which files to get,
then this service prepares files to be downloaded.

After **getFiles** is received, dispatcher knows which files to send. Before
creating zip file **resetTimeout** message is sent to device with interval as
explained in detail below.

After preparing zip, emulator is informed about the zip size by sending 
**fileSize** message. Then actual zip file is streamed over *FILE socket*.

Then dispatcher stops sending **resetTimeout** messages.

### Creating zip

Zip creation is performed on memory for performance. No compression is performed
on zip which decreases memory usage dramatically for other processes.

Emulator processes file paths with a URI scheme. (For example 
*script://[PATH_OF_SCRIPT]*) So a descriptor file is needed for storing a map of
actual file path and URI.

Because of that zip includes a descriptor file other than actual files to send.

### Delta Calculation

This operation is performed to not to download any unchanged files.

Delta calculation occurs on emulator side. IDE is generating full index. Emulator
receives new index when it is going to update existing files. Emulator may or may
not have an old index.

If old index is not present, emulator is going to full download without going over
the delta calculation. 

If old index is present, then emulator goes over by comparing two index values.
For the same item with different value, emulator is going to download latest version
of the same file. Emulator does not perform hash or validation, just scans the
index. As the files downloaded from IDE to emulator are not subject to be changed
by emulator programmatically. IDE will not be aware any file changed on emulator. 
User made changes are subject to their problem.

Index data is stored as a single file. Which is called index file. Format of 
this data is JSON.

## 3) Debug

Used to communicate with corresponding **debugger proxy** on IDE. If this 
connection is not established, the running project is not being debugged.

## 4) UI

Provides communication between IDE UI and dispatcher itself. By IDE UI we mean
dispatcher plugin running on browser.

Log messages such as **console.log** are transmitted to dispatcher plugin using
this service.

When user wants to stop current debugging session from IDE UI, related request
is sent to dispatcher using this service.

## Commands

### getIndex

----

**getIndex** is received from emulator from *CONTROL* socket and is used to get 
information about device. 

When this message is received, index is calculated with CRC's of each file.
Then this information is sent with **getFiles** command which is explained below.

```javascript
{
   "command": "getIndex",
   "data": {
      "brandModel": "<string>",
      "brandName": "<string>",
      "deviceID": "<string: Random GUID generated by emulator once>",
      "deviceName": "<string>",
      "os": "<string: name of the OS: iOS | Android>",
      "osVersion": "<number: Full version of the OS>",
      "resourceFolderOrder": [],
      "screen": {
         "pt": {
            "height": "<number>",
            "width": "<number>"
         },
         "px": {
            "height": "<number>",
            "width": "<number>"
         }
      },
      "screenDPI": "<number>",
      "smartfaceVersion": "<number: Full version of emulator>",
   },
   "id": "<string: Random GUID generated by emulator once>",
}
```

Update mechanism and storing index information is explained at 
**Delta Calculation** section.

*resourceFolderOrder:*
Android only data, iOS does not transmit this field. In a string array Android 
transmits which resource folders are used in order. Density names includes 
drawable prefixes too.

### getFiles

----

**getFiles** is used to send device **project.json** information including each
file with CRC's calculated by dispatcher. This message is sent from *CONTROL* 
socket. Like below:

```javascript
{
   "id": "<string: Random GUID>",
   "command": "getFiles",
   "data": {
      "api": {},
      "build": {},
      "config": {},
      "files": [],
      "info": {},
      "projectID": "<string>",
      "workspace": {}
   }
}
```

In given example message, each field except for *deviceID* and *files*; denotes
fields from **project.json**.

When emulator receives **getFiles** command it decides which files to retrieve
from dispatcher (**Delta Calculation** section). Then a message like below is
sent to dispatcher (*FILE* socket) as a response:

```javascript
{
   "command": "getFiles",
   "data": {
      "files": []
   },
   "id": "<string: Random GUID>"
}
```

Not all files, but only the ones necessary is retrieved. Which files to be
retrieved is under files array.

### keepAlive

----

```javascript
{
	"command": "keepAlive",
	"service": "<string: Service>"
}
```

For *each socket* connected to dispatcher, **keepAlive** command is sent with 
predefined interval (15 secs).

### resetTimeout

----

When device is connected to dispatcher, if no message is sent for a minute (which
is defined by emulator) connection is considered to be timed out. Which causes
unwanted timeouts to occur when number of files to be sent is too much for 
instance.

In order to solve this, **resetTimeout** is implemented.

**resetTimeout** is sent from dispatcher to device from *CONTROL socket* with an
interval (currently 10 secs), when an operation may take too much time than 
expected. This prevents unwanted timeouts.

When emulator receives **resetTimeout**, countdown and timeout value resets itself.
So emulator keeps waiting for dispatcher to complete an operation.

Currently this command is sent to emulator in following cases:
   - Before calculating index
   - Before preparing zip file to be sent

Note that when this message is sent with an interval before a heavy operation,
dispatcher must stop sending this message after related operation is complete
to prevent sending unnecessary messages to device.

### fileSize

----

```javascript
{
	"id": "<string: Random GUID>",
	"command": "fileSize",
	"data": {
		"size": "<number>"
	}
}
```

This command is sent to emulator right before sending the file itself.

*size* denotes the size of the zip file in terms of bytes.

### start project

----

Received from emulator from *CONTROL* socket, used to start a new debugging 
session.

### stop project

----

Received from emulator from *CONTROL* socket, used to finalize current debugging 
session.

### stopDebug

----

```javascript
{
	"command": "stopDebug"
}
```

Received from IDE UI when user presses stop debug button from debugger panel.
When this is received, **stop** command is sent to emulator which finalizes
debugging process & kills emulator.

Then **stop project** is received from emulator.

### cancelTransfer

----

Project checker module runs within CLI right before **getIndex** message is
retrieved.

When project checker returns with some errors, transfering files to device must
be blocked. In order to inform user, **cancelTransfer** message is sent to
device over *CONTROL socket* which means a message will be shown on device screen 
indicating that there are errors must be solved on current workspace.

Note that dispatcher can send **cancelTransfer** message with any custom message
to be shown on emulator. This message is also used with the development of
*IDE Connection Checker*.

### showErrors

----

Works just like *cancelTransfer* message.

This message is sent to IDE UI over *UI socket* to inform user from IDE side
that there are errors.

Errors to be shown are informative enough for user to solve the problems and
continue to work.

### - Image Serving

When a component with an image source is used with UI-Editor, related image must 
be rendered correctly. Scaling & rendering image by device information and serving 
correct image is also performed by dispatcher.

Whan a request is made to dispatcher, that request url includes information
about image and device.

Sample request url:
[DISPATCHER_URL]/ui-editor/img/Icon.png?os=iOS&osVersion=10.2&density=326&densityRatio=0.5&zoomLevel=0.37&brandModel=iPhone%207?random=0.40965630020468335

### - IDE Connection Checker

This development is performed due to the requirements specified by Apple AppStore.

Updating emulator should not work when IDE is no longer active. This is achieved
by storing active project id's inside dispatcher. When UI socket connection is
lost, it means connection is lost and updating emulator should not work.

In this case user is informed with **cancelTransfer** message with following
message:

*For security reasons, you cannot update the app while the IDE is closed. To update 
the app, please start a new session by launching the Cloud IDE and rescanning the 
new QR code.*

This prevents emulator to be updated.

## NOTES

- **All** messages are sent to device by 10000B chunks. Which aims the stability
of debugger in the first place. Because messages might be too big for v8 to 
handle. Please refer *src/common/SendChunkedMessage.js* for more information.

## SEQUENCE DIAGRAM

![SEQUENCE DIAGRAM](https://bytebucket.org/smartface-team/ide-dispatcher/raw/e5588ef206bf6f4f0c85b8b909ecd65ea681e128/analysis/dispatcher-sequence-diagram.png?token=51d684fbf89a9d84a4dd0239421059ca6f13ce0f)

## CONNECTIONS

![CONNECTIONS](https://bytebucket.org/smartface-team/ide-dispatcher/raw/526bed98bca0c8bc0957b3648890c701d7d08b37/analysis/connections.png?token=f876fda29572d4afe626e3b24de3d260db0ea658)
