Returns 1 or 0 for success/failure. */
| 174 | |
| 175 | /* Returns 1 or 0 for success/failure. */ |
| 176 | static size_t rioConnRead(rio *r, void *buf, size_t len) { |
| 177 | size_t avail = sdslen(r->io.conn.buf)-r->io.conn.pos; |
| 178 | |
| 179 | /* If the buffer is too small for the entire request: realloc. */ |
| 180 | if (sdslen(r->io.conn.buf) + sdsavail(r->io.conn.buf) < len) |
| 181 | r->io.conn.buf = sdsMakeRoomFor(r->io.conn.buf, len - sdslen(r->io.conn.buf)); |
| 182 | |
| 183 | /* If the remaining unused buffer is not large enough: memmove so that we |
| 184 | * can read the rest. */ |
| 185 | if (len > avail && sdsavail(r->io.conn.buf) < len - avail) { |
| 186 | sdsrange(r->io.conn.buf, r->io.conn.pos, -1); |
| 187 | r->io.conn.pos = 0; |
| 188 | } |
| 189 | |
| 190 | /* If we don't already have all the data in the sds, read more */ |
| 191 | while (len > sdslen(r->io.conn.buf) - r->io.conn.pos) { |
| 192 | size_t buffered = sdslen(r->io.conn.buf) - r->io.conn.pos; |
| 193 | size_t needs = len - buffered; |
| 194 | /* Read either what's missing, or PROTO_IOBUF_LEN, the bigger of |
| 195 | * the two. */ |
| 196 | size_t toread = needs < PROTO_IOBUF_LEN ? PROTO_IOBUF_LEN: needs; |
| 197 | if (toread > sdsavail(r->io.conn.buf)) toread = sdsavail(r->io.conn.buf); |
| 198 | if (r->io.conn.read_limit != 0 && |
| 199 | r->io.conn.read_so_far + buffered + toread > r->io.conn.read_limit) |
| 200 | { |
| 201 | /* Make sure the caller didn't request to read past the limit. |
| 202 | * If they didn't we'll buffer till the limit, if they did, we'll |
| 203 | * return an error. */ |
| 204 | if (r->io.conn.read_limit >= r->io.conn.read_so_far + len) |
| 205 | toread = r->io.conn.read_limit - r->io.conn.read_so_far - buffered; |
| 206 | else { |
| 207 | errno = EOVERFLOW; |
| 208 | return 0; |
| 209 | } |
| 210 | } |
| 211 | int retval = connRead(r->io.conn.conn, |
| 212 | (char*)r->io.conn.buf + sdslen(r->io.conn.buf), |
| 213 | toread); |
| 214 | if (retval <= 0) { |
| 215 | if (errno == EWOULDBLOCK) errno = ETIMEDOUT; |
| 216 | return 0; |
| 217 | } |
| 218 | sdsIncrLen(r->io.conn.buf, retval); |
| 219 | } |
| 220 | |
| 221 | memcpy(buf, (char*)r->io.conn.buf + r->io.conn.pos, len); |
| 222 | r->io.conn.read_so_far += len; |
| 223 | r->io.conn.pos += len; |
| 224 | return len; |
| 225 | } |
| 226 | |
| 227 | /* Returns read/write position in file. */ |
| 228 | static off_t rioConnTell(rio *r) { |
nothing calls this directly
no test coverage detected