static int redisSetBlocking(redisContext *c, int fd, int blocking) { int flags; /* Set the socket nonblocking. * Note that fcntl(2) for F_GETFL and F_SETFL can't be * interrupted by a signal. */ if ((flags = fcntl(fd, F_GETFL)) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "fcntl(F_GETFL): %s", strerror(errno))); close(fd); return REDIS_ERR; } if (blocking) flags &= ~O_NONBLOCK; else flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "fcntl(F_SETFL): %s", strerror(errno))); close(fd); return REDIS_ERR; } 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; }
int redisKeepAlive(redisContext *c,int interval) { int val = 1; int fd = c->fd; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } val = interval; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } val = interval/3; if (val == 0) val = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } val = 3; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } 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]; #ifdef _WIN32 int nread = recv((SOCKET)c->fd,buf,sizeof(buf),0); if (nread == -1) { errno = WSAGetLastError(); if ((errno == ENOENT) || (errno == WSAEWOULDBLOCK)) errno = EAGAIN; } #else int nread = read(c->fd,buf,sizeof(buf)); #endif 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 { __redisCreateReplyReader(c); redisReplyReaderFeed(c->reader,buf,nread); } 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 FASTOREDIS if(c->channel){ nwritten = libssh2_channel_write(c->channel, c->obuf, sdslen(c->obuf)); } else{ #ifdef OS_WIN nwritten = send(c->fd,c->obuf,sdslen(c->obuf),0); #else nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); #endif } if (nwritten == -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 (nwritten > 0) { if (nwritten == (signed)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); } else { sdsrange(c->obuf,nwritten,-1); } } #else nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); if (nwritten == -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 (nwritten > 0) { if (nwritten == (signed)sdslen(c->obuf)) { sdsfree(c->obuf); c->obuf = sdsempty(); } else { sdsrange(c->obuf,nwritten,-1); } } #endif } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; }
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) { int s, rv; char _port[6]; /* strlen("65535"); */ struct addrinfo hints, *servinfo, *p; int blocking = (c->flags & REDIS_BLOCK); snprintf(_port, 6, "%d", port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); return REDIS_ERR; } for (p = servinfo; p != NULL; p = p->ai_next) { if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1) continue; if (redisSetBlocking(c,s,0) != REDIS_OK) goto error; if (connect(s,p->ai_addr,p->ai_addrlen) == -1) { SETERRNO; if (errno == EHOSTUNREACH) { close(s); continue; } else if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else { if (redisContextWaitReady(c,s,timeout) != REDIS_OK) goto error; } } if (blocking && redisSetBlocking(c,s,1) != REDIS_OK) goto error; if (redisSetTcpNoDelay(c,s) != REDIS_OK) goto error; c->fd = s; c->flags |= REDIS_CONNECTED; rv = REDIS_OK; goto end; } if (p == NULL) { char buf[128]; snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno)); __redisSetError(c,REDIS_ERR_OTHER,buf); goto error; } error: rv = REDIS_ERR; end: freeaddrinfo(servinfo); return rv; // Need to return REDIS_OK if alright }
static int redisContextWaitReady(redisContext *c, int fd, const struct timeval *timeout) { struct timeval to; struct timeval *toptr = NULL; fd_set wfd; int err; socklen_t errlen; /* Only use timeout when not NULL. */ if (timeout != NULL) { to = *timeout; toptr = &to; } if (errno == EINPROGRESS) { FD_ZERO(&wfd); FD_SET(fd, &wfd); if (select(FD_SETSIZE, NULL, &wfd, NULL, toptr) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "select(2): %s", strerror(errno))); close(fd); return REDIS_ERR; } if (!FD_ISSET(fd, &wfd)) { errno = ETIMEDOUT; __redisSetError(c,REDIS_ERR_IO,NULL); close(fd); return REDIS_ERR; } err = 0; errlen = sizeof(err); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "getsockopt(SO_ERROR): %s", strerror(errno))); close(fd); return REDIS_ERR; } if (err) { errno = err; __redisSetError(c,REDIS_ERR_IO,NULL); close(fd); return REDIS_ERR; } return REDIS_OK; } __redisSetError(c,REDIS_ERR_IO,NULL); close(fd); return REDIS_ERR; }
int redisContextSetTimeout(redisContext *c, struct timeval tv) { if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "setsockopt(SO_RCVTIMEO): %s", strerror(errno))); return REDIS_ERR; } if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "setsockopt(SO_SNDTIMEO): %s", strerror(errno))); return REDIS_ERR; } 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[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; }
static int redisCreateSocket(redisContext *c, int type) { int s, on = 1; if ((s = socket(type, SOCK_STREAM, 0)) == -1) { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } if (type == AF_INET) { if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { __redisSetError(c,REDIS_ERR_IO,NULL); close(s); return REDIS_ERR; } } return s; }
int redisReconnect(redisContext *c) { c->err = 0; memset(c->errstr, '\0', strlen(c->errstr)); if (c->fd > 0) { close(c->fd); } sdsfree(c->obuf); redisReaderFree(c->reader); c->obuf = sdsempty(); c->reader = redisReaderCreate(); if (c->connection_type == REDIS_CONN_TCP) { return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port, c->timeout, c->tcp.source_addr); } else if (c->connection_type == REDIS_CONN_UNIX) { return redisContextConnectUnix(c, c->unix_sock.path, c->timeout); } else { /* Something bad happened here and shouldn't have. There isn't enough information in the context to reconnect. */ __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect"); } return REDIS_ERR; }
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) { (void) timeout; __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(),"Unix sockets are not suported on Windows platform. (%s)\n", path)); return REDIS_ERR; }
/* 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 redisContextConnectUnix(redisContext *c, const char *path) { int s; int blocking = (c->flags & REDIS_BLOCK); struct sockaddr_un sa; if ((s = redisCreateSocket(c,AF_LOCAL)) == REDIS_ERR) return REDIS_ERR; if (!blocking && redisSetNonBlock(c,s) != REDIS_OK) return REDIS_ERR; sa.sun_family = AF_LOCAL; strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); close(s); return REDIS_ERR; } } c->fd = s; c->flags |= REDIS_CONNECTED; 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, "wdone" is set to 1 (if given). * * Returns REDIS_ERR if an error occured trying to write and sets * c->error 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) { nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); if (nwritten == -1) { if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) { /* 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; }
/* 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, "wdone" is set to 1 (if given). * * Returns REDIS_ERR if an error occured trying to write and sets * c->error to hold the appropriate error string. */ int redisBufferWrite(redisContext *c, int *done) { int nwritten; if (sdslen(c->obuf) > 0) { #ifdef _WIN32 nwritten = send((SOCKET)c->fd,c->obuf,sdslen(c->obuf),0); if (nwritten == -1) { errno = WSAGetLastError(); if ((errno == ENOENT) || (errno == WSAEWOULDBLOCK)) errno = EAGAIN; } #else nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); #endif if (nwritten == -1) { if (errno == EAGAIN /*&& !(c->flags & REDIS_BLOCK)*/) { /* 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; }
int redisContextConnectTcp(redisContext *c, const char *addr, int port) { int s; int blocking = (c->flags & REDIS_BLOCK); struct sockaddr_in sa; if ((s = redisCreateSocket(c,AF_INET)) == REDIS_ERR) return REDIS_ERR; if (!blocking && redisSetNonBlock(c,s) == REDIS_ERR) return REDIS_ERR; sa.sin_family = AF_INET; sa.sin_port = htons(port); if (inet_aton(addr, &sa.sin_addr) == 0) { struct hostent *he; he = gethostbyname(addr); if (he == NULL) { __redisSetError(c,REDIS_ERR_OTHER, sdscatprintf(sdsempty(),"Can't resolve: %s",addr)); closesocket(c->fd); WSACleanup(); return REDIS_ERR; } memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr)); } if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (WSAGetLastError() == WSAEINPROGRESS && !blocking) { /* This is ok. */ } else { __redisSetError(c,REDIS_ERR_IO,NULL); closesocket(c->fd); WSACleanup(); return REDIS_ERR; } } if (redisSetTcpNoDelay(c,s) != REDIS_OK) { closesocket(c->fd); WSACleanup(); return REDIS_ERR; } c->fd = s; c->flags |= REDIS_CONNECTED; return REDIS_OK; }
int redisSslRead(redisContext *c, char *buf, size_t bufcap) { int nread = SSL_read(c->ssl->ssl, buf, bufcap); if (nread > 0) { return nread; } else if (nread == 0) { __redisSetError(c, REDIS_ERR_EOF, "Server closed the connection"); return -1; } else { int err = SSL_get_error(c->ssl->ssl, nread); if (maybeCheckWant(c->ssl, err)) { return 0; } else { __redisSetError(c, REDIS_ERR_IO, NULL); return -1; } } }
static int redisSetTcpNoDelay(redisContext *c, int fd) { int yes = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(errno))); return REDIS_ERR; } 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) { __redisCreateReplyReader(c); if (redisReplyReaderGetReply(c->reader,reply) == REDIS_ERR) { __redisSetError(c,REDIS_ERR_PROTOCOL, sdsnew(((redisReader*)c->reader)->error)); return REDIS_ERR; } return REDIS_OK; }
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { char buf[128]; size_t len = 0; if (prefix != NULL) len = snprintf(buf,sizeof(buf),"%s: ",prefix); strerror_r(errno,buf+len,sizeof(buf)-len); __redisSetError(c,type,buf); }
/* 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; }
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) { int errorno = errno; /* snprintf() may change errno */ char buf[128] = { 0 }; size_t len = 0; if (prefix != NULL) len = snprintf(buf,sizeof(buf),"%s: ",prefix); __redis_strerror_r(errorno, (char *)(buf + len), sizeof(buf) - len); __redisSetError(c,type,buf); }
/* Helper function for the redisAppendCommand* family of functions. *追加到obuf中 * 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; }
int redisKeepAlive(redisContext *c, int interval) { int val = 1; int fd = c->fd; if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){ __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } val = interval; #ifdef _OSX if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) { __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } #else #if defined(__GLIBC__) && !defined(__FreeBSD_kernel__) val = interval; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) { __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } val = interval/3; if (val == 0) val = 1; if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) { __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); return REDIS_ERR; } val = 3; setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)); //if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) { // __redisSetError(c,REDIS_ERR_OTHER,strerror(errno)); // return REDIS_ERR; //} #endif #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 = 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, sdsnew("Server closed the connection")); return REDIS_ERR; } else { __redisCreateReplyReader(c); redisReplyReaderFeed(c->reader,buf,nread); } 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) { if( c->ssl.ssl ) { nwritten = SSL_write( c->ssl.ssl, c->obuf, sdslen(c->obuf)); } else { nwritten = write(c->fd,c->obuf,sdslen(c->obuf)); } if (nwritten == -1) { if( c->ssl.ssl ) { int errorCode = SSL_get_error( c->ssl.ssl, nwritten ); if( ( SSL_ERROR_WANT_READ != errorCode && SSL_ERROR_WANT_WRITE != errorCode) || ( SSL_ERROR_ZERO_RETURN == errorCode ) ) { __redisSetError(c,REDIS_ERR_IO,NULL); return REDIS_ERR; } } if ((errno == EAGAIN && !(c->flags & REDIS_BLOCK)) || (errno == EINTR)) { /* 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 { sdsrange(c->obuf,nwritten,-1); } } } if (done != NULL) *done = (sdslen(c->obuf) == 0); return REDIS_OK; }
static int redisSetTcpNoDelay(redisContext *c, int fd) { SOCKET s = fd; BOOL yes = TRUE; if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&yes, sizeof(BOOL)) == SOCKET_ERROR) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(WSAGetLastError()))); return REDIS_ERR; } return REDIS_OK; }
static int redisCreateSocket(redisContext *c, int type) { SOCKET s; WSADATA wsa_data; int res; res = WSAStartup(MAKEWORD(2,2), &wsa_data); if (res != NO_ERROR) { __redisSetError(c,REDIS_ERR_IO,"Error at WSAStartup()\n"); return REDIS_ERR; } s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { __redisSetError(c,REDIS_ERR_IO, sdscatprintf(sdsempty(), "Error at socket(): %ld\n", WSAGetLastError())); WSACleanup(); return REDIS_ERR; } return s; }
int redisvAppendCommand(redisContext *c, const char *format, va_list ap) { char *cmd; int len; len = redisvFormatCommand(&cmd,format,ap); if (len == -1) { __redisSetError(c,REDIS_ERR_OOM,"Out of memory"); return REDIS_ERR; } else if (len == -2) { __redisSetError(c,REDIS_ERR_OTHER,"Invalid format string"); return REDIS_ERR; } if (__redisAppendCommand(c,cmd,len) != REDIS_OK) { free(cmd); return REDIS_ERR; } free(cmd); return REDIS_OK; }