Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ne_getbuf(). #133

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
4 changes: 2 additions & 2 deletions test/request.c
Original file line number Diff line number Diff line change
Expand Up @@ -2366,8 +2366,8 @@ static int retry_408(void)
ne_session *sess;

/* Serve two responses down a single persistent connection, the
* second of which is invalid and will cause the request to be
* aborted. */
* second of which should be treated as a timed-out persistent
* connection, i.e. should be retried on a new connection. */
CALL(multi_session_server(&sess, "http", "localhost",
2, single_serve_string,
EMPTY_RESP
Expand Down