free(wsi->u.ws.rxflow_buffer);
wsi->u.ws.rxflow_buffer = NULL;
}
- if (wsi->u.ws.truncated_send_malloc) {
+ if (wsi->truncated_send_malloc) {
/* not going to be completed... nuke it */
- free(wsi->u.ws.truncated_send_malloc);
- wsi->u.ws.truncated_send_malloc = NULL;
+ free(wsi->truncated_send_malloc);
+ wsi->truncated_send_malloc = NULL;
}
}
{
struct pollfd fds;
+ /* treat the fact we got a truncated send pending as if we're choked */
+ if (wsi->truncated_send_malloc)
+ return 1;
+
fds.fd = wsi->sock;
fds.events = POLLOUT;
fds.revents = 0;
/* pending truncated sends have uber priority */
- if (wsi->u.ws.truncated_send_malloc) {
- lws_issue_raw(wsi, wsi->u.ws.truncated_send_malloc +
- wsi->u.ws.truncated_send_offset,
- wsi->u.ws.truncated_send_len);
+ if (wsi->truncated_send_malloc) {
+ lws_issue_raw(wsi, wsi->truncated_send_malloc +
+ wsi->truncated_send_offset,
+ wsi->truncated_send_len);
/* leave POLLOUT active either way */
return 0;
}
int n;
#ifndef LWS_NO_EXTENSIONS
int m;
+ size_t real_len = len;
+
+ if (wsi->truncated_send_malloc &&
+ (buf < wsi->truncated_send_malloc ||
+ buf > (wsi->truncated_send_malloc + wsi->truncated_send_len + wsi->truncated_send_offset))) {
+ lwsl_err("****** %x Sending something else while pending truncated ...\n", wsi);
+ assert(0);
+ }
/*
* one of the extensions is carrying our data itself? Like mux?
lws_hexdump(buf, len);
#endif
+#if 0
+ /* test partial send support by forcing multiple sends on everything */
+ len = len / 2;
+ if (!len)
+ len = 1;
+#endif
+
lws_latency_pre(context, wsi);
#ifdef LWS_OPENSSL_SUPPORT
if (wsi->ssl) {
n = SSL_write(wsi->ssl, buf, len);
lws_latency(context, wsi, "SSL_write lws_issue_raw", n, n >= 0);
if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR) {
+ n = 0;
+ goto handle_truncated_send;
+ }
lwsl_debug("ERROR writing to socket\n");
return -1;
}
n = send(wsi->sock, buf, len, MSG_NOSIGNAL);
lws_latency(context, wsi, "send lws_issue_raw", n, n == len);
if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR) {
+ n = 0;
+ goto handle_truncated_send;
+ }
lwsl_debug("ERROR writing len %d to skt %d\n", len, n);
return -1;
}
/*
* already handling a truncated send?
*/
- if (wsi->u.ws.truncated_send_malloc) {
- lwsl_info("***** partial send moved on by %d (vs %d)\n", n, len);
- wsi->u.ws.truncated_send_offset += n;
- wsi->u.ws.truncated_send_len -= n;
+ if (wsi->truncated_send_malloc) {
+ lwsl_info("***** %x partial send moved on by %d (vs %d)\n", wsi, n, real_len);
+ wsi->truncated_send_offset += n;
+ wsi->truncated_send_len -= n;
- if (!wsi->u.ws.truncated_send_len) {
- lwsl_info("***** partial send completed\n");
+ if (!wsi->truncated_send_len) {
+ lwsl_info("***** %x partial send completed\n", wsi);
/* done with it */
- free(wsi->u.ws.truncated_send_malloc);
- wsi->u.ws.truncated_send_malloc = NULL;
+ free(wsi->truncated_send_malloc);
+ wsi->truncated_send_malloc = NULL;
+ n = real_len;
} else
libwebsocket_callback_on_writable(
wsi->protocol->owning_server, wsi);
return n;
}
- if (n < len) {
+ if (n < real_len) {
if (wsi->u.ws.clean_buffer)
/*
* This buffer unaffected by extension rewriting.
* Newly truncated send. Buffer the remainder (it will get
* first priority next time the socket is writable)
*/
- lwsl_info("***** new partial send %d sent %d accepted\n", len, n);
+ lwsl_info("***** %x new partial sent %d from %d total\n", wsi, n, real_len);
- wsi->u.ws.truncated_send_malloc = malloc(len - n);
- if (!wsi->u.ws.truncated_send_malloc) {
+ wsi->truncated_send_malloc = malloc(real_len - n);
+ if (!wsi->truncated_send_malloc) {
lwsl_err("truncated send: unable to malloc %d\n",
- len - n);
+ real_len - n);
return -1;
}
- wsi->u.ws.truncated_send_offset = 0;
- wsi->u.ws.truncated_send_len = len - n;
- memcpy(wsi->u.ws.truncated_send_malloc, buf + n, len - n);
+ wsi->truncated_send_offset = 0;
+ wsi->truncated_send_len = real_len - n;
+ memcpy(wsi->truncated_send_malloc, buf + n, real_len - n);
libwebsocket_callback_on_writable(
wsi->protocol->owning_server, wsi);
- return len;
+ return real_len;
}
return n;
*/
if (!lws_send_pipe_choked(wsi) &&
- !wsi->u.ws.truncated_send_malloc)
+ !wsi->truncated_send_malloc)
/* no we could add more, lets's do that */
continue;
int n, m;
while (!lws_send_pipe_choked(wsi)) {
+
+ if (wsi->truncated_send_malloc) {
+ lws_issue_raw(wsi, wsi->truncated_send_malloc +
+ wsi->truncated_send_offset,
+ wsi->truncated_send_len);
+ continue;
+ }
+
+ if (wsi->u.http.filepos == wsi->u.http.filelen)
+ goto all_sent;
+
n = read(wsi->u.http.fd, context->service_buffer,
sizeof(context->service_buffer));
if (n > 0) {
if (n < 0)
return -1; /* caller will close */
-
- if (wsi->u.http.filepos == wsi->u.http.filelen) {
+all_sent:
+ if (!wsi->truncated_send_malloc &&
+ wsi->u.http.filepos == wsi->u.http.filelen) {
wsi->state = WSI_STATE_HTTP;
if (wsi->protocol->callback)
}
}
- lwsl_notice("choked before able to send whole file (post)\n");
+ lwsl_info("choked before able to send whole file (post)\n");
libwebsocket_callback_on_writable(context, wsi);
return 0; /* indicates further processing must be done */
/* handle http headers coming in */
+ /* pending truncated sends have uber priority */
+
+ if (wsi->truncated_send_malloc) {
+ if (pollfd->revents & POLLOUT)
+ lws_issue_raw(wsi, wsi->truncated_send_malloc +
+ wsi->truncated_send_offset,
+ wsi->truncated_send_len);
+ /*
+ * we can't afford to allow input processing send
+ * something new, so spin around he event loop until
+ * he doesn't have any partials
+ */
+ break;
+ }
+
/* any incoming data ready? */
if (pollfd->revents & POLLIN) {
return 0;
}
+ /* hm this may want to send (via HTTP callback for example) */
+
n = libwebsocket_read(context, wsi,
context->service_buffer, len);
if (n < 0)
/* we closed wsi */
return 0;
+
+ /* hum he may have used up the writability above */
+
+ break;
}
/* this handles POLLOUT for http serving fragments */