blob: 64318f725680fabcc1a6e3b509e7d79bdae5b897 [file] [log] [blame]
/* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
* ====================================================================
*/
#include "serf.h"
#include "serf_private.h"
/* Global error processing. */
apr_status_t
serf__global_error_callback(void *baton,
unsigned source,
apr_status_t status,
const char *message)
{
return APR_SUCCESS;
}
static void *global_error_callback_baton = NULL;
static serf_error_cb_t global_error_callback = serf__global_error_callback;
void serf_global_error_callback_set(serf_error_cb_t callback, void *baton)
{
global_error_callback_baton = baton;
global_error_callback = callback;
}
/* The various process_*_error functions set the error source, then either
call the appropriate error callback or, if that's not defined, send the
message up the hierarchy until it's either handled by a registered
callback or thrown away by default_global_error_callback().
This way, the callers of serf__*_error() don't have to bother with
the error source or check if their callbacks have been defined. */
static apr_status_t process_global_error(unsigned source,
apr_status_t status,
const char *message)
{
if (0 == (source & SERF_ERROR_CB_MASK)) {
source |= SERF_ERROR_CB_GLOBAL;
}
return global_error_callback(global_error_callback_baton,
source, status, message);
}
/* Context error processing. */
static apr_status_t process_context_error(unsigned source,
const serf_context_t* ctx,
apr_status_t status,
const char *message)
{
if (0 == (source & SERF_ERROR_CB_MASK)) {
source |= SERF_ERROR_CB_CONTEXT;
}
if (ctx->error_callback) {
return ctx->error_callback(ctx->error_callback_baton,
source, status, message);
}
return process_global_error(source, status, message);
}
apr_status_t serf__context_error(const serf_context_t* ctx,
apr_status_t status,
const char *message)
{
return process_context_error(SERF_ERROR_CB_CONTEXT,
ctx, status, message);
}
/* Connection error processing. */
static apr_status_t process_connection_error(unsigned source,
const serf_connection_t *conn,
apr_status_t status,
const char *message)
{
if (0 == (source & SERF_ERROR_CB_MASK)) {
source |= SERF_ERROR_CB_OUTGOING;
}
if (conn->error_callback) {
return conn->error_callback(conn->error_callback_baton,
source, status, message);
}
return process_context_error(source, conn->ctx, status, message);
}
apr_status_t serf__connection_error(const serf_connection_t *conn,
apr_status_t status,
const char *message)
{
return process_connection_error(SERF_ERROR_CB_OUTGOING,
conn, status, message);
}
apr_status_t serf__request_error(const serf_request_t *req,
apr_status_t status,
const char *message)
{
return process_connection_error(SERF_ERROR_CB_OUTGOING
| SERF_ERROR_CB_REQUEST,
req->conn, status, message);
}
apr_status_t serf__response_error(const serf_request_t *req,
apr_status_t status,
const char *message)
{
return process_connection_error(SERF_ERROR_CB_OUTGOING
| SERF_ERROR_CB_RESPONSE,
req->conn, status, message);
}
/* Incoming error processing. */
static apr_status_t process_incoming_error(unsigned source,
const serf_incoming_t *client,
apr_status_t status,
const char *message)
{
if (0 == (source & SERF_ERROR_CB_MASK)) {
source |= SERF_ERROR_CB_INCOMING;
}
if (client->error_callback) {
return client->error_callback(client->error_callback_baton,
source, status, message);
}
return process_context_error(source, client->ctx, status, message);
}
apr_status_t serf__incoming_error(const serf_incoming_t *client,
apr_status_t status,
const char *message)
{
return process_incoming_error(SERF_ERROR_CB_INCOMING,
client, status, message);
}
apr_status_t serf__incoming_request_error(const serf_incoming_request_t *req,
apr_status_t status,
const char *message)
{
return process_incoming_error(SERF_ERROR_CB_INCOMING
| SERF_ERROR_CB_REQUEST,
req->incoming, status, message);
}
apr_status_t serf__incoming_response_error(const serf_incoming_request_t *req,
apr_status_t status,
const char *message)
{
return process_incoming_error(SERF_ERROR_CB_INCOMING
| SERF_ERROR_CB_RESPONSE,
req->incoming, status, message);
}
/* Errors from the SSL context.
Callers of the SSL functions can create an serf__ssl_error_ctx_t
on the stack and pass it to the called function, which can then
dispatch any errors it generates to the appropriate callback. */
apr_status_t serf__global_ssl_error(const void *baton,
apr_status_t status,
const char *message)
{
/* Ignores the baton, since there's only one global error callback. */
return process_global_error(SERF_ERROR_CB_SSL_CONTEXT
| SERF_ERROR_CB_GLOBAL,
status, message);
}
apr_status_t serf__context_ssl_error(const void *baton,
apr_status_t status,
const char *message)
{
const serf_context_t *const ctx = baton;
return process_context_error(SERF_ERROR_CB_SSL_CONTEXT
| SERF_ERROR_CB_CONTEXT,
ctx, status, message);
}
apr_status_t serf__connection_ssl_error(const void *baton,
apr_status_t status,
const char *message)
{
const serf_connection_t *const conn = baton;
return process_connection_error(SERF_ERROR_CB_SSL_CONTEXT
| SERF_ERROR_CB_OUTGOING,
conn, status, message);
}
apr_status_t serf__incoming_ssl_error(const void *baton,
apr_status_t status,
const char *message)
{
const serf_incoming_t *const client = baton;
return process_incoming_error(SERF_ERROR_CB_SSL_CONTEXT
| SERF_ERROR_CB_INCOMING,
client, status, message);
}