base
This commit is contained in:
+282
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
HTTP Request Handling
|
||||
Copyright (C) 1999-2005, Joe Orton <joe@manyfish.co.uk>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NE_REQUEST_H
|
||||
#define NE_REQUEST_H
|
||||
|
||||
#include "ne_utils.h" /* For ne_status */
|
||||
#include "ne_string.h" /* For ne_buffer */
|
||||
#include "ne_session.h"
|
||||
|
||||
BEGIN_NEON_DECLS
|
||||
|
||||
#define NE_OK (0) /* Success */
|
||||
#define NE_ERROR (1) /* Generic error; use ne_get_error(session) for message */
|
||||
#define NE_LOOKUP (2) /* Server or proxy hostname lookup failed */
|
||||
#define NE_AUTH (3) /* User authentication failed on server */
|
||||
#define NE_PROXYAUTH (4) /* User authentication failed on proxy */
|
||||
#define NE_CONNECT (5) /* Could not connect to server */
|
||||
#define NE_TIMEOUT (6) /* Connection timed out */
|
||||
#define NE_FAILED (7) /* The precondition failed */
|
||||
#define NE_RETRY (8) /* Retry request (ne_end_request ONLY) */
|
||||
#define NE_REDIRECT (9) /* See ne_redirect.h */
|
||||
|
||||
/* Opaque object representing a single HTTP request. */
|
||||
typedef struct ne_request_s ne_request;
|
||||
|
||||
/***** Request Handling *****/
|
||||
|
||||
/* Create a request in session 'sess', with given method and path.
|
||||
* 'path' must conform to the 'abs_path' grammar in RFC2396, with an
|
||||
* optional "? query" part, and MUST be URI-escaped by the caller. */
|
||||
ne_request *ne_request_create(ne_session *sess,
|
||||
const char *method, const char *path);
|
||||
|
||||
/* The request body will be taken from 'size' bytes of 'buffer'. */
|
||||
void ne_set_request_body_buffer(ne_request *req, const char *buffer,
|
||||
size_t size);
|
||||
|
||||
/* The request body will be taken from 'length' bytes read from the
|
||||
* file descriptor 'fd', starting from file offset 'offset'. */
|
||||
void ne_set_request_body_fd(ne_request *req, int fd,
|
||||
off_t offset, off_t length);
|
||||
|
||||
#ifdef NE_LFS
|
||||
/* Alternate version of ne_set_request_body_fd taking off64_t
|
||||
* offset type for systems supporting _LARGEFILE64_SOURCE. */
|
||||
void ne_set_request_body_fd64(ne_request *req, int fd,
|
||||
off64_t offset, off64_t length);
|
||||
#endif
|
||||
|
||||
/* "Pull"-based request body provider: a callback which is invoked to
|
||||
* provide blocks of request body on demand.
|
||||
*
|
||||
* Before each time the body is provided, the callback will be called
|
||||
* once with buflen == 0. The body may have to be provided >1 time
|
||||
* per request (for authentication retries etc.).
|
||||
*
|
||||
* For a call with buflen == 0, the callback must return zero on success
|
||||
* or non-zero on error; the session error string must be set on error.
|
||||
* For a call with buflen > 0, the callback must return:
|
||||
* <0 : error, abort request; session error string must be set.
|
||||
* 0 : ignore 'buffer' contents, end of body.
|
||||
* 0 < x <= buflen : buffer contains x bytes of body data. */
|
||||
typedef ssize_t (*ne_provide_body)(void *userdata,
|
||||
char *buffer, size_t buflen);
|
||||
|
||||
/* Install a callback which is invoked as needed to provide the
|
||||
* request body, a block at a time. The total size of the request
|
||||
* body is 'length'; the callback must ensure that it returns no more
|
||||
* than 'length' bytes in total. */
|
||||
void ne_set_request_body_provider(ne_request *req, off_t length,
|
||||
ne_provide_body provider, void *userdata);
|
||||
|
||||
#ifdef NE_LFS
|
||||
/* Duplicate version of ne_set_request_body_provider, taking an off64_t
|
||||
* offset. */
|
||||
void ne_set_request_body_provider64(ne_request *req, off64_t length,
|
||||
ne_provide_body provider, void *userdata);
|
||||
#endif
|
||||
|
||||
/* Handling response bodies; two callbacks must be provided:
|
||||
*
|
||||
* 1) 'acceptance' callback: determines whether you want to handle the
|
||||
* response body given the response-status information, e.g., if you
|
||||
* only want 2xx responses, say so here.
|
||||
*
|
||||
* 2) 'reader' callback: passed blocks of the response-body as they
|
||||
* arrive, if the acceptance callback returned non-zero. */
|
||||
|
||||
/* 'acceptance' callback type. Return non-zero to accept the response,
|
||||
* else zero to ignore it. */
|
||||
typedef int (*ne_accept_response)(void *userdata, ne_request *req,
|
||||
const ne_status *st);
|
||||
|
||||
/* An 'acceptance' callback which only accepts 2xx-class responses.
|
||||
* Ignores userdata. */
|
||||
int ne_accept_2xx(void *userdata, ne_request *req, const ne_status *st);
|
||||
|
||||
/* An acceptance callback which accepts all responses. Ignores
|
||||
* userdata. */
|
||||
int ne_accept_always(void *userdata, ne_request *req, const ne_status *st);
|
||||
|
||||
/* Callback for reading a block of data. Returns zero on success, or
|
||||
* non-zero on error. If returning an error, the response will be
|
||||
* aborted and the callback will not be invoked again. The request
|
||||
* dispatch (or ne_read_response_block call) will fail with NE_ERROR;
|
||||
* the session error string should have been set by the callback. */
|
||||
typedef int (*ne_block_reader)(void *userdata, const char *buf, size_t len);
|
||||
|
||||
/* Add a response reader for the given request, with the given
|
||||
* acceptance function. userdata is passed as the first argument to
|
||||
* the acceptance + reader callbacks.
|
||||
*
|
||||
* The acceptance callback is called once each time the request is
|
||||
* sent: it may be sent >1 time because of authentication retries etc.
|
||||
* For each time the acceptance callback is called, if it returns
|
||||
* non-zero, blocks of the response body will be passed to the reader
|
||||
* callback as the response is read. After all the response body has
|
||||
* been read, the callback will be called with a 'len' argument of
|
||||
* zero. */
|
||||
void ne_add_response_body_reader(ne_request *req, ne_accept_response accpt,
|
||||
ne_block_reader reader, void *userdata);
|
||||
|
||||
/* Retrieve the value of the response header field with given name;
|
||||
* returns NULL if no response header with given name was found. The
|
||||
* return value is valid only until the next call to either
|
||||
* ne_request_destroy or ne_begin_request for this request. */
|
||||
const char *ne_get_response_header(ne_request *req, const char *name);
|
||||
|
||||
/* Iterator interface for response headers: if passed a NULL cursor,
|
||||
* returns the first header; if passed a non-NULL cursor pointer,
|
||||
* returns the next header. The return value is a cursor pointer: if
|
||||
* it is non-NULL, *name and *value are set to the name and value of
|
||||
* the header field. If the return value is NULL, no more headers are
|
||||
* found, *name and *value are undefined.
|
||||
*
|
||||
* The order in which response headers is returned is undefined. Both
|
||||
* the cursor and name/value pointers are valid only until the next
|
||||
* call to either ne_request_destroy or ne_begin_request for this
|
||||
* request. */
|
||||
void *ne_response_header_iterate(ne_request *req, void *cursor,
|
||||
const char **name, const char **value);
|
||||
|
||||
/* Adds a header to the request with given name and value. */
|
||||
void ne_add_request_header(ne_request *req, const char *name,
|
||||
const char *value);
|
||||
/* Adds a header to the request with given name, using printf-like
|
||||
* format arguments for the value. */
|
||||
void ne_print_request_header(ne_request *req, const char *name,
|
||||
const char *format, ...)
|
||||
ne_attribute((format(printf, 3, 4)));
|
||||
|
||||
/* ne_request_dispatch: Sends the given request, and reads the
|
||||
* response. Returns:
|
||||
* - NE_OK if the request was sent and response read successfully
|
||||
* - NE_AUTH, NE_PROXYAUTH for a server or proxy server authentication error
|
||||
* - NE_CONNECT if connection could not be established
|
||||
* - NE_TIMEOUT if an timeout occurred sending or reading from the server
|
||||
* - NE_ERROR for other fatal dispatch errors
|
||||
* On any error, the session error string is set. On success or
|
||||
* authentication error, the actual response-status can be retrieved using
|
||||
* ne_get_status(). */
|
||||
int ne_request_dispatch(ne_request *req);
|
||||
|
||||
/* Returns a pointer to the response status information for the given
|
||||
* request; pointer is valid until request object is destroyed. */
|
||||
const ne_status *ne_get_status(const ne_request *req) ne_attribute((const));
|
||||
|
||||
/* Returns pointer to session associated with request. */
|
||||
ne_session *ne_get_session(const ne_request *req) ne_attribute((const));
|
||||
|
||||
/* Destroy memory associated with request pointer */
|
||||
void ne_request_destroy(ne_request *req);
|
||||
|
||||
/* "Caller-pulls" request interface. This is an ALTERNATIVE interface
|
||||
* to ne_request_dispatch: either use that, or do all this yourself:
|
||||
*
|
||||
* caller must call:
|
||||
* 1. ne_begin_request (fail if returns non-NE_OK)
|
||||
* 2. while(ne_read_response_block(...) > 0) ... loop ...;
|
||||
* (fail if ne_read_response_block returns <0)
|
||||
* 3. ne_end_request
|
||||
*
|
||||
* ne_end_request and ne_begin_request both return an NE_* code; if
|
||||
* ne_end_request returns NE_RETRY, you must restart the loop from (1)
|
||||
* above. */
|
||||
int ne_begin_request(ne_request *req);
|
||||
int ne_end_request(ne_request *req);
|
||||
|
||||
/* Read a block of the response into the passed buffer of size 'buflen'.
|
||||
*
|
||||
* Returns:
|
||||
* <0 - error, stop reading.
|
||||
* 0 - end of response
|
||||
* >0 - number of bytes read into buffer.
|
||||
*/
|
||||
ssize_t ne_read_response_block(ne_request *req, char *buffer, size_t buflen);
|
||||
|
||||
/* Read response blocks until end of response; exactly equivalent to
|
||||
* calling ne_read_response_block() until it returns 0. Returns
|
||||
* non-zero on error. */
|
||||
int ne_discard_response(ne_request *req);
|
||||
|
||||
/* Read response blocks until end of response, writing content to the
|
||||
* given file descriptor. Returns NE_ERROR on error. */
|
||||
int ne_read_response_to_fd(ne_request *req, int fd);
|
||||
|
||||
/* If 'flag' is non-zer, enable the HTTP/1.1 "Expect: 100-continue"
|
||||
* feature for the request, which allows the server to send an error
|
||||
* response before the request body is sent. This should only be used
|
||||
* if the server is known to support the feature (not all HTTP/1.1
|
||||
* servers do); the request will time out and fail otherwise. */
|
||||
void ne_set_request_expect100(ne_request *req, int flag);
|
||||
|
||||
/**** Request hooks handling *****/
|
||||
|
||||
typedef void (*ne_free_hooks)(void *cookie);
|
||||
|
||||
/* Hook called when a create is created; passed the request method,
|
||||
* and the string used as the Request-URI (which may be an abs_path,
|
||||
* or an absoluteURI, depending on whether an HTTP proxy is in
|
||||
* use). */
|
||||
typedef void (*ne_create_request_fn)(ne_request *req, void *userdata,
|
||||
const char *method, const char *requri);
|
||||
void ne_hook_create_request(ne_session *sess,
|
||||
ne_create_request_fn fn, void *userdata);
|
||||
|
||||
/* Hook called before the request is sent. 'header' is the raw HTTP
|
||||
* header before the trailing CRLF is added: add in more here. */
|
||||
typedef void (*ne_pre_send_fn)(ne_request *req, void *userdata,
|
||||
ne_buffer *header);
|
||||
void ne_hook_pre_send(ne_session *sess, ne_pre_send_fn fn, void *userdata);
|
||||
|
||||
/* Hook called after the request is dispatched (request sent, and
|
||||
* the entire response read). If an error occurred reading the response,
|
||||
* this hook will not run. May return:
|
||||
* NE_OK everything is okay
|
||||
* NE_RETRY try sending the request again.
|
||||
* anything else signifies an error, and the request is failed. The return
|
||||
* code is passed back the _dispatch caller, so the session error must
|
||||
* also be set appropriately (ne_set_error).
|
||||
*/
|
||||
typedef int (*ne_post_send_fn)(ne_request *req, void *userdata,
|
||||
const ne_status *status);
|
||||
void ne_hook_post_send(ne_session *sess, ne_post_send_fn fn, void *userdata);
|
||||
|
||||
/* Hook called when the function is destroyed. */
|
||||
typedef void (*ne_destroy_req_fn)(ne_request *req, void *userdata);
|
||||
void ne_hook_destroy_request(ne_session *sess,
|
||||
ne_destroy_req_fn fn, void *userdata);
|
||||
|
||||
typedef void (*ne_destroy_sess_fn)(void *userdata);
|
||||
/* Hook called when the session is destroyed. */
|
||||
void ne_hook_destroy_session(ne_session *sess,
|
||||
ne_destroy_sess_fn fn, void *userdata);
|
||||
|
||||
/* Store an opaque context for the request, 'priv' is returned by a
|
||||
* call to ne_request_get_private with the same ID. */
|
||||
void ne_set_request_private(ne_request *req, const char *id, void *priv);
|
||||
void *ne_get_request_private(ne_request *req, const char *id);
|
||||
|
||||
END_NEON_DECLS
|
||||
|
||||
#endif /* NE_REQUEST_H */
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
socket handling interface
|
||||
Copyright (C) 1999-2005, Joe Orton <joe@manyfish.co.uk>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
|
||||
MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NE_SOCKET_H
|
||||
#define NE_SOCKET_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ne_defs.h"
|
||||
#include "ne_ssl.h" /* for ne_ssl_context */
|
||||
|
||||
BEGIN_NEON_DECLS
|
||||
|
||||
#define NE_SOCK_ERROR (-1)
|
||||
/* Read/Write timed out */
|
||||
#define NE_SOCK_TIMEOUT (-2)
|
||||
/* Socket was closed */
|
||||
#define NE_SOCK_CLOSED (-3)
|
||||
/* Connection was reset (e.g. server crashed) */
|
||||
#define NE_SOCK_RESET (-4)
|
||||
/* Secure connection was closed without proper SSL shutdown. */
|
||||
#define NE_SOCK_TRUNC (-5)
|
||||
|
||||
/* ne_socket represents a TCP socket. */
|
||||
typedef struct ne_socket_s ne_socket;
|
||||
|
||||
/* ne_sock_addr represents an address object. */
|
||||
typedef struct ne_sock_addr_s ne_sock_addr;
|
||||
|
||||
#ifndef NE_INET_ADDR_DEFINED
|
||||
typedef struct ne_inet_addr_s ne_inet_addr;
|
||||
#endif
|
||||
|
||||
/* While neon itself doesn't require per-process global
|
||||
* initialization, some platforms do, and so does the OpenSSL
|
||||
* library. */
|
||||
int ne_sock_init(void);
|
||||
|
||||
/* Shutdown any underlying libraries. */
|
||||
void ne_sock_exit(void);
|
||||
|
||||
/* Resolve the given hostname. 'flags' must be zero. Hex
|
||||
* string IPv6 addresses (e.g. `::1') may be enclosed in brackets
|
||||
* (e.g. `[::1]'). */
|
||||
ne_sock_addr *ne_addr_resolve(const char *hostname, int flags);
|
||||
|
||||
/* Returns zero if name resolution was successful, non-zero on
|
||||
* error. */
|
||||
int ne_addr_result(const ne_sock_addr *addr);
|
||||
|
||||
/* Returns the first network address associated with the 'addr'
|
||||
* object. Undefined behaviour if ne_addr_result returns non-zero for
|
||||
* 'addr'; otherwise, never returns NULL. */
|
||||
const ne_inet_addr *ne_addr_first(ne_sock_addr *addr);
|
||||
|
||||
/* Returns the next network address associated with the 'addr' object,
|
||||
* or NULL if there are no more. */
|
||||
const ne_inet_addr *ne_addr_next(ne_sock_addr *addr);
|
||||
|
||||
/* NB: the pointers returned by ne_addr_first and ne_addr_next are
|
||||
* valid until ne_addr_destroy is called for the corresponding
|
||||
* ne_sock_addr object. They must not be passed to ne_iaddr_free. */
|
||||
|
||||
/* If name resolution fails, copies the error string into 'buffer',
|
||||
* which is of size 'bufsiz'. 'buffer' is returned. */
|
||||
char *ne_addr_error(const ne_sock_addr *addr, char *buffer, size_t bufsiz);
|
||||
|
||||
/* Destroys an address object created by ne_addr_resolve. */
|
||||
void ne_addr_destroy(ne_sock_addr *addr);
|
||||
|
||||
/* Network address type; IPv4 or IPv6 */
|
||||
typedef enum {
|
||||
ne_iaddr_ipv4 = 0,
|
||||
ne_iaddr_ipv6
|
||||
} ne_iaddr_type;
|
||||
|
||||
/* Create a network address from raw byte representation (in network
|
||||
* byte order) of given type. 'raw' must be four bytes for an IPv4
|
||||
* address, 16 bytes for an IPv6 address. May return NULL if address
|
||||
* type is not supported. */
|
||||
ne_inet_addr *ne_iaddr_make(ne_iaddr_type type, const unsigned char *raw);
|
||||
|
||||
/* Compare two network addresses i1 and i2; return non-zero if they
|
||||
* are not equal. */
|
||||
int ne_iaddr_cmp(const ne_inet_addr *i1, const ne_inet_addr *i2);
|
||||
|
||||
/* Returns the type of the given network address. */
|
||||
ne_iaddr_type ne_iaddr_typeof(const ne_inet_addr *ia);
|
||||
|
||||
/* Prints the string representation of network address 'ia' into the
|
||||
* 'buffer', which is of size 'bufsiz'. Returns 'buffer'. */
|
||||
char *ne_iaddr_print(const ne_inet_addr *ia, char *buffer, size_t bufsiz);
|
||||
|
||||
/* Free a network address created using ne_iaddr_make. */
|
||||
void ne_iaddr_free(ne_inet_addr *addr);
|
||||
|
||||
/* Create a TCP socket; returns NULL on error. */
|
||||
ne_socket *ne_sock_create(void);
|
||||
|
||||
/* Connect the socket to server at address 'addr' on port 'port'.
|
||||
* Returns non-zero if a connection could not be established. */
|
||||
int ne_sock_connect(ne_socket *sock, const ne_inet_addr *addr,
|
||||
unsigned int port);
|
||||
|
||||
/* ne_sock_read reads up to 'count' bytes into 'buffer'.
|
||||
* Returns:
|
||||
* NE_SOCK_* on error,
|
||||
* >0 length of data read into buffer.
|
||||
*/
|
||||
ssize_t ne_sock_read(ne_socket *sock, char *buffer, size_t count);
|
||||
|
||||
/* ne_sock_peek reads up to 'count' bytes into 'buffer', but the data
|
||||
* will still be returned on a subsequent call to ne_sock_read or
|
||||
* ne_sock_peek.
|
||||
* Returns:
|
||||
* NE_SOCK_* on error,
|
||||
* >0 length of data read into buffer.
|
||||
*/
|
||||
ssize_t ne_sock_peek(ne_socket *sock, char *buffer, size_t count);
|
||||
|
||||
/* Block for up to 'n' seconds until data becomes available for reading
|
||||
* on the socket. Returns:
|
||||
* NE_SOCK_* on error,
|
||||
* NE_SOCK_TIMEOUT if no data arrives in 'n' seconds.
|
||||
* 0 if data arrived on the socket.
|
||||
*/
|
||||
int ne_sock_block(ne_socket *sock, int n);
|
||||
|
||||
/* Writes 'count' bytes of 'data' to the socket.
|
||||
* Returns 0 on success, NE_SOCK_* on error. */
|
||||
int ne_sock_fullwrite(ne_socket *sock, const char *data, size_t count);
|
||||
|
||||
/* Reads an LF-terminated line into 'buffer', and NUL-terminate it.
|
||||
* At most 'len' bytes are read (including the NUL terminator).
|
||||
* Returns:
|
||||
* NE_SOCK_* on error,
|
||||
* >0 number of bytes read (including NUL terminator)
|
||||
*/
|
||||
ssize_t ne_sock_readline(ne_socket *sock, char *buffer, size_t len);
|
||||
|
||||
/* Read exactly 'len' bytes into buffer; returns 0 on success,
|
||||
* NE_SOCK_* on error. */
|
||||
ssize_t ne_sock_fullread(ne_socket *sock, char *buffer, size_t len);
|
||||
|
||||
/* Accept a connection on listening socket 'fd'. */
|
||||
int ne_sock_accept(ne_socket *sock, int fd);
|
||||
|
||||
/* Returns the file descriptor used for socket 'sock'. */
|
||||
int ne_sock_fd(const ne_socket *sock);
|
||||
|
||||
/* Close the socket, and destroy the socket object. Returns non-zero
|
||||
* on error. */
|
||||
int ne_sock_close(ne_socket *sock);
|
||||
|
||||
/* Return current error string for socket. */
|
||||
const char *ne_sock_error(const ne_socket *sock);
|
||||
|
||||
/* Set read timeout for socket. */
|
||||
void ne_sock_read_timeout(ne_socket *sock, int timeout);
|
||||
|
||||
/* Negotiate an SSL connection on socket as an SSL server, using given
|
||||
* SSL context. */
|
||||
int ne_sock_accept_ssl(ne_socket *sock, ne_ssl_context *ctx);
|
||||
|
||||
/* Negotiate an SSL connection on socket as an SSL client, using given
|
||||
* SSL context. The 'userdata' parameter is associated with the
|
||||
* underlying SSL library's socket structure for use in callbacks.
|
||||
* Returns zero on success, or non-zero on error. */
|
||||
int ne_sock_connect_ssl(ne_socket *sock, ne_ssl_context *ctx,
|
||||
void *userdata);
|
||||
|
||||
END_NEON_DECLS
|
||||
|
||||
#endif /* NE_SOCKET_H */
|
||||
Reference in New Issue
Block a user