Skip to content

Commit

Permalink
Merge pull request #42 from 1c3t3a/safe-websockets
Browse files Browse the repository at this point in the history
Add safe web-sockets and the ability to preconfigure the TLS backend
  • Loading branch information
1c3t3a authored May 13, 2021
2 parents 1209d8a + 6a2fa42 commit 9954692
Show file tree
Hide file tree
Showing 13 changed files with 539 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Build docker container
run: |
cd ci && docker build -t test_suite:latest .
docker run -d --name test_suite -p 4200:4200 -p 4201:4201 test_suite:latest
docker run -d --name test_suite -p 4200:4200 -p 4201:4201 -p 4202:4202 test_suite:latest
- name: Run cargo-tarpaulin
uses: actions-rs/tarpaulin@v0.1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Build docker container
run: |
cd ci && docker build -t test_suite:latest .
docker run -d -p 4200:4200 -p 4201:4201 test_suite:latest
docker run -d -p 4200:4200 -p 4201:4201 -p 4202:4202 test_suite:latest
- name: Run testsuite
run: cargo test --verbose
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ base64 = "0.13.0"
bytes = "1"
rand = "0.8.1"
crossbeam-utils = "0.8.1"
reqwest = { version = "0.11.0", features = ["blocking"] }
reqwest = { version = "0.11.0", features = ["blocking", "native-tls"] }
adler32 = "1.2.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
regex = "1.4.2"
byte = "0.2.4"
websocket = "0.26.2"
thiserror = "1.0"
native-tls = "0.2.7"
11 changes: 6 additions & 5 deletions ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,21 @@ There are three different pipelines:
If you'd like to trigger this manually, run `make checks` in the project root.
* Build and test: Builds the code and kicks of a docker container containing the socket.io and engine.io servers. Then the tests run against the servers. The servers code should not be changed as the clients' tests assume certain events to fire e.g. an ack gets acked or a certain namespace exists. Two servers are started:
* An engine.io server with some callbacks that send normal string data.
* A _safe_ engine.io server with some callbacks that send normal string data. Safe means the server is built upon a tls certificate which can be found in the `cert/` folder. This server is used for tests using `wss://` and `https://`.
* A socket.io server which sends string and binary data, handles acks, etc.
* Generate coverage: This action acts like the `Build and test` action, but generates a coverage report as well. Afterward the coverage report is uploaded to codecov.io.
This action also collects the docker server logs and uploads them as an artifact.

# How to run the tests locally

If you'd like to run the full test suite locally, you need to run the two server instances as well. You could do this manually by running them directly with node:
If you'd like to run the full test suite locally, you need to run the three server instances as well. You could do this manually by running them directly with node:

```
node engine-io.js / socket-io.js
node engine-io.js / socket-io.js / engine-io-secure.js
```
or if you'd like to see debug log as well:
```
DEBUG=* node engine-io.js / socket-io.js
DEBUG=* node engine-io.js / socket-io.js / engine-io-secure.jss
```

You need to have the two dependencies socket.io and engine.io installed, if this is not the case, fetch them via `npm install`.
Expand All @@ -29,12 +30,12 @@ If you don't want to run the servers locally, you could also build and run the d

```
docker build -t test_suite:latest .
docker run -d --name test_suite -p 4200:4200 -p 4201:4201 test_suite:latest
docker run -d --name test_suite -p 4200:4200 -p 4201:4201 -p 4202:4202 test_suite:latest
```
The docker container runs a shell script that starts the two servers in the background and checks if the processes are still alive.

As soon as the servers are running, you can start the test via `make pipeline`, which will execute every tests that's run in the whole pipeline.

# Polling vs. Websockets

