# Simple TCP Server
This is ~~a project of my Computer Internet course~~ a project inspired by my school homework.
Several days before I'm asked to write a project on TCP server-client communication, and I wondered why not build a simple chat service beyond that which would be much more fun?
Therefore here it is, a simple tcp server with several functions which makes it acts like a small chat app.
## Functions
- User register / login / logout
- Remember login state for device (simple token approach though)
- Send messages via users
- Search users and add contacts (and accept them of course)
- Message sync via different devices
- Send message to offline server (a SMTP-like approach)
- File handling (transfer to and fetch from server)
## Notice
- To support multilanguage, use `base64Encode(utf8.encode(yourMessageHere))` before wrapping client messages in json object and sending that to the server (the serve will crash!)
- Always open a new TCP connection to fetch or send file
## Compile and Deploy
To clone and run this project in command prompt, do the following under Windows environment with dart SDK configured.
```bash
git clone https://github.com/Linloir/Simple-TCP-Server.git
cd Simple-TCP-Server
# [+] In case you want to build an exe
# mkdir build
# dart compile exe ./bin/tcp_server.dart -o ./build/tcp_server.exe
# cd build
# tcp_server.exe [listen port]
dart run
```
## Application Layer Protocol
Since I was not allowed to base my homework on an existing HTTP protocol, I create my private protocol for this project.
To communicate with the server, your data should conform the following formats:
### Overall Request / Response Structure
Every request sent by any client to this server should and should only consist four regions:
- Request length region (4 bytes)
- Payload length region (4 bytes)
- Request JSON (variable length)
- Payload byte stream (variable length)
Each section should interconnect with each other with no byte insets.
### Request JSON Region
The request JSON region is self-explanatory, which contains a encoded JSON string describing the request from the client.
#### Fields of Request JSON
To get use of the JSON object, all you need is the table below describing the supported fields in a JSON object and the possible combinations between them:
| Field | Content | Meaning |
|:-----:|:-------:|:-------:|
| `request` |
- `STATE`: Check for the current login state *(also used to fetch a token for first used device)*
- `REGISTER`: Register new user
- `LOGIN`: Login via username and password
- `LOGOUT`: Logout current device
- `SENDMSG`: Send message to user
- `FETCHMSG`: Fetch messages sent to or from the logged user that haven't been fetched by current device
- `SEARCHUSR`: Search user info via username
- `ADDCONTACT`: Add contact via userid
- `FETCHCONTACT`: Get the contact *(Including both dual-sided and single-sided contacts)*
- `FETCHFILE`: Fetch the attached file of a message
| The type of the request |
| `body` | *JSON object* | The information needed for the request |
| `tokenid` | *number \| null* | The identifier of a device |
#### Body of Request JSON
The body field of the JSON object is the key part of a request; it contains the key information the server needs to perform the request command.
There are mainly four different types of a body:
The **UserInfo** body is used to describe the information of an arbitrary user:
- `userid`: The user ID
- `username`: The username
- `avatar`: The base64 encoded form of the user's avatar
The **UserIdentity** body is used as a credential of a specific user:
- `username`: The username
- `passwd`: The password of the user
- `newPasswd`: The modified password *(Should only exists if a user is trying to modify his/hers password)*
The **Message** body is used to describe a message:
- `userid`: The user ID of the sender
- `targetid`: The user ID of the reciever
- `contenttype`: The type of content attached to the message, should only contain values among `plaintext`, `image` and `file`
- `content`: The base64encoded utf8encoded string of the original message *(Should contain filename if the content type is 'file')*
- `md5encoded`: The calculated md5 value of the encoded content string
- `filemd5`: The attached file's md5 value *(Calculated at client side before sending the request; should only exist if the content type is 'file')*
The **MessageIdentifier** is the identifier for a client to fetch a file for a message, it contains only the necessary part to identify a message:
- `msgmd5`: The md5 of the message
The **UserName** or **UserID** is self-explanatory, which contains only the username of a user in order to search the full info of the user:
- `username`: The provided username **Or** `userid`: The provided user ID
The usage of different body parts for different request types is described below:
| Request Type | Body Part Contents |
|:------------:|:------------------:|
|`STATE`| *NONE* |
|`REGISTER`| **UserIdentity** |
|`LOGIN`| **UserIdentity** |
|`LOGOUT`| *NONE* |
|`SENDMSG`| **Message** |
|`FETCHMSG`| *NONE* |
|`FETCHFILE`| **MessageIdentifier** |
|`SEARCHUSR`| **UserName** |
|`ADDCONTACT`| **UserID** |
|`FETCHCONTACT`| *NONE* |
### Response JSON Region
#### Fields of Response JSON
The fields of a response JSON is similar to that of a request JSON, excludes for the `tokenid` field.
The response JSON also offers extra fields to describe the state of a performed command:
| Field | Content | Meaning |
|:-----:|:-------:|:-------:|
|`status`|- `OK`: The request completes with no err
- `ERR`: The request completes with at least one err
| The completion status of the request |
|`info`| *String \| null* | Description of error *(Only exists if the status is 'ERR')* |
#### Body of Response JSON
The body of a response JSON object contains all possible types of a request JSON object, with the addition of two special types below.
The **TokenInfo** body is self-explanatory, which carries the info of a token. This kind of response body only appears in an extra response preceding the original responsse of the first request from a new client device, which offers the client device a token number:
- `tokenid`: The allocated token ID
The **MessageList** body is also self-explanatory, which is a list of **Message** objects, this kind of response body exists in a `FETCHMSG` response:
- `messages`: A list of **Message** objects