Skip to content

Commit

Permalink
Add ne_getbuf().
Browse files Browse the repository at this point in the history
* src/ne_basic.c (ne_getbuf),
* src/ne_basic.h (ne_getbuf): New function.

* test/basic.c (getbuf, getbuf2): New tests.

* test/common/child.c (new_spawn_server2): Close listening socket
  once last accept() is done.
  • Loading branch information
notroj committed Nov 14, 2023
1 parent a07b8e2 commit cf0354f
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 1 deletion.
44 changes: 44 additions & 0 deletions src/ne_basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,50 @@ int ne_putbuf(ne_session *sess, const char *path,
return ret;
}

int ne_getbuf(ne_session *sess, const char *path,
char *buf, size_t *buflen)
{
ne_request *req = ne_request_create(sess, "GET", path);
int ret;
char *ptr;

do {
size_t remain = *buflen;
ssize_t rlen = -1;

ptr = buf;

ret = ne_begin_request(req);
if (ret != NE_OK) break;

while (remain > 0
&& (rlen = ne_read_response_block(req, ptr, remain)) > 0) {
remain -= rlen;
ptr += rlen;
}

if (rlen < 0) {
ret = NE_ERROR;
}
else if (rlen > 0) {
ne_set_error(sess, N_("Response buffer size too small"));
ret = NE_FAILED;
}

if (ret == NE_OK) ret = ne_end_request(req);
} while (ret == NE_RETRY);

if (ret == NE_OK)
*buflen = ptr - buf;

if (ret != NE_OK)
ne_close_connection(sess);

ne_request_destroy(req);

return ret;
}

/* Dispatch a GET request REQ, writing the response body to FD fd. If
* RANGE is non-NULL, then it is the value of the Range request
* header, e.g. "bytes=1-5". Returns an NE_* error code. */
Expand Down
8 changes: 8 additions & 0 deletions src/ne_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ int ne_put(ne_session *sess, const char *path, int fd);
int ne_putbuf(ne_session *sess, const char *path,
const char *buf, size_t buflen);

/* Perform a GET request on resource at 'path', writing the entity
* body which is returned to 'buffer', of maximum length *buflen. On
* return, *buflen is updated to reflect the number of bytes
* received. If the response content length exceeds the maximum,
* NE_FAILED is returned. */
int ne_getbuf(ne_session *sess, const char *path,
char *buf, size_t *buflen);

#define NE_DEPTH_ZERO (0)
#define NE_DEPTH_ONE (1)
#define NE_DEPTH_INFINITE (2)
Expand Down
1 change: 1 addition & 0 deletions src/neon.vers
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ NEON_0_32 {
NEON_0_33 {
ne_add_interim_handler;
ne_putbuf;
ne_getbuf;
};
58 changes: 58 additions & 0 deletions test/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,62 @@ static int get(void)
return destroy_and_wait(sess);
}


#define CHUNK(len, data) #len "\r\n" data "\r\n"

#define ABCDE_CHUNKS CHUNK(1, "a") CHUNK(1, "b") \
CHUNK(1, "c") CHUNK(1, "d") \
CHUNK(1, "e") CHUNK(0, "")

static int getbuf(void)
{
ne_session *sess;
char buffer[16];
size_t buflen = sizeof buffer;

CALL(make_session(&sess, single_serve_string,
"HTTP/1.1 200 OK\r\n" "Server: neon-test-server\r\n"
"Transfer-Encoding: chunked\r\n"
"\r\n"
ABCDE_CHUNKS));

ONREQ(ne_getbuf(sess, "/", buffer, &buflen));

ONV(buflen != 5, ("unexpected buffer length %" NE_FMT_SIZE_T, buflen));

ONV(memcmp("abcde", buffer, 5) != 0,
("mismatched chunked response: [%5s]", buffer));

return destroy_and_wait(sess);
}

static int getbuf2(void)
{
ne_session *sess;
char buf;
size_t buflen = sizeof buf;
int ret;

CALL(make_session(&sess, single_serve_string,
"HTTP/1.1 200 OK\r\n" "Server: neon-test-server\r\n"
"Content-Length: 5\r\n"
"\r\n"
"abcde"
"HTTP/1.1 200 OK\r\n" "Server: neon-test-server\r\n"
"Content-Length: 5\r\n"
"\r\n"
"abcde"));

ret = ne_getbuf(sess, "/", &buf, &buflen);
ONV(ret != NE_FAILED, ("overflow case gave %d not FAILED", ret));
ONV(buflen != 1, ("buffer length returned as %" NE_FMT_SIZE_T, buflen));

ret = any_request(sess, "/closeme");
ONN("failed to close connection", ret != NE_CONNECT);

return destroy_and_wait(sess);
}

#define CLASS_12 (NE_CAP_DAV_CLASS1 | NE_CAP_DAV_CLASS2)

static int options2(void)
Expand Down Expand Up @@ -335,6 +391,8 @@ ne_test tests[] = {
T(fail_range_unsatify),
T(dav_capabilities),
T(get),
T(getbuf),
T(getbuf2),
T(options2),
T(put),
T(NULL)
Expand Down
7 changes: 6 additions & 1 deletion test/common/child.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,12 @@ int new_spawn_server2(int count, server_fn fn, void *userdata,
exit(FAIL);
}

NE_DEBUG(NE_DBG_HTTP, "child got connection, invoking server\n");
NE_DEBUG(NE_DBG_HTTP, "child: got connection, invoking server\n");
if (iter == count) {
close(ls);
NE_DEBUG(NE_DBG_HTTP, "child: closed listening socket.\n");
}

ret = fn(sock, userdata);
NE_DEBUG(NE_DBG_HTTP, "child iteration #%d returns %d\n",
iter, ret);
Expand Down

0 comments on commit cf0354f

Please sign in to comment.