You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It works fine on small responses. But when response is pretty large (say 100K+) the client returns error:
failed to read searchd response (status=0, ver=256, len=112460, read=24608)
If I reduce response size (by lowering the LIMIT or number of fields returned) it works.
Via Wireshark I see that manticore returns whole response. But client interrupts the connection.
I looked through the client code and found out that reading from socket is implemented with single call to Conn.Read(). It returns data read. If response is large it reads part of the response and returns size of that part. Further in code there is a comparison of data expected and data read. They're not equal. Hence, client returns error. link to code
Googling over the internet I found that it's not the right way to read from socket. E.g. look through this article.
I tried to implement reading by chunks and it worked:
diff --git a/manticore/client.go b/manticore/client.go
index bf9f3e6..315579e 100644
--- a/manticore/client.go+++ b/manticore/client.go@@ -135,6 +135,34 @@ func (cl *Client) connect() error {
return cl.failclose(err)
}
+/// read raw answer (with fixed size) to buf+func (cl *Client) readRawAnswer(buf []byte, size int) (int, error) {+ const MAX_CHUNK_SIZE = 16 * 1024+ nbytes := 0+ for {+ chunkSize := MAX_CHUNK_SIZE+ bytesRemaining := size - nbytes+ if bytesRemaining < chunkSize {+ chunkSize = bytesRemaining+ }+ n, e := cl.conn.Read(buf[nbytes:nbytes+chunkSize])+ if e != nil {+ return n, e+ }+ nbytes += n+ if (nbytes < size) {+ continue+ }+ break+ }++ if (nbytes > size) {+ return nbytes, errors.New("Logical error in Client.read()!")+ }++ return nbytes, nil+}+
/// get and check response packet from searchd server
func (cl *Client) getResponse(client_ver uCommandVersion) (apibuf, error) {
rawrecv := cl.getByteBuf(8)
@@ -151,7 +179,7 @@ func (cl *Client) getResponse(client_ver uCommandVersion) (apibuf, error) {
iReplySize := rawrecv.getInt()
rawanswer := cl.getByteBuf(iReplySize)
- nbytes, err = cl.conn.Read(*rawanswer)+ nbytes, err = cl.readRawAnswer(*rawanswer, iReplySize)
if err != nil {
return nil, err
}
I'm not sure that it is correct go-idiomatic solution because I'm not a go-developer. But I hope it helps to make a proper fix.
The text was updated successfully, but these errors were encountered:
I try running this simple code:
It works fine on small responses. But when response is pretty large (say 100K+) the client returns error:
If I reduce response size (by lowering the LIMIT or number of fields returned) it works.
Via Wireshark I see that manticore returns whole response. But client interrupts the connection.
I looked through the client code and found out that reading from socket is implemented with single call to
Conn.Read()
. It returns data read. If response is large it reads part of the response and returns size of that part. Further in code there is a comparison of data expected and data read. They're not equal. Hence, client returns error. link to codeGoogling over the internet I found that it's not the right way to read from socket. E.g. look through this article.
I tried to implement reading by chunks and it worked:
I'm not sure that it is correct go-idiomatic solution because I'm not a go-developer. But I hope it helps to make a proper fix.
The text was updated successfully, but these errors were encountered: