/** * Resets the socket timeout to the configured socketTimeout. Does nothing if currently not * connected. * * @throws SQLException If the timeout value cannot be changed */ public final void resetSocketTimeout() throws SQLException { if (isConnected()) { try { final int soTimeout = attachProperties.getSoTimeout(); final int desiredTimeout = soTimeout != -1 ? soTimeout : 0; if (socket.getSoTimeout() != desiredTimeout) { socket.setSoTimeout(desiredTimeout); } } catch (SocketException e) { // TODO Add SQLState throw new SQLException("Unable to change socket timeout (SO_TIMEOUT)", e); } } }
/** * 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; } }
/** * Establishes the TCP/IP connection to serverName and portNumber of this Connection * * @throws SQLTimeoutException If the connection cannot be established within the connect timeout * (either explicitly set or implied by the OS timeout of the socket) * @throws SQLException If the connection cannot be established. */ public final void socketConnect() throws SQLException { try { socket = new Socket(); socket.setTcpNoDelay(true); final int connectTimeout = attachProperties.getConnectTimeout(); final int socketConnectTimeout; if (connectTimeout != -1) { // connectTimeout is in seconds, need milliseconds socketConnectTimeout = (int) TimeUnit.SECONDS.toMillis(connectTimeout); // Blocking timeout initially identical to connect timeout socket.setSoTimeout(socketConnectTimeout); } else { // socket connect timeout is not set, so indefinite (0) socketConnectTimeout = 0; // Blocking timeout to normal socket timeout, 0 if not set socket.setSoTimeout(Math.max(attachProperties.getSoTimeout(), 0)); } final int socketBufferSize = attachProperties.getSocketBufferSize(); if (socketBufferSize != IConnectionProperties.DEFAULT_SOCKET_BUFFER_SIZE) { socket.setReceiveBufferSize(socketBufferSize); socket.setSendBufferSize(socketBufferSize); } socket.connect(new InetSocketAddress(getServerName(), getPortNumber()), socketConnectTimeout); } 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(); } }
/** * Writes directly to the {@code OutputStream} of the underlying socket. * * @param data Data to write * @throws IOException If there is no socket, the socket is closed, or for errors writing to the * socket. */ public final void writeDirect(byte[] data) throws IOException { if (!isConnected()) throw new SocketException("Socket closed"); final OutputStream outputStream = socket.getOutputStream(); outputStream.write(data); outputStream.flush(); }
/** * 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(); } }
public final boolean isConnected() { return !(socket == null || socket.isClosed()); }