Client-Server Protocol.md 10 KB

Client-Server Protocol

Protocol version: "0.3"

Every json message must be minimized (i.e. must not contain newlines) and be followed by a newline. This rule makes receiving and parsing the messages easier because you can read until a newline comes and you will parse every json message seperately because you won't read multiple json messages from the buffer at a time.

1. Start a connection

To start a connection you have to check the versions and verify the login or signup. Only if step 1.1 and 1.2 have been accomplished a usable connection is negotiated. You can close the connection by sending a cancel message.

1.1 Version check

Client:

{
	"major": int,
	"minor": int
}

(For example, if the version number is 42.1, then major is 42, minor is 1.)

Server:

{
	"major": int,
	"minor": int,
	"accept": bool
}

If accept is true the connection is valid. Else the connection will be terminated after the server answered.

1.2 Login / Signup

The client is supposed to always send every field used for the login requests: login, user, pass and cancel. The server is supposed to always send every field used for the login answer: accept and error.

1.2.1 Login

Client:

{
	"login": true,
	"user": string,
	"pass": string,
	"cancel": false
}

Server:

{
	"accept": bool,
	"error": string
}

If accept is true the connection is valid and the user is logged in. Else error has an error string and the connection will be terminated after the server answered.

1.2.2 Signup

Client:

{
	"login": false,
	"user": string,
	"pass": string,
	"cancel": false
}

Server:

{
	"accept": bool,
	"error": string
}

If accept is true the connection is valid and the user is logged in and signed up. Else error has an error string and the connection will be terminated after the server answered.

1.2.3 Cancel login

Client:

{
	"login": bool,
	"user": string,
	"pass": string,
	"cancel": true
}

After the cancel message was sent the connection will be closed.

2. Sending commands

Commands can be sent by the client after a connection has been negotiated (See 1). Commands can be used unrelated to each other.

2.1 Status command

Client:

{
	"command": "status"
}

Server:

{
	"command": "status",
	"response": string
}

2.2 List command

List is split in two commands. list to request a list download and listdata to download the list.

2.2.1 list - request file list download

Client:

{
	"command": "list"
}

Server:

{
	"command": "list",
	"accept": bool,
	"items": int,
	"chunks": int,
	"error": string
}

chunks is the number of chunks that will be sent.

2.2.2 listdata - download file list

Client:

{
	"command": "listdata",
	"chunk": int,
	"cancel": bool
}

Here chunk is the number of remaining chunks. (Thus, when requesting the first chunk the number of chunks - 1 is expected.)

Server:

{
	"command": "listdata",
	"remaining": int,
	"cancel": bool,
	"names": string[],
	"error": string
}

The client has to request every chunk until all names have been sent and remaining hits 0.

2.3 Put command

Put is split in two commands. put to request a file upload and putdata to upload the data.

2.3.1 put - request upload

Client:

{
	"command": "put",
	"file": string,
	"size": int,
	"chunks": int
}

chunks is the number of chunks of the file to send.

Server:

{
	"command": "put",
	"file": string,
	"accept": bool,
	"error": string
}

If accept is true the connection is valid and the client can start sending the file. Else the put request was rejected and is hereby canceled. error should contain an error string if the request was rejected.

2.3.2 putdata - upload data

Client:

{
	"command": "putdata",
	"file": string,
	"data": string,
	"remaining": int,
	"cancel": bool
}

data is a base64 string and contains a piece of the file. The client will loop this until the file is completely sent and the server has to send and received message for every chunk. remaining is a counter how many chunks will follow and the transfer is over after it hits 0. If cancel is true the file transfer will be canceled.

Server:

{
	"command": "putdata",
	"file": string,
	"recieved": int,
	"cancel": bool,
	"error": string
}

If cancel is true then the upload of the file is canceled and an error message should be in error.
Note that received is the number of remaining (!!!) chunks, here the server responds with the remaining value originally sent in the request.

2.4 Get command

Get is split in two commands. get to request a file download and getdata to download the data.

2.4.1 get - request download

Client:

{
	"command": "get",
	"file": string
}

Server:

{
	"command": "get",
	"file": string,
	"accept": bool,
	"chunks": int,
	"error": string
}

If accept is true the connection is valid and the server can start sending the file. Else the get request was rejected and is hereby canceled. error should contain an error string if the request was rejected. chunks is the number of chunks of the file.

2.4.2 getdata - download data

Client:

