private PGStream enableSSL(PGStream pgStream, boolean requireSSL, Properties info, Logger logger)
      throws IOException, SQLException {
    if (logger.logDebug()) logger.debug(" FE=> SSLRequest");

    // Send SSL request packet
    pgStream.SendInteger4(8);
    pgStream.SendInteger2(1234);
    pgStream.SendInteger2(5679);
    pgStream.flush();

    // Now get the response from the backend, one of N, E, S.
    int beresp = pgStream.ReceiveChar();
    switch (beresp) {
      case 'E':
        if (logger.logDebug()) logger.debug(" <=BE SSLError");

        // Server doesn't even know about the SSL handshake protocol
        if (requireSSL)
          throw new PSQLException(
              GT.tr("The server does not support SSL."), PSQLState.CONNECTION_FAILURE);

        // We have to reconnect to continue.
        pgStream.close();
        return new PGStream(pgStream.getHost(), pgStream.getPort());

      case 'N':
        if (logger.logDebug()) logger.debug(" <=BE SSLRefused");

        // Server does not support ssl
        if (requireSSL)
          throw new PSQLException(
              GT.tr("The server does not support SSL."), PSQLState.CONNECTION_FAILURE);

        return pgStream;

      case 'S':
        if (logger.logDebug()) logger.debug(" <=BE SSLOk");

        // Server supports ssl
        Driver.makeSSL(pgStream, info, logger);
        return pgStream;

      default:
        throw new PSQLException(
            GT.tr("An error occured while setting up the SSL connection."),
            PSQLState.CONNECTION_FAILURE);
    }
  }
  private void sendStartupPacket(PGStream pgStream, String[][] params, Logger logger)
      throws IOException {
    if (logger.logDebug()) {
      String details = "";
      for (int i = 0; i < params.length; ++i) {
        if (i != 0) details += ", ";
        details += params[i][0] + "=" + params[i][1];
      }
      logger.debug(" FE=> StartupPacket(" + details + ")");
    }

    /*
     * Precalculate message length and encode params.
     */
    int length = 4 + 4;
    byte[][] encodedParams = new byte[params.length * 2][];
    for (int i = 0; i < params.length; ++i) {
      encodedParams[i * 2] = params[i][0].getBytes("US-ASCII");
      encodedParams[i * 2 + 1] = params[i][1].getBytes("US-ASCII");
      length += encodedParams[i * 2].length + 1 + encodedParams[i * 2 + 1].length + 1;
    }

    length += 1; // Terminating \0

    /*
     * Send the startup message.
     */
    pgStream.SendInteger4(length);
    pgStream.SendInteger2(3); // protocol major
    pgStream.SendInteger2(0); // protocol minor
    for (int i = 0; i < encodedParams.length; ++i) {
      pgStream.Send(encodedParams[i]);
      pgStream.SendChar(0);
    }

    pgStream.SendChar(0);
    pgStream.flush();
  }