78 IOStream* net_stream_from_fd(pool_handle_t *pool, int fd) { |
78 IOStream* net_stream_from_fd(pool_handle_t *pool, int fd) { |
79 NetIOStream *st = pool_malloc(pool, sizeof(NetIOStream)); |
79 NetIOStream *st = pool_malloc(pool, sizeof(NetIOStream)); |
80 st->st = net_io_funcs; |
80 st->st = net_io_funcs; |
81 st->fd = fd; |
81 st->fd = fd; |
82 st->max_read = 0; |
82 st->max_read = 0; |
83 st->rd = 0; |
83 st->read = 0; |
84 st->chunkedenc = 0; |
84 st->chunked_enc = 0; |
85 st->buffered = 0; |
85 st->buffered = 0; |
86 return (IOStream*)st; |
86 return (IOStream*)st; |
87 } |
87 } |
88 |
88 |
89 ssize_t net_stream_write(NetIOStream *st, void *buf, size_t nbytes) { |
89 ssize_t net_stream_write(NetIOStream *st, void *buf, size_t nbytes) { |
90 if(st->chunkedenc) { |
90 if(st->chunked_enc) { |
91 // TODO: on some plattforms iov_len is smaller than size_t |
91 // TODO: on some plattforms iov_len is smaller than size_t |
92 struct iovec io[2]; |
92 struct iovec io[2]; |
93 char chunk_len[16]; |
93 char chunk_len[16]; |
94 io[0].iov_base = chunk_len; |
94 io[0].iov_base = chunk_len; |
95 io[0].iov_len = snprintf(chunk_len, 16, "\n%x\r\n", nbytes); |
95 io[0].iov_len = snprintf(chunk_len, 16, "\n%x\r\n", nbytes); |
101 return write(st->fd, buf, nbytes); |
101 return write(st->fd, buf, nbytes); |
102 } |
102 } |
103 } |
103 } |
104 |
104 |
105 ssize_t net_stream_writev(NetIOStream *st, struct iovec *iovec, int iovcnt) { |
105 ssize_t net_stream_writev(NetIOStream *st, struct iovec *iovec, int iovcnt) { |
106 if(st->chunkedenc) { |
106 if(st->chunked_enc) { |
107 struct iovec *io = calloc(iovcnt + 1, sizeof(struct iovec)); |
107 struct iovec *io = calloc(iovcnt + 1, sizeof(struct iovec)); |
108 char chunk_len[16]; |
108 char chunk_len[16]; |
109 io[0].iov_base = chunk_len; |
109 io[0].iov_base = chunk_len; |
110 size_t len = 0; |
110 size_t len = 0; |
111 for(int i=0;i<iovcnt;i++) { |
111 for(int i=0;i<iovcnt;i++) { |
119 return writev(st->fd, iovec, iovcnt); |
119 return writev(st->fd, iovec, iovcnt); |
120 } |
120 } |
121 } |
121 } |
122 |
122 |
123 ssize_t net_stream_read(NetIOStream *st, void *buf, size_t nbytes) { |
123 ssize_t net_stream_read(NetIOStream *st, void *buf, size_t nbytes) { |
124 if(st->max_read != 0 && st->rd >= st->max_read) { |
124 if(st->max_read != 0 && st->read >= st->max_read) { |
125 return 0; |
125 return 0; |
126 } |
126 } |
127 ssize_t r = read(st->fd, buf, nbytes); |
127 ssize_t r = read(st->fd, buf, nbytes); |
128 st->rd += r; |
128 st->read += r; |
129 return r; |
129 return r; |
130 } |
130 } |
131 |
131 |
132 ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) { |
132 ssize_t net_stream_sendfile(NetIOStream *st, sendfiledata *sfd) { |
133 // TODO: header and trailer |
133 // TODO: header and trailer |
177 free(buf); |
177 free(buf); |
178 return r; |
178 return r; |
179 } |
179 } |
180 |
180 |
181 ssize_t net_sendfile(SYS_NETFD fd, sendfiledata *sfd) { |
181 ssize_t net_sendfile(SYS_NETFD fd, sendfiledata *sfd) { |
182 IOStream *out = fd; |
182 NetIOStream *out = fd; |
183 if(out->sendfile) { |
183 if(out->st.sendfile && sfd->fd && sfd->fd->fd != -1) { |
184 ssize_t r = ((IOStream*)fd)->sendfile(fd, sfd); |
184 ssize_t r = ((IOStream*)fd)->sendfile(fd, sfd); |
185 if(r < 0) { |
185 if(r < 0) { |
186 return IO_ERROR; |
186 return IO_ERROR; |
187 } |
187 } |
188 } else { |
188 } else { |
189 fprintf(stderr, "stream does not support sendfile\n"); |
189 // stream/file does not support sendfile |
|
190 // do regular copy |
|
191 char *buf = malloc(4096); |
|
192 if(!buf) { |
|
193 // TODO: out of memory error |
|
194 return IO_ERROR; |
|
195 } |
|
196 char *header = (char*)sfd->header; |
|
197 int hlen = sfd->hlen; |
|
198 char *trailer = (char*)sfd->trailer; |
|
199 int tlen = sfd->tlen; |
|
200 if(header == NULL) { |
|
201 hlen = 0; |
|
202 } |
|
203 if(trailer == NULL) { |
|
204 tlen = 0; |
|
205 } |
|
206 |
|
207 ssize_t r; |
|
208 while(hlen > 0) { |
|
209 r = out->st.write(fd, header, hlen); |
|
210 header += r; |
|
211 hlen -= r; |
|
212 if(r <= 0) { |
|
213 free(buf); |
|
214 return IO_ERROR; |
|
215 } |
|
216 } |
|
217 |
|
218 if(system_lseek(sfd->fd, sfd->offset, SEEK_SET) == -1) { |
|
219 free(buf); |
|
220 return IO_ERROR; |
|
221 } |
|
222 |
|
223 size_t length = sfd->len; |
|
224 while(length > 0) { |
|
225 if((r = system_fread(sfd->fd, buf, 4096)) <= 0) { |
|
226 break; |
|
227 } |
|
228 char *write_buf = buf; |
|
229 while(r > 0) { |
|
230 ssize_t w = out->st.write(fd, write_buf, r); |
|
231 r -= w; |
|
232 length -= w; |
|
233 write_buf += w; |
|
234 } |
|
235 } |
|
236 free(buf); |
|
237 if(length > 0) { |
|
238 return IO_ERROR; |
|
239 } |
|
240 |
|
241 while(tlen > 0) { |
|
242 r = out->st.write(fd, trailer, tlen); |
|
243 trailer += r; |
|
244 tlen -= r; |
|
245 if(r <= 0) { |
|
246 return IO_ERROR; |
|
247 } |
|
248 } |
|
249 |
|
250 return sfd->hlen + sfd->len + sfd->tlen; |
190 } |
251 } |
191 return IO_ERROR; |
252 return IO_ERROR; |
192 } |
253 } |
193 |
254 |
194 |
255 |