int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf) { struct libwebsocket *wsi_eff = lws_http2_get_network_wsi(wsi); unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH]; int n; *p++ = len >> 16; *p++ = len >> 8; *p++ = len; *p++ = type; *p++ = flags; *p++ = sid >> 24; *p++ = sid >> 16; *p++ = sid >> 8; *p++ = sid; lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n", __func__, wsi, wsi_eff, type, flags, sid, len); n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH], len + LWS_HTTP2_FRAME_HEADER_LENGTH); if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH) return n - LWS_HTTP2_FRAME_HEADER_LENGTH; return n; }
int lws_http2_frame_write(struct libwebsocket *wsi, int type, int flags, unsigned int sid, unsigned int len, unsigned char *buf) { struct libwebsocket *wsi_eff = lws_http2_get_network_wsi(wsi); unsigned char *p = &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH]; int n; *p++ = len >> 16; *p++ = len >> 8; *p++ = len; *p++ = type; *p++ = flags; *p++ = sid >> 24; *p++ = sid >> 16; *p++ = sid >> 8; *p++ = sid; lwsl_info("%s: %p (eff %p). type %d, flags 0x%x, sid=%d, len=%d\n", __func__, wsi, wsi_eff, type, flags, sid, len, wsi->u.http2.tx_credit); if (type == LWS_HTTP2_FRAME_TYPE_DATA) { if (wsi->u.http2.tx_credit < len) lwsl_err("%s: %p: sending payload len %d but tx_credit only %d!\n", len, wsi->u.http2.tx_credit); wsi->u.http2.tx_credit -= len; } n = lws_issue_raw(wsi_eff, &buf[-LWS_HTTP2_FRAME_HEADER_LENGTH], len + LWS_HTTP2_FRAME_HEADER_LENGTH); if (n >= LWS_HTTP2_FRAME_HEADER_LENGTH) return n - LWS_HTTP2_FRAME_HEADER_LENGTH; return n; }
LWS_VISIBLE int libwebsocket_callback_on_writable(struct libwebsocket_context *context, struct libwebsocket *wsi) { #ifdef LWS_USE_HTTP2 struct libwebsocket *network_wsi, *wsi2; int already; lwsl_info("%s: %p\n", __func__, wsi); if (wsi->mode != LWS_CONNMODE_HTTP2_SERVING) goto network_sock; if (wsi->u.http2.requested_POLLOUT) { lwsl_info("already pending writable\n"); return 1; } if (wsi->u.http2.tx_credit <= 0) { /* * other side is not able to cope with us sending * anything so no matter if we have POLLOUT on our side. * * Delay waiting for our POLLOUT until peer indicates he has * space for more using tx window command in http2 layer */ lwsl_info("%s: %p: waiting_tx_credit (%d)\n", __func__, wsi, wsi->u.http2.tx_credit); wsi->u.http2.waiting_tx_credit = 1; return 0; } network_wsi = lws_http2_get_network_wsi(wsi); already = network_wsi->u.http2.requested_POLLOUT; /* mark everybody above him as requesting pollout */ wsi2 = wsi; while (wsi2) { wsi2->u.http2.requested_POLLOUT = 1; lwsl_info("mark %p pending writable\n", wsi2); wsi2 = wsi2->u.http2.parent_wsi; } /* for network action, act only on the network wsi */ wsi = network_wsi; if (already) return 1; network_sock: #endif (void)context; if (lws_ext_callback_for_each_active(wsi, LWS_EXT_CALLBACK_REQUEST_ON_WRITEABLE, NULL, 0)) return 1; if (wsi->position_in_fds_table < 0) { lwsl_err("%s: failed to find socket %d\n", __func__, wsi->sock); return -1; } if (lws_change_pollfd(wsi, 0, LWS_POLLOUT)) return -1; lws_libev_io(context, wsi, LWS_EV_START | LWS_EV_WRITE); return 1; }