Import serf-1.3.0
This commit is contained in:
parent
4e6fa1a552
commit
1f89a666e3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/serf/dist/; revision=253893 svn path=/vendor/serf/serf-1.3.0/; revision=253894; tag=vendor/serf/serf-1.3.0
20
CHANGES
20
CHANGES
@ -1,4 +1,20 @@
|
||||
Serf 1.2.1 [2013-06-03, from /tags/1.2.1]
|
||||
Serf 1.3.0 [2013-07-23, from /tags/1.3.0]
|
||||
Fix issue 83: use PATH rather than URI within an ssltunnel (r1952)
|
||||
Fix issue 108: improved error reporting from the underlying socket (r1951)
|
||||
NEW: Switch to the SCons build system; retire serfmake, serf.mak, autotools
|
||||
Improved Basic and Digest authentication:
|
||||
- remember credentials on a per-server basis
|
||||
- properly manage authentication realms
|
||||
- continue functioning when a server sets KeepAlive: off
|
||||
Windows: add support for NTLM authentication
|
||||
Improved 2617 compliance: always use strongest authentication (r1968,1971)
|
||||
Fixed bugs with proxy authentication and SSL tunneling through a proxy
|
||||
Fixed bugs the response parser (r2032,r2036)
|
||||
SSL connection performance improvements
|
||||
Huge expansion of the test suite
|
||||
|
||||
|
||||
Serf 1.2.1 [2013-06-03, from /tags/1.2.1, r1906]
|
||||
Fix issue 95: add gssapi switches to configure (r1864, r1900)
|
||||
Fix issue 97: skip mmap bucket if APR_HAS_MMAP is undefined (r1877)
|
||||
Fix issue 100: building against an old Windows Platform SDK (r1881)
|
||||
@ -19,7 +35,7 @@ Serf 1.2.0 [2013-02-22, from /tags/1.2.0, r1726]
|
||||
Fixed issue 93: cleanup-after-fork interferes with parent (r1714)
|
||||
Fixed most of issue 89: Support REAL SPNEGO authentication
|
||||
Enable Negotiate/Kerberos support for proxy servers.
|
||||
Return error when C-L, chunked, gzip encoded response bodies where
|
||||
Return error when C-L, chunked, gzip encoded response bodies were
|
||||
truncated (due to aborted connection) (r1688)
|
||||
Add a logging mechanism that can be enabled at compile-time.
|
||||
Don't lookup server address if a proxy was configured. (r1706)
|
||||
|
171
Makefile.in
171
Makefile.in
@ -1,171 +0,0 @@
|
||||
#
|
||||
# Makefile for Serf
|
||||
#
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SERF_MAJOR_VERSION=@SERF_MAJOR_VERSION@
|
||||
SERF_DOTTED_VERSION=@SERF_DOTTED_VERSION@
|
||||
|
||||
OBJECTS = buckets/aggregate_buckets.lo buckets/request_buckets.lo context.lo \
|
||||
buckets/buckets.lo buckets/simple_buckets.lo buckets/file_buckets.lo \
|
||||
buckets/mmap_buckets.lo buckets/socket_buckets.lo \
|
||||
buckets/response_body_buckets.lo buckets/response_buckets.lo \
|
||||
buckets/headers_buckets.lo \
|
||||
buckets/allocator.lo buckets/dechunk_buckets.lo \
|
||||
buckets/deflate_buckets.lo buckets/limit_buckets.lo \
|
||||
buckets/ssl_buckets.lo buckets/barrier_buckets.lo \
|
||||
buckets/chunk_buckets.lo buckets/bwtp_buckets.lo \
|
||||
buckets/iovec_buckets.lo \
|
||||
incoming.lo outgoing.lo ssltunnel.lo \
|
||||
auth/auth.lo auth/auth_basic.lo auth/auth_digest.lo \
|
||||
auth/auth_kerb.lo auth/auth_kerb_gss.lo
|
||||
|
||||
TARGET_LIB=libserf-$(SERF_MAJOR_VERSION).la
|
||||
|
||||
TEST_OBJECTS = test/serf_get.lo test/serf_response.lo test/serf_request.lo \
|
||||
test/serf_spider.lo test/serf_server.lo test/serf_bwtp.lo
|
||||
|
||||
TEST_SUITE_OBJECTS = test/CuTest.lo test/test_all.lo test/test_util.lo \
|
||||
test/test_buckets.lo test/test_context.lo \
|
||||
test/test_ssl.lo test/server/test_server.lo \
|
||||
test/server/test_sslserver.lo
|
||||
|
||||
PROGRAMS = $(TEST_OBJECTS:.lo=) test/test_all
|
||||
|
||||
TESTCASES = test/testcases/simple.response \
|
||||
test/testcases/chunked-empty.response test/testcases/chunked.response \
|
||||
test/testcases/chunked-trailers.response \
|
||||
test/testcases/deflate.response
|
||||
|
||||
HEADERS = serf.h serf_bucket_types.h serf_bucket_util.h
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
pkgconfigdir=$(libdir)/pkgconfig
|
||||
|
||||
LIBTOOL = @APR_LIBTOOL@
|
||||
LTFLAGS = @LTFLAGS@ --tag=CC
|
||||
CC = @CC@
|
||||
CFLAGS = @EXTRA_CFLAGS@ @CFLAGS@
|
||||
CPPFLAGS = @EXTRA_CPPFLAGS@ @CPPFLAGS@
|
||||
INCLUDES = -I$(srcdir) @APR_INCLUDES@ @APU_INCLUDES@ @EXTRA_INCLUDES@
|
||||
MKDIR = @mkdir_p@
|
||||
INSTALL = @INSTALL@
|
||||
|
||||
LDFLAGS = @EXTRA_LDFLAGS@ @LDFLAGS@
|
||||
LIBS = @EXTRA_LIBS@ @SERF_LIBS@ -lz -lssl -lcrypto
|
||||
|
||||
all: $(TARGET_LIB) $(PROGRAMS)
|
||||
|
||||
context.lo: context.c $(HEADERS)
|
||||
incoming.lo: incoming.c $(HEADERS)
|
||||
outgoing.lo: outgoing.c $(HEADERS)
|
||||
ssltunnel.lo: ssltunnel.c $(HEADERS)
|
||||
buckets/aggregate_buckets.lo: buckets/aggregate_buckets.c $(HEADERS)
|
||||
buckets/request_buckets.lo: buckets/request_buckets.c $(HEADERS)
|
||||
buckets/buckets.lo: buckets/buckets.c $(HEADERS)
|
||||
buckets/simple_buckets.lo: buckets/simple_buckets.c $(HEADERS)
|
||||
buckets/file_buckets.lo: buckets/file_buckets.c $(HEADERS)
|
||||
buckets/mmap_buckets.lo: buckets/mmap_buckets.c $(HEADERS)
|
||||
buckets/socket_buckets.lo: buckets/socket_buckets.c $(HEADERS)
|
||||
buckets/response_body_buckets.lo: buckets/response_body_buckets.c $(HEADERS)
|
||||
buckets/response_buckets.lo: buckets/response_buckets.c $(HEADERS)
|
||||
buckets/headers_buckets.lo: buckets/headers_buckets.c $(HEADERS)
|
||||
buckets/allocator.lo: buckets/allocator.c $(HEADERS)
|
||||
buckets/dechunk_buckets.lo: buckets/dechunk_buckets.c $(HEADERS)
|
||||
buckets/deflate_buckets.lo: buckets/deflate_buckets.c $(HEADERS)
|
||||
buckets/limit_buckets.lo: buckets/limit_buckets.c $(HEADERS)
|
||||
buckets/ssl_buckets.lo: buckets/ssl_buckets.c $(HEADERS)
|
||||
buckets/barrier_buckets.lo: buckets/barrier_buckets.c $(HEADERS)
|
||||
buckets/chunk_buckets.lo: buckets/chunk_buckets.c $(HEADERS)
|
||||
buckets/bwtp_buckets.lo: buckets/bwtp_buckets.c $(HEADERS)
|
||||
buckets/iovec_buckets.lo: buckets/iovec_buckets.c $(HEADERS)
|
||||
|
||||
test/serf_get.lo: test/serf_get.c $(HEADERS)
|
||||
test/serf_response.lo: test/serf_response.c $(HEADERS)
|
||||
test/serf_request.lo: test/serf_request.c $(HEADERS)
|
||||
test/serf_server.lo: test/serf_server.c $(HEADERS)
|
||||
test/serf_spider.lo: test/serf_spider.c $(HEADERS)
|
||||
test/serf_bwtp.lo: test/serf_bwtp.c $(HEADERS)
|
||||
|
||||
test/CuTest.lo: test/CuTest.c $(HEADERS)
|
||||
test/test_all.lo: test/test_all.c $(HEADERS)
|
||||
test/test_util.lo: test/test_util.c $(HEADERS)
|
||||
test/test_buckets.lo: test/test_buckets.c $(HEADERS)
|
||||
test/test_context.lo: test/test_context.c $(HEADERS)
|
||||
test/test_ssl.lo: test/test_ssl.c $(HEADERS)
|
||||
|
||||
$(TARGET_LIB): $(OBJECTS)
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -rpath $(libdir) -o $@ $(OBJECTS) $(LIBS)
|
||||
|
||||
test/serf_get: $(TARGET_LIB) test/serf_get.lo
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_get.lo $(LIBS)
|
||||
|
||||
test/serf_response: $(TARGET_LIB) test/serf_response.lo
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_response.lo $(LIBS)
|
||||
|
||||
test/serf_request: $(TARGET_LIB) test/serf_request.lo
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_request.lo $(LIBS)
|
||||
|
||||
test/serf_server: $(TARGET_LIB) test/serf_server.lo
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_server.lo $(LIBS)
|
||||
|
||||
test/serf_spider: $(TARGET_LIB) test/serf_spider.lo
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_spider.lo $(LIBS)
|
||||
|
||||
test/serf_bwtp: $(TARGET_LIB) test/serf_bwtp.lo
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) test/serf_bwtp.lo $(LIBS)
|
||||
|
||||
test/test_all: $(TARGET_LIB) $(TEST_SUITE_OBJECTS)
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LDFLAGS) -static -o $@ $(TARGET_LIB) $(TEST_SUITE_OBJECTS) $(LIBS)
|
||||
|
||||
check: test/serf_response test/test_all
|
||||
@for i in $(TESTCASES); \
|
||||
do echo "== Testing $$i =="; \
|
||||
./test/serf_response $(srcdir)/$$i; \
|
||||
done;
|
||||
@echo "== Running test_all ==";
|
||||
@./test/test_all
|
||||
|
||||
install: $(TARGET_LIB)
|
||||
$(MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir) $(DESTDIR)$(pkgconfigdir)
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=install $(INSTALL) -m 644 $(TARGET_LIB) $(DESTDIR)$(libdir)
|
||||
for i in $(HEADERS); do \
|
||||
$(INSTALL) -m 644 $(srcdir)/$$i $(DESTDIR)$(includedir); \
|
||||
done
|
||||
$(INSTALL) -m 644 serf.pc $(DESTDIR)$(pkgconfigdir)/serf-$(SERF_MAJOR_VERSION).pc
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET_LIB) $(OBJECTS) $(OBJECTS:.lo=.o) $(PROGRAMS) $(TEST_OBJECTS) $(TEST_OBJECTS:.lo=.o) $(TEST_SUITE_OBJECTS) $(TEST_SUITE_OBJECTS:.lo=.o)
|
||||
for subdir in . buckets test; do \
|
||||
(cd $$subdir && rm -rf .libs) ; \
|
||||
done
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile serf.pc config.log config.status
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .lo .o
|
||||
|
||||
mkdir-vpath:
|
||||
@if [ ! -d auth ]; then \
|
||||
$(MKDIR) auth; \
|
||||
fi;
|
||||
@if [ ! -d buckets ]; then \
|
||||
$(MKDIR) buckets; \
|
||||
fi;
|
||||
@if [ ! -d test ]; then \
|
||||
$(MKDIR) test; \
|
||||
fi;
|
||||
@if [ ! -d test/server ]; then \
|
||||
$(MKDIR) test/server; \
|
||||
fi;
|
||||
@if [ ! -r test/serftestca.pem ]; then \
|
||||
cp -f $(srcdir)/test/serftestca.pem test/; \
|
||||
fi;
|
||||
|
||||
.c.lo:
|
||||
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(INCLUDES) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< && touch $@
|
70
README
70
README
@ -14,25 +14,67 @@ kept to a minimum to provide high performance operation.
|
||||
|
||||
----
|
||||
|
||||
Quick guide for the impatient
|
||||
1. INSTALL
|
||||
|
||||
(Unix)
|
||||
% ./configure
|
||||
% make
|
||||
% make install
|
||||
1.1. SCons build system
|
||||
|
||||
----
|
||||
serf uses SCons 2.x for its build system. If it is not installed on
|
||||
your system, then you can install it onto your system. If you do not
|
||||
have permissions, then you can download and install the "local"
|
||||
version into your home directory. When installed privately, simply
|
||||
create a symlink for 'scons' in your PATH to /path/to/scons/scons.py.
|
||||
|
||||
Building serf from a Subversion checkout (non-packaged releases)
|
||||
Fetch the scons-local package:
|
||||
http://prdownloads.sourceforge.net/scons/scons-local-2.0.1.tar.gz
|
||||
|
||||
We suggest that you try out 'serfmake'.
|
||||
|
||||
% ./serfmake --prefix=/usr/local/serf --with-apr=/usr/local/apr install
|
||||
1.2 Building serf
|
||||
|
||||
If you want to use the autoconf build system and are using a Subversion
|
||||
checkout, you need to run buildconf and have APR and APR-util sources handy.
|
||||
To build serf:
|
||||
|
||||
% ./buildconf --with-apr=/path/to/apr --with-apr-util=/path/to/apr-util
|
||||
(By default, buildconf will look in . and ../ for apr and apr-util.)
|
||||
$ scons APR=/path/to/apr APU=/path/to/apu OPENSSL=/openssl/base PREFIX=/path/to/prefix
|
||||
|
||||
Then, you can use ./configure, make, etc.
|
||||
The switches are recorded into .saved_config, so they only need to be
|
||||
specified the first time scons is run.
|
||||
|
||||
PREFIX should specify where serf should be installed. PREFIX defaults to
|
||||
/usr/local.
|
||||
|
||||
The default for the other three switches (APR, APU, OPENSSL) is /usr.
|
||||
|
||||
The build system looks for apr-1-config at $APR/bin/apr-1-config, or
|
||||
the path should indicate apr-1-config itself. Similarly for the path
|
||||
to apu-1-config.
|
||||
|
||||
OPENSSL should specify the root of the install (eg. /opt/local). The
|
||||
includes will be found OPENSSL/include and libraries at OPENSSL/lib.
|
||||
|
||||
If you wish to use VPATH-style builds (where objects are created in a
|
||||
distinct directory from the source), you can use:
|
||||
|
||||
$ scons -Y /path/to/serf/source
|
||||
|
||||
At any point, the current settings can be examined:
|
||||
|
||||
$ scons --help
|
||||
|
||||
|
||||
1.3 Running the test suite
|
||||
|
||||
$ scons check
|
||||
|
||||
|
||||
1.4 Installing serf
|
||||
|
||||
$ scons install
|
||||
|
||||
Note that the PREFIX variable should have been specified in a previous
|
||||
invocation of scons (and saved into .saved_config), or it can be
|
||||
specified on the install command line:
|
||||
|
||||
$ scons PREFIX=/some/path install
|
||||
|
||||
|
||||
1.4 Cleaning up the build
|
||||
|
||||
$ scons -c
|
||||
|
438
SConstruct
Normal file
438
SConstruct
Normal file
@ -0,0 +1,438 @@
|
||||
# -*- python -*-
|
||||
#
|
||||
# Copyright 2011-2012 Justin Erenkrantz and Greg Stein
|
||||
#
|
||||
# Licensed 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.
|
||||
#
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
|
||||
HEADER_FILES = ['serf.h',
|
||||
'serf_bucket_types.h',
|
||||
'serf_bucket_util.h',
|
||||
]
|
||||
|
||||
# where we save the configuration variables
|
||||
SAVED_CONFIG = '.saved_config'
|
||||
|
||||
# Variable class that does no validation on the input
|
||||
def _converter(val):
|
||||
"""
|
||||
"""
|
||||
if val == 'none':
|
||||
val = []
|
||||
else:
|
||||
val = val.split(',')
|
||||
return val
|
||||
|
||||
def RawListVariable(key, help, default):
|
||||
"""
|
||||
The input parameters describe a 'raw string list' option. This class
|
||||
accepts a comma separated list and converts it to a space separated
|
||||
list.
|
||||
"""
|
||||
return (key, '%s' % (help), default, None, lambda val: _converter(val))
|
||||
|
||||
# default directories
|
||||
if sys.platform == 'win32':
|
||||
default_libdir='..'
|
||||
default_prefix='Debug'
|
||||
else:
|
||||
default_libdir='/usr'
|
||||
default_prefix='/usr/local'
|
||||
|
||||
opts = Variables(files=[SAVED_CONFIG])
|
||||
opts.AddVariables(
|
||||
PathVariable('PREFIX',
|
||||
'Directory to install under',
|
||||
default_prefix,
|
||||
PathVariable.PathIsDir),
|
||||
PathVariable('APR',
|
||||
"Path to apr-1-config, or to APR's install area",
|
||||
default_libdir,
|
||||
PathVariable.PathAccept),
|
||||
PathVariable('APU',
|
||||
"Path to apu-1-config, or to APR's install area",
|
||||
default_libdir,
|
||||
PathVariable.PathAccept),
|
||||
PathVariable('OPENSSL',
|
||||
"Path to OpenSSL's install area",
|
||||
default_libdir,
|
||||
PathVariable.PathIsDir),
|
||||
PathVariable('ZLIB',
|
||||
"Path to zlib's install area",
|
||||
default_libdir,
|
||||
PathVariable.PathIsDir),
|
||||
PathVariable('GSSAPI',
|
||||
"Path to GSSAPI's install area",
|
||||
None,
|
||||
None),
|
||||
BoolVariable('DEBUG',
|
||||
"Enable debugging info and strict compile warnings",
|
||||
False),
|
||||
BoolVariable('APR_STATIC',
|
||||
"Enable using a static compiled APR",
|
||||
False),
|
||||
RawListVariable('CC', "Command name or path of the C compiler", None),
|
||||
RawListVariable('CFLAGS', "Extra flags for the C compiler (comma separated)",
|
||||
None),
|
||||
RawListVariable('LIBS', "Extra libraries passed to the linker, "
|
||||
"e.g. -l<library> (comma separated)", None),
|
||||
RawListVariable('LINKFLAGS', "Extra flags for the linker (comma separated)",
|
||||
None),
|
||||
RawListVariable('CPPFLAGS', "Extra flags for the C preprocessor "
|
||||
"(comma separated)", None),
|
||||
)
|
||||
|
||||
if sys.platform == 'win32':
|
||||
opts.AddVariables(
|
||||
# By default SCons builds for the host platform on Windows, when using
|
||||
# a supported compiler (E.g. VS2010/VS2012). Allow overriding
|
||||
|
||||
# Note that Scons 1.3 only supports this on Windows and only when
|
||||
# constructing Environment(). Later changes to TARGET_ARCH are ignored
|
||||
EnumVariable('TARGET_ARCH',
|
||||
"Platform to build for (x86|x64|win32|x86_64)",
|
||||
'x86',
|
||||
allowed_values=('x86', 'x86_64', 'ia64'),
|
||||
map={'X86' : 'x86',
|
||||
'win32': 'x86',
|
||||
'Win32': 'x86',
|
||||
'x64' : 'x86_64',
|
||||
'X64' : 'x86_64'
|
||||
}),
|
||||
|
||||
EnumVariable('MSVC_VERSION',
|
||||
"Visual C++ to use for building (E.g. 11.0, 9.0)",
|
||||
None,
|
||||
allowed_values=('12.0', '11.0', '10.0', '9.0', '8.0', '6.0')
|
||||
),
|
||||
|
||||
# We always documented that we handle an install layout, but in fact we
|
||||
# hardcoded source layouts. Allow disabling this behavior.
|
||||
# ### Fix default?
|
||||
BoolVariable('SOURCE_LAYOUT',
|
||||
"Assume a source layout instead of install layout",
|
||||
True),
|
||||
)
|
||||
|
||||
env = Environment(variables=opts,
|
||||
tools=('default', 'textfile',),
|
||||
CPPPATH=['.', ],
|
||||
)
|
||||
|
||||
env.Append(BUILDERS = {
|
||||
'GenDef' :
|
||||
Builder(action = sys.executable + ' build/gen_def.py $SOURCES > $TARGET',
|
||||
suffix='.def', src_suffix='.h')
|
||||
})
|
||||
|
||||
match = re.search('SERF_MAJOR_VERSION ([0-9]+).*'
|
||||
'SERF_MINOR_VERSION ([0-9]+).*'
|
||||
'SERF_PATCH_VERSION ([0-9]+)',
|
||||
env.File('serf.h').get_contents(),
|
||||
re.DOTALL)
|
||||
MAJOR, MINOR, PATCH = [int(x) for x in match.groups()]
|
||||
env.Append(MAJOR=str(MAJOR))
|
||||
|
||||
# Calling external programs is okay if we're not cleaning or printing help.
|
||||
# (cleaning: no sense in fetching information; help: we may not know where
|
||||
# they are)
|
||||
CALLOUT_OKAY = not (env.GetOption('clean') or env.GetOption('help'))
|
||||
|
||||
|
||||
# HANDLING OF OPTION VARIABLES
|
||||
|
||||
unknown = opts.UnknownVariables()
|
||||
if unknown:
|
||||
print 'Unknown variables:', ', '.join(unknown.keys())
|
||||
Exit(1)
|
||||
|
||||
apr = str(env['APR'])
|
||||
apu = str(env['APU'])
|
||||
zlib = str(env['ZLIB'])
|
||||
gssapi = env.get('GSSAPI', None)
|
||||
|
||||
if gssapi and os.path.isdir(gssapi):
|
||||
krb5_config = os.path.join(gssapi, 'bin', 'krb5-config')
|
||||
if os.path.isfile(krb5_config):
|
||||
gssapi = krb5_config
|
||||
env['GSSAPI'] = krb5_config
|
||||
|
||||
debug = env.get('DEBUG', None)
|
||||
aprstatic = env.get('APR_STATIC', None)
|
||||
|
||||
Help(opts.GenerateHelpText(env))
|
||||
opts.Save(SAVED_CONFIG, env)
|
||||
|
||||
|
||||
# PLATFORM-SPECIFIC BUILD TWEAKS
|
||||
|
||||
thisdir = os.getcwd()
|
||||
libdir = '$PREFIX/lib'
|
||||
incdir = '$PREFIX/include/serf-$MAJOR'
|
||||
|
||||
LIBNAME = 'libserf-${MAJOR}'
|
||||
if sys.platform != 'win32':
|
||||
LIBNAMESTATIC = LIBNAME
|
||||
else:
|
||||
LIBNAMESTATIC = 'serf-${MAJOR}'
|
||||
|
||||
env.Append(RPATH=libdir,
|
||||
PDB='${TARGET.filebase}.pdb')
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
# linkflags.append('-Wl,-install_name,@executable_path/%s.dylib' % (LIBNAME,))
|
||||
env.Append(LINKFLAGS='-Wl,-install_name,%s/%s.dylib' % (thisdir, LIBNAME,))
|
||||
# 'man ld' says positive non-zero for the first number, so we add one.
|
||||
# Mac's interpretation of compatibility is the same as our MINOR version.
|
||||
env.Append(LINKFLAGS='-Wl,-compatibility_version,%d' % (MINOR+1,))
|
||||
env.Append(LINKFLAGS='-Wl,-current_version,%d.%d' % (MINOR+1, PATCH,))
|
||||
|
||||
if sys.platform != 'win32':
|
||||
### gcc only. figure out appropriate test / better way to check these
|
||||
### flags, and check for gcc.
|
||||
env.Append(CFLAGS='-std=c89')
|
||||
env.Append(CCFLAGS=[
|
||||
'-Wdeclaration-after-statement',
|
||||
'-Wmissing-prototypes',
|
||||
])
|
||||
|
||||
### -Wall is not available on Solaris
|
||||
if sys.platform != 'sunos5':
|
||||
env.Append(CCFLAGS='-Wall')
|
||||
|
||||
if debug:
|
||||
env.Append(CCFLAGS='-g')
|
||||
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
|
||||
else:
|
||||
env.Append(CCFLAGS='-O2')
|
||||
env.Append(CPPDEFINES='NDEBUG')
|
||||
|
||||
### works for Mac OS. probably needs to change
|
||||
env.Append(LIBS=['ssl', 'crypto', 'z', ])
|
||||
|
||||
if sys.platform == 'sunos5':
|
||||
env.Append(LIBS='m')
|
||||
else:
|
||||
# Warning level 4, no unused argument warnings
|
||||
env.Append(CCFLAGS=['/W4', '/wd4100'])
|
||||
|
||||
# Choose runtime and optimization
|
||||
if debug:
|
||||
# Disable optimizations for debugging, use debug DLL runtime
|
||||
env.Append(CCFLAGS=['/Od', '/MDd'])
|
||||
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
|
||||
else:
|
||||
# Optimize for speed, use DLL runtime
|
||||
env.Append(CCFLAGS=['/O2', '/MD'])
|
||||
env.Append(CPPDEFINES='NDEBUG')
|
||||
|
||||
# PLAN THE BUILD
|
||||
SHARED_SOURCES = []
|
||||
if sys.platform == 'win32':
|
||||
env.GenDef(['serf.h','serf_bucket_types.h', 'serf_bucket_util.h'])
|
||||
SHARED_SOURCES.append(['serf.def'])
|
||||
|
||||
SOURCES = Glob('*.c') + Glob('buckets/*.c') + Glob('auth/*.c')
|
||||
|
||||
lib_static = env.StaticLibrary(LIBNAMESTATIC, SOURCES)
|
||||
lib_shared = env.SharedLibrary(LIBNAME, SOURCES + SHARED_SOURCES)
|
||||
|
||||
if aprstatic:
|
||||
env.Append(CPPDEFINES=['APR_DECLARE_STATIC', 'APU_DECLARE_STATIC'])
|
||||
|
||||
if sys.platform == 'win32':
|
||||
env.Append(LIBS=['user32.lib', 'advapi32.lib', 'gdi32.lib', 'ws2_32.lib',
|
||||
'crypt32.lib', 'mswsock.lib', 'rpcrt4.lib', 'secur32.lib'])
|
||||
|
||||
# Get apr/apu information into our build
|
||||
env.Append(CPPDEFINES=['WIN32','WIN32_LEAN_AND_MEAN','NOUSER',
|
||||
'NOGDI', 'NONLS','NOCRYPT'])
|
||||
|
||||
if env.get('TARGET_ARCH', None) == 'x86_64':
|
||||
env.Append(CPPDEFINES=['WIN64'])
|
||||
|
||||
if aprstatic:
|
||||
apr_libs='apr-1.lib'
|
||||
apu_libs='aprutil-1.lib'
|
||||
else:
|
||||
apr_libs='libapr-1.lib'
|
||||
apu_libs='libaprutil-1.lib'
|
||||
|
||||
env.Append(LIBS=[apr_libs, apu_libs])
|
||||
if not env.get('SOURCE_LAYOUT', None):
|
||||
env.Append(LIBPATH=['$APR/lib', '$APU/lib'],
|
||||
CPPPATH=['$APR/include/apr-1', '$APU/include/apr-1'])
|
||||
elif aprstatic:
|
||||
env.Append(LIBPATH=['$APR/LibR','$APU/LibR'],
|
||||
CPPPATH=['$APR/include', '$APU/include'])
|
||||
else:
|
||||
env.Append(LIBPATH=['$APR/Release','$APU/Release'],
|
||||
CPPPATH=['$APR/include', '$APU/include'])
|
||||
|
||||
# zlib
|
||||
env.Append(LIBS='zlib.lib')
|
||||
if not env.get('SOURCE_LAYOUT', None):
|
||||
env.Append(CPPPATH='$ZLIB/include',
|
||||
LIBPATH='$ZLIB/lib')
|
||||
else:
|
||||
env.Append(CPPPATH='$ZLIB',
|
||||
LIBPATH='$ZLIB')
|
||||
|
||||
# openssl
|
||||
env.Append(LIBS=['libeay32.lib', 'ssleay32.lib'])
|
||||
if not env.get('SOURCE_LAYOUT', None):
|
||||
env.Append(CPPPATH='$OPENSSL/include/openssl',
|
||||
LIBPATH='$OPENSSL/lib')
|
||||
elif 0: # opensslstatic:
|
||||
env.Append(CPPPATH='$OPENSSL/inc32',
|
||||
LIBPATH='$OPENSSL/out32')
|
||||
else:
|
||||
env.Append(CPPPATH='$OPENSSL/inc32',
|
||||
LIBPATH='$OPENSSL/out32dll')
|
||||
else:
|
||||
if os.path.isdir(apr):
|
||||
apr = os.path.join(apr, 'bin', 'apr-1-config')
|
||||
env['APR'] = apr
|
||||
if os.path.isdir(apu):
|
||||
apu = os.path.join(apu, 'bin', 'apu-1-config')
|
||||
env['APU'] = apu
|
||||
|
||||
### we should use --cc, but that is giving some scons error about an implict
|
||||
### dependency upon gcc. probably ParseConfig doesn't know what to do with
|
||||
### the apr-1-config output
|
||||
if CALLOUT_OKAY:
|
||||
env.ParseConfig('$APR --cflags --cppflags --ldflags --includes'
|
||||
' --link-ld --libs')
|
||||
env.ParseConfig('$APU --ldflags --includes --link-ld --libs')
|
||||
|
||||
### there is probably a better way to run/capture output.
|
||||
### env.ParseConfig() may be handy for getting this stuff into the build
|
||||
if CALLOUT_OKAY:
|
||||
apr_libs = os.popen(env.subst('$APR --link-libtool --libs')).read().strip()
|
||||
apu_libs = os.popen(env.subst('$APU --link-libtool --libs')).read().strip()
|
||||
else:
|
||||
apr_libs = ''
|
||||
apu_libs = ''
|
||||
|
||||
env.Append(CPPPATH='$OPENSSL/include')
|
||||
env.Append(LIBPATH='$OPENSSL/lib')
|
||||
|
||||
|
||||
# If build with gssapi, get its information and define SERF_HAVE_GSSAPI
|
||||
if gssapi and CALLOUT_OKAY:
|
||||
env.ParseConfig('$GSSAPI --libs gssapi')
|
||||
env.Append(CPPDEFINES='SERF_HAVE_GSSAPI')
|
||||
if sys.platform == 'win32':
|
||||
env.Append(CPPDEFINES=['SERF_HAVE_SSPI'])
|
||||
|
||||
# On Solaris, the -R values that APR describes never make it into actual
|
||||
# RPATH flags. We'll manually map all directories in LIBPATH into new
|
||||
# flags to set RPATH values.
|
||||
if sys.platform == 'sunos5':
|
||||
for d in env['LIBPATH']:
|
||||
env.Append(RPATH=d)
|
||||
|
||||
# Set up the construction of serf-*.pc
|
||||
# TODO: add gssapi libs
|
||||
pkgconfig = env.Textfile('serf-%d.pc' % (MAJOR,),
|
||||
env.File('build/serf.pc.in'),
|
||||
SUBST_DICT = {
|
||||
'@MAJOR@': str(MAJOR),
|
||||
'@PREFIX@': '$PREFIX',
|
||||
'@INCLUDE_SUBDIR@': 'serf-%d' % (MAJOR,),
|
||||
'@VERSION@': '%d.%d.%d' % (MAJOR, MINOR, PATCH),
|
||||
'@LIBS@': '%s %s -lz' % (apu_libs, apr_libs),
|
||||
})
|
||||
|
||||
env.Default(lib_static, lib_shared, pkgconfig)
|
||||
|
||||
if CALLOUT_OKAY:
|
||||
conf = Configure(env)
|
||||
|
||||
### some configuration stuffs
|
||||
|
||||
env = conf.Finish()
|
||||
|
||||
|
||||
# INSTALLATION STUFF
|
||||
|
||||
install_static = env.Install(libdir, lib_static)
|
||||
install_shared = env.Install(libdir, lib_shared)
|
||||
|
||||
if sys.platform == 'darwin':
|
||||
install_shared_path = install_shared[0].abspath
|
||||
env.AddPostAction(install_shared, ('install_name_tool -id %s %s'
|
||||
% (install_shared_path,
|
||||
install_shared_path)))
|
||||
### construct shared lib symlinks. this also means install the lib
|
||||
### as libserf-2.1.0.0.dylib, then add the symlinks.
|
||||
### note: see InstallAs
|
||||
|
||||
env.Alias('install-lib', [install_static, install_shared,
|
||||
])
|
||||
env.Alias('install-inc', env.Install(incdir, HEADER_FILES))
|
||||
env.Alias('install-pc', env.Install(os.path.join(libdir, 'pkgconfig'),
|
||||
pkgconfig))
|
||||
env.Alias('install', ['install-lib', 'install-inc', 'install-pc', ])
|
||||
|
||||
|
||||
# TESTS
|
||||
### make move to a separate scons file in the test/ subdir?
|
||||
|
||||
tenv = env.Clone()
|
||||
|
||||
TEST_PROGRAMS = [ 'serf_get', 'serf_response', 'serf_request', 'serf_spider',
|
||||
'test_all', 'serf_bwtp' ]
|
||||
if sys.platform == 'win32':
|
||||
TEST_EXES = [ os.path.join('test', '%s.exe' % (prog)) for prog in TEST_PROGRAMS ]
|
||||
else:
|
||||
TEST_EXES = [ os.path.join('test', '%s' % (prog)) for prog in TEST_PROGRAMS ]
|
||||
|
||||
env.AlwaysBuild(env.Alias('check', TEST_EXES, sys.executable + ' build/check.py',
|
||||
ENV={'PATH' : os.environ['PATH']}))
|
||||
|
||||
# Find the (dynamic) library in this directory
|
||||
tenv.Replace(RPATH=thisdir)
|
||||
tenv.Prepend(LIBS=[LIBNAMESTATIC, ],
|
||||
LIBPATH=[thisdir, ])
|
||||
|
||||
testall_files = [
|
||||
'test/test_all.c',
|
||||
'test/CuTest.c',
|
||||
'test/test_util.c',
|
||||
'test/test_context.c',
|
||||
'test/test_buckets.c',
|
||||
'test/test_auth.c',
|
||||
'test/mock_buckets.c',
|
||||
'test/test_ssl.c',
|
||||
'test/server/test_server.c',
|
||||
'test/server/test_sslserver.c',
|
||||
]
|
||||
|
||||
for proggie in TEST_EXES:
|
||||
if 'test_all' in proggie:
|
||||
tenv.Program(proggie, testall_files )
|
||||
else:
|
||||
tenv.Program(target = proggie, source = [proggie.replace('.exe','') + '.c'])
|
||||
|
||||
|
||||
# HANDLE CLEANING
|
||||
|
||||
if env.GetOption('clean'):
|
||||
# When we're cleaning, we want the dependency tree to include "everything"
|
||||
# that could be built. Thus, include all of the tests.
|
||||
env.Default('check')
|
387
auth/auth.c
387
auth/auth.c
@ -20,6 +20,7 @@
|
||||
#include <apr.h>
|
||||
#include <apr_base64.h>
|
||||
#include <apr_strings.h>
|
||||
#include <apr_lib.h>
|
||||
|
||||
static apr_status_t
|
||||
default_auth_response_handler(peer_t peer,
|
||||
@ -32,10 +33,52 @@ default_auth_response_handler(peer_t peer,
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* These authentication schemes are in order of decreasing security, the topmost
|
||||
scheme will be used first when the server supports it.
|
||||
|
||||
Each set of handlers should support both server (401) and proxy (407)
|
||||
authentication.
|
||||
|
||||
Use lower case for the scheme names to enable case insensitive matching.
|
||||
*/
|
||||
static const serf__authn_scheme_t serf_authn_schemes[] = {
|
||||
#ifdef SERF_HAVE_SPNEGO
|
||||
{
|
||||
"Negotiate",
|
||||
"negotiate",
|
||||
SERF_AUTHN_NEGOTIATE,
|
||||
serf__init_spnego,
|
||||
serf__init_spnego_connection,
|
||||
serf__handle_spnego_auth,
|
||||
serf__setup_request_spnego_auth,
|
||||
serf__validate_response_spnego_auth,
|
||||
},
|
||||
#ifdef WIN32
|
||||
{
|
||||
"NTLM",
|
||||
"ntlm",
|
||||
SERF_AUTHN_NTLM,
|
||||
serf__init_spnego,
|
||||
serf__init_spnego_connection,
|
||||
serf__handle_spnego_auth,
|
||||
serf__setup_request_spnego_auth,
|
||||
serf__validate_response_spnego_auth,
|
||||
},
|
||||
#endif /* #ifdef WIN32 */
|
||||
#endif /* SERF_HAVE_SPNEGO */
|
||||
{
|
||||
"Digest",
|
||||
"digest",
|
||||
SERF_AUTHN_DIGEST,
|
||||
serf__init_digest,
|
||||
serf__init_digest_connection,
|
||||
serf__handle_digest_auth,
|
||||
serf__setup_request_digest_auth,
|
||||
serf__validate_response_digest_auth,
|
||||
},
|
||||
{
|
||||
401,
|
||||
"Basic",
|
||||
"basic",
|
||||
SERF_AUTHN_BASIC,
|
||||
serf__init_basic,
|
||||
serf__init_basic_connection,
|
||||
@ -43,58 +86,6 @@ static const serf__authn_scheme_t serf_authn_schemes[] = {
|
||||
serf__setup_request_basic_auth,
|
||||
default_auth_response_handler,
|
||||
},
|
||||
{
|
||||
407,
|
||||
"Basic",
|
||||
SERF_AUTHN_BASIC,
|
||||
serf__init_basic,
|
||||
serf__init_basic_connection,
|
||||
serf__handle_basic_auth,
|
||||
serf__setup_request_basic_auth,
|
||||
default_auth_response_handler,
|
||||
},
|
||||
{
|
||||
401,
|
||||
"Digest",
|
||||
SERF_AUTHN_DIGEST,
|
||||
serf__init_digest,
|
||||
serf__init_digest_connection,
|
||||
serf__handle_digest_auth,
|
||||
serf__setup_request_digest_auth,
|
||||
serf__validate_response_digest_auth,
|
||||
},
|
||||
{
|
||||
407,
|
||||
"Digest",
|
||||
SERF_AUTHN_DIGEST,
|
||||
serf__init_digest,
|
||||
serf__init_digest_connection,
|
||||
serf__handle_digest_auth,
|
||||
serf__setup_request_digest_auth,
|
||||
serf__validate_response_digest_auth,
|
||||
},
|
||||
#ifdef SERF_HAVE_KERB
|
||||
{
|
||||
401,
|
||||
"Negotiate",
|
||||
SERF_AUTHN_NEGOTIATE,
|
||||
serf__init_kerb,
|
||||
serf__init_kerb_connection,
|
||||
serf__handle_kerb_auth,
|
||||
serf__setup_request_kerb_auth,
|
||||
serf__validate_response_kerb_auth,
|
||||
},
|
||||
{
|
||||
407,
|
||||
"Negotiate",
|
||||
SERF_AUTHN_NEGOTIATE,
|
||||
serf__init_kerb,
|
||||
serf__init_kerb_connection,
|
||||
serf__handle_kerb_auth,
|
||||
serf__setup_request_kerb_auth,
|
||||
serf__validate_response_kerb_auth,
|
||||
},
|
||||
#endif
|
||||
/* ADD NEW AUTHENTICATION IMPLEMENTATIONS HERE (as they're written) */
|
||||
|
||||
/* sentinel */
|
||||
@ -102,21 +93,6 @@ static const serf__authn_scheme_t serf_authn_schemes[] = {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Baton passed to the response header callback function
|
||||
*/
|
||||
typedef struct {
|
||||
int code;
|
||||
apr_status_t status;
|
||||
const char *header;
|
||||
serf_request_t *request;
|
||||
serf_bucket_t *response;
|
||||
void *baton;
|
||||
apr_pool_t *pool;
|
||||
const serf__authn_scheme_t *scheme;
|
||||
const char *last_scheme_name;
|
||||
} auth_baton_t;
|
||||
|
||||
/* Reads and discards all bytes in the response body. */
|
||||
static apr_status_t discard_body(serf_bucket_t *response)
|
||||
{
|
||||
@ -142,99 +118,128 @@ static apr_status_t discard_body(serf_bucket_t *response)
|
||||
*
|
||||
* Returns a non-0 value of a matching handler was found.
|
||||
*/
|
||||
static int handle_auth_header(void *baton,
|
||||
const char *key,
|
||||
const char *header)
|
||||
static int handle_auth_headers(int code,
|
||||
void *baton,
|
||||
apr_hash_t *hdrs,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const serf__authn_scheme_t *scheme;
|
||||
serf_connection_t *conn = request->conn;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
apr_status_t status;
|
||||
|
||||
status = SERF_ERROR_AUTHN_NOT_SUPPORTED;
|
||||
|
||||
/* Find the matching authentication handler.
|
||||
Note that we don't reuse the auth scheme stored in the context,
|
||||
as that may have changed. (ex. fallback from ntlm to basic.) */
|
||||
for (scheme = serf_authn_schemes; scheme->name != 0; ++scheme) {
|
||||
const char *auth_hdr;
|
||||
serf__auth_handler_func_t handler;
|
||||
serf__authn_info_t *authn_info;
|
||||
|
||||
if (! (ctx->authn_types & scheme->type))
|
||||
continue;
|
||||
|
||||
serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
|
||||
"Client supports: %s\n", scheme->name);
|
||||
|
||||
auth_hdr = apr_hash_get(hdrs, scheme->key, APR_HASH_KEY_STRING);
|
||||
|
||||
if (!auth_hdr)
|
||||
continue;
|
||||
|
||||
/* Found a matching scheme */
|
||||
status = APR_SUCCESS;
|
||||
|
||||
handler = scheme->handle_func;
|
||||
|
||||
serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
|
||||
"... matched: %s\n", scheme->name);
|
||||
|
||||
if (code == 401) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
/* If this is the first time we use this scheme on this context and/or
|
||||
this connection, make sure to initialize the authentication handler
|
||||
first. */
|
||||
if (authn_info->scheme != scheme) {
|
||||
status = scheme->init_ctx_func(code, ctx, ctx->pool);
|
||||
if (!status) {
|
||||
status = scheme->init_conn_func(scheme, code, conn,
|
||||
conn->pool);
|
||||
if (!status)
|
||||
authn_info->scheme = scheme;
|
||||
else
|
||||
authn_info->scheme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
const char *auth_attr = strchr(auth_hdr, ' ');
|
||||
if (auth_attr) {
|
||||
auth_attr++;
|
||||
}
|
||||
|
||||
status = handler(code, request, response,
|
||||
auth_hdr, auth_attr, baton, ctx->pool);
|
||||
}
|
||||
|
||||
if (status == APR_SUCCESS)
|
||||
break;
|
||||
|
||||
/* No success authenticating with this scheme, try the next.
|
||||
If no more authn schemes are found the status of this scheme will be
|
||||
returned.
|
||||
*/
|
||||
serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
|
||||
"%s authentication failed.\n", scheme->name);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Baton passed to the store_header_in_dict callback function
|
||||
*/
|
||||
typedef struct {
|
||||
const char *header;
|
||||
apr_pool_t *pool;
|
||||
apr_hash_t *hdrs;
|
||||
} auth_baton_t;
|
||||
|
||||
static int store_header_in_dict(void *baton,
|
||||
const char *key,
|
||||
const char *header)
|
||||
{
|
||||
auth_baton_t *ab = baton;
|
||||
int scheme_found = FALSE;
|
||||
const char *auth_name;
|
||||
const char *auth_attr;
|
||||
const serf__authn_scheme_t *scheme = NULL;
|
||||
serf_connection_t *conn = ab->request->conn;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
char *auth_name, *c;
|
||||
|
||||
/* We're only interested in xxxx-Authenticate headers. */
|
||||
if (strcmp(key, ab->header) != 0)
|
||||
return 0;
|
||||
|
||||
/* Extract the authentication scheme name, and prepare for reading
|
||||
the attributes. */
|
||||
/* Extract the authentication scheme name. */
|
||||
auth_attr = strchr(header, ' ');
|
||||
if (auth_attr) {
|
||||
auth_name = apr_pstrmemdup(ab->pool, header, auth_attr - header);
|
||||
++auth_attr;
|
||||
}
|
||||
else
|
||||
auth_name = header;
|
||||
auth_name = apr_pstrmemdup(ab->pool, header, strlen(header));
|
||||
|
||||
ab->last_scheme_name = auth_name;
|
||||
/* Convert scheme name to lower case to enable case insensitive matching. */
|
||||
for (c = auth_name; *c != '\0'; c++)
|
||||
*c = (char)apr_tolower(*c);
|
||||
|
||||
/* Find the matching authentication handler.
|
||||
Note that we don't reuse the auth scheme stored in the context,
|
||||
as that may have changed. (ex. fallback from ntlm to basic.) */
|
||||
for (scheme = serf_authn_schemes; scheme->code != 0; ++scheme) {
|
||||
if (! (ab->code == scheme->code &&
|
||||
ctx->authn_types & scheme->type))
|
||||
continue;
|
||||
apr_hash_set(ab->hdrs, auth_name, APR_HASH_KEY_STRING,
|
||||
apr_pstrdup(ab->pool, header));
|
||||
|
||||
serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
|
||||
"Client supports: %s\n", scheme->name);
|
||||
if (strcmp(auth_name, scheme->name) == 0) {
|
||||
serf__auth_handler_func_t handler = scheme->handle_func;
|
||||
apr_status_t status = 0;
|
||||
|
||||
serf__log_skt(AUTH_VERBOSE, __FILE__, conn->skt,
|
||||
"... matched: %s\n", scheme->name);
|
||||
/* If this is the first time we use this scheme on this connection,
|
||||
make sure to initialize the authentication handler first. */
|
||||
if (ab->code == 401 && ctx->authn_info.scheme != scheme) {
|
||||
status = scheme->init_ctx_func(ab->code, ctx, ctx->pool);
|
||||
if (!status) {
|
||||
status = scheme->init_conn_func(ab->code, conn, conn->pool);
|
||||
|
||||
if (!status)
|
||||
ctx->authn_info.scheme = scheme;
|
||||
else
|
||||
ctx->authn_info.scheme = NULL;
|
||||
}
|
||||
}
|
||||
else if (ab->code == 407 && ctx->proxy_authn_info.scheme != scheme) {
|
||||
status = scheme->init_ctx_func(ab->code, ctx, ctx->pool);
|
||||
if (!status) {
|
||||
status = scheme->init_conn_func(ab->code, conn, conn->pool);
|
||||
|
||||
if (!status)
|
||||
ctx->proxy_authn_info.scheme = scheme;
|
||||
else
|
||||
ctx->proxy_authn_info.scheme = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
scheme_found = TRUE;
|
||||
ab->scheme = scheme;
|
||||
status = handler(ab->code, ab->request, ab->response,
|
||||
header, auth_attr, ab->baton, ctx->pool);
|
||||
}
|
||||
|
||||
/* If the authentication fails, cache the error for now. Try the
|
||||
next available scheme. If there's none raise the error. */
|
||||
if (status) {
|
||||
scheme_found = FALSE;
|
||||
scheme = NULL;
|
||||
}
|
||||
/* Let the caller now if the authentication setup was succesful
|
||||
or not. */
|
||||
ab->status = status;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If a matching scheme handler was found, we can stop iterating
|
||||
over the response headers - so return a non-0 value. */
|
||||
return scheme_found;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Dispatch authentication handling. This function matches the possible
|
||||
@ -252,11 +257,7 @@ static apr_status_t dispatch_auth(int code,
|
||||
auth_baton_t ab = { 0 };
|
||||
const char *auth_hdr;
|
||||
|
||||
ab.code = code;
|
||||
ab.status = APR_SUCCESS;
|
||||
ab.request = request;
|
||||
ab.response = response;
|
||||
ab.baton = baton;
|
||||
ab.hdrs = apr_hash_make(pool);
|
||||
ab.pool = pool;
|
||||
|
||||
/* Before iterating over all authn headers, check if there are any. */
|
||||
@ -275,8 +276,8 @@ static apr_status_t dispatch_auth(int code,
|
||||
"%s authz required. Response header(s): %s\n",
|
||||
code == 401 ? "Server" : "Proxy", auth_hdr);
|
||||
|
||||
/* Iterate over all headers. Try to find a matching authentication scheme
|
||||
handler.
|
||||
|
||||
/* Store all WWW- or Proxy-Authenticate headers in a dictionary.
|
||||
|
||||
Note: it is possible to have multiple Authentication: headers. We do
|
||||
not want to combine them (per normal header combination rules) as that
|
||||
@ -285,15 +286,13 @@ static apr_status_t dispatch_auth(int code,
|
||||
work with.
|
||||
*/
|
||||
serf_bucket_headers_do(hdrs,
|
||||
handle_auth_header,
|
||||
store_header_in_dict,
|
||||
&ab);
|
||||
if (ab.status != APR_SUCCESS)
|
||||
return ab.status;
|
||||
|
||||
if (!ab.scheme || ab.scheme->name == NULL) {
|
||||
/* No matching authentication found. */
|
||||
return SERF_ERROR_AUTHN_NOT_SUPPORTED;
|
||||
}
|
||||
/* Iterate over all authentication schemes, in order of decreasing
|
||||
security. Try to find a authentication schema the server support. */
|
||||
return handle_auth_headers(code, baton, ab.hdrs,
|
||||
request, response, pool);
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
@ -356,28 +355,41 @@ apr_status_t serf__handle_auth_response(int *consumed_response,
|
||||
|
||||
/* Requeue the request with the necessary auth headers. */
|
||||
/* ### Application doesn't know about this request! */
|
||||
serf_connection_priority_request_create(request->conn,
|
||||
request->setup,
|
||||
request->setup_baton);
|
||||
if (request->ssltunnel) {
|
||||
serf__ssltunnel_request_create(request->conn,
|
||||
request->setup,
|
||||
request->setup_baton);
|
||||
} else {
|
||||
serf_connection_priority_request_create(request->conn,
|
||||
request->setup,
|
||||
request->setup_baton);
|
||||
}
|
||||
|
||||
return APR_EOF;
|
||||
} else {
|
||||
/* Validate the response authn headers if needed. */
|
||||
serf__validate_response_func_t validate_resp;
|
||||
serf_connection_t *conn = request->conn;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info;
|
||||
apr_status_t resp_status = APR_SUCCESS;
|
||||
|
||||
if (ctx->authn_info.scheme) {
|
||||
validate_resp = ctx->authn_info.scheme->validate_response_func;
|
||||
|
||||
|
||||
/* Validate the response server authn headers. */
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
if (authn_info->scheme) {
|
||||
validate_resp = authn_info->scheme->validate_response_func;
|
||||
resp_status = validate_resp(HOST, sl.code, conn, request, response,
|
||||
pool);
|
||||
}
|
||||
if (!resp_status && ctx->proxy_authn_info.scheme) {
|
||||
validate_resp = ctx->proxy_authn_info.scheme->validate_response_func;
|
||||
|
||||
/* Validate the response proxy authn headers. */
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
if (!resp_status && authn_info->scheme) {
|
||||
validate_resp = authn_info->scheme->validate_response_func;
|
||||
resp_status = validate_resp(PROXY, sl.code, conn, request, response,
|
||||
pool);
|
||||
}
|
||||
|
||||
if (resp_status) {
|
||||
/* If there was an error in the final step of the authentication,
|
||||
consider the reponse body as invalid and discard it. */
|
||||
@ -419,3 +431,42 @@ void serf__encode_auth_header(const char **header,
|
||||
|
||||
apr_base64_encode(ptr, data, data_len);
|
||||
}
|
||||
|
||||
const char *serf__construct_realm(peer_t peer,
|
||||
serf_connection_t *conn,
|
||||
const char *realm_name,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
if (peer == HOST) {
|
||||
return apr_psprintf(pool, "<%s://%s:%d> %s",
|
||||
conn->host_info.scheme,
|
||||
conn->host_info.hostname,
|
||||
conn->host_info.port,
|
||||
realm_name);
|
||||
} else {
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
|
||||
return apr_psprintf(pool, "<http://%s:%d> %s",
|
||||
ctx->proxy_address->hostname,
|
||||
ctx->proxy_address->port,
|
||||
realm_name);
|
||||
}
|
||||
}
|
||||
|
||||
serf__authn_info_t *serf__get_authn_info_for_server(serf_connection_t *conn)
|
||||
{
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info;
|
||||
|
||||
authn_info = apr_hash_get(ctx->server_authn_info, conn->host_url,
|
||||
APR_HASH_KEY_STRING);
|
||||
|
||||
if (!authn_info) {
|
||||
authn_info = apr_pcalloc(ctx->pool, sizeof(serf__authn_info_t));
|
||||
apr_hash_set(ctx->server_authn_info,
|
||||
apr_pstrdup(ctx->pool, conn->host_url),
|
||||
APR_HASH_KEY_STRING, authn_info);
|
||||
}
|
||||
|
||||
return authn_info;
|
||||
}
|
||||
|
70
auth/auth.h
70
auth/auth.h
@ -16,7 +16,7 @@
|
||||
#ifndef AUTH_H
|
||||
#define AUTH_H
|
||||
|
||||
#include "auth_kerb.h"
|
||||
#include "auth_spnego.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -26,11 +26,19 @@ void serf__encode_auth_header(const char **header, const char *protocol,
|
||||
const char *data, apr_size_t data_len,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* Prefixes the realm_name with a string containing scheme, hostname and port
|
||||
of the connection, for providing it to the application. */
|
||||
const char *serf__construct_realm(peer_t peer,
|
||||
serf_connection_t *conn,
|
||||
const char *realm_name,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Basic authentication **/
|
||||
apr_status_t serf__init_basic(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__init_basic_connection(int code,
|
||||
apr_status_t serf__init_basic_connection(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__handle_basic_auth(int code,
|
||||
@ -52,7 +60,8 @@ apr_status_t serf__setup_request_basic_auth(peer_t peer,
|
||||
apr_status_t serf__init_digest(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__init_digest_connection(int code,
|
||||
apr_status_t serf__init_digest_connection(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__handle_digest_auth(int code,
|
||||
@ -76,34 +85,35 @@ apr_status_t serf__validate_response_digest_auth(peer_t peer,
|
||||
serf_bucket_t *response,
|
||||
apr_pool_t *pool);
|
||||
|
||||
#ifdef SERF_HAVE_KERB
|
||||
#ifdef SERF_HAVE_SPNEGO
|
||||
/** Kerberos authentication **/
|
||||
apr_status_t serf__init_kerb(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__init_kerb_connection(int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__handle_kerb_auth(int code,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
const char *auth_hdr,
|
||||
const char *auth_attr,
|
||||
void *baton,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__setup_request_kerb_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
const char *method,
|
||||
const char *uri,
|
||||
serf_bucket_t *hdrs_bkt);
|
||||
apr_status_t serf__validate_response_kerb_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__init_spnego(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__init_spnego_connection(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__handle_spnego_auth(int code,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
const char *auth_hdr,
|
||||
const char *auth_attr,
|
||||
void *baton,
|
||||
apr_pool_t *pool);
|
||||
apr_status_t serf__setup_request_spnego_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
const char *method,
|
||||
const char *uri,
|
||||
serf_bucket_t *hdrs_bkt);
|
||||
apr_status_t serf__validate_response_spnego_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
apr_pool_t *pool);
|
||||
#endif /* SERF_HAVE_SPNEGO */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <apr_base64.h>
|
||||
#include <apr_strings.h>
|
||||
|
||||
/* Stores the context information related to Basic authentication.
|
||||
This information is stored in the per server cache in the serf context. */
|
||||
typedef struct basic_authn_info_t {
|
||||
const char *header;
|
||||
const char *value;
|
||||
@ -41,12 +43,12 @@ serf__handle_basic_auth(int code,
|
||||
apr_size_t tmp_len;
|
||||
serf_connection_t *conn = request->conn;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info :
|
||||
&ctx->proxy_authn_info;
|
||||
basic_authn_info_t *basic_info = authn_info->baton;
|
||||
serf__authn_info_t *authn_info;
|
||||
basic_authn_info_t *basic_info;
|
||||
apr_status_t status;
|
||||
apr_pool_t *cred_pool;
|
||||
char *username, *password;
|
||||
char *username, *password, *realm_name;
|
||||
const char *eq, *realm;
|
||||
|
||||
/* Can't do Basic authentication if there's no callback to get
|
||||
username & password. */
|
||||
@ -54,20 +56,25 @@ serf__handle_basic_auth(int code,
|
||||
return SERF_ERROR_AUTHN_FAILED;
|
||||
}
|
||||
|
||||
if (!authn_info->realm) {
|
||||
char *realm_name = NULL;
|
||||
const char *eq = strchr(auth_attr, '=');
|
||||
if (code == 401) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
basic_info = authn_info->baton;
|
||||
|
||||
if (eq && strncasecmp(auth_attr, "realm", 5) == 0) {
|
||||
realm_name = apr_pstrdup(pool, eq + 1);
|
||||
if (realm_name[0] == '\"') {
|
||||
apr_size_t realm_len;
|
||||
realm_name = NULL;
|
||||
eq = strchr(auth_attr, '=');
|
||||
|
||||
realm_len = strlen(realm_name);
|
||||
if (realm_name[realm_len - 1] == '\"') {
|
||||
realm_name[realm_len - 1] = '\0';
|
||||
realm_name++;
|
||||
}
|
||||
if (eq && strncasecmp(auth_attr, "realm", 5) == 0) {
|
||||
realm_name = apr_pstrdup(pool, eq + 1);
|
||||
if (realm_name[0] == '\"') {
|
||||
apr_size_t realm_len;
|
||||
|
||||
realm_len = strlen(realm_name);
|
||||
if (realm_name[realm_len - 1] == '\"') {
|
||||
realm_name[realm_len - 1] = '\0';
|
||||
realm_name++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,18 +82,18 @@ serf__handle_basic_auth(int code,
|
||||
return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE;
|
||||
}
|
||||
|
||||
authn_info->realm = apr_psprintf(conn->pool, "<%s://%s:%d> %s",
|
||||
conn->host_info.scheme,
|
||||
conn->host_info.hostname,
|
||||
conn->host_info.port,
|
||||
realm_name);
|
||||
realm = serf__construct_realm(code == 401 ? HOST : PROXY,
|
||||
conn, realm_name,
|
||||
pool);
|
||||
}
|
||||
|
||||
/* Ask the application for credentials */
|
||||
apr_pool_create(&cred_pool, pool);
|
||||
status = (*ctx->cred_cb)(&username, &password, request, baton,
|
||||
code, authn_info->scheme->name,
|
||||
authn_info->realm, cred_pool);
|
||||
status = serf__provide_credentials(ctx,
|
||||
&username, &password,
|
||||
request, baton,
|
||||
code, authn_info->scheme->name,
|
||||
realm, cred_pool);
|
||||
if (status) {
|
||||
apr_pool_destroy(cred_pool);
|
||||
return status;
|
||||
@ -104,28 +111,39 @@ serf__handle_basic_auth(int code,
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Basic authentication we expect all authn info to be the same for all
|
||||
connections in the context (same realm, username, password). Therefore we
|
||||
can keep the header value in the context instead of per connection. */
|
||||
apr_status_t
|
||||
serf__init_basic(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
if (code == 401) {
|
||||
ctx->authn_info.baton = apr_pcalloc(pool, sizeof(basic_authn_info_t));
|
||||
} else {
|
||||
ctx->proxy_authn_info.baton = apr_pcalloc(pool, sizeof(basic_authn_info_t));
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* For Basic authentication we expect all authn info to be the same for all
|
||||
connections in the context to the same server (same realm, username,
|
||||
password). Therefore we can keep the header value in the per-server store
|
||||
context instead of per connection.
|
||||
TODO: we currently don't cache this info per realm, so each time a request
|
||||
'switches realms', we have to ask the application for new credentials. */
|
||||
apr_status_t
|
||||
serf__init_basic_connection(int code,
|
||||
serf__init_basic_connection(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info;
|
||||
|
||||
if (code == 401) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
|
||||
if (!authn_info->baton) {
|
||||
authn_info->baton = apr_pcalloc(pool, sizeof(basic_authn_info_t));
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
@ -139,17 +157,19 @@ serf__setup_request_basic_auth(peer_t peer,
|
||||
serf_bucket_t *hdrs_bkt)
|
||||
{
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
basic_authn_info_t *authn_info;
|
||||
serf__authn_info_t *authn_info;
|
||||
basic_authn_info_t *basic_info;
|
||||
|
||||
if (peer == HOST) {
|
||||
authn_info = ctx->authn_info.baton;
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = ctx->proxy_authn_info.baton;
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
basic_info = authn_info->baton;
|
||||
|
||||
if (authn_info && authn_info->header && authn_info->value) {
|
||||
serf_bucket_headers_setn(hdrs_bkt, authn_info->header,
|
||||
authn_info->value);
|
||||
if (basic_info && basic_info->header && basic_info->value) {
|
||||
serf_bucket_headers_setn(hdrs_bkt, basic_info->header,
|
||||
basic_info->value);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,12 @@
|
||||
|
||||
/** Digest authentication, implements RFC 2617. **/
|
||||
|
||||
/* TODO: add support for the domain attribute. This defines the protection
|
||||
space, so that serf can decide per URI if it should reuse the cached
|
||||
credentials for the server, or not. */
|
||||
|
||||
/* Stores the context information related to Digest authentication.
|
||||
The context is per connection. */
|
||||
This information is stored in the per server cache in the serf context. */
|
||||
typedef struct digest_authn_info_t {
|
||||
/* nonce-count for digest authentication */
|
||||
unsigned int digest_nc;
|
||||
@ -217,7 +221,7 @@ serf__handle_digest_auth(int code,
|
||||
{
|
||||
char *attrs;
|
||||
char *nextkv;
|
||||
const char *realm_name = NULL;
|
||||
const char *realm, *realm_name = NULL;
|
||||
const char *nonce = NULL;
|
||||
const char *algorithm = NULL;
|
||||
const char *qop = NULL;
|
||||
@ -225,10 +229,8 @@ serf__handle_digest_auth(int code,
|
||||
const char *key;
|
||||
serf_connection_t *conn = request->conn;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info = (code == 401) ? &ctx->authn_info :
|
||||
&ctx->proxy_authn_info;
|
||||
digest_authn_info_t *digest_info = (code == 401) ? conn->authn_baton :
|
||||
conn->proxy_authn_baton;
|
||||
serf__authn_info_t *authn_info;
|
||||
digest_authn_info_t *digest_info;
|
||||
apr_status_t status;
|
||||
apr_pool_t *cred_pool;
|
||||
char *username, *password;
|
||||
@ -239,6 +241,13 @@ serf__handle_digest_auth(int code,
|
||||
return SERF_ERROR_AUTHN_FAILED;
|
||||
}
|
||||
|
||||
if (code == 401) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
digest_info = authn_info->baton;
|
||||
|
||||
/* Need a copy cuz we're going to write NUL characters into the string. */
|
||||
attrs = apr_pstrdup(pool, auth_attr);
|
||||
|
||||
@ -286,17 +295,17 @@ serf__handle_digest_auth(int code,
|
||||
return SERF_ERROR_AUTHN_MISSING_ATTRIBUTE;
|
||||
}
|
||||
|
||||
authn_info->realm = apr_psprintf(conn->pool, "<%s://%s:%d> %s",
|
||||
conn->host_info.scheme,
|
||||
conn->host_info.hostname,
|
||||
conn->host_info.port,
|
||||
realm_name);
|
||||
realm = serf__construct_realm(code == 401 ? HOST : PROXY,
|
||||
conn, realm_name,
|
||||
pool);
|
||||
|
||||
/* Ask the application for credentials */
|
||||
apr_pool_create(&cred_pool, pool);
|
||||
status = (*ctx->cred_cb)(&username, &password, request, baton,
|
||||
code, authn_info->scheme->name,
|
||||
authn_info->realm, cred_pool);
|
||||
status = serf__provide_credentials(ctx,
|
||||
&username, &password,
|
||||
request, baton,
|
||||
code, authn_info->scheme->name,
|
||||
realm, cred_pool);
|
||||
if (status) {
|
||||
apr_pool_destroy(cred_pool);
|
||||
return status;
|
||||
@ -305,9 +314,12 @@ serf__handle_digest_auth(int code,
|
||||
digest_info->header = (code == 401) ? "Authorization" :
|
||||
"Proxy-Authorization";
|
||||
|
||||
/* Store the digest authentication parameters in the context relative
|
||||
to this connection, so we can use it to create the Authorization header
|
||||
when setting up requests. */
|
||||
/* Store the digest authentication parameters in the context cached for
|
||||
this server in the serf context, so we can use it to create the
|
||||
Authorization header when setting up requests on the same or different
|
||||
connections (e.g. in case of KeepAlive off on the server).
|
||||
TODO: we currently don't cache this info per realm, so each time a request
|
||||
'switches realms', we have to ask the application for new credentials. */
|
||||
digest_info->pool = conn->pool;
|
||||
digest_info->qop = apr_pstrdup(digest_info->pool, qop);
|
||||
digest_info->nonce = apr_pstrdup(digest_info->pool, nonce);
|
||||
@ -339,16 +351,22 @@ serf__init_digest(int code,
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__init_digest_connection(int code,
|
||||
serf__init_digest_connection(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
/* Digest authentication is done per connection, so keep all progress
|
||||
information per connection. */
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info;
|
||||
|
||||
if (code == 401) {
|
||||
conn->authn_baton = apr_pcalloc(pool, sizeof(digest_authn_info_t));
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
conn->proxy_authn_baton = apr_pcalloc(pool, sizeof(digest_authn_info_t));
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
|
||||
if (!authn_info->baton) {
|
||||
authn_info->baton = apr_pcalloc(pool, sizeof(digest_authn_info_t));
|
||||
}
|
||||
|
||||
/* Make serf send the initial requests one by one */
|
||||
@ -366,23 +384,44 @@ serf__setup_request_digest_auth(peer_t peer,
|
||||
const char *uri,
|
||||
serf_bucket_t *hdrs_bkt)
|
||||
{
|
||||
digest_authn_info_t *digest_info = (peer == HOST) ? conn->authn_baton :
|
||||
conn->proxy_authn_baton;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info;
|
||||
digest_authn_info_t *digest_info;
|
||||
apr_status_t status = APR_SUCCESS;
|
||||
|
||||
if (peer == HOST) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
digest_info = authn_info->baton;
|
||||
|
||||
if (digest_info && digest_info->realm) {
|
||||
const char *value;
|
||||
apr_uri_t parsed_uri;
|
||||
const char *path;
|
||||
|
||||
/* TODO: per request pool? */
|
||||
|
||||
/* Extract path from uri. */
|
||||
status = apr_uri_parse(conn->pool, uri, &parsed_uri);
|
||||
/* for request 'CONNECT serf.googlecode.com:443', the uri also should be
|
||||
serf.googlecode.com:443. apr_uri_parse can't handle this, so special
|
||||
case. */
|
||||
if (strcmp(method, "CONNECT") == 0)
|
||||
path = uri;
|
||||
else {
|
||||
apr_uri_t parsed_uri;
|
||||
|
||||
/* Extract path from uri. */
|
||||
status = apr_uri_parse(conn->pool, uri, &parsed_uri);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
path = parsed_uri.path;
|
||||
}
|
||||
|
||||
/* Build a new Authorization header. */
|
||||
digest_info->header = (peer == HOST) ? "Authorization" :
|
||||
"Proxy-Authorization";
|
||||
value = build_auth_header(digest_info, parsed_uri.path, method,
|
||||
value = build_auth_header(digest_info, path, method,
|
||||
conn->pool);
|
||||
|
||||
serf_bucket_headers_setn(hdrs_bkt, digest_info->header,
|
||||
@ -392,7 +431,7 @@ serf__setup_request_digest_auth(peer_t peer,
|
||||
/* Store the uri of this request on the serf_request_t object, to make
|
||||
it available when validating the Authentication-Info header of the
|
||||
matching response. */
|
||||
request->auth_baton = parsed_uri.path;
|
||||
request->auth_baton = path;
|
||||
}
|
||||
|
||||
return status;
|
||||
@ -413,8 +452,7 @@ serf__validate_response_digest_auth(peer_t peer,
|
||||
const char *qop = NULL;
|
||||
const char *nc_str = NULL;
|
||||
serf_bucket_t *hdrs;
|
||||
digest_authn_info_t *digest_info = (peer == HOST) ? conn->authn_baton :
|
||||
conn->proxy_authn_baton;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
|
||||
hdrs = serf_bucket_response_get_headers(response);
|
||||
|
||||
@ -468,6 +506,15 @@ serf__validate_response_digest_auth(peer_t peer,
|
||||
const char *ha2, *tmp, *resp_hdr_hex;
|
||||
unsigned char resp_hdr[APR_MD5_DIGESTSIZE];
|
||||
const char *req_uri = request->auth_baton;
|
||||
serf__authn_info_t *authn_info;
|
||||
digest_authn_info_t *digest_info;
|
||||
|
||||
if (peer == HOST) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
digest_info = authn_info->baton;
|
||||
|
||||
ha2 = build_digest_ha2(req_uri, "", qop, pool);
|
||||
tmp = apr_psprintf(pool, "%s:%s:%s:%s:%s:%s",
|
||||
|
@ -13,9 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "auth_kerb.h"
|
||||
#include "auth_spnego.h"
|
||||
|
||||
#ifdef SERF_HAVE_KERB
|
||||
#ifdef SERF_HAVE_SPNEGO
|
||||
|
||||
/** These functions implement SPNEGO-based Kerberos and NTLM authentication,
|
||||
* using either GSS-API (RFC 2743) or SSPI on Windows.
|
||||
@ -31,8 +31,6 @@
|
||||
#include <apr_strings.h>
|
||||
|
||||
/** TODO:
|
||||
** - This implements the SPNEGO mechanism, not Kerberos directly. Adapt
|
||||
** filename, functions & comments.
|
||||
** - send session key directly on new connections where we already know
|
||||
** the server requires Kerberos authn.
|
||||
** - Add a way for serf to give detailed error information back to the
|
||||
@ -166,7 +164,7 @@ typedef struct
|
||||
apr_pool_t *pool;
|
||||
|
||||
/* GSSAPI context */
|
||||
serf__kerb_context_t *gss_ctx;
|
||||
serf__spnego_context_t *gss_ctx;
|
||||
|
||||
/* Current state of the authentication cycle. */
|
||||
gss_api_auth_state state;
|
||||
@ -188,8 +186,8 @@ gss_api_get_credentials(char *token, apr_size_t token_len,
|
||||
const char **buf, apr_size_t *buf_len,
|
||||
gss_authn_info_t *gss_info)
|
||||
{
|
||||
serf__kerb_buffer_t input_buf;
|
||||
serf__kerb_buffer_t output_buf;
|
||||
serf__spnego_buffer_t input_buf;
|
||||
serf__spnego_buffer_t output_buf;
|
||||
apr_status_t status = APR_SUCCESS;
|
||||
|
||||
/* If the server sent us a token, pass it to gss_init_sec_token for
|
||||
@ -203,8 +201,8 @@ gss_api_get_credentials(char *token, apr_size_t token_len,
|
||||
}
|
||||
|
||||
/* Establish a security context to the server. */
|
||||
status = serf__kerb_init_sec_context
|
||||
(gss_info->gss_ctx,
|
||||
status = serf__spnego_init_sec_context(
|
||||
gss_info->gss_ctx,
|
||||
KRB_HTTP_SERVICE, hostname,
|
||||
&input_buf,
|
||||
&output_buf,
|
||||
@ -248,13 +246,18 @@ do_auth(peer_t peer,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
serf__authn_info_t *authn_info = (peer == HOST) ? &ctx->authn_info :
|
||||
&ctx->proxy_authn_info;
|
||||
serf__authn_info_t *authn_info;
|
||||
const char *tmp = NULL;
|
||||
char *token = NULL;
|
||||
apr_size_t tmp_len = 0, token_len = 0;
|
||||
apr_status_t status;
|
||||
|
||||
if (peer == HOST) {
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
} else {
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
}
|
||||
|
||||
/* Is this a response from a host/proxy? auth_hdr should always be set. */
|
||||
if (code && auth_hdr) {
|
||||
const char *space = NULL;
|
||||
@ -306,7 +309,7 @@ do_auth(peer_t peer,
|
||||
/* If the server didn't provide us with a token, start with a new initial
|
||||
step in the SPNEGO authentication. */
|
||||
if (!token) {
|
||||
serf__kerb_reset_sec_context(gss_info->gss_ctx);
|
||||
serf__spnego_reset_sec_context(gss_info->gss_ctx);
|
||||
gss_info->state = gss_api_auth_not_started;
|
||||
}
|
||||
|
||||
@ -339,9 +342,9 @@ do_auth(peer_t peer,
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__init_kerb(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
serf__init_spnego(int code,
|
||||
serf_context_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
@ -349,19 +352,20 @@ serf__init_kerb(int code,
|
||||
/* A new connection is created to a server that's known to use
|
||||
Kerberos. */
|
||||
apr_status_t
|
||||
serf__init_kerb_connection(int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool)
|
||||
serf__init_spnego_connection(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
gss_authn_info_t *gss_info;
|
||||
apr_status_t status;
|
||||
|
||||
gss_info = apr_pcalloc(pool, sizeof(*gss_info));
|
||||
gss_info = apr_pcalloc(conn->pool, sizeof(*gss_info));
|
||||
gss_info->pool = conn->pool;
|
||||
gss_info->state = gss_api_auth_not_started;
|
||||
gss_info->pstate = pstate_init;
|
||||
status = serf__kerb_create_sec_context(&gss_info->gss_ctx, pool,
|
||||
gss_info->pool);
|
||||
status = serf__spnego_create_sec_context(&gss_info->gss_ctx, scheme,
|
||||
gss_info->pool, pool);
|
||||
|
||||
if (status) {
|
||||
return status;
|
||||
@ -384,13 +388,13 @@ serf__init_kerb_connection(int code,
|
||||
|
||||
/* A 40x response was received, handle the authentication. */
|
||||
apr_status_t
|
||||
serf__handle_kerb_auth(int code,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
const char *auth_hdr,
|
||||
const char *auth_attr,
|
||||
void *baton,
|
||||
apr_pool_t *pool)
|
||||
serf__handle_spnego_auth(int code,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
const char *auth_hdr,
|
||||
const char *auth_attr,
|
||||
void *baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
serf_connection_t *conn = request->conn;
|
||||
gss_authn_info_t *gss_info = (code == 401) ? conn->authn_baton :
|
||||
@ -406,13 +410,13 @@ serf__handle_kerb_auth(int code,
|
||||
|
||||
/* Setup the authn headers on this request message. */
|
||||
apr_status_t
|
||||
serf__setup_request_kerb_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
const char *method,
|
||||
const char *uri,
|
||||
serf_bucket_t *hdrs_bkt)
|
||||
serf__setup_request_spnego_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
const char *method,
|
||||
const char *uri,
|
||||
serf_bucket_t *hdrs_bkt)
|
||||
{
|
||||
gss_authn_info_t *gss_info = (peer == HOST) ? conn->authn_baton :
|
||||
conn->proxy_authn_baton;
|
||||
@ -488,12 +492,12 @@ serf__setup_request_kerb_auth(peer_t peer,
|
||||
* data which should be validated by the client (mutual authentication).
|
||||
*/
|
||||
apr_status_t
|
||||
serf__validate_response_kerb_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
apr_pool_t *pool)
|
||||
serf__validate_response_spnego_auth(peer_t peer,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
serf_request_t *request,
|
||||
serf_bucket_t *response,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
gss_authn_info_t *gss_info;
|
||||
const char *auth_hdr_name;
|
||||
@ -549,4 +553,4 @@ serf__validate_response_kerb_auth(peer_t peer,
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* SERF_HAVE_GSSAPI */
|
||||
#endif /* SERF_HAVE_SPNEGO */
|
@ -13,32 +13,34 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef AUTH_KERB_H
|
||||
#define AUTH_KERB_H
|
||||
#ifndef AUTH_SPNEGO_H
|
||||
#define AUTH_SPNEGO_H
|
||||
|
||||
#include <apr.h>
|
||||
#include <apr_pools.h>
|
||||
#include "serf.h"
|
||||
#include "serf_private.h"
|
||||
|
||||
#if defined(SERF_HAVE_SSPI)
|
||||
#define SERF_HAVE_KERB
|
||||
#define SERF_HAVE_SPNEGO
|
||||
#define SERF_USE_SSPI
|
||||
#elif defined(SERF_HAVE_GSSAPI)
|
||||
#define SERF_HAVE_KERB
|
||||
#define SERF_HAVE_SPNEGO
|
||||
#define SERF_USE_GSSAPI
|
||||
#endif
|
||||
|
||||
#ifdef SERF_HAVE_KERB
|
||||
#ifdef SERF_HAVE_SPNEGO
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct serf__kerb_context_t serf__kerb_context_t;
|
||||
typedef struct serf__spnego_context_t serf__spnego_context_t;
|
||||
|
||||
typedef struct serf__kerb_buffer_t {
|
||||
typedef struct serf__spnego_buffer_t {
|
||||
apr_size_t length;
|
||||
void *value;
|
||||
} serf__kerb_buffer_t;
|
||||
} serf__spnego_buffer_t;
|
||||
|
||||
/* Create outbound security context.
|
||||
*
|
||||
@ -48,9 +50,10 @@ typedef struct serf__kerb_buffer_t {
|
||||
*
|
||||
*/
|
||||
apr_status_t
|
||||
serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
|
||||
apr_pool_t *scratch_pool,
|
||||
apr_pool_t *result_pool);
|
||||
serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p,
|
||||
const serf__authn_scheme_t *scheme,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Initialize outbound security context.
|
||||
*
|
||||
@ -58,7 +61,7 @@ serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
|
||||
* application and a remote peer.
|
||||
*
|
||||
* CTX is pointer to existing context created using
|
||||
* serf__kerb_create_sec_context() function.
|
||||
* serf__spnego_create_sec_context() function.
|
||||
*
|
||||
* SERVICE is name of Kerberos service name. Usually 'HTTP'. HOSTNAME is
|
||||
* canonical name of destination server. Caller should resolve server's alias
|
||||
@ -78,21 +81,21 @@ serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
|
||||
* for a return token.
|
||||
*
|
||||
* - APR_SUCCESS The security context was successfully initialized. There is no
|
||||
* need for another serf__kerb_init_sec_context call. If the function returns
|
||||
* need for another serf__spnego_init_sec_context call. If the function returns
|
||||
* an output token, that is, if the OUTPUT_BUF is of nonzero length, that
|
||||
* token must be sent to the server.
|
||||
*
|
||||
* Other returns values indicates error.
|
||||
*/
|
||||
apr_status_t
|
||||
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
const char *service,
|
||||
const char *hostname,
|
||||
serf__kerb_buffer_t *input_buf,
|
||||
serf__kerb_buffer_t *output_buf,
|
||||
apr_pool_t *scratch_pool,
|
||||
apr_pool_t *result_pool
|
||||
);
|
||||
serf__spnego_init_sec_context(serf__spnego_context_t *ctx,
|
||||
const char *service,
|
||||
const char *hostname,
|
||||
serf__spnego_buffer_t *input_buf,
|
||||
serf__spnego_buffer_t *output_buf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool
|
||||
);
|
||||
|
||||
/*
|
||||
* Reset a previously created security context so we can start with a new one.
|
||||
@ -101,12 +104,12 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
* where each request requires a new security context.
|
||||
*/
|
||||
apr_status_t
|
||||
serf__kerb_reset_sec_context(serf__kerb_context_t *ctx);
|
||||
serf__spnego_reset_sec_context(serf__spnego_context_t *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SERF_HAVE_KERB */
|
||||
#endif /* SERF_HAVE_SPNEGO */
|
||||
|
||||
#endif /* !AUTH_KERB_H */
|
||||
#endif /* !AUTH_SPNEGO_H */
|
@ -15,7 +15,7 @@
|
||||
|
||||
#include "serf.h"
|
||||
#include "serf_private.h"
|
||||
#include "auth_kerb.h"
|
||||
#include "auth_spnego.h"
|
||||
|
||||
#ifdef SERF_USE_GSSAPI
|
||||
#include <apr_strings.h>
|
||||
@ -33,7 +33,7 @@ static gss_OID_desc spnego_mech_oid = { 6, "\x2b\x06\x01\x05\x05\x02" };
|
||||
#define GSS_SPNEGO_MECHANISM &spnego_mech_oid
|
||||
#endif
|
||||
|
||||
struct serf__kerb_context_t
|
||||
struct serf__spnego_context_t
|
||||
{
|
||||
/* GSSAPI context */
|
||||
gss_ctx_id_t gss_ctx;
|
||||
@ -44,7 +44,7 @@ struct serf__kerb_context_t
|
||||
|
||||
static void
|
||||
log_error(int verbose_flag, const char *filename,
|
||||
serf__kerb_context_t *ctx,
|
||||
serf__spnego_context_t *ctx,
|
||||
OM_uint32 err_maj_stat,
|
||||
OM_uint32 err_min_stat,
|
||||
const char *msg)
|
||||
@ -81,13 +81,19 @@ log_error(int verbose_flag, const char *filename,
|
||||
static apr_status_t
|
||||
cleanup_ctx(void *data)
|
||||
{
|
||||
OM_uint32 min_stat;
|
||||
serf__kerb_context_t *ctx = data;
|
||||
serf__spnego_context_t *ctx = data;
|
||||
|
||||
if (ctx->gss_ctx != GSS_C_NO_CONTEXT) {
|
||||
if (gss_delete_sec_context(&min_stat, &ctx->gss_ctx,
|
||||
GSS_C_NO_BUFFER) == GSS_S_FAILURE)
|
||||
return APR_EGENERAL;
|
||||
OM_uint32 gss_min_stat, gss_maj_stat;
|
||||
|
||||
gss_maj_stat = gss_delete_sec_context(&gss_min_stat, &ctx->gss_ctx,
|
||||
GSS_C_NO_BUFFER);
|
||||
if(GSS_ERROR(gss_maj_stat)) {
|
||||
log_error(AUTH_VERBOSE, __FILE__, ctx,
|
||||
gss_maj_stat, gss_min_stat,
|
||||
"Error cleaning up GSS security context");
|
||||
return SERF_ERROR_AUTHN_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
@ -105,11 +111,12 @@ cleanup_sec_buffer(void *data)
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
|
||||
apr_pool_t *scratch_pool,
|
||||
apr_pool_t *result_pool)
|
||||
serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p,
|
||||
const serf__authn_scheme_t *scheme,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
serf__kerb_context_t *ctx;
|
||||
serf__spnego_context_t *ctx;
|
||||
|
||||
ctx = apr_pcalloc(result_pool, sizeof(*ctx));
|
||||
|
||||
@ -126,7 +133,7 @@ serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__kerb_reset_sec_context(serf__kerb_context_t *ctx)
|
||||
serf__spnego_reset_sec_context(serf__spnego_context_t *ctx)
|
||||
{
|
||||
OM_uint32 dummy_stat;
|
||||
|
||||
@ -139,14 +146,14 @@ serf__kerb_reset_sec_context(serf__kerb_context_t *ctx)
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
const char *service,
|
||||
const char *hostname,
|
||||
serf__kerb_buffer_t *input_buf,
|
||||
serf__kerb_buffer_t *output_buf,
|
||||
apr_pool_t *scratch_pool,
|
||||
apr_pool_t *result_pool
|
||||
)
|
||||
serf__spnego_init_sec_context(serf__spnego_context_t *ctx,
|
||||
const char *service,
|
||||
const char *hostname,
|
||||
serf__spnego_buffer_t *input_buf,
|
||||
serf__spnego_buffer_t *output_buf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool
|
||||
)
|
||||
{
|
||||
gss_buffer_desc gss_input_buf = GSS_C_EMPTY_BUFFER;
|
||||
gss_buffer_desc *gss_output_buf_p;
|
||||
@ -164,7 +171,10 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
GSS_C_NT_HOSTBASED_SERVICE,
|
||||
&host_gss_name);
|
||||
if(GSS_ERROR(gss_maj_stat)) {
|
||||
return APR_EGENERAL;
|
||||
log_error(AUTH_VERBOSE, __FILE__, ctx,
|
||||
gss_maj_stat, gss_min_stat,
|
||||
"Error converting principal name to GSS internal format ");
|
||||
return SERF_ERROR_AUTHN_FAILED;
|
||||
}
|
||||
|
||||
/* If the server sent us a token, pass it to gss_init_sec_token for
|
||||
@ -207,7 +217,7 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
log_error(AUTH_VERBOSE, __FILE__, ctx,
|
||||
gss_maj_stat, gss_min_stat,
|
||||
"Error during Kerberos handshake");
|
||||
return APR_EGENERAL;
|
||||
return SERF_ERROR_AUTHN_FAILED;
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "auth_kerb.h"
|
||||
#include "auth_spnego.h"
|
||||
#include "serf.h"
|
||||
#include "serf_private.h"
|
||||
|
||||
#ifdef SERF_USE_SSPI
|
||||
#include <apr.h>
|
||||
@ -28,11 +29,18 @@
|
||||
#define SEC_E_MUTUAL_AUTH_FAILED _HRESULT_TYPEDEF_(0x80090363L)
|
||||
#endif
|
||||
|
||||
struct serf__kerb_context_t
|
||||
struct serf__spnego_context_t
|
||||
{
|
||||
CredHandle sspi_credentials;
|
||||
CtxtHandle sspi_context;
|
||||
BOOL initalized;
|
||||
apr_pool_t *pool;
|
||||
|
||||
/* Service Principal Name (SPN) used for authentication. */
|
||||
const char *target_name;
|
||||
|
||||
/* One of SERF_AUTHN_* authentication types.*/
|
||||
int authn_type;
|
||||
};
|
||||
|
||||
/* Map SECURITY_STATUS from SSPI to APR error code. Some error codes mapped
|
||||
@ -79,7 +87,7 @@ map_sspi_status(SECURITY_STATUS sspi_status)
|
||||
static apr_status_t
|
||||
cleanup_ctx(void *data)
|
||||
{
|
||||
serf__kerb_context_t *ctx = data;
|
||||
serf__spnego_context_t *ctx = data;
|
||||
|
||||
if (SecIsValidHandle(&ctx->sspi_context)) {
|
||||
DeleteSecurityContext(&ctx->sspi_context);
|
||||
@ -103,25 +111,35 @@ cleanup_sec_buffer(void *data)
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__kerb_create_sec_context(serf__kerb_context_t **ctx_p,
|
||||
apr_pool_t *scratch_pool,
|
||||
apr_pool_t *result_pool)
|
||||
serf__spnego_create_sec_context(serf__spnego_context_t **ctx_p,
|
||||
const serf__authn_scheme_t *scheme,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
SECURITY_STATUS sspi_status;
|
||||
serf__kerb_context_t *ctx;
|
||||
serf__spnego_context_t *ctx;
|
||||
const char *sspi_package;
|
||||
|
||||
ctx = apr_pcalloc(result_pool, sizeof(*ctx));
|
||||
|
||||
SecInvalidateHandle(&ctx->sspi_context);
|
||||
SecInvalidateHandle(&ctx->sspi_credentials);
|
||||
ctx->initalized = FALSE;
|
||||
ctx->pool = result_pool;
|
||||
ctx->target_name = NULL;
|
||||
ctx->authn_type = scheme->type;
|
||||
|
||||
apr_pool_cleanup_register(result_pool, ctx,
|
||||
cleanup_ctx,
|
||||
apr_pool_cleanup_null);
|
||||
|
||||
if (ctx->authn_type == SERF_AUTHN_NEGOTIATE)
|
||||
sspi_package = "Negotiate";
|
||||
else
|
||||
sspi_package = "NTLM";
|
||||
|
||||
sspi_status = AcquireCredentialsHandle(
|
||||
NULL, "Negotiate", SECPKG_CRED_OUTBOUND,
|
||||
NULL, sspi_package, SECPKG_CRED_OUTBOUND,
|
||||
NULL, NULL, NULL, NULL,
|
||||
&ctx->sspi_credentials, NULL);
|
||||
|
||||
@ -161,7 +179,7 @@ get_canonical_hostname(const char **canonname,
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__kerb_reset_sec_context(serf__kerb_context_t *ctx)
|
||||
serf__spnego_reset_sec_context(serf__spnego_context_t *ctx)
|
||||
{
|
||||
if (SecIsValidHandle(&ctx->sspi_context)) {
|
||||
DeleteSecurityContext(&ctx->sspi_context);
|
||||
@ -174,14 +192,14 @@ serf__kerb_reset_sec_context(serf__kerb_context_t *ctx)
|
||||
}
|
||||
|
||||
apr_status_t
|
||||
serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
const char *service,
|
||||
const char *hostname,
|
||||
serf__kerb_buffer_t *input_buf,
|
||||
serf__kerb_buffer_t *output_buf,
|
||||
apr_pool_t *scratch_pool,
|
||||
apr_pool_t *result_pool
|
||||
)
|
||||
serf__spnego_init_sec_context(serf__spnego_context_t *ctx,
|
||||
const char *service,
|
||||
const char *hostname,
|
||||
serf__spnego_buffer_t *input_buf,
|
||||
serf__spnego_buffer_t *output_buf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool
|
||||
)
|
||||
{
|
||||
SECURITY_STATUS status;
|
||||
ULONG actual_attr;
|
||||
@ -189,15 +207,26 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
SecBufferDesc sspi_in_buffer_desc;
|
||||
SecBuffer sspi_out_buffer;
|
||||
SecBufferDesc sspi_out_buffer_desc;
|
||||
char *target_name;
|
||||
apr_status_t apr_status;
|
||||
const char *canonname;
|
||||
|
||||
apr_status = get_canonical_hostname(&canonname, hostname, scratch_pool);
|
||||
if (apr_status) {
|
||||
return apr_status;
|
||||
if (!ctx->initalized && ctx->authn_type == SERF_AUTHN_NEGOTIATE) {
|
||||
apr_status = get_canonical_hostname(&canonname, hostname, scratch_pool);
|
||||
if (apr_status) {
|
||||
return apr_status;
|
||||
}
|
||||
|
||||
ctx->target_name = apr_pstrcat(scratch_pool, service, "/", canonname,
|
||||
NULL);
|
||||
|
||||
serf__log(AUTH_VERBOSE, __FILE__,
|
||||
"Using SPN '%s' for '%s'\n", ctx->target_name, hostname);
|
||||
}
|
||||
else if (ctx->authn_type == SERF_AUTHN_NTLM)
|
||||
{
|
||||
/* Target name is not used for NTLM authentication. */
|
||||
ctx->target_name = NULL;
|
||||
}
|
||||
target_name = apr_pstrcat(scratch_pool, service, "/", canonname, NULL);
|
||||
|
||||
/* Prepare input buffer description. */
|
||||
sspi_in_buffer.BufferType = SECBUFFER_TOKEN;
|
||||
@ -220,7 +249,7 @@ serf__kerb_init_sec_context(serf__kerb_context_t *ctx,
|
||||
status = InitializeSecurityContext(
|
||||
&ctx->sspi_credentials,
|
||||
ctx->initalized ? &ctx->sspi_context : NULL,
|
||||
target_name,
|
||||
ctx->target_name,
|
||||
ISC_REQ_ALLOCATE_MEMORY
|
||||
| ISC_REQ_MUTUAL_AUTH
|
||||
| ISC_REQ_CONFIDENTIALITY,
|
@ -353,16 +353,104 @@ static apr_status_t serf_aggregate_readline(serf_bucket_t *bucket,
|
||||
int acceptable, int *found,
|
||||
const char **data, apr_size_t *len)
|
||||
{
|
||||
/* Follow pattern from serf_aggregate_read. */
|
||||
return APR_ENOTIMPL;
|
||||
aggregate_context_t *ctx = bucket->data;
|
||||
apr_status_t status;
|
||||
|
||||
cleanup_aggregate(ctx, bucket->allocator);
|
||||
|
||||
do {
|
||||
serf_bucket_t *head;
|
||||
|
||||
*len = 0;
|
||||
|
||||
if (!ctx->list) {
|
||||
if (ctx->hold_open) {
|
||||
return ctx->hold_open(ctx->hold_open_baton, bucket);
|
||||
}
|
||||
else {
|
||||
return APR_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
head = ctx->list->bucket;
|
||||
|
||||
status = serf_bucket_readline(head, acceptable, found,
|
||||
data, len);
|
||||
if (SERF_BUCKET_READ_ERROR(status))
|
||||
return status;
|
||||
|
||||
if (status == APR_EOF) {
|
||||
bucket_list_t *next_list;
|
||||
|
||||
/* head bucket is empty, move to to-be-cleaned-up list. */
|
||||
next_list = ctx->list->next;
|
||||
ctx->list->next = ctx->done;
|
||||
ctx->done = ctx->list;
|
||||
ctx->list = next_list;
|
||||
|
||||
/* If we have no more in our list, return EOF. */
|
||||
if (!ctx->list) {
|
||||
if (ctx->hold_open) {
|
||||
return ctx->hold_open(ctx->hold_open_baton, bucket);
|
||||
}
|
||||
else {
|
||||
return APR_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
/* we read something, so bail out and let the appl. read again. */
|
||||
if (*len)
|
||||
status = APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* continue with APR_SUCCESS or APR_EOF and no data read yet. */
|
||||
} while (!*len && status != APR_EAGAIN);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static apr_status_t serf_aggregate_peek(serf_bucket_t *bucket,
|
||||
const char **data,
|
||||
apr_size_t *len)
|
||||
{
|
||||
/* Follow pattern from serf_aggregate_read. */
|
||||
return APR_ENOTIMPL;
|
||||
aggregate_context_t *ctx = bucket->data;
|
||||
serf_bucket_t *head;
|
||||
apr_status_t status;
|
||||
|
||||
cleanup_aggregate(ctx, bucket->allocator);
|
||||
|
||||
/* Peek the first bucket in the list, if any. */
|
||||
if (!ctx->list) {
|
||||
*len = 0;
|
||||
if (ctx->hold_open) {
|
||||
status = ctx->hold_open(ctx->hold_open_baton, bucket);
|
||||
if (status == APR_EAGAIN)
|
||||
status = APR_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
else {
|
||||
return APR_EOF;
|
||||
}
|
||||
}
|
||||
|
||||
head = ctx->list->bucket;
|
||||
|
||||
status = serf_bucket_peek(head, data, len);
|
||||
|
||||
if (status == APR_EOF) {
|
||||
if (ctx->list->next) {
|
||||
status = APR_SUCCESS;
|
||||
} else {
|
||||
if (ctx->hold_open) {
|
||||
status = ctx->hold_open(ctx->hold_open_baton, bucket);
|
||||
if (status == APR_EAGAIN)
|
||||
status = APR_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static serf_bucket_t * serf_aggregate_read_bucket(
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "serf.h"
|
||||
#include "serf_bucket_util.h"
|
||||
|
||||
#include "serf_private.h"
|
||||
|
||||
serf_bucket_t *serf_bucket_create(
|
||||
const serf_bucket_type_t *type,
|
||||
@ -155,6 +155,32 @@ char *serf_bstrdup(serf_bucket_alloc_t *allocator,
|
||||
return newstr;
|
||||
}
|
||||
|
||||
char *serf_bstrcatv(serf_bucket_alloc_t *allocator, struct iovec *vec,
|
||||
int vecs, apr_size_t *bytes_written)
|
||||
{
|
||||
int i;
|
||||
apr_size_t new_len = 0;
|
||||
char *c, *newstr;
|
||||
|
||||
for (i = 0; i < vecs; i++) {
|
||||
new_len += vec[i].iov_len;
|
||||
}
|
||||
|
||||
/* It's up to the caller to free this memory later. */
|
||||
newstr = serf_bucket_mem_alloc(allocator, new_len);
|
||||
|
||||
c = newstr;
|
||||
for (i = 0; i < vecs; i++) {
|
||||
memcpy(c, vec[i].iov_base, vec[i].iov_len);
|
||||
c += vec[i].iov_len;
|
||||
}
|
||||
|
||||
if (bytes_written) {
|
||||
*bytes_written = c - newstr;
|
||||
}
|
||||
|
||||
return newstr;
|
||||
}
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
|
@ -162,6 +162,9 @@ static apr_status_t serf_dechunk_read(serf_bucket_t *bucket,
|
||||
ctx->state = STATE_SIZE;
|
||||
}
|
||||
|
||||
/* Don't return the CR of CRLF to the caller! */
|
||||
*len = 0;
|
||||
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
@ -169,6 +172,7 @@ static apr_status_t serf_dechunk_read(serf_bucket_t *bucket,
|
||||
|
||||
case STATE_DONE:
|
||||
/* Just keep returning EOF */
|
||||
*len = 0;
|
||||
return APR_EOF;
|
||||
|
||||
default:
|
||||
|
@ -325,8 +325,10 @@ static apr_status_t serf_headers_read(serf_bucket_t *bucket,
|
||||
apr_size_t avail;
|
||||
|
||||
select_value(ctx, data, &avail);
|
||||
if (ctx->state == READ_DONE)
|
||||
if (ctx->state == READ_DONE) {
|
||||
*len = avail;
|
||||
return APR_EOF;
|
||||
}
|
||||
|
||||
if (requested >= avail) {
|
||||
/* return everything from this chunk */
|
||||
|
@ -17,14 +17,7 @@
|
||||
|
||||
#include "serf.h"
|
||||
#include "serf_bucket_util.h"
|
||||
|
||||
/* Older versions of APR do not have this macro. */
|
||||
#ifdef APR_SIZE_MAX
|
||||
#define REQUESTED_MAX APR_SIZE_MAX
|
||||
#else
|
||||
#define REQUESTED_MAX (~((apr_size_t)0))
|
||||
#endif
|
||||
|
||||
#include "serf_private.h"
|
||||
|
||||
typedef struct {
|
||||
serf_bucket_t *stream;
|
||||
|
@ -105,14 +105,9 @@ static void serialize_data(serf_bucket_t *bucket)
|
||||
iov[3].iov_base = " HTTP/1.1\r\n";
|
||||
iov[3].iov_len = sizeof(" HTTP/1.1\r\n") - 1;
|
||||
|
||||
/* ### pool allocation! */
|
||||
new_data = apr_pstrcatv(serf_bucket_allocator_get_pool(bucket->allocator),
|
||||
iov, 4, &nbytes);
|
||||
|
||||
/* Create a new bucket for this string. A free function isn't needed
|
||||
* since the string is residing in a pool.
|
||||
*/
|
||||
new_bucket = SERF_BUCKET_SIMPLE_STRING_LEN(new_data, nbytes,
|
||||
/* Create a new bucket for this string with a flat string. */
|
||||
new_data = serf_bstrcatv(bucket->allocator, iov, 4, &nbytes);
|
||||
new_bucket = serf_bucket_simple_own_create(new_data, nbytes,
|
||||
bucket->allocator);
|
||||
|
||||
/* Build up the new bucket structure.
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
#include "serf.h"
|
||||
#include "serf_bucket_util.h"
|
||||
|
||||
#include "serf_private.h"
|
||||
|
||||
typedef struct {
|
||||
serf_bucket_t *stream;
|
||||
|
@ -71,6 +71,23 @@ serf_bucket_t *serf_bucket_simple_copy_create(
|
||||
return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
|
||||
}
|
||||
|
||||
serf_bucket_t *serf_bucket_simple_own_create(
|
||||
const char *data, apr_size_t len,
|
||||
serf_bucket_alloc_t *allocator)
|
||||
{
|
||||
simple_context_t *ctx;
|
||||
|
||||
ctx = serf_bucket_mem_alloc(allocator, sizeof(*ctx));
|
||||
|
||||
ctx->original = ctx->current = data;
|
||||
|
||||
ctx->remaining = len;
|
||||
ctx->freefunc = free_copied_data;
|
||||
ctx->baton = allocator;
|
||||
|
||||
return serf_bucket_create(&serf_bucket_type_simple, allocator, ctx);
|
||||
}
|
||||
|
||||
static apr_status_t serf_simple_read(serf_bucket_t *bucket,
|
||||
apr_size_t requested,
|
||||
const char **data, apr_size_t *len)
|
||||
|
@ -211,14 +211,14 @@ apps_ssl_info_callback(const SSL *s, int where, int ret)
|
||||
const char *str;
|
||||
int w;
|
||||
w = where & ~SSL_ST_MASK;
|
||||
|
||||
|
||||
if (w & SSL_ST_CONNECT)
|
||||
str = "SSL_connect";
|
||||
else if (w & SSL_ST_ACCEPT)
|
||||
str = "SSL_accept";
|
||||
else
|
||||
str = "undefined";
|
||||
|
||||
|
||||
if (where & SSL_CB_LOOP) {
|
||||
serf__log(SSL_VERBOSE, __FILE__, "%s:%s\n", str,
|
||||
SSL_state_string_long(s));
|
||||
@ -255,7 +255,8 @@ static int bio_bucket_read(BIO *bio, char *in, int inlen)
|
||||
|
||||
if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
|
||||
&& BIO_should_read(ctx->bio)) {
|
||||
serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_read waiting: (%d %d %d)\n",
|
||||
serf__log(SSL_VERBOSE, __FILE__,
|
||||
"bio_bucket_read waiting: (%d %d %d)\n",
|
||||
BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
|
||||
BIO_get_retry_flags(ctx->bio));
|
||||
/* Falling back... */
|
||||
@ -296,7 +297,8 @@ static int bio_bucket_write(BIO *bio, const char *in, int inl)
|
||||
|
||||
if (ctx->encrypt.status == SERF_ERROR_WAIT_CONN
|
||||
&& !BIO_should_read(ctx->bio)) {
|
||||
serf__log(SSL_VERBOSE, __FILE__, "bio_bucket_write waiting: (%d %d %d)\n",
|
||||
serf__log(SSL_VERBOSE, __FILE__,
|
||||
"bio_bucket_write waiting: (%d %d %d)\n",
|
||||
BIO_should_retry(ctx->bio), BIO_should_read(ctx->bio),
|
||||
BIO_get_retry_flags(ctx->bio));
|
||||
/* Falling back... */
|
||||
@ -570,6 +572,15 @@ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
|
||||
apr_pool_destroy(subpool);
|
||||
}
|
||||
|
||||
/* Return a specific error if the server certificate is not accepted by
|
||||
OpenSSL and the application has not set callbacks to override this. */
|
||||
if (!cert_valid &&
|
||||
!ctx->server_cert_chain_callback &&
|
||||
!ctx->server_cert_callback)
|
||||
{
|
||||
ctx->pending_err = SERF_ERROR_SSL_CERT_FAILED;
|
||||
}
|
||||
|
||||
return cert_valid;
|
||||
}
|
||||
|
||||
@ -621,9 +632,12 @@ static apr_status_t ssl_decrypt(void *baton, apr_size_t bufsize,
|
||||
switch (ssl_err) {
|
||||
case SSL_ERROR_SYSCALL:
|
||||
*len = 0;
|
||||
/* Return the underlying network error that caused OpenSSL
|
||||
to fail. ### This can be a crypt error! */
|
||||
status = ctx->decrypt.status;
|
||||
break;
|
||||
case SSL_ERROR_WANT_READ:
|
||||
case SSL_ERROR_WANT_WRITE:
|
||||
*len = 0;
|
||||
status = APR_EAGAIN;
|
||||
break;
|
||||
@ -784,16 +798,19 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
|
||||
serf__log(SSL_VERBOSE, __FILE__,
|
||||
"ssl_encrypt: SSL write: %d\n", ssl_len);
|
||||
|
||||
/* We're done. */
|
||||
serf_bucket_mem_free(ctx->allocator, vecs_data);
|
||||
|
||||
/* If we failed to write... */
|
||||
if (ssl_len < 0) {
|
||||
int ssl_err;
|
||||
|
||||
/* Ah, bugger. We need to put that data back. */
|
||||
serf_bucket_aggregate_prepend_iovec(ctx->encrypt.stream,
|
||||
vecs, vecs_read);
|
||||
/* Ah, bugger. We need to put that data back.
|
||||
Note: use the copy here, we do not own the original iovec
|
||||
data buffer so it will be freed on next read. */
|
||||
serf_bucket_t *vecs_copy =
|
||||
serf_bucket_simple_own_create(vecs_data,
|
||||
vecs_data_len,
|
||||
ctx->allocator);
|
||||
serf_bucket_aggregate_prepend(ctx->encrypt.stream,
|
||||
vecs_copy);
|
||||
|
||||
ssl_err = SSL_get_error(ctx->ssl, ssl_len);
|
||||
|
||||
@ -801,6 +818,8 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
|
||||
"ssl_encrypt: SSL write error: %d\n", ssl_err);
|
||||
|
||||
if (ssl_err == SSL_ERROR_SYSCALL) {
|
||||
/* Return the underlying network error that caused OpenSSL
|
||||
to fail. ### This can be a decrypt error! */
|
||||
status = ctx->encrypt.status;
|
||||
if (SERF_BUCKET_READ_ERROR(status)) {
|
||||
return status;
|
||||
@ -812,13 +831,17 @@ static apr_status_t ssl_encrypt(void *baton, apr_size_t bufsize,
|
||||
status = SERF_ERROR_WAIT_CONN;
|
||||
}
|
||||
else {
|
||||
ctx->fatal_err = status = SERF_ERROR_SSL_COMM_FAILED;
|
||||
ctx->fatal_err = status =
|
||||
SERF_ERROR_SSL_COMM_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
serf__log(SSL_VERBOSE, __FILE__,
|
||||
"ssl_encrypt: SSL write error: %d %d\n",
|
||||
status, *len);
|
||||
} else {
|
||||
/* We're done with this data. */
|
||||
serf_bucket_mem_free(ctx->allocator, vecs_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1024,7 +1047,7 @@ static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey)
|
||||
}
|
||||
|
||||
if (status || !cert_path) {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Load the x.509 cert file stored in PKCS12 */
|
||||
@ -1313,7 +1336,7 @@ apr_status_t serf_ssl_load_cert_file(
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
FILE *fp = fopen(file_path, "r");
|
||||
|
||||
|
||||
if (fp) {
|
||||
X509 *ssl_cert = PEM_read_X509(fp, NULL, NULL, NULL);
|
||||
fclose(fp);
|
||||
|
@ -1,985 +0,0 @@
|
||||
dnl -------------------------------------------------------- -*- autoconf -*-
|
||||
dnl Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
dnl contributor license agreements. See the NOTICE file distributed with
|
||||
dnl this work for additional information regarding copyright ownership.
|
||||
dnl The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
dnl (the "License"); you may not use this file except in compliance with
|
||||
dnl the License. You may obtain a copy of the License at
|
||||
dnl
|
||||
dnl http://www.apache.org/licenses/LICENSE-2.0
|
||||
dnl
|
||||
dnl Unless required by applicable law or agreed to in writing, software
|
||||
dnl distributed under the License is distributed on an "AS IS" BASIS,
|
||||
dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
dnl See the License for the specific language governing permissions and
|
||||
dnl limitations under the License.
|
||||
|
||||
dnl
|
||||
dnl apr_common.m4: APR's general-purpose autoconf macros
|
||||
dnl
|
||||
|
||||
dnl
|
||||
dnl APR_CONFIG_NICE(filename)
|
||||
dnl
|
||||
dnl Saves a snapshot of the configure command-line for later reuse
|
||||
dnl
|
||||
AC_DEFUN([APR_CONFIG_NICE], [
|
||||
rm -f $1
|
||||
cat >$1<<EOF
|
||||
#! /bin/sh
|
||||
#
|
||||
# Created by configure
|
||||
|
||||
EOF
|
||||
if test -n "$CC"; then
|
||||
echo "CC=\"$CC\"; export CC" >> $1
|
||||
fi
|
||||
if test -n "$CFLAGS"; then
|
||||
echo "CFLAGS=\"$CFLAGS\"; export CFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$CPPFLAGS"; then
|
||||
echo "CPPFLAGS=\"$CPPFLAGS\"; export CPPFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$LDFLAGS"; then
|
||||
echo "LDFLAGS=\"$LDFLAGS\"; export LDFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$LTFLAGS"; then
|
||||
echo "LTFLAGS=\"$LTFLAGS\"; export LTFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$LIBS"; then
|
||||
echo "LIBS=\"$LIBS\"; export LIBS" >> $1
|
||||
fi
|
||||
if test -n "$INCLUDES"; then
|
||||
echo "INCLUDES=\"$INCLUDES\"; export INCLUDES" >> $1
|
||||
fi
|
||||
if test -n "$NOTEST_CFLAGS"; then
|
||||
echo "NOTEST_CFLAGS=\"$NOTEST_CFLAGS\"; export NOTEST_CFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$NOTEST_CPPFLAGS"; then
|
||||
echo "NOTEST_CPPFLAGS=\"$NOTEST_CPPFLAGS\"; export NOTEST_CPPFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$NOTEST_LDFLAGS"; then
|
||||
echo "NOTEST_LDFLAGS=\"$NOTEST_LDFLAGS\"; export NOTEST_LDFLAGS" >> $1
|
||||
fi
|
||||
if test -n "$NOTEST_LIBS"; then
|
||||
echo "NOTEST_LIBS=\"$NOTEST_LIBS\"; export NOTEST_LIBS" >> $1
|
||||
fi
|
||||
|
||||
# Retrieve command-line arguments.
|
||||
eval "set x $[0] $ac_configure_args"
|
||||
shift
|
||||
|
||||
for arg
|
||||
do
|
||||
APR_EXPAND_VAR(arg, $arg)
|
||||
echo "\"[$]arg\" \\" >> $1
|
||||
done
|
||||
echo '"[$]@"' >> $1
|
||||
chmod +x $1
|
||||
])dnl
|
||||
|
||||
dnl APR_MKDIR_P_CHECK(fallback-mkdir-p)
|
||||
dnl checks whether mkdir -p works
|
||||
AC_DEFUN([APR_MKDIR_P_CHECK], [
|
||||
AC_CACHE_CHECK(for working mkdir -p, ac_cv_mkdir_p,[
|
||||
test -d conftestdir && rm -rf conftestdir
|
||||
mkdir -p conftestdir/somedir >/dev/null 2>&1
|
||||
if test -d conftestdir/somedir; then
|
||||
ac_cv_mkdir_p=yes
|
||||
else
|
||||
ac_cv_mkdir_p=no
|
||||
fi
|
||||
rm -rf conftestdir
|
||||
])
|
||||
if test "$ac_cv_mkdir_p" = "yes"; then
|
||||
mkdir_p="mkdir -p"
|
||||
else
|
||||
mkdir_p="$1"
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl APR_SUBDIR_CONFIG(dir [, sub-package-cmdline-args, args-to-drop])
|
||||
dnl
|
||||
dnl dir: directory to find configure in
|
||||
dnl sub-package-cmdline-args: arguments to add to the invocation (optional)
|
||||
dnl args-to-drop: arguments to drop from the invocation (optional)
|
||||
dnl
|
||||
dnl Note: This macro relies on ac_configure_args being set properly.
|
||||
dnl
|
||||
dnl The args-to-drop argument is shoved into a case statement, so
|
||||
dnl multiple arguments can be separated with a |.
|
||||
dnl
|
||||
dnl Note: Older versions of autoconf do not single-quote args, while 2.54+
|
||||
dnl places quotes around every argument. So, if you want to drop the
|
||||
dnl argument called --enable-layout, you must pass the third argument as:
|
||||
dnl [--enable-layout=*|\'--enable-layout=*]
|
||||
dnl
|
||||
dnl Trying to optimize this is left as an exercise to the reader who wants
|
||||
dnl to put up with more autoconf craziness. I give up.
|
||||
dnl
|
||||
AC_DEFUN([APR_SUBDIR_CONFIG], [
|
||||
# save our work to this point; this allows the sub-package to use it
|
||||
AC_CACHE_SAVE
|
||||
|
||||
echo "configuring package in $1 now"
|
||||
ac_popdir=`pwd`
|
||||
apr_config_subdirs="$1"
|
||||
test -d $1 || $mkdir_p $1
|
||||
ac_abs_srcdir=`(cd $srcdir/$1 && pwd)`
|
||||
cd $1
|
||||
|
||||
changequote(, )dnl
|
||||
# A "../" for each directory in /$config_subdirs.
|
||||
ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'`
|
||||
changequote([, ])dnl
|
||||
|
||||
# Make the cache file pathname absolute for the subdirs
|
||||
# required to correctly handle subdirs that might actually
|
||||
# be symlinks
|
||||
case "$cache_file" in
|
||||
/*) # already absolute
|
||||
ac_sub_cache_file=$cache_file ;;
|
||||
*) # Was relative path.
|
||||
ac_sub_cache_file="$ac_popdir/$cache_file" ;;
|
||||
esac
|
||||
|
||||
ifelse($3, [], [apr_configure_args=$ac_configure_args],[
|
||||
apr_configure_args=
|
||||
apr_sep=
|
||||
for apr_configure_arg in $ac_configure_args
|
||||
do
|
||||
case "$apr_configure_arg" in
|
||||
$3)
|
||||
continue ;;
|
||||
esac
|
||||
apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'"
|
||||
apr_sep=" "
|
||||
done
|
||||
])
|
||||
|
||||
dnl autoconf doesn't add --silent to ac_configure_args; explicitly pass it
|
||||
test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent"
|
||||
|
||||
dnl AC_CONFIG_SUBDIRS silences option warnings, emulate this for 2.62
|
||||
apr_configure_args="--disable-option-checking $apr_configure_args"
|
||||
|
||||
dnl The eval makes quoting arguments work - specifically the second argument
|
||||
dnl where the quoting mechanisms used is "" rather than [].
|
||||
dnl
|
||||
dnl We need to execute another shell because some autoconf/shell combinations
|
||||
dnl will choke after doing repeated APR_SUBDIR_CONFIG()s. (Namely Solaris
|
||||
dnl and autoconf-2.54+)
|
||||
if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir $2
|
||||
then :
|
||||
echo "$1 configured properly"
|
||||
else
|
||||
echo "configure failed for $1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd $ac_popdir
|
||||
|
||||
# grab any updates from the sub-package
|
||||
AC_CACHE_LOAD
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_SAVE_THE_ENVIRONMENT(variable_name)
|
||||
dnl
|
||||
dnl Stores the variable (usually a Makefile macro) for later restoration
|
||||
dnl
|
||||
AC_DEFUN([APR_SAVE_THE_ENVIRONMENT], [
|
||||
apr_ste_save_$1="$$1"
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_RESTORE_THE_ENVIRONMENT(variable_name, prefix_)
|
||||
dnl
|
||||
dnl Uses the previously saved variable content to figure out what configure
|
||||
dnl has added to the variable, moving the new bits to prefix_variable_name
|
||||
dnl and restoring the original variable contents. This makes it possible
|
||||
dnl for a user to override configure when it does something stupid.
|
||||
dnl
|
||||
AC_DEFUN([APR_RESTORE_THE_ENVIRONMENT], [
|
||||
dnl Check whether $apr_ste_save_$1 is empty or
|
||||
dnl only whitespace. The verbatim "X" is token number 1,
|
||||
dnl the following whitespace will be ignored.
|
||||
set X $apr_ste_save_$1
|
||||
if test ${#} -eq 1; then
|
||||
$2$1="$$1"
|
||||
$1=
|
||||
else
|
||||
if test "x$apr_ste_save_$1" = "x$$1"; then
|
||||
$2$1=
|
||||
else
|
||||
$2$1=`echo "$$1" | sed -e "s%${apr_ste_save_$1}%%"`
|
||||
$1="$apr_ste_save_$1"
|
||||
fi
|
||||
fi
|
||||
if test "x$silent" != "xyes"; then
|
||||
echo " restoring $1 to \"$$1\""
|
||||
echo " setting $2$1 to \"$$2$1\""
|
||||
fi
|
||||
AC_SUBST($2$1)
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_SETIFNULL(variable, value)
|
||||
dnl
|
||||
dnl Set variable iff it's currently null
|
||||
dnl
|
||||
AC_DEFUN([APR_SETIFNULL], [
|
||||
if test -z "$$1"; then
|
||||
test "x$silent" != "xyes" && echo " setting $1 to \"$2\""
|
||||
$1="$2"
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_SETVAR(variable, value)
|
||||
dnl
|
||||
dnl Set variable no matter what
|
||||
dnl
|
||||
AC_DEFUN([APR_SETVAR], [
|
||||
test "x$silent" != "xyes" && echo " forcing $1 to \"$2\""
|
||||
$1="$2"
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_ADDTO(variable, value)
|
||||
dnl
|
||||
dnl Add value to variable
|
||||
dnl
|
||||
AC_DEFUN([APR_ADDTO], [
|
||||
if test "x$$1" = "x"; then
|
||||
test "x$silent" != "xyes" && echo " setting $1 to \"$2\""
|
||||
$1="$2"
|
||||
else
|
||||
apr_addto_bugger="$2"
|
||||
for i in $apr_addto_bugger; do
|
||||
apr_addto_duplicate="0"
|
||||
for j in $$1; do
|
||||
if test "x$i" = "x$j"; then
|
||||
apr_addto_duplicate="1"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test $apr_addto_duplicate = "0"; then
|
||||
test "x$silent" != "xyes" && echo " adding \"$i\" to $1"
|
||||
$1="$$1 $i"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_REMOVEFROM(variable, value)
|
||||
dnl
|
||||
dnl Remove a value from a variable
|
||||
dnl
|
||||
AC_DEFUN([APR_REMOVEFROM], [
|
||||
if test "x$$1" = "x$2"; then
|
||||
test "x$silent" != "xyes" && echo " nulling $1"
|
||||
$1=""
|
||||
else
|
||||
apr_new_bugger=""
|
||||
apr_removed=0
|
||||
for i in $$1; do
|
||||
if test "x$i" != "x$2"; then
|
||||
apr_new_bugger="$apr_new_bugger $i"
|
||||
else
|
||||
apr_removed=1
|
||||
fi
|
||||
done
|
||||
if test $apr_removed = "1"; then
|
||||
test "x$silent" != "xyes" && echo " removed \"$2\" from $1"
|
||||
$1=$apr_new_bugger
|
||||
fi
|
||||
fi
|
||||
]) dnl
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_DEFINE_FILES( symbol, header_file [header_file ...] )
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_DEFINE_FILES], [
|
||||
AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[
|
||||
ac_cv_define_$1=no
|
||||
for curhdr in $2
|
||||
do
|
||||
AC_EGREP_CPP(YES_IS_DEFINED, [
|
||||
#include <$curhdr>
|
||||
#ifdef $1
|
||||
YES_IS_DEFINED
|
||||
#endif
|
||||
], ac_cv_define_$1=yes)
|
||||
done
|
||||
])
|
||||
if test "$ac_cv_define_$1" = "yes"; then
|
||||
AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_DEFINE(symbol, header_file)
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_DEFINE], [
|
||||
AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[
|
||||
AC_EGREP_CPP(YES_IS_DEFINED, [
|
||||
#include <$2>
|
||||
#ifdef $1
|
||||
YES_IS_DEFINED
|
||||
#endif
|
||||
], ac_cv_define_$1=yes, ac_cv_define_$1=no)
|
||||
])
|
||||
if test "$ac_cv_define_$1" = "yes"; then
|
||||
AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined in $2])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_APR_DEFINE( symbol )
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_APR_DEFINE], [
|
||||
apr_old_cppflags=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $INCLUDES"
|
||||
AC_EGREP_CPP(YES_IS_DEFINED, [
|
||||
#include <apr.h>
|
||||
#if $1
|
||||
YES_IS_DEFINED
|
||||
#endif
|
||||
], ac_cv_define_$1=yes, ac_cv_define_$1=no)
|
||||
CPPFLAGS=$apr_old_cppflags
|
||||
])
|
||||
|
||||
dnl APR_CHECK_FILE(filename); set ac_cv_file_filename to
|
||||
dnl "yes" if 'filename' is readable, else "no".
|
||||
dnl @deprecated! - use AC_CHECK_FILE instead
|
||||
AC_DEFUN([APR_CHECK_FILE], [
|
||||
dnl Pick a safe variable name
|
||||
define([apr_cvname], ac_cv_file_[]translit([$1], [./+-], [__p_]))
|
||||
AC_CACHE_CHECK([for $1], [apr_cvname],
|
||||
[if test -r $1; then
|
||||
apr_cvname=yes
|
||||
else
|
||||
apr_cvname=no
|
||||
fi])
|
||||
])
|
||||
|
||||
define(APR_IFALLYES,[dnl
|
||||
ac_rc=yes
|
||||
for ac_spec in $1; do
|
||||
ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'`
|
||||
ac_item=`echo "$ac_spec" | sed -e 's/^.*://'`
|
||||
case $ac_type in
|
||||
header )
|
||||
ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
|
||||
ac_var="ac_cv_header_$ac_item"
|
||||
;;
|
||||
file )
|
||||
ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'`
|
||||
ac_var="ac_cv_file_$ac_item"
|
||||
;;
|
||||
func ) ac_var="ac_cv_func_$ac_item" ;;
|
||||
struct ) ac_var="ac_cv_struct_$ac_item" ;;
|
||||
define ) ac_var="ac_cv_define_$ac_item" ;;
|
||||
custom ) ac_var="$ac_item" ;;
|
||||
esac
|
||||
eval "ac_val=\$$ac_var"
|
||||
if test ".$ac_val" != .yes; then
|
||||
ac_rc=no
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test ".$ac_rc" = .yes; then
|
||||
:
|
||||
$2
|
||||
else
|
||||
:
|
||||
$3
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
define(APR_BEGIN_DECISION,[dnl
|
||||
ac_decision_item='$1'
|
||||
ac_decision_msg='FAILED'
|
||||
ac_decision=''
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([APR_DECIDE],[dnl
|
||||
dnl Define the flag (or not) in apr_private.h via autoheader
|
||||
AH_TEMPLATE($1, [Define if $2 will be used])
|
||||
ac_decision='$1'
|
||||
ac_decision_msg='$2'
|
||||
ac_decision_$1=yes
|
||||
ac_decision_$1_msg='$2'
|
||||
])
|
||||
|
||||
|
||||
define(APR_DECISION_OVERRIDE,[dnl
|
||||
ac_decision=''
|
||||
for ac_item in $1; do
|
||||
eval "ac_decision_this=\$ac_decision_${ac_item}"
|
||||
if test ".$ac_decision_this" = .yes; then
|
||||
ac_decision=$ac_item
|
||||
eval "ac_decision_msg=\$ac_decision_${ac_item}_msg"
|
||||
fi
|
||||
done
|
||||
])
|
||||
|
||||
|
||||
define(APR_DECISION_FORCE,[dnl
|
||||
ac_decision="$1"
|
||||
eval "ac_decision_msg=\"\$ac_decision_${ac_decision}_msg\""
|
||||
])
|
||||
|
||||
|
||||
define(APR_END_DECISION,[dnl
|
||||
if test ".$ac_decision" = .; then
|
||||
echo "[$]0:Error: decision on $ac_decision_item failed" 1>&2
|
||||
exit 1
|
||||
else
|
||||
if test ".$ac_decision_msg" = .; then
|
||||
ac_decision_msg="$ac_decision"
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED(${ac_decision_item})
|
||||
AC_MSG_RESULT([decision on $ac_decision_item... $ac_decision_msg])
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_SIZEOF_EXTENDED(INCLUDES, TYPE [, CROSS_SIZE])
|
||||
dnl
|
||||
dnl A variant of AC_CHECK_SIZEOF which allows the checking of
|
||||
dnl sizes of non-builtin types
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_SIZEOF_EXTENDED],
|
||||
[changequote(<<, >>)dnl
|
||||
dnl The name to #define.
|
||||
define(<<AC_TYPE_NAME>>, translit(sizeof_$2, [a-z *], [A-Z_P]))dnl
|
||||
dnl The cache variable name.
|
||||
define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$2, [ *], [_p]))dnl
|
||||
changequote([, ])dnl
|
||||
AC_MSG_CHECKING(size of $2)
|
||||
AC_CACHE_VAL(AC_CV_NAME,
|
||||
[AC_TRY_RUN([#include <stdio.h>
|
||||
$1
|
||||
main()
|
||||
{
|
||||
FILE *f=fopen("conftestval", "w");
|
||||
if (!f) exit(1);
|
||||
fprintf(f, "%d\n", sizeof($2));
|
||||
exit(0);
|
||||
}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$3],,,
|
||||
AC_CV_NAME=$3))])dnl
|
||||
AC_MSG_RESULT($AC_CV_NAME)
|
||||
AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The size of ]$2)
|
||||
undefine([AC_TYPE_NAME])dnl
|
||||
undefine([AC_CV_NAME])dnl
|
||||
])
|
||||
|
||||
|
||||
dnl
|
||||
dnl APR_TRY_COMPILE_NO_WARNING(INCLUDES, FUNCTION-BODY,
|
||||
dnl [ACTIONS-IF-NO-WARNINGS], [ACTIONS-IF-WARNINGS])
|
||||
dnl
|
||||
dnl Tries a compile test with warnings activated so that the result
|
||||
dnl is false if the code doesn't compile cleanly. For compilers
|
||||
dnl where it is not known how to activate a "fail-on-error" mode,
|
||||
dnl it is undefined which of the sets of actions will be run.
|
||||
dnl
|
||||
AC_DEFUN([APR_TRY_COMPILE_NO_WARNING],
|
||||
[apr_save_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS $CFLAGS_WARN"
|
||||
if test "$ac_cv_prog_gcc" = "yes"; then
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
fi
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_SOURCE(
|
||||
[#include "confdefs.h"
|
||||
]
|
||||
[[$1]]
|
||||
[int main(int argc, const char *const *argv) {]
|
||||
[[$2]]
|
||||
[ return 0; }]
|
||||
)],
|
||||
[$3], [$4])
|
||||
CFLAGS=$apr_save_CFLAGS
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_STRERROR_R_RC
|
||||
dnl
|
||||
dnl Decide which style of retcode is used by this system's
|
||||
dnl strerror_r(). It either returns int (0 for success, -1
|
||||
dnl for failure), or it returns a pointer to the error
|
||||
dnl string.
|
||||
dnl
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_STRERROR_R_RC], [
|
||||
AC_MSG_CHECKING(for type of return code from strerror_r)
|
||||
AC_TRY_RUN([
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
main()
|
||||
{
|
||||
char buf[1024];
|
||||
if (strerror_r(ERANGE, buf, sizeof buf) < 1) {
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
}], [
|
||||
ac_cv_strerror_r_rc_int=yes ], [
|
||||
ac_cv_strerror_r_rc_int=no ], [
|
||||
ac_cv_strerror_r_rc_int=no ] )
|
||||
if test "x$ac_cv_strerror_r_rc_int" = xyes; then
|
||||
AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int])
|
||||
msg="int"
|
||||
else
|
||||
msg="pointer"
|
||||
fi
|
||||
AC_MSG_RESULT([$msg])
|
||||
] )
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_DIRENT_INODE
|
||||
dnl
|
||||
dnl Decide if d_fileno or d_ino are available in the dirent
|
||||
dnl structure on this platform. Single UNIX Spec says d_ino,
|
||||
dnl BSD uses d_fileno. Undef to find the real beast.
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_DIRENT_INODE], [
|
||||
AC_CACHE_CHECK([for inode member of struct dirent], apr_cv_dirent_inode, [
|
||||
apr_cv_dirent_inode=no
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
],[
|
||||
#ifdef d_ino
|
||||
#undef d_ino
|
||||
#endif
|
||||
struct dirent de; de.d_fileno;
|
||||
], apr_cv_dirent_inode=d_fileno)
|
||||
if test "$apr_cv_dirent_inode" = "no"; then
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
],[
|
||||
#ifdef d_fileno
|
||||
#undef d_fileno
|
||||
#endif
|
||||
struct dirent de; de.d_ino;
|
||||
], apr_cv_dirent_inode=d_ino)
|
||||
fi
|
||||
])
|
||||
if test "$apr_cv_dirent_inode" != "no"; then
|
||||
AC_DEFINE_UNQUOTED(DIRENT_INODE, $apr_cv_dirent_inode,
|
||||
[Define if struct dirent has an inode member])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_DIRENT_TYPE
|
||||
dnl
|
||||
dnl Decide if d_type is available in the dirent structure
|
||||
dnl on this platform. Not part of the Single UNIX Spec.
|
||||
dnl Note that this is worthless without DT_xxx macros, so
|
||||
dnl look for one while we are at it.
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_DIRENT_TYPE], [
|
||||
AC_CACHE_CHECK([for file type member of struct dirent], apr_cv_dirent_type,[
|
||||
apr_cv_dirent_type=no
|
||||
AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
],[
|
||||
struct dirent de; de.d_type = DT_REG;
|
||||
], apr_cv_dirent_type=d_type)
|
||||
])
|
||||
if test "$apr_cv_dirent_type" != "no"; then
|
||||
AC_DEFINE_UNQUOTED(DIRENT_TYPE, $apr_cv_dirent_type,
|
||||
[Define if struct dirent has a d_type member])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl the following is a newline, a space, a tab, and a backslash (the
|
||||
dnl backslash is used by the shell to skip newlines, but m4 sees it;
|
||||
dnl treat it like whitespace).
|
||||
dnl WARNING: don't reindent these lines, or the space/tab will be lost!
|
||||
define([apr_whitespace],[
|
||||
\])
|
||||
|
||||
dnl
|
||||
dnl APR_COMMA_ARGS(ARG1 ...)
|
||||
dnl convert the whitespace-separated arguments into comman-separated
|
||||
dnl arguments.
|
||||
dnl
|
||||
dnl APR_FOREACH(CODE-BLOCK, ARG1, ARG2, ...)
|
||||
dnl subsitute CODE-BLOCK for each ARG[i]. "eachval" will be set to ARG[i]
|
||||
dnl within each iteration.
|
||||
dnl
|
||||
changequote({,})
|
||||
define({APR_COMMA_ARGS},{patsubst([$}{1],[[}apr_whitespace{]+],[,])})
|
||||
define({APR_FOREACH},
|
||||
{ifelse($}{2,,,
|
||||
[define([eachval],
|
||||
$}{2)$}{1[]APR_FOREACH([$}{1],
|
||||
builtin([shift],
|
||||
builtin([shift], $}{@)))])})
|
||||
changequote([,])
|
||||
|
||||
dnl APR_FLAG_HEADERS(HEADER-FILE ... [, FLAG-TO-SET ] [, "yes" ])
|
||||
dnl we set FLAG-TO-SET to 1 if we find HEADER-FILE, otherwise we set to 0
|
||||
dnl if FLAG-TO-SET is null, we automagically determine it's name
|
||||
dnl by changing all "/" to "_" in the HEADER-FILE and dropping
|
||||
dnl all "." and "-" chars. If the 3rd parameter is "yes" then instead of
|
||||
dnl setting to 1 or 0, we set FLAG-TO-SET to yes or no.
|
||||
dnl
|
||||
AC_DEFUN([APR_FLAG_HEADERS], [
|
||||
AC_CHECK_HEADERS($1)
|
||||
for aprt_i in $1
|
||||
do
|
||||
ac_safe=`echo "$aprt_i" | sed 'y%./+-%__p_%'`
|
||||
aprt_2=`echo "$aprt_i" | sed -e 's%/%_%g' -e 's/\.//g' -e 's/-//g'`
|
||||
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
|
||||
eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,yes,1)"
|
||||
else
|
||||
eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,no,0)"
|
||||
fi
|
||||
done
|
||||
])
|
||||
|
||||
dnl APR_FLAG_FUNCS(FUNC ... [, FLAG-TO-SET] [, "yes" ])
|
||||
dnl if FLAG-TO-SET is null, we automagically determine it's name
|
||||
dnl prepending "have_" to the function name in FUNC, otherwise
|
||||
dnl we use what's provided as FLAG-TO-SET. If the 3rd parameter
|
||||
dnl is "yes" then instead of setting to 1 or 0, we set FLAG-TO-SET
|
||||
dnl to yes or no.
|
||||
dnl
|
||||
AC_DEFUN([APR_FLAG_FUNCS], [
|
||||
AC_CHECK_FUNCS($1)
|
||||
for aprt_j in $1
|
||||
do
|
||||
aprt_3="have_$aprt_j"
|
||||
if eval "test \"`echo '$ac_cv_func_'$aprt_j`\" = yes"; then
|
||||
eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,yes,1)"
|
||||
else
|
||||
eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,no,0)"
|
||||
fi
|
||||
done
|
||||
])
|
||||
|
||||
dnl Iteratively interpolate the contents of the second argument
|
||||
dnl until interpolation offers no new result. Then assign the
|
||||
dnl final result to $1.
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl
|
||||
dnl foo=1
|
||||
dnl bar='${foo}/2'
|
||||
dnl baz='${bar}/3'
|
||||
dnl APR_EXPAND_VAR(fraz, $baz)
|
||||
dnl $fraz is now "1/2/3"
|
||||
dnl
|
||||
AC_DEFUN([APR_EXPAND_VAR], [
|
||||
ap_last=
|
||||
ap_cur="$2"
|
||||
while test "x${ap_cur}" != "x${ap_last}";
|
||||
do
|
||||
ap_last="${ap_cur}"
|
||||
ap_cur=`eval "echo ${ap_cur}"`
|
||||
done
|
||||
$1="${ap_cur}"
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl Removes the value of $3 from the string in $2, strips of any leading
|
||||
dnl slashes, and returns the value in $1.
|
||||
dnl
|
||||
dnl Example:
|
||||
dnl orig_path="${prefix}/bar"
|
||||
dnl APR_PATH_RELATIVE(final_path, $orig_path, $prefix)
|
||||
dnl $final_path now contains "bar"
|
||||
AC_DEFUN([APR_PATH_RELATIVE], [
|
||||
ap_stripped=`echo $2 | sed -e "s#^$3##"`
|
||||
# check if the stripping was successful
|
||||
if test "x$2" != "x${ap_stripped}"; then
|
||||
# it was, so strip of any leading slashes
|
||||
$1="`echo ${ap_stripped} | sed -e 's#^/*##'`"
|
||||
else
|
||||
# it wasn't so return the original
|
||||
$1="$2"
|
||||
fi
|
||||
])
|
||||
|
||||
dnl APR_HELP_STRING(LHS, RHS)
|
||||
dnl Autoconf 2.50 can not handle substr correctly. It does have
|
||||
dnl AC_HELP_STRING, so let's try to call it if we can.
|
||||
dnl Note: this define must be on one line so that it can be properly returned
|
||||
dnl as the help string. When using this macro with a multi-line RHS, ensure
|
||||
dnl that you surround the macro invocation with []s
|
||||
AC_DEFUN([APR_HELP_STRING], [ifelse(regexp(AC_ACVERSION, 2\.1), -1, AC_HELP_STRING([$1],[$2]),[ ][$1] substr([ ],len($1))[$2])])
|
||||
|
||||
dnl
|
||||
dnl APR_LAYOUT(configlayout, layoutname [, extravars])
|
||||
dnl
|
||||
AC_DEFUN([APR_LAYOUT], [
|
||||
if test ! -f $srcdir/config.layout; then
|
||||
echo "** Error: Layout file $srcdir/config.layout not found"
|
||||
echo "** Error: Cannot use undefined layout '$LAYOUT'"
|
||||
exit 1
|
||||
fi
|
||||
# Catch layout names including a slash which will otherwise
|
||||
# confuse the heck out of the sed script.
|
||||
case $2 in
|
||||
*/*)
|
||||
echo "** Error: $2 is not a valid layout name"
|
||||
exit 1 ;;
|
||||
esac
|
||||
pldconf=./config.pld
|
||||
changequote({,})
|
||||
sed -e "1s/[ ]*<[lL]ayout[ ]*$2[ ]*>[ ]*//;1t" \
|
||||
-e "1,/[ ]*<[lL]ayout[ ]*$2[ ]*>[ ]*/d" \
|
||||
-e '/[ ]*<\/Layout>[ ]*/,$d' \
|
||||
-e "s/^[ ]*//g" \
|
||||
-e "s/:[ ]*/=\'/g" \
|
||||
-e "s/[ ]*$/'/g" \
|
||||
$1 > $pldconf
|
||||
layout_name=$2
|
||||
if test ! -s $pldconf; then
|
||||
echo "** Error: unable to find layout $layout_name"
|
||||
exit 1
|
||||
fi
|
||||
. $pldconf
|
||||
rm $pldconf
|
||||
for var in prefix exec_prefix bindir sbindir libexecdir mandir \
|
||||
sysconfdir datadir includedir localstatedir runtimedir \
|
||||
logfiledir libdir installbuilddir libsuffix $3; do
|
||||
eval "val=\"\$$var\""
|
||||
case $val in
|
||||
*+)
|
||||
val=`echo $val | sed -e 's;\+$;;'`
|
||||
eval "$var=\"\$val\""
|
||||
autosuffix=yes
|
||||
;;
|
||||
*)
|
||||
autosuffix=no
|
||||
;;
|
||||
esac
|
||||
val=`echo $val | sed -e 's:\(.\)/*$:\1:'`
|
||||
val=`echo $val | sed -e 's:[\$]\([a-z_]*\):${\1}:g'`
|
||||
if test "$autosuffix" = "yes"; then
|
||||
if echo $val | grep apache >/dev/null; then
|
||||
addtarget=no
|
||||
else
|
||||
addtarget=yes
|
||||
fi
|
||||
if test "$addtarget" = "yes"; then
|
||||
val="$val/apache2"
|
||||
fi
|
||||
fi
|
||||
eval "$var='$val'"
|
||||
done
|
||||
changequote([,])
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_ENABLE_LAYOUT(default layout name [, extra vars])
|
||||
dnl
|
||||
AC_DEFUN([APR_ENABLE_LAYOUT], [
|
||||
AC_ARG_ENABLE(layout,
|
||||
[ --enable-layout=LAYOUT],[
|
||||
LAYOUT=$enableval
|
||||
])
|
||||
|
||||
if test -z "$LAYOUT"; then
|
||||
LAYOUT="$1"
|
||||
fi
|
||||
APR_LAYOUT($srcdir/config.layout, $LAYOUT, $2)
|
||||
|
||||
AC_MSG_CHECKING(for chosen layout)
|
||||
AC_MSG_RESULT($layout_name)
|
||||
])
|
||||
|
||||
|
||||
dnl
|
||||
dnl APR_PARSE_ARGUMENTS
|
||||
dnl a reimplementation of autoconf's argument parser,
|
||||
dnl used here to allow us to co-exist layouts and argument based
|
||||
dnl set ups.
|
||||
AC_DEFUN([APR_PARSE_ARGUMENTS], [
|
||||
ac_prev=
|
||||
# Retrieve the command-line arguments. The eval is needed because
|
||||
# the arguments are quoted to preserve accuracy.
|
||||
eval "set x $ac_configure_args"
|
||||
shift
|
||||
for ac_option
|
||||
do
|
||||
# If the previous option needs an argument, assign it.
|
||||
if test -n "$ac_prev"; then
|
||||
eval "$ac_prev=\$ac_option"
|
||||
ac_prev=
|
||||
continue
|
||||
fi
|
||||
|
||||
ac_optarg=`expr "x$ac_option" : 'x[[^=]]*=\(.*\)'`
|
||||
|
||||
case $ac_option in
|
||||
|
||||
-bindir | --bindir | --bindi | --bind | --bin | --bi)
|
||||
ac_prev=bindir ;;
|
||||
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
|
||||
bindir="$ac_optarg" ;;
|
||||
|
||||
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
|
||||
ac_prev=datadir ;;
|
||||
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
|
||||
| --da=*)
|
||||
datadir="$ac_optarg" ;;
|
||||
|
||||
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
|
||||
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
|
||||
| --exec | --exe | --ex)
|
||||
ac_prev=exec_prefix ;;
|
||||
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
|
||||
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
|
||||
| --exec=* | --exe=* | --ex=*)
|
||||
exec_prefix="$ac_optarg" ;;
|
||||
|
||||
-includedir | --includedir | --includedi | --included | --include \
|
||||
| --includ | --inclu | --incl | --inc)
|
||||
ac_prev=includedir ;;
|
||||
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
|
||||
| --includ=* | --inclu=* | --incl=* | --inc=*)
|
||||
includedir="$ac_optarg" ;;
|
||||
|
||||
-infodir | --infodir | --infodi | --infod | --info | --inf)
|
||||
ac_prev=infodir ;;
|
||||
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
|
||||
infodir="$ac_optarg" ;;
|
||||
|
||||
-libdir | --libdir | --libdi | --libd)
|
||||
ac_prev=libdir ;;
|
||||
-libdir=* | --libdir=* | --libdi=* | --libd=*)
|
||||
libdir="$ac_optarg" ;;
|
||||
|
||||
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
|
||||
| --libexe | --libex | --libe)
|
||||
ac_prev=libexecdir ;;
|
||||
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
|
||||
| --libexe=* | --libex=* | --libe=*)
|
||||
libexecdir="$ac_optarg" ;;
|
||||
|
||||
-localstatedir | --localstatedir | --localstatedi | --localstated \
|
||||
| --localstate | --localstat | --localsta | --localst \
|
||||
| --locals | --local | --loca | --loc | --lo)
|
||||
ac_prev=localstatedir ;;
|
||||
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
|
||||
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
|
||||
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
|
||||
localstatedir="$ac_optarg" ;;
|
||||
|
||||
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
|
||||
ac_prev=mandir ;;
|
||||
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
|
||||
mandir="$ac_optarg" ;;
|
||||
|
||||
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
|
||||
ac_prev=prefix ;;
|
||||
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
|
||||
prefix="$ac_optarg" ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
| --sbi=* | --sb=*)
|
||||
sbindir="$ac_optarg" ;;
|
||||
|
||||
-sharedstatedir | --sharedstatedir | --sharedstatedi \
|
||||
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
|
||||
| --sharedst | --shareds | --shared | --share | --shar \
|
||||
| --sha | --sh)
|
||||
ac_prev=sharedstatedir ;;
|
||||
-sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
|
||||
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
|
||||
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
|
||||
| --sha=* | --sh=*)
|
||||
sharedstatedir="$ac_optarg" ;;
|
||||
|
||||
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
|
||||
| --syscon | --sysco | --sysc | --sys | --sy)
|
||||
ac_prev=sysconfdir ;;
|
||||
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
|
||||
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
|
||||
sysconfdir="$ac_optarg" ;;
|
||||
|
||||
esac
|
||||
done
|
||||
|
||||
# Be sure to have absolute paths.
|
||||
for ac_var in exec_prefix prefix
|
||||
do
|
||||
eval ac_val=$`echo $ac_var`
|
||||
case $ac_val in
|
||||
[[\\/$]]* | ?:[[\\/]]* | NONE | '' ) ;;
|
||||
*) AC_MSG_ERROR([expected an absolute path for --$ac_var: $ac_val]);;
|
||||
esac
|
||||
done
|
||||
|
||||
])dnl
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_DEPEND
|
||||
dnl
|
||||
dnl Determine what program we can use to generate .deps-style dependencies
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_DEPEND], [
|
||||
dnl Try to determine what depend program we can use
|
||||
dnl All GCC-variants should have -MM.
|
||||
dnl If not, then we can check on those, too.
|
||||
if test "$GCC" = "yes"; then
|
||||
MKDEP='$(CC) -MM'
|
||||
else
|
||||
rm -f conftest.c
|
||||
dnl <sys/types.h> should be available everywhere!
|
||||
cat > conftest.c <<EOF
|
||||
#include <sys/types.h>
|
||||
int main() { return 0; }
|
||||
EOF
|
||||
MKDEP="true"
|
||||
for i in "$CC -MM" "$CC -M" "$CPP -MM" "$CPP -M" "cpp -M"; do
|
||||
AC_MSG_CHECKING([if $i can create proper make dependencies])
|
||||
if $i conftest.c 2>/dev/null | grep 'conftest.o: conftest.c' >/dev/null; then
|
||||
MKDEP=$i
|
||||
AC_MSG_RESULT(yes)
|
||||
break;
|
||||
fi
|
||||
AC_MSG_RESULT(no)
|
||||
done
|
||||
rm -f conftest.c
|
||||
fi
|
||||
|
||||
AC_SUBST(MKDEP)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl APR_CHECK_TYPES_COMPATIBLE(TYPE-1, TYPE-2, [ACTION-IF-TRUE])
|
||||
dnl
|
||||
dnl Try to determine whether two types are the same. Only works
|
||||
dnl for gcc and icc.
|
||||
dnl
|
||||
AC_DEFUN([APR_CHECK_TYPES_COMPATIBLE], [
|
||||
define([apr_cvname], apr_cv_typematch_[]translit([$1], [ ], [_])_[]translit([$2], [ ], [_]))
|
||||
AC_CACHE_CHECK([whether $1 and $2 are the same], apr_cvname, [
|
||||
AC_TRY_COMPILE(AC_INCLUDES_DEFAULT, [
|
||||
int foo[0 - !__builtin_types_compatible_p($1, $2)];
|
||||
], [apr_cvname=yes
|
||||
$3], [apr_cvname=no])])
|
||||
])
|
56
build/check.py
Executable file
56
build/check.py
Executable file
@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# check.py : Run all the test cases.
|
||||
#
|
||||
# ====================================================================
|
||||
# Copyright 2013 Justin Erenkrantz and Greg Stein
|
||||
#
|
||||
# Licensed 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.
|
||||
# ====================================================================
|
||||
|
||||
import sys
|
||||
import glob
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# get the test directory from the commandline, if set.
|
||||
if len(sys.argv) > 1:
|
||||
testdir = sys.argv[1]
|
||||
else:
|
||||
testdir = 'test'
|
||||
|
||||
# define test executable paths
|
||||
if sys.platform == 'win32':
|
||||
SERF_RESPONSE_EXE = 'serf_response.exe'
|
||||
TEST_ALL_EXE = 'test_all.exe'
|
||||
else:
|
||||
SERF_RESPONSE_EXE = 'serf_response'
|
||||
TEST_ALL_EXE = 'test_all'
|
||||
SERF_RESPONSE_EXE = os.path.join(testdir, SERF_RESPONSE_EXE)
|
||||
TEST_ALL_EXE = os.path.join(testdir, TEST_ALL_EXE)
|
||||
|
||||
# Find test responses and run them one by one
|
||||
for case in glob.glob(testdir + "/testcases/*.response"):
|
||||
print "== Testing %s ==" % (case)
|
||||
try:
|
||||
subprocess.check_call([SERF_RESPONSE_EXE, case])
|
||||
except subprocess.CalledProcessError:
|
||||
print "ERROR: test case %s failed" % (case)
|
||||
|
||||
print "== Running the unit tests =="
|
||||
try:
|
||||
subprocess.check_call(TEST_ALL_EXE)
|
||||
except subprocess.CalledProcessError:
|
||||
print "ERROR: test(s) failed in test_all"
|
1544
build/config.guess
vendored
1544
build/config.guess
vendored
File diff suppressed because it is too large
Load Diff
1788
build/config.sub
vendored
1788
build/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@ -1,202 +0,0 @@
|
||||
dnl -------------------------------------------------------- -*- autoconf -*-
|
||||
dnl Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
dnl contributor license agreements. See the NOTICE file distributed with
|
||||
dnl this work for additional information regarding copyright ownership.
|
||||
dnl The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
dnl (the "License"); you may not use this file except in compliance with
|
||||
dnl the License. You may obtain a copy of the License at
|
||||
dnl
|
||||
dnl http://www.apache.org/licenses/LICENSE-2.0
|
||||
dnl
|
||||
dnl Unless required by applicable law or agreed to in writing, software
|
||||
dnl distributed under the License is distributed on an "AS IS" BASIS,
|
||||
dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
dnl See the License for the specific language governing permissions and
|
||||
dnl limitations under the License.
|
||||
|
||||
dnl
|
||||
dnl find_apr.m4 : locate the APR include files and libraries
|
||||
dnl
|
||||
dnl This macro file can be used by applications to find and use the APR
|
||||
dnl library. It provides a standardized mechanism for using APR. It supports
|
||||
dnl embedding APR into the application source, or locating an installed
|
||||
dnl copy of APR.
|
||||
dnl
|
||||
dnl APR_FIND_APR(srcdir, builddir, implicit-install-check, acceptable-majors,
|
||||
dnl detailed-check)
|
||||
dnl
|
||||
dnl where srcdir is the location of the bundled APR source directory, or
|
||||
dnl empty if source is not bundled.
|
||||
dnl
|
||||
dnl where builddir is the location where the bundled APR will will be built,
|
||||
dnl or empty if the build will occur in the srcdir.
|
||||
dnl
|
||||
dnl where implicit-install-check set to 1 indicates if there is no
|
||||
dnl --with-apr option specified, we will look for installed copies.
|
||||
dnl
|
||||
dnl where acceptable-majors is a space separated list of acceptable major
|
||||
dnl version numbers. Often only a single major version will be acceptable.
|
||||
dnl If multiple versions are specified, and --with-apr=PREFIX or the
|
||||
dnl implicit installed search are used, then the first (leftmost) version
|
||||
dnl in the list that is found will be used. Currently defaults to [0 1].
|
||||
dnl
|
||||
dnl where detailed-check is an M4 macro which sets the apr_acceptable to
|
||||
dnl either "yes" or "no". The macro will be invoked for each installed
|
||||
dnl copy of APR found, with the apr_config variable set appropriately.
|
||||
dnl Only installed copies of APR which are considered acceptable by
|
||||
dnl this macro will be considered found. If no installed copies are
|
||||
dnl considered acceptable by this macro, apr_found will be set to either
|
||||
dnl either "no" or "reconfig".
|
||||
dnl
|
||||
dnl Sets the following variables on exit:
|
||||
dnl
|
||||
dnl apr_found : "yes", "no", "reconfig"
|
||||
dnl
|
||||
dnl apr_config : If the apr-config tool exists, this refers to it. If
|
||||
dnl apr_found is "reconfig", then the bundled directory
|
||||
dnl should be reconfigured *before* using apr_config.
|
||||
dnl
|
||||
dnl Note: this macro file assumes that apr-config has been installed; it
|
||||
dnl is normally considered a required part of an APR installation.
|
||||
dnl
|
||||
dnl If a bundled source directory is available and needs to be (re)configured,
|
||||
dnl then apr_found is set to "reconfig". The caller should reconfigure the
|
||||
dnl (passed-in) source directory, placing the result in the build directory,
|
||||
dnl as appropriate.
|
||||
dnl
|
||||
dnl If apr_found is "yes" or "reconfig", then the caller should use the
|
||||
dnl value of apr_config to fetch any necessary build/link information.
|
||||
dnl
|
||||
|
||||
AC_DEFUN([APR_FIND_APR], [
|
||||
apr_found="no"
|
||||
|
||||
if test "$target_os" = "os2-emx"; then
|
||||
# Scripts don't pass test -x on OS/2
|
||||
TEST_X="test -f"
|
||||
else
|
||||
TEST_X="test -x"
|
||||
fi
|
||||
|
||||
ifelse([$4], [], [
|
||||
ifdef(AC_WARNING,AC_WARNING([$0: missing argument 4 (acceptable-majors): Defaulting to APR 0.x then APR 1.x]))
|
||||
acceptable_majors="0 1"],
|
||||
[acceptable_majors="$4"])
|
||||
|
||||
apr_temp_acceptable_apr_config=""
|
||||
for apr_temp_major in $acceptable_majors
|
||||
do
|
||||
case $apr_temp_major in
|
||||
0)
|
||||
apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config"
|
||||
;;
|
||||
*)
|
||||
apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
AC_MSG_CHECKING(for APR)
|
||||
AC_ARG_WITH(apr,
|
||||
[ --with-apr=PATH prefix for installed APR or the full path to
|
||||
apr-config],
|
||||
[
|
||||
if test "$withval" = "no" || test "$withval" = "yes"; then
|
||||
AC_MSG_ERROR([--with-apr requires a directory or file to be provided])
|
||||
fi
|
||||
|
||||
for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
|
||||
do
|
||||
for lookdir in "$withval/bin" "$withval"
|
||||
do
|
||||
if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then
|
||||
apr_config="$lookdir/$apr_temp_apr_config_file"
|
||||
ifelse([$5], [], [], [
|
||||
apr_acceptable="yes"
|
||||
$5
|
||||
if test "$apr_acceptable" != "yes"; then
|
||||
AC_MSG_WARN([Found APR in $apr_config, but we think it is considered unacceptable])
|
||||
continue
|
||||
fi])
|
||||
apr_found="yes"
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
|
||||
apr_config="$withval"
|
||||
ifelse([$5], [], [apr_found="yes"], [
|
||||
apr_acceptable="yes"
|
||||
$5
|
||||
if test "$apr_acceptable" = "yes"; then
|
||||
apr_found="yes"
|
||||
fi])
|
||||
fi
|
||||
|
||||
dnl if --with-apr is used, it is a fatal error for its argument
|
||||
dnl to be invalid
|
||||
if test "$apr_found" != "yes"; then
|
||||
AC_MSG_ERROR([the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file.])
|
||||
fi
|
||||
],[
|
||||
dnl If we allow installed copies, check those before using bundled copy.
|
||||
if test -n "$3" && test "$3" = "1"; then
|
||||
for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config
|
||||
do
|
||||
if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then
|
||||
apr_config="$apr_temp_apr_config_file"
|
||||
ifelse([$5], [], [], [
|
||||
apr_acceptable="yes"
|
||||
$5
|
||||
if test "$apr_acceptable" != "yes"; then
|
||||
AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
|
||||
continue
|
||||
fi])
|
||||
apr_found="yes"
|
||||
break
|
||||
else
|
||||
dnl look in some standard places
|
||||
for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
|
||||
if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then
|
||||
apr_config="$lookdir/bin/$apr_temp_apr_config_file"
|
||||
ifelse([$5], [], [], [
|
||||
apr_acceptable="yes"
|
||||
$5
|
||||
if test "$apr_acceptable" != "yes"; then
|
||||
AC_MSG_WARN([skipped APR at $apr_config, version not acceptable])
|
||||
continue
|
||||
fi])
|
||||
apr_found="yes"
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
dnl if we have not found anything yet and have bundled source, use that
|
||||
if test "$apr_found" = "no" && test -d "$1"; then
|
||||
apr_temp_abs_srcdir="`cd \"$1\" && pwd`"
|
||||
apr_found="reconfig"
|
||||
apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apr_version.h\"`"
|
||||
case $apr_bundled_major in
|
||||
"")
|
||||
AC_MSG_ERROR([failed to find major version of bundled APR])
|
||||
;;
|
||||
0)
|
||||
apr_temp_apr_config_file="apr-config"
|
||||
;;
|
||||
*)
|
||||
apr_temp_apr_config_file="apr-$apr_bundled_major-config"
|
||||
;;
|
||||
esac
|
||||
if test -n "$2"; then
|
||||
apr_config="$2/$apr_temp_apr_config_file"
|
||||
else
|
||||
apr_config="$1/$apr_temp_apr_config_file"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_MSG_RESULT($apr_found)
|
||||
])
|
@ -1,211 +0,0 @@
|
||||
dnl -------------------------------------------------------- -*- autoconf -*-
|
||||
dnl Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
dnl contributor license agreements. See the NOTICE file distributed with
|
||||
dnl this work for additional information regarding copyright ownership.
|
||||
dnl The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
dnl (the "License"); you may not use this file except in compliance with
|
||||
dnl the License. You may obtain a copy of the License at
|
||||
dnl
|
||||
dnl http://www.apache.org/licenses/LICENSE-2.0
|
||||
dnl
|
||||
dnl Unless required by applicable law or agreed to in writing, software
|
||||
dnl distributed under the License is distributed on an "AS IS" BASIS,
|
||||
dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
dnl See the License for the specific language governing permissions and
|
||||
dnl limitations under the License.
|
||||
|
||||
dnl
|
||||
dnl find_apu.m4 : locate the APR-util (APU) include files and libraries
|
||||
dnl
|
||||
dnl This macro file can be used by applications to find and use the APU
|
||||
dnl library. It provides a standardized mechanism for using APU. It supports
|
||||
dnl embedding APU into the application source, or locating an installed
|
||||
dnl copy of APU.
|
||||
dnl
|
||||
dnl APR_FIND_APU(srcdir, builddir, implicit-install-check, acceptable-majors,
|
||||
dnl detailed-check)
|
||||
dnl
|
||||
dnl where srcdir is the location of the bundled APU source directory, or
|
||||
dnl empty if source is not bundled.
|
||||
dnl
|
||||
dnl where builddir is the location where the bundled APU will be built,
|
||||
dnl or empty if the build will occur in the srcdir.
|
||||
dnl
|
||||
dnl where implicit-install-check set to 1 indicates if there is no
|
||||
dnl --with-apr-util option specified, we will look for installed copies.
|
||||
dnl
|
||||
dnl where acceptable-majors is a space separated list of acceptable major
|
||||
dnl version numbers. Often only a single major version will be acceptable.
|
||||
dnl If multiple versions are specified, and --with-apr-util=PREFIX or the
|
||||
dnl implicit installed search are used, then the first (leftmost) version
|
||||
dnl in the list that is found will be used. Currently defaults to [0 1].
|
||||
dnl
|
||||
dnl where detailed-check is an M4 macro which sets the apu_acceptable to
|
||||
dnl either "yes" or "no". The macro will be invoked for each installed
|
||||
dnl copy of APU found, with the apu_config variable set appropriately.
|
||||
dnl Only installed copies of APU which are considered acceptable by
|
||||
dnl this macro will be considered found. If no installed copies are
|
||||
dnl considered acceptable by this macro, apu_found will be set to either
|
||||
dnl either "no" or "reconfig".
|
||||
dnl
|
||||
dnl Sets the following variables on exit:
|
||||
dnl
|
||||
dnl apu_found : "yes", "no", "reconfig"
|
||||
dnl
|
||||
dnl apu_config : If the apu-config tool exists, this refers to it. If
|
||||
dnl apu_found is "reconfig", then the bundled directory
|
||||
dnl should be reconfigured *before* using apu_config.
|
||||
dnl
|
||||
dnl Note: this macro file assumes that apr-config has been installed; it
|
||||
dnl is normally considered a required part of an APR installation.
|
||||
dnl
|
||||
dnl Note: At this time, we cannot find *both* a source dir and a build dir.
|
||||
dnl If both are available, the build directory should be passed to
|
||||
dnl the --with-apr-util switch.
|
||||
dnl
|
||||
dnl Note: the installation layout is presumed to follow the standard
|
||||
dnl PREFIX/lib and PREFIX/include pattern. If the APU config file
|
||||
dnl is available (and can be found), then non-standard layouts are
|
||||
dnl possible, since it will be described in the config file.
|
||||
dnl
|
||||
dnl If a bundled source directory is available and needs to be (re)configured,
|
||||
dnl then apu_found is set to "reconfig". The caller should reconfigure the
|
||||
dnl (passed-in) source directory, placing the result in the build directory,
|
||||
dnl as appropriate.
|
||||
dnl
|
||||
dnl If apu_found is "yes" or "reconfig", then the caller should use the
|
||||
dnl value of apu_config to fetch any necessary build/link information.
|
||||
dnl
|
||||
|
||||
AC_DEFUN([APR_FIND_APU], [
|
||||
apu_found="no"
|
||||
|
||||
if test "$target_os" = "os2-emx"; then
|
||||
# Scripts don't pass test -x on OS/2
|
||||
TEST_X="test -f"
|
||||
else
|
||||
TEST_X="test -x"
|
||||
fi
|
||||
|
||||
ifelse([$4], [],
|
||||
[
|
||||
ifdef(AC_WARNING,([$0: missing argument 4 (acceptable-majors): Defaulting to APU 0.x then APU 1.x]))
|
||||
acceptable_majors="0 1"
|
||||
], [acceptable_majors="$4"])
|
||||
|
||||
apu_temp_acceptable_apu_config=""
|
||||
for apu_temp_major in $acceptable_majors
|
||||
do
|
||||
case $apu_temp_major in
|
||||
0)
|
||||
apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-config"
|
||||
;;
|
||||
*)
|
||||
apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-$apu_temp_major-config"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
AC_MSG_CHECKING(for APR-util)
|
||||
AC_ARG_WITH(apr-util,
|
||||
[ --with-apr-util=PATH prefix for installed APU or the full path to
|
||||
apu-config],
|
||||
[
|
||||
if test "$withval" = "no" || test "$withval" = "yes"; then
|
||||
AC_MSG_ERROR([--with-apr-util requires a directory or file to be provided])
|
||||
fi
|
||||
|
||||
for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
|
||||
do
|
||||
for lookdir in "$withval/bin" "$withval"
|
||||
do
|
||||
if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then
|
||||
apu_config="$lookdir/$apu_temp_apu_config_file"
|
||||
ifelse([$5], [], [], [
|
||||
apu_acceptable="yes"
|
||||
$5
|
||||
if test "$apu_acceptable" != "yes"; then
|
||||
AC_MSG_WARN([Found APU in $apu_config, but it is considered unacceptable])
|
||||
continue
|
||||
fi])
|
||||
apu_found="yes"
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
|
||||
apu_config="$withval"
|
||||
ifelse([$5], [], [apu_found="yes"], [
|
||||
apu_acceptable="yes"
|
||||
$5
|
||||
if test "$apu_acceptable" = "yes"; then
|
||||
apu_found="yes"
|
||||
fi])
|
||||
fi
|
||||
|
||||
dnl if --with-apr-util is used, it is a fatal error for its argument
|
||||
dnl to be invalid
|
||||
if test "$apu_found" != "yes"; then
|
||||
AC_MSG_ERROR([the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file.])
|
||||
fi
|
||||
],[
|
||||
if test -n "$3" && test "$3" = "1"; then
|
||||
for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
|
||||
do
|
||||
if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then
|
||||
apu_config="$apu_temp_apu_config_file"
|
||||
ifelse([$5], [], [], [
|
||||
apu_acceptable="yes"
|
||||
$5
|
||||
if test "$apu_acceptable" != "yes"; then
|
||||
AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable])
|
||||
continue
|
||||
fi])
|
||||
apu_found="yes"
|
||||
break
|
||||
else
|
||||
dnl look in some standard places (apparently not in builtin/default)
|
||||
for lookdir in /usr /usr/local /usr/local/apr /opt/apr; do
|
||||
if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then
|
||||
apu_config="$lookdir/bin/$apu_temp_apu_config_file"
|
||||
ifelse([$5], [], [], [
|
||||
apu_acceptable="yes"
|
||||
$5
|
||||
if test "$apu_acceptable" != "yes"; then
|
||||
AC_MSG_WARN([skipped APR-util at $apu_config, version not acceptable])
|
||||
continue
|
||||
fi])
|
||||
apu_found="yes"
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
fi
|
||||
dnl if we have not found anything yet and have bundled source, use that
|
||||
if test "$apu_found" = "no" && test -d "$1"; then
|
||||
apu_temp_abs_srcdir="`cd \"$1\" && pwd`"
|
||||
apu_found="reconfig"
|
||||
apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apu_version.h\"`"
|
||||
case $apu_bundled_major in
|
||||
"")
|
||||
AC_MSG_ERROR([failed to find major version of bundled APU])
|
||||
;;
|
||||
0)
|
||||
apu_temp_apu_config_file="apu-config"
|
||||
;;
|
||||
*)
|
||||
apu_temp_apu_config_file="apu-$apu_bundled_major-config"
|
||||
;;
|
||||
esac
|
||||
if test -n "$2"; then
|
||||
apu_config="$2/$apu_temp_apu_config_file"
|
||||
else
|
||||
apu_config="$1/$apu_temp_apu_config_file"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
AC_MSG_RESULT($apu_found)
|
||||
])
|
@ -58,11 +58,19 @@ def extract_exports(fname):
|
||||
exports.append(name)
|
||||
return exports
|
||||
|
||||
# Blacklist the serf v2 API for now
|
||||
blacklist = ['serf_connection_switch_protocol',
|
||||
'serf_http_protocol_create',
|
||||
'serf_http_request_create',
|
||||
'serf_https_protocol_create']
|
||||
|
||||
if __name__ == '__main__':
|
||||
# run the extraction over each file mentioned
|
||||
import sys
|
||||
print("EXPORTS")
|
||||
|
||||
for fname in sys.argv[1:]:
|
||||
for func in extract_exports(fname):
|
||||
funclist = extract_exports(fname)
|
||||
funclist = set(funclist) - set(blacklist)
|
||||
for func in funclist:
|
||||
print(func)
|
||||
|
@ -1,37 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# extract version numbers from a header file
|
||||
#
|
||||
# USAGE: get-version.sh CMD VERSION_HEADER PREFIX
|
||||
# where CMD is one of: all, major, libtool
|
||||
# where PREFIX is the prefix to {MAJOR|MINOR|PATCH}_VERSION defines
|
||||
#
|
||||
# get-version.sh all returns a dotted version number
|
||||
# get-version.sh major returns just the major version number
|
||||
# get-version.sh libtool returns a version "libtool -version-info" format
|
||||
#
|
||||
|
||||
if test $# != 3; then
|
||||
echo "USAGE: $0 CMD VERSION_HEADER PREFIX"
|
||||
echo " where CMD is one of: all, major, libtool"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
major_sed="/#define.*$3_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p"
|
||||
minor_sed="/#define.*$3_MINOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p"
|
||||
patch_sed="/#define.*$3_PATCH_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p"
|
||||
major="`sed -n $major_sed $2`"
|
||||
minor="`sed -n $minor_sed $2`"
|
||||
patch="`sed -n $patch_sed $2`"
|
||||
|
||||
if test "$1" = "all"; then
|
||||
echo ${major}.${minor}.${patch}
|
||||
elif test "$1" = "major"; then
|
||||
echo ${major}
|
||||
elif test "$1" = "libtool"; then
|
||||
# Yes, ${minor}:${patch}:${minor} is correct due to libtool idiocy.
|
||||
echo ${minor}:${patch}:${minor}
|
||||
else
|
||||
echo "ERROR: unknown version CMD ($1)"
|
||||
exit 1
|
||||
fi
|
112
build/install.sh
112
build/install.sh
@ -1,112 +0,0 @@
|
||||
#!/bin/sh
|
||||
##
|
||||
## install.sh -- install a program, script or datafile
|
||||
##
|
||||
## Based on `install-sh' from the X Consortium's X11R5 distribution
|
||||
## as of 89/12/18 which is freely available.
|
||||
## Cleaned up for Apache's Autoconf-style Interface (APACI)
|
||||
## by Ralf S. Engelschall <rse@apache.org>
|
||||
##
|
||||
#
|
||||
# This script falls under the Apache License.
|
||||
# See http://www.apache.org/docs/LICENSE
|
||||
|
||||
|
||||
#
|
||||
# put in absolute paths if you don't have them in your path;
|
||||
# or use env. vars.
|
||||
#
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
|
||||
#
|
||||
# parse argument line
|
||||
#
|
||||
instcmd="$mvprog"
|
||||
chmodcmd=""
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
ext=""
|
||||
src=""
|
||||
dst=""
|
||||
while [ "x$1" != "x" ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift; continue
|
||||
;;
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift; shift; continue
|
||||
;;
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift; shift; continue
|
||||
;;
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift; shift; continue
|
||||
;;
|
||||
-s) stripcmd="$stripprog"
|
||||
shift; continue
|
||||
;;
|
||||
-S) stripcmd="$stripprog $2"
|
||||
shift; shift; continue
|
||||
;;
|
||||
-e) ext="$2"
|
||||
shift; shift; continue
|
||||
;;
|
||||
*) if [ "x$src" = "x" ]; then
|
||||
src=$1
|
||||
else
|
||||
dst=$1
|
||||
fi
|
||||
shift; continue
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ "x$src" = "x" ]; then
|
||||
echo "install.sh: no input file specified"
|
||||
exit 1
|
||||
fi
|
||||
if [ "x$dst" = "x" ]; then
|
||||
echo "install.sh: no destination specified"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# If destination is a directory, append the input filename; if
|
||||
# your system does not like double slashes in filenames, you may
|
||||
# need to add some logic
|
||||
#
|
||||
if [ -d $dst ]; then
|
||||
dst="$dst/`basename $src`"
|
||||
fi
|
||||
|
||||
# Add a possible extension (such as ".exe") to src and dst
|
||||
src="$src$ext"
|
||||
dst="$dst$ext"
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
dstdir=`dirname $dst`
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
$instcmd $src $dsttmp
|
||||
|
||||
# And set any options; do chmod last to preserve setuid bits
|
||||
if [ "x$chowncmd" != "x" ]; then $chowncmd $dsttmp; fi
|
||||
if [ "x$chgrpcmd" != "x" ]; then $chgrpcmd $dsttmp; fi
|
||||
if [ "x$stripcmd" != "x" ]; then $stripcmd $dsttmp; fi
|
||||
if [ "x$chmodcmd" != "x" ]; then $chmodcmd $dsttmp; fi
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$rmcmd $dst
|
||||
$mvcmd $dsttmp $dst
|
||||
|
||||
exit 0
|
||||
|
141
build/serf.def
141
build/serf.def
@ -1,141 +0,0 @@
|
||||
EXPORTS
|
||||
serf_error_string
|
||||
serf_context_create
|
||||
serf_context_create_ex
|
||||
serf_event_trigger
|
||||
serf_context_run
|
||||
serf_context_prerun
|
||||
serf_context_set_progress_cb
|
||||
serf_connection_create
|
||||
serf_connection_create2
|
||||
serf_listener_create
|
||||
serf_incoming_create
|
||||
serf_connection_reset
|
||||
serf_connection_close
|
||||
serf_connection_set_max_outstanding_requests
|
||||
serf_connection_set_async_responses
|
||||
serf_connection_request_create
|
||||
serf_connection_priority_request_create
|
||||
serf_connection_get_latency
|
||||
serf_request_is_written
|
||||
serf_request_cancel
|
||||
serf_request_get_pool
|
||||
serf_request_get_alloc
|
||||
serf_request_get_conn
|
||||
serf_request_set_handler
|
||||
serf_config_proxy
|
||||
serf_config_authn_types
|
||||
serf_config_credentials_callback
|
||||
serf_context_bucket_socket_create
|
||||
serf_request_bucket_request_create
|
||||
serf_bucket_allocator_create
|
||||
serf_bucket_allocator_get_pool
|
||||
serf_linebuf_init
|
||||
serf_linebuf_fetch
|
||||
serf_debug__record_read
|
||||
serf_debug__entered_loop
|
||||
serf_debug__closed_conn
|
||||
serf_debug__bucket_destroy
|
||||
serf_debug__bucket_alloc_check
|
||||
serf_lib_version
|
||||
serf_bucket_request_create
|
||||
serf_bucket_request_get_headers
|
||||
serf_bucket_request_become
|
||||
serf_bucket_request_set_root
|
||||
serf_bucket_response_create
|
||||
serf_bucket_response_status
|
||||
serf_bucket_response_wait_for_headers
|
||||
serf_bucket_response_get_headers
|
||||
serf_bucket_response_set_head
|
||||
serf_bucket_response_body_create
|
||||
serf_bucket_bwtp_frame_get_channel
|
||||
serf_bucket_bwtp_frame_get_type
|
||||
serf_bucket_bwtp_frame_get_phrase
|
||||
serf_bucket_bwtp_frame_get_headers
|
||||
serf_bucket_bwtp_channel_open
|
||||
serf_bucket_bwtp_channel_close
|
||||
serf_bucket_bwtp_header_create
|
||||
serf_bucket_bwtp_message_create
|
||||
serf_bucket_bwtp_incoming_frame_create
|
||||
serf_bucket_bwtp_incoming_frame_wait_for_headers
|
||||
serf_bucket_aggregate_cleanup
|
||||
serf_bucket_aggregate_create
|
||||
serf_bucket_aggregate_become
|
||||
serf_bucket_aggregate_prepend
|
||||
serf_bucket_aggregate_append
|
||||
serf_bucket_aggregate_hold_open
|
||||
serf_bucket_aggregate_prepend_iovec
|
||||
serf_bucket_aggregate_append_iovec
|
||||
serf_bucket_file_create
|
||||
serf_bucket_socket_create
|
||||
serf_bucket_socket_set_read_progress_cb
|
||||
serf_bucket_simple_create
|
||||
serf_bucket_simple_copy_create
|
||||
serf_bucket_mmap_create
|
||||
serf_bucket_headers_create
|
||||
serf_bucket_headers_set
|
||||
serf_bucket_headers_setc
|
||||
serf_bucket_headers_setn
|
||||
serf_bucket_headers_setx
|
||||
serf_bucket_headers_get
|
||||
serf_bucket_headers_do
|
||||
serf_bucket_chunk_create
|
||||
serf_bucket_dechunk_create
|
||||
serf_bucket_deflate_create
|
||||
serf_bucket_limit_create
|
||||
serf_ssl_client_cert_provider_set
|
||||
serf_ssl_client_cert_password_set
|
||||
serf_ssl_server_cert_callback_set
|
||||
serf_ssl_server_cert_chain_callback_set
|
||||
serf_ssl_use_default_certificates
|
||||
serf_ssl_set_hostname
|
||||
serf_ssl_cert_depth
|
||||
serf_ssl_cert_issuer
|
||||
serf_ssl_cert_subject
|
||||
serf_ssl_cert_certificate
|
||||
serf_ssl_cert_export
|
||||
serf_ssl_load_cert_file
|
||||
serf_ssl_trust_cert
|
||||
serf_ssl_use_compression
|
||||
serf_bucket_ssl_encrypt_create
|
||||
serf_bucket_ssl_encrypt_context_get
|
||||
serf_bucket_ssl_decrypt_create
|
||||
serf_bucket_ssl_decrypt_context_get
|
||||
serf_bucket_barrier_create
|
||||
serf_bucket_iovec_create
|
||||
serf_bucket_type_request
|
||||
serf_bucket_type_response
|
||||
serf_bucket_type_response_body
|
||||
serf_bucket_type_bwtp_frame
|
||||
serf_bucket_type_bwtp_incoming_frame
|
||||
serf_bucket_type_aggregate
|
||||
serf_bucket_type_file
|
||||
serf_bucket_type_socket
|
||||
serf_bucket_type_simple
|
||||
serf_bucket_type_mmap
|
||||
serf_bucket_type_headers
|
||||
serf_bucket_type_chunk
|
||||
serf_bucket_type_dechunk
|
||||
serf_bucket_type_deflate
|
||||
serf_bucket_type_limit
|
||||
serf_bucket_type_ssl_encrypt
|
||||
serf_bucket_type_ssl_decrypt
|
||||
serf_bucket_type_barrier
|
||||
serf_bucket_type_iovec
|
||||
serf_bucket_create
|
||||
serf_default_read_iovec
|
||||
serf_default_read_for_sendfile
|
||||
serf_default_read_bucket
|
||||
serf_default_destroy
|
||||
serf_default_destroy_and_data
|
||||
serf_bucket_mem_alloc
|
||||
serf_bucket_mem_calloc
|
||||
serf_bucket_mem_free
|
||||
serf_bstrmemdup
|
||||
serf_bmemdup
|
||||
serf_bstrdup
|
||||
serf_util_readline
|
||||
serf_databuf_init
|
||||
serf_databuf_read
|
||||
serf_databuf_readline
|
||||
serf_databuf_peek
|
13
build/serf.pc.in
Normal file
13
build/serf.pc.in
Normal file
@ -0,0 +1,13 @@
|
||||
SERF_MAJOR_VERSION=@MAJOR@
|
||||
prefix=@PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include/@INCLUDE_SUBDIR@
|
||||
|
||||
Name: serf
|
||||
Description: HTTP client library
|
||||
Version: @VERSION@
|
||||
Requires.private: libssl libcrypto
|
||||
Libs: -L${libdir} -lserf-${SERF_MAJOR_VERSION}
|
||||
Libs.private: @LIBS@
|
||||
Cflags: -I${includedir}
|
119
buildconf
119
buildconf
@ -1,119 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright 2005 Justin Erenkrantz and Greg Stein
|
||||
# Copyright 2005 The Apache Software Foundation or its licensors, as
|
||||
# applicable.
|
||||
#
|
||||
# Licensed 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.
|
||||
#
|
||||
#
|
||||
# buildconf: Build the support scripts needed to compile from a
|
||||
# checked-out version of the source code.
|
||||
|
||||
# set a couple of defaults for where we should be looking for our support libs.
|
||||
# can be overridden with --with-apr=[dir] and --with-apr-util=[dir]
|
||||
|
||||
apr_src_dir="apr ../apr"
|
||||
apu_src_dir="apr-util ../apr-util"
|
||||
|
||||
while test $# -gt 0
|
||||
do
|
||||
# Normalize
|
||||
case "$1" in
|
||||
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
|
||||
*) optarg= ;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
--with-apr=*)
|
||||
apr_src_dir=$optarg
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
--with-apr-util=*)
|
||||
apu_src_dir=$optarg
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done
|
||||
|
||||
#
|
||||
# Check to be sure that we have the srclib dependencies checked-out
|
||||
#
|
||||
|
||||
should_exit=0
|
||||
apr_found=0
|
||||
apu_found=0
|
||||
|
||||
for dir in $apr_src_dir
|
||||
do
|
||||
if [ -d "${dir}" -a -f "${dir}/build/apr_common.m4" ]; then
|
||||
echo "found apr source: ${dir}"
|
||||
apr_src_dir=$dir
|
||||
apr_found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $apr_found -lt 1 ]; then
|
||||
echo ""
|
||||
echo "You don't have a copy of the apr source in srclib/apr. "
|
||||
echo "Please get the source using the following instructions,"
|
||||
echo "or specify the location of the source with "
|
||||
echo "--with-apr=[path to apr] :"
|
||||
echo ""
|
||||
echo " svn co http://svn.apache.org/repos/asf/apr/apr/trunk srclib/apr"
|
||||
echo ""
|
||||
should_exit=1
|
||||
fi
|
||||
|
||||
for dir in $apu_src_dir
|
||||
do
|
||||
if [ -d "${dir}" -a -f "${dir}/Makefile.in" ]; then
|
||||
echo "found apr-util source: ${dir}"
|
||||
apu_src_dir=$dir
|
||||
apu_found=1
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ $apu_found -lt 1 ]; then
|
||||
echo ""
|
||||
echo "APR-util not found. Assuming you are using APR 2.x."
|
||||
echo ""
|
||||
apu_src_dir=
|
||||
fi
|
||||
|
||||
if [ $should_exit -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo copying build files
|
||||
cp $apr_src_dir/build/config.guess $apr_src_dir/build/config.sub \
|
||||
$apr_src_dir/build/install.sh $apr_src_dir/build/apr_common.m4 \
|
||||
$apr_src_dir/build/find_apr.m4 $apr_src_dir/build/get-version.sh build
|
||||
|
||||
if [ -n "$apu_src_dir" -a -d "$apu_src_dir" ] ; then
|
||||
cp $apu_src_dir/build/find_apu.m4 build
|
||||
fi
|
||||
|
||||
echo generating configure
|
||||
${AUTOCONF:-autoconf}
|
||||
|
||||
# Remove autoconf 2.5x's cache directory
|
||||
rm -rf autom4te*.cache
|
||||
|
||||
echo generating serf.def
|
||||
./build/gen_def.py serf.h serf_bucket_*.h > build/serf.def
|
@ -1,26 +0,0 @@
|
||||
##
|
||||
## config.layout -- Pre-defined Installation Path Layouts
|
||||
##
|
||||
## Hints:
|
||||
## - layouts can be loaded with configure's --enable-layout=ID option
|
||||
## - when no --enable-layout option is given, the default layout is `serf'
|
||||
## - a trailing plus character (`+') on paths is replaced with a
|
||||
## `/<target>' suffix where <target> is currently hardcoded to 'serf'.
|
||||
## (This may become a configurable parameter at some point.)
|
||||
##
|
||||
|
||||
<Layout Serf>
|
||||
prefix: /usr/local/serf
|
||||
exec_prefix: ${prefix}
|
||||
bindir: ${exec_prefix}/bin
|
||||
sbindir: ${exec_prefix}/bin
|
||||
libdir: ${exec_prefix}/lib
|
||||
libexecdir: ${exec_prefix}/modules
|
||||
mandir: ${prefix}/man
|
||||
sysconfdir: ${prefix}/conf
|
||||
datadir: ${prefix}
|
||||
installbuilddir: ${datadir}/build-${SERF_MAJOR_VERSION}
|
||||
includedir: ${prefix}/include/serf-${SERF_MAJOR_VERSION}
|
||||
localstatedir: ${prefix}
|
||||
libsuffix: -${SERF_MAJOR_VERSION}
|
||||
</Layout>
|
277
configure.in
277
configure.in
@ -1,277 +0,0 @@
|
||||
dnl Autoconf file for Serf
|
||||
|
||||
AC_PREREQ(2.50)
|
||||
AC_INIT(context.c)
|
||||
|
||||
AC_CONFIG_AUX_DIR(build)
|
||||
|
||||
sinclude(build/apr_common.m4)
|
||||
sinclude(build/find_apr.m4)
|
||||
|
||||
AC_PREFIX_DEFAULT(/usr/local/serf)
|
||||
|
||||
dnl Get the layout here, so we can pass the required variables to apr
|
||||
APR_ENABLE_LAYOUT(Serf, [])
|
||||
|
||||
dnl reparse the configure arguments.
|
||||
APR_PARSE_ARGUMENTS
|
||||
|
||||
APR_SAVE_THE_ENVIRONMENT(CPPFLAGS)
|
||||
APR_SAVE_THE_ENVIRONMENT(CFLAGS)
|
||||
APR_SAVE_THE_ENVIRONMENT(CXXFLAGS)
|
||||
APR_SAVE_THE_ENVIRONMENT(LDFLAGS)
|
||||
APR_SAVE_THE_ENVIRONMENT(LIBS)
|
||||
APR_SAVE_THE_ENVIRONMENT(INCLUDES)
|
||||
|
||||
APR_CONFIG_NICE(config.nice)
|
||||
|
||||
nl='
|
||||
'
|
||||
dnl Check that mkdir -p works
|
||||
APR_MKDIR_P_CHECK($top_srcdir/build/mkdir.sh)
|
||||
AC_SUBST(mkdir_p)
|
||||
|
||||
dnl ## Run configure for packages Apache uses
|
||||
|
||||
dnl shared library support for these packages doesn't currently
|
||||
dnl work on some platforms
|
||||
|
||||
AC_CANONICAL_SYSTEM
|
||||
|
||||
orig_prefix="$prefix"
|
||||
|
||||
echo $ac_n "${nl}Configuring Apache Portable Runtime library...${nl}"
|
||||
|
||||
APR_FIND_APR("$srcdir/apr", "./apr", 1, 0 1 2)
|
||||
|
||||
if test "$apr_found" = "no"; then
|
||||
AC_MSG_ERROR([APR not found. Please read the documentation.])
|
||||
fi
|
||||
|
||||
if test "$apr_found" = "reconfig"; then
|
||||
APR_SUBDIR_CONFIG(apr,
|
||||
[--prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir --datadir=$datadir --with-installbuilddir=$installbuilddir],
|
||||
[--enable-layout=*|\'--enable-layout=*])
|
||||
dnl We must be the first to build and the last to be cleaned
|
||||
SERF_BUILD_SRCLIB_DIRS="apr $SERF_BUILD_SRCLIB_DIRS"
|
||||
SERF_CLEAN_SRCLIB_DIRS="$SERF_CLEAN_SRCLIB_DIRS apr"
|
||||
fi
|
||||
|
||||
APR_SETIFNULL(CC, `$apr_config --cc`)
|
||||
APR_SETIFNULL(CPP, `$apr_config --cpp`)
|
||||
APR_SETIFNULL(APR_LIBTOOL, `$apr_config --apr-libtool`)
|
||||
APR_ADDTO(CFLAGS, `$apr_config --cflags`)
|
||||
APR_ADDTO(CPPFLAGS, `$apr_config --cppflags`)
|
||||
APR_ADDTO(LDFLAGS, `$apr_config --ldflags`)
|
||||
SHLIBPATH_VAR=`$apr_config --shlib-path-var`
|
||||
APR_BINDIR=`$apr_config --bindir`
|
||||
APR_INCLUDES=`$apr_config --includes`
|
||||
APR_VERSION=`$apr_config --version`
|
||||
APR_CONFIG="$apr_config"
|
||||
|
||||
APR_SETIFNULL(LTFLAGS, "--silent")
|
||||
AC_SUBST(LTFLAGS)
|
||||
|
||||
AC_SUBST(APR_LIBTOOL)
|
||||
AC_SUBST(APR_BINDIR)
|
||||
AC_SUBST(APR_INCLUDES)
|
||||
AC_SUBST(APR_VERSION)
|
||||
AC_SUBST(APR_CONFIG)
|
||||
|
||||
APR_VERSION_MAJOR="`echo \"$APR_VERSION\" | sed 's,\..*,,'`"
|
||||
APR_VERSION_NUM="`echo \"$APR_VERSION\" | \
|
||||
sed -e 's/[[^0-9\.]].*$//' \
|
||||
-e 's/\.\([[0-9]]\)$/.0\1/' \
|
||||
-e 's/\.\([[0-9]][[0-9]]\)$/.0\1/' \
|
||||
-e 's/\.\([[0-9]]\)\./0\1/; s/\.//g;'`"
|
||||
|
||||
if test "$APR_VERSION_NUM" -ge "200000"; then
|
||||
|
||||
APU_BINDIR=""
|
||||
APU_INCLUDES=""
|
||||
APU_VERSION=""
|
||||
APU_CONFIG=""
|
||||
|
||||
else
|
||||
sinclude(build/find_apu.m4)
|
||||
|
||||
echo $ac_n "${nl}Configuring Apache Portable Runtime Utility library...${nl}"
|
||||
|
||||
ifdef([APR_FIND_APU], [
|
||||
APR_FIND_APU("$srcdir/apr-util", "./apr-util", 1, $APR_VERSION_MAJOR)
|
||||
], [AC_MSG_ERROR([APR-util required, but find_apu.m4 not present!])])
|
||||
|
||||
if test "$apu_found" = "no"; then
|
||||
AC_MSG_ERROR([APR-util not found. Please read the documentation.])
|
||||
fi
|
||||
|
||||
# Catch some misconfigurations:
|
||||
case ${apr_found}.${apu_found} in
|
||||
reconfig.yes)
|
||||
AC_MSG_ERROR([Cannot use an external APR-util with the bundled APR])
|
||||
;;
|
||||
yes.reconfig)
|
||||
AC_MSG_ERROR([Cannot use an external APR with the bundled APR-util])
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "$apu_found" = "reconfig"; then
|
||||
APR_SUBDIR_CONFIG(apr-util,
|
||||
[--with-apr=../apr --prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir],
|
||||
[--enable-layout=*|\'--enable-layout=*])
|
||||
dnl We must be the last to build and the first to be cleaned
|
||||
SERF_BUILD_SRCLIB_DIRS="$SERF_BUILD_SRCLIB_DIRS apr-util"
|
||||
SERF_CLEAN_SRCLIB_DIRS="apr-util $SERF_CLEAN_SRCLIB_DIRS"
|
||||
fi
|
||||
|
||||
APR_ADDTO(LDFLAGS, `$apu_config --ldflags`)
|
||||
APU_BINDIR=`$apu_config --bindir`
|
||||
APU_INCLUDES=`$apu_config --includes`
|
||||
APU_VERSION=`$apu_config --version`
|
||||
APU_CONFIG="$APU_BINDIR/apu-`echo ${APU_VERSION} | sed 's,\..*,,'`-config"
|
||||
fi
|
||||
|
||||
AC_SUBST(APU_BINDIR)
|
||||
AC_SUBST(APU_INCLUDES)
|
||||
AC_SUBST(APU_VERSION)
|
||||
AC_SUBST(APU_CONFIG)
|
||||
|
||||
dnl In case we picked up CC and CPP from APR, get that info into the
|
||||
dnl config cache so that PCRE uses it. Otherwise, CC and CPP used for
|
||||
dnl PCRE and for our config tests will be whatever PCRE determines.
|
||||
AC_PROG_CC
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
|
||||
if test "x${cache_file}" = "x/dev/null"; then
|
||||
# Likewise, ensure that CC and CPP are passed through to the pcre
|
||||
# configure script iff caching is disabled (the autoconf 2.5x default).
|
||||
export CC; export CPP
|
||||
fi
|
||||
|
||||
echo $ac_n "Configuring Serf...${nl}"
|
||||
|
||||
dnl Absolute source/build directory
|
||||
abs_srcdir=`(cd $srcdir && pwd)`
|
||||
abs_builddir=`pwd`
|
||||
|
||||
dnl get our version information
|
||||
get_version="$abs_srcdir/build/get-version.sh"
|
||||
version_hdr="$abs_srcdir/serf.h"
|
||||
SERF_MAJOR_VERSION="`$get_version major $version_hdr SERF`"
|
||||
SERF_DOTTED_VERSION="`$get_version all $version_hdr SERF`"
|
||||
|
||||
AC_SUBST(SERF_MAJOR_VERSION)
|
||||
AC_SUBST(SERF_DOTTED_VERSION)
|
||||
|
||||
AC_SUBST(SERF_BUILD_SRCLIB_DIRS)
|
||||
AC_SUBST(SERF_CLEAN_SRCLIB_DIRS)
|
||||
|
||||
AC_ARG_WITH(openssl,
|
||||
APR_HELP_STRING([--with-openssl=PATH],[Path to OpenSSL (eg. /usr/local/ssl)]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
AC_MSG_ERROR([--with-openssl requires a path])
|
||||
else
|
||||
openssl_prefix=$withval
|
||||
|
||||
if test "x$openssl_prefix" != "x" -a ! -d "$openssl_prefix"; then
|
||||
AC_MSG_ERROR('--with-openssl requires a path to a directory')
|
||||
fi
|
||||
|
||||
APR_ADDTO(CPPFLAGS, "-I${openssl_prefix}/include")
|
||||
if test -e "${openssl_prefix}/Makefile"; then
|
||||
APR_ADDTO(LDFLAGS, "-L${openssl_prefix}")
|
||||
APR_ADDTO(LDFLAGS, "-R${openssl_prefix}")
|
||||
else
|
||||
APR_ADDTO(LDFLAGS, "-L${openssl_prefix}/lib")
|
||||
APR_ADDTO(LDFLAGS, "-R${openssl_prefix}/lib")
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Look for OpenSSL
|
||||
AC_CHECK_HEADER([openssl/opensslv.h], [],
|
||||
[AC_MSG_ERROR([We require OpenSSL; try --with-openssl])])
|
||||
|
||||
dnl Look for Kerberos 5 for GSSAPI
|
||||
AC_ARG_WITH(gssapi,
|
||||
APR_HELP_STRING([--with-gssapi=PATH],[build with GSSAPI support; needs krb5-config in PATH/bin (eg. /usr/lib/mit)]),
|
||||
[
|
||||
if test "$withval" = "yes"; then
|
||||
AC_MSG_ERROR([--with-gssapi requires a path])
|
||||
else
|
||||
gssapi_prefix=$withval/
|
||||
|
||||
if test "x$gssapi_prefix" != "x" -a ! -d "$gssapi_prefix"; then
|
||||
AC_MSG_ERROR('--with-gssapi requires a path to a directory')
|
||||
fi
|
||||
AC_MSG_CHECKING([for krb5-config])
|
||||
if test -x "$gssapi_prefix/bin/krb5-config"; then
|
||||
krb5conf=$gssapi_prefix/bin/krb5-config
|
||||
AC_MSG_RESULT([$krb5conf])
|
||||
AC_MSG_CHECKING([for gssapi support in krb5-config])
|
||||
if "$krb5conf" | grep gssapi > /dev/null; then
|
||||
AC_MSG_RESULT([yes])
|
||||
GSSAPI_confopts=gssapi
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
GSSAPI_confopts=
|
||||
fi
|
||||
GSSAPI_cflags=`"$krb5conf" --cflags $GSSAPI_confopts`
|
||||
GSSAPI_libs=`"$krb5conf" --libs $GSSAPI_confopts`
|
||||
if test -z "$GSSAPI_confopts"; then
|
||||
case "${host_os}" in
|
||||
solaris*)
|
||||
GSSAPI_cflags="$GSSAPI_cflags -I/usr/include/gssapi"
|
||||
GSSAPI_libs="$GSSAPI_libs -lgss"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
APR_ADDTO(CFLAGS, "$GSSAPI_cflags")
|
||||
APR_ADDTO(CFLAGS, [-DSERF_HAVE_GSSAPI])
|
||||
APR_ADDTO(LDFLAGS, "$GSSAPI_libs")
|
||||
AC_MSG_CHECKING([if gssapi works])
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
||||
#include <gssapi.h>
|
||||
int main()
|
||||
{gss_init_sec_context(NULL, NULL, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL);}]])],
|
||||
lib_gssapi="yes", lib_gssapi="no")
|
||||
if test "$lib_gssapi" = "yes"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot find GSSAPI (Kerberos)])
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_WARN([--with-gssapi specified but krb5-config not found])
|
||||
fi
|
||||
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl CuTest requires libm on Solaris
|
||||
AC_SEARCH_LIBS(fabs, m)
|
||||
|
||||
libs=""
|
||||
if test -n "$apu_config"; then
|
||||
APR_ADDTO(libs, [`$apu_config --link-libtool --libs`])
|
||||
fi
|
||||
APR_ADDTO(libs, [`$apr_config --link-libtool --libs` $LIBS])
|
||||
|
||||
APR_ADDTO(SERF_LIBS, [$libs])
|
||||
AC_SUBST(SERF_LIBS)
|
||||
|
||||
APR_RESTORE_THE_ENVIRONMENT(CPPFLAGS, EXTRA_)
|
||||
APR_RESTORE_THE_ENVIRONMENT(CFLAGS, EXTRA_)
|
||||
APR_RESTORE_THE_ENVIRONMENT(CXXFLAGS, EXTRA_)
|
||||
APR_RESTORE_THE_ENVIRONMENT(LDFLAGS, EXTRA_)
|
||||
APR_RESTORE_THE_ENVIRONMENT(LIBS, EXTRA_)
|
||||
APR_RESTORE_THE_ENVIRONMENT(INCLUDES, EXTRA_)
|
||||
|
||||
AC_CONFIG_FILES([Makefile serf.pc])
|
||||
AC_CONFIG_COMMANDS([mkdir-vpath],[make mkdir-vpath])
|
||||
|
||||
AC_OUTPUT
|
17
context.c
17
context.c
@ -22,20 +22,6 @@
|
||||
|
||||
#include "serf_private.h"
|
||||
|
||||
/* Older versions of APR do not have the APR_VERSION_AT_LEAST macro. Those
|
||||
implementations are safe.
|
||||
|
||||
If the macro *is* defined, and we're on WIN32, and APR is version 1.4.0,
|
||||
then we have a broken WSAPoll() implementation.
|
||||
|
||||
See serf_context_create_ex() below. */
|
||||
#if defined(APR_VERSION_AT_LEAST) && defined(WIN32)
|
||||
#if APR_VERSION_AT_LEAST(1,4,0)
|
||||
#define BROKEN_WSAPOLL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Callback function (implements serf_progress_t). Takes a number of bytes
|
||||
* read @a read and bytes written @a written, adds those to the total for this
|
||||
@ -182,6 +168,7 @@ serf_context_t *serf_context_create_ex(
|
||||
ctx->progress_written = 0;
|
||||
|
||||
ctx->authn_types = SERF_AUTHN_ALL;
|
||||
ctx->server_authn_info = apr_hash_make(pool);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
@ -382,7 +369,7 @@ const char *serf_error_string(apr_status_t errcode)
|
||||
case SERF_ERROR_AUTHN_INITALIZATION_FAILED:
|
||||
return "Initialization of an authentication type failed";
|
||||
case SERF_ERROR_SSLTUNNEL_SETUP_FAILED:
|
||||
return "The proxy server returned an error while setting up the "\
|
||||
return "The proxy server returned an error while setting up the "
|
||||
"SSL tunnel.";
|
||||
default:
|
||||
return NULL;
|
||||
|
@ -152,7 +152,7 @@ apr_status_t serf_listener_create(
|
||||
rv = apr_socket_opt_set(l->skt, APR_SO_REUSEADDR, 1);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
||||
|
||||
rv = apr_socket_bind(l->skt, sa);
|
||||
if (rv)
|
||||
return rv;
|
||||
|
554
outgoing.c
554
outgoing.c
@ -16,6 +16,7 @@
|
||||
#include <apr_pools.h>
|
||||
#include <apr_poll.h>
|
||||
#include <apr_version.h>
|
||||
#include <apr_portable.h>
|
||||
|
||||
#include "serf.h"
|
||||
#include "serf_bucket_util.h"
|
||||
@ -113,30 +114,34 @@ apr_status_t serf__conn_update_pollset(serf_connection_t *conn)
|
||||
/* ### not true. we only want to read IF we have sent some data */
|
||||
desc.reqevents |= APR_POLLIN;
|
||||
|
||||
/* If the connection is not closing down and
|
||||
* has unwritten data or
|
||||
* there are any requests that still have buckets to write out,
|
||||
* then we want to write.
|
||||
*/
|
||||
if (conn->vec_len &&
|
||||
conn->state != SERF_CONN_CLOSING)
|
||||
desc.reqevents |= APR_POLLOUT;
|
||||
else {
|
||||
serf_request_t *request = conn->requests;
|
||||
/* Don't write if OpenSSL told us that it needs to read data first. */
|
||||
if (conn->stop_writing != 1) {
|
||||
|
||||
if ((conn->probable_keepalive_limit &&
|
||||
conn->completed_requests > conn->probable_keepalive_limit) ||
|
||||
(conn->max_outstanding_requests &&
|
||||
conn->completed_requests - conn->completed_responses >=
|
||||
conn->max_outstanding_requests)) {
|
||||
/* we wouldn't try to write any way right now. */
|
||||
}
|
||||
/* If the connection is not closing down and
|
||||
* has unwritten data or
|
||||
* there are any requests that still have buckets to write out,
|
||||
* then we want to write.
|
||||
*/
|
||||
if (conn->vec_len &&
|
||||
conn->state != SERF_CONN_CLOSING)
|
||||
desc.reqevents |= APR_POLLOUT;
|
||||
else {
|
||||
while (request != NULL && request->req_bkt == NULL &&
|
||||
request->written)
|
||||
request = request->next;
|
||||
if (request != NULL)
|
||||
desc.reqevents |= APR_POLLOUT;
|
||||
serf_request_t *request = conn->requests;
|
||||
|
||||
if ((conn->probable_keepalive_limit &&
|
||||
conn->completed_requests > conn->probable_keepalive_limit) ||
|
||||
(conn->max_outstanding_requests &&
|
||||
conn->completed_requests - conn->completed_responses >=
|
||||
conn->max_outstanding_requests)) {
|
||||
/* we wouldn't try to write any way right now. */
|
||||
}
|
||||
else {
|
||||
while (request != NULL && request->req_bkt == NULL &&
|
||||
request->written)
|
||||
request = request->next;
|
||||
if (request != NULL)
|
||||
desc.reqevents |= APR_POLLOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -177,6 +182,108 @@ static void check_buckets_drained(serf_connection_t *conn)
|
||||
|
||||
#endif
|
||||
|
||||
static void destroy_ostream(serf_connection_t *conn)
|
||||
{
|
||||
if (conn->ostream_head != NULL) {
|
||||
serf_bucket_destroy(conn->ostream_head);
|
||||
conn->ostream_head = NULL;
|
||||
conn->ostream_tail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
|
||||
{
|
||||
serf_connection_t *conn = baton;
|
||||
conn->hit_eof = 1;
|
||||
return APR_EAGAIN;
|
||||
}
|
||||
|
||||
static apr_status_t do_conn_setup(serf_connection_t *conn)
|
||||
{
|
||||
apr_status_t status;
|
||||
serf_bucket_t *ostream;
|
||||
|
||||
if (conn->ostream_head == NULL) {
|
||||
conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
|
||||
}
|
||||
|
||||
if (conn->ostream_tail == NULL) {
|
||||
conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
|
||||
detect_eof,
|
||||
conn);
|
||||
}
|
||||
|
||||
ostream = conn->ostream_tail;
|
||||
|
||||
status = (*conn->setup)(conn->skt,
|
||||
&conn->stream,
|
||||
&ostream,
|
||||
conn->setup_baton,
|
||||
conn->pool);
|
||||
if (status) {
|
||||
/* extra destroy here since it wasn't added to the head bucket yet. */
|
||||
serf_bucket_destroy(conn->ostream_tail);
|
||||
destroy_ostream(conn);
|
||||
return status;
|
||||
}
|
||||
|
||||
serf_bucket_aggregate_append(conn->ostream_head,
|
||||
ostream);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set up the input and output stream buckets.
|
||||
When a tunnel over an http proxy is needed, create a socket bucket and
|
||||
empty aggregate bucket for sending and receiving unencrypted requests
|
||||
over the socket.
|
||||
|
||||
After the tunnel is there, or no tunnel was needed, ask the application
|
||||
to create the input and output buckets, which should take care of the
|
||||
[en/de]cryption.
|
||||
*/
|
||||
|
||||
static apr_status_t prepare_conn_streams(serf_connection_t *conn,
|
||||
serf_bucket_t **istream,
|
||||
serf_bucket_t **ostreamt,
|
||||
serf_bucket_t **ostreamh)
|
||||
{
|
||||
apr_status_t status;
|
||||
|
||||
if (conn->stream == NULL) {
|
||||
conn->latency = apr_time_now() - conn->connect_time;
|
||||
}
|
||||
|
||||
/* Do we need a SSL tunnel first? */
|
||||
if (conn->state == SERF_CONN_CONNECTED) {
|
||||
/* If the connection does not have an associated bucket, then
|
||||
* call the setup callback to get one.
|
||||
*/
|
||||
if (conn->stream == NULL) {
|
||||
status = do_conn_setup(conn);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
*ostreamt = conn->ostream_tail;
|
||||
*ostreamh = conn->ostream_head;
|
||||
*istream = conn->stream;
|
||||
} else {
|
||||
/* SSL tunnel needed and not set up yet, get a direct unencrypted
|
||||
stream for this socket */
|
||||
if (conn->stream == NULL) {
|
||||
*istream = serf_bucket_socket_create(conn->skt,
|
||||
conn->allocator);
|
||||
}
|
||||
/* Don't create the ostream bucket chain including the ssl_encrypt
|
||||
bucket yet. This ensure the CONNECT request is sent unencrypted
|
||||
to the proxy. */
|
||||
*ostreamt = *ostreamh = conn->ssltunnel_ostream;
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Create and connect sockets for any connections which don't have them
|
||||
* yet. This is the core of our lazy-connect behavior.
|
||||
*/
|
||||
@ -186,6 +293,7 @@ apr_status_t serf__open_connections(serf_context_t *ctx)
|
||||
|
||||
for (i = ctx->conns->nelts; i--; ) {
|
||||
serf_connection_t *conn = GET_CONN(ctx, i);
|
||||
serf__authn_info_t *authn_info;
|
||||
apr_status_t status;
|
||||
apr_socket_t *skt;
|
||||
|
||||
@ -240,7 +348,7 @@ apr_status_t serf__open_connections(serf_context_t *ctx)
|
||||
serf__log_skt(SOCK_VERBOSE, __FILE__, skt,
|
||||
"connected socket for conn 0x%x, status %d\n",
|
||||
conn, status);
|
||||
if (status != APR_SUCCESS) {
|
||||
if (status != APR_SUCCESS) {
|
||||
if (!APR_STATUS_IS_EINPROGRESS(status))
|
||||
return status;
|
||||
}
|
||||
@ -253,21 +361,33 @@ apr_status_t serf__open_connections(serf_context_t *ctx)
|
||||
prepare this connection (it might be possible to skip some
|
||||
part of the handshaking). */
|
||||
if (ctx->proxy_address) {
|
||||
if (conn->ctx->proxy_authn_info.scheme)
|
||||
conn->ctx->proxy_authn_info.scheme->init_conn_func(407, conn,
|
||||
conn->pool);
|
||||
authn_info = &ctx->proxy_authn_info;
|
||||
if (authn_info->scheme) {
|
||||
authn_info->scheme->init_conn_func(authn_info->scheme, 407,
|
||||
conn, conn->pool);
|
||||
}
|
||||
}
|
||||
|
||||
if (conn->ctx->authn_info.scheme)
|
||||
conn->ctx->authn_info.scheme->init_conn_func(401, conn,
|
||||
conn->pool);
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
if (authn_info->scheme) {
|
||||
authn_info->scheme->init_conn_func(authn_info->scheme, 401,
|
||||
conn, conn->pool);
|
||||
}
|
||||
|
||||
/* Does this connection require a SSL tunnel over the proxy? */
|
||||
if (ctx->proxy_address && strcmp(conn->host_info.scheme, "https") == 0)
|
||||
serf__ssltunnel_connect(conn);
|
||||
else
|
||||
else {
|
||||
serf_bucket_t *dummy1, *dummy2;
|
||||
|
||||
conn->state = SERF_CONN_CONNECTED;
|
||||
|
||||
status = prepare_conn_streams(conn, &conn->stream,
|
||||
&dummy1, &dummy2);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
@ -396,15 +516,6 @@ static apr_status_t remove_connection(serf_context_t *ctx,
|
||||
&desc, conn);
|
||||
}
|
||||
|
||||
static void destroy_ostream(serf_connection_t *conn)
|
||||
{
|
||||
if (conn->ostream_head != NULL) {
|
||||
serf_bucket_destroy(conn->ostream_head);
|
||||
conn->ostream_head = NULL;
|
||||
conn->ostream_tail = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* A socket was closed, inform the application. */
|
||||
static void handle_conn_closed(serf_connection_t *conn, apr_status_t status)
|
||||
{
|
||||
@ -492,7 +603,7 @@ static apr_status_t socket_writev(serf_connection_t *conn)
|
||||
|
||||
status = apr_socket_sendv(conn->skt, conn->vec,
|
||||
conn->vec_len, &written);
|
||||
if (status && !APR_STATUS_IS_EAGAIN(status))
|
||||
if (status && !APR_STATUS_IS_EAGAIN(status))
|
||||
serf__log_skt(SOCK_VERBOSE, __FILE__, conn->skt,
|
||||
"socket_sendv error %d\n", status);
|
||||
|
||||
@ -535,99 +646,29 @@ static apr_status_t socket_writev(serf_connection_t *conn)
|
||||
return status;
|
||||
}
|
||||
|
||||
static apr_status_t detect_eof(void *baton, serf_bucket_t *aggregate_bucket)
|
||||
{
|
||||
serf_connection_t *conn = baton;
|
||||
conn->hit_eof = 1;
|
||||
return APR_EAGAIN;
|
||||
}
|
||||
|
||||
static apr_status_t do_conn_setup(serf_connection_t *conn)
|
||||
static apr_status_t setup_request(serf_request_t *request)
|
||||
{
|
||||
serf_connection_t *conn = request->conn;
|
||||
apr_status_t status;
|
||||
serf_bucket_t *ostream;
|
||||
|
||||
if (conn->ostream_head == NULL) {
|
||||
conn->ostream_head = serf_bucket_aggregate_create(conn->allocator);
|
||||
}
|
||||
|
||||
if (conn->ostream_tail == NULL) {
|
||||
conn->ostream_tail = serf__bucket_stream_create(conn->allocator,
|
||||
detect_eof,
|
||||
conn);
|
||||
}
|
||||
|
||||
ostream = conn->ostream_tail;
|
||||
|
||||
status = (*conn->setup)(conn->skt,
|
||||
&conn->stream,
|
||||
&ostream,
|
||||
conn->setup_baton,
|
||||
conn->pool);
|
||||
if (status) {
|
||||
/* extra destroy here since it wasn't added to the head bucket yet. */
|
||||
serf_bucket_destroy(conn->ostream_tail);
|
||||
destroy_ostream(conn);
|
||||
return status;
|
||||
}
|
||||
|
||||
serf_bucket_aggregate_append(conn->ostream_head,
|
||||
ostream);
|
||||
/* Now that we are about to serve the request, allocate a pool. */
|
||||
apr_pool_create(&request->respool, conn->pool);
|
||||
request->allocator = serf_bucket_allocator_create(request->respool,
|
||||
NULL, NULL);
|
||||
apr_pool_cleanup_register(request->respool, request,
|
||||
clean_resp, clean_resp);
|
||||
|
||||
/* Fill in the rest of the values for the request. */
|
||||
status = request->setup(request, request->setup_baton,
|
||||
&request->req_bkt,
|
||||
&request->acceptor,
|
||||
&request->acceptor_baton,
|
||||
&request->handler,
|
||||
&request->handler_baton,
|
||||
request->respool);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Set up the input and output stream buckets.
|
||||
When a tunnel over an http proxy is needed, create a socket bucket and
|
||||
empty aggregate bucket for sending and receiving unencrypted requests
|
||||
over the socket.
|
||||
|
||||
After the tunnel is there, or no tunnel was needed, ask the application
|
||||
to create the input and output buckets, which should take care of the
|
||||
[en/de]cryption.
|
||||
*/
|
||||
|
||||
static apr_status_t prepare_conn_streams(serf_connection_t *conn,
|
||||
serf_bucket_t **istream,
|
||||
serf_bucket_t **ostreamt,
|
||||
serf_bucket_t **ostreamh)
|
||||
{
|
||||
apr_status_t status;
|
||||
|
||||
if (conn->stream == NULL) {
|
||||
conn->latency = apr_time_now() - conn->connect_time;
|
||||
}
|
||||
|
||||
/* Do we need a SSL tunnel first? */
|
||||
if (conn->state == SERF_CONN_CONNECTED) {
|
||||
/* If the connection does not have an associated bucket, then
|
||||
* call the setup callback to get one.
|
||||
*/
|
||||
if (conn->stream == NULL) {
|
||||
status = do_conn_setup(conn);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
*ostreamt = conn->ostream_tail;
|
||||
*ostreamh = conn->ostream_head;
|
||||
*istream = conn->stream;
|
||||
} else {
|
||||
/* SSL tunnel needed and not set up yet, get a direct unencrypted
|
||||
stream for this socket */
|
||||
if (conn->stream == NULL) {
|
||||
*istream = serf_bucket_socket_create(conn->skt,
|
||||
conn->allocator);
|
||||
}
|
||||
/* Don't create the ostream bucket chain including the ssl_encrypt
|
||||
bucket yet. This ensure the CONNECT request is sent unencrypted
|
||||
to the proxy. */
|
||||
*ostreamt = *ostreamh = conn->ssltunnel_ostream;
|
||||
}
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* write data out to the connection */
|
||||
static apr_status_t write_to_connection(serf_connection_t *conn)
|
||||
{
|
||||
@ -717,32 +758,23 @@ static apr_status_t write_to_connection(serf_connection_t *conn)
|
||||
}
|
||||
|
||||
if (request->req_bkt == NULL) {
|
||||
/* Now that we are about to serve the request, allocate a pool. */
|
||||
apr_pool_create(&request->respool, conn->pool);
|
||||
request->allocator = serf_bucket_allocator_create(request->respool,
|
||||
NULL, NULL);
|
||||
apr_pool_cleanup_register(request->respool, request,
|
||||
clean_resp, clean_resp);
|
||||
|
||||
/* Fill in the rest of the values for the request. */
|
||||
read_status = request->setup(request, request->setup_baton,
|
||||
&request->req_bkt,
|
||||
&request->acceptor,
|
||||
&request->acceptor_baton,
|
||||
&request->handler,
|
||||
&request->handler_baton,
|
||||
request->respool);
|
||||
|
||||
read_status = setup_request(request);
|
||||
if (read_status) {
|
||||
/* Something bad happened. Propagate any errors. */
|
||||
return read_status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!request->written) {
|
||||
request->written = 1;
|
||||
serf_bucket_aggregate_append(ostreamt, request->req_bkt);
|
||||
}
|
||||
|
||||
/* ### optimize at some point by using read_for_sendfile */
|
||||
/* TODO: now that read_iovec will effectively try to return as much
|
||||
data as available, we probably don't want to read ALL_AVAIL, but
|
||||
a lower number, like the size of one or a few TCP packets, the
|
||||
available TCP buffer size ... */
|
||||
read_status = serf_bucket_read_iovec(ostreamh,
|
||||
SERF_READ_ALL_AVAIL,
|
||||
IOV_MAX,
|
||||
@ -750,17 +782,24 @@ static apr_status_t write_to_connection(serf_connection_t *conn)
|
||||
&conn->vec_len);
|
||||
|
||||
if (!conn->hit_eof) {
|
||||
if (APR_STATUS_IS_EAGAIN(read_status) ||
|
||||
read_status == SERF_ERROR_WAIT_CONN) {
|
||||
if (APR_STATUS_IS_EAGAIN(read_status)) {
|
||||
/* We read some stuff, but should not try to read again. */
|
||||
stop_reading = 1;
|
||||
}
|
||||
else if (read_status == SERF_ERROR_WAIT_CONN) {
|
||||
/* The bucket told us that it can't provide more data until
|
||||
more data is read from the socket. This normally happens
|
||||
during a SSL handshake.
|
||||
|
||||
/* ### we should avoid looking for writability for a while so
|
||||
### that (hopefully) something will appear in the bucket so
|
||||
### we can actually write something. otherwise, we could
|
||||
### end up in a CPU spin: socket wants something, but we
|
||||
### don't have anything (and keep returning EAGAIN)
|
||||
*/
|
||||
We should avoid looking for writability for a while so
|
||||
that (hopefully) something will appear in the bucket so
|
||||
we can actually write something. otherwise, we could
|
||||
end up in a CPU spin: socket wants something, but we
|
||||
don't have anything (and keep returning EAGAIN)
|
||||
*/
|
||||
conn->stop_writing = 1;
|
||||
conn->dirty_conn = 1;
|
||||
conn->ctx->dirty_pollset = 1;
|
||||
}
|
||||
else if (read_status && !APR_STATUS_IS_EOF(read_status)) {
|
||||
/* Something bad happened. Propagate any errors. */
|
||||
@ -790,6 +829,9 @@ static apr_status_t write_to_connection(serf_connection_t *conn)
|
||||
|
||||
if (read_status == SERF_ERROR_WAIT_CONN) {
|
||||
stop_reading = 1;
|
||||
conn->stop_writing = 1;
|
||||
conn->dirty_conn = 1;
|
||||
conn->ctx->dirty_pollset = 1;
|
||||
}
|
||||
else if (read_status && conn->hit_eof && conn->vec_len == 0) {
|
||||
/* If we hit the end of the request bucket and all of its data has
|
||||
@ -895,6 +937,57 @@ static apr_status_t handle_async_response(serf_connection_t *conn,
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
apr_status_t
|
||||
serf__provide_credentials(serf_context_t *ctx,
|
||||
char **username,
|
||||
char **password,
|
||||
serf_request_t *request, void *baton,
|
||||
int code, const char *authn_type,
|
||||
const char *realm,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
serf_connection_t *conn = request->conn;
|
||||
serf_request_t *authn_req = request;
|
||||
apr_status_t status;
|
||||
|
||||
if (request->ssltunnel == 1 &&
|
||||
conn->state == SERF_CONN_SETUP_SSLTUNNEL) {
|
||||
/* This is a CONNECT request to set up an SSL tunnel over a proxy.
|
||||
This request is created by serf, so if the proxy requires
|
||||
authentication, we can't ask the application for credentials with
|
||||
this request.
|
||||
|
||||
Solution: setup the first request created by the application on
|
||||
this connection, and use that request and its handler_baton to
|
||||
call back to the application. */
|
||||
|
||||
authn_req = request->next;
|
||||
/* assert: app_request != NULL */
|
||||
if (!authn_req)
|
||||
return APR_EGENERAL;
|
||||
|
||||
if (!authn_req->req_bkt) {
|
||||
apr_status_t status;
|
||||
|
||||
status = setup_request(authn_req);
|
||||
/* If we can't setup a request, don't bother setting up the
|
||||
ssl tunnel. */
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ask the application. */
|
||||
status = (*ctx->cred_cb)(username, password,
|
||||
authn_req, authn_req->handler_baton,
|
||||
code, authn_type, realm, pool);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* read data from the connection */
|
||||
static apr_status_t read_from_connection(serf_connection_t *conn)
|
||||
{
|
||||
@ -907,6 +1000,14 @@ static apr_status_t read_from_connection(serf_connection_t *conn)
|
||||
*/
|
||||
serf_request_t *request = conn->requests;
|
||||
|
||||
/* If the stop_writing flag was set on the connection, reset it now because
|
||||
there is some data to read. */
|
||||
if (conn->stop_writing) {
|
||||
conn->stop_writing = 0;
|
||||
conn->dirty_conn = 1;
|
||||
conn->ctx->dirty_pollset = 1;
|
||||
}
|
||||
|
||||
/* assert: request != NULL */
|
||||
|
||||
if ((status = apr_pool_create(&tmppool, conn->pool)) != APR_SUCCESS)
|
||||
@ -1137,6 +1238,20 @@ apr_status_t serf__process_connection(serf_connection_t *conn,
|
||||
if (conn->completed_requests && !conn->probable_keepalive_limit) {
|
||||
return reset_connection(conn, 1);
|
||||
}
|
||||
#ifdef SO_ERROR
|
||||
/* If possible, get the error from the platform's socket layer and
|
||||
convert it to an APR status code. */
|
||||
{
|
||||
apr_os_sock_t osskt;
|
||||
if (!apr_os_sock_get(&osskt, conn->skt)) {
|
||||
int error;
|
||||
apr_socklen_t l = sizeof(error);
|
||||
|
||||
if (!getsockopt(osskt, SOL_SOCKET, SO_ERROR, (char*)&error, &l))
|
||||
return APR_FROM_OS_ERROR(error);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
if ((events & APR_POLLOUT) != 0) {
|
||||
@ -1180,7 +1295,8 @@ serf_connection_t *serf_connection_create(
|
||||
apr_pool_create(&conn->skt_pool, conn->pool);
|
||||
|
||||
/* register a cleanup */
|
||||
apr_pool_cleanup_register(conn->pool, conn, clean_conn, apr_pool_cleanup_null);
|
||||
apr_pool_cleanup_register(conn->pool, conn, clean_conn,
|
||||
apr_pool_cleanup_null);
|
||||
|
||||
/* Add the connection to the context. */
|
||||
*(serf_connection_t **)apr_array_push(ctx->conns) = conn;
|
||||
@ -1227,7 +1343,12 @@ apr_status_t serf_connection_create2(
|
||||
c->host_url = apr_uri_unparse(c->pool,
|
||||
&host_info,
|
||||
APR_URI_UNP_OMITPATHINFO);
|
||||
c->host_info = host_info;
|
||||
|
||||
/* Store the host info without the path on the connection. */
|
||||
(void)apr_uri_parse(c->pool, c->host_url, &(c->host_info));
|
||||
if (!c->host_info.port) {
|
||||
c->host_info.port = apr_uri_port_of_scheme(c->host_info.scheme);
|
||||
}
|
||||
|
||||
*conn = c;
|
||||
|
||||
@ -1330,11 +1451,12 @@ void serf_connection_set_async_responses(
|
||||
conn->async_handler_baton = handler_baton;
|
||||
}
|
||||
|
||||
|
||||
serf_request_t *serf_connection_request_create(
|
||||
serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton)
|
||||
static serf_request_t *
|
||||
create_request(serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton,
|
||||
int priority,
|
||||
int ssltunnel)
|
||||
{
|
||||
serf_request_t *request;
|
||||
|
||||
@ -1346,10 +1468,25 @@ serf_request_t *serf_connection_request_create(
|
||||
request->respool = NULL;
|
||||
request->req_bkt = NULL;
|
||||
request->resp_bkt = NULL;
|
||||
request->priority = 0;
|
||||
request->priority = priority;
|
||||
request->written = 0;
|
||||
request->ssltunnel = ssltunnel;
|
||||
request->next = NULL;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
serf_request_t *serf_connection_request_create(
|
||||
serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton)
|
||||
{
|
||||
serf_request_t *request;
|
||||
|
||||
request = create_request(conn, setup, setup_baton,
|
||||
0, /* priority */
|
||||
0 /* ssl tunnel */);
|
||||
|
||||
/* Link the request to the end of the request chain. */
|
||||
link_requests(&conn->requests, &conn->requests_tail, request);
|
||||
|
||||
@ -1360,26 +1497,18 @@ serf_request_t *serf_connection_request_create(
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
serf_request_t *serf_connection_priority_request_create(
|
||||
serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton)
|
||||
static serf_request_t *
|
||||
priority_request_create(serf_connection_t *conn,
|
||||
int ssltunnelreq,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton)
|
||||
{
|
||||
serf_request_t *request;
|
||||
serf_request_t *iter, *prev;
|
||||
|
||||
request = serf_bucket_mem_alloc(conn->allocator, sizeof(*request));
|
||||
request->conn = conn;
|
||||
request->setup = setup;
|
||||
request->setup_baton = setup_baton;
|
||||
request->handler = NULL;
|
||||
request->respool = NULL;
|
||||
request->req_bkt = NULL;
|
||||
request->resp_bkt = NULL;
|
||||
request->priority = 1;
|
||||
request->written = 0;
|
||||
request->next = NULL;
|
||||
request = create_request(conn, setup, setup_baton,
|
||||
1, /* priority */
|
||||
ssltunnelreq);
|
||||
|
||||
/* Link the new request after the last written request. */
|
||||
iter = conn->requests;
|
||||
@ -1391,10 +1520,17 @@ serf_request_t *serf_connection_priority_request_create(
|
||||
iter = iter->next;
|
||||
}
|
||||
|
||||
/* Advance to next non priority request */
|
||||
while (iter != NULL && iter->priority) {
|
||||
prev = iter;
|
||||
iter = iter->next;
|
||||
/* A CONNECT request to setup an ssltunnel has absolute priority over all
|
||||
other requests on the connection, so:
|
||||
a. add it first to the queue
|
||||
b. ensure that other priority requests are added after the CONNECT
|
||||
request */
|
||||
if (!request->ssltunnel) {
|
||||
/* Advance to next non priority request */
|
||||
while (iter != NULL && iter->priority) {
|
||||
prev = iter;
|
||||
iter = iter->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev) {
|
||||
@ -1412,6 +1548,24 @@ serf_request_t *serf_connection_priority_request_create(
|
||||
return request;
|
||||
}
|
||||
|
||||
serf_request_t *serf_connection_priority_request_create(
|
||||
serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton)
|
||||
{
|
||||
return priority_request_create(conn,
|
||||
0, /* not a ssltunnel CONNECT request */
|
||||
setup, setup_baton);
|
||||
}
|
||||
|
||||
serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton)
|
||||
{
|
||||
return priority_request_create(conn,
|
||||
1, /* This is a ssltunnel CONNECT request */
|
||||
setup, setup_baton);
|
||||
}
|
||||
|
||||
apr_status_t serf_request_cancel(serf_request_t *request)
|
||||
{
|
||||
@ -1466,29 +1620,53 @@ serf_bucket_t *serf_request_bucket_request_create(
|
||||
serf_bucket_t *req_bkt, *hdrs_bkt;
|
||||
serf_connection_t *conn = request->conn;
|
||||
serf_context_t *ctx = conn->ctx;
|
||||
int ssltunnel;
|
||||
|
||||
ssltunnel = ctx->proxy_address &&
|
||||
(strcmp(conn->host_info.scheme, "https") == 0);
|
||||
|
||||
req_bkt = serf_bucket_request_create(method, uri, body, allocator);
|
||||
hdrs_bkt = serf_bucket_request_get_headers(req_bkt);
|
||||
|
||||
/* Proxy? */
|
||||
if (ctx->proxy_address && conn->host_url)
|
||||
/* Use absolute uri's in requests to a proxy. USe relative uri's in
|
||||
requests directly to a server or sent through an SSL tunnel. */
|
||||
if (ctx->proxy_address && conn->host_url &&
|
||||
!(ssltunnel && !request->ssltunnel)) {
|
||||
|
||||
serf_bucket_request_set_root(req_bkt, conn->host_url);
|
||||
}
|
||||
|
||||
if (conn->host_info.hostinfo)
|
||||
serf_bucket_headers_setn(hdrs_bkt, "Host",
|
||||
conn->host_info.hostinfo);
|
||||
|
||||
/* Setup server authorization headers */
|
||||
if (ctx->authn_info.scheme)
|
||||
ctx->authn_info.scheme->setup_request_func(HOST, 0, conn, request,
|
||||
/* Setup server authorization headers, unless this is a CONNECT request. */
|
||||
if (!request->ssltunnel) {
|
||||
serf__authn_info_t *authn_info;
|
||||
authn_info = serf__get_authn_info_for_server(conn);
|
||||
if (authn_info->scheme)
|
||||
authn_info->scheme->setup_request_func(HOST, 0, conn, request,
|
||||
method, uri,
|
||||
hdrs_bkt);
|
||||
}
|
||||
|
||||
/* Setup proxy authorization headers */
|
||||
if (ctx->proxy_authn_info.scheme)
|
||||
ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
|
||||
request,
|
||||
method, uri, hdrs_bkt);
|
||||
/* Setup proxy authorization headers.
|
||||
Don't set these headers on the requests to the server if we're using
|
||||
an SSL tunnel, only on the CONNECT request to setup the tunnel. */
|
||||
if (ctx->proxy_authn_info.scheme) {
|
||||
if (strcmp(conn->host_info.scheme, "https") == 0) {
|
||||
if (request->ssltunnel)
|
||||
ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
|
||||
request,
|
||||
method, uri,
|
||||
hdrs_bkt);
|
||||
} else {
|
||||
ctx->proxy_authn_info.scheme->setup_request_func(PROXY, 0, conn,
|
||||
request,
|
||||
method, uri,
|
||||
hdrs_bkt);
|
||||
}
|
||||
}
|
||||
|
||||
return req_bkt;
|
||||
}
|
||||
|
44
serf.h
44
serf.h
@ -59,57 +59,55 @@ typedef struct serf_request_t serf_request_t;
|
||||
* Serf-specific error codes
|
||||
*/
|
||||
#define SERF_ERROR_RANGE 100
|
||||
#define SERF_ERROR_START (APR_OS_START_USERERR + SERF_ERROR_RANGE)
|
||||
|
||||
/* This code is for when this is the last response on this connection:
|
||||
* i.e. do not send any more requests on this connection or expect
|
||||
* any more responses.
|
||||
*/
|
||||
#define SERF_ERROR_CLOSING (APR_OS_START_USERERR + SERF_ERROR_RANGE + 1)
|
||||
#define SERF_ERROR_CLOSING (SERF_ERROR_START + 1)
|
||||
/* This code is for when the connection terminated before the request
|
||||
* could be processed on the other side.
|
||||
*/
|
||||
#define SERF_ERROR_REQUEST_LOST (APR_OS_START_USERERR + SERF_ERROR_RANGE + 2)
|
||||
#define SERF_ERROR_REQUEST_LOST (SERF_ERROR_START + 2)
|
||||
/* This code is for when the connection is blocked - we can not proceed
|
||||
* until something happens - generally due to SSL negotiation-like behavior
|
||||
* where a write() is blocked until a read() is processed.
|
||||
*/
|
||||
#define SERF_ERROR_WAIT_CONN (APR_OS_START_USERERR + SERF_ERROR_RANGE + 3)
|
||||
#define SERF_ERROR_WAIT_CONN (SERF_ERROR_START + 3)
|
||||
/* This code is for when something went wrong during deflating compressed
|
||||
* data e.g. a CRC error. */
|
||||
#define SERF_ERROR_DECOMPRESSION_FAILED (APR_OS_START_USERERR + \
|
||||
SERF_ERROR_RANGE + 4)
|
||||
#define SERF_ERROR_DECOMPRESSION_FAILED (SERF_ERROR_START + 4)
|
||||
/* This code is for when a response received from a http server is not in
|
||||
* http-compliant syntax. */
|
||||
#define SERF_ERROR_BAD_HTTP_RESPONSE (APR_OS_START_USERERR + \
|
||||
SERF_ERROR_RANGE + 5)
|
||||
#define SERF_ERROR_BAD_HTTP_RESPONSE (SERF_ERROR_START + 5)
|
||||
/* The server sent less data than what was announced. */
|
||||
#define SERF_ERROR_TRUNCATED_HTTP_RESPONSE (APR_OS_START_USERERR + \
|
||||
SERF_ERROR_RANGE + 6)
|
||||
#define SERF_ERROR_TRUNCATED_HTTP_RESPONSE (SERF_ERROR_START + 6)
|
||||
/* The proxy server returned an error while setting up the SSL tunnel. */
|
||||
#define SERF_ERROR_SSLTUNNEL_SETUP_FAILED (APR_OS_START_USERERR + \
|
||||
SERF_ERROR_RANGE + 7)
|
||||
#define SERF_ERROR_SSLTUNNEL_SETUP_FAILED (SERF_ERROR_START + 7)
|
||||
/* The server unexpectedly closed the connection prematurely. */
|
||||
#define SERF_ERROR_ABORTED_CONNECTION (APR_OS_START_USERERR + \
|
||||
SERF_ERROR_RANGE + 8)
|
||||
#define SERF_ERROR_ABORTED_CONNECTION (SERF_ERROR_START + 8)
|
||||
|
||||
/* SSL certificates related errors */
|
||||
#define SERF_ERROR_SSL_CERT_FAILED (APR_OS_START_USERERR + SERF_ERROR_RANGE + 70)
|
||||
#define SERF_ERROR_SSL_CERT_FAILED (SERF_ERROR_START + 70)
|
||||
|
||||
/* SSL communications related errors */
|
||||
#define SERF_ERROR_SSL_COMM_FAILED (APR_OS_START_USERERR + SERF_ERROR_RANGE + 71)
|
||||
#define SERF_ERROR_SSL_COMM_FAILED (SERF_ERROR_START + 71)
|
||||
|
||||
/* General authentication related errors */
|
||||
#define SERF_ERROR_AUTHN_FAILED (APR_OS_START_USERERR + SERF_ERROR_RANGE + 90)
|
||||
#define SERF_ERROR_AUTHN_FAILED (SERF_ERROR_START + 90)
|
||||
|
||||
/* None of the available authn mechanisms for the request are supported */
|
||||
#define SERF_ERROR_AUTHN_NOT_SUPPORTED (APR_OS_START_USERERR + SERF_ERROR_RANGE + 91)
|
||||
#define SERF_ERROR_AUTHN_NOT_SUPPORTED (SERF_ERROR_START + 91)
|
||||
|
||||
/* Authn was requested by the server but the header lacked some attribute */
|
||||
#define SERF_ERROR_AUTHN_MISSING_ATTRIBUTE (APR_OS_START_USERERR + SERF_ERROR_RANGE + 92)
|
||||
#define SERF_ERROR_AUTHN_MISSING_ATTRIBUTE (SERF_ERROR_START + 92)
|
||||
|
||||
/* Authentication handler initialization related errors */
|
||||
#define SERF_ERROR_AUTHN_INITALIZATION_FAILED (APR_OS_START_USERERR +\
|
||||
SERF_ERROR_RANGE + 93)
|
||||
#define SERF_ERROR_AUTHN_INITALIZATION_FAILED (SERF_ERROR_START + 93)
|
||||
|
||||
/* Error code reserved for use in the test suite. */
|
||||
#define SERF_ERROR_ISSUE_IN_TESTSUITE (SERF_ERROR_START + 99)
|
||||
|
||||
/* This macro groups errors potentially raised when reading a http response. */
|
||||
#define SERF_BAD_RESPONSE_ERROR(status) ((status) \
|
||||
@ -497,6 +495,8 @@ apr_status_t serf_connection_close(
|
||||
* connection @a conn. Setting max_requests to 0 means unlimited (the default).
|
||||
* Ex.: setting max_requests to 1 means a request is sent when a response on the
|
||||
* previous request was received and handled.
|
||||
*
|
||||
* In general, serf tends to take around 16KB per outstanding request.
|
||||
*/
|
||||
void serf_connection_set_max_outstanding_requests(
|
||||
serf_connection_t *conn,
|
||||
@ -1061,8 +1061,8 @@ void serf_debug__bucket_alloc_check(
|
||||
|
||||
/* Version info */
|
||||
#define SERF_MAJOR_VERSION 1
|
||||
#define SERF_MINOR_VERSION 2
|
||||
#define SERF_PATCH_VERSION 1
|
||||
#define SERF_MINOR_VERSION 3
|
||||
#define SERF_PATCH_VERSION 0
|
||||
|
||||
/* Version number string */
|
||||
#define SERF_VERSION_STRING APR_STRINGIFY(SERF_MAJOR_VERSION) "." \
|
||||
|
215
serf.mak
215
serf.mak
@ -1,215 +0,0 @@
|
||||
#**** serf Win32 -*- Makefile -*- ********************************************
|
||||
#
|
||||
# Define DEBUG_BUILD to create a debug version of the library.
|
||||
|
||||
!IF "$(OS)" == "Windows_NT"
|
||||
NULL=
|
||||
!ELSE
|
||||
NULL=nul
|
||||
!ENDIF
|
||||
|
||||
CFLAGS = /Zi /W3 /EHsc /I "./"
|
||||
|
||||
!IF "$(DEBUG_BUILD)" == ""
|
||||
INTDIR = Release
|
||||
CFLAGS = /MD /O2 /D "NDEBUG" $(CFLAGS)
|
||||
STATIC_LIB = $(INTDIR)\serf-1.lib
|
||||
!ELSE
|
||||
INTDIR = Debug
|
||||
CFLAGS = /MDd /Od /W3 /Gm /D "_DEBUG" $(CFLAGS)
|
||||
STATIC_LIB = $(INTDIR)\serf-1.lib
|
||||
!ENDIF
|
||||
|
||||
########
|
||||
# Support for OpenSSL integration
|
||||
!IF "$(OPENSSL_SRC)" == ""
|
||||
!ERROR OpenSSL is required. Please define OPENSSL_SRC.
|
||||
!ELSE
|
||||
OPENSSL_FLAGS = /I "$(OPENSSL_SRC)\inc32"
|
||||
!ENDIF
|
||||
|
||||
!IF "$(HTTPD_SRC)" != ""
|
||||
!IF "$(APR_SRC)" == ""
|
||||
APR_SRC=$(HTTPD_SRC)\srclib\apr
|
||||
!ENDIF
|
||||
|
||||
!IF "$(APRUTIL_SRC)" == ""
|
||||
APRUTIL_SRC=$(HTTPD_SRC)\srclib\apr-util
|
||||
!ENDIF
|
||||
|
||||
!ENDIF
|
||||
|
||||
########
|
||||
# APR
|
||||
!IF "$(APR_SRC)" == ""
|
||||
!ERROR APR is required. Please define APR_SRC or HTTPD_SRC.
|
||||
!ENDIF
|
||||
|
||||
APR_FLAGS = /I "$(APR_SRC)\include"
|
||||
!IF [IF EXIST "$(APR_SRC)\$(INTDIR)\libapr-1.lib" exit 1] == 1
|
||||
APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr-1.lib"
|
||||
!ELSE
|
||||
APR_LIBS = "$(APR_SRC)\$(INTDIR)\libapr.lib"
|
||||
!ENDIF
|
||||
|
||||
########
|
||||
# APR Util
|
||||
!IF "$(APRUTIL_SRC)" == ""
|
||||
!ERROR APR-Util is required. Please define APRUTIL_SRC or HTTPD_SRC.
|
||||
!ENDIF
|
||||
|
||||
APRUTIL_FLAGS = /I "$(APRUTIL_SRC)\include"
|
||||
!IF [IF EXIST "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib" exit 1] == 1
|
||||
APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil-1.lib"
|
||||
!ELSE
|
||||
APRUTIL_LIBS = "$(APRUTIL_SRC)\$(INTDIR)\libaprutil.lib"
|
||||
!ENDIF
|
||||
|
||||
########
|
||||
# Support for zlib integration
|
||||
!IF "$(ZLIB_SRC)" == ""
|
||||
!ERROR ZLib is required. Please define ZLIB_SRC.
|
||||
!ELSE
|
||||
ZLIB_FLAGS = /I "$(ZLIB_SRC)"
|
||||
!IF "$(ZLIB_DLL)" == ""
|
||||
!IF "$(ZLIB_LIBDIR)" == ""
|
||||
!IF "$(DEBUG_BUILD)" == ""
|
||||
ZLIB_LIBS = "$(ZLIB_SRC)\zlibstat.lib"
|
||||
!ELSE
|
||||
ZLIB_LIBS = "$(ZLIB_SRC)\zlibstatD.lib"
|
||||
!ENDIF
|
||||
!ELSE
|
||||
ZLIB_LIBS = "$(ZLIB_LIBDIR)\x86\ZlibStat$(INTDIR)\zlibstat.lib"
|
||||
ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_WINAPI
|
||||
!ENDIF
|
||||
!ELSE
|
||||
ZLIB_FLAGS = $(ZLIB_FLAGS) /D ZLIB_DLL
|
||||
ZLIB_LIBS = "$(ZLIB_SRC)\zlibdll.lib"
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
|
||||
# Exclude stuff we don't need from the Win32 headers
|
||||
WIN32_DEFS = /D WIN32 /D WIN32_LEAN_AND_MEAN /D NOUSER /D NOGDI /D NONLS /D NOCRYPT /D SERF_HAVE_SSPI
|
||||
|
||||
CPP=cl.exe
|
||||
CPP_PROJ = /c /nologo $(CFLAGS) $(WIN32_DEFS) $(APR_FLAGS) $(APRUTIL_FLAGS) $(OPENSSL_FLAGS) $(ZLIB_FLAGS) /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\"
|
||||
LIB32=link.exe
|
||||
LIB32_FLAGS=/nologo
|
||||
|
||||
LIB32_OBJS= \
|
||||
"$(INTDIR)\aggregate_buckets.obj" \
|
||||
"$(INTDIR)\auth.obj" \
|
||||
"$(INTDIR)\auth_basic.obj" \
|
||||
"$(INTDIR)\auth_digest.obj" \
|
||||
"$(INTDIR)\auth_kerb.obj" \
|
||||
"$(INTDIR)\auth_kerb_gss.obj" \
|
||||
"$(INTDIR)\auth_kerb_sspi.obj" \
|
||||
"$(INTDIR)\context.obj" \
|
||||
"$(INTDIR)\ssltunnel.obj" \
|
||||
"$(INTDIR)\allocator.obj" \
|
||||
"$(INTDIR)\barrier_buckets.obj" \
|
||||
"$(INTDIR)\buckets.obj" \
|
||||
"$(INTDIR)\chunk_buckets.obj" \
|
||||
"$(INTDIR)\dechunk_buckets.obj" \
|
||||
"$(INTDIR)\deflate_buckets.obj" \
|
||||
"$(INTDIR)\file_buckets.obj" \
|
||||
"$(INTDIR)\headers_buckets.obj" \
|
||||
"$(INTDIR)\incoming.obj" \
|
||||
"$(INTDIR)\iovec_buckets.obj" \
|
||||
"$(INTDIR)\limit_buckets.obj" \
|
||||
"$(INTDIR)\mmap_buckets.obj" \
|
||||
"$(INTDIR)\outgoing.obj" \
|
||||
"$(INTDIR)\request_buckets.obj" \
|
||||
"$(INTDIR)\response_buckets.obj" \
|
||||
"$(INTDIR)\response_body_buckets.obj" \
|
||||
"$(INTDIR)\simple_buckets.obj" \
|
||||
"$(INTDIR)\socket_buckets.obj" \
|
||||
"$(INTDIR)\ssl_buckets.obj" \
|
||||
|
||||
!IFDEF OPENSSL_STATIC
|
||||
LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32\libeay32.lib" \
|
||||
"$(OPENSSL_SRC)\out32\ssleay32.lib"
|
||||
!ELSE
|
||||
LIB32_OBJS = $(LIB32_OBJS) "$(OPENSSL_SRC)\out32dll\libeay32.lib" \
|
||||
"$(OPENSSL_SRC)\out32dll\ssleay32.lib"
|
||||
!ENDIF
|
||||
|
||||
LIB32_OBJS = $(LIB32_OBJS) $(APR_LIBS) $(APRUTIL_LIBS) $(ZLIB_LIBS)
|
||||
|
||||
SYS_LIBS = secur32.lib
|
||||
|
||||
TEST_OBJS = \
|
||||
"$(INTDIR)\CuTest.obj" \
|
||||
"$(INTDIR)\test_all.obj" \
|
||||
"$(INTDIR)\test_util.obj" \
|
||||
"$(INTDIR)\test_context.obj" \
|
||||
"$(INTDIR)\test_buckets.obj" \
|
||||
"$(INTDIR)\test_ssl.obj" \
|
||||
"$(INTDIR)\test_server.obj" \
|
||||
"$(INTDIR)\test_sslserver.obj" \
|
||||
|
||||
TEST_LIBS = user32.lib advapi32.lib gdi32.lib ws2_32.lib
|
||||
|
||||
|
||||
ALL: $(INTDIR) $(STATIC_LIB) TESTS
|
||||
|
||||
CLEAN:
|
||||
-@erase /q "$(INTDIR)" >nul
|
||||
|
||||
$(INTDIR):
|
||||
-@if not exist "$(INTDIR)/$(NULL)" mkdir "$(INTDIR)"
|
||||
|
||||
TESTS: $(STATIC_LIB) $(INTDIR)\serf_response.exe $(INTDIR)\serf_get.exe \
|
||||
$(INTDIR)\serf_request.exe $(INTDIR)\test_all.exe
|
||||
|
||||
CHECK: $(INTDIR) TESTS
|
||||
$(INTDIR)\serf_response.exe test\testcases\simple.response
|
||||
$(INTDIR)\serf_response.exe test\testcases\chunked-empty.response
|
||||
$(INTDIR)\serf_response.exe test\testcases\chunked.response
|
||||
$(INTDIR)\serf_response.exe test\testcases\chunked-trailers.response
|
||||
$(INTDIR)\serf_response.exe test\testcases\deflate.response
|
||||
$(INTDIR)\test_all.exe
|
||||
|
||||
"$(STATIC_LIB)": $(INTDIR) $(LIB32_OBJS)
|
||||
$(LIB32) -lib @<<
|
||||
$(LIB32_FLAGS) $(LIB32_OBJS) $(SYS_LIBS) /OUT:$@
|
||||
<<
|
||||
|
||||
|
||||
.c{$(INTDIR)}.obj:
|
||||
$(CPP) @<<
|
||||
$(CPP_PROJ) $<
|
||||
<<
|
||||
|
||||
{auth}.c{$(INTDIR)}.obj:
|
||||
$(CPP) @<<
|
||||
$(CPP_PROJ) $<
|
||||
<<
|
||||
|
||||
{buckets}.c{$(INTDIR)}.obj:
|
||||
$(CPP) @<<
|
||||
$(CPP_PROJ) $<
|
||||
<<
|
||||
|
||||
{test}.c{$(INTDIR)}.obj:
|
||||
$(CPP) @<<
|
||||
$(CPP_PROJ) $<
|
||||
<<
|
||||
|
||||
{test\server}.c{$(INTDIR)}.obj:
|
||||
$(CPP) @<<
|
||||
$(CPP_PROJ) $<
|
||||
<<
|
||||
|
||||
$(INTDIR)\serf_response.exe: $(INTDIR)\serf_response.obj $(STATIC_LIB)
|
||||
$(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS)
|
||||
|
||||
$(INTDIR)\serf_get.exe: $(INTDIR)\serf_get.obj $(STATIC_LIB)
|
||||
$(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS)
|
||||
|
||||
$(INTDIR)\serf_request.exe: $(INTDIR)\serf_request.obj $(STATIC_LIB)
|
||||
$(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS)
|
||||
|
||||
$(INTDIR)\test_all.exe: $(TEST_OBJS) $(STATIC_LIB)
|
||||
$(LIB32) /DEBUG /OUT:$@ $** $(LIB32_FLAGS) $(TEST_LIBS)
|
13
serf.pc.in
13
serf.pc.in
@ -1,13 +0,0 @@
|
||||
SERF_MAJOR_VERSION=@SERF_MAJOR_VERSION@
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: serf
|
||||
Description: HTTP client library
|
||||
Version: @SERF_DOTTED_VERSION@
|
||||
Requires.private: libssl libcrypto
|
||||
Libs: -L${libdir} -lserf-${SERF_MAJOR_VERSION}
|
||||
Libs.private: @EXTRA_LIBS@ @SERF_LIBS@ -lz
|
||||
Cflags: -I${includedir}
|
@ -307,6 +307,16 @@ serf_bucket_t *serf_bucket_simple_copy_create(
|
||||
apr_size_t len,
|
||||
serf_bucket_alloc_t *allocator);
|
||||
|
||||
/**
|
||||
* Equivalent to serf_bucket_simple_create, except that the bucket assumes
|
||||
* responsibility for freeing the data on this allocator without making
|
||||
* a copy. It is assumed that data was created by a call from allocator.
|
||||
*/
|
||||
serf_bucket_t *serf_bucket_simple_own_create(
|
||||
const char *data,
|
||||
apr_size_t len,
|
||||
serf_bucket_alloc_t *allocator);
|
||||
|
||||
#define SERF_BUCKET_SIMPLE_STRING(s,a) \
|
||||
serf_bucket_simple_create(s, strlen(s), NULL, NULL, a);
|
||||
|
||||
@ -579,7 +589,7 @@ apr_hash_t *serf_ssl_cert_subject(
|
||||
|
||||
/**
|
||||
* Extract the fields of the certificate in a table with keys (sha1, notBefore,
|
||||
* notAfter). The returned table will be allocated in @a pool.
|
||||
* notAfter, subjectAltName). The returned table will be allocated in @a pool.
|
||||
*/
|
||||
apr_hash_t *serf_ssl_cert_certificate(
|
||||
const serf_ssl_certificate_t *cert,
|
||||
|
@ -148,6 +148,14 @@ char * serf_bstrdup(
|
||||
serf_bucket_alloc_t *allocator,
|
||||
const char *str);
|
||||
|
||||
/**
|
||||
* Analogous to apr_pstrcatv, using a bucket allocator instead.
|
||||
*/
|
||||
char * serf_bstrcatv(
|
||||
serf_bucket_alloc_t *allocator,
|
||||
struct iovec *vec,
|
||||
int vecs,
|
||||
apr_size_t *bytes_written);
|
||||
|
||||
/**
|
||||
* Read data up to a newline.
|
||||
|
@ -26,6 +26,13 @@
|
||||
#define IOV_MAX 16
|
||||
#endif
|
||||
|
||||
/* Older versions of APR do not have this macro. */
|
||||
#ifdef APR_SIZE_MAX
|
||||
#define REQUESTED_MAX APR_SIZE_MAX
|
||||
#else
|
||||
#define REQUESTED_MAX (~((apr_size_t)0))
|
||||
#endif
|
||||
|
||||
#define SERF_IO_CLIENT (1)
|
||||
#define SERF_IO_CONN (2)
|
||||
#define SERF_IO_LISTENER (3)
|
||||
@ -39,6 +46,18 @@
|
||||
#define CONN_VERBOSE 0
|
||||
#define AUTH_VERBOSE 0
|
||||
|
||||
/* Older versions of APR do not have the APR_VERSION_AT_LEAST macro. Those
|
||||
implementations are safe.
|
||||
|
||||
If the macro *is* defined, and we're on WIN32, and APR is version 1.4.0+,
|
||||
then we have a broken WSAPoll() implementation.
|
||||
|
||||
See serf_context_create_ex() below. */
|
||||
#if defined(APR_VERSION_AT_LEAST) && defined(WIN32)
|
||||
#if APR_VERSION_AT_LEAST(1,4,0)
|
||||
#define BROKEN_WSAPOLL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef struct serf__authn_scheme_t serf__authn_scheme_t;
|
||||
|
||||
@ -76,6 +95,8 @@ struct serf_request_t {
|
||||
|
||||
int written;
|
||||
int priority;
|
||||
/* 1 if this is a request to setup a SSL tunnel, 0 for normal requests. */
|
||||
int ssltunnel;
|
||||
|
||||
/* This baton is currently only used for digest authentication, which
|
||||
needs access to the uri of the request in the response handler.
|
||||
@ -93,8 +114,6 @@ typedef struct serf_pollset_t {
|
||||
} serf_pollset_t;
|
||||
|
||||
typedef struct serf__authn_info_t {
|
||||
const char *realm;
|
||||
|
||||
const serf__authn_scheme_t *scheme;
|
||||
|
||||
void *baton;
|
||||
@ -124,8 +143,15 @@ struct serf_context_t {
|
||||
apr_off_t progress_read;
|
||||
apr_off_t progress_written;
|
||||
|
||||
/* authentication info for this context, shared by all connections. */
|
||||
serf__authn_info_t authn_info;
|
||||
/* authentication info for the servers used in this context. Shared by all
|
||||
connections to the same server.
|
||||
Structure of the hashtable: key: host url, e.g. https://localhost:80
|
||||
value: serf__authn_info_t *
|
||||
*/
|
||||
apr_hash_t *server_authn_info;
|
||||
|
||||
/* authentication info for the proxy configured in this context, shared by
|
||||
all connections. */
|
||||
serf__authn_info_t proxy_authn_info;
|
||||
|
||||
/* List of authn types supported by the client.*/
|
||||
@ -158,7 +184,7 @@ typedef enum {
|
||||
SERF_CONN_INIT, /* no socket created yet */
|
||||
SERF_CONN_SETUP_SSLTUNNEL, /* ssl tunnel being setup, no requests sent */
|
||||
SERF_CONN_CONNECTED, /* conn is ready to send requests */
|
||||
SERF_CONN_CLOSING, /* conn is closing, no more requests,
|
||||
SERF_CONN_CLOSING /* conn is closing, no more requests,
|
||||
start a new socket */
|
||||
} serf__connection_state_t;
|
||||
|
||||
@ -232,8 +258,12 @@ struct serf_connection_t {
|
||||
unsigned int max_outstanding_requests;
|
||||
|
||||
int hit_eof;
|
||||
/* Host info. */
|
||||
|
||||
/* Host url, path ommitted, syntax: https://svn.apache.org . */
|
||||
const char *host_url;
|
||||
|
||||
/* Exploded host url, path ommitted. Only scheme, hostinfo, hostname &
|
||||
port values are filled in. */
|
||||
apr_uri_t host_info;
|
||||
|
||||
/* connection and authentication scheme specific information */
|
||||
@ -245,6 +275,9 @@ struct serf_connection_t {
|
||||
|
||||
/* Calculated connection latency. Negative value if latency is unknown. */
|
||||
apr_interval_time_t latency;
|
||||
|
||||
/* Needs to read first before we can write again. */
|
||||
int stop_writing;
|
||||
};
|
||||
|
||||
/*** Internal bucket functions ***/
|
||||
@ -293,7 +326,8 @@ typedef apr_status_t
|
||||
* connection is opened.
|
||||
*/
|
||||
typedef apr_status_t
|
||||
(*serf__init_conn_func_t)(int code,
|
||||
(*serf__init_conn_func_t)(const serf__authn_scheme_t *scheme,
|
||||
int code,
|
||||
serf_connection_t *conn,
|
||||
apr_pool_t *pool);
|
||||
|
||||
@ -329,15 +363,14 @@ typedef apr_status_t
|
||||
* serf__authn_scheme_t: vtable for an authn scheme provider.
|
||||
*/
|
||||
struct serf__authn_scheme_t {
|
||||
/* The http status code that's handled by this authentication scheme.
|
||||
Normal values are 401 for server authentication and 407 for proxy
|
||||
authentication */
|
||||
int code;
|
||||
|
||||
/* The name of this authentication scheme. This should be a case
|
||||
sensitive match of the string sent in the HTTP authentication header. */
|
||||
/* The name of this authentication scheme. Used in headers of requests and
|
||||
for logging. */
|
||||
const char *name;
|
||||
|
||||
/* Key is the name of the authentication scheme in lower case, to
|
||||
facilitate case insensitive matching of the response headers. */
|
||||
const char *key;
|
||||
|
||||
/* Internal code used for this authn type. */
|
||||
int type;
|
||||
|
||||
@ -367,6 +400,14 @@ apr_status_t serf__handle_auth_response(int *consumed_response,
|
||||
void *baton,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* Get the cached serf__authn_info_t object for the target server, or create one
|
||||
when this is the first connection to the server.
|
||||
TODO: The serf__authn_info_t objects are allocated in the context pool, so
|
||||
a context that's used to connect to many different servers using Basic or
|
||||
Digest authencation will hold on to many objects indefinitely. We should be
|
||||
able to cleanup stale objects from time to time. */
|
||||
serf__authn_info_t *serf__get_authn_info_for_server(serf_connection_t *conn);
|
||||
|
||||
/* fromt context.c */
|
||||
void serf__context_progress_delta(void *progress_baton, apr_off_t read,
|
||||
apr_off_t written);
|
||||
@ -380,6 +421,17 @@ apr_status_t serf__open_connections(serf_context_t *ctx);
|
||||
apr_status_t serf__process_connection(serf_connection_t *conn,
|
||||
apr_int16_t events);
|
||||
apr_status_t serf__conn_update_pollset(serf_connection_t *conn);
|
||||
serf_request_t *serf__ssltunnel_request_create(serf_connection_t *conn,
|
||||
serf_request_setup_t setup,
|
||||
void *setup_baton);
|
||||
apr_status_t serf__provide_credentials(serf_context_t *ctx,
|
||||
char **username,
|
||||
char **password,
|
||||
serf_request_t *request,
|
||||
void *baton,
|
||||
int code, const char *authn_type,
|
||||
const char *realm,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* from ssltunnel.c */
|
||||
apr_status_t serf__ssltunnel_connect(serf_connection_t *conn);
|
||||
|
506
serfmake
506
serfmake
@ -1,506 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import stat
|
||||
import copy
|
||||
|
||||
### use get_version() ?
|
||||
MAJOR = 1
|
||||
|
||||
# Basic defines for our outputs.
|
||||
LIBNAME = 'libserf-%d' % (MAJOR,)
|
||||
INCLUDES = 'serf-%d' % (MAJOR,)
|
||||
PCFILE = 'serf-%d' % (MAJOR,)
|
||||
|
||||
|
||||
FILES_HDR = [
|
||||
('.', 'serf'),
|
||||
('.', 'serf_bucket_types'),
|
||||
('.', 'serf_bucket_util'),
|
||||
]
|
||||
|
||||
LIB_FILES = [
|
||||
('.', 'context'),
|
||||
('.', 'incoming'),
|
||||
('.', 'outgoing'),
|
||||
('.', 'ssltunnel'),
|
||||
|
||||
('buckets', 'aggregate_buckets'),
|
||||
('buckets', 'request_buckets'),
|
||||
('buckets', 'buckets'),
|
||||
('buckets', 'simple_buckets'),
|
||||
('buckets', 'file_buckets'),
|
||||
('buckets', 'mmap_buckets'),
|
||||
('buckets', 'socket_buckets'),
|
||||
('buckets', 'response_buckets'),
|
||||
('buckets', 'response_body_buckets'),
|
||||
('buckets', 'headers_buckets'),
|
||||
('buckets', 'allocator'),
|
||||
('buckets', 'dechunk_buckets'),
|
||||
('buckets', 'deflate_buckets'),
|
||||
('buckets', 'limit_buckets'),
|
||||
('buckets', 'ssl_buckets'),
|
||||
('buckets', 'barrier_buckets'),
|
||||
('buckets', 'chunk_buckets'),
|
||||
('buckets', 'iovec_buckets'),
|
||||
('auth', 'auth'),
|
||||
('auth', 'auth_basic'),
|
||||
('auth', 'auth_digest'),
|
||||
('auth', 'auth_kerb'),
|
||||
('auth', 'auth_kerb_gss'),
|
||||
]
|
||||
|
||||
TEST_DEPS = [
|
||||
('test', 'CuTest'),
|
||||
('test', 'test_util'),
|
||||
('test', 'test_context'),
|
||||
('test', 'test_buckets'),
|
||||
('test', 'test_ssl'),
|
||||
('test/server', 'test_server'),
|
||||
('test/server', 'test_sslserver'),
|
||||
]
|
||||
|
||||
TEST_HDR_FILES = [
|
||||
('test', 'CuTest'),
|
||||
('test', 'test_serf'),
|
||||
]
|
||||
|
||||
TEST_FILES = [
|
||||
('test', 'serf_get'),
|
||||
('test', 'serf_response'),
|
||||
('test', 'serf_request'),
|
||||
('test', 'serf_spider'),
|
||||
('test', 'test_all'),
|
||||
]
|
||||
|
||||
TESTCASES = [
|
||||
('test/testcases', 'simple.response'),
|
||||
('test/testcases', 'chunked-empty.response'),
|
||||
('test/testcases', 'chunked.response'),
|
||||
('test/testcases', 'chunked-trailers.response'),
|
||||
('test/testcases', 'deflate.response'),
|
||||
]
|
||||
|
||||
|
||||
def main(argv):
|
||||
params = {}
|
||||
|
||||
commands = []
|
||||
|
||||
for arg in argv[1:]:
|
||||
idx = arg.find('=')
|
||||
if idx > 0:
|
||||
start = arg.rfind('-', 0, idx)
|
||||
if start > 0:
|
||||
params[arg[start+1:idx]] = arg[idx+1:].strip()
|
||||
else:
|
||||
func = globals().get('cmd_' + arg)
|
||||
if func:
|
||||
commands.append(func)
|
||||
else:
|
||||
print('ERROR: unknown argument: ' + arg)
|
||||
usage()
|
||||
|
||||
if not commands:
|
||||
usage()
|
||||
|
||||
for func in commands:
|
||||
try:
|
||||
func(params)
|
||||
except:
|
||||
print('ERROR: exception:')
|
||||
print(sys.exc_info()[1])
|
||||
print("")
|
||||
usage()
|
||||
|
||||
|
||||
def usage():
|
||||
### print something
|
||||
print('serfmake [cmd] [options]')
|
||||
print('Commands:')
|
||||
print('\tbuild\tBuilds (default)')
|
||||
print('\tcheck\tRuns test cases')
|
||||
print('\tinstall\tInstalls serf into PREFIX')
|
||||
print('\tclean\tCleans')
|
||||
print('Options:')
|
||||
print('\t--with-apr=PATH\t\tprefix for installed APR and APR-util')
|
||||
print('\t\t\t\t(needs apr-1-config and apu-1-config; will look in PATH)')
|
||||
print('\t--with-gssapi=PATH\tbuild serf with GSSAPI support')
|
||||
print('\t\t\t\t(needs krb5-config; will look in PATH/bin)')
|
||||
|
||||
print('\t--prefix=PATH\t\tinstall serf into PATH (default: /usr/local)')
|
||||
print('Quick guide:')
|
||||
print('\tserfmake --prefix=/usr/local/serf --with-apr=/usr/local/apr install')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def cmd_build(param):
|
||||
builder = Builder(param)
|
||||
builder.build_target(File('.', LIBNAME, 'la'), False)
|
||||
builder.build_target(File('.', PCFILE, 'pc'), False)
|
||||
|
||||
|
||||
def cmd_install(param):
|
||||
builder = Builder(param)
|
||||
builder.build_target(File('.', PCFILE, 'pc'), False)
|
||||
### should be called .install_all()
|
||||
builder.install_target(File('.', LIBNAME, 'la'), False)
|
||||
|
||||
|
||||
def cmd_check(param):
|
||||
builder = Builder(param)
|
||||
for dirpath, fname in TEST_FILES:
|
||||
builder.build_target(File(dirpath, fname, None), False)
|
||||
|
||||
for dirpath, fname in TESTCASES:
|
||||
case = os.path.join(dirpath, fname)
|
||||
print('== Testing %s ==' % case)
|
||||
result = os.system('%s %s' % (os.path.join('test', 'serf_response'), case))
|
||||
if result:
|
||||
raise TestError("", result)
|
||||
|
||||
# run the test suite based on the CuTest framework
|
||||
result = os.system(os.path.join('test', 'test_all'))
|
||||
if result:
|
||||
raise TestError(case, result)
|
||||
|
||||
def cmd_clean(param):
|
||||
targets = [File(dirpath, fname, 'o') for dirpath, fname in LIB_FILES]
|
||||
targets += [File(dirpath, fname, 'lo') for dirpath, fname in LIB_FILES]
|
||||
targets += [File('.', LIBNAME, 'la'),
|
||||
File('.', PCFILE, 'pc'),
|
||||
]
|
||||
targets += [File(dirpath, fname, 'o') for dirpath, fname in TEST_FILES]
|
||||
targets += [File(dirpath, fname, 'lo') for dirpath, fname in TEST_FILES]
|
||||
targets += [File(dirpath, fname, None) for dirpath, fname in TEST_FILES]
|
||||
targets += [File(dirpath, fname, 'o') for dirpath, fname in TEST_DEPS]
|
||||
targets += [File(dirpath, fname, 'lo') for dirpath, fname in TEST_DEPS]
|
||||
|
||||
clean = [file for file in targets if file.mtime]
|
||||
if clean:
|
||||
sys.stdout.write('Cleaning %d files... ' % len(clean))
|
||||
for i in clean:
|
||||
if i.mtime:
|
||||
os.remove(i.fname)
|
||||
print('done.')
|
||||
else:
|
||||
print('Clean.')
|
||||
|
||||
|
||||
class Builder(object):
|
||||
def __init__(self, params):
|
||||
# use apr option if set
|
||||
if 'apr' in params:
|
||||
self.apr = APRConfig(params['apr'])
|
||||
self.apu = APUConfig(params['apr'])
|
||||
else:
|
||||
self.apr = APRConfig(None)
|
||||
self.apu = APUConfig(None)
|
||||
|
||||
# build with gssapi if option is set
|
||||
if 'gssapi' in params:
|
||||
self.gssapi = GSSAPIConfig(params['gssapi'])
|
||||
else:
|
||||
self.gssapi = None
|
||||
|
||||
try:
|
||||
self.prefix = params['prefix']
|
||||
except:
|
||||
self.prefix = '/usr/local'
|
||||
|
||||
### no way to tweak these
|
||||
self.libdir = os.path.join(self.prefix, 'lib')
|
||||
self.pkgconfigdir = os.path.join(self.prefix, 'lib', 'pkgconfig')
|
||||
self.includedir = os.path.join(self.prefix, 'include', INCLUDES)
|
||||
|
||||
self.load_vars()
|
||||
self.load_deps()
|
||||
|
||||
def load_vars(self):
|
||||
self.CC = self.apr.get_value('CC', '--cc')
|
||||
self.CFLAGS = self.apr.get_value('CFLAGS', '--cflags')
|
||||
self.CPPFLAGS = self.apr.get_value('CPPFLAGS', '--cppflags')
|
||||
self.LIBTOOL = self.apr.get_value('LIBTOOL', '--apr-libtool')
|
||||
self.LDFLAGS = self.apr.get_value('LDFLAGS', '--ldflags') \
|
||||
+ ' ' + self.apu.get_value('LDFLAGS', '--ldflags')
|
||||
|
||||
self.INCLUDES = '-I%s -I%s -I%s' % (
|
||||
'.',
|
||||
self.apr.get_value(None, '--includedir'),
|
||||
self.apu.get_value(None, '--includedir'),
|
||||
)
|
||||
if os.getenv('EXTRA_INCLUDES'):
|
||||
self.INCLUDES += ' -I' + os.getenv('EXTRA_INCLUDES')
|
||||
|
||||
self.LIBS = self.apu.get_value(None, '--link-libtool') \
|
||||
+ ' ' + self.apu.get_value(None, '--libs') \
|
||||
+ ' ' + self.apr.get_value(None, '--link-libtool') \
|
||||
+ ' ' + self.apr.get_value(None, '--libs') \
|
||||
+ ' -lz'
|
||||
self.SSL_LIBS = '-lssl -lcrypto'
|
||||
if self.gssapi:
|
||||
self.LIBS += ' ' + self.gssapi.get_value(None, '--libs gssapi')
|
||||
self.CFLAGS += ' ' + self.gssapi.get_value('CFLAGS', '--cflags gssapi')\
|
||||
+ ' -DSERF_HAVE_GSSAPI -g'
|
||||
|
||||
self.MODE = 644
|
||||
|
||||
def load_deps(self):
|
||||
self.deps = { }
|
||||
|
||||
hdrs = [File(dirpath, fname, 'h') for dirpath, fname in FILES_HDR]
|
||||
libfiles = [File(dirpath, fname, 'c') for dirpath, fname in LIB_FILES]
|
||||
libobjs = [File(dirpath, fname, 'lo') for dirpath, fname in LIB_FILES]
|
||||
for src, obj in zip(libfiles, libobjs):
|
||||
self._add_compile(src, obj, hdrs)
|
||||
|
||||
self.hdrs = hdrs
|
||||
|
||||
all_libs = self.LIBS + ' ' + self.SSL_LIBS
|
||||
|
||||
lib = File('.', LIBNAME, 'la')
|
||||
cmd = '%s --silent --mode=link %s %s -rpath %s -o %s %s %s' % (
|
||||
self.LIBTOOL, self.CC, self.LDFLAGS, self.libdir,
|
||||
lib.fname, ' '.join([l.fname for l in libobjs]), all_libs)
|
||||
self._add_dep(lib, libobjs, cmd)
|
||||
|
||||
# load the test program dependencies now
|
||||
testhdrs = copy.deepcopy(hdrs)
|
||||
testhdrs += [File(dirpath, fname, 'h') for dirpath, fname in TEST_HDR_FILES]
|
||||
testdeps = [File(dirpath, fname, 'c') for dirpath, fname in TEST_DEPS]
|
||||
testobjs = [File(dirpath, fname, 'lo') for dirpath, fname in TEST_DEPS]
|
||||
|
||||
for testsrc, testobj in zip(testdeps, testobjs):
|
||||
self._add_compile(testsrc, testobj, testhdrs)
|
||||
|
||||
for dirpath, fname in TEST_FILES:
|
||||
src = File(dirpath, fname, 'c')
|
||||
obj = File(dirpath, fname, 'lo')
|
||||
prog = File(dirpath, fname, None)
|
||||
|
||||
self._add_compile(src, obj, hdrs)
|
||||
|
||||
# test_all requires extra dependencies
|
||||
if fname == "test_all":
|
||||
cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % (
|
||||
self.LIBTOOL, self.CC, self.LDFLAGS,
|
||||
prog.fname, lib.fname, ' '.join([l.fname for l in [obj] + testobjs]),
|
||||
all_libs)
|
||||
self._add_dep(prog, [lib, obj] + testobjs, cmd)
|
||||
else:
|
||||
cmd = '%s --silent --mode=link %s %s -static -o %s %s %s %s' % (
|
||||
self.LIBTOOL, self.CC, self.LDFLAGS,
|
||||
prog.fname, lib.fname, obj.fname, all_libs)
|
||||
self._add_dep(prog, [lib, obj], cmd)
|
||||
|
||||
# create 'serf-1.pc' if it doesn't exist.
|
||||
pcfile = File('.', PCFILE, 'pc')
|
||||
self._add_dep(pcfile, [], self._write_pcfile)
|
||||
|
||||
def _add_compile(self, src, obj, hdrs):
|
||||
cmd = '%s --silent --mode=compile %s %s %s %s -c -o %s %s' % (
|
||||
self.LIBTOOL, self.CC, self.CFLAGS, self.CPPFLAGS, self.INCLUDES,
|
||||
obj.fname, src.fname)
|
||||
self._add_dep(obj, [src] + hdrs, cmd)
|
||||
|
||||
def _add_dep(self, target, deps, cmd):
|
||||
if target.mtime:
|
||||
for dep in deps:
|
||||
if dep in self.deps or (dep.mtime and dep.mtime > target.mtime):
|
||||
# a dep is newer. this needs to be rebuilt.
|
||||
break
|
||||
else:
|
||||
# this is up to date. don't add it to the deps[] structure.
|
||||
return
|
||||
# else non-existent, so it must be rebuilt.
|
||||
|
||||
# Commands that are strings are cmdline invocations. Otherwise, it
|
||||
# should be a callable.
|
||||
if isinstance(cmd, str):
|
||||
cmd = CommandLine(cmd)
|
||||
|
||||
# register the dependency so this will get built
|
||||
self.deps[target] = deps, cmd
|
||||
|
||||
def _write_pcfile(self):
|
||||
"""Generating serf-1.pc ..."""
|
||||
|
||||
open(PCFILE + '.pc', 'w').write(
|
||||
"""SERF_MAJOR_VERSION=%d
|
||||
prefix=%s
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
includedir=${prefix}/include/%s
|
||||
|
||||
Name: serf
|
||||
Description: HTTP client library
|
||||
Version: %s
|
||||
Requires.private: libssl libcrypto
|
||||
Libs: -L${libdir} -lserf-${SERF_MAJOR_VERSION}
|
||||
Libs.private: %s
|
||||
Cflags: -I${includedir}
|
||||
""" % (MAJOR, self.prefix, INCLUDES, get_version(), self.LIBS))
|
||||
|
||||
def build_target(self, target, dry_run):
|
||||
deps, cmd = self.deps.get(target, (None, None))
|
||||
if cmd is None:
|
||||
# it's already up to date. all done.
|
||||
return
|
||||
|
||||
for f in deps:
|
||||
subdep = self.deps.get(f)
|
||||
if subdep:
|
||||
self.build_target(f, dry_run)
|
||||
|
||||
# build the target now
|
||||
print(cmd.__doc__)
|
||||
if not dry_run:
|
||||
result = cmd()
|
||||
if result:
|
||||
raise BuildError(cmd.__doc__, result)
|
||||
# FALLTHROUGH
|
||||
|
||||
# it's a dry run. pretend we built the target.
|
||||
del self.deps[target]
|
||||
return 0
|
||||
|
||||
def install_target(self, target, dry_run):
|
||||
self.build_target(target, dry_run)
|
||||
|
||||
# install the target now
|
||||
if not dry_run:
|
||||
|
||||
for path in (self.libdir, self.pkgconfigdir, self.includedir):
|
||||
if not os.path.exists(path):
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError:
|
||||
raise BuildError('os.makedirs',
|
||||
'can not create install directories')
|
||||
|
||||
for f in self.hdrs:
|
||||
print("Installing: %s" % (os.path.basename(f.fname),))
|
||||
shutil.copy(f.fname, self.includedir)
|
||||
|
||||
print("Installing: %s.pc" % (PCFILE,))
|
||||
shutil.copy(PCFILE + '.pc', self.pkgconfigdir)
|
||||
|
||||
cmd = '%s --silent --mode=install %s -c -m %d %s %s' % (
|
||||
self.LIBTOOL, '/usr/bin/install', self.MODE, target.fname,
|
||||
self.libdir)
|
||||
|
||||
print("Installing: %s" % (os.path.basename(target.fname),))
|
||||
result = os.system(cmd)
|
||||
if result:
|
||||
raise BuildError(cmd, result)
|
||||
# FALLTHROUGH
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
class ConfigScript(object):
|
||||
script_name = None
|
||||
locations = [
|
||||
'/usr/bin',
|
||||
'/usr/local/bin',
|
||||
'/usr/local/apache2/bin',
|
||||
]
|
||||
|
||||
def __init__(self, search_dir):
|
||||
if search_dir:
|
||||
locations = [search_dir, os.path.join(search_dir, 'bin')]
|
||||
else:
|
||||
locations = self.locations
|
||||
|
||||
for dirname in locations:
|
||||
bin = os.path.join(dirname, self.script_name)
|
||||
if os.access(bin, os.X_OK):
|
||||
self.bin = bin
|
||||
break
|
||||
else:
|
||||
raise ConfigScriptNotFound(self.script_name)
|
||||
|
||||
def get_value(self, env_name, switch):
|
||||
if env_name and os.getenv(env_name):
|
||||
return os.getenv(env_name)
|
||||
return os.popen('%s %s' % (self.bin, switch), 'r').read().strip()
|
||||
|
||||
|
||||
class APRConfig(ConfigScript):
|
||||
script_name = 'apr-1-config'
|
||||
|
||||
|
||||
class APUConfig(ConfigScript):
|
||||
script_name = 'apu-1-config'
|
||||
|
||||
|
||||
class GSSAPIConfig(ConfigScript):
|
||||
script_name = 'krb5-config'
|
||||
|
||||
|
||||
class CommandLine(object):
|
||||
"""Simple helper to invoke a system command when called."""
|
||||
|
||||
def __init__(self, cmd):
|
||||
self.cmd = cmd
|
||||
self.__doc__ = cmd # when we print the execution of this command
|
||||
|
||||
def __call__(self):
|
||||
return os.system(self.cmd)
|
||||
|
||||
|
||||
class File:
|
||||
def __init__(self, dirpath, fname, ext):
|
||||
if ext:
|
||||
self.fname = os.path.join(dirpath, fname + '.' + ext)
|
||||
else:
|
||||
self.fname = os.path.join(dirpath, fname)
|
||||
|
||||
try:
|
||||
s = os.stat(self.fname)
|
||||
except OSError:
|
||||
self.mtime = None
|
||||
else:
|
||||
self.mtime = s[stat.ST_MTIME]
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.fname == other.fname
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.fname)
|
||||
|
||||
|
||||
def get_version():
|
||||
match = re.search('SERF_MAJOR_VERSION ([0-9]+).*'
|
||||
'SERF_MINOR_VERSION ([0-9]+).*'
|
||||
'SERF_PATCH_VERSION ([0-9]+)',
|
||||
open('serf.h').read(),
|
||||
re.DOTALL)
|
||||
major, minor, patch = match.groups()
|
||||
return '%s.%s.%s' % (major, minor, patch)
|
||||
|
||||
|
||||
class BuildError(Exception):
|
||||
"An error occurred while building a target."
|
||||
class TestError(Exception):
|
||||
"An error occurred while running a unit test."
|
||||
class ConfigScriptNotFound(Exception):
|
||||
def __init__(self, value):
|
||||
self.value = "ERROR: A configuration script was not found: " + value
|
||||
def __str__(self):
|
||||
return self.value
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main(sys.argv)
|
||||
|
||||
|
||||
###
|
||||
### TODO:
|
||||
### * obey DESTDIR
|
||||
### * arfrever says LDFLAGS is passed twice
|
||||
### * be able to specify libdir and includedir
|
||||
###
|
@ -159,17 +159,16 @@ apr_status_t serf__ssltunnel_connect(serf_connection_t *conn)
|
||||
|
||||
ctx = apr_palloc(ssltunnel_pool, sizeof(*ctx));
|
||||
ctx->pool = ssltunnel_pool;
|
||||
ctx->uri = apr_psprintf(ctx->pool, "%s:%d", conn->host_info.hostinfo,
|
||||
ctx->uri = apr_psprintf(ctx->pool, "%s:%d", conn->host_info.hostname,
|
||||
conn->host_info.port);
|
||||
|
||||
conn->ssltunnel_ostream = serf__bucket_stream_create(conn->allocator,
|
||||
detect_eof,
|
||||
conn);
|
||||
|
||||
/* TODO: should be the first request on the connection. */
|
||||
serf_connection_priority_request_create(conn,
|
||||
setup_request,
|
||||
ctx);
|
||||
serf__ssltunnel_request_create(conn,
|
||||
setup_request,
|
||||
ctx);
|
||||
|
||||
conn->state = SERF_CONN_SETUP_SSLTUNNEL;
|
||||
serf__log(CONN_VERBOSE, __FILE__,
|
||||
|
Loading…
Reference in New Issue
Block a user