src/server/safs/proxy.c

changeset 707
5fb102d2c745
parent 706
df64b4b79912
--- a/src/server/safs/proxy.c	Wed Feb 25 23:14:47 2026 +0100
+++ b/src/server/safs/proxy.c	Thu Feb 26 21:35:53 2026 +0100
@@ -130,6 +130,17 @@
         ret = REQ_ABORTED;
     }
     
+    if(client->last_event != &proxy->event && proxy->event.fn != NULL) {
+        if(!ev_remove_poll(client->ev, proxy->event.object)) {
+            proxy_unref(proxy);
+        } else {
+            log_ereport(LOG_FAILURE, "proxy_response_finished: cannot remove poll");
+        }
+        proxy->event.finish = NULL;
+    }
+    
+    // return to nsapi threadpool
+    net_setnonblock(proxy->sn->csd, 0);
     nsapi_function_return(proxy->sn, proxy->rq, ret);
     
     proxy_unref(proxy);
@@ -137,7 +148,7 @@
 
 static int proxy_request_read_event(EventHandler *eh, Event *event) {
     ProxyRequest *proxy = event->cookie;
-    if(http_client_process(proxy->client)) {
+    if(http_client_process(proxy->client, event)) {
         if(proxy->client->error == 0) {
             return 1;
         }
@@ -161,7 +172,7 @@
         if(st->io_errno == EWOULDBLOCK) {
             ret = HTTP_CLIENT_CALLBACK_WOULD_BLOCK;
             // is there already an poll event for csd?
-            if(!proxy->event.cookie) {
+            if(!proxy->event.fn) {
                 proxy->ref++;
                 proxy->event.cookie = proxy;
                 proxy->event.fn = proxy_request_read_event;
@@ -181,16 +192,41 @@
 static ssize_t proxy_response_write(HttpClient *client, void *buf, size_t nbytes, void *userdata) {
     ProxyRequest *proxy = userdata;
     ssize_t ret = net_write(proxy->sn->csd, buf, nbytes);
-    // TODO: handle errors
+    if(ret == NETBUF_EOF) {
+        ret = HTTP_CLIENT_CALLBACK_ERROR;
+    } else if(ret < 0) {
+        IOStream *st = proxy->sn->csd;
+        if(st->io_errno == EWOULDBLOCK) {
+            // Is there already an poll event for csd?
+            if(client->last_event == &proxy->event) {
+                // Yes, there is already an event, and it even is the event that triggert this call.
+                // Make sure it is a write event
+                proxy->event.events = EVENT_POLLOUT;
+                return HTTP_CLIENT_CALLBACK_WOULD_BLOCK;
+            } else if(proxy->event.fn != NULL) {
+                // There is an inactive event, probably a read event
+                // Remove the old event before we add a write event
+                if(ev_remove_poll(client->ev, proxy->event.object)) {
+                    log_ereport(LOG_FAILURE, "proxy_response_write: cannot remove poll");
+                    return HTTP_CLIENT_CALLBACK_ERROR;
+                }
+            } else {
+                proxy->ref++;
+                proxy->event.cookie = proxy;
+                proxy->event.fn = proxy_request_read_event;
+                proxy->event.finish = proxy_request_read_finished;
+            }
+            // Add write event
+            if(event_pollout(client->ev, proxy->sn->csd, &proxy->event)) {
+                proxy_unref(proxy);
+                log_ereport(LOG_FAILURE, "proxy_response_write: cannot add write poll");
+            }
+            return HTTP_CLIENT_CALLBACK_ERROR;
+        }
+    }
     return ret;
 }
 
-static void proxy_request_finished(HttpClient *client, void *userdata) {
-    ProxyRequest *proxy = userdata;
-    net_setnonblock(proxy->sn->csd, 0);
-    nsapi_saf_return(proxy->sn, proxy->rq, REQ_PROCEED);
-}
-
 int http_reverse_proxy_service(pblock *param, Session *sn, Request *rq) {
     EventHandler *ev = sn->ev;
     const char *method = pblock_findkeyval(pb_key_method, rq->reqpb);
@@ -396,7 +432,7 @@
     client->response_start_userdata = proxy;
     client->response_body_write = proxy_response_write;
     client->response_body_write_userdata = proxy;
-    client->response_finished = proxy_request_finished;
+    client->response_finished = proxy_response_finished;
     client->response_finished_userdata = proxy;
     
     net_setnonblock(sn->csd, 1);

mercurial