{"id":20979637,"url":"https://github.com/velimir/ssl_cat","last_synced_at":"2026-05-22T08:03:52.688Z","repository":{"id":148997171,"uuid":"83784340","full_name":"velimir/ssl_cat","owner":"velimir","description":"Small application which was built to reproduce issue () with ssl sockets, when messages are received one by one using [{active, once}] method.","archived":false,"fork":false,"pushed_at":"2017-03-04T21:23:19.000Z","size":8775,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-20T06:25:10.997Z","etag":null,"topics":["erlang","issue","otp","ssl"],"latest_commit_sha":null,"homepage":"https://bugs.erlang.org/browse/ERL-371","language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/velimir.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-03T09:59:35.000Z","updated_at":"2017-05-10T10:03:23.000Z","dependencies_parsed_at":null,"dependency_job_id":"e9416035-30b6-4002-a1ab-3758664ed8ce","html_url":"https://github.com/velimir/ssl_cat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velimir%2Fssl_cat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velimir%2Fssl_cat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velimir%2Fssl_cat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/velimir%2Fssl_cat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/velimir","download_url":"https://codeload.github.com/velimir/ssl_cat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243382933,"owners_count":20282050,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["erlang","issue","otp","ssl"],"created_at":"2024-11-19T05:14:01.417Z","updated_at":"2025-12-26T08:20:11.880Z","avatar_url":"https://github.com/velimir.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SSL cat #\n\nSmall application which was built to reproduce issue with ssl sockets, when messages are received one by one using `[{active, once}]` method.\n\n## Build and run ##\n\n    $ rebar3 get-deps\n    $ rebar3 compile\n    $ rebar3 shell --apps ssl_cat\n\n## Steps to reproduce ##\n\nApplication starts 2 listeners on ports 8443 (`gen_tcp`) and 9443 (`ssl`). Both of them has the same protocol, which will be described later. The only difference is 8443 proxies requests to 9443 and back to requester.\n\nListeners receive file names, which are read from `priv` directory and sent back to requester.\n\n### Working example ###\n\nApplication works fine before Erlang 19.0, hence if you need to see that it works as it's supposed to work, you need to use Erlang version before 19.0, (let's say 18.3, on which it was tested).\n\nRun `ssl_cat` in one of terminals, as it's said above. Service will produce some traces, that it's started:\n\n```\n    (18.3)bash-3.2$ rebar3 shell --apps ssl_cat\n    ===\u003e Verifying dependencies...\n    ===\u003e Compiling ssl_cat\n    Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]\n    \n    Eshell V7.3  (abort with ^G)\n    1\u003e ===\u003e The rebar3 shell is a development tool; to deploy applications in production, consider using rel\n    eases (http://www.rebar3.org/docs/releases)\n    14:15:05.373 [info] Application lager started on node nonode@nohost\n    ===\u003e Booted syntax_tools\n    14:15:05.377 [info] Application ssl_cat started on node nonode@nohost\n    ===\u003e Booted compiler\n    ===\u003e Booted goldrush\n    ===\u003e Booted lager\n    ===\u003e Booted ssl_cat\n    14:15:05.395 [info] gen tcp is listening on port: 8443\n    14:15:05.429 [info] ssl is listening on port 9443\n```\n\nOnce it's started ask to read and reply back `small.json` file from `priv` directory:\n\n```\n    $ telnet 127.0.0.1 8443 \u003e out.json\n    small.json\n    Connection closed by foreign host.\n```\n\n`ssl_cat` produce something similar to this in the log:\n\n```\n    14:17:38.353 [info] tcp connection accepted\n    14:17:38.385 [info] ssl transport accepted\n    14:17:38.483 [info] ssl accepted\n    14:17:38.483 [info] connected to ssl reader\n    14:17:43.967 [info] received data from frontend\n    14:17:43.968 [info] ssl received: \u003c\u003c\"small.json\\r\\n\"\u003e\u003e\n    14:17:43.968 [info] reading file: \"\u003c ... \u003e/ssl_cat/_build/default/lib/ssl_cat/priv/small.json\"\n    14:17:43.998 [info] file is sent\n    14:17:43.998 [info] received data from backed: 16384, total: 16384\n    14:17:43.999 [info] received data from backed: 16384, total: 32768\n    14:17:44.000 [info] received data from backed: 16384, total: 49152\n    ...... skipped ....\n    14:17:44.268 [info] received data from backed: 11391, total: 1895551\n    14:17:44.269 [info] backend closed connection: ssl_closed\n```\n\nNotice that total bytes sent is equal to the size of small.json file:\n\n```\n-rw-r--r--  1 user  group  1895551 Feb 22 13:57 priv/small.json\n```\n\nYou can check, that `out.json` (output from telnet) contains the whole content from small.json.\n\n### Erlang 19 issue ###\n\nTry to do the same steps, but use Erlang 19.(0|1|2).\nAsk for `small.json` file once again, you'll see something like that in the output:\n\n```\n    14:23:41.071 [info] tcp connection accepted\n    14:23:41.103 [info] ssl transport accepted\n    14:23:41.212 [info] ssl accepted\n    14:23:41.212 [info] connected to ssl reader\n    14:23:43.789 [info] received data from frontend\n    14:23:43.789 [info] ssl received: \u003c\u003c\"small.json\\r\\n\"\u003e\u003e\n    14:23:43.789 [info] reading file: \"\u003c ... \u003e/ssl_cat/_build/default/lib/ssl_cat/priv/small.json\"\n    14:23:43.796 [info] file is sent\n    14:23:43.796 [info] received data from backed: 16384, total: 16384\n    ...... skipped ....\n    14:23:43.875 [info] received data from backed: 16384, total: 1884160\n    14:23:43.875 [info] ssl closed\n    14:23:43.880 [info] backend closed connection: ssl_closed\n```\n\nNotice, that `total` size is smaller, than `small.json` file. You can verify, that `out.json` now has a cut version of `small.json` file.\nIssue is `{ssl_closed, Socket}` message is received earlier, than other buffer (packet) from socket even though according to tcp trace and Erlang trace the whole file was successfully transferred from `9443` to requester (`ssl_cat_listener`).\n\n## Notes ##\n\nIssue is reproducible when:\n* Application is run on Erlang 19\n* `ssl_cat_ssl_reader` uses ssl under the hood (`gen_tcp` works fine)\n* `ssl_cat_listener` uses `{active, once}` method in a loop. If `{active, true}` is set issue is not reproducible.\n\n    ```erlang\n        proxy_request(FSocket, BSocket) -\u003e\n            %% -------------------vvvvvvvvvvvvvvv\n            inet:setopts(FSocket, [{active, once}]),\n            ssl:setopts(BSocket, [{active, once}]),\n            %% -------------------^^^^^^^^^^^^^^^\n            receive\n                {_, FSocket, Data} -\u003e\n                    ok = ssl:send(BSocket, Data),\n                    proxy_request(FSocket, BSocket);\n                {_, BSocket, Data} -\u003e\n                    ok = gen_tcp:send(FSocket, Data),\n                    proxy_request(FSocket, BSocket);\n                %% ....\n            end.\n    ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvelimir%2Fssl_cat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvelimir%2Fssl_cat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvelimir%2Fssl_cat/lists"}