You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2012/04/23 14:33:03 UTC
svn commit: r1329209 [18/38] - in /subversion/branches/javahl-ra: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/ build/win32/
contrib/client-side/emacs/ contrib/client-side/vim/
contrib/server-side/mod_dontdothat/ notes/ notes/a...
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/ra_serf.h Mon Apr 23 12:32:48 2012
@@ -39,6 +39,7 @@
#include "svn_dirent_uri.h"
#include "private/svn_dav_protocol.h"
+#include "private/svn_subr_private.h"
#include "blncache.h"
@@ -70,6 +71,10 @@ typedef struct svn_ra_serf__connection_t
/* Our connection to a server. */
serf_connection_t *conn;
+ /* The server is not Apache/mod_dav_svn (directly) and only supports
+ HTTP/1.0. Thus, we cannot send chunked requests. */
+ svn_boolean_t http10;
+
/* Bucket allocator for this connection. */
serf_bucket_alloc_t *bkt_alloc;
@@ -78,6 +83,7 @@ typedef struct svn_ra_serf__connection_t
/* Are we using ssl */
svn_boolean_t using_ssl;
+ int server_cert_failures; /* Collected cert failures in chain */
/* Should we ask for compressed responses? */
svn_boolean_t using_compression;
@@ -147,6 +153,9 @@ struct svn_ra_serf__session_t {
svn_cancel_func_t cancel_func;
void *cancel_baton;
+ /* Ev2 shim callbacks */
+ svn_delta_shim_callbacks_t *shim_callbacks;
+
/* Error that we've received but not yet returned upstream. */
svn_error_t *pending_error;
@@ -315,12 +324,6 @@ svn_ra_serf__conn_setup(apr_socket_t *so
void *baton,
apr_pool_t *pool);
-serf_bucket_t*
-svn_ra_serf__accept_response(serf_request_t *request,
- serf_bucket_t *stream,
- void *acceptor_baton,
- apr_pool_t *pool);
-
void
svn_ra_serf__conn_closed(serf_connection_t *conn,
void *closed_baton,
@@ -347,24 +350,6 @@ svn_ra_serf__handle_client_cert_pw(void
const char *cert_path,
const char **password);
-/*
- * Create a REQUEST with an associated REQ_BKT in the SESSION.
- *
- * If HDRS_BKT is not-NULL, it will be set to a headers_bucket that
- * corresponds to the new request.
- *
- * The request will be METHOD at URL.
- *
- * If BODY_BKT is not-NULL, it will be sent as the request body.
- *
- * If CONTENT_TYPE is not-NULL, it will be sent as the Content-Type header.
- */
-svn_error_t *
-svn_ra_serf__setup_serf_req(serf_request_t *request,
- serf_bucket_t **req_bkt, serf_bucket_t **hdrs_bkt,
- svn_ra_serf__connection_t *conn,
- const char *method, const char *url,
- serf_bucket_t *body_bkt, const char *content_type);
/*
* This function will run the serf context in SESS until *DONE is TRUE.
@@ -381,29 +366,20 @@ typedef svn_error_t *
void *handler_baton,
apr_pool_t *pool);
-/* Callback for setting up a complete serf request */
-typedef svn_error_t *
-(*svn_ra_serf__request_setup_t)(serf_request_t *request,
- void *setup_baton,
- serf_bucket_t **req_bkt,
- serf_response_acceptor_t *acceptor,
- void **acceptor_baton,
- svn_ra_serf__response_handler_t *handler,
- void **handler_baton,
- apr_pool_t *pool);
-
/* Callback for when a request body is needed. */
+/* ### should pass a scratch_pool */
typedef svn_error_t *
(*svn_ra_serf__request_body_delegate_t)(serf_bucket_t **body_bkt,
void *baton,
serf_bucket_alloc_t *alloc,
- apr_pool_t *pool);
+ apr_pool_t *request_pool);
/* Callback for when request headers are needed. */
+/* ### should pass a scratch_pool */
typedef svn_error_t *
(*svn_ra_serf__request_header_delegate_t)(serf_bucket_t *headers,
void *baton,
- apr_pool_t *pool);
+ apr_pool_t *request_pool);
/* Callback for when a response has an error. */
typedef svn_error_t *
@@ -437,15 +413,6 @@ typedef struct svn_ra_serf__handler_t {
svn_ra_serf__response_error_t response_error;
void *response_error_baton;
- /* This function and baton will be executed when the request is about
- * to be delivered by serf.
- *
- * This just passes through serf's raw request creation parameters.
- * None of the other parameters will be utilized if this field is set.
- */
- svn_ra_serf__request_setup_t setup;
- void *setup_baton;
-
/* This function and baton pair allows for custom request headers to
* be set.
*
@@ -509,30 +476,28 @@ typedef struct svn_ra_serf__xml_parser_t
*/
typedef svn_error_t *
(*svn_ra_serf__xml_start_element_t)(svn_ra_serf__xml_parser_t *parser,
- void *baton,
svn_ra_serf__dav_props_t name,
- const char **attrs);
+ const char **attrs,
+ apr_pool_t *scratch_pool);
/* Callback invoked with @a baton by our XML @a parser when an element with
* the @a name is closed.
*/
typedef svn_error_t *
(*svn_ra_serf__xml_end_element_t)(svn_ra_serf__xml_parser_t *parser,
- void *baton,
- svn_ra_serf__dav_props_t name);
+ svn_ra_serf__dav_props_t name,
+ apr_pool_t *scratch_pool);
/* Callback invoked with @a baton by our XML @a parser when a CDATA portion
* of @a data with size @a len is encountered.
*
* This may be invoked multiple times for the same tag.
- *
- * @see svn_ra_serf__expand_string
*/
typedef svn_error_t *
(*svn_ra_serf__xml_cdata_chunk_handler_t)(svn_ra_serf__xml_parser_t *parser,
- void *baton,
const char *data,
- apr_size_t len);
+ apr_size_t len,
+ apr_pool_t *scratch_pool);
/*
* Helper structure associated with handle_xml_parser handler that will
@@ -881,16 +846,6 @@ svn_ra_serf__expand_ns(svn_ra_serf__dav_
svn_ra_serf__ns_t *ns_list,
const char *name);
-/*
- * Expand the string represented by @a cur with a current size of @a
- * cur_len by appending @a new with a size of @a new_len.
- *
- * The reallocated string is made in @a pool.
- */
-void
-svn_ra_serf__expand_string(const char **cur, apr_size_t *cur_len,
- const char *new, apr_size_t new_len,
- apr_pool_t *pool);
/** PROPFIND-related functions **/
@@ -1453,6 +1408,29 @@ svn_ra_serf__error_on_status(int status_
const char *path,
const char *location);
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks);
+
+
+svn_error_t *
+svn_ra_serf__copy_into_spillbuf(svn_spillbuf_t **spillbuf,
+ serf_bucket_t *bkt,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+serf_bucket_t *
+svn_ra_serf__create_sb_bucket(svn_spillbuf_t *spillbuf,
+ serf_bucket_alloc_t *allocator,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+
+svn_error_t *
+svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
+ const char **url,
+ apr_pool_t *pool);
+
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/replay.c Mon Apr 23 12:32:48 2012
@@ -40,6 +40,8 @@
#include "svn_path.h"
#include "svn_private_config.h"
+#include "private/svn_string_private.h"
+
#include "ra_serf.h"
@@ -83,8 +85,7 @@ typedef struct prop_info_t {
const char *name;
svn_boolean_t del_prop;
- const char *data;
- apr_size_t len;
+ svn_stringbuf_t *prop_value;
replay_info_t *parent;
} prop_info_t;
@@ -165,6 +166,7 @@ push_state(svn_ra_serf__xml_parser_t *pa
info->pool = replay_ctx->dst_rev_pool;
info->parent = parser->state->private;
+ info->prop_value = svn_stringbuf_create_empty(info->pool);
parser->state->private = info;
}
@@ -174,11 +176,11 @@ push_state(svn_ra_serf__xml_parser_t *pa
static svn_error_t *
start_replay(svn_ra_serf__xml_parser_t *parser,
- void *userData,
svn_ra_serf__dav_props_t name,
- const char **attrs)
+ const char **attrs,
+ apr_pool_t *scratch_pool)
{
- replay_context_t *ctx = userData;
+ replay_context_t *ctx = parser->user_data;
replay_state_e state;
state = parser->state->current_state;
@@ -471,14 +473,12 @@ start_replay(svn_ra_serf__xml_parser_t *
static svn_error_t *
end_replay(svn_ra_serf__xml_parser_t *parser,
- void *userData,
- svn_ra_serf__dav_props_t name)
+ svn_ra_serf__dav_props_t name,
+ apr_pool_t *scratch_pool)
{
- replay_context_t *ctx = userData;
+ replay_context_t *ctx = parser->user_data;
replay_state_e state;
- UNUSED_CTX(ctx);
-
state = parser->state->current_state;
if (state == REPORT &&
@@ -535,15 +535,17 @@ end_replay(svn_ra_serf__xml_parser_t *pa
}
else
{
- svn_string_t tmp_prop;
+ const svn_string_t *morph;
- tmp_prop.data = info->data;
- tmp_prop.len = info->len;
+ morph = svn_stringbuf__morph_into_string(info->prop_value);
+#ifdef SVN_DEBUG
+ info->prop_value = NULL; /* morph killed the stringbuf. */
+#endif
if (strcmp(name.name, "change-file-prop") == 0)
- prop_val = svn_base64_decode_string(&tmp_prop, ctx->file_pool);
+ prop_val = svn_base64_decode_string(morph, ctx->file_pool);
else
- prop_val = svn_base64_decode_string(&tmp_prop, ctx->dst_rev_pool);
+ prop_val = svn_base64_decode_string(morph, ctx->dst_rev_pool);
}
SVN_ERR(info->change(info->parent->baton, info->name, prop_val,
@@ -556,11 +558,11 @@ end_replay(svn_ra_serf__xml_parser_t *pa
static svn_error_t *
cdata_replay(svn_ra_serf__xml_parser_t *parser,
- void *userData,
const char *data,
- apr_size_t len)
+ apr_size_t len,
+ apr_pool_t *scratch_pool)
{
- replay_context_t *replay_ctx = userData;
+ replay_context_t *replay_ctx = parser->user_data;
replay_state_e state;
UNUSED_CTX(replay_ctx);
@@ -584,8 +586,7 @@ cdata_replay(svn_ra_serf__xml_parser_t *
{
prop_info_t *info = parser->state->private;
- svn_ra_serf__expand_string(&info->data, &info->len,
- data, len, parser->state->pool);
+ svn_stringbuf_appendbytes(info->prop_value, data, len);
}
return SVN_NO_ERROR;
@@ -845,7 +846,26 @@ svn_ra_serf__replay_range(svn_ra_session
/* Run the serf loop, send outgoing and process incoming requests.
This request will block when there are no more requests to send or
- responses to receive, so we have to be careful on our bookkeeping. */
+ responses to receive, so we have to be careful on our bookkeeping.
+
+ ### we should probably adjust this timeout. if we get (say) 3
+ ### requests completed, then we want to exit immediately rather
+ ### than block for a few seconds. that will allow us to clear up
+ ### those 3 requests. if we have queued all of our revisions,
+ ### then we may want to block until timeout since we really don't
+ ### have much work other than destroying memory. (though that
+ ### is important, as we could end up with 50 src_rev_pool pools)
+
+ ### idea: when a revision is marked DONE, we can probably destroy
+ ### most of the memory. that will reduce pressue to have serf
+ ### return control to us, to complete the major memory disposal.
+
+ ### theoretically, we should use an iterpool here, but it turns
+ ### out that serf doesn't even use the pool param. if we grow
+ ### an iterpool in this loop for other purposes, then yeah: go
+ ### ahead and apply it here, too, in case serf eventually uses
+ ### that parameter.
+ */
status = serf_context_run(session->context, session->timeout,
pool);
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/serf.c Mon Apr 23 12:32:48 2012
@@ -103,12 +103,11 @@ load_http_auth_types(apr_pool_t *pool, s
if (http_auth_types)
{
- char *token, *last;
+ char *token;
char *auth_types_list = apr_palloc(pool, strlen(http_auth_types) + 1);
apr_collapse_spaces(auth_types_list, http_auth_types);
- while ((token = apr_strtok(auth_types_list, ";", &last)) != NULL)
+ while ((token = svn_cstring_tokenize(";", &auth_types_list)) != NULL)
{
- auth_types_list = NULL;
if (svn_cstring_casecmp("basic", token) == 0)
*authn_types |= SERF_AUTHN_BASIC;
else if (svn_cstring_casecmp("digest", token) == 0)
@@ -398,6 +397,8 @@ svn_ra_serf__open(svn_ra_session_t *sess
serf_sess->conns[0] = apr_pcalloc(serf_sess->pool,
sizeof(*serf_sess->conns[0]));
+ serf_sess->conns[0]->http10 = TRUE; /* until we confirm HTTP/1.1 */
+ serf_sess->conns[0]->http10 = FALSE; /* ### don't change behavior yet */
serf_sess->conns[0]->bkt_alloc =
serf_bucket_allocator_create(serf_sess->pool, NULL, NULL);
serf_sess->conns[0]->session = serf_sess;
@@ -406,7 +407,6 @@ svn_ra_serf__open(svn_ra_session_t *sess
serf_sess->conns[0]->using_ssl = serf_sess->using_ssl;
serf_sess->conns[0]->using_compression = serf_sess->using_compression;
serf_sess->conns[0]->hostname = url.hostname;
- serf_sess->conns[0]->useragent = NULL;
/* create the user agent string */
if (callbacks->get_client_string)
@@ -1063,7 +1063,7 @@ svn_ra_serf__get_dir(svn_ra_session_t *r
return SVN_NO_ERROR;
}
-static svn_error_t *
+svn_error_t *
svn_ra_serf__get_repos_root(svn_ra_session_t *ra_session,
const char **url,
apr_pool_t *pool)
@@ -1157,7 +1157,8 @@ static const svn_ra__vtable_t serf_vtabl
svn_ra_serf__replay,
svn_ra_serf__has_capability,
svn_ra_serf__replay_range,
- svn_ra_serf__get_deleted_rev
+ svn_ra_serf__get_deleted_rev,
+ svn_ra_serf__register_editor_shim_callbacks
};
svn_error_t *
@@ -1195,6 +1196,7 @@ svn_ra_serf__init(const svn_version_t *l
|| serf_minor < SERF_MINOR_VERSION)
{
return svn_error_createf(
+ /* ### should return a unique error */
SVN_ERR_VERSION_MISMATCH, NULL,
_("ra_serf was compiled for serf %d.%d.%d but loaded "
"an incompatible %d.%d.%d library"),
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/update.c Mon Apr 23 12:32:48 2012
@@ -43,6 +43,7 @@
#include "svn_private_config.h"
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
+#include "private/svn_string_private.h"
#include "ra_serf.h"
#include "../libsvn_ra/ra_loader.h"
@@ -241,8 +242,7 @@ typedef struct report_info_t
*/
const char *prop_ns;
const char *prop_name;
- const char *prop_val;
- apr_size_t prop_val_len;
+ svn_stringbuf_t *prop_value;
const char *prop_encoding;
} report_info_t;
@@ -397,6 +397,7 @@ push_state(svn_ra_serf__xml_parser_t *pa
new_info = apr_pcalloc(info_parent_pool, sizeof(*new_info));
new_info->pool = svn_pool_create(info_parent_pool);
new_info->lock_token = NULL;
+ new_info->prop_value = svn_stringbuf_create_empty(new_info->pool);
new_info->dir = apr_pcalloc(new_info->pool, sizeof(*new_info->dir));
new_info->dir->pool = new_info->pool;
@@ -441,6 +442,7 @@ push_state(svn_ra_serf__xml_parser_t *pa
new_info->file_baton = NULL;
new_info->lock_token = NULL;
new_info->fetch_file = FALSE;
+ new_info->prop_value = svn_stringbuf_create_empty(new_info->pool);
/* Point at our parent's directory state. */
new_info->dir = info->dir;
@@ -1327,11 +1329,11 @@ fetch_file(report_context_t *ctx, report
static svn_error_t *
start_report(svn_ra_serf__xml_parser_t *parser,
- void *userData,
svn_ra_serf__dav_props_t name,
- const char **attrs)
+ const char **attrs,
+ apr_pool_t *scratch_pool)
{
- report_context_t *ctx = userData;
+ report_context_t *ctx = parser->user_data;
report_state_e state;
state = parser->state->current_state;
@@ -1557,9 +1559,11 @@ start_report(svn_ra_serf__xml_parser_t *
strcmp(name.name, "delete-entry") == 0)
{
const char *file_name;
+ const char *rev_str;
report_info_t *info;
apr_pool_t *tmppool;
const char *full_path;
+ svn_revnum_t delete_rev = SVN_INVALID_REVNUM;
file_name = svn_xml_get_attr_value("name", attrs);
@@ -1570,6 +1574,10 @@ start_report(svn_ra_serf__xml_parser_t *
_("Missing name attr in delete-entry element"));
}
+ rev_str = svn_xml_get_attr_value("rev", attrs);
+ if (rev_str) /* Not available on older repositories! */
+ delete_rev = SVN_STR_TO_REV(rev_str);
+
info = parser->state->private;
SVN_ERR(open_dir(info->dir));
@@ -1579,7 +1587,7 @@ start_report(svn_ra_serf__xml_parser_t *
full_path = svn_relpath_join(info->dir->name, file_name, tmppool);
SVN_ERR(info->dir->update_editor->delete_entry(full_path,
- SVN_INVALID_REVNUM,
+ delete_rev,
info->dir->dir_baton,
tmppool));
@@ -1645,8 +1653,7 @@ start_report(svn_ra_serf__xml_parser_t *
info->prop_ns = name.namespace;
info->prop_name = apr_pstrdup(parser->state->pool, name.name);
info->prop_encoding = NULL;
- info->prop_val = NULL;
- info->prop_val_len = 0;
+ svn_stringbuf_setempty(info->prop_value);
}
else if (strcmp(name.name, "set-prop") == 0 ||
strcmp(name.name, "remove-prop") == 0)
@@ -1675,8 +1682,7 @@ start_report(svn_ra_serf__xml_parser_t *
colon - full_prop_name);
info->prop_name = apr_pstrdup(parser->state->pool, colon);
info->prop_encoding = svn_xml_get_attr_value("encoding", attrs);
- info->prop_val = NULL;
- info->prop_val_len = 0;
+ svn_stringbuf_setempty(info->prop_value);
}
else if (strcmp(name.name, "prop") == 0)
{
@@ -1691,7 +1697,9 @@ start_report(svn_ra_serf__xml_parser_t *
}
else
{
- SVN_ERR_MALFUNCTION();
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ _("Unknown tag '%s' while at state %d"),
+ name.name, state);
}
}
@@ -1705,8 +1713,7 @@ start_report(svn_ra_serf__xml_parser_t *
info->prop_ns = name.namespace;
info->prop_name = apr_pstrdup(parser->state->pool, name.name);
info->prop_encoding = NULL;
- info->prop_val = NULL;
- info->prop_val_len = 0;
+ svn_stringbuf_setempty(info->prop_value);
}
else if (strcmp(name.name, "prop") == 0)
{
@@ -1761,12 +1768,13 @@ start_report(svn_ra_serf__xml_parser_t *
colon - full_prop_name);
info->prop_name = apr_pstrdup(parser->state->pool, colon);
info->prop_encoding = svn_xml_get_attr_value("encoding", attrs);
- info->prop_val = NULL;
- info->prop_val_len = 0;
+ svn_stringbuf_setempty(info->prop_value);
}
else
{
- SVN_ERR_MALFUNCTION();
+ return svn_error_createf(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ _("Unknown tag '%s' while at state %d"),
+ name.name, state);
}
}
else if (state == IGNORE_PROP_NAME)
@@ -1783,8 +1791,7 @@ start_report(svn_ra_serf__xml_parser_t *
info->prop_ns = name.namespace;
info->prop_name = apr_pstrdup(parser->state->pool, name.name);
info->prop_encoding = svn_xml_get_attr_value("encoding", attrs);
- info->prop_val = NULL;
- info->prop_val_len = 0;
+ svn_stringbuf_setempty(info->prop_value);
}
return SVN_NO_ERROR;
@@ -1792,10 +1799,10 @@ start_report(svn_ra_serf__xml_parser_t *
static svn_error_t *
end_report(svn_ra_serf__xml_parser_t *parser,
- void *userData,
- svn_ra_serf__dav_props_t name)
+ svn_ra_serf__dav_props_t name,
+ apr_pool_t *scratch_pool)
{
- report_context_t *ctx = userData;
+ report_context_t *ctx = parser->user_data;
report_state_e state;
state = parser->state->current_state;
@@ -1946,7 +1953,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
}
else if (state == PROP)
{
- /* We need to move the prop_ns, prop_name, and prop_val into the
+ /* We need to move the prop_ns, prop_name, and prop_value into the
* same lifetime as the dir->pool.
*/
svn_ra_serf__ns_t *ns, *ns_name_match;
@@ -1954,8 +1961,7 @@ end_report(svn_ra_serf__xml_parser_t *pa
report_info_t *info;
report_dir_t *dir;
apr_hash_t *props;
- const char *set_val;
- svn_string_t *set_val_str;
+ const svn_string_t *set_val_str;
apr_pool_t *pool;
info = parser->state->private;
@@ -2005,24 +2011,21 @@ end_report(svn_ra_serf__xml_parser_t *pa
{
props = dir->removed_props;
pool = dir->pool;
- info->prop_val = "";
- info->prop_val_len = 1;
+ svn_stringbuf_setempty(info->prop_value);
}
if (info->prop_encoding)
{
if (strcmp(info->prop_encoding, "base64") == 0)
{
- svn_string_t encoded;
- const svn_string_t *decoded;
-
- encoded.data = info->prop_val;
- encoded.len = info->prop_val_len;
+ svn_string_t tmp;
- decoded = svn_base64_decode_string(&encoded, parser->state->pool);
+ /* Don't use morph_info_string cuz we need prop_value to
+ remain usable. */
+ tmp.data = info->prop_value->data;
+ tmp.len = info->prop_value->len;
- info->prop_val = decoded->data;
- info->prop_val_len = decoded->len;
+ set_val_str = svn_base64_decode_string(&tmp, pool);
}
else
{
@@ -2031,11 +2034,11 @@ end_report(svn_ra_serf__xml_parser_t *pa
_("Got unrecognized encoding '%s'"),
info->prop_encoding);
}
-
}
-
- set_val = apr_pmemdup(pool, info->prop_val, info->prop_val_len);
- set_val_str = svn_string_ncreate(set_val, info->prop_val_len, pool);
+ else
+ {
+ set_val_str = svn_string_create_from_buf(info->prop_value, pool);
+ }
svn_ra_serf__set_ver_prop(props, info->base_name, info->base_rev,
ns->namespace, ns->url, set_val_str, pool);
@@ -2051,11 +2054,11 @@ end_report(svn_ra_serf__xml_parser_t *pa
static svn_error_t *
cdata_report(svn_ra_serf__xml_parser_t *parser,
- void *userData,
const char *data,
- apr_size_t len)
+ apr_size_t len,
+ apr_pool_t *scratch_pool)
{
- report_context_t *ctx = userData;
+ report_context_t *ctx = parser->user_data;
UNUSED_CTX(ctx);
@@ -2063,8 +2066,7 @@ cdata_report(svn_ra_serf__xml_parser_t *
{
report_info_t *info = parser->state->private;
- svn_ra_serf__expand_string(&info->prop_val, &info->prop_val_len,
- data, len, parser->state->pool);
+ svn_stringbuf_appendbytes(info->prop_value, data, len);
}
return SVN_NO_ERROR;
@@ -2222,16 +2224,17 @@ open_connection_if_needed(svn_ra_serf__s
int cur = sess->num_conns;
apr_status_t status;
- sess->conns[cur] = apr_palloc(sess->pool, sizeof(*sess->conns[cur]));
+ sess->conns[cur] = apr_pcalloc(sess->pool, sizeof(*sess->conns[cur]));
+ sess->conns[cur]->http10 = TRUE; /* until we confirm HTTP/1.1 */
+ sess->conns[cur]->http10 = FALSE; /* ### don't change behavior yet */
sess->conns[cur]->bkt_alloc = serf_bucket_allocator_create(sess->pool,
NULL, NULL);
sess->conns[cur]->hostname = sess->conns[0]->hostname;
sess->conns[cur]->using_ssl = sess->conns[0]->using_ssl;
sess->conns[cur]->using_compression = sess->conns[0]->using_compression;
- sess->conns[cur]->useragent = sess->conns[0]->useragent;
sess->conns[cur]->last_status_code = -1;
- sess->conns[cur]->ssl_context = NULL;
sess->conns[cur]->session = sess;
+ sess->conns[cur]->useragent = sess->conns[0]->useragent;
status = serf_connection_create2(&sess->conns[cur]->conn,
sess->context,
sess->session_url,
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/util.c Mon Apr 23 12:32:48 2012
@@ -38,8 +38,11 @@
#include "svn_private_config.h"
#include "svn_string.h"
#include "svn_xml.h"
+
+#include "../libsvn_ra/ra_loader.h"
#include "private/svn_dep_compat.h"
#include "private/svn_fspath.h"
+#include "private/svn_subr_private.h"
#include "ra_serf.h"
@@ -53,124 +56,29 @@
#endif
+/* Read/write chunks of this size into the spillbuf. */
#define PARSE_CHUNK_SIZE 8000
-/* As chunks of content arrive from the server, and we need to hold them
- in memory (because the XML parser is paused), they are copied into
- these buffers. The buffers are arranged into a linked list. */
-struct pending_buffer_t {
- apr_size_t size;
- char data[PARSE_CHUNK_SIZE];
-
- struct pending_buffer_t *next;
-};
+/* We will store one megabyte in memory, before switching to store content
+ into a temporary file. */
+#define SPILL_SIZE 1000000
/* This structure records pending data for the parser in memory blocks,
and possibly into a temporary file if "too much" content arrives. */
struct svn_ra_serf__pending_t {
- /* The amount of content in memory. */
- apr_size_t memory_size;
-
- /* HEAD points to the first block of the linked list of buffers.
- TAIL points to the last block, for quickly appending more blocks
- to the overall list. */
- struct pending_buffer_t *head;
- struct pending_buffer_t *tail;
-
- /* Available blocks for storing pending data. These were allocated
- previously, then the data consumed and returned to this list. */
- struct pending_buffer_t *avail;
-
- /* Once MEMORY_SIZE exceeds SPILL_SIZE, then arriving content will be
- appended to the (temporary) file indicated by SPILL. */
- apr_file_t *spill;
-
- /* As we consume content from SPILL, this value indicates where we
- will begin reading. */
- apr_off_t spill_start;
+ /* The spillbuf where we record the pending data. */
+ svn_spillbuf_t *buf;
/* This flag is set when the network has reached EOF. The PENDING
processing can then properly detect when parsing has completed. */
svn_boolean_t network_eof;
};
-#define HAS_PENDING_DATA(p) ((p) != NULL \
- && ((p)->head != NULL || (p)->spill != NULL))
-
-/* We will store one megabyte in memory, before switching to store content
- into a temporary file. */
-#define SPILL_SIZE 1000000
-
-/* See notes/ra-serf-testing.txt for some information on testing this
- new "paused" feature (aka network pushback).
-
- Define PBTEST_ACTIVE, if you would like to run the pushback tests. */
-#undef PBTEST_ACTIVE
-#ifdef PBTEST_ACTIVE
-
-static int pbtest_step = 0;
-
-/* Note: this cannot resolve states 5 and 7. */
-#define PBTEST_STATE(p) \
- ((p) == NULL ? 1 \
- : ((p)->spill == NULL ? ((p)->head == NULL ? 2 : 3) \
- : ((p)->head == NULL ? 6 : 4)))
-
-/* Note: INJECT and COMPLETED are only used for debug output. */
-typedef struct {
- svn_boolean_t paused; /* pause the parser on this step? */
- svn_boolean_t inject; /* inject pending content on this step? */
- int when_next; /* when to move to the next step? */
- const char *completed; /* what test was completed? */
-} pbtest_desc_t;
-
-static const pbtest_desc_t pbtest_description[] = {
- { 0 }, /* unused */
- { TRUE, FALSE, 3, "1.1" },
- { TRUE, FALSE, 3, "1.3" },
- { FALSE, FALSE, 3, "2.3" },
- { FALSE, TRUE, 2, "3.3" }, /* WHEN_NEXT is ignored due to INJECT */
- { TRUE, FALSE, 3, "1.2" },
- { TRUE, FALSE, 4, NULL },
- { TRUE, FALSE, 4, "1.4" },
- { FALSE, FALSE, 4, "2.4" },
- { FALSE, TRUE, 6, "3.4" }, /* WHEN_NEXT is ignored due to INJECT */
- { TRUE, FALSE, 6, "1.6" },
- { FALSE, FALSE, 6, "2.6" },
- { FALSE, TRUE, 7, "3.6" }, /* WHEN_NEXT is ignored due to INJECT */
- { TRUE, FALSE, 6, "1.7" },
- { 0 } /* unused */
-};
-
-#define PBTEST_SET_PAUSED(ctx) \
- (PBTEST_THIS_REQ(ctx) && pbtest_step < 14 \
- ? (ctx)->paused = pbtest_description[pbtest_step].paused \
- : FALSE)
-
-#define PBTEST_MAYBE_STEP(ctx, force) maybe_next_step(ctx, force)
-
-#define PBTEST_FORCE_SPILL(ctx) (PBTEST_THIS_REQ(ctx) && pbtest_step == 6)
-
-#define PBTEST_THIS_REQ(ctx) \
- ((ctx)->response_type != NULL \
- && strcmp((ctx)->response_type, "update-report") == 0)
+#define HAS_PENDING_DATA(p) ((p) != NULL && (p)->buf != NULL \
+ && svn_spillbuf__get_size((p)->buf) != 0)
-#else /* PBTEST_ACTIVE */
-/* Be wary with the definition of these macros so that we don't
- end up with "statement with no effect" warnings. Obviously, this
- depends upon particular usage, which is easy to verify. */
-#define PBTEST_SET_PAUSED(ctx) /* empty */
-#define PBTEST_MAYBE_STEP(ctx, force) /* empty */
-
-#define PBTEST_FORCE_SPILL(ctx) FALSE
-#define PBTEST_THIS_REQ(ctx) FALSE
-
-#endif /* PBTEST_ACTIVE */
-
-
-
static const apr_uint32_t serf_failure_map[][2] =
{
{ SERF_SSL_CERT_NOTYETVALID, SVN_AUTH_SSL_NOTYETVALID },
@@ -271,6 +179,8 @@ ssl_server_cert(void *baton, int failure
/* Implicitly approve any non-server certs. */
if (serf_ssl_cert_depth(cert) > 0)
{
+ if (failures)
+ conn->server_cert_failures |= ssl_convert_serf_failures(failures);
return APR_SUCCESS;
}
@@ -295,7 +205,8 @@ ssl_server_cert(void *baton, int failure
cert_info.issuer_dname = convert_organisation_to_str(issuer, scratch_pool);
cert_info.ascii_cert = serf_ssl_cert_export(cert, scratch_pool);
- svn_failures = ssl_convert_serf_failures(failures);
+ svn_failures = (ssl_convert_serf_failures(failures)
+ | conn->server_cert_failures);
/* Try to find matching server name via subjectAltName first... */
if (san) {
@@ -383,24 +294,26 @@ static svn_error_t *
load_authorities(svn_ra_serf__connection_t *conn, const char *authorities,
apr_pool_t *pool)
{
- char *files, *file, *last;
- files = apr_pstrdup(pool, authorities);
+ apr_array_header_t *files = svn_cstring_split(authorities, ";",
+ TRUE /* chop_whitespace */,
+ pool);
+ int i;
- while ((file = apr_strtok(files, ";", &last)) != NULL)
+ for (i = 0; i < files->nelts; ++i)
{
+ const char *file = APR_ARRAY_IDX(files, i, const char *);
serf_ssl_certificate_t *ca_cert;
apr_status_t status = serf_ssl_load_cert_file(&ca_cert, file, pool);
+
if (status == APR_SUCCESS)
status = serf_ssl_trust_cert(conn->ssl_context, ca_cert);
if (status != APR_SUCCESS)
{
- return svn_error_createf
- (SVN_ERR_BAD_CONFIG_VALUE, NULL,
+ return svn_error_createf(SVN_ERR_BAD_CONFIG_VALUE, NULL,
_("Invalid config: unable to load certificate file '%s'"),
svn_dirent_local_style(file, pool));
}
- files = NULL;
}
return SVN_NO_ERROR;
@@ -478,7 +391,7 @@ svn_ra_serf__conn_setup(apr_socket_t *so
{
svn_ra_serf__connection_t *conn = baton;
svn_ra_serf__session_t *session = conn->session;
- apr_status_t status = SVN_NO_ERROR;
+ apr_status_t status = APR_SUCCESS;
svn_error_t *err = conn_setup(sock,
read_bkt,
@@ -498,11 +411,13 @@ svn_ra_serf__conn_setup(apr_socket_t *so
return status;
}
-serf_bucket_t*
-svn_ra_serf__accept_response(serf_request_t *request,
- serf_bucket_t *stream,
- void *acceptor_baton,
- apr_pool_t *pool)
+
+/* Our default serf response acceptor. */
+static serf_bucket_t *
+accept_response(serf_request_t *request,
+ serf_bucket_t *stream,
+ void *acceptor_baton,
+ apr_pool_t *pool)
{
serf_bucket_t *c;
serf_bucket_alloc_t *bkt_alloc;
@@ -513,7 +428,9 @@ svn_ra_serf__accept_response(serf_reques
return serf_bucket_response_create(c, bkt_alloc);
}
-static serf_bucket_t*
+
+/* Custom response acceptor for HEAD requests. */
+static serf_bucket_t *
accept_head(serf_request_t *request,
serf_bucket_t *stream,
void *acceptor_baton,
@@ -521,8 +438,7 @@ accept_head(serf_request_t *request,
{
serf_bucket_t *response;
- response = svn_ra_serf__accept_response(request, stream, acceptor_baton,
- pool);
+ response = accept_response(request, stream, acceptor_baton, pool);
/* We know we shouldn't get a response body. */
serf_bucket_response_set_head(response);
@@ -692,41 +608,91 @@ apr_status_t svn_ra_serf__handle_client_
}
-svn_error_t *
-svn_ra_serf__setup_serf_req(serf_request_t *request,
- serf_bucket_t **req_bkt,
- serf_bucket_t **ret_hdrs_bkt,
- svn_ra_serf__connection_t *conn,
- const char *method, const char *url,
- serf_bucket_t *body_bkt, const char *content_type)
-{
- serf_bucket_t *hdrs_bkt;
+/*
+ * Given a REQUEST on connection CONN, construct a request bucket for it,
+ * returning the bucket in *REQ_BKT.
+ *
+ * If HDRS_BKT is not-NULL, it will be set to a headers_bucket that
+ * corresponds to the new request.
+ *
+ * The request will be METHOD at URL.
+ *
+ * If BODY_BKT is not-NULL, it will be sent as the request body.
+ *
+ * If CONTENT_TYPE is not-NULL, it will be sent as the Content-Type header.
+ *
+ * REQUEST_POOL should live for the duration of the request. Serf will
+ * construct this and provide it to the request_setup callback, so we
+ * should just use that one.
+ */
+static svn_error_t *
+setup_serf_req(serf_request_t *request,
+ serf_bucket_t **req_bkt,
+ serf_bucket_t **hdrs_bkt,
+ svn_ra_serf__connection_t *conn,
+ const char *method, const char *url,
+ serf_bucket_t *body_bkt, const char *content_type,
+ apr_pool_t *request_pool,
+ apr_pool_t *scratch_pool)
+{
+ serf_bucket_alloc_t *allocator = serf_request_get_alloc(request);
+
+#if SERF_VERSION_AT_LEAST(1, 1, 0)
+ svn_spillbuf_t *buf;
+
+ if (conn->http10 && body_bkt != NULL)
+ {
+ /* Ugh. Use HTTP/1.0 to talk to the server because we don't know if
+ it speaks HTTP/1.1 (and thus, chunked requests), or because the
+ server actually responded as only supporting HTTP/1.0.
+
+ We'll take the existing body_bkt, spool it into a spillbuf, and
+ then wrap a bucket around that spillbuf. The spillbuf will give
+ us the Content-Length value. */
+ SVN_ERR(svn_ra_serf__copy_into_spillbuf(&buf, body_bkt,
+ request_pool,
+ scratch_pool));
+ body_bkt = svn_ra_serf__create_sb_bucket(buf, allocator,
+ request_pool,
+ scratch_pool);
+ }
+#endif
/* Create a request bucket. Note that this sucker is kind enough to
add a "Host" header for us. */
- *req_bkt =
- serf_request_bucket_request_create(request, method, url, body_bkt,
- serf_request_get_alloc(request));
+ *req_bkt = serf_request_bucket_request_create(request, method, url,
+ body_bkt, allocator);
- hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
- serf_bucket_headers_setn(hdrs_bkt, "User-Agent", conn->useragent);
+ /* Set the Content-Length value. This will also trigger an HTTP/1.0
+ request (rather than the default chunked request). */
+#if SERF_VERSION_AT_LEAST(1, 1, 0)
+ if (conn->http10)
+ {
+ if (body_bkt == NULL)
+ serf_bucket_request_set_CL(*req_bkt, 0);
+ else
+ serf_bucket_request_set_CL(*req_bkt, svn_spillbuf__get_size(buf));
+ }
+#endif
+
+ *hdrs_bkt = serf_bucket_request_get_headers(*req_bkt);
+
+ /* We use serf_bucket_headers_setn() because the string below have a
+ lifetime longer than this bucket. Thus, there is no need to copy
+ the header values. */
+ serf_bucket_headers_setn(*hdrs_bkt, "User-Agent", conn->useragent);
if (content_type)
{
- serf_bucket_headers_setn(hdrs_bkt, "Content-Type", content_type);
+ serf_bucket_headers_setn(*hdrs_bkt, "Content-Type", content_type);
}
/* These headers need to be sent with every request; see issue #3255
("mod_dav_svn does not pass client capabilities to start-commit
hooks") for why. */
- serf_bucket_headers_set(hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH);
- serf_bucket_headers_set(hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_MERGEINFO);
- serf_bucket_headers_set(hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
-
- if (ret_hdrs_bkt)
- {
- *ret_hdrs_bkt = hdrs_bkt;
- }
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_DEPTH);
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_MERGEINFO);
+ serf_bucket_headers_setn(*hdrs_bkt, "DAV", SVN_DAV_NS_DAV_SVN_LOG_REVPROPS);
return SVN_NO_ERROR;
}
@@ -795,11 +761,11 @@ svn_ra_serf__context_run_wait(svn_boolea
*/
static svn_error_t *
start_error(svn_ra_serf__xml_parser_t *parser,
- void *userData,
svn_ra_serf__dav_props_t name,
- const char **attrs)
+ const char **attrs,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__server_error_t *ctx = userData;
+ svn_ra_serf__server_error_t *ctx = parser->user_data;
if (!ctx->in_error &&
strcmp(name.namespace, "DAV:") == 0 &&
@@ -837,10 +803,10 @@ start_error(svn_ra_serf__xml_parser_t *p
*/
static svn_error_t *
end_error(svn_ra_serf__xml_parser_t *parser,
- void *userData,
- svn_ra_serf__dav_props_t name)
+ svn_ra_serf__dav_props_t name,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__server_error_t *ctx = userData;
+ svn_ra_serf__server_error_t *ctx = parser->user_data;
if (ctx->in_error &&
strcmp(name.namespace, "DAV:") == 0 &&
@@ -875,11 +841,11 @@ end_error(svn_ra_serf__xml_parser_t *par
*/
static svn_error_t *
cdata_error(svn_ra_serf__xml_parser_t *parser,
- void *userData,
const char *data,
- apr_size_t len)
+ apr_size_t len,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__server_error_t *ctx = userData;
+ svn_ra_serf__server_error_t *ctx = parser->user_data;
if (ctx->collect_cdata)
{
@@ -1062,11 +1028,11 @@ parse_dav_status(int *status_code_out, s
*/
static svn_error_t *
start_207(svn_ra_serf__xml_parser_t *parser,
- void *userData,
svn_ra_serf__dav_props_t name,
- const char **attrs)
+ const char **attrs,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__server_error_t *ctx = userData;
+ svn_ra_serf__server_error_t *ctx = parser->user_data;
if (!ctx->in_error &&
strcmp(name.namespace, "DAV:") == 0 &&
@@ -1097,10 +1063,10 @@ start_207(svn_ra_serf__xml_parser_t *par
*/
static svn_error_t *
end_207(svn_ra_serf__xml_parser_t *parser,
- void *userData,
- svn_ra_serf__dav_props_t name)
+ svn_ra_serf__dav_props_t name,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__server_error_t *ctx = userData;
+ svn_ra_serf__server_error_t *ctx = parser->user_data;
if (ctx->in_error &&
strcmp(name.namespace, "DAV:") == 0 &&
@@ -1141,11 +1107,11 @@ end_207(svn_ra_serf__xml_parser_t *parse
*/
static svn_error_t *
cdata_207(svn_ra_serf__xml_parser_t *parser,
- void *userData,
const char *data,
- apr_size_t len)
+ apr_size_t len,
+ apr_pool_t *scratch_pool)
{
- svn_ra_serf__server_error_t *ctx = userData;
+ svn_ra_serf__server_error_t *ctx = parser->user_data;
if (ctx->collect_cdata)
{
@@ -1246,11 +1212,14 @@ svn_ra_serf__handle_multistatus_only(ser
return svn_error_trace(err);
}
+
+/* Conforms to Expat's XML_StartElementHandler */
static void
start_xml(void *userData, const char *raw_name, const char **attrs)
{
svn_ra_serf__xml_parser_t *parser = userData;
svn_ra_serf__dav_props_t name;
+ apr_pool_t *scratch_pool;
if (parser->error)
return;
@@ -1258,31 +1227,43 @@ start_xml(void *userData, const char *ra
if (!parser->state)
svn_ra_serf__xml_push_state(parser, 0);
+ /* ### get a real scratch_pool */
+ scratch_pool = parser->state->pool;
+
svn_ra_serf__define_ns(&parser->state->ns_list, attrs, parser->state->pool);
svn_ra_serf__expand_ns(&name, parser->state->ns_list, raw_name);
- parser->error = parser->start(parser, parser->user_data, name, attrs);
+ parser->error = parser->start(parser, name, attrs, scratch_pool);
}
+
+/* Conforms to Expat's XML_EndElementHandler */
static void
end_xml(void *userData, const char *raw_name)
{
svn_ra_serf__xml_parser_t *parser = userData;
svn_ra_serf__dav_props_t name;
+ apr_pool_t *scratch_pool;
if (parser->error)
return;
+ /* ### get a real scratch_pool */
+ scratch_pool = parser->state->pool;
+
svn_ra_serf__expand_ns(&name, parser->state->ns_list, raw_name);
- parser->error = parser->end(parser, parser->user_data, name);
+ parser->error = parser->end(parser, name, scratch_pool);
}
+
+/* Conforms to Expat's XML_CharacterDataHandler */
static void
cdata_xml(void *userData, const char *data, int len)
{
svn_ra_serf__xml_parser_t *parser = userData;
+ apr_pool_t *scratch_pool;
if (parser->error)
return;
@@ -1290,7 +1271,10 @@ cdata_xml(void *userData, const char *da
if (!parser->state)
svn_ra_serf__xml_push_state(parser, 0);
- parser->error = parser->cdata(parser, parser->user_data, data, len);
+ /* ### get a real scratch_pool */
+ scratch_pool = parser->state->pool;
+
+ parser->error = parser->cdata(parser, data, len, scratch_pool);
}
/* Flip the requisite bits in CTX to indicate that processing of the
@@ -1313,157 +1297,24 @@ add_done_item(svn_ra_serf__xml_parser_t
}
-#ifdef PBTEST_ACTIVE
-
-/* Determine whether we should move to the next step. Print out the
- transition for debugging purposes. If FORCE is TRUE, then we
- definitely make a step (injection has completed). */
-static void
-maybe_next_step(svn_ra_serf__xml_parser_t *parser, svn_boolean_t force)
-{
- const pbtest_desc_t *desc;
- int state;
-
- /* This would fail the state transition, but for clarity... just return
- when the testing has completed. */
- if (pbtest_step == 14)
- return;
-
- /* If this is not the request running the test, then exit. */
- if (!PBTEST_THIS_REQ(parser))
- return;
-
- desc = &pbtest_description[pbtest_step];
- state = PBTEST_STATE(parser->pending);
-
- /* Forced? ... or reached target state? */
- if (force || state == desc->when_next)
- {
- ++pbtest_step;
-
- if (desc->completed != NULL)
- SVN_DBG(("PBTEST: completed TEST %s\n", desc->completed));
-
- /* Pause the parser based on the new step's config. */
- ++desc;
- parser->paused = desc->paused;
-
- SVN_DBG(("PBTEST: advanced: step=%d paused=%d inject=%d state=%d\n",
- pbtest_step, desc->paused, desc->inject, state));
- }
- else
- {
- SVN_DBG(("PBTEST: step[%d]: state=%d waiting_for=%d\n",
- pbtest_step, state, desc->when_next));
- }
-}
-
-#endif /* PBTEST_ACTIVE */
-
-
-/* Get a buffer from the parsing context. It will come from the free list,
- or allocated as necessary. */
-static struct pending_buffer_t *
-get_buffer(svn_ra_serf__xml_parser_t *parser)
-{
- struct pending_buffer_t *pb;
-
- if (parser->pending->avail == NULL)
- return apr_palloc(parser->pool, sizeof(*pb));
-
- pb = parser->pending->avail;
- parser->pending->avail = pb->next;
- return pb;
-}
-
-
-/* Return PB to the list of available buffers in PARSER. */
-static void
-return_buffer(svn_ra_serf__xml_parser_t *parser,
- struct pending_buffer_t *pb)
-{
- pb->next = parser->pending->avail;
- parser->pending->avail = pb;
-}
-
-
static svn_error_t *
write_to_pending(svn_ra_serf__xml_parser_t *ctx,
const char *data,
apr_size_t len,
apr_pool_t *scratch_pool)
{
- struct pending_buffer_t *pb;
-
- /* The caller should not have provided us more than we can store into
- a single memory block. */
- SVN_ERR_ASSERT(len <= PARSE_CHUNK_SIZE);
-
if (ctx->pending == NULL)
- ctx->pending = apr_pcalloc(ctx->pool, sizeof(*ctx->pending));
-
- /* We do not (yet) have a spill file, but the amount stored in memory
- has grown too large. Create the file and place the pending data into
- the temporary file.
-
- For testing purposes, there are points when we may want to
- create the spill file, regardless. */
- if (PBTEST_FORCE_SPILL(ctx)
- || (ctx->pending->spill == NULL
- && ctx->pending->memory_size > SPILL_SIZE))
- {
-#ifdef PBTEST_ACTIVE
- /* Only allow a spill file for steps 6 or later. */
- if (!PBTEST_THIS_REQ(ctx) || pbtest_step >= 6)
-#endif
- SVN_ERR(svn_io_open_unique_file3(&ctx->pending->spill,
- NULL /* temp_path */,
- NULL /* dirpath */,
- svn_io_file_del_on_pool_cleanup,
- ctx->pool, scratch_pool));
- }
-
- /* Once a spill file has been constructed, then we need to put all
- arriving data into the file. We will no longer attempt to hold it
- in memory. */
- if (ctx->pending->spill != NULL)
- {
- /* NOTE: we assume the file position is at the END. The caller should
- ensure this, so that we will append. */
- SVN_ERR(svn_io_file_write_full(ctx->pending->spill, data, len,
- NULL, scratch_pool));
- return SVN_NO_ERROR;
- }
-
- /* We're still within bounds of holding the pending information in
- memory. Get a buffer, copy the data there, and link it into our
- pending data. */
- pb = get_buffer(ctx);
- /* NOTE: *pb is uninitialized. All fields must be stored. */
-
- pb->size = len;
- memcpy(pb->data, data, len);
- pb->next = NULL;
-
- /* Start a list of buffers, or append to the end of the linked list
- of buffers. */
- if (ctx->pending->tail == NULL)
- {
- ctx->pending->head = pb;
- ctx->pending->tail = pb;
- }
- else
{
- ctx->pending->tail->next = pb;
- ctx->pending->tail = pb;
+ ctx->pending = apr_pcalloc(ctx->pool, sizeof(*ctx->pending));
+ ctx->pending->buf = svn_spillbuf__create(PARSE_CHUNK_SIZE,
+ SPILL_SIZE,
+ ctx->pool);
}
- /* We need to record how much is buffered in memory. Once we reach
- SPILL_SIZE (or thereabouts, it doesn't have to be precise), then
- we'll switch to putting the content into a file. */
- ctx->pending->memory_size += len;
-
- return SVN_NO_ERROR;
+ /* Copy the data into one or more chunks in the spill buffer. */
+ return svn_error_trace(svn_spillbuf__write(ctx->pending->buf,
+ data, len,
+ scratch_pool));
}
@@ -1490,10 +1341,6 @@ inject_to_parser(svn_ra_serf__xml_parser
if (ctx->error && !ctx->ignore_errors)
return svn_error_trace(ctx->error);
- /* We may want to ignore the callbacks choice for the PAUSED flag.
- Set this value, as appropriate. */
- PBTEST_SET_PAUSED(ctx);
-
return SVN_NO_ERROR;
}
@@ -1517,23 +1364,6 @@ svn_error_t *
svn_ra_serf__process_pending(svn_ra_serf__xml_parser_t *parser,
apr_pool_t *scratch_pool)
{
- struct pending_buffer_t *pb;
- svn_error_t *err;
- apr_off_t output_unused;
-
- /* We may need to repair the PAUSED state when testing. */
- PBTEST_SET_PAUSED(parser);
-
-#ifdef PBTEST_ACTIVE
- /* If this step should not inject content, then fast-path exit. */
- if (PBTEST_THIS_REQ(parser)
- && pbtest_step < 14 && !pbtest_description[pbtest_step].inject)
- {
- SVN_DBG(("PBTEST: process: injection disabled\n"));
- return SVN_NO_ERROR;
- }
-#endif
-
/* Fast path exit: already paused, nothing to do, or already done. */
if (parser->paused || parser->pending == NULL || *parser->done)
return SVN_NO_ERROR;
@@ -1541,107 +1371,35 @@ svn_ra_serf__process_pending(svn_ra_serf
/* ### it is possible that the XML parsing of the pending content is
### so slow, and that we don't return to reading the connection
### fast enough... that the server will disconnect us. right now,
- ### that is highly improbably, but is noted for future's sake.
+ ### that is highly improbable, but is noted for future's sake.
### should that ever happen, the loops in this function can simply
### terminate after N seconds. */
- /* Empty out memory buffers until we run out, or we get paused again. */
- while (parser->pending->head != NULL)
- {
- /* Pull the HEAD buffer out of the list. */
- pb = parser->pending->head;
- if (parser->pending->tail == pb)
- parser->pending->head = parser->pending->tail = NULL;
- else
- parser->pending->head = pb->next;
-
- /* We're using less memory now. If we haven't hit the spill file,
- then we may be able to keep using memory. */
- parser->pending->memory_size -= pb->size;
-
- err = inject_to_parser(parser, pb->data, pb->size, NULL);
-
- return_buffer(parser, pb);
-
- if (err)
- return svn_error_trace(err);
-
- /* If the callbacks paused us, then we're done for now. */
- if (parser->paused)
- return SVN_NO_ERROR;
- }
-
-#ifdef PBTEST_ACTIVE
- /* For steps 4 and 9, we wait until all of the memory content has been
- injected. At that point, we can take another step which will pause
- the parser, and we'll need to exit. */
- if (PBTEST_THIS_REQ(parser)
- && (pbtest_step == 4 || pbtest_step == 9))
- {
- PBTEST_MAYBE_STEP(parser, TRUE);
- return SVN_NO_ERROR;
- }
-#endif
-
- /* If we don't have a spill file, then we've exhausted all
- pending content. */
- if (parser->pending->spill == NULL)
- goto pending_empty;
-
- /* Seek once to where we left off reading. */
- output_unused = parser->pending->spill_start; /* ### stupid API */
- SVN_ERR(svn_io_file_seek(parser->pending->spill,
- APR_SET, &output_unused,
- scratch_pool));
-
- /* We need a buffer for reading out of the file. One of these will always
- exist by the time we start reading from the spill file. */
- pb = get_buffer(parser);
-
- /* Keep reading until we hit EOF, or get paused again. */
+ /* Try to read everything from the spillbuf. */
while (TRUE)
{
- apr_size_t len = sizeof(pb->data);
- apr_status_t status;
-
- /* Read some data and remember where we left off. */
- status = apr_file_read(parser->pending->spill, pb->data, &len);
- if (status && !APR_STATUS_IS_EOF(status))
- {
- err = svn_error_wrap_apr(status, NULL);
- break;
- }
- parser->pending->spill_start += len;
+ const char *data;
+ apr_size_t len;
- err = inject_to_parser(parser, pb->data, len, NULL);
- if (err)
+ /* Get a block of content, stopping the loop when we run out. */
+ SVN_ERR(svn_spillbuf__read(&data, &len, parser->pending->buf,
+ scratch_pool));
+ if (data == NULL)
break;
- /* If we just consumed everything in the spill file, then we may
- be done with the parsing. */
- /* ### future change: when we hit EOF, then remove the spill file.
- ### we could go back to using memory for a while. */
- if (APR_STATUS_IS_EOF(status))
- goto pending_empty;
+ /* Inject the content into the XML parser. */
+ SVN_ERR(inject_to_parser(parser, data, len, NULL));
- /* If the callbacks paused the parsing, then we're done for now. */
+ /* If the XML parsing callbacks paused us, then we're done for now. */
if (parser->paused)
- break;
+ return SVN_NO_ERROR;
}
+ /* All stored content (memory and file) has now been exhausted. */
- return_buffer(parser, pb);
- return svn_error_trace(err); /* may be SVN_NO_ERROR */
-
- pending_empty:
/* If the PENDING structures are empty *and* we consumed all content from
the network, then we're completely done with the parsing. */
if (parser->pending->network_eof)
{
-#ifdef PBTEST_ACTIVE
- if (PBTEST_THIS_REQ(parser))
- SVN_DBG(("process: terminating parse.\n"));
-#endif
-
SVN_ERR_ASSERT(parser->xmlp != NULL);
/* Tell the parser that no more content will be parsed. Ignore the
@@ -1653,10 +1411,6 @@ svn_ra_serf__process_pending(svn_ra_serf
add_done_item(parser);
}
- /* For testing step 12, we have written all of the disk content. This
- will advance to step 13 and pause the parser again. */
- PBTEST_MAYBE_STEP(parser, TRUE);
-
return SVN_NO_ERROR;
}
@@ -1732,25 +1486,6 @@ svn_ra_serf__handle_xml_parser(serf_requ
{
XML_SetCharacterDataHandler(ctx->xmlp, cdata_xml);
}
-
- /* This is the first invocation. If we're looking at an update
- report, then move to step 1 of the testing sequence. */
-#ifdef PBTEST_ACTIVE
- if (PBTEST_THIS_REQ(ctx))
- PBTEST_MAYBE_STEP(ctx, TRUE);
-#endif
- }
-
- /* If we are storing content into a spill file, then move to the end of
- the file. We need to pre-position the file so that write_to_pending()
- will always append the content. */
- if (ctx->pending != NULL && ctx->pending->spill != NULL)
- {
- apr_off_t output_unused = 0; /* ### stupid API */
-
- SVN_ERR(svn_io_file_seek(ctx->pending->spill,
- APR_END, &output_unused,
- pool));
}
while (1)
@@ -1794,24 +1529,6 @@ svn_ra_serf__handle_xml_parser(serf_requ
ctx->skip_size = 0;
}
- /* Ensure that the parser's PAUSED state is correct before we test
- the flag. */
- PBTEST_SET_PAUSED(ctx);
-
-#ifdef PBTEST_ACTIVE
- if (PBTEST_THIS_REQ(ctx))
- {
- SVN_DBG(("response: len=%d paused=%d status=%08x\n",
- (int)len, ctx->paused, status));
-#if 0
- /* ### DATA is not necessarily NUL-terminated, but this
- ### generally works. so if you want to see content... */
- if (len > 0)
- SVN_DBG(("content=%s\n", data));
-#endif
- }
-#endif
-
/* Note: once the callbacks invoked by inject_to_parser() sets the
PAUSED flag, then it will not be cleared. write_to_pending() will
only save the content. Logic outside of serf_context_run() will
@@ -1824,13 +1541,6 @@ svn_ra_serf__handle_xml_parser(serf_requ
if (ctx->paused || HAS_PENDING_DATA(ctx->pending))
{
err = write_to_pending(ctx, data, len, pool);
-
- /* We may have a transition to a next step.
-
- Note: this only happens on writing to PENDING. If the
- parser is unpaused, then we will never change state within
- this network-reading loop. */
- PBTEST_MAYBE_STEP(ctx, FALSE);
}
else
{
@@ -1860,20 +1570,10 @@ svn_ra_serf__handle_xml_parser(serf_requ
if (ctx->pending != NULL)
ctx->pending->network_eof = TRUE;
-#ifdef PBTEST_ACTIVE
- if (PBTEST_THIS_REQ(ctx))
- SVN_DBG(("network: reached EOF.\n"));
-#endif
-
/* We just hit the end of the network content. If we have nothing
in the PENDING structures, then we're completely done. */
if (!HAS_PENDING_DATA(ctx->pending))
{
-#ifdef PBTEST_ACTIVE
- if (PBTEST_THIS_REQ(ctx))
- SVN_DBG(("network: terminating parse.\n"));
-#endif
-
SVN_ERR_ASSERT(ctx->xmlp != NULL);
/* Ignore the return status. We just don't care. */
@@ -2147,68 +1847,55 @@ handle_response_cb(serf_request_t *reque
return serf_status;
}
-/* If the CTX->setup() callback is non-NULL, invoke it to carry out the
- majority of the serf_request_setup_t implementation. Otherwise, perform
- default setup, with special handling for HEAD requests, and finer-grained
- callbacks invoked (if non-NULL) to produce the request headers and
- body. */
+/* Perform basic request setup, with special handling for HEAD requests,
+ and finer-grained callbacks invoked (if non-NULL) to produce the request
+ headers and body. */
static svn_error_t *
setup_request(serf_request_t *request,
- svn_ra_serf__handler_t *ctx,
- serf_bucket_t **req_bkt,
- serf_response_acceptor_t *acceptor,
- void **acceptor_baton,
- serf_response_handler_t *handler,
- void **handler_baton,
- apr_pool_t *pool)
+ svn_ra_serf__handler_t *ctx,
+ serf_bucket_t **req_bkt,
+ serf_response_acceptor_t *acceptor,
+ void **acceptor_baton,
+ serf_response_handler_t *handler,
+ void **handler_baton,
+ apr_pool_t *request_pool,
+ apr_pool_t *scratch_pool)
{
+ serf_bucket_t *body_bkt;
serf_bucket_t *headers_bkt;
- *acceptor = svn_ra_serf__accept_response;
+ /* Default response acceptor. */
+ *acceptor = accept_response;
*acceptor_baton = ctx->session;
- if (ctx->setup)
+ if (strcmp(ctx->method, "HEAD") == 0)
{
- svn_ra_serf__response_handler_t response_handler;
- void *response_baton;
+ *acceptor = accept_head;
+ }
- SVN_ERR(ctx->setup(request, ctx->setup_baton, req_bkt,
- acceptor, acceptor_baton,
- &response_handler, &response_baton,
- pool));
+ if (ctx->body_delegate)
+ {
+ serf_bucket_alloc_t *bkt_alloc = serf_request_get_alloc(request);
- ctx->response_handler = response_handler;
- ctx->response_baton = response_baton;
+ /* ### should pass the scratch_pool */
+ SVN_ERR(ctx->body_delegate(&body_bkt, ctx->body_delegate_baton,
+ bkt_alloc, request_pool));
}
else
{
- serf_bucket_t *body_bkt;
- serf_bucket_alloc_t *bkt_alloc = serf_request_get_alloc(request);
-
- if (strcmp(ctx->method, "HEAD") == 0)
- {
- *acceptor = accept_head;
- }
-
- if (ctx->body_delegate)
- {
- SVN_ERR(ctx->body_delegate(&body_bkt, ctx->body_delegate_baton,
- bkt_alloc, pool));
- }
- else
- {
- body_bkt = NULL;
- }
+ body_bkt = NULL;
+ }
- SVN_ERR(svn_ra_serf__setup_serf_req(request, req_bkt, &headers_bkt,
- ctx->conn, ctx->method, ctx->path,
- body_bkt, ctx->body_type));
+ SVN_ERR(setup_serf_req(request, req_bkt, &headers_bkt,
+ ctx->conn, ctx->method, ctx->path,
+ body_bkt, ctx->body_type,
+ request_pool, scratch_pool));
- if (ctx->header_delegate)
- {
- SVN_ERR(ctx->header_delegate(headers_bkt, ctx->header_delegate_baton,
- pool));
- }
+ if (ctx->header_delegate)
+ {
+ /* ### should pass the scratch_pool */
+ SVN_ERR(ctx->header_delegate(headers_bkt, ctx->header_delegate_baton,
+ request_pool));
}
*handler = handle_response_cb;
@@ -2233,11 +1920,15 @@ setup_request_cb(serf_request_t *request
svn_ra_serf__handler_t *ctx = setup_baton;
svn_error_t *err;
+ /* ### construct a scratch_pool? serf gives us a pool that will live for
+ ### the duration of the request. */
+ apr_pool_t *scratch_pool = pool;
+
err = setup_request(request, ctx,
req_bkt,
acceptor, acceptor_baton,
handler, handler_baton,
- pool);
+ pool /* request_pool */, scratch_pool);
if (err)
{
@@ -2461,3 +2152,13 @@ svn_ra_serf__error_on_status(int status_
return SVN_NO_ERROR;
}
+
+svn_error_t *
+svn_ra_serf__register_editor_shim_callbacks(svn_ra_session_t *ra_session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ svn_ra_serf__session_t *session = ra_session->priv;
+
+ session->shim_callbacks = callbacks;
+ return SVN_NO_ERROR;
+}
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_serf/xml.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_serf/xml.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_serf/xml.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_serf/xml.c Mon Apr 23 12:32:48 2012
@@ -124,34 +124,6 @@ svn_ra_serf__expand_ns(svn_ra_serf__dav_
return;
}
-void
-svn_ra_serf__expand_string(const char **cur, apr_size_t *cur_len,
- const char *new, apr_size_t new_len,
- apr_pool_t *pool)
-{
- if (!*cur)
- {
- *cur = apr_pstrmemdup(pool, new, new_len);
- *cur_len = new_len;
- }
- else
- {
- char *new_cur;
-
- /* append the data we received before. */
- new_cur = apr_palloc(pool, *cur_len + new_len + 1);
-
- memcpy(new_cur, *cur, *cur_len);
- memcpy(new_cur + *cur_len, new, new_len);
-
- /* NULL-term our new string */
- new_cur[*cur_len + new_len] = '\0';
-
- /* update our length */
- *cur_len += new_len;
- *cur = new_cur;
- }
-}
#define XML_HEADER "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/client.c Mon Apr 23 12:32:48 2012
@@ -1152,7 +1152,18 @@ static svn_error_t *ra_svn_get_dir(svn_r
dirent->size = size;/* FIXME: svn_filesize_t */
dirent->has_props = has_props;
dirent->created_rev = crev;
- SVN_ERR(svn_time_from_cstring(&dirent->time, cdate, pool));
+ /* NOTE: the tuple's format string says CDATE may be NULL. But this
+ function does not allow that. The server has always sent us some
+ random date, however, so this just happens to work. But let's
+ be wary of servers that are (improperly) fixed to send NULL.
+
+ Note: they should NOT be "fixed" to send NULL, as that would break
+ any older clients which received that NULL. But we may as well
+ be defensive against a malicous server. */
+ if (cdate == NULL)
+ dirent->time = 0;
+ else
+ SVN_ERR(svn_time_from_cstring(&dirent->time, cdate, pool));
dirent->last_author = cauthor;
apr_hash_set(*dirents, name, APR_HASH_KEY_STRING, dirent);
}
@@ -1166,15 +1177,12 @@ static svn_error_t *ra_svn_get_dir(svn_r
static svn_tristate_t
optbool_to_tristate(apr_uint64_t v)
{
- switch (v)
- {
- case TRUE:
- return svn_tristate_true;
- case FALSE:
- return svn_tristate_false;
- default: /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
- return svn_tristate_unknown;
- }
+ if (v == TRUE)
+ return svn_tristate_true;
+ if (v == FALSE)
+ return svn_tristate_false;
+
+ return svn_tristate_unknown; /* Contains SVN_RA_SVN_UNSPECIFIED_NUMBER */
}
/* If REVISION is SVN_INVALID_REVNUM, no value is sent to the
@@ -2499,6 +2507,18 @@ ra_svn_get_deleted_rev(svn_ra_session_t
return svn_ra_svn_read_cmd_response(conn, pool, "r", revision_deleted);
}
+static svn_error_t *
+ra_svn_register_editor_shim_callbacks(svn_ra_session_t *session,
+ svn_delta_shim_callbacks_t *callbacks)
+{
+ svn_ra_svn__session_baton_t *sess_baton = session->priv;
+ svn_ra_svn_conn_t *conn = sess_baton->conn;
+
+ conn->shim_callbacks = callbacks;
+
+ return SVN_NO_ERROR;
+}
+
static const svn_ra__vtable_t ra_svn_vtable = {
svn_ra_svn_version,
@@ -2535,7 +2555,8 @@ static const svn_ra__vtable_t ra_svn_vta
ra_svn_replay,
ra_svn_has_capability,
ra_svn_replay_range,
- ra_svn_get_deleted_rev
+ ra_svn_get_deleted_rev,
+ ra_svn_register_editor_shim_callbacks
};
svn_error_t *
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/cyrus_auth.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/cyrus_auth.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/cyrus_auth.c Mon Apr 23 12:32:48 2012
@@ -125,7 +125,7 @@ static int check_result(svn_error_t *err
svn_error_clear(err);
return -1;
}
-
+
return 0;
}
@@ -180,18 +180,70 @@ svn_ra_svn__sasl_common_init(apr_pool_t
sasl_mutex_free_cb);
free_mutexes = apr_array_make(sasl_pool, 0, sizeof(svn_mutex__t *));
return svn_mutex__init(&array_mutex, TRUE, sasl_pool);
-
+
#endif /* APR_HAS_THREADS */
-
+
return SVN_NO_ERROR;
}
+/* We are going to look at errno when we get SASL_FAIL but we don't
+ know for sure whether SASL always sets errno. Clearing errno
+ before calling SASL functions helps in cases where SASL does
+ nothing to set errno. */
+#ifdef apr_set_os_error
+#define clear_sasl_errno() apr_set_os_error(APR_SUCCESS)
+#else
+#define clear_sasl_errno() (void)0
+#endif
+
+/* Sometimes SASL returns SASL_FAIL as RESULT and sets errno.
+ * SASL_FAIL translates to "generic error" which is quite unhelpful.
+ * Try to append a more informative error message based on errno so
+ * should be called before doing anything that may change errno. */
+static const char *
+get_sasl_errno_msg(int result, apr_pool_t *result_pool)
+{
+#ifdef apr_get_os_error
+ char buf[1024];
+
+ if (result == SASL_FAIL && apr_get_os_error() != 0)
+ return apr_psprintf(result_pool, ": %s",
+ svn_strerror(apr_get_os_error(), buf, sizeof(buf)));
+#endif
+ return "";
+}
+
+/* Wrap an error message from SASL with a prefix that allows users
+ * to tell that the error message came from SASL. Queries errno and
+ * so should be called before doing anything that may change errno. */
+static const char *
+get_sasl_error(sasl_conn_t *sasl_ctx, int result, apr_pool_t *result_pool)
+{
+ const char *sasl_errno_msg = get_sasl_errno_msg(result, result_pool);
+
+ return apr_psprintf(result_pool,
+ _("SASL authentication error: %s%s"),
+ sasl_errdetail(sasl_ctx), sasl_errno_msg);
+}
+
static svn_error_t *sasl_init_cb(void *baton, apr_pool_t *pool)
{
+ int result;
+
SVN_ERR(svn_ra_svn__sasl_common_init(pool));
- if (sasl_client_init(NULL) != SASL_OK)
- return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- _("Could not initialize the SASL library"));
+ clear_sasl_errno();
+ result = sasl_client_init(NULL);
+ if (result != SASL_OK)
+ {
+ const char *sasl_errno_msg = get_sasl_errno_msg(result, pool);
+
+ return svn_error_createf
+ (SVN_ERR_RA_NOT_AUTHORIZED, NULL,
+ _("Could not initialized the SASL library: %s%s"),
+ sasl_errstring(result, NULL, NULL),
+ sasl_errno_msg);
+ }
+
return SVN_NO_ERROR;
}
@@ -338,16 +390,6 @@ get_password_cb(sasl_conn_t *conn, void
return SASL_FAIL;
}
-/* Wrap an error message from SASL with a prefix that allows users
- * to tell that the error message came from SASL. */
-static const char *
-get_sasl_error(sasl_conn_t *sasl_ctx, apr_pool_t *result_pool)
-{
- return apr_psprintf(result_pool,
- _("SASL authentication error: %s"),
- sasl_errdetail(sasl_ctx));
-}
-
/* Create a new SASL context. */
static svn_error_t *new_sasl_ctx(sasl_conn_t **sasl_ctx,
svn_boolean_t is_tunneled,
@@ -360,14 +402,20 @@ static svn_error_t *new_sasl_ctx(sasl_co
sasl_security_properties_t secprops;
int result;
+ clear_sasl_errno();
result = sasl_client_new(SVN_RA_SVN_SASL_NAME,
hostname, local_addrport, remote_addrport,
callbacks, SASL_SUCCESS_DATA,
sasl_ctx);
if (result != SASL_OK)
- return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- sasl_errstring(result, NULL, NULL));
+ {
+ const char *sasl_errno_msg = get_sasl_errno_msg(result, pool);
+ return svn_error_createf(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
+ _("Could not create SASL context: %s%s"),
+ sasl_errstring(result, NULL, NULL),
+ sasl_errno_msg);
+ }
svn_atomic_inc(&sasl_ctx_count);
apr_pool_cleanup_register(pool, *sasl_ctx, sasl_dispose_cb,
apr_pool_cleanup_null);
@@ -378,11 +426,12 @@ static svn_error_t *new_sasl_ctx(sasl_co
otherwise it will ignore EXTERNAL. The third parameter
should be the username, but since SASL doesn't seem
to use it on the client side, any non-empty string will do. */
+ clear_sasl_errno();
result = sasl_setprop(*sasl_ctx,
SASL_AUTH_EXTERNAL, " ");
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(*sasl_ctx, pool));
+ get_sasl_error(*sasl_ctx, result, pool));
}
/* Set security properties. */
@@ -410,6 +459,7 @@ static svn_error_t *try_auth(svn_ra_svn_
do
{
again = FALSE;
+ clear_sasl_errno();
result = sasl_client_start(sasl_ctx,
mechstring,
&client_interact,
@@ -428,7 +478,7 @@ static svn_error_t *try_auth(svn_ra_svn_
case SASL_NOMEM:
/* Fatal error. Fail the authentication. */
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_ctx, pool));
+ get_sasl_error(sasl_ctx, result, pool));
default:
/* For anything else, delete the mech from the list
and try again. */
@@ -480,16 +530,17 @@ static svn_error_t *try_auth(svn_ra_svn_
if (strcmp(mech, "CRAM-MD5") != 0)
in = svn_base64_decode_string(in, pool);
+ clear_sasl_errno();
result = sasl_client_step(sasl_ctx,
in->data,
- in->len,
+ (const unsigned int) in->len,
&client_interact,
&out, /* Filled in by SASL. */
&outlen);
if (result != SASL_OK && result != SASL_CONTINUE)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_ctx, pool));
+ get_sasl_error(sasl_ctx, result, pool));
/* If the server thinks we're done, then don't send any response. */
if (strcmp(status, "success") == 0)
@@ -568,12 +619,13 @@ static svn_error_t *sasl_read_cb(void *b
*len = 0;
return SVN_NO_ERROR;
}
- result = sasl_decode(sasl_baton->ctx, buffer, len2,
+ clear_sasl_errno();
+ result = sasl_decode(sasl_baton->ctx, buffer, (unsigned int) len2,
&sasl_baton->read_buf,
&sasl_baton->read_len);
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_baton->ctx,
+ get_sasl_error(sasl_baton->ctx, result,
sasl_baton->scratch_pool));
}
@@ -609,13 +661,14 @@ sasl_write_cb(void *baton, const char *b
{
/* Make sure we don't write too much. */
*len = (*len > sasl_baton->maxsize) ? sasl_baton->maxsize : *len;
- result = sasl_encode(sasl_baton->ctx, buffer, *len,
+ clear_sasl_errno();
+ result = sasl_encode(sasl_baton->ctx, buffer, (unsigned int) *len,
&sasl_baton->write_buf,
&sasl_baton->write_len);
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_baton->ctx,
+ get_sasl_error(sasl_baton->ctx, result,
sasl_baton->scratch_pool));
}
@@ -669,10 +722,11 @@ svn_error_t *svn_ra_svn__enable_sasl_enc
int result;
/* Get the strength of the security layer. */
+ clear_sasl_errno();
result = sasl_getprop(sasl_ctx, SASL_SSF, (void*) &ssfp);
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_ctx, pool));
+ get_sasl_error(sasl_ctx, result, pool));
if (*ssfp > 0)
{
@@ -688,23 +742,24 @@ svn_error_t *svn_ra_svn__enable_sasl_enc
sasl_baton->scratch_pool = conn->pool;
/* Find out the maximum input size for sasl_encode. */
+ clear_sasl_errno();
result = sasl_getprop(sasl_ctx, SASL_MAXOUTBUF, &maxsize);
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_ctx, pool));
+ get_sasl_error(sasl_ctx, result, pool));
sasl_baton->maxsize = *((const unsigned int *) maxsize);
/* If there is any data left in the read buffer at this point,
we need to decrypt it. */
if (conn->read_end > conn->read_ptr)
{
+ clear_sasl_errno();
result = sasl_decode(sasl_ctx, conn->read_ptr,
- conn->read_end - conn->read_ptr,
- &sasl_baton->read_buf,
- &sasl_baton->read_len);
+ (unsigned int) (conn->read_end - conn->read_ptr),
+ &sasl_baton->read_buf, &sasl_baton->read_len);
if (result != SASL_OK)
return svn_error_create(SVN_ERR_RA_NOT_AUTHORIZED, NULL,
- get_sasl_error(sasl_ctx, pool));
+ get_sasl_error(sasl_ctx, result, pool));
conn->read_end = conn->read_ptr;
}
Modified: subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c?rev=1329209&r1=1329208&r2=1329209&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/javahl-ra/subversion/libsvn_ra_svn/editorp.c Mon Apr 23 12:32:48 2012
@@ -408,8 +408,6 @@ void svn_ra_svn_get_editor(const svn_del
{
svn_delta_editor_t *ra_svn_editor = svn_delta_default_editor(pool);
ra_svn_edit_baton_t *eb;
- svn_delta_shim_callbacks_t *shim_callbacks =
- svn_delta_shim_callbacks_default(pool);
eb = apr_palloc(pool, sizeof(*eb));
eb->conn = conn;
@@ -439,7 +437,8 @@ void svn_ra_svn_get_editor(const svn_del
*edit_baton = eb;
svn_error_clear(svn_editor__insert_shims(editor, edit_baton, *editor,
- *edit_baton, shim_callbacks,
+ *edit_baton, NULL, NULL,
+ conn->shim_callbacks,
pool, pool));
}