xref: /lighttpd1.4/src/network_write.c (revision d147673d)
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