/** * Reads the next operation code. Skips all {@link * org.firebirdsql.gds.impl.wire.WireProtocolConstants#op_dummy} codes received. * * @return Operation code * @throws IOException if an error occurs while reading from the underlying InputStream */ public final int readNextOperation() throws IOException { int op; do { op = xdrIn.readInt(); } while (op == op_dummy); return op; }
/** * Closes the TCP/IP connection. This is not a normal detach operation. * * @throws IOException if closing fails */ public final void close() throws IOException { IOException ioex = null; try { if (socket != null) { try { if (xdrOut != null) xdrOut.close(); } catch (IOException ex) { ioex = ex; } try { if (xdrIn != null) xdrIn.close(); } catch (IOException ex) { if (ioex == null) ioex = ex; } try { socket.close(); } catch (IOException ex) { if (ioex == null) ioex = ex; } if (ioex != null) throw ioex; } } finally { xdrOut = null; xdrIn = null; socket = null; protocols = null; } }
/** * Performs the connection identification phase of the Wire protocol and returns the * FbWireDatabase implementation for the agreed protocol. * * @return FbWireDatabase * @throws SQLTimeoutException * @throws SQLException */ @Override public final C identify() throws SQLException { try { xdrIn = new XdrInputStream(socket.getInputStream()); xdrOut = new XdrOutputStream(socket.getOutputStream()); // Here we identify the user to the engine. // This may or may not be used as login info to a database. final byte[] userBytes = getSystemUserName().getBytes(); final byte[] hostBytes = getSystemHostName().getBytes(); ByteArrayOutputStream userId = new ByteArrayOutputStream(); userId.write(CNCT_user); int userLength = Math.min(userBytes.length, 255); userId.write(userLength); userId.write(userBytes, 0, userLength); userId.write(CNCT_host); int hostLength = Math.min(hostBytes.length, 255); userId.write(hostLength); userId.write(hostBytes, 0, hostLength); userId.write(CNCT_user_verification); userId.write(0); xdrOut.writeInt(op_connect); xdrOut.writeInt(op_attach); xdrOut.writeInt(CONNECT_VERSION2); xdrOut.writeInt(arch_generic); xdrOut.writeString(getAttachObjectName(), getEncoding()); xdrOut.writeInt(protocols.getProtocolCount()); // Count of protocols understood xdrOut.writeBuffer(userId.toByteArray()); for (ProtocolDescriptor protocol : protocols) { xdrOut.writeInt(protocol.getVersion()); // Protocol version xdrOut.writeInt(protocol.getArchitecture()); // Architecture of client xdrOut.writeInt(protocol.getMinimumType()); // Minimum type xdrOut.writeInt(protocol.getMaximumType()); // Maximum type xdrOut.writeInt(protocol.getWeight()); // Preference weight } xdrOut.flush(); if (readNextOperation() == op_accept) { protocolVersion = xdrIn.readInt(); // Protocol version protocolArchitecture = xdrIn.readInt(); // Architecture for protocol protocolMinimumType = xdrIn.readInt(); // Minimum type if (protocolVersion < 0) { protocolVersion = (protocolVersion & FB_PROTOCOL_MASK) | FB_PROTOCOL_FLAG; } ProtocolDescriptor descriptor = protocols.getProtocolDescriptor(protocolVersion); if (descriptor == null) { throw new SQLException( String.format( "Unsupported or unexpected protocol version %d connecting to database %s. Supported version(s): %s", protocolVersion, getServerName(), protocols.getProtocolVersions())); } return createConnectionHandle(descriptor); } else { try { close(); } catch (Exception ex) { log.debug("Ignoring exception on disconnect in connect phase of protocol", ex); } throw new FbExceptionBuilder().exception(ISCConstants.isc_connect_reject).toSQLException(); } } catch (SocketTimeoutException ste) { throw new FbExceptionBuilder() .timeoutException(ISCConstants.isc_network_error) .messageParameter(getServerName()) .cause(ste) .toSQLException(); } catch (IOException ioex) { throw new FbExceptionBuilder() .exception(ISCConstants.isc_network_error) .messageParameter(getServerName()) .cause(ioex) .toSQLException(); } }