diff --git a/CHANGELOG.md b/CHANGELOG.md index 83c41a82..80e7dce0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,10 @@ Expected: June 2021 * hide-database : specifies that a command is not visible in database. This can be useful for setting passwords and not exposing them to users. * hide-database-auto-completion : specifies that a command is not visible in database and in auto completion. This can be useful for a password that was put in device by super user, not be changed. +### Corrected Bugs + +* Fixed: [Multiple http requests in native restconf yields same reply #212](https://github.com/clicon/clixon/issues/212) + ## 5.1.0 15 April 2021 diff --git a/apps/restconf/restconf_main_native.c b/apps/restconf/restconf_main_native.c index f4544b14..2f4ec52f 100644 --- a/apps/restconf/restconf_main_native.c +++ b/apps/restconf/restconf_main_native.c @@ -946,12 +946,25 @@ restconf_connection(int s, struct evbuffer *ev; if ((ev = bufferevent_get_output(conn->bev)) != NULL){ - buf = (char*)evbuffer_pullup(ev, -1); buflen = evbuffer_get_length(ev); - clicon_debug(1, "%s buf:%s", __FUNCTION__, buf); if (buflen){ +#ifdef RESTCONF_LIBEVENT_POS_PATCH + size_t pos; + + pos = (size_t)conn->arg; +#endif + buf = (char*)evbuffer_pullup(ev, -1); + clicon_debug(1, "%s buf:%s", __FUNCTION__, buf); +#ifdef RESTCONF_LIBEVENT_POS_PATCH + if (buf_write(buf+pos, buflen, conn->sock, conn->ssl) < 0) + goto done; + pos += buflen; + conn->arg = (void*)pos; +#else + /* Does not work w multiple requests */ if (buf_write(buf, buflen, conn->sock, conn->ssl) < 0) goto done; +#endif } else{ /* Return 0 from evhtp parser can be that it needs more data. @@ -1231,6 +1244,12 @@ restconf_accept_client(int fd, /* * Register callbacks for actual data socket */ +#ifdef LIBEVENT_POS_PATCH + /* patch to keep track os position in output buffer + * cannot use drain/copyout since the start position is "freezed" in bufferevent_socket_new + */ + conn->arg = (void*)0; +#endif if (clixon_event_reg_fd(s, restconf_connection, (void*)conn, "restconf client socket") < 0) goto done; ok: diff --git a/include/clixon_custom.h b/include/clixon_custom.h index a0ff95da..fa157224 100644 --- a/include/clixon_custom.h +++ b/include/clixon_custom.h @@ -93,3 +93,14 @@ /* Name of default netns for clixon-restconf.yang socket/namespace field */ #define RESTCONF_NETNS_DEFAULT "default" + +/* Patch to keep track os position in output buffer for native restconf using libevent + * It addresses that multiple requests in a single TCP HTTP session will only reply first + * reply again + * Cannot use drain/copyout since the start position is "freezed" in bufferevent_socket_new + * Strange thing is that evbuffer_drain / evbuffer_copyout cannot be used due to freeze set + * One could have thought freeze was in place for writing only? + * Note may not wrap-around correctly at size-t boundary + + */ +#define RESTCONF_LIBEVENT_POS_PATCH diff --git a/test/test_restconf2.sh b/test/test_restconf_op.sh similarity index 95% rename from test/test_restconf2.sh rename to test/test_restconf_op.sh index 674a4285..7ca3e2fd 100755 --- a/test/test_restconf2.sh +++ b/test/test_restconf_op.sh @@ -197,6 +197,13 @@ expectpart "$(curl $CURLOPTS -X PUT -H "Content-Type: application/yang-data+json new "restconf GET datastore eth" expectpart "$(curl $CURLOPTS -X GET $RCPROTO://localhost/restconf/data/example:cont1/interface=local0)" 0 "HTTP/1.1 200 OK" '{"example:interface":\[{"name":"local0","type":"eth0"}\]}' +new "restconf DELETE whole datastore" +expectpart "$(curl $CURLOPTS -X DELETE $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 204 No Content" + +#--------------- Multiple request in single TCP tests + +expectpart "$(curl $CURLOPTS -H "Accept: application/yang-data+xml" -X GET $RCPROTO://localhost/restconf/data?content=config --next $CURLOPTS -H "Content-Type: application/yang-data+json" -X POST $RCPROTO://localhost/restconf/data -d '{"example:cont1":{"interface":{"name":"local0","type":"regular"}}}')" 0 "HTTP/1.1 200 OK" '' 'HTTP/1.1 201 Created' + #--------------- json type tests new "restconf POST type x3 POST" expectpart "$(curl $CURLOPTS -X POST -H "Content-Type: application/yang-data+json" -d '{"example:types":{"tint":42,"tdec64":42.123,"tbool":false,"tstr":"str"}}' $RCPROTO://localhost/restconf/data)" 0 "HTTP/1.1 201 Created" "Location: $RCPROTO://localhost/restconf/data/example:types"