The underlying engine.io protocol provides two mechanisms for transporting: polling and websockets. In order to test both in the pipeline, the two servers are configured differently. The socket.io test suite always upgrades to websockets as fast as possible while the engine.io suite just uses long-polling. This assures that both the websocket connection code and the long-polling code gets tested (as seen on codecov.io). Keep that in mind while expanding the tests.
The underlying engine.io protocol provides two mechanisms for transporting: polling and websockets. In order to test both in the pipeline, the two servers are configured differently. The socket.io test suite always upgrades to websockets as fast as possible while one of the engine.io suites just uses long-polling, the other one uses websockets but is reachable via `https://` and `wss://`. This assures that both the websocket connection code and the long-polling code gets tested (as seen on codecov.io). Keep that in mind while expanding the tests.
33 changes: 33 additions & 0 deletions ci/cert/ca.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIJAJKBPV3nMXjsMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTE4MTczODAwWhcNMjUxMTE1MTczODAwWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
CgKCAgEAmNWKTumE1f+ptArhPTOcaUReoqBlri/ujIzm1N8Qr0hghS6B8eXGngAS
YM7ziTlLZmLKgZg7TYOs+qK+xNNjSMbkA4Tions7vX3FYAokfh1iSiQigAw3TAwg
brUaA0phucJBjvWI2mDuwzTLhQp1wmGrliAJhXag2ZQt817m6wrsFWuwiviMIHlq
mQhC+vwd2SvW4xGf5zxjzCM8m7pOiJCLjxXwvNphiTR3tb807W00mi5cMFwhmAUT
uSiVkVERubIYEKNSW2ynxzGFfb+GF/ddUxCKsnMDfM+SpMrsTBv9BzJzXU7Hc9jP
NPFtrZiVo9aKn8csTSvKifmfiNwl2YGuWlW++1+ew6Q9rqEqvKHnKU+Cuwt3y37U
ryqrBS47cz1xxFb3fCn+a72ytcHjI9lMqIQ0+IZ0/4cf0TK80ECEQ0CyrCk0E9Qz
eMEzIALRa/pI8uTXdoAtQIlOsfALWeni+QphZ1BVjwZRmr+F1Px2/R30+gAcZHKc
D+0Bm6owvpBWDe1s0DrkwtY3fyZ+OPS5/3eQtyhy9/3vnz9WBw0BGZyN2nzs5HsB
RB5qDBRx+NQz1QYp/Ba3WeVmZURe2NMnS4uEypkWahW1XNQ+g+JJhK1p01s0+v/B
f4DodYEcsw/3fRU0AKdsAkabQ68VIJAYyfQyinpNR9sHDKZ6Dx8CAwEAAaOBpzCB
pDAdBgNVHQ4EFgQUdwTc4idMFJo0xYmoLTJQeD7A59kwdQYDVR0jBG4wbIAUdwTc
4idMFJo0xYmoLTJQeD7A59mhSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpT
b21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQCS
gT1d5zF47DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4ICAQBRLzphOdJO
ekU+iwFLGXJiLfUQi3EORaA3mBtozvyRRUyxu0FqWdGGINcyq7xaZxkQ0P+eBMDv
V3F7FvidhaVe6TR7VJB2gyaWeLd1BSOi5gGBk5kuuqV3VbusNzY+WhJip98HEK+y
XP+Lt/LXJpPwOORF9TiR6IBFQn3fBVhPjsqQRzT468QuZ5DCGQ5UW+wWl43I8OxS
PDiUmHTlwLnLqqVFgSE+VnX4vSUZD8kDf0kkxssg1r56IzneSlRBegSVXIuRCbRf
QmWaxz+D6ffM1eNiE3nQxsgJy3dPL1Lfsaidgz39yAC099pjLyVH23cfmFmT/l5b
OdhRE5D75rL8eXAiI2/voz1M+v7XznHjZEhcVUlFsBXsk3zHb2vQQZRNPLnybTb8
biFpReSIWdpno+F5IrT7z0L8JI3LU0leEFV+Rf525Q+78Rffohxd51fUj0vLKoy9
un0IEkOcaJhHTPc2dMXb2qGcV4MaUEUsERrnanGZmdNd1aD3YAG3C+nJ8gxrEGHO
veD6Xbyf1K8e7H2sqhGCm8eyHgCFGQiul6yQ41ZwjKgoSCJvOJaYUFE18k0S9k/I
rWYvYWRYbDj4GYx+6LUTfyo30KK5jl4KAil92LrGlIfWK4IjUJyPlOJkb6gXkj0l
lfbUHTmnKthFwJS0958xBq7UM7+RzyFIOg==
-----END CERTIFICATE-----
23 changes: 23 additions & 0 deletions ci/cert/server.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

