OSDN Git Service

fix flag clear in not exist endpoint.
[bbk/bchanf.git] / src / http / http_connector.c
index 2ad35a7..d341dbb 100644 (file)
@@ -305,8 +305,22 @@ struct http_connector_t_ {
        http_reqdict_t *dict;
        http_transport_t *transport;
        ID flg;
+       ID sem;
 };
 
+#define HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector) \
+       err = wai_sem((connector)->sem, T_FOREVER); \
+       if (err < 0) { \
+               return err; \
+       }
+#define HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_VOID(connector) \
+       err = wai_sem((connector)->sem, T_FOREVER); \
+       if (err < 0) { \
+               return; \
+       }
+#define HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector) \
+       sig_sem((connector)->sem); 
+
 #define HTTP_CONNECTOR_FLAG_CREARMASK(flag) (~(flag))
 #define HTTP_CONNECTOR_FLAG_REQUEST 0x00000001
 #define HTTP_CONNECTOR_FLAG_EVENT   0x00000002
@@ -318,7 +332,9 @@ EXPORT ID http_connector_createendpoint(http_connector_t *connector, UB *host, W
        ID id;
        W err;
 
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
        id = http_reqdict_allocate(connector->dict, host, host_len, port, method);
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
        if (id < 0) {
                DP_ER("http_reqdict_allocate", id);
                return id; /* TODO */
@@ -338,9 +354,13 @@ EXPORT VOID http_connector_deleteendpoint(http_connector_t *connector, ID endpoi
 {
        http_reqentry_t *entry;
        Bool transport_close = True;
+       W err;
+
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_VOID(connector);
 
        entry = http_reqdict_getentrybyID(connector->dict, endpoint);
        if (entry == NULL) {
+               HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                return;
        }
 
@@ -362,6 +382,8 @@ EXPORT VOID http_connector_deleteendpoint(http_connector_t *connector, ID endpoi
        }
 
        http_reqdict_free(connector->dict, endpoint);
+
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
 }
 
 LOCAL W http_connector_searchwaiting(http_connector_t *connector)
@@ -401,6 +423,37 @@ LOCAL W http_connector_searchwaiting(http_connector_t *connector)
        return ret;
 }
 
+LOCAL Bool http_connector_isexistwaiting(http_connector_t *connector)
+{
+       http_reqentry_t *entry;
+       http_recdictiterator_t iter;
+       Bool cont, ret = False;
+
+       http_reqdictiterator_initialize(&iter, connector->dict);
+       for (;;) {
+               cont = http_reqdictiterator_next(&iter, &entry);
+               if (cont == False) {
+                       break;
+               }
+               if (entry->status == WAITING_TRANSPORT) {
+                       ret = True;
+                       break;
+               } else if (entry->status == SENDING_REQUEST) {
+                       ret = True;
+                       break;
+               } else if (entry->status == WAITING_RESPONSE) {
+                       ret = True;
+                       break;
+               } else if (entry->status == RECEIVING_RESPONSE) {
+                       ret = True;
+                       break;
+               }
+       }
+       http_reqdictiterator_finalize(&iter);
+
+       return ret;
+}
+
 LOCAL W http_connector_waitreceiving(http_connector_t *connector, TMOUT tmout)
 {
        W ret = 0;
@@ -444,10 +497,17 @@ LOCAL W http_connector_waitreceiving(http_connector_t *connector, TMOUT tmout)
 EXPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout)
 {
        W err;
-       Bool evt = False;
+       Bool evt = False, exist;
 
+       err = wai_flg(connector->flg, HTTP_CONNECTOR_FLAG_REQUEST, WF_AND|NOCLR, tmout);
+       if (err < 0) {
+               return err;
+       }
+
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
        err = http_connector_searchwaiting(connector);
        if (err < 0) {
+               HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                return err;
        }
        if (err > 0) {
@@ -455,7 +515,13 @@ EXPORT W http_connector_waitconnection(http_connector_t *connector, TMOUT tmout)
        }
        http_transport_releaseunusedendpoint(connector->transport);
 
+       exist = http_connector_isexistwaiting(connector);
+       if (exist == False) {
+               clr_flg(connector->flg, HTTP_CONNECTOR_FLAG_CLEARMASK_REQUEST);
+       }
+
        err = http_connector_waitreceiving(connector, tmout);
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
        if (err < 0) {
                return err;
        }
@@ -776,7 +842,9 @@ EXPORT W http_connector_getevent(http_connector_t *connector, http_connector_eve
                DP_ER("wai_flg", err);
                return err;
        }
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
        found = http_connector_searcheventtarget(connector, event);
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
        if (found == False) {
                err = clr_flg(connector->flg, HTTP_CONNECTOR_FLAG_CLEARMASK_EVENT);
                if (err < 0) {
@@ -823,10 +891,13 @@ EXPORT W http_connector_sendrequestline(http_connector_t *connector, ID endpoint
        Bool cont;
        CONST UB *str;
 
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
+
        HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_REQUEST_LINE, entry);
 
        err = http_requestlinestream_initialize(&reqline, entry->method, path, path_len);
        if (err < 0) {
+               HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                return err;
        }
        for (;;) {
@@ -842,11 +913,14 @@ EXPORT W http_connector_sendrequestline(http_connector_t *connector, ID endpoint
        http_requestlinestream_finalize(&reqline);
 
        if (err < 0) {
+               HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                return err;
        }
 
        entry->snd_state = SEND_HEADER_MINE;
 
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
+
        return 0;
 }
 
@@ -878,16 +952,21 @@ EXPORT W http_connector_sendheader(http_connector_t *connector, ID endpoint, UB
        http_reqentry_t *entry;
        W err;
 
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
+
        HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
 
        if (entry->snd_state == SEND_HEADER_MINE) {
                err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
                if (err < 0) {
+                       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                        return err;
                }
                entry->snd_state = SEND_HEADER_USER;
        }
 
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
+
        return 0;
 }
 
@@ -896,21 +975,27 @@ EXPORT W http_connector_sendheaderend(http_connector_t *connector, ID endpoint)
        http_reqentry_t *entry;
        W err;
 
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
+
        HTTP_CONNECTOR_SENDXXX_GET_CHECK_2(connector, endpoint, SEND_HEADER_MINE, SEND_HEADER_USER, entry);
 
        if (entry->snd_state == SEND_HEADER_MINE) {
                err = http_connector_writedefaultheader(connector, entry->transport, entry->host, entry->host_len);
                if (err < 0) {
+                       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                        return err;
                }
        }
        err = http_transport_write(connector->transport, entry->transport, "\r\n", 2);
        if (err < 0) {
+               HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
                return err;
        }
 
        entry->snd_state = SEND_MESSAGE_BODY;
 
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
+
        return 0;
 }
 
@@ -919,9 +1004,12 @@ EXPORT W http_connector_sendmessagebody(http_connector_t *connector, ID endpoint
        http_reqentry_t *entry;
        W err;
 
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
+
        HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
 
        err = http_transport_write(connector->transport, entry->transport, p, len);
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
        if (err < 0) {
                return err;
        }
@@ -932,11 +1020,16 @@ EXPORT W http_connector_sendmessagebody(http_connector_t *connector, ID endpoint
 EXPORT W http_connector_sendmessagebodyend(http_connector_t *connector, ID endpoint)
 {
        http_reqentry_t *entry;
+       W err;
+
+       HTTP_CONNECTOR_ENTER_CRITICAL_SECTION_RET_ERR(connector);
 
        HTTP_CONNECTOR_SENDXXX_GET_CHECK(connector, endpoint, SEND_MESSAGE_BODY, entry);
 
        entry->status = WAITING_RESPONSE;
 
+       HTTP_CONNECTOR_LEAVE_CRITICAL_SECTION(connector);
+
        return 0;
 }
 
@@ -959,6 +1052,11 @@ EXPORT http_connector_t* http_connector_new()
                DP_ER("cre_flg", connector->flg);
                goto error_flg;
        }
+       connector->sem = cre_sem(1, SEM_EXCL|DELEXIT);
+       if (connector->sem < 0) {
+               DP_ER("cre_sem", connector->sem);
+               goto error_sem;
+       }
        connector->transport = http_transport_new(10/*tmp*/);
        if (connector->transport == NULL) {
                DP_ER("http_transport_new", -1);
@@ -969,6 +1067,8 @@ EXPORT http_connector_t* http_connector_new()
 
        http_transport_delete(connector->transport);
 error_transport:
+       del_sem(connector->sem);
+error_sem:
        del_flg(connector->flg);
 error_flg:
        http_reqdict_delete(connector->dict);
@@ -980,6 +1080,7 @@ error_http_reqdict:
 EXPORT VOID http_connector_delete(http_connector_t *connector)
 {
        http_transport_delete(connector->transport);
+       del_sem(connector->sem);
        del_flg(connector->flg);
        http_reqdict_delete(connector->dict);
        free(connector);