/** Internal method. Connect to searchd, send request, get response as DataInputStream. */ private DataInputStream _DoRequest(int command, int version, ByteArrayOutputStream req) { /* connect */ Socket sock = _Connect(); if (sock == null) return null; /* send request */ byte[] reqBytes = req.toByteArray(); try { DataOutputStream sockDS = new DataOutputStream(sock.getOutputStream()); sockDS.writeShort(command); sockDS.writeShort(version); sockDS.writeInt(reqBytes.length); sockDS.write(reqBytes); } catch (Exception e) { _error = "network error: " + e; _connerror = true; return null; } /* get response */ byte[] response = _GetResponse(sock); if (response == null) return null; /* spawn that tampon */ return new DataInputStream(new ByteArrayInputStream(response)); }
/** Internal method. Connect to searchd and exchange versions. */ private Socket _Connect() { if (_socket != null) return _socket; _connerror = false; Socket sock = null; try { sock = new Socket(); sock.setSoTimeout(_timeout); InetSocketAddress addr = new InetSocketAddress(_host, _port); sock.connect(addr, _timeout); DataInputStream sIn = new DataInputStream(sock.getInputStream()); int version = sIn.readInt(); if (version < 1) { sock.close(); _error = "expected searchd protocol version 1+, got version " + version; return null; } DataOutputStream sOut = new DataOutputStream(sock.getOutputStream()); sOut.writeInt(VER_MAJOR_PROTO); } catch (IOException e) { _error = "connection to " + _host + ":" + _port + " failed: " + e; _connerror = true; try { if (sock != null) sock.close(); } catch (IOException e1) { } return null; } return sock; }
/** Close existing persistent connection. */ public boolean Close() { if (_socket == null) { _error = "not connected"; return false; } try { _socket.close(); } catch (IOException e) { } _socket = null; return true; }
/** Open persistent connection to searchd. */ public boolean Open() { if (_socket != null) { _error = "already connected"; return false; } Socket sock = _Connect(); if (sock == null) return false; // command, command version = 0, body length = 4, body = 1 try { DataOutputStream sOut = new DataOutputStream(sock.getOutputStream()); sOut.writeShort(SEARCHD_COMMAND_PERSIST); sOut.writeShort(0); sOut.writeInt(4); sOut.writeInt(1); } catch (IOException e) { _error = "network error: " + e; _connerror = true; } _socket = sock; return true; }
/** Internal method. Get and check response packet from searchd. */ private byte[] _GetResponse(Socket sock) { /* connect */ DataInputStream sIn = null; InputStream SockInput = null; try { SockInput = sock.getInputStream(); sIn = new DataInputStream(SockInput); } catch (IOException e) { _error = "getInputStream() failed: " + e; return null; } /* read response */ byte[] response = null; short status = 0, ver = 0; int len = 0; try { /* read status fields */ status = sIn.readShort(); ver = sIn.readShort(); len = sIn.readInt(); /* read response if non-empty */ if (len <= 0) { _error = "invalid response packet size (len=" + len + ")"; return null; } response = new byte[len]; sIn.readFully(response, 0, len); /* check status */ if (status == SEARCHD_WARNING) { DataInputStream in = new DataInputStream(new ByteArrayInputStream(response)); int iWarnLen = in.readInt(); _warning = new String(response, 4, iWarnLen); System.arraycopy(response, 4 + iWarnLen, response, 0, response.length - 4 - iWarnLen); } else if (status == SEARCHD_ERROR) { _error = "searchd error: " + new String(response, 4, response.length - 4); return null; } else if (status == SEARCHD_RETRY) { _error = "temporary searchd error: " + new String(response, 4, response.length - 4); return null; } else if (status != SEARCHD_OK) { _error = "searched returned unknown status, code=" + status; return null; } } catch (IOException e) { if (len != 0) { /* get trace, to provide even more failure details */ PrintWriter ew = new PrintWriter(new StringWriter()); e.printStackTrace(ew); ew.flush(); ew.close(); String sTrace = ew.toString(); /* build error message */ _error = "failed to read searchd response (status=" + status + ", ver=" + ver + ", len=" + len + ", trace=" + sTrace + ")"; } else { _error = "received zero-sized searchd response (searchd crashed?): " + e.getMessage(); } return null; } finally { if (_socket == null) { try { if (sIn != null) sIn.close(); if (sock != null && !sock.isConnected()) sock.close(); } catch (IOException e) { /* silently ignore close failures; nothing could be done anyway */ } } } return response; }