-----BEGIN CERTIFICATE-----
MIIDoTCCAYkCAQEwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV
BAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0
ZDAeFw0xNTExMTgxNzM4MDhaFw0yNTExMTUxNzM4MDhaMGwxCzAJBgNVBAYTAkZJ
MRMwEQYDVQQIEwpTb21lLVN0YXRlMREwDwYDVQQHEwhIZWxzaW5raTEhMB8GA1UE
ChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRIwEAYDVQQDEwlsb2NhbGhvc3Qw
gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMBAs08Mguowi6W8+BrqiByLr3Fh
pKnnRTtO/wfDDebgP3Da5vIapHt0NbbSIYkju1M1y/9S0uqCScSIIFeSr8wOvmB1
c0jRX+P6oA6p8lJXG/HEfEuu3uK+Olkds7sHcrtuRaYLEAXNYCUTlT0VdfVvxV96
0m/5wMRpexjC5h+jAgMBAAEwDQYJKoZIhvcNAQEFBQADggIBACvxt9oSl8zDz2i9
DFtBVA87TYkv7MPqc6HKzpzKjUpay1CmTrXxaw9WKXGC47aoj/wXNqe1W/w5KUdH
79Z7n/TKpQJ9hj3NQJerFGD5EGu+rL4/FshMiwjp0/AiuAIThVa11BDzmEltwf86
mHfIhRG89m3LmJbCzOLTjqjnt3vL5fcW0KEN+5TDFxINbXC6o+ioZgMeh3n+d01D
MZImN01A0ZwKch81IDmPZD/IrtCLGwG/YfTaQUshMHUaQIKqDIyzDb/VgWGh1vET
J6Zpbvr3xc+mg34588qd6JcyND6X1LKBvLUNqcIrcAaChbabyPUCy1w+XDgcATZg
uerXcELSApivaSVGZVNkrbUskDySjZp2NhpEhDFim3HZye7CUvVIM5AI8BPeI5ZA
nYi2kcya3e9/u3YxfsCklbxCiBUMhVYT3EVHNILr0Eik4NJp92xBLyRk770WvwMc
MAiRNK5+XM0DffzHe9PrcopWRwvPsh8ce9IUsTJQjx0zALc8JKT6VN8J1cNseZR5
ALuTasgFliRFYCwUJcwCpoXUDJas7hbBDcbecMbFKDCrmUbG6moRqETtljDtn4na
cKwaAk2sp9CSaNoLAsWd45ElXpeoKtNz7dFsRf1nSu2GPdE2SdaPJ6br+bKcO6TW
LRObFtVqZM7TTrPUuVji72CfFMtl
-----END CERTIFICATE-----
15 changes: 15 additions & 0 deletions ci/cert/server.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDAQLNPDILqMIulvPga6ogci69xYaSp50U7Tv8Hww3m4D9w2uby
GqR7dDW20iGJI7tTNcv/UtLqgknEiCBXkq/MDr5gdXNI0V/j+qAOqfJSVxvxxHxL
rt7ivjpZHbO7B3K7bkWmCxAFzWAlE5U9FXX1b8VfetJv+cDEaXsYwuYfowIDAQAB
AoGBAL7tQmXl2fmz/mu5kHhCpKwcuT6TpxEo4aN132aY+qxn1flBHAwiE2mbTmDi
rHViq/2GNrK5UUed3p60RdJSlgwIkyqtcGxWhUJGYCR/hU60qeeLp3MhhOoOFbiV
YTDsoC7V/SuWbX+1qG5FxnHSnTZhAIRkZXS4uTZ5WDcQm/7BAkEA+TlZ1IT9CeU/
FpHpqc8RgR8377Ehjy8o4Z4EGFnxQlAUWASnhs6dw4isr3+c7hA1OEmqmcRClPVZ
t1JbHAPC4QJBAMV60WSJzPUccCF47T9Ao2CeWFl/9dmgQQe9idpTNuKMXNtPJN44
0MQvnb+xS828woJOoRI+/UTVLLBc4xwMtwMCQQDZTadExTw4v5l1nX5GoJUbp9PG
/ARN64nSx0u8y9evwVErucs0oL0we+BOGZAEhz9QN/M3pceESDWUwYtNbv4hAkBB
Ku2MqvjK7k6GjTxlgjQn/zkSl+qOnZa4MjEarhlPm5hM+wokl0U1aK07BAwK4b6i
d8YpmkXEAEEWFiEQMZX3AkEA1SkdiFj1u7HnzO7onLJsnFzowX3pm1UFl0azOMlM
2GkjYxWeJ/4VL7Y6QkhHE0Nj3my2+MJQI9xpYgMbw/l11w==
-----END RSA PRIVATE KEY-----
45 changes: 45 additions & 0 deletions ci/engine-io-secure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const fs = require('fs');
const https = require('https');
const eio = require('engine.io');

