Skip to content

Commit

Permalink
Merge pull request #12 from exodus4d/develop
Browse files Browse the repository at this point in the history
v1.2.0
  • Loading branch information
exodus4d authored May 10, 2019
2 parents 7f3009f + f78b177 commit 96d0037
Show file tree
Hide file tree
Showing 6 changed files with 718 additions and 69 deletions.
111 changes: 87 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,100 @@
### [WIP] WebSocket server for [Pathfinder](https://github.com/exodus4d/pathfinder)
## WebSocket server for [Pathfinder](https://github.com/exodus4d/pathfinder)

####Requirements:
1. A working instance of *[Pathfinder](https://github.com/exodus4d/pathfinder)* **(>= v1.2.0)**.
2. A working installation of *[ØMQ](http://zeromq.org/area:download)* **(>= v4.2.0)**.
Which is a "network library" written in C (very fast) that handles TCP based socket connections
between your existing _Pathfinder_ installation and this WebSocket server extension. [download *ØMQ*](http://zeromq.org/area:download).
3. A new [PHP extension for *ØMQ*](http://zeromq.org/bindings:php) that handles the communication between this WebSocket server and *ØMQ*. **(>= v1.1.3)**
### Requirements
- A working instance of *[Pathfinder](https://github.com/exodus4d/pathfinder)* **(≥ v1.2.0)**
- [_Composer_](https://getcomposer.org/download/) to install packages for the WebSocket server

####Install:
Make sure you meet the requirements before continue with the installation.

1. Install [Composer](https://getcomposer.org/download/)
### Install
1. Checkout this project in a **new** folder (NOT the install for _Pathfinder_ itself) e.g. `/var/www/websocket.pathfinder`
1. Install [_Composer_](https://getcomposer.org/download/)
2. Install Composer dependencies from `composer.json` file:
- `$ composer install` OR
- `$ php composer.phar install` (change composer.phar path to your Composer directory)
3. Start WebSocket server `php cmd.php`
- `$ cd /var/www/websocket.pathfinder`
- `$ composer install`
3. Start WebSocket server `$ php cmd.php`

### Configuration

#### Default

####Default Configuration
**Clients (WebBrowser) listen for connections**
- Host:`0.0.0.0.` (=> any client can connect)
- Port:`8020`
- URI:`127.0.0.1:8020` (Your WebServer (e.g. Nginx) should pass all WebSocket connections to this source)
- Host: `0.0.0.0.` (=> any client can connect)
- Port: `8020`
- URI: `127.0.0.1:8020` (Your WebServer (e.g. Nginx) should pass all WebSocket connections to this source)

**TCP Socket connection (Internal use fore WebServer <=> WebSocket communication)**
- Host:`127.0.0.1` (=> Assumed WebServer and WebSocket Server running on the same machine)
- Port:`5555`
**TCP TcpSocket connection (Internal use for WebServer WebSocket communication)**
- Host: `127.0.0.1` (=> Assumed WebServer and WebSocket Server running on the same machine)
- Port: `5555`
- URI: `tcp://127.0.0.1:5555`

#### Custom [Optional]

**[Optional]**
The default configuration should be fine for most installations.
You can change/overwrite the default **Host** and **Port** configuration by adding additional CLI parameters when starting the WebSocket server:

`php cmd.php --pf_listen_host [CLIENTS_HOST] --pf_listen_port [CLIENTS_PORT] --pf_host [TCP_HOST] --pf_port [TCP_PORT]`
`$ php cmd.php --pf_listen_host [CLIENTS_HOST] --pf_listen_port [CLIENTS_PORT] --pf_host [TCP_HOST] --pf_port [TCP_PORT]`

### Unix Service (systemd)

#### New Service
It is recommended to wrap the `cmd.php` script in a Unix service, that over control the WebSocket server.
This creates a systemd service on CentOS7:
1. `$ cd /etc/systemd/system`
2. `$ vi websocket.pathfinder.service`
3. Copy script and adjust `ExecStart` and `WorkingDirectory` values:

```
[Unit]
Description = WebSocket server (Pathfinder) [LIVE] environment
After = multi-user.target
[Service]
Type = idle
ExecStart = /usr/bin/php /var/www/websocket.pathfinder/pathfinder_websocket/cmd.php
WorkingDirectory = /var/www/websocket.pathfinder/pathfinder_websocket
TimeoutStopSec = 0
Restart = always
LimitNOFILE = 10000
Nice = 10
[Install]
WantedBy = multi-user.target
```

Now you can use the service to start/stop/restart your WebSocket server
- `$ systemctl start websocket.pathfinder.service`
- `$ systemctl restart websocket.pathfinder.service`
- `$ systemctl stop websocket.pathfinder.service`

#### Auto-Restart the Service
You can automatically restart your service (e.g. on _EVE-Online_ downtime). Create a new "timer" for the automatic restart.
1. `$ cd /etc/systemd/system` (same dir as before)
2. `$ vi restart.websocket.pathfinder.timer`
3. Copy script:

```
[Unit]
Description = Restart timer (EVE downtime) for WebSocket server [LIVE]
[Timer]
OnCalendar = *-*-* 12:01:00
Persistent = true
[Install]
WantedBy = timer.target
```
Now we need a new "restart service" for the timer:
1. `$ cd /etc/systemd/system` (same dir as before)
2. `$ vi restart.websocket.pathfinder.service`
3. Copy script:

```
[Unit]
Description = Restart (periodically) WebSocket server [LIVE]
[Service]
Type = oneshot
ExecStart = /usr/bin/systemctl try-restart websocket.pathfinder.service
```

####Info:
### Info
- [*Ratchet*](http://socketo.me/) - "WebSockets for PHP"
42 changes: 25 additions & 17 deletions app/Main/MapUpdate.php
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,14 @@ private function getCharacterIdsByConnection(ConnectionInterface $conn){
* @return array
*/
private function getCharacterIdsByMapId(int $mapId) : array {
return array_keys((array)$this->subscriptions[$mapId]);
$characterIds = [];
if(
array_key_exists($mapId, $this->subscriptions) &&
is_array($this->subscriptions[$mapId])
){
$characterIds = array_keys($this->subscriptions[$mapId]);
}
return $characterIds;
}

/**
Expand Down Expand Up @@ -485,43 +492,44 @@ private function broadcastData($connections, string $task, $load, array $charact
/**
* receive data from TCP socket (main App)
* -> send response back
* @param $data
* @param string $task
* @param null $load
* @return bool|float|int|null
*/
public function receiveData($data){
$data = (array)json_decode($data, true);
$load = $data['load'];
$task = $data['task'];
$response = false;
public function receiveData(string $task, $load = null){
$responseLoad = null;

switch($task){
case 'healthCheck':
$this->healthCheckToken = (float)$load;
$responseLoad = $this->healthCheckToken;
break;
case 'characterUpdate':
$response = $this->updateCharacterData($load);
$this->updateCharacterData($load);
$mapIds = $this->getMapIdsByCharacterId((int)$load['id']);
$this->broadcastMapSubscriptions('mapSubscriptions', $mapIds);
break;
case 'characterLogout':
$response = $this->unSubscribeCharacterIds($load);
$responseLoad = $this->unSubscribeCharacterIds($load);
break;
case 'mapConnectionAccess':
$response = $this->setConnectionAccess($load);
$responseLoad = $this->setConnectionAccess($load);
break;
case 'mapAccess':
$response = $this->setAccess($task, $load);
$responseLoad = $this->setAccess($task, $load);
break;
case 'mapUpdate':
$response = $this->broadcastMapUpdate($task, $load);
$responseLoad = $this->broadcastMapUpdate($task, $load);
break;
case 'mapDeleted':
$response = $this->deleteMapId($task, $load);
break;
case 'healthCheck':
$this->healthCheckToken = (float)$load;
$response = 'OK';
$responseLoad = $this->deleteMapId($task, $load);
break;
case 'logData':
$this->handleLogData((array)$load['meta'], (array)$load['log']);
break;
}

return $responseLoad;
}

private function setCharacterData(array $characterData){
Expand Down
Loading

0 comments on commit 96d0037

Please sign in to comment.