|
|
|
@ -48,144 +48,6 @@ int connection_set_state(server *srv, connection *con, connection_state_t state)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
static void dump_packet(const unsigned char *data, size_t len) {
|
|
|
|
|
size_t i, j;
|
|
|
|
|
|
|
|
|
|
if (len == 0) return;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
|
if (i % 16 == 0) fprintf(stderr, " ");
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%02x ", data[i]);
|
|
|
|
|
|
|
|
|
|
if ((i + 1) % 16 == 0) {
|
|
|
|
|
fprintf(stderr, " ");
|
|
|
|
|
for (j = 0; j <= i % 16; j++) {
|
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
|
|
if (i-15+j >= len) break;
|
|
|
|
|
|
|
|
|
|
c = data[i-15+j];
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (len % 16 != 0) {
|
|
|
|
|
for (j = i % 16; j < 16; j++) {
|
|
|
|
|
fprintf(stderr, " ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, " ");
|
|
|
|
|
for (j = i & ~0xf; j < len; j++) {
|
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
|
|
c = data[j];
|
|
|
|
|
fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
|
|
|
|
|
}
|
|
|
|
|
fprintf(stderr, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* 0: everything ok, -1: error, -2: con closed */
|
|
|
|
|
int connection_read_cq(server *srv, connection *con, chunkqueue *cq, off_t max_bytes) {
|
|
|
|
|
int len;
|
|
|
|
|
char *mem = NULL;
|
|
|
|
|
size_t mem_len = 0;
|
|
|
|
|
int toread;
|
|
|
|
|
force_assert(cq == con->read_queue); /*(code transform assumption; minimize diff)*/
|
|
|
|
|
force_assert(max_bytes == MAX_READ_LIMIT); /*(code transform assumption; minimize diff)*/
|
|
|
|
|
|
|
|
|
|
/* default size for chunks is 4kb; only use bigger chunks if FIONREAD tells
|
|
|
|
|
* us more than 4kb is available
|
|
|
|
|
* if FIONREAD doesn't signal a big chunk we fill the previous buffer
|
|
|
|
|
* if it has >= 1kb free
|
|
|
|
|
*/
|
|
|
|
|
#if defined(__WIN32)
|
|
|
|
|
chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, 4096);
|
|
|
|
|
|
|
|
|
|
len = recv(con->fd, mem, mem_len, 0);
|
|
|
|
|
#else /* __WIN32 */
|
|
|
|
|
if (ioctl(con->fd, FIONREAD, &toread) || toread <= 4*1024) {
|
|
|
|
|
toread = 4096;
|
|
|
|
|
}
|
|
|
|
|
else if (toread > MAX_READ_LIMIT) {
|
|
|
|
|
toread = MAX_READ_LIMIT;
|
|
|
|
|
}
|
|
|
|
|
chunkqueue_get_memory(con->read_queue, &mem, &mem_len, 0, toread);
|
|
|
|
|
|
|
|
|
|
len = read(con->fd, mem, mem_len);
|
|
|
|
|
#endif /* __WIN32 */
|
|
|
|
|
|
|
|
|
|
chunkqueue_use_memory(con->read_queue, len > 0 ? len : 0);
|
|
|
|
|
|
|
|
|
|
if (len < 0) {
|
|
|
|
|
con->is_readable = 0;
|
|
|
|
|
|
|
|
|
|
#if defined(__WIN32)
|
|
|
|
|
{
|
|
|
|
|
int lastError = WSAGetLastError();
|
|
|
|
|
switch (lastError) {
|
|
|
|
|
case EAGAIN:
|
|
|
|
|
return 0;
|
|
|
|
|
case EINTR:
|
|
|
|
|
/* we have been interrupted before we could read */
|
|
|
|
|
con->is_readable = 1;
|
|
|
|
|
return 0;
|
|
|
|
|
case ECONNRESET:
|
|
|
|
|
/* suppress logging for this error, expected for keep-alive */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - recv failed: ", lastError);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#else /* __WIN32 */
|
|
|
|
|
switch (errno) {
|
|
|
|
|
case EAGAIN:
|
|
|
|
|
return 0;
|
|
|
|
|
case EINTR:
|
|
|
|
|
/* we have been interrupted before we could read */
|
|
|
|
|
con->is_readable = 1;
|
|
|
|
|
return 0;
|
|
|
|
|
case ECONNRESET:
|
|
|
|
|
/* suppress logging for this error, expected for keep-alive */
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif /* __WIN32 */
|
|
|
|
|
|
|
|
|
|
connection_set_state(srv, con, CON_STATE_ERROR);
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
} else if (len == 0) {
|
|
|
|
|
con->is_readable = 0;
|
|
|
|
|
/* the other end close the connection -> KEEP-ALIVE */
|
|
|
|
|
|
|
|
|
|
/* pipelining */
|
|
|
|
|
|
|
|
|
|
return -2;
|
|
|
|
|
} else if (len != (ssize_t) mem_len) {
|
|
|
|
|
/* we got less then expected, wait for the next fd-event */
|
|
|
|
|
|
|
|
|
|
con->is_readable = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
con->bytes_read += len;
|
|
|
|
|
#if 0
|
|
|
|
|
dump_packet(b->ptr, len);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int connection_handle_read_post_cq_compact(chunkqueue *cq) {
|
|
|
|
|
/* combine first mem chunk with next non-empty mem chunk
|
|
|
|
|
* (loop if next chunk is empty) */
|
|
|
|
|