const serverOpts = {
key: fs.readFileSync("cert/server.key"),
cert: fs.readFileSync("cert/server.crt"),
ca: fs.readFileSync("cert/ca.crt"),
};

const http = https.createServer(serverOpts);

const server = eio.attach(http);

console.log("Started")
http.listen(4202, () => {
server.on('connection', socket => {
console.log("Connected");

socket.on('message', message => {
console.log(message.toString());
if (message == "CLOSE") {
socket.close();
}
});

socket.on('ping', () => {
console.log("Ping");
});

socket.on('pong', () => {
console.log("Pong");
});

socket.on('error', message => {
console.log(message.toString());
});

socket.on('close', () => {
console.log("Close");
});

socket.send('utf 8 string');
});
});
16 changes: 13 additions & 3 deletions ci/start_test_server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,24 @@ if [ $status -ne 0 ]; then
fi
echo "Successfully started socket.io instance"

DEBUG=* node engine-io-secure.js &
status=$?
if [ $status -ne 0 ]; then
echo "Failed to start secure engine.io: $status"
exit $status
fi
echo "Successfully started secure engine.io instance"

while sleep 60; do
ps aux |grep socket |grep -q -v grep
ps aux | grep socket | grep -q -v grep
PROCESS_1_STATUS=$?
ps aux |grep engine-io.js |grep -q -v grep
ps aux | grep engine-io.js | grep -q -v grep
PROCESS_2_STATUS=$?
ps aux | grep engine-io-secure.js | grep -q -v grep
PROCESS_3_STATUS=$?
# If the greps above find anything, they exit with 0 status
# If they are not both 0, then something is wrong
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 -o $PROCESS_3_STATUS -ne 0]; then
echo "One of the processes has already exited."
exit 1
fi
Expand Down
18 changes: 14 additions & 4 deletions src/engineio/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use super::packet::{Packet, PacketId};
use crate::engineio::transport::TransportClient;
use crate::error::{Error, Result};
use bytes::Bytes;
use native_tls::TlsConnector;
use reqwest::header::HeaderMap;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, RwLock,
Expand All @@ -19,9 +21,17 @@ pub struct EngineSocket {

impl EngineSocket {
/// Creates an instance of `EngineSocket`.
pub fn new(engine_io_mode: bool) -> Self {
pub fn new(
engine_io_mode: bool,
tls_config: Option<TlsConnector>,
opening_headers: Option<HeaderMap>,
) -> Self {
EngineSocket {
transport_client: Arc::new(RwLock::new(TransportClient::new(engine_io_mode))),
transport_client: Arc::new(RwLock::new(TransportClient::new(
engine_io_mode,
tls_config,
opening_headers,
))),
}
}

Expand Down Expand Up @@ -160,7 +170,7 @@ mod test {

#[test]
fn test_basic_connection() {
let mut socket = EngineSocket::new(true);
let mut socket = EngineSocket::new(true, None, None);

assert!(socket
.on_open(|_| {
Expand Down Expand Up @@ -212,7 +222,7 @@ mod test {

#[test]
fn test_illegal_actions() {
let mut sut = EngineSocket::new(true);
let mut sut = EngineSocket::new(true, None, None);

assert!(sut
.emit(Packet::new(PacketId::Close, Bytes::from_static(b"")))
Expand Down
Loading

0 comments on commit 9954692

Please sign in to comment.