Unable to return http_status in LWS_CALLBACK_TIMER reason
Currently I do have the issue to be unable to close a server connection within the LWS_CALLBACK_TIMER reason.
I am calling the lws_set_timer_usecs(wsi, WAIT_FOR_BACKEND_RESP_TIME_S * LWS_US_PER_SEC); in the callback reason LWS_CALLBACK_HTTP. Within this reason it is possible to return a http response. Unfortunately in LWS_CALLBACK_TIMER it isn't.
This is the method which is called in both callback reasons:
[[nodiscard]] int
FileUpload::closeServerConnection(lws* wsi, http_status status, char const* const description)
{
auto ret{0};
if (lws_return_http_status(wsi, status, description)) {
ret = -1;
}
if (lws_http_transaction_completed(wsi)) {
ret = -1;
}
return ret;
}
Is this expected behaviour?
Thanks in advance!
CALLBACK_TIMER is deprecated, since some years you should use lws_sul timers instead... you can have as many of these as you need, without having to be bound to a wsi if that's more convenient.
With http, you can only return a status if done at the beginning of the transaction. If it already started sending something else, you can't stop partway and redo the response. And if the peer hung up on you, the transaction is already over.
But if these lws_sul timers aren't wsi bound, how can I call lws_return_http_status then?
We do need this timer, because we are waiting for a signal from another module (outside lws). In this timer callback we are checking if we did get this signal and checking if this signal is correct. When incorrect we do like to send an http status back to the client. With the deprecated timer we could use the wsi struct. Do you have an idea where to call this return http status method then? Currently I can't wrap my head around how to do this in this particular case. Thanks!
The callbacks for lws_sul aren't related to any protocol, they each have their own callback. They are called back from the event loop, which makes it safe to touch other event loop things like wsi from them. So they are much more useful, you can have n of them.
Although they're not bound to wsi, they can be composed into, eg, a pss, which can point to a wsi; you could ask for a callback-on-writeable for the wsi from the sul cb safely, if you take care to do lws_sul_cancel() on it when the pss is destroyed.
Okay thank you, we did implemented the sul timer now.
But the issue with the http status isn't resolved yet. So I am pretty sure that nothing else has been sent yet but still we aren't able to return a status after reason "LWS_CALLBACK_HTTP". Do you have an example when it is possible to return a status?
For example in our server timer we are trying to connect a client to a backend server "lws_client_connect_via_info(&connCtx->clientConnectionInfo)". If this fails we land in reason "LWS_CALLBACK_CLIENT_CONNECTION_ERROR" after that in "LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL". Here again it isn't possible to return an http status from our server to the external client.
In our logging you can see that the http return status is set but it never shows at our external client:
[15:48:24.291406] [718222] [I] [LWS]: LWS_CALLBACK_CLIENT_CONNECTION_ERROR [15:48:24.291420] [718222] [E] [LWS]: Forward-Client failed to connect to backend [15:48:24.291434] [718222] [E] [LWS]: Reason: DNS NXDOMAIN [15:48:24.291448] [718222] [I] [LWS]: re-configure TLS CTX [15:48:24.291557] [718222] [I] [RestClient]: calling: http://localhost:5050/certificate/ROOT?api-version=2020-12-01-preview [15:48:24.297853] [718222] [I] [RestClient]: call succeeded: http://localhost:5050/certificate/ROOT?api-version=2020-12-01-preview [15:48:24.328616] [718222] [D] [LWS]: [wsicli|0|PUT/h1/default/]: __lws_close_free_wsi: caller: client_connect2 [15:48:24.328642] [718222] [I] [LWS]: LWS_CALLBACK_CLIENT_HTTP_DROP_PROTOCOL [15:48:24.328645] [718222] [I] [LWS]: complete server transaction [15:48:28.261818] [718222] [D] [LWS]: [wsisrv|0|default|(null)]: lws_issue_raw: ssl_capable_write (606) says 606 [15:48:31.176217] [718222] [D] [LWS]: [wsicli|0|PUT/h1/default/]: __lws_close_free_wsi: real just_kill_connection: sockfd -1 [15:48:31.176284] [718222] [D] [LWS]: [wsicli|0|PUT/h1/default/]: __lws_close_free_wsi: cce=0 [15:48:31.176313] [718222] [D] [LWS]: rops_destroy_role_h1: ah det due to close [15:48:31.176331] [718222] [D] [LWS]: __lws_header_table_detach: [wsicli|0|PUT/h1/default/]: ah 0x7fffd001b260 (tsi=0, count = 2) [15:48:31.176346] [718222] [D] [LWS]: __lws_header_table_detach: nobody usable waiting [15:48:31.176363] [718222] [D] [LWS]: _lws_destroy_ah: freed ah 0x7fffd001b260 : pool length 1 [15:48:31.176379] [718222] [D] [LWS]: __lws_header_table_detach: [wsicli|0|PUT/h1/default/]: ah 0x7fffd001b260 (tsi=0, count = 1) [15:48:31.176406] [718222] [I] [LWS]: forward-client failed to start connection [15:48:31.176425] [718222] [D] [LWS]: [wsisrv|0|default|(null)]: lws_sul_wsitimeout_cb: TIMEDOUT WAITING 0, dhdr 1, ah 0x7fffd000b810, wl 0 [15:48:31.176441] [718222] [D] [LWS]: [wsisrv|0|default|(null)]: __lws_close_free_wsi: caller: timeout [15:48:31.176458] [718222] [I] [LWS]: LWS_CALLBACK_HTTP_DROP_PROTOCOL [15:48:31.176475] [718222] [D] [LWS]: [wsisrv|0|default|(null)]: __lws_close_free_wsi: real just_kill_connection: sockfd 13 [15:48:31.176497] [718222] [D] [LWS]: [wsisrv|0|default|(null)]: __lws_close_free_wsi: cce=1 [15:48:31.176513] [718222] [I] [LWS]: LWS_CALLBACK_CLOSED_HTTP [15:48:31.176527] [718222] [I] [LWS]: Instance destruction of ConnectionContext [15:48:31.176875] [718222] [D] [LWS]: rops_destroy_role_h1: ah det due to close [15:48:31.176903] [718222] [D] [LWS]: __lws_header_table_detach: [wsisrv|0|default|(null)]: ah 0x7fffd000b810 (tsi=0, count = 1) [15:48:31.176919] [718222] [D] [LWS]: __lws_header_table_detach: nobody usable waiting [15:48:31.176935] [718222] [D] [LWS]: _lws_destroy_ah: freed ah 0x7fffd000b810 : pool length 0 [15:48:31.176952] [718222] [D] [LWS]: __lws_header_table_detach: [wsisrv|0|default|(null)]: ah 0x7fffd000b810 (tsi=0, count = 0)
What can be the problem?
Do you have documentation at which stages (reasons) it is possible to return http status?