From 155aa6dac5971bec711c54163dd79a21aaf05efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomas=20Hellstr=C3=B6m?= Date: Sat, 21 Nov 2020 14:45:45 +0100 Subject: [PATCH] x.websocket: fix autobahn tests for wss and wss close behavor (#6901) --- .github/workflows/ci.yml | 18 +++++++++ vlib/net/openssl/c.v | 3 +- vlib/x/openssl/openssl.v | 36 +++++------------ vlib/x/websocket/io.v | 11 ++++- vlib/x/websocket/tests/autobahn/README.md | 16 ++++++++ .../tests/autobahn/autobahn_client_wss.v | 40 +++++++++++++++++++ .../tests/autobahn/docker-compose.yml | 15 +++---- .../tests/autobahn/fuzzing_server/Dockerfile | 3 +- .../autobahn/fuzzing_server/check_results.py | 13 ------ .../autobahn/fuzzing_server_wss/Dockerfile | 9 +++++ .../fuzzing_server_wss/check_results.py | 35 ++++++++++++++++ .../config/fuzzingserver.json | 16 ++++++++ .../fuzzing_server_wss/config/server.crt | 19 +++++++++ .../fuzzing_server_wss/config/server.csr | 16 ++++++++ .../fuzzing_server_wss/config/server.key | 27 +++++++++++++ .../fuzzing_server_wss/config/server.pem | 19 +++++++++ .../tests/autobahn/local_run/README.md | 4 -- .../autobahn/local_run/autobahn_client.v | 38 ++++++++++++++++++ .../autobahn/local_run/autobahn_client_wss.v | 40 +++++++++++++++++++ vlib/x/websocket/websocket_client.v | 18 +++++---- 20 files changed, 333 insertions(+), 63 deletions(-) create mode 100644 vlib/x/websocket/tests/autobahn/autobahn_client_wss.v create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/Dockerfile create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/check_results.py create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/fuzzingserver.json create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.crt create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.csr create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.key create mode 100644 vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.pem delete mode 100644 vlib/x/websocket/tests/autobahn/local_run/README.md create mode 100644 vlib/x/websocket/tests/autobahn/local_run/autobahn_client.v create mode 100644 vlib/x/websocket/tests/autobahn/local_run/autobahn_client_wss.v diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d64fb29f2f..6e0dd5c670 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -546,12 +546,20 @@ jobs: run: docker exec autobahn_client "/src/v" "/src/vlib/x/websocket/tests/autobahn/autobahn_client.v" - name: Run client test 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 run: docker exec autobahn_server "wstest" "-m" "fuzzingclient" "-s" "/config/fuzzingclient.json" - name: Copy 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 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 uses: actions/upload-artifact@v2 @@ -568,3 +576,13 @@ jobs: with: name: server 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 diff --git a/vlib/net/openssl/c.v b/vlib/net/openssl/c.v index 00ba5bcf13..9aa8b9e295 100644 --- a/vlib/net/openssl/c.v +++ b/vlib/net/openssl/c.v @@ -42,10 +42,11 @@ fn C.SSL_set_fd() int fn C.SSL_connect() int fn C.SSL_set_cipher_list() int fn C.SSL_get_peer_certificate() int +fn C.ERR_clear_error() fn C.SSL_get_error() int fn C.SSL_get_verify_result() 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_write() int fn C.SSL_read() int diff --git a/vlib/x/openssl/openssl.v b/vlib/x/openssl/openssl.v index 8af617ffeb..7a493b11c1 100644 --- a/vlib/x/openssl/openssl.v +++ b/vlib/x/openssl/openssl.v @@ -34,7 +34,7 @@ pub fn (mut s SSLConn) shutdown() ? { if s.ssl != 0 { mut res := 0 for { - res = int(C.SSL_shutdown(s.ssl)) + res = C.SSL_shutdown(s.ssl) if res < 0 { err_res := openssl.ssl_error(res, s.ssl) or { break // We break to free rest of resources @@ -56,9 +56,15 @@ pub fn (mut s SSLConn) shutdown() ? { } continue } else { + C.SSL_free(s.ssl) + if s.sslctx != 0 { + C.SSL_CTX_free(s.sslctx) + } 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 { 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 { return 0 } - return error('Could not read using SSL. ($err_res),err') + return error('Could not read using SSL. ($err_res)') } 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 have to be consolidated into common net lib features diff --git a/vlib/x/websocket/io.v b/vlib/x/websocket/io.v index 1bc71856c8..456cf9b721 100644 --- a/vlib/x/websocket/io.v +++ b/vlib/x/websocket/io.v @@ -11,6 +11,9 @@ interface WebsocketIO { // socket_read reads into the provided buffer with its length fn (mut ws Client) socket_read(mut buffer []byte) ?int { 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 { r := ws.ssl_conn.read_into(mut buffer)? 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 { 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 { r := ws.ssl_conn.socket_read_into_ptr(buf_ptr, len)? 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) ? { lock { if ws.state == .closed || ws.conn.sock.handle <= 1 { - ws.debug_log('write: Socket allready closed') - return error('Socket allready closed') + ws.debug_log('socket_write: Socket allready closed') + return error('socket_write: trying to write on a closed socket') } if ws.is_ssl { ws.ssl_conn.write(bytes)? diff --git a/vlib/x/websocket/tests/autobahn/README.md b/vlib/x/websocket/tests/autobahn/README.md index 14e6715cf1..40724ee5e5 100644 --- a/vlib/x/websocket/tests/autobahn/README.md +++ b/vlib/x/websocket/tests/autobahn/README.md @@ -2,3 +2,19 @@ This is the autobahn automatic tests on build. 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 \ No newline at end of file diff --git a/vlib/x/websocket/tests/autobahn/autobahn_client_wss.v b/vlib/x/websocket/tests/autobahn/autobahn_client_wss.v new file mode 100644 index 0000000000..4959147648 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/autobahn_client_wss.v @@ -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) + } +} diff --git a/vlib/x/websocket/tests/autobahn/docker-compose.yml b/vlib/x/websocket/tests/autobahn/docker-compose.yml index c982a321db..52885d05ef 100644 --- a/vlib/x/websocket/tests/autobahn/docker-compose.yml +++ b/vlib/x/websocket/tests/autobahn/docker-compose.yml @@ -1,20 +1,21 @@ version: '3' services: - web: + server: container_name: autobahn_server build: fuzzing_server ports: - "9001:9001" - "8080:8080" + server_wss: + container_name: autobahn_server_wss + build: fuzzing_server_wss + + ports: + - "9002:9002" + - "8081:8080" client: container_name: autobahn_client build: - #vlib/x/websocket/tests/autobahn/ws_test/Dockerfile dockerfile: vlib/x/websocket/tests/autobahn/ws_test/Dockerfile context: ../../../../../ - # volumes: - # - ../../:/src -# redis: -# container_name: redis-backend -# image: "redis:alpine" \ No newline at end of file diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server/Dockerfile b/vlib/x/websocket/tests/autobahn/fuzzing_server/Dockerfile index 68be8dda52..ca5201b201 100644 --- a/vlib/x/websocket/tests/autobahn/fuzzing_server/Dockerfile +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server/Dockerfile @@ -2,5 +2,4 @@ FROM crossbario/autobahn-testsuite COPY check_results.py /check_results.py RUN chmod +x /check_results.py -COPY config/fuzzingserver.json /config/fuzzingserver.json -COPY config/fuzzingclient.json /config/fuzzingclient.json +COPY config /config diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server/check_results.py b/vlib/x/websocket/tests/autobahn/fuzzing_server/check_results.py index 2c3dcd5ff1..9275c3cb86 100644 --- a/vlib/x/websocket/tests/autobahn/fuzzing_server/check_results.py +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server/check_results.py @@ -6,19 +6,6 @@ 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 - with open("/reports/clients/index.json") as f: data = json.load(f) diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/Dockerfile b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/Dockerfile new file mode 100644 index 0000000000..67114c4657 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/Dockerfile @@ -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 \ No newline at end of file diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/check_results.py b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/check_results.py new file mode 100644 index 0000000000..d75904c247 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/check_results.py @@ -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 + ) +) diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/fuzzingserver.json b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/fuzzingserver.json new file mode 100644 index 0000000000..494dfffc83 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/fuzzingserver.json @@ -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": {} +} \ No newline at end of file diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.crt b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.crt new file mode 100644 index 0000000000..d4071d1a33 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.crt @@ -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----- diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.csr b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.csr new file mode 100644 index 0000000000..6013ea917e --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.csr @@ -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----- diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.key b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.key new file mode 100644 index 0000000000..05c9d77f61 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.key @@ -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----- diff --git a/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.pem b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.pem new file mode 100644 index 0000000000..d4071d1a33 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/fuzzing_server_wss/config/server.pem @@ -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----- diff --git a/vlib/x/websocket/tests/autobahn/local_run/README.md b/vlib/x/websocket/tests/autobahn/local_run/README.md deleted file mode 100644 index 8f100e7c45..0000000000 --- a/vlib/x/websocket/tests/autobahn/local_run/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Run tests locally - -Todo: document how, also how to use https://github.com/nektos/act - diff --git a/vlib/x/websocket/tests/autobahn/local_run/autobahn_client.v b/vlib/x/websocket/tests/autobahn/local_run/autobahn_client.v new file mode 100644 index 0000000000..90599870f6 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/local_run/autobahn_client.v @@ -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) + } +} diff --git a/vlib/x/websocket/tests/autobahn/local_run/autobahn_client_wss.v b/vlib/x/websocket/tests/autobahn/local_run/autobahn_client_wss.v new file mode 100644 index 0000000000..4959147648 --- /dev/null +++ b/vlib/x/websocket/tests/autobahn/local_run/autobahn_client_wss.v @@ -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) + } +} diff --git a/vlib/x/websocket/websocket_client.v b/vlib/x/websocket/websocket_client.v index 9e4b87d00b..f06147f5bc 100644 --- a/vlib/x/websocket/websocket_client.v +++ b/vlib/x/websocket/websocket_client.v @@ -94,12 +94,13 @@ pub fn new_client(address string) ?&Client { // connect, connects and do handshake procedure with remote server pub fn (mut ws Client) connect() ? { - ws.assert_not_connected() + ws.assert_not_connected()? ws.set_state(.connecting) ws.logger.info('connecting to host $ws.uri') ws.conn = ws.dial_socket()? - ws.conn.set_read_timeout(net.infinite_timeout) - ws.conn.set_write_timeout(net.infinite_timeout) + // Todo: make setting configurable + ws.conn.set_read_timeout(time.second * 30) + ws.conn.set_write_timeout(time.second * 30) ws.handshake()? ws.set_state(.open) 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)...') defer { 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 { 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') return error(err) } + if ws.state in [.closed, .closing] { + return + } ws.debug_log('got message: $msg.opcode') // , payload: $msg.payload') leaks match msg.opcode { .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)') err_msg := 'Socket allready closed: $code' ret_err := error(err_msg) - // unsafe { - // err_msg.free() - // } return ret_err } defer { @@ -482,6 +485,7 @@ fn (ws Client) assert_not_connected() ? { match ws.state { .connecting { return error('connect: websocket is connecting') } .open { return error('connect: websocket already open') } + .closing { return error('connect: reconnect on closing websocket not supported, please use new client') } else {} } }