x.websocket: fix autobahn tests for wss and wss close behavor (#6901)

pull/6903/head
Tomas Hellström 2020-11-21 14:45:45 +01:00 committed by GitHub
parent b6099cd978
commit 155aa6dac5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 333 additions and 63 deletions

View File

@ -546,12 +546,20 @@ jobs:
run: docker exec autobahn_client "/src/v" "/src/vlib/x/websocket/tests/autobahn/autobahn_client.v" run: docker exec autobahn_client "/src/v" "/src/vlib/x/websocket/tests/autobahn/autobahn_client.v"
- name: Run client test - name: Run client test
run: docker exec autobahn_client "/src/vlib/x/websocket/tests/autobahn/autobahn_client" run: docker exec autobahn_client "/src/vlib/x/websocket/tests/autobahn/autobahn_client"
- name: Build client wss test
run: docker exec autobahn_client "/src/v" "/src/vlib/x/websocket/tests/autobahn/autobahn_client_wss.v"
- name: Run client wss test
run: docker exec autobahn_client "/src/vlib/x/websocket/tests/autobahn/autobahn_client_wss"
- name: Run server test - name: Run server test
run: docker exec autobahn_server "wstest" "-m" "fuzzingclient" "-s" "/config/fuzzingclient.json" run: docker exec autobahn_server "wstest" "-m" "fuzzingclient" "-s" "/config/fuzzingclient.json"
- name: Copy reports - name: Copy reports
run: docker cp autobahn_server:/reports ${{github.workspace}}/reports run: docker cp autobahn_server:/reports ${{github.workspace}}/reports
- name: Copy reports wss
run: docker cp autobahn_server_wss:/reports ${{github.workspace}}/reports_wss
- name: Test success - name: Test success
run: docker exec autobahn_server "python" "/check_results.py" run: docker exec autobahn_server "python" "/check_results.py"
- name: Test success WSS
run: docker exec autobahn_server_wss "python" "/check_results.py"
- name: Publish all reports - name: Publish all reports
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
@ -568,3 +576,13 @@ jobs:
with: with:
name: server name: server
path: ${{github.workspace}}/reports/servers/index.html path: ${{github.workspace}}/reports/servers/index.html
- name: Publish all reports WSS
uses: actions/upload-artifact@v2
with:
name: full report wss
path: ${{github.workspace}}/reports_wss
- name: Publish report client wss
uses: actions/upload-artifact@v2
with:
name: client wss
path: ${{github.workspace}}/reports_wss/clients/index.html

View File

@ -42,10 +42,11 @@ fn C.SSL_set_fd() int
fn C.SSL_connect() int fn C.SSL_connect() int
fn C.SSL_set_cipher_list() int fn C.SSL_set_cipher_list() int
fn C.SSL_get_peer_certificate() int fn C.SSL_get_peer_certificate() int
fn C.ERR_clear_error()
fn C.SSL_get_error() int fn C.SSL_get_error() int
fn C.SSL_get_verify_result() int fn C.SSL_get_verify_result() int
fn C.SSL_set_tlsext_host_name() int fn C.SSL_set_tlsext_host_name() int
fn C.SSL_shutdown() fn C.SSL_shutdown() int
fn C.SSL_free() fn C.SSL_free()
fn C.SSL_write() int fn C.SSL_write() int
fn C.SSL_read() int fn C.SSL_read() int

View File

@ -34,7 +34,7 @@ pub fn (mut s SSLConn) shutdown() ? {
if s.ssl != 0 { if s.ssl != 0 {
mut res := 0 mut res := 0
for { for {
res = int(C.SSL_shutdown(s.ssl)) res = C.SSL_shutdown(s.ssl)
if res < 0 { if res < 0 {
err_res := openssl.ssl_error(res, s.ssl) or { err_res := openssl.ssl_error(res, s.ssl) or {
break // We break to free rest of resources break // We break to free rest of resources
@ -56,9 +56,15 @@ pub fn (mut s SSLConn) shutdown() ? {
} }
continue continue
} else { } else {
C.SSL_free(s.ssl)
if s.sslctx != 0 {
C.SSL_CTX_free(s.sslctx)
}
return error('unexepedted ssl error $err_res') return error('unexepedted ssl error $err_res')
} }
C.SSL_free(s.ssl) if s.ssl != 0 {
C.SSL_free(s.ssl)
}
if s.sslctx != 0 { if s.sslctx != 0 {
C.SSL_CTX_free(s.sslctx) C.SSL_CTX_free(s.sslctx)
} }
@ -144,7 +150,7 @@ pub fn (mut s SSLConn) socket_read_into_ptr(buf_ptr byteptr, len int) ?int {
} else if err_res == .ssl_error_zero_return { } else if err_res == .ssl_error_zero_return {
return 0 return 0
} }
return error('Could not read using SSL. ($err_res),err') return error('Could not read using SSL. ($err_res)')
} }
break break
} }
@ -192,30 +198,6 @@ pub fn (mut s SSLConn) write(bytes []Byte) ? {
} }
} }
// // ssl_error returns non error ssl code or error if unrecoverable and we should panic
// fn (mut s SSLConn) ssl_error(ret int) ?SSLError {
// res := C.SSL_get_error(s.ssl, ret)
// match SSLError(res) {
// .ssl_error_syscall { return error_with_code('unrecoverable syscall ($res)', res) }
// .ssl_error_ssl { return error_with_code('unrecoverable ssl protocol error ($res)',
// res) }
// else { return res }
// }
// }
// enum SSLError {
// ssl_error_none = C.SSL_ERROR_NONE
// ssl_error_ssl = C.SSL_ERROR_SSL
// ssl_error_want_read = C.SSL_ERROR_WANT_READ
// ssl_error_want_write = C.SSL_ERROR_WANT_WRITE
// ssl_error_want_x509_lookup = C.SSL_ERROR_WANT_X509_LOOKUP
// ssl_error_syscall = C.SSL_ERROR_SYSCALL
// ssl_error_zero_return = C.SSL_ERROR_ZERO_RETURN
// ssl_error_want_connect = C.SSL_ERROR_WANT_CONNECT
// ssl_error_want_accept = C.SSL_ERROR_WANT_ACCEPT
// ssl_error_want_async = C.SSL_ERROR_WANT_ASYNC
// ssl_error_want_async_job = C.SSL_ERROR_WANT_ASYNC_JOB
// ssl_error_want_client_hello_cb = C.SSL_ERROR_WANT_CLIENT_HELLO_CB
// }
/* /*
This is basically a copy of Emily socket implementation of select. This is basically a copy of Emily socket implementation of select.
This have to be consolidated into common net lib features This have to be consolidated into common net lib features

View File

@ -11,6 +11,9 @@ interface WebsocketIO {
// socket_read reads into the provided buffer with its length // socket_read reads into the provided buffer with its length
fn (mut ws Client) socket_read(mut buffer []byte) ?int { fn (mut ws Client) socket_read(mut buffer []byte) ?int {
lock { lock {
if ws.state in [.closed, .closing] || ws.conn.sock.handle <= 1 {
return error('socket_read: trying to read a closed socket')
}
if ws.is_ssl { if ws.is_ssl {
r := ws.ssl_conn.read_into(mut buffer)? r := ws.ssl_conn.read_into(mut buffer)?
return r return r
@ -30,6 +33,10 @@ fn (mut ws Client) socket_read(mut buffer []byte) ?int {
fn (mut ws Client) socket_read_ptr(buf_ptr byteptr, len int) ?int { fn (mut ws Client) socket_read_ptr(buf_ptr byteptr, len int) ?int {
lock { lock {
if ws.state in [.closed, .closing] || ws.conn.sock.handle <= 1 {
return error('socket_read_ptr: trying to read a closed socket')
}
if ws.is_ssl { if ws.is_ssl {
r := ws.ssl_conn.socket_read_into_ptr(buf_ptr, len)? r := ws.ssl_conn.socket_read_into_ptr(buf_ptr, len)?
return r return r
@ -51,8 +58,8 @@ fn (mut ws Client) socket_read_ptr(buf_ptr byteptr, len int) ?int {
fn (mut ws Client) socket_write(bytes []byte) ? { fn (mut ws Client) socket_write(bytes []byte) ? {
lock { lock {
if ws.state == .closed || ws.conn.sock.handle <= 1 { if ws.state == .closed || ws.conn.sock.handle <= 1 {
ws.debug_log('write: Socket allready closed') ws.debug_log('socket_write: Socket allready closed')
return error('Socket allready closed') return error('socket_write: trying to write on a closed socket')
} }
if ws.is_ssl { if ws.is_ssl {
ws.ssl_conn.write(bytes)? ws.ssl_conn.write(bytes)?

View File

@ -2,3 +2,19 @@
This is the autobahn automatic tests on build. This is the autobahn automatic tests on build.
The performance tests are skipped due to timeouts in Github actions. The performance tests are skipped due to timeouts in Github actions.
## Run it locally
### Test the client
This is how to test the client:
1. Run the docker autobahn test suite by running the `docker-compose up`
2. From the `local_run` folder, compile and run `autobahn_client.v` to test non ws (no TLS) and
`autobahn_client_wss.v` to run the TLS tests
3. Open `http://localhost:8080` and browse client test results for non TLS and `https://localhost:8081`
if you ran the wss tests (it uses local certificat so you will get trust error but just accept use)
### Test the server
Todo: add information here

View File

@ -0,0 +1,40 @@
// use this test to test the websocket client in the autobahn test
module main
import x.websocket
fn main() {
for i in 1 ..304 {
println('\ncase: $i')
handle_case(i) or {
println('error should be ok: $err')
}
}
// update the reports
// uri := 'wss://localhost:9002/updateReports?agent=v-client'
uri := 'wss://autobahn_server_wss:9002/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
}
fn handle_case(case_nr int) ? {
uri := 'wss://autobahn_server_wss:9002/runCase?case=$case_nr&agent=v-client'
// uri := 'wss://localhost:9002/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
ws.on_message(on_message)
ws.connect()?
ws.listen()?
}
fn on_message(mut ws websocket.Client, msg &websocket.Message)? {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn
return
}
ws.write(msg.payload, msg.opcode) or {
panic(err)
}
}

View File

@ -1,20 +1,21 @@
version: '3' version: '3'
services: services:
web: server:
container_name: autobahn_server container_name: autobahn_server
build: fuzzing_server build: fuzzing_server
ports: ports:
- "9001:9001" - "9001:9001"
- "8080:8080" - "8080:8080"
server_wss:
container_name: autobahn_server_wss
build: fuzzing_server_wss
ports:
- "9002:9002"
- "8081:8080"
client: client:
container_name: autobahn_client container_name: autobahn_client
build: build:
#vlib/x/websocket/tests/autobahn/ws_test/Dockerfile
dockerfile: vlib/x/websocket/tests/autobahn/ws_test/Dockerfile dockerfile: vlib/x/websocket/tests/autobahn/ws_test/Dockerfile
context: ../../../../../ context: ../../../../../
# volumes:
# - ../../:/src
# redis:
# container_name: redis-backend
# image: "redis:alpine"

View File

@ -2,5 +2,4 @@ FROM crossbario/autobahn-testsuite
COPY check_results.py /check_results.py COPY check_results.py /check_results.py
RUN chmod +x /check_results.py RUN chmod +x /check_results.py
COPY config/fuzzingserver.json /config/fuzzingserver.json COPY config /config
COPY config/fuzzingclient.json /config/fuzzingclient.json

View File

@ -6,19 +6,6 @@ nr_of_client_tests = 0
nr_of_server_errs = 0 nr_of_server_errs = 0
nr_of_server_tests = 0 nr_of_server_tests = 0
with open("/reports/clients/index.json") as f:
data = json.load(f)
for i in data["v-client"]:
# Count errors
if (
data["v-client"][i]["behavior"] == "FAILED"
or data["v-client"][i]["behaviorClose"] == "FAILED"
):
nr_of_client_errs = nr_of_client_errs + 1
nr_of_client_tests = nr_of_client_tests + 1
with open("/reports/clients/index.json") as f: with open("/reports/clients/index.json") as f:
data = json.load(f) data = json.load(f)

View File

@ -0,0 +1,9 @@
FROM crossbario/autobahn-testsuite
COPY check_results.py /check_results.py
RUN chmod +x /check_results.py
COPY config /config
RUN chmod +rx /config/server.crt
RUN chmod +rx /config/server.key
EXPOSE 9002 9002

View File

@ -0,0 +1,35 @@
import json
nr_of_client_errs = 0
nr_of_client_tests = 0
nr_of_server_errs = 0
nr_of_server_tests = 0
with open("/reports/clients/index.json") as f:
data = json.load(f)
for i in data["v-client"]:
# Count errors
if (
data["v-client"][i]["behavior"] == "FAILED"
or data["v-client"][i]["behaviorClose"] == "FAILED"
):
nr_of_client_errs = nr_of_client_errs + 1
nr_of_client_tests = nr_of_client_tests + 1
if nr_of_client_errs > 0 or nr_of_server_errs > 0:
print(
"FAILED AUTOBAHN TESTS, CLIENT ERRORS {0}(of {1}), SERVER ERRORS {2}(of {3})".format(
nr_of_client_errs, nr_of_client_tests, nr_of_server_errs, nr_of_server_tests
)
)
exit(1)
print(
"TEST SUCCESS!, CLIENT TESTS({0}), SERVER TESTS ({1})".format(
nr_of_client_tests, nr_of_server_tests
)
)

View File

@ -0,0 +1,16 @@
{
"url": "wss://127.0.0.1:9002",
"outdir": "./reports/clients",
"key": "/config/server.key",
"cert": "/config/server.crt",
"cases": [
"*"
],
"exclude-cases": [
"9.*",
"11.*",
"12.*",
"13.*"
],
"exclude-agent-cases": {}
}

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDETCCAfkCFAtFKlcdB3jhD+AXPul81dwmZcs/MA0GCSqGSIb3DQEBCwUAMEUx
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAxMTIxMDgyNjQ5WhcNMzAxMTE5MDgy
NjQ5WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnbysLfcIr9+wpoJjb5r728j2e07agedOzh8VLuGnHqmKOUPN
f8Ik707kEoBcFY7UM2A9G/1RMIysGp8eleQLMtNdeYc3KlKHBGFrOM3i4gCd7G44
lERuKP1PKzRQ6RdVNUXn51XjfxjHWo7kHCEVvZowxvzxLxhwbSwmEmgzcQ1T6vj6
Cdop87sdq00F+eOCfTdy+cl+R65sbImVdfY4EQ0QWAVdF3X6njLjpdmteppggbEa
ECv3R3qNIV7/rflIPm1efbqp7R1ugvjLPJZ1u12ovtqkgsWbnEyzST8hbEEjsOTJ
/cPkH2DaLdh7fMgfcVmqnYXd9T+gpsNGv98DjwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQBG9GxUOjcrFd1ept9AOTzbxvIUvBiqIEzrL2/+3T1yPPAWQzOmBfZhIVVm
EZeeU3xcvd7+AmX+2FPCAD+evjSHjKY048X1YksQS7mYChSgeJiknoJi3mAEAyw6
oYGVkETksZLQfXtWTjgljbIQrwTA1s+EW0jvmvaJnWD3/8nFqmfly2/kxVsTcGEa
wJGEUS53Cq6y6lLZ+ojjjj1iVCQ94U6L/0xPB9hgXOyL2+iQj+n38ruatnUNF77C
UKS7N9BFF42eqVY83Xab0m25s93m8Z7J/63qu0eeA8p5t7+8lbGvOYpwReknLRMf
pJfgSEWqWfSaetihbJl2Fmzg2SeJ
-----END CERTIFICATE-----

View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAJ28rC33CK/fsKaCY2+a+9vI9ntO2oHnTs4fFS7h
px6pijlDzX/CJO9O5BKAXBWO1DNgPRv9UTCMrBqfHpXkCzLTXXmHNypShwRhazjN
4uIAnexuOJREbij9Tys0UOkXVTVF5+dV438Yx1qO5BwhFb2aMMb88S8YcG0sJhJo
M3ENU+r4+gnaKfO7HatNBfnjgn03cvnJfkeubGyJlXX2OBENEFgFXRd1+p4y46XZ
rXqaYIGxGhAr90d6jSFe/635SD5tXn26qe0dboL4yzyWdbtdqL7apILFm5xMs0k/
IWxBI7Dkyf3D5B9g2i3Ye3zIH3FZqp2F3fU/oKbDRr/fA48CAwEAAaAAMA0GCSqG
SIb3DQEBCwUAA4IBAQARfNhaiioyJPZZ8Hkf9UPbi85djYLDYCC9EqBPHpYpGh15
WdRsTModg/X5DeGwtWwRyGSP2ROMWa1NB5RHZ9buIgCIOeszhAvXVaQMlHmpNhSD
/hWKGGpAEq12TKHxgi9eTOE2u9MhoJf1G6iGffVsHc8r52THvGqKBp3Bi8G1Pl6L
2J1f5qX42K1DEnCx0gGnQkydO6E4UnMbsaDSFSODQwg5LpzSYoYUfpYHstMpqAqL
rcEt869YKjemKuTCzHODWxfqlvVr9GctNjKG2WtoqnX+10x3tw/9lsNRKUelCQxb
E56eujAoQdMxQ4OjwSnc/gbpWa5gXKYjpgAfx2kY
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAnbysLfcIr9+wpoJjb5r728j2e07agedOzh8VLuGnHqmKOUPN
f8Ik707kEoBcFY7UM2A9G/1RMIysGp8eleQLMtNdeYc3KlKHBGFrOM3i4gCd7G44
lERuKP1PKzRQ6RdVNUXn51XjfxjHWo7kHCEVvZowxvzxLxhwbSwmEmgzcQ1T6vj6
Cdop87sdq00F+eOCfTdy+cl+R65sbImVdfY4EQ0QWAVdF3X6njLjpdmteppggbEa
ECv3R3qNIV7/rflIPm1efbqp7R1ugvjLPJZ1u12ovtqkgsWbnEyzST8hbEEjsOTJ
/cPkH2DaLdh7fMgfcVmqnYXd9T+gpsNGv98DjwIDAQABAoIBAE+IFfiHGiYzT0pl
a+WV62+CAGVj+OCO1Dkxiui8dhsLuNnuyeqk5SKUUILTnZpxDaVp3OYD76/e/dfe
avmApfTWhccE2lfIjLM0u29EwCTb0sSnPnfjmPep4QUTt8gPL7NQsAEAWVh4Eewj
J/jW5bNXz0hFuQXZ+LXTEM8vIuDY4M0RX/jhEcCVr3QH8Sp/6JEeRY2Mbn5Z6LZ+
BVuu8e4sCpamWOOWfoIQq3e3TbATFSNP9vzPLKvxwwAw9g5dAKPn3dvem8ofzaaF
MeJ6T485mnx0naBrI+1qHLb3QcRpSZp6uEOp/4uvkCFm9S3dBGIwOGwHcybWFfFr
StPfccECgYEAzN2f1BcvL3rt4970lG/MGNeLMpF7h7aWca0DzUNY5sCh+kvENHrD
U4nH5EHoqxB1c036LKBhsrrrk5F/eQ8M+QEqpKUfqAYUrfy+HRAAeTYbhLkCysrL
+X/mlqYeyzMHj4Pjy5rqoy2TnJFnfIZYwYOL/OfA9IPwGpW2rxVSk1cCgYEAxRul
9j0Ii3Te08TprfriDpAFQyLH54vqVwe8mkox3cdOyYvUNHdEmDNh3/7dadxVKsIx
gIkPdGcizOw4elLKWnNFQN3+dCc3LN/zhsop0a6Ow2IatWQ8qOSqNYtD2DGj0w3j
cJ/BZfacpr/OkAv0kjanYw4+ZSIH/r3Vjdli5okCgYBXltni4Ba4giJ7rrN7U2E7
rcxBzpm2KIaiC4r4k7bK0clvLj2xAlvIt7vTB6rmmJ7esZQoyFl9BRX7fdW2eIzf
WXRV+JNUT2VADjNqUZEiQdP6Ju/erF4RSnHYLyYzUpoE7irSvmVbZv0Zj8FjKD2C
Xy/W7W8+G7roYuI8cS1g+QKBgQCDoHwK3SU4o9ouB0CZ64FMgkbRV4exi9D5P3Rm
gIeed/uYQiV6x+7pyN5ijDtl9zp0rGwMTvsgG8O0n0b0AReaoYGs2NKU1J9W+1MQ
Py8AFJbHyVrWqVKM4u77hL3QwQ2K4qpwym6HXdGs1UfnD+TKQ28yig+Gz9wQ9MqI
yJPwKQKBgQCmZxhmX1SUe3DVnVulMHDLUldbRbFns0VZLiSDhY+hjOAEmnvEdEHp
6L8/gvdTqUPF/VZQSQiZlii1oTIapQClI2oLfHcGytSorB+bpL7PxAKABp0pA6BS
JkXzEiV1h5anbxiwid5ZICt6QGQvGvBF7b1VSb+8p9WglLBWZo36pw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDETCCAfkCFAtFKlcdB3jhD+AXPul81dwmZcs/MA0GCSqGSIb3DQEBCwUAMEUx
CzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl
cm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMjAxMTIxMDgyNjQ5WhcNMzAxMTE5MDgy
NjQ5WjBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UE
CgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAnbysLfcIr9+wpoJjb5r728j2e07agedOzh8VLuGnHqmKOUPN
f8Ik707kEoBcFY7UM2A9G/1RMIysGp8eleQLMtNdeYc3KlKHBGFrOM3i4gCd7G44
lERuKP1PKzRQ6RdVNUXn51XjfxjHWo7kHCEVvZowxvzxLxhwbSwmEmgzcQ1T6vj6
Cdop87sdq00F+eOCfTdy+cl+R65sbImVdfY4EQ0QWAVdF3X6njLjpdmteppggbEa
ECv3R3qNIV7/rflIPm1efbqp7R1ugvjLPJZ1u12ovtqkgsWbnEyzST8hbEEjsOTJ
/cPkH2DaLdh7fMgfcVmqnYXd9T+gpsNGv98DjwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQBG9GxUOjcrFd1ept9AOTzbxvIUvBiqIEzrL2/+3T1yPPAWQzOmBfZhIVVm
EZeeU3xcvd7+AmX+2FPCAD+evjSHjKY048X1YksQS7mYChSgeJiknoJi3mAEAyw6
oYGVkETksZLQfXtWTjgljbIQrwTA1s+EW0jvmvaJnWD3/8nFqmfly2/kxVsTcGEa
wJGEUS53Cq6y6lLZ+ojjjj1iVCQ94U6L/0xPB9hgXOyL2+iQj+n38ruatnUNF77C
UKS7N9BFF42eqVY83Xab0m25s93m8Z7J/63qu0eeA8p5t7+8lbGvOYpwReknLRMf
pJfgSEWqWfSaetihbJl2Fmzg2SeJ
-----END CERTIFICATE-----

View File

@ -1,4 +0,0 @@
# Run tests locally
Todo: document how, also how to use https://github.com/nektos/act

View File

@ -0,0 +1,38 @@
// use this test to test the websocket client in the autobahn test
module main
import x.websocket
fn main() {
for i in 1 ..304 {
println('\ncase: $i')
handle_case(i) or {
println('error should be ok: $err')
}
}
// update the reports
uri := 'ws://localhost:9001/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
}
fn handle_case(case_nr int) ? {
uri := 'ws://localhost:9001/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
ws.on_message(on_message)
ws.connect()?
ws.listen()?
}
fn on_message(mut ws websocket.Client, msg &websocket.Message)? {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn
return
}
ws.write(msg.payload, msg.opcode) or {
panic(err)
}
}

View File

@ -0,0 +1,40 @@
// use this test to test the websocket client in the autobahn test
module main
import x.websocket
fn main() {
for i in 1 ..304 {
println('\ncase: $i')
handle_case(i) or {
println('error should be ok: $err')
}
}
// update the reports
// uri := 'wss://localhost:9002/updateReports?agent=v-client'
uri := 'wss://autobahn_server_wss:9002/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
}
fn handle_case(case_nr int) ? {
uri := 'wss://autobahn_server_wss:9002/runCase?case=$case_nr&agent=v-client'
// uri := 'wss://localhost:9002/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
ws.on_message(on_message)
ws.connect()?
ws.listen()?
}
fn on_message(mut ws websocket.Client, msg &websocket.Message)? {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn
return
}
ws.write(msg.payload, msg.opcode) or {
panic(err)
}
}

View File

@ -94,12 +94,13 @@ pub fn new_client(address string) ?&Client {
// connect, connects and do handshake procedure with remote server // connect, connects and do handshake procedure with remote server
pub fn (mut ws Client) connect() ? { pub fn (mut ws Client) connect() ? {
ws.assert_not_connected() ws.assert_not_connected()?
ws.set_state(.connecting) ws.set_state(.connecting)
ws.logger.info('connecting to host $ws.uri') ws.logger.info('connecting to host $ws.uri')
ws.conn = ws.dial_socket()? ws.conn = ws.dial_socket()?
ws.conn.set_read_timeout(net.infinite_timeout) // Todo: make setting configurable
ws.conn.set_write_timeout(net.infinite_timeout) ws.conn.set_read_timeout(time.second * 30)
ws.conn.set_write_timeout(time.second * 30)
ws.handshake()? ws.handshake()?
ws.set_state(.open) ws.set_state(.open)
ws.logger.info('successfully connected to host $ws.uri') ws.logger.info('successfully connected to host $ws.uri')
@ -111,7 +112,9 @@ pub fn (mut ws Client) listen() ? {
ws.logger.info('Starting client listener, server($ws.is_server)...') ws.logger.info('Starting client listener, server($ws.is_server)...')
defer { defer {
ws.logger.info('Quit client listener, server($ws.is_server)...') ws.logger.info('Quit client listener, server($ws.is_server)...')
ws.close(1000, 'closed by client') if ws.state == .open {
ws.close(1000, 'closed by client')
}
} }
for ws.state == .open { for ws.state == .open {
msg := ws.read_next_message() or { msg := ws.read_next_message() or {
@ -122,6 +125,9 @@ pub fn (mut ws Client) listen() ? {
ws.send_error_event('failed to read next message: $err') ws.send_error_event('failed to read next message: $err')
return error(err) return error(err)
} }
if ws.state in [.closed, .closing] {
return
}
ws.debug_log('got message: $msg.opcode') // , payload: $msg.payload') leaks ws.debug_log('got message: $msg.opcode') // , payload: $msg.payload') leaks
match msg.opcode { match msg.opcode {
.text_frame { .text_frame {
@ -345,9 +351,6 @@ pub fn (mut ws Client) close(code int, message string) ? {
ws.debug_log('close: Websocket allready closed ($ws.state), $message, $code handle($ws.conn.sock.handle)') ws.debug_log('close: Websocket allready closed ($ws.state), $message, $code handle($ws.conn.sock.handle)')
err_msg := 'Socket allready closed: $code' err_msg := 'Socket allready closed: $code'
ret_err := error(err_msg) ret_err := error(err_msg)
// unsafe {
// err_msg.free()
// }
return ret_err return ret_err
} }
defer { defer {
@ -482,6 +485,7 @@ fn (ws Client) assert_not_connected() ? {
match ws.state { match ws.state {
.connecting { return error('connect: websocket is connecting') } .connecting { return error('connect: websocket is connecting') }
.open { return error('connect: websocket already open') } .open { return error('connect: websocket already open') }
.closing { return error('connect: reconnect on closing websocket not supported, please use new client') }
else {} else {}
} }
} }