{
	"command": "getdata",
	"file": string,
	"chunk": int,
	"cancel": bool
}

Here chunk is a counter how many chunks will follow. (Thus, when requesting the first chunk, the number of chunks - 1 is expected.) If cancel is true then cancel the download of the file.

Server:

{
	"command": "getdata",
	"file": string,
	"data": string,
	"remaining": int,
	"cancel": bool,
	"error": string
}

data is a base64 string and contains a piece of the file. The client must request every chunk. remaining is a counter how many chunks will follow (so it equals the chunk value originally sent in the request) and the transfer is over after it hits 0. If cancel is true then the download of the file is canceled and an error message should be in error.

2.5 Head command

The head command requests the first 32 bytes of file from the server for further inspection by the client. If the file is smaller than 32 bytes, the first 4 bytes are sent instead. If the file is even too small for this, data stays empty, and an error is sent.

Client:

{
	"command": "head",
	"file": string
}

Server:

{
	"command": "head",
	"accept": bool,
	"file": string,
	"data": string,
	"error": string
}

data is a base64 encoded string containing the requested bytes of the file.

2.6 Deleteme command

The deleteme command allows a logged in user to delete their account on the server. This action needs to be confirmed with the users password.

Client:

{
	"command": "deleteme",
	"pass": string
}

Server:

{
	"command": "deleteme",
	"accept": bool,
	"error": string
}

If accept is true the user has been deleted and the connection will be closed by the server.

2.7 Deletefile

The deletefile command deletes a file from the server if its allowed to in config.

Client:

{
	"command": "deletefile",
	"file": string
}

Server:

{
	"command": "deletefile",
	"file": string,
	"accept": bool,
	"error": string
}

2.8 Notifications

The notifications command allows the logged in user to get a list of notifications since the last time.

Client:

{
	"command": "notifications"
}

Server:

{
	"command": "notifications",
	"accept": bool,
	"messages": string[], 
	"error": string
}

2.9 ExtendedStatus

The extendedstatus command allows the client to request detailed information about ongoing transfers at the server.

Client:

{
	"command": "extendedstatus"
}

Server:

{
    "command": "extendedstatus",
    "accept": bool,
    "error": string,
    "transfersclientserver": {
        "upload": bool,
        "file": string,
        "progress": int
    }[],
    "transfersserverserver": {
        "type": string,
        "file": string,
        "progress": int,
        "speed": float,
        "method": string
    }[]
}

The answer consists of an array of objects, each representing a transfer.
In case of client-server transfers, upload indicates wether the transfer is an up- or download. In case of server-server transfers, type indicates wether the file is uploading, downloading or queued for upload.
file contains the name of the file being transferred.
progress contains the percentage completed.
speed contains the speed in bytes per second.
method contains the covert channel method being used.

2.10 Queue command

To add a file that is already on the server to the queue for sending with the covert channel, the client uses the queue command.

Client:

{
	"command": "queue",
	"file": string
}

Server:

{
	"command": "queue",
	"file": string,
	"accept": bool,
	"error": string
}

2.11 Dequeue command

To remove a file from the queue for sending with the covert channel, the client uses the dequeue command.

Client:

{
	"command": "dequeue",
	"file": string
}

Server:

{
	"command": "dequeue",
	"file": string,
	"accept": bool,
	"error": string
}

2.12 Extendedlist command

Extendedlist is split in two commands. extendedlist to request a list download and extendedlistdata to download the list.

2.12.1 extendedlist - request file list download

Client:

{
	"command": "extendedlist"
}

Server:

{
	"command": "extendedlist",
	"accept": bool,
	"items": int,
	"chunks": int,
	"error": string
}

chunks is the number of chunks that will be sent.

2.12.2 extendedlistdata - download file list

Client:

{
	"command": "extendedlistdata",
	"chunk": int,
	"cancel": bool
}

Here chunk is the number of remaining chunks. (Thus, when requesting the first chunk the number of chunks - 1 is expected.)

Server:

{
	"command": "extendedlistdata",
	"remaining": int,
	"cancel": bool,
	"files": {
        "name": string,
        "head": string,
        "size": float
    }[],
	"error": string
}

The client has to request every chunk until all names have been sent and remaining hits 0.
The list contains the name of a file and the head as specified by the data field of the head command (section 2.5), and its size in kByte.

3. Close connection

3.1 Close command

Client:

{
	"command": "close"
}

Server:

{
	"command": "close",
	"response": "bye"
}