(filed as bug #4304)
Below is a test case for a problem where communication between two Pike processes over SSL stalls with Pike 7.6.86.
To reproduce, run in two different terminals on the same computer. Start as 1) pike bug.pike server 2) pike bug.pike client
Expected behaviour: a lot of communication back and forth between the two processes: ping?, pong!, etc
Observed behaviour: 7.6.51: works as expected 7.6.66: works as expected 7.6.76: works as expected 7.6.86: communication stalled after first message sent 7.7: communication stalled after first message sent
Some hints:
- Reason for problem seems to be that the read callback is deregistred from the underlying file object.
- A workaround for the problem seems to be to pass 1 as 3rd argument to macro RUN_MAYBE_BLOCKING in method direct_write in SSL.pmod/sslfile.pike instead of SSL_INTERNAL_READING, preventing the callback to be unregistred (possible side effects of workaround unknown)
bug.pike:
#!/usr/bin/env pike
int i = 0;
class Server {
// from http.server string my_certificate = MIME.decode_base64( "MIIBxDCCAW4CAQAwDQYJKoZIhvcNAQEEBQAwbTELMAkGA1UEBhMCREUxEzARBgNV\n" "BAgTClRodWVyaW5nZW4xEDAOBgNVBAcTB0lsbWVuYXUxEzARBgNVBAoTClRVIEls\n" "bWVuYXUxDDAKBgNVBAsTA1BNSTEUMBIGA1UEAxMLZGVtbyBzZXJ2ZXIwHhcNOTYw\n" "NDMwMDUzNjU4WhcNOTYwNTMwMDUzNjU5WjBtMQswCQYDVQQGEwJERTETMBEGA1UE\n" "CBMKVGh1ZXJpbmdlbjEQMA4GA1UEBxMHSWxtZW5hdTETMBEGA1UEChMKVFUgSWxt\n" "ZW5hdTEMMAoGA1UECxMDUE1JMRQwEgYDVQQDEwtkZW1vIHNlcnZlcjBcMA0GCSqG\n" "SIb3DQEBAQUAA0sAMEgCQQDBB6T7bGJhRhRSpDESxk6FKh3iKKrpn4KcDtFM0W6s\n" "16QSPz6J0Z2a00lDxudwhJfQFkarJ2w44Gdl/8b+de37AgMBAAEwDQYJKoZIhvcN\n" "AQEEBQADQQB5O9VOLqt28vjLBuSP1De92uAiLURwg41idH8qXxmylD39UE/YtHnf\n" "bC6QS0pqetnZpQj1yEsjRTeVfuRfANGw\n");
string my_key = MIME.decode_base64( "MIIBOwIBAAJBAMEHpPtsYmFGFFKkMRLGToUqHeIoqumfgpwO0UzRbqzXpBI/PonR\n" "nZrTSUPG53CEl9AWRqsnbDjgZ2X/xv517fsCAwEAAQJBALzUbJmkQm1kL9dUVclH\n" "A2MTe15VaDTY3N0rRaZ/LmSXb3laiOgBnrFBCz+VRIi88go3wQ3PKLD8eQ5to+SB\n" "oWECIQDrmq//unoW1+/+D3JQMGC1KT4HJprhfxBsEoNrmyIhSwIhANG9c0bdpJse\n" "VJA0y6nxLeB9pyoGWNZrAB4636jTOigRAiBhLQlAqhJnT6N+H7LfnkSVFDCwVFz3\n" "eygz2yL3hCH8pwIhAKE6vEHuodmoYCMWorT5tGWM0hLpHCN/z3Btm38BGQSxAiAz\n" "jwsOclu4b+H8zopfzpAaoB8xMcbs0heN+GNNI0h/dQ==\n");
void create(Stdio.File file) { write("server: got connection\n"); SSL.context ctx = SSL.context(); ctx->random = Crypto.Random.random_string; ctx->rsa = Standards.PKCS.RSA.parse_private_key(my_key); ctx->certificates = ({ my_certificate }); SSL.sslfile f = SSL.sslfile(file, ctx, 0, 0); f->set_nonblocking(lambda(mixed id, string data) { write("server: (%d) got data <%s>, sending pong\n", i++, data); f->write("pong!"); }, lambda() { }, lambda() { write("server: close callback, exiting\n"); exit(-1); }, 0, 0, lambda() { write("server: handshake done, waiting for client to initiate\n"); }); } }
class Client { void create(Stdio.File file) { SSL.context ctx = SSL.context(); ctx->random = Crypto.Random.random_string; SSL.sslfile f = SSL.sslfile(file, ctx, 1, 0); write("client: connected\n"); f->set_nonblocking(lambda(mixed id, string data) { write("client: (%d) got data <%s>, sending ping\n", i++, data); f->write("ping?"); }, lambda() { }, lambda() { write("client: close callback\n"); exit(-1); }, 0, 0, lambda() { write("client: handshake done, sending ping\n"); f->write("ping?"); }); } }
void main(int argc, array argv) { int port = 12345;
if (argc == 2 && argv[1] == "server") { Stdio.Port p = Stdio.Port(); p->bind(port, lambda() { Server(p->accept()); }); write("server: waiting for connection\n"); } else if (argc == 2 && argv[1] == "client") { write("client: connecting\n"); Stdio.File socket = Stdio.File(); socket->connect("localhost", port); Client(socket); } else { write("specify client or server\n"); exit(-1); }
while (1) { Pike.DefaultBackend(); } }