/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[1024*16]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; #ifdef FASTOREDIS if(c->channel){ nread = libssh2_channel_read(c->channel, buf, sizeof(buf)); } else{ #ifdef OS_WIN nread = recv(c->fd,buf,sizeof(buf),0); #else nread = read(c->fd,buf,sizeof(buf)); #endif } if (nread == -1) { if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == F_EINTR)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } #else nread = read(c->fd,buf,sizeof(buf)); if (nread == -1) { if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } #endif return REDIS_OK; }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[2048]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; nread = read(c->fd,buf,sizeof(buf)); if (nread == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; }
void RedisClient::Response::feed(const QByteArray& buffer) { m_responseSource.append(buffer); if (redisReaderFeed(m_redisReader.data(), buffer.constData(), buffer.size()) == REDIS_ERR) { qDebug() << "hiredis cannot feed buffer"; } }
static VALUE reader_feed(VALUE klass, VALUE str) { redisReader *reader; if (TYPE(str) != T_STRING) rb_raise(rb_eTypeError, "not a string"); Data_Get_Struct(klass, redisReader, reader); redisReaderFeed(reader,RSTRING_PTR(str),(size_t)RSTRING_LEN(str)); return INT2NUM(0); }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[1024*16]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; if( c->ssl.ssl ) { nread = SSL_read( c->ssl.ssl, buf, sizeof(buf)); if( nread < 0 ) { int errorCode = SSL_get_error( c->ssl.ssl, nread ); if( SSL_ERROR_WANT_READ == errorCode || SSL_ERROR_WANT_WRITE == errorCode) { return REDIS_OK; } else if( SSL_ERROR_ZERO_RETURN == errorCode ) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { char error[65535]; ERR_error_string_n(ERR_get_error(), error, 65535); __redisSetError(c,REDIS_ERR_IO,error); return REDIS_ERR; } } } else { nread = read(c->fd,buf,sizeof(buf)); } if (nread == -1) { if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; }
/* Use this function if the caller has already read the data. It will * feed bytes to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferReadDone(redisContext *c, char *buf, int nread) { if (nread == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF, sdsnew("Server closed the connection")); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; }
bool parse_redis_protocol(struct request *req) { int ret; void *reply; redisReader *reader; if(strncmp(req->buf, "$-1", 3) == 0) { lua_pushboolean(req->vm, false); return true; } else if(strncmp(req->buf, "+OK", 3) == 0) { lua_pushboolean(req->vm, true); return true; } reader = redisReaderCreate(); DEBUG_PRINT("req->buf=%s\r\n", req->buf); redisReaderFeed(reader, req->buf, sdslen(req->buf)); ret = redisReaderGetReply(reader,&reply); if (ret == REDIS_ERR) { freeReplyObject(reply); redisReaderFree(reader); return false; } push_reply(req->vm, (redisReply*)reply); //printf("%s\r\n", ((redisReply*)reply)->str); freeReplyObject(reply); redisReaderFree(reader); return true; }
static void test_reply_reader(void) { redisReader *reader; void *reply; int ret; int i; test("Error handling in reply parser: "); reader = redisReaderCreate(); redisReaderFeed(reader,(char*)"@foo\r\n",6); ret = redisReaderGetReply(reader,NULL); test_cond(ret == REDIS_ERR && strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); redisReaderFree(reader); /* when the reply already contains multiple items, they must be free'd * on an error. valgrind will bark when this doesn't happen. */ test("Memory cleanup in reply parser: "); reader = redisReaderCreate(); redisReaderFeed(reader,(char*)"*2\r\n",4); redisReaderFeed(reader,(char*)"$5\r\nhello\r\n",11); redisReaderFeed(reader,(char*)"@foo\r\n",6); ret = redisReaderGetReply(reader,NULL); test_cond(ret == REDIS_ERR && strcasecmp(reader->errstr,"Protocol error, got \"@\" as reply type byte") == 0); redisReaderFree(reader); test("Set error on nested multi bulks with depth > 7: "); reader = redisReaderCreate(); for (i = 0; i < 9; i++) { redisReaderFeed(reader,(char*)"*1\r\n",4); } ret = redisReaderGetReply(reader,NULL); test_cond(ret == REDIS_ERR && strncasecmp(reader->errstr,"No support for",14) == 0); redisReaderFree(reader); test("Works with NULL functions for reply: "); reader = redisReaderCreate(); reader->fn = NULL; redisReaderFeed(reader,(char*)"+OK\r\n",5); ret = redisReaderGetReply(reader,&reply); test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); redisReaderFree(reader); test("Works when a single newline (\\r\\n) covers two calls to feed: "); reader = redisReaderCreate(); reader->fn = NULL; redisReaderFeed(reader,(char*)"+OK\r",4); ret = redisReaderGetReply(reader,&reply); assert(ret == REDIS_OK && reply == NULL); redisReaderFeed(reader,(char*)"\n",1); ret = redisReaderGetReply(reader,&reply); test_cond(ret == REDIS_OK && reply == (void*)REDIS_REPLY_STATUS); redisReaderFree(reader); test("Don't reset state after protocol error: "); reader = redisReaderCreate(); reader->fn = NULL; redisReaderFeed(reader,(char*)"x",1); ret = redisReaderGetReply(reader,&reply); assert(ret == REDIS_ERR); ret = redisReaderGetReply(reader,&reply); test_cond(ret == REDIS_ERR && reply == NULL); redisReaderFree(reader); /* Regression test for issue #45 on GitHub. */ test("Don't do empty allocation for empty multi bulk: "); reader = redisReaderCreate(); redisReaderFeed(reader,(char*)"*0\r\n",4); ret = redisReaderGetReply(reader,&reply); test_cond(ret == REDIS_OK && ((redisReply*)reply)->type == REDIS_REPLY_ARRAY && ((redisReply*)reply)->elements == 0); freeReplyObject(reply); redisReaderFree(reader); }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[1024*16]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; #ifndef HIREDIS_WIN nread = read(c->fd,buf,sizeof(buf)); if (nread == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #else nread = recv(c->fd,buf,sizeof(buf),0); if (nread == -1) { errno = WSAGetLastError(); if ((errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK) && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #endif } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; } /* Write the output buffer to the socket. * * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was * succesfully written to the socket. When the buffer is empty after the * write operation, "done" is set to 1 (if given). * * Returns REDIS_ERR if an error occured trying to write and sets * c->errstr to hold the appropriate error string. */ int redisBufferWrite(redisContext *c, int *done) { int nwritten; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; if (sdslen(c->obuf) > 0) { #ifndef HIREDIS_WIN nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); if (nwritten == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #else nwritten = send(c->fd,c->obuf,sdslen(c->obuf),0); if (nwritten == -1) { errno = WSAGetLastError(); if ((errno == WSAEINPROGRESS || errno == WSAEWOULDBLOCK) && !(c->flags & REDIS_BLOCK)) { /* Try again later */ #endif } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nwritten > 0) { if (nwritten == (signed)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); } else { c->obuf = sdsrange(c->obuf,nwritten,-1); } } } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; } /* Internal helper function to try and get a reply from the reader, * or set an error in the context otherwise. */ int redisGetReplyFromReader(redisContext *c, void **reply) { if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } return REDIS_OK; } int redisGetReply(redisContext *c, void **reply) { int wdone = 0; void *aux = NULL; /* Try to read pending replies */ if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; /* For the blocking context, flush output buffer and read reply */ if (aux == NULL && c->flags & REDIS_BLOCK) { /* Write until done */ do { if (redisBufferWrite(c,&wdone) == REDIS_ERR) return REDIS_ERR; } while (!wdone); /* Read until there is a reply */ do { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; } while (aux == NULL); } /* Set reply object */ if (reply != NULL) *reply = aux; return REDIS_OK; } /* Helper function for the redisAppendCommand* family of functions. * * Write a formatted command to the output buffer. When this family * is used, you need to call redisGetReply yourself to retrieve * the reply (or replies in pub/sub). */ int __redisAppendCommand(redisContext *c, char *cmd, size_t len) { sds newbuf; newbuf = sdscatlen(c->obuf,cmd,len); if (newbuf == NULL) { __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); return REDIS_ERR; } c->obuf = newbuf; return REDIS_OK; }
static void pipeMode(void) { int fd = context->fd; long long errors = 0, replies = 0, obuf_len = 0, obuf_pos = 0; char ibuf[1024*16], obuf[1024*16]; /* Input and output buffers */ char aneterr[ANET_ERR_LEN]; redisReader *reader = redisReaderCreate(); redisReply *reply; int eof = 0; /* True once we consumed all the standard input. */ int done = 0; char magic[20]; /* Special reply we recognize. */ srand(time(NULL)); /* Use non blocking I/O. */ if (anetNonBlock(aneterr,fd) == ANET_ERR) { fprintf(stderr, "Can't set the socket in non blocking mode: %s\n", aneterr); exit(1); } /* Transfer raw protocol and read replies from the server at the same * time. */ while(!done) { int mask = AE_READABLE; if (!eof || obuf_len != 0) mask |= AE_WRITABLE; mask = aeWait(fd,mask,1000); /* Handle the readable state: we can read replies from the server. */ if (mask & AE_READABLE) { ssize_t nread; /* Read from socket and feed the hiredis reader. */ do { nread = read(fd,ibuf,sizeof(ibuf)); if (nread == -1 && errno != EAGAIN && errno != EINTR) { fprintf(stderr, "Error reading from the server: %s\n", strerror(errno)); exit(1); } if (nread > 0) redisReaderFeed(reader,ibuf,nread); } while(nread > 0); /* Consume replies. */ do { if (redisReaderGetReply(reader,(void**)&reply) == REDIS_ERR) { fprintf(stderr, "Error reading replies from server\n"); exit(1); } if (reply) { if (reply->type == REDIS_REPLY_ERROR) { fprintf(stderr,"%s\n", reply->str); errors++; } else if (eof && reply->type == REDIS_REPLY_STRING && reply->len == 20) { /* Check if this is the reply to our final ECHO * command. If so everything was received * from the server. */ if (memcmp(reply->str,magic,20) == 0) { printf("Last reply received from server.\n"); done = 1; replies--; } } replies++; freeReplyObject(reply); } } while(reply); } /* Handle the writable state: we can send protocol to the server. */ if (mask & AE_WRITABLE) { while(1) { /* Transfer current buffer to server. */ if (obuf_len != 0) { ssize_t nwritten = write(fd,obuf+obuf_pos,obuf_len); if (nwritten == -1) { if (errno != EAGAIN && errno != EINTR) { fprintf(stderr, "Error writing to the server: %s\n", strerror(errno)); exit(1); } else { nwritten = 0; } } obuf_len -= nwritten; obuf_pos += nwritten; if (obuf_len != 0) break; /* Can't accept more data. */ } /* If buffer is empty, load from stdin. */ if (obuf_len == 0 && !eof) { ssize_t nread = read(STDIN_FILENO,obuf,sizeof(obuf)); if (nread == 0) { char echo[] = "*2\r\n$4\r\nECHO\r\n$20\r\n01234567890123456789\r\n"; int j; eof = 1; /* Everything transfered, so we queue a special * ECHO command that we can match in the replies * to make sure everything was read from the server. */ for (j = 0; j < 20; j++) magic[j] = rand() & 0xff; memcpy(echo+19,magic,20); memcpy(obuf,echo,sizeof(echo)-1); obuf_len = sizeof(echo)-1; obuf_pos = 0; printf("All data transferred. Waiting for the last reply...\n"); } else if (nread == -1) { fprintf(stderr, "Error reading from stdin: %s\n", strerror(errno)); exit(1); } else { obuf_len = nread; obuf_pos = 0; } } if (obuf_len == 0 && eof) break; } } } redisReaderFree(reader); printf("errors: %lld, replies: %lld\n", errors, replies); if (errors) exit(1); else exit(0); }
/* Use this function to handle a read event on the descriptor. It will try * and read some bytes from the socket and feed them to the reply parser. * * After this function is called, you may use redisContextReadReply to * see if there is a reply available. */ int redisBufferRead(redisContext *c) { char buf[1024*16]; int nread; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; #ifdef WIN32 nread = recv(c->fd,buf,sizeof(buf),0); #else nread = read(c->fd,buf,sizeof(buf)); #endif if (nread == -1) { #ifdef WIN32 errno = WSAGetLastError(); if ((errno == WSAEWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == WSAEINTR)) { #else if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { #endif /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nread == 0) { __redisSetError(c,REDIS_ERR_EOF,"Server closed the connection"); return REDIS_ERR; } else { if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } } return REDIS_OK; } /* Write the output buffer to the socket. * * Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was * succesfully written to the socket. When the buffer is empty after the * write operation, "done" is set to 1 (if given). * * Returns REDIS_ERR if an error occured trying to write and sets * c->errstr to hold the appropriate error string. */ int redisBufferWrite(redisContext *c, int *done) { int nwritten; /* Return early when the context has seen an error. */ if (c->err) return REDIS_ERR; if (sdslen(c->obuf) > 0) { #ifdef WIN32 nwritten = send(c->fd,c->obuf,sdslen(c->obuf),0); #else nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); #endif if (nwritten == -1) { #ifdef WIN32 errno = WSAGetLastError(); if ((errno == WSAEWOULDBLOCK && !(c->flags & REDIS_BLOCK)) || (errno == WSAEINTR)) { #else if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { #endif /* Try again later */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } else if (nwritten > 0) { if (nwritten == (signed)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); } else { c->obuf = sdsrange(c->obuf,nwritten,-1); } } } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; } /* Internal helper function to try and get a reply from the reader, * or set an error in the context otherwise. */ int redisGetReplyFromReader(redisContext *c, void **reply) { if (redisReaderGetReply(c->reader,reply) == REDIS_ERR) { __redisSetError(c,c->reader->err,c->reader->errstr); return REDIS_ERR; } return REDIS_OK; } int redisGetReply(redisContext *c, void **reply) { int wdone = 0; void *aux = NULL; /* Try to read pending replies */ if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; /* For the blocking context, flush output buffer and read reply */ if (aux == NULL && c->flags & REDIS_BLOCK) { /* Write until done */ do { if (redisBufferWrite(c,&wdone) == REDIS_ERR) return REDIS_ERR; } while (!wdone); /* Read until there is a reply */ do { if (redisBufferRead(c) == REDIS_ERR) return REDIS_ERR; if (redisGetReplyFromReader(c,&aux) == REDIS_ERR) return REDIS_ERR; } while (aux == NULL); } /* Set reply object */ if (reply != NULL) *reply = aux; return REDIS_OK; }
void pythonReaderFeed(pythonReader *self, const char *buf, size_t len) { redisReaderFeed(self->reader,buf,len); }