1 #include "network_backends.h" 2 3 #include "network.h" 4 #include "log.h" 5 6 #include "sys-socket.h" 7 8 #include <unistd.h> 9 10 #include <errno.h> 11 #include <string.h> 12 13 int network_write_mem_chunk(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes) { 14 chunk* const c = cq->first; 15 off_t c_len; 16 ssize_t r; 17 UNUSED(con); 18 19 force_assert(NULL != c); 20 force_assert(MEM_CHUNK == c->type); 21 force_assert(c->offset >= 0 && c->offset <= (off_t)buffer_string_length(c->mem)); 22 23 c_len = buffer_string_length(c->mem) - c->offset; 24 if (c_len > *p_max_bytes) c_len = *p_max_bytes; 25 26 if (0 == c_len) { 27 chunkqueue_remove_finished_chunks(cq); 28 return 0; 29 } 30 31 #if defined(__WIN32) 32 if ((r = send(fd, c->mem->ptr + c->offset, c_len, 0)) < 0) { 33 int lastError = WSAGetLastError(); 34 switch (lastError) { 35 case WSAEINTR: 36 case WSAEWOULDBLOCK: 37 break; 38 case WSAECONNRESET: 39 case WSAETIMEDOUT: 40 case WSAECONNABORTED: 41 return -2; 42 default: 43 log_error_write(srv, __FILE__, __LINE__, "sdd", 44 "send failed: ", lastError, fd); 45 return -1; 46 } 47 } 48 #else /* __WIN32 */ 49 if ((r = write(fd, c->mem->ptr + c->offset, c_len)) < 0) { 50 switch (errno) { 51 case EAGAIN: 52 case EINTR: 53 break; 54 case EPIPE: 55 case ECONNRESET: 56 return -2; 57 default: 58 log_error_write(srv, __FILE__, __LINE__, "ssd", 59 "write failed:", strerror(errno), fd); 60 return -1; 61 } 62 } 63 #endif /* __WIN32 */ 64 65 if (r >= 0) { 66 *p_max_bytes -= r; 67 chunkqueue_mark_written(cq, r); 68 } 69 70 return (r > 0 && r == c_len) ? 0 : -3; 71 } 72 73 int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq, off_t max_bytes) { 74 while (max_bytes > 0 && NULL != cq->first) { 75 int r = -1; 76 77 switch (cq->first->type) { 78 case MEM_CHUNK: 79 r = network_write_mem_chunk(srv, con, fd, cq, &max_bytes); 80 break; 81 case FILE_CHUNK: 82 r = network_write_file_chunk_mmap(srv, con, fd, cq, &max_bytes); 83 break; 84 } 85 86 if (-3 == r) return 0; 87 if (0 != r) return r; 88 } 89 90 return 0; 91 } 92 93 int network_write_chunkqueue_sendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t max_bytes) { 94 while (max_bytes > 0 && NULL != cq->first) { 95 int r = -1; 96 97 switch (cq->first->type) { 98 case MEM_CHUNK: 99 r = network_writev_mem_chunks(srv, con, fd, cq, &max_bytes); 100 break; 101 case FILE_CHUNK: 102 r = network_write_file_chunk_sendfile(srv, con, fd, cq, &max_bytes); 103 break; 104 } 105 106 if (-3 == r) return 0; 107 if (0 != r) return r; 108 } 109 110 return 0; 111 } 112