Explorar el Código

ncd: modules: sys_request_server: send finished/error message only after the request process has finished

ambrop7 hace 14 años
padre
commit
1c6b2bc54d
Se han modificado 1 ficheros con 33 adiciones y 24 borrados
  1. 33 24
      ncd/modules/sys_request_server.c

+ 33 - 24
ncd/modules/sys_request_server.c

@@ -96,6 +96,8 @@ struct instance {
 #define CONNECTION_STATE_RUNNING 1
 #define CONNECTION_STATE_TERMINATING 2
 
+struct reply;
+
 struct connection {
     struct instance *inst;
     LinkedList0Node connections_list_node;
@@ -114,8 +116,10 @@ struct request {
     uint32_t request_id;
     LinkedList0Node requests_list_node;
     NCDValue request_data;
+    struct reply *end_reply;
     NCDModuleProcess process;
     int terminating;
+    int got_finished;
 };
 
 struct reply {
@@ -140,8 +144,8 @@ static void request_process_handler_event (struct request *r, int event);
 static int request_process_func_getspecialobj (struct request *r, const char *name, NCDObject *out_object);
 static int request_process_request_obj_func_getvar (struct request *r, const char *name, NCDValue *out_value);
 static void request_terminate (struct request *r);
-static struct reply * reply_init (struct connection *c, uint32_t request_id, uint32_t type, NCDValue *reply_data);
-static void reply_start (struct reply *r);
+static struct reply * reply_init (struct connection *c, uint32_t request_id, NCDValue *reply_data);
+static void reply_start (struct reply *r, uint32_t type);
 static void reply_free (struct reply *r);
 static void reply_send_qflow_if_handler_done (struct reply *r);
 static void instance_free (struct instance *o);
@@ -319,15 +323,7 @@ static void connection_recv_if_handler_send (struct connection *c, uint8_t *data
             }
             
             if (!r->terminating) {
-                struct reply *rpl = reply_init(c, r->request_id, REQUESTPROTO_TYPE_SERVER_ERROR, NULL);
-                if (!rpl) {
-                    ModuleLog(o->i, BLOG_ERROR, "failed to submit error");
-                    goto fail;
-                }
-                
-                // send reply first!
                 request_terminate(r);
-                reply_start(rpl);
             }
         } break;
         
@@ -366,25 +362,32 @@ static int request_init (struct connection *c, uint32_t request_id, const uint8_
         goto fail1;
     }
     
+    if (!(r->end_reply = reply_init(c, request_id, NULL))) {
+        goto fail2;
+    }
+    
     NCDValue args;
     if (!NCDValue_InitCopy(&args, o->args)) {
         ModuleLog(o->i, BLOG_ERROR, "NCDValue_InitCopy failed");
-        goto fail2;
+        goto fail3;
     }
     
     if (!NCDModuleProcess_Init(&r->process, o->i, o->request_handler_template, args, r, (NCDModuleProcess_handler_event)request_process_handler_event)) {
         ModuleLog(o->i, BLOG_ERROR, "NCDModuleProcess_Init failed");
         NCDValue_Free(&args);
-        goto fail2;
+        goto fail3;
     }
     
     NCDModuleProcess_SetSpecialFuncs(&r->process, (NCDModuleProcess_func_getspecialobj)request_process_func_getspecialobj);
     
     r->terminating = 0;
+    r->got_finished = 0;
     
     ModuleLog(o->i, BLOG_INFO, "request initialized");
     return 1;
     
+fail3:
+    reply_free(r->end_reply);
 fail2:
     NCDValue_Free(&r->request_data);
 fail1:
@@ -399,6 +402,11 @@ static void request_free (struct request *r)
     struct connection *c = r->con;
     NCDModuleProcess_AssertFree(&r->process);
     
+    if (c->state != CONNECTION_STATE_TERMINATING) {
+        uint32_t type = r->got_finished ? REQUESTPROTO_TYPE_SERVER_FINISHED : REQUESTPROTO_TYPE_SERVER_ERROR;
+        reply_start(r->end_reply, type);
+    }
+    
     NCDModuleProcess_Free(&r->process);
     NCDValue_Free(&r->request_data);
     LinkedList0_Remove(&c->requests_list, &r->requests_list_node);
@@ -486,7 +494,7 @@ static void request_terminate (struct request *r)
     r->terminating = 1;
 }
 
-static struct reply * reply_init (struct connection *c, uint32_t request_id, uint32_t type, NCDValue *reply_data)
+static struct reply * reply_init (struct connection *c, uint32_t request_id, NCDValue *reply_data)
 {
     struct instance *o = c->inst;
     ASSERT(c->state == CONNECTION_STATE_RUNNING)
@@ -538,7 +546,6 @@ static struct reply * reply_init (struct connection *c, uint32_t request_id, uin
     struct reply_header *header = (void *)r->send_buf;
     header->pp.len = htol16(len - sizeof(header->pp));
     header->rp.request_id = htol32(request_id);
-    header->rp.type = htol32(type);
     
     return r;
     
@@ -552,9 +559,16 @@ fail0:
     return NULL;
 }
 
-static void reply_start (struct reply *r)
+static void reply_start (struct reply *r, uint32_t type)
 {
-    int len = ltoh16(((struct packetproto_header *)r->send_buf)->len) + sizeof(struct packetproto_header);
+    struct reply_header {
+        struct packetproto_header pp;
+        struct requestproto_header rp;
+    } __attribute__((packed));
+    
+    struct reply_header *header = (void *)r->send_buf;
+    header->rp.type = htol32(type);
+    int len = ltoh16(header->pp.len) + sizeof(struct packetproto_header);
     
     PacketPassInterface_Sender_Send(r->send_qflow_if, r->send_buf, len);
 }
@@ -697,13 +711,13 @@ static void reply_func_new (NCDModuleInst *i)
         goto fail;
     }
     
-    struct reply *rpl = reply_init(c, r->request_id, REQUESTPROTO_TYPE_SERVER_REPLY, reply_data);
+    struct reply *rpl = reply_init(c, r->request_id, reply_data);
     if (!rpl) {
         ModuleLog(i, BLOG_ERROR, "failed to submit reply");
         goto fail;
     }
     
-    reply_start(rpl);
+    reply_start(rpl, REQUESTPROTO_TYPE_SERVER_REPLY);
     return;
     
 fail:
@@ -728,14 +742,9 @@ static void finish_func_new (NCDModuleInst *i)
         goto fail;
     }
     
-    struct reply *rpl = reply_init(c, r->request_id, REQUESTPROTO_TYPE_SERVER_FINISHED, NULL);
-    if (!rpl) {
-        ModuleLog(i, BLOG_ERROR, "failed to submit finished");
-        goto fail;
-    }
+    r->got_finished = 1;
     
     request_terminate(r);
-    reply_start(rpl);
     return;
     
 fail: