/* * Sends a change cipher spec message and updates the write side * cipher state so that future messages use the just-negotiated spec. */ void sendChangeCipherSpec(Finished mesg, boolean lastMessage) throws IOException { output.flush(); // i.e. handshake data /* * The write cipher state is protected by the connection write lock * so we must grab it while making the change. We also * make sure no writes occur between sending the ChangeCipherSpec * message, installing the new cipher state, and sending the * Finished message. * * We already hold SSLEngine/SSLSocket "this" by virtue * of this being called from the readRecord code. */ OutputRecord r; if (conn != null) { r = new OutputRecord(Record.ct_change_cipher_spec); } else { r = new EngineOutputRecord(Record.ct_change_cipher_spec, engine); } r.setVersion(protocolVersion); r.write(1); // single byte of data if (conn != null) { conn.writeLock.lock(); try { conn.writeRecord(r); conn.changeWriteCiphers(); if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } mesg.write(output); output.flush(); } finally { conn.writeLock.unlock(); } } else { synchronized (engine.writeLock) { engine.writeRecord((EngineOutputRecord) r); engine.changeWriteCiphers(); if (debug != null && Debug.isOn("handshake")) { mesg.print(System.out); } mesg.write(output); if (lastMessage) { output.setFinishedMsg(); } output.flush(); } } }
/* * Used to kickstart the negotiation ... either writing a * ClientHello or a HelloRequest as appropriate, whichever * the subclass returns. NOP if handshaking's already started. */ void kickstart() throws IOException { if (state >= 0) { return; } HandshakeMessage m = getKickstartMessage(); if (debug != null && Debug.isOn("handshake")) { m.print(System.out); } m.write(output); output.flush(); state = m.messageType(); }