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