version 1.16, 2019/05/08 20:00:25 |
version 1.17, 2019/05/08 21:30:11 |
|
|
* Returns <0 on failure, 0 if there's no data, >0 if there is. |
* Returns <0 on failure, 0 if there's no data, >0 if there is. |
*/ |
*/ |
int |
int |
io_read_check(struct sess *sess, int fd) |
io_read_check(int fd) |
{ |
{ |
struct pollfd pfd; |
struct pollfd pfd; |
|
|
|
|
* On success, fills in "sz" with the amount written. |
* On success, fills in "sz" with the amount written. |
*/ |
*/ |
static int |
static int |
io_write_nonblocking(struct sess *sess, int fd, const void *buf, size_t bsz, |
io_write_nonblocking(int fd, const void *buf, size_t bsz, |
size_t *sz) |
size_t *sz) |
{ |
{ |
struct pollfd pfd; |
struct pollfd pfd; |
|
|
* Returns 0 on failure, non-zero on success (all bytes written). |
* Returns 0 on failure, non-zero on success (all bytes written). |
*/ |
*/ |
static int |
static int |
io_write_blocking(struct sess *sess, int fd, const void *buf, size_t sz) |
io_write_blocking(int fd, const void *buf, size_t sz) |
{ |
{ |
size_t wsz; |
size_t wsz; |
int c; |
int c; |
|
|
while (sz > 0) { |
while (sz > 0) { |
c = io_write_nonblocking(sess, fd, buf, sz, &wsz); |
c = io_write_nonblocking(fd, buf, sz, &wsz); |
if (!c) { |
if (!c) { |
ERRX1("io_write_nonblocking"); |
ERRX1("io_write_nonblocking"); |
return 0; |
return 0; |
|
|
int c; |
int c; |
|
|
if (!sess->mplex_writes) { |
if (!sess->mplex_writes) { |
c = io_write_blocking(sess, fd, buf, sz); |
c = io_write_blocking(fd, buf, sz); |
sess->total_write += sz; |
sess->total_write += sz; |
return c; |
return c; |
} |
} |
|
|
wsz = sz & 0xFFFFFF; |
wsz = sz & 0xFFFFFF; |
tag = (7 << 24) + wsz; |
tag = (7 << 24) + wsz; |
tagbuf = htole32(tag); |
tagbuf = htole32(tag); |
if (!io_write_blocking(sess, fd, &tagbuf, sizeof(tagbuf))) { |
if (!io_write_blocking(fd, &tagbuf, sizeof(tagbuf))) { |
ERRX1("io_write_blocking"); |
ERRX1("io_write_blocking"); |
return 0; |
return 0; |
} |
} |
if (!io_write_blocking(sess, fd, buf, wsz)) { |
if (!io_write_blocking(fd, buf, wsz)) { |
ERRX1("io_write_blocking"); |
ERRX1("io_write_blocking"); |
return 0; |
return 0; |
} |
} |
|
|
* Returns zero on failure, non-zero on success (zero or more bytes). |
* Returns zero on failure, non-zero on success (zero or more bytes). |
*/ |
*/ |
static int |
static int |
io_read_nonblocking(struct sess *sess, |
io_read_nonblocking(int fd, void *buf, size_t bsz, size_t *sz) |
int fd, void *buf, size_t bsz, size_t *sz) |
|
{ |
{ |
struct pollfd pfd; |
struct pollfd pfd; |
ssize_t rsz; |
ssize_t rsz; |
|
|
* Returns 0 on failure, non-zero on success (all bytes read). |
* Returns 0 on failure, non-zero on success (all bytes read). |
*/ |
*/ |
static int |
static int |
io_read_blocking(struct sess *sess, |
io_read_blocking(int fd, void *buf, size_t sz) |
int fd, void *buf, size_t sz) |
|
{ |
{ |
size_t rsz; |
size_t rsz; |
int c; |
int c; |
|
|
while (sz > 0) { |
while (sz > 0) { |
c = io_read_nonblocking(sess, fd, buf, sz, &rsz); |
c = io_read_nonblocking(fd, buf, sz, &rsz); |
if (!c) { |
if (!c) { |
ERRX1("io_read_nonblocking"); |
ERRX1("io_read_nonblocking"); |
return 0; |
return 0; |
|
|
* for the remaining data size. |
* for the remaining data size. |
*/ |
*/ |
|
|
if (!io_read_blocking(sess, fd, &tagbuf, sizeof(tagbuf))) { |
if (!io_read_blocking(fd, &tagbuf, sizeof(tagbuf))) { |
ERRX1("io_read_blocking"); |
ERRX1("io_read_blocking"); |
return 0; |
return 0; |
} |
} |
|
|
} else if (sess->mplex_read_remain == 0) |
} else if (sess->mplex_read_remain == 0) |
return 1; |
return 1; |
|
|
if (!io_read_blocking(sess, fd, mpbuf, sess->mplex_read_remain)) { |
if (!io_read_blocking(fd, mpbuf, sess->mplex_read_remain)) { |
ERRX1("io_read_blocking"); |
ERRX1("io_read_blocking"); |
return 0; |
return 0; |
} |
} |
|
|
|
|
if (!sess->mplex_reads) { |
if (!sess->mplex_reads) { |
assert(sess->mplex_read_remain == 0); |
assert(sess->mplex_read_remain == 0); |
c = io_read_blocking(sess, fd, buf, sz); |
c = io_read_blocking(fd, buf, sz); |
sess->total_read += sz; |
sess->total_read += sz; |
return c; |
return c; |
} |
} |
|
|
if (sess->mplex_read_remain) { |
if (sess->mplex_read_remain) { |
rsz = sess->mplex_read_remain < sz ? |
rsz = sess->mplex_read_remain < sz ? |
sess->mplex_read_remain : sz; |
sess->mplex_read_remain : sz; |
if (!io_read_blocking(sess, fd, buf, rsz)) { |
if (!io_read_blocking(fd, buf, rsz)) { |
ERRX1("io_read_blocking"); |
ERRX1("io_read_blocking"); |
return 0; |
return 0; |
} |
} |
|
|
* is insufficient for the new data. |
* is insufficient for the new data. |
*/ |
*/ |
void |
void |
io_buffer_buf(struct sess *sess, void *buf, |
io_buffer_buf(void *buf, size_t *bufpos, size_t buflen, const void *val, |
size_t *bufpos, size_t buflen, const void *val, size_t valsz) |
size_t valsz) |
{ |
{ |
|
|
assert(*bufpos + valsz <= buflen); |
assert(*bufpos + valsz <= buflen); |
|
|
return; |
return; |
|
|
if (!sess->mplex_writes) { |
if (!sess->mplex_writes) { |
io_buffer_buf(sess, buf, bufpos, buflen, val, valsz); |
io_buffer_buf(buf, bufpos, buflen, val, valsz); |
return; |
return; |
} |
} |
|
|
|
|
assert(valsz == (valsz & 0xFFFFFF)); |
assert(valsz == (valsz & 0xFFFFFF)); |
tagbuf = htole32((7 << 24) + valsz); |
tagbuf = htole32((7 << 24) + valsz); |
|
|
io_buffer_int(sess, buf, bufpos, buflen, tagbuf); |
io_buffer_int(buf, bufpos, buflen, tagbuf); |
io_buffer_buf(sess, buf, bufpos, buflen, val, valsz); |
io_buffer_buf(buf, bufpos, buflen, val, valsz); |
} |
} |
|
|
/* |
/* |
|
|
* Like io_buffer_buf(), but for a single integer. |
* Like io_buffer_buf(), but for a single integer. |
*/ |
*/ |
void |
void |
io_buffer_int(struct sess *sess, void *buf, |
io_buffer_int(void *buf, size_t *bufpos, size_t buflen, int32_t val) |
size_t *bufpos, size_t buflen, int32_t val) |
|
{ |
{ |
int32_t nv = htole32(val); |
int32_t nv = htole32(val); |
|
|
io_buffer_buf(sess, buf, bufpos, buflen, &nv, sizeof(int32_t)); |
io_buffer_buf(buf, bufpos, buflen, &nv, sizeof(int32_t)); |
} |
} |
|
|
/* |
/* |
|
|
* Increases "bufpos" to the new position. |
* Increases "bufpos" to the new position. |
*/ |
*/ |
void |
void |
io_unbuffer_buf(struct sess *sess, const void *buf, |
io_unbuffer_buf(const void *buf, size_t *bufpos, size_t bufsz, void *val, |
size_t *bufpos, size_t bufsz, void *val, size_t valsz) |
size_t valsz) |
{ |
{ |
|
|
assert(*bufpos + valsz <= bufsz); |
assert(*bufpos + valsz <= bufsz); |
|
|
* Calls io_unbuffer_buf() and converts. |
* Calls io_unbuffer_buf() and converts. |
*/ |
*/ |
void |
void |
io_unbuffer_int(struct sess *sess, const void *buf, |
io_unbuffer_int(const void *buf, size_t *bufpos, size_t bufsz, int32_t *val) |
size_t *bufpos, size_t bufsz, int32_t *val) |
|
{ |
{ |
int32_t oval; |
int32_t oval; |
|
|
io_unbuffer_buf(sess, buf, bufpos, bufsz, &oval, sizeof(int32_t)); |
io_unbuffer_buf(buf, bufpos, bufsz, &oval, sizeof(int32_t)); |
*val = le32toh(oval); |
*val = le32toh(oval); |
} |
} |
|
|
|
|
* Calls io_unbuffer_buf() and converts. |
* Calls io_unbuffer_buf() and converts. |
*/ |
*/ |
int |
int |
io_unbuffer_size(struct sess *sess, const void *buf, |
io_unbuffer_size(const void *buf, size_t *bufpos, size_t bufsz, size_t *val) |
size_t *bufpos, size_t bufsz, size_t *val) |
|
{ |
{ |
int32_t oval; |
int32_t oval; |
|
|
io_unbuffer_int(sess, buf, bufpos, bufsz, &oval); |
io_unbuffer_int(buf, bufpos, bufsz, &oval); |
if (oval < 0) { |
if (oval < 0) { |
ERRX("io_unbuffer_size: negative value"); |
ERRX("io_unbuffer_size: negative value"); |
return 0; |
return 0; |