v1.7
This commit is contained in:
parent
aa8ca77702
commit
07c5291f07
9
AUTHORS
9
AUTHORS
@ -2,3 +2,12 @@ AUTHORS
|
||||
=======
|
||||
Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
|
||||
Binary distributions
|
||||
--------------------
|
||||
Binary distributions of E-MailRelay may include code from:
|
||||
* OpenSSL Toolkit (http://www.openssl.org)
|
||||
* MinGW (http://www.mingw.org)
|
||||
* Trolltech Qt (http://trolltech.com)
|
||||
|
||||
This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
|
||||
|
@ -1,6 +1,14 @@
|
||||
E-MailRelay Change Log
|
||||
======================
|
||||
|
||||
1.6 -> 1.7
|
||||
----------
|
||||
* TLS/SSL support for SMTP using OpenSSL ("./configure --with-openssl" with "--client-tls" and "--server-tls").
|
||||
* Authentication mechanism "PLAIN" added.
|
||||
* Some tightening up of the SMTP server protocol.
|
||||
* Windows service wrapper has an "--uninstall" option.
|
||||
* Windows installation GUI uninstalls the service before reinstalling it.
|
||||
|
||||
1.5 -> 1.6
|
||||
----------
|
||||
* GPLv3 licence (see "http://gplv3.fsf.org").
|
||||
|
93
LICENSE
Normal file
93
LICENSE
Normal file
@ -0,0 +1,93 @@
|
||||
Licenses
|
||||
========
|
||||
|
||||
Source distributions
|
||||
--------------------
|
||||
Permission to copy E-MailRelay is under the terms of the GPLv3 license. The text
|
||||
of the license is in the file "COPYING".
|
||||
|
||||
Binary distributions
|
||||
--------------------
|
||||
Binary distributions of E-MailRelay may also include code from:
|
||||
* OpenSSL Toolkit (http://www.openssl.org)
|
||||
* MinGW (http://www.mingw.org)
|
||||
* Trolltech Qt (http://trolltech.com)
|
||||
|
||||
OpenSSL
|
||||
-------
|
||||
This product includes software developed by the OpenSSL Project
|
||||
for use in the OpenSSL Toolkit. (http://www.openssl.org/)
|
||||
|
||||
OpenSSL is dual-licensed, including the following:
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
MinGW
|
||||
-----
|
||||
The MinGW runtime that is included in the Windows binary distributions of
|
||||
E-MailRelay is uncopyrighted and in the public domain.
|
||||
|
||||
Trolltech Qt
|
||||
------------
|
||||
The Qt runtime that is included in the Windows binary distributions of
|
||||
E-MailRelay is dual-licensed, including the GPLv2 (see http://www.gnu.org).
|
||||
E-MailRelay is not a derived work and so the terms of the GPLv2 only apply to
|
||||
the Qt runtime files within the E-MailRelay binary distribution.
|
||||
|
||||
The Qt GUI Toolkit is Copyright (C) 1994-2006 Trolltech ASA.
|
||||
|
||||
Qt source code is available from the Trolltech web site,
|
||||
http://trolltech.com.
|
||||
|
@ -14,7 +14,7 @@
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
EXTRA_DIST = emailrelay.spec ChangeLog README.windows
|
||||
EXTRA_DIST = emailrelay.spec ChangeLog README.windows LICENSE
|
||||
SUBDIRS = src bin lib etc doc test
|
||||
e_doc_DATA = NEWS README ChangeLog
|
||||
uninstall-local:
|
||||
|
@ -136,6 +136,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
@ -190,7 +194,7 @@ top_srcdir = @top_srcdir@
|
||||
|
||||
#
|
||||
#
|
||||
EXTRA_DIST = emailrelay.spec ChangeLog README.windows
|
||||
EXTRA_DIST = emailrelay.spec ChangeLog README.windows LICENSE
|
||||
SUBDIRS = src bin lib etc doc test
|
||||
e_doc_DATA = NEWS README ChangeLog
|
||||
all: config.h
|
||||
|
187
acinclude.m4
187
acinclude.m4
@ -15,19 +15,18 @@ dnl along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
dnl ===
|
||||
|
||||
dnl socketlen_t
|
||||
dnl derived from lars brinkhoff...
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_TYPE_SOCKLEN_T],
|
||||
[AC_CACHE_CHECK([for socklen_t], aclocal_cv_type_socklen_t,
|
||||
[AC_CACHE_CHECK([for socklen_t],[aclocal_type_socklen_t],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <sys/socket.h>],
|
||||
[socklen_t len = 42; return len;],
|
||||
aclocal_cv_type_socklen_t=yes,
|
||||
aclocal_cv_type_socklen_t=no )
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/socket.h>]],
|
||||
[[socklen_t len = 42; return len;]])],
|
||||
aclocal_type_socklen_t=yes,
|
||||
aclocal_type_socklen_t=no )
|
||||
])
|
||||
if test $aclocal_cv_type_socklen_t = yes; then
|
||||
if test $aclocal_type_socklen_t = yes; then
|
||||
AC_DEFINE(HAVE_SOCKLEN_T, 1,[Define to 1 if socklen_t type definition in sys/socket.h])
|
||||
else
|
||||
AC_DEFINE(HAVE_SOCKLEN_T, 0,[Define to 1 if socklen_t type definition in sys/socket.h])
|
||||
@ -37,18 +36,18 @@ AC_DEFUN([ACLOCAL_TYPE_SOCKLEN_T],
|
||||
dnl ipv6
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_IPV6],
|
||||
[AC_CACHE_CHECK([for ipv6], aclocal_cv_ipv6,
|
||||
[AC_CACHE_CHECK([for ipv6],[aclocal_ipv6],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>],
|
||||
[sockaddr_in6 * p = 0;],
|
||||
aclocal_cv_ipv6=yes ,
|
||||
aclocal_cv_ipv6=no )
|
||||
#include <arpa/inet.h>]],
|
||||
[[sockaddr_in6 * p = 0;]])],
|
||||
aclocal_ipv6=yes ,
|
||||
aclocal_ipv6=no )
|
||||
])
|
||||
if test $aclocal_cv_ipv6 = yes; then
|
||||
if test $aclocal_ipv6 = yes; then
|
||||
AC_DEFINE(HAVE_IPV6,1,[Define to 1 if ipv6 is available])
|
||||
else
|
||||
AC_DEFINE(HAVE_IPV6,0,[Define to 1 if ipv6 is available])
|
||||
@ -58,19 +57,19 @@ AC_DEFUN([ACLOCAL_CHECK_IPV6],
|
||||
dnl getipnodebyname for ipv6 rfc2553
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_GETIPNODEBYNAME],
|
||||
[AC_CACHE_CHECK([for getipnodebyname], aclocal_cv_getipnodebyname,
|
||||
[AC_CACHE_CHECK([for getipnodebyname],[aclocal_getipnodebyname],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>],
|
||||
[int i=0; getipnodebyname("",AF_INET6,AI_DEFAULT,&i);],
|
||||
aclocal_cv_getipnodebyname=yes ,
|
||||
aclocal_cv_getipnodebyname=no )
|
||||
#include <netdb.h>]],
|
||||
[[int i=0; getipnodebyname("",AF_INET6,AI_DEFAULT,&i);]])],
|
||||
aclocal_getipnodebyname=yes ,
|
||||
aclocal_getipnodebyname=no )
|
||||
])
|
||||
if test $aclocal_cv_getipnodebyname = yes; then
|
||||
if test $aclocal_getipnodebyname = yes; then
|
||||
AC_DEFINE(HAVE_GETIPNODEBYNAME,1,[Define to 1 if getipnodebyname() is available])
|
||||
else
|
||||
AC_DEFINE(HAVE_GETIPNODEBYNAME,0,[Define to 1 if getipnodebyname() is available])
|
||||
@ -80,17 +79,17 @@ AC_DEFUN([ACLOCAL_CHECK_GETIPNODEBYNAME],
|
||||
dnl check for sin6_len in sockaddr_in6
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_SIN6_LEN],
|
||||
[AC_CACHE_CHECK([for sin6_len], aclocal_cv_sin6_len,
|
||||
[AC_CACHE_CHECK([for sin6_len],[aclocal_sin6_len],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>],
|
||||
[struct sockaddr_in6 s; s.sin6_len = 1;],
|
||||
aclocal_cv_sin6_len=yes ,
|
||||
aclocal_cv_sin6_len=no )
|
||||
#include <netinet/in.h>]],
|
||||
[[struct sockaddr_in6 s; s.sin6_len = 1;]])],
|
||||
aclocal_sin6_len=yes ,
|
||||
aclocal_sin6_len=no )
|
||||
])
|
||||
if test $aclocal_cv_sin6_len = yes; then
|
||||
if test $aclocal_sin6_len = yes; then
|
||||
AC_DEFINE(HAVE_SIN6_LEN,1,[Define to 1 if sockaddr_in6 has a sin6_len member])
|
||||
else
|
||||
AC_DEFINE(HAVE_SIN6_LEN,0,[Define to 1 if sockaddr_in6 has a sin6_len member])
|
||||
@ -100,17 +99,17 @@ AC_DEFUN([ACLOCAL_CHECK_SIN6_LEN],
|
||||
dnl setgroups
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_SETGROUPS],
|
||||
[AC_CACHE_CHECK([for setgroups], aclocal_cv_setgroups,
|
||||
[AC_CACHE_CHECK([for setgroups],[aclocal_setgroups],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <grp.h>],
|
||||
[setgroups(0,0) ;],
|
||||
aclocal_cv_setgroups=yes ,
|
||||
aclocal_cv_setgroups=no )
|
||||
#include <grp.h>]],
|
||||
[[setgroups(0,0) ;]])],
|
||||
aclocal_setgroups=yes ,
|
||||
aclocal_setgroups=no )
|
||||
])
|
||||
if test $aclocal_cv_setgroups = yes; then
|
||||
if test $aclocal_setgroups = yes; then
|
||||
AC_DEFINE(HAVE_SETGROUPS,1,[Define to 1 if setgroups is available])
|
||||
else
|
||||
AC_DEFINE(HAVE_SETGROUPS,0,[Define to 1 if setgroups is available])
|
||||
@ -120,15 +119,15 @@ AC_DEFUN([ACLOCAL_CHECK_SETGROUPS],
|
||||
dnl gmtime_r
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_GMTIME_R],
|
||||
[AC_CACHE_CHECK([for gmtime_r], aclocal_cv_gmtime_r,
|
||||
[AC_CACHE_CHECK([for gmtime_r],[aclocal_gmtime_r],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <time.h>],
|
||||
[gmtime_r((time_t*)0,(struct tm*)0) ;],
|
||||
aclocal_cv_gmtime_r=yes ,
|
||||
aclocal_cv_gmtime_r=no )
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <time.h>]],
|
||||
[[gmtime_r((time_t*)0,(struct tm*)0) ;]])],
|
||||
aclocal_gmtime_r=yes ,
|
||||
aclocal_gmtime_r=no )
|
||||
])
|
||||
if test $aclocal_cv_gmtime_r = yes; then
|
||||
if test $aclocal_gmtime_r = yes; then
|
||||
AC_DEFINE(HAVE_GMTIME_R,1,[Define to 1 if gmtime_r in time.h])
|
||||
else
|
||||
AC_DEFINE(HAVE_GMTIME_R,0,[Define to 1 if gmtime_r in time.h])
|
||||
@ -138,15 +137,15 @@ AC_DEFUN([ACLOCAL_CHECK_GMTIME_R],
|
||||
dnl localtime_r
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_LOCALTIME_R],
|
||||
[AC_CACHE_CHECK([for localtime_r], aclocal_cv_localtime_r,
|
||||
[AC_CACHE_CHECK([for localtime_r],[aclocal_localtime_r],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <time.h>],
|
||||
[localtime_r((time_t*)0,(struct tm*)0) ;],
|
||||
aclocal_cv_localtime_r=yes ,
|
||||
aclocal_cv_localtime_r=no )
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <time.h>]],
|
||||
[[localtime_r((time_t*)0,(struct tm*)0) ;]])],
|
||||
aclocal_localtime_r=yes ,
|
||||
aclocal_localtime_r=no )
|
||||
])
|
||||
if test $aclocal_cv_localtime_r = yes; then
|
||||
if test $aclocal_localtime_r = yes; then
|
||||
AC_DEFINE(HAVE_LOCALTIME_R,1,[Define to 1 if localtime_r in time.h])
|
||||
else
|
||||
AC_DEFINE(HAVE_LOCALTIME_R,0,[Define to 1 if localtime_r in time.h])
|
||||
@ -157,16 +156,16 @@ dnl buggy ctime
|
||||
dnl sunpro5 ctime + unistd.h doesnt compile -- fix with time.h first
|
||||
dnl
|
||||
AC_DEFUN([ACLOCAL_CHECK_BUGGY_CTIME],
|
||||
[AC_CACHE_CHECK([for buggy ctime], aclocal_cv_buggy_ctime,
|
||||
[AC_CACHE_CHECK([for buggy ctime],[aclocal_buggy_ctime],
|
||||
[
|
||||
AC_TRY_COMPILE(
|
||||
[#include <ctime>
|
||||
#include <unistd.h>],
|
||||
[] ,
|
||||
aclocal_cv_buggy_ctime=no ,
|
||||
aclocal_cv_buggy_ctime=yes )
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <ctime>
|
||||
#include <unistd.h>]],
|
||||
[[ ]])] ,
|
||||
aclocal_buggy_ctime=no ,
|
||||
aclocal_buggy_ctime=yes )
|
||||
])
|
||||
if test $aclocal_cv_buggy_ctime = yes; then
|
||||
if test $aclocal_buggy_ctime = yes; then
|
||||
AC_DEFINE(HAVE_BUGGY_CTIME,1,[Define to 1 if <ctime> requires <time.h>])
|
||||
else
|
||||
AC_DEFINE(HAVE_BUGGY_CTIME,0,[Define to 1 if <ctime> requires <time.h>])
|
||||
@ -243,9 +242,9 @@ AC_DEFUN([ENABLE_IPV6],
|
||||
[
|
||||
if test "$enable_ipv6" = "yes"
|
||||
then
|
||||
if test "$aclocal_cv_ipv6" != "yes"
|
||||
if test "$aclocal_ipv6" != "yes"
|
||||
then
|
||||
AC_MSG_WARN(ignoring --enable-ipv6)
|
||||
AC_MSG_WARN([ignoring --enable-ipv6])
|
||||
IP="ipv4"
|
||||
else
|
||||
IP="ipv6"
|
||||
@ -256,6 +255,60 @@ fi
|
||||
AC_SUBST(IP)
|
||||
])
|
||||
|
||||
dnl with-openssl
|
||||
dnl
|
||||
AC_DEFUN([WITH_OPENSSL],
|
||||
if test "$with_openssl" != "no"
|
||||
then
|
||||
[AC_CACHE_CHECK([for openssl],[aclocal_openssl],
|
||||
[
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[#include <openssl/ssl.h>]],
|
||||
[[SSL_CTX * p = 0 ; return 1;]])],
|
||||
aclocal_openssl=yes,
|
||||
aclocal_openssl=no )
|
||||
])
|
||||
if test "$aclocal_openssl" = "yes"
|
||||
then
|
||||
AC_DEFINE(HAVE_OPENSSL,1,[Define to 1 to enable tls/ssh code using openssl])
|
||||
SSL_LIBS="-lssl -lcrypto"
|
||||
SSL="openssl"
|
||||
else
|
||||
if test "$with_openssl" = "yes"
|
||||
then
|
||||
AC_MSG_WARN([ignoring --with-openssl, check config.log and try setting CFLAGS])
|
||||
fi
|
||||
AC_DEFINE(HAVE_OPENSSL,0,[Define to 1 to enable tls/ssh code using openssl])
|
||||
SSL_LIBS=""
|
||||
SSL="none"
|
||||
fi
|
||||
else
|
||||
AC_DEFINE(HAVE_OPENSSL,0,[Define to 1 to enable tls/ssh code using openssl])
|
||||
SSL_LIBS=""
|
||||
SSL="none"
|
||||
fi
|
||||
AC_SUBST(SSL_LIBS)
|
||||
AC_SUBST(SSL)
|
||||
])
|
||||
|
||||
dnl enable-static-linking
|
||||
dnl
|
||||
dnl TODO remove -ldl
|
||||
dnl
|
||||
AC_DEFUN([ENABLE_STATIC_LINKING],
|
||||
[
|
||||
if test "$enable_static_linking" = "yes"
|
||||
then
|
||||
STATIC_START="-Xlinker -Bstatic"
|
||||
STATIC_END="-Xlinker -Bdynamic -ldl"
|
||||
else
|
||||
STATIC_START=""
|
||||
STATIC_END=""
|
||||
fi
|
||||
AC_SUBST(STATIC_START)
|
||||
AC_SUBST(STATIC_END)
|
||||
])
|
||||
|
||||
dnl with-workshop
|
||||
dnl
|
||||
AC_DEFUN([WITH_WORKSHOP],
|
||||
@ -276,7 +329,7 @@ if test "$with_doxygen" != ""
|
||||
then
|
||||
if test "$with_doxygen" = "yes" -a "$HAVE_DOXYGEN" != "yes"
|
||||
then
|
||||
AC_MSG_WARN(ignoring --with-doxygen)
|
||||
AC_MSG_WARN([ignoring --with-doxygen])
|
||||
else
|
||||
HAVE_DOXYGEN="$with_doxygen"
|
||||
AC_SUBST(HAVE_DOXYGEN)
|
||||
@ -292,7 +345,7 @@ if test "$with_man2html" != ""
|
||||
then
|
||||
if test "$with_man2html" = "yes" -a "$HAVE_MAN2HTML" != "yes"
|
||||
then
|
||||
AC_MSG_WARN(ignoring --with-man2html)
|
||||
AC_MSG_WARN([ignoring --with-man2html])
|
||||
else
|
||||
HAVE_MAN2HTML="$with_man2html"
|
||||
AC_SUBST(HAVE_MAN2HTML)
|
||||
|
@ -15,8 +15,8 @@
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
EXTRA_DIST = emailrelay.sh_ txt2html.sh_ txt2mu.sh_ mu2html.sh_ mu2docbook.sh_ expand.sh_ emailrelay-notify.sh_ emailrelay-resubmit.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ emailrelay-runperl.js emailrelay-resubmit.js emailrelay-submit.sh_
|
||||
work_scripts = txt2mu.sh mu2html.sh mu2docbook.sh expand.sh txt2html.sh emailrelay.sh
|
||||
EXTRA_DIST = emailrelay.sh_ doxygen.sh_ txt2html.sh_ txt2mu.sh_ mu2html.sh_ mu2docbook.sh_ expand.sh_ emailrelay-notify.sh_ emailrelay-resubmit.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ emailrelay-runperl.js emailrelay-resubmit.js emailrelay-submit.sh_
|
||||
work_scripts = doxygen.sh txt2mu.sh mu2html.sh mu2docbook.sh expand.sh txt2html.sh emailrelay.sh
|
||||
noinst_SCRIPTS = emailrelay-runperl.js emailrelay-resubmit.js $(work_scripts)
|
||||
e_init_SCRIPTS = emailrelay
|
||||
e_examples_DATA = emailrelay-process.sh emailrelay-notify.sh emailrelay-deliver.sh emailrelay-resubmit.sh emailrelay-submit.sh
|
||||
|
@ -116,6 +116,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
@ -167,8 +171,8 @@ sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
EXTRA_DIST = emailrelay.sh_ txt2html.sh_ txt2mu.sh_ mu2html.sh_ mu2docbook.sh_ expand.sh_ emailrelay-notify.sh_ emailrelay-resubmit.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ emailrelay-runperl.js emailrelay-resubmit.js emailrelay-submit.sh_
|
||||
work_scripts = txt2mu.sh mu2html.sh mu2docbook.sh expand.sh txt2html.sh emailrelay.sh
|
||||
EXTRA_DIST = emailrelay.sh_ doxygen.sh_ txt2html.sh_ txt2mu.sh_ mu2html.sh_ mu2docbook.sh_ expand.sh_ emailrelay-notify.sh_ emailrelay-resubmit.sh_ emailrelay-deliver.sh_ emailrelay-process.sh_ emailrelay-runperl.js emailrelay-resubmit.js emailrelay-submit.sh_
|
||||
work_scripts = doxygen.sh txt2mu.sh mu2html.sh mu2docbook.sh expand.sh txt2html.sh emailrelay.sh
|
||||
noinst_SCRIPTS = emailrelay-runperl.js emailrelay-resubmit.js $(work_scripts)
|
||||
e_init_SCRIPTS = emailrelay
|
||||
e_examples_DATA = emailrelay-process.sh emailrelay-notify.sh emailrelay-deliver.sh emailrelay-resubmit.sh emailrelay-submit.sh
|
||||
|
41
bin/doxygen.sh_
Normal file
41
bin/doxygen.sh_
Normal file
@ -0,0 +1,41 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===
|
||||
#
|
||||
# doxygen.sh
|
||||
#
|
||||
# Used by doc/Makefile to run doxygen with a bit of
|
||||
# post-processing.
|
||||
#
|
||||
# usage: doxygen <have-doxygen> <top-srcdir> <top-builddir>
|
||||
#
|
||||
|
||||
HAVE_DOXYGEN="$1"
|
||||
top_srcdir="$2"
|
||||
top_builddir="$3"
|
||||
|
||||
if test "$HAVE_DOXYGEN" = "yes" -o -z "$HAVE_DOXYGEN"
|
||||
then
|
||||
cat "${top_srcdir}/src/main/doxygen.cfg" | \
|
||||
sed "s:__TOP_SRC__:${top_srcdir}:g" | \
|
||||
sed "s:__TOP_BUILD__:${top_builddir}:g" | \
|
||||
doxygen -
|
||||
else
|
||||
mkdir doxygen 2>/dev/null
|
||||
cp -f "${top_srcdir}/doc/doxygen_missing.html" doxygen/index.html
|
||||
fi
|
||||
|
@ -113,7 +113,7 @@ do
|
||||
# deliver the notification using procmail
|
||||
#
|
||||
echo `basename $0`: delivering `basename ${content}` to ${deliver_to}
|
||||
${procmail} -d ${deliver_to} < ${tmp}
|
||||
${procmail} -d "${deliver_to}" < ${tmp}
|
||||
rc=$?
|
||||
|
||||
# clean up
|
||||
|
@ -52,8 +52,8 @@ do
|
||||
failures="`fgrep MailRelay-Reason: < ${file} | wc -l`"
|
||||
if test "${failures}" -lt "${retry_limit}"
|
||||
then
|
||||
good_file="`echo ${file} | sed 's/\.bad$//'`"
|
||||
mv -f ${file} ${good_file}
|
||||
good_file="`echo \"${file}\" | sed 's/\.bad$//'`"
|
||||
mv -f "${file}" "${good_file}"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
@ -34,6 +34,9 @@
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define to 1 to enable tls/ssh code using openssl */
|
||||
#undef HAVE_OPENSSL
|
||||
|
||||
/* Define to 1 if setgroups is available */
|
||||
#undef HAVE_SETGROUPS
|
||||
|
||||
|
230
configure
vendored
230
configure
vendored
@ -714,6 +714,10 @@ QT_LIBS
|
||||
MOC
|
||||
GUI_TRUE
|
||||
GUI_FALSE
|
||||
SSL_LIBS
|
||||
SSL
|
||||
STATIC_START
|
||||
STATIC_END
|
||||
e_docdir
|
||||
e_initdir
|
||||
e_spooldir
|
||||
@ -1321,6 +1325,8 @@ Optional Features:
|
||||
--enable-ipv6 enable ipv6 (default disabled)
|
||||
--enable-gui enable configuration gui (requires Qt4) (default
|
||||
auto)
|
||||
--enable-static-linking prefer static linking for some libraries (default
|
||||
no)
|
||||
--enable-fhs force FHS-compliant directories, ignoring --prefix
|
||||
etc (default disabled)
|
||||
|
||||
@ -1333,6 +1339,8 @@ Optional Packages:
|
||||
(default auto)
|
||||
--with-man2html convert man pages to html using man2html (default
|
||||
auto)
|
||||
--with-openssl use openssl for smtp client tls extension (default
|
||||
auto)
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
@ -2108,7 +2116,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=emailrelay
|
||||
VERSION=1.6
|
||||
VERSION=1.7
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@ -5987,7 +5995,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for socklen_t" >&5
|
||||
echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_type_socklen_t+set}" = set; then
|
||||
if test "${aclocal_type_socklen_t+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6024,20 +6032,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_type_socklen_t=yes
|
||||
aclocal_type_socklen_t=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_type_socklen_t=no
|
||||
aclocal_type_socklen_t=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_type_socklen_t" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_type_socklen_t" >&6; }
|
||||
if test $aclocal_cv_type_socklen_t = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_type_socklen_t" >&5
|
||||
echo "${ECHO_T}$aclocal_type_socklen_t" >&6; }
|
||||
if test $aclocal_type_socklen_t = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_SOCKLEN_T 1
|
||||
@ -6053,7 +6061,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for ipv6" >&5
|
||||
echo $ECHO_N "checking for ipv6... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_ipv6+set}" = set; then
|
||||
if test "${aclocal_ipv6+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6092,20 +6100,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_ipv6=yes
|
||||
aclocal_ipv6=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_ipv6=no
|
||||
aclocal_ipv6=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_ipv6" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_ipv6" >&6; }
|
||||
if test $aclocal_cv_ipv6 = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_ipv6" >&5
|
||||
echo "${ECHO_T}$aclocal_ipv6" >&6; }
|
||||
if test $aclocal_ipv6 = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_IPV6 1
|
||||
@ -6121,7 +6129,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for getipnodebyname" >&5
|
||||
echo $ECHO_N "checking for getipnodebyname... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_getipnodebyname+set}" = set; then
|
||||
if test "${aclocal_getipnodebyname+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6161,20 +6169,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_getipnodebyname=yes
|
||||
aclocal_getipnodebyname=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_getipnodebyname=no
|
||||
aclocal_getipnodebyname=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_getipnodebyname" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_getipnodebyname" >&6; }
|
||||
if test $aclocal_cv_getipnodebyname = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_getipnodebyname" >&5
|
||||
echo "${ECHO_T}$aclocal_getipnodebyname" >&6; }
|
||||
if test $aclocal_getipnodebyname = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_GETIPNODEBYNAME 1
|
||||
@ -6190,7 +6198,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for sin6_len" >&5
|
||||
echo $ECHO_N "checking for sin6_len... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_sin6_len+set}" = set; then
|
||||
if test "${aclocal_sin6_len+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6228,20 +6236,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_sin6_len=yes
|
||||
aclocal_sin6_len=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_sin6_len=no
|
||||
aclocal_sin6_len=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_sin6_len" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_sin6_len" >&6; }
|
||||
if test $aclocal_cv_sin6_len = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_sin6_len" >&5
|
||||
echo "${ECHO_T}$aclocal_sin6_len" >&6; }
|
||||
if test $aclocal_sin6_len = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_SIN6_LEN 1
|
||||
@ -6257,7 +6265,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for buggy ctime" >&5
|
||||
echo $ECHO_N "checking for buggy ctime... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_buggy_ctime+set}" = set; then
|
||||
if test "${aclocal_buggy_ctime+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6294,20 +6302,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_buggy_ctime=no
|
||||
aclocal_buggy_ctime=no
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_buggy_ctime=yes
|
||||
aclocal_buggy_ctime=yes
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_buggy_ctime" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_buggy_ctime" >&6; }
|
||||
if test $aclocal_cv_buggy_ctime = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_buggy_ctime" >&5
|
||||
echo "${ECHO_T}$aclocal_buggy_ctime" >&6; }
|
||||
if test $aclocal_buggy_ctime = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_BUGGY_CTIME 1
|
||||
@ -6323,7 +6331,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for gmtime_r" >&5
|
||||
echo $ECHO_N "checking for gmtime_r... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_gmtime_r+set}" = set; then
|
||||
if test "${aclocal_gmtime_r+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6359,20 +6367,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_gmtime_r=yes
|
||||
aclocal_gmtime_r=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_gmtime_r=no
|
||||
aclocal_gmtime_r=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_gmtime_r" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_gmtime_r" >&6; }
|
||||
if test $aclocal_cv_gmtime_r = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_gmtime_r" >&5
|
||||
echo "${ECHO_T}$aclocal_gmtime_r" >&6; }
|
||||
if test $aclocal_gmtime_r = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_GMTIME_R 1
|
||||
@ -6388,7 +6396,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for localtime_r" >&5
|
||||
echo $ECHO_N "checking for localtime_r... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_localtime_r+set}" = set; then
|
||||
if test "${aclocal_localtime_r+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6424,20 +6432,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_localtime_r=yes
|
||||
aclocal_localtime_r=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_localtime_r=no
|
||||
aclocal_localtime_r=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_localtime_r" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_localtime_r" >&6; }
|
||||
if test $aclocal_cv_localtime_r = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_localtime_r" >&5
|
||||
echo "${ECHO_T}$aclocal_localtime_r" >&6; }
|
||||
if test $aclocal_localtime_r = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_LOCALTIME_R 1
|
||||
@ -6453,7 +6461,7 @@ _ACEOF
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for setgroups" >&5
|
||||
echo $ECHO_N "checking for setgroups... $ECHO_C" >&6; }
|
||||
if test "${aclocal_cv_setgroups+set}" = set; then
|
||||
if test "${aclocal_setgroups+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
@ -6491,20 +6499,20 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_cv_setgroups=yes
|
||||
aclocal_setgroups=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_cv_setgroups=no
|
||||
aclocal_setgroups=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_cv_setgroups" >&5
|
||||
echo "${ECHO_T}$aclocal_cv_setgroups" >&6; }
|
||||
if test $aclocal_cv_setgroups = yes; then
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_setgroups" >&5
|
||||
echo "${ECHO_T}$aclocal_setgroups" >&6; }
|
||||
if test $aclocal_setgroups = yes; then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_SETGROUPS 1
|
||||
@ -6664,7 +6672,7 @@ fi
|
||||
|
||||
if test "$enable_ipv6" = "yes"
|
||||
then
|
||||
if test "$aclocal_cv_ipv6" != "yes"
|
||||
if test "$aclocal_ipv6" != "yes"
|
||||
then
|
||||
{ echo "$as_me:$LINENO: WARNING: ignoring --enable-ipv6" >&5
|
||||
echo "$as_me: WARNING: ignoring --enable-ipv6" >&2;}
|
||||
@ -6906,6 +6914,119 @@ echo "$as_me: WARNING: ignoring --with-man2html" >&2;}
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-openssl was given.
|
||||
if test "${with_openssl+set}" = set; then
|
||||
withval=$with_openssl;
|
||||
fi
|
||||
|
||||
if test "$with_openssl" != "no"
|
||||
then
|
||||
{ echo "$as_me:$LINENO: checking for openssl" >&5
|
||||
echo $ECHO_N "checking for openssl... $ECHO_C" >&6; }
|
||||
if test "${aclocal_openssl+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <openssl/ssl.h>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
SSL_CTX * p = 0 ; return 1;
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } && {
|
||||
test -z "$ac_cxx_werror_flag" ||
|
||||
test ! -s conftest.err
|
||||
} && test -s conftest.$ac_objext; then
|
||||
aclocal_openssl=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
aclocal_openssl=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $aclocal_openssl" >&5
|
||||
echo "${ECHO_T}$aclocal_openssl" >&6; }
|
||||
if test "$aclocal_openssl" = "yes"
|
||||
then
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_OPENSSL 1
|
||||
_ACEOF
|
||||
|
||||
SSL_LIBS="-lssl -lcrypto"
|
||||
SSL="openssl"
|
||||
else
|
||||
if test "$with_openssl" = "yes"
|
||||
then
|
||||
{ echo "$as_me:$LINENO: WARNING: ignoring --with-openssl, check config.log and try setting CFLAGS" >&5
|
||||
echo "$as_me: WARNING: ignoring --with-openssl, check config.log and try setting CFLAGS" >&2;}
|
||||
fi
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_OPENSSL 0
|
||||
_ACEOF
|
||||
|
||||
SSL_LIBS=""
|
||||
SSL="none"
|
||||
fi
|
||||
else
|
||||
|
||||
cat >>confdefs.h <<\_ACEOF
|
||||
#define HAVE_OPENSSL 0
|
||||
_ACEOF
|
||||
|
||||
SSL_LIBS=""
|
||||
SSL="none"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-static-linking was given.
|
||||
if test "${enable_static_linking+set}" = set; then
|
||||
enableval=$enable_static_linking;
|
||||
fi
|
||||
|
||||
|
||||
if test "$enable_static_linking" = "yes"
|
||||
then
|
||||
STATIC_START="-Xlinker -Bstatic"
|
||||
STATIC_END="-Xlinker -Bdynamic -ldl"
|
||||
else
|
||||
STATIC_START=""
|
||||
STATIC_END=""
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
# Check whether --enable-fhs was given.
|
||||
if test "${enable_fhs+set}" = set; then
|
||||
enableval=$enable_fhs;
|
||||
@ -6961,7 +7082,7 @@ then
|
||||
fi
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/gpop/Makefile src/main/Makefile src/win32/Makefile src/gui/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile lib/sunpro5/Makefile bin/Makefile doc/Makefile etc/Makefile test/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile src/Makefile src/glib/Makefile src/gssl/Makefile src/gnet/Makefile src/gsmtp/Makefile src/gpop/Makefile src/main/Makefile src/win32/Makefile src/gui/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile lib/sunpro5/Makefile bin/Makefile doc/Makefile etc/Makefile test/Makefile"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@ -7566,6 +7687,7 @@ do
|
||||
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||
"src/glib/Makefile") CONFIG_FILES="$CONFIG_FILES src/glib/Makefile" ;;
|
||||
"src/gssl/Makefile") CONFIG_FILES="$CONFIG_FILES src/gssl/Makefile" ;;
|
||||
"src/gnet/Makefile") CONFIG_FILES="$CONFIG_FILES src/gnet/Makefile" ;;
|
||||
"src/gsmtp/Makefile") CONFIG_FILES="$CONFIG_FILES src/gsmtp/Makefile" ;;
|
||||
"src/gpop/Makefile") CONFIG_FILES="$CONFIG_FILES src/gpop/Makefile" ;;
|
||||
@ -7784,6 +7906,10 @@ QT_LIBS!$QT_LIBS$ac_delim
|
||||
MOC!$MOC$ac_delim
|
||||
GUI_TRUE!$GUI_TRUE$ac_delim
|
||||
GUI_FALSE!$GUI_FALSE$ac_delim
|
||||
SSL_LIBS!$SSL_LIBS$ac_delim
|
||||
SSL!$SSL$ac_delim
|
||||
STATIC_START!$STATIC_START$ac_delim
|
||||
STATIC_END!$STATIC_END$ac_delim
|
||||
e_docdir!$e_docdir$ac_delim
|
||||
e_initdir!$e_initdir$ac_delim
|
||||
e_spooldir!$e_spooldir$ac_delim
|
||||
@ -7795,7 +7921,7 @@ LIBOBJS!$LIBOBJS$ac_delim
|
||||
LTLIBOBJS!$LTLIBOBJS$ac_delim
|
||||
_ACEOF
|
||||
|
||||
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 13; then
|
||||
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 17; then
|
||||
break
|
||||
elif $ac_last_try; then
|
||||
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
|
||||
|
16
configure.ac
16
configure.ac
@ -18,7 +18,7 @@ dnl Process this file with autoconf to produce a configure script.
|
||||
dnl
|
||||
|
||||
AC_INIT(src/gsmtp/gsmtp.h)
|
||||
AM_INIT_AUTOMAKE(emailrelay,1.6)
|
||||
AM_INIT_AUTOMAKE(emailrelay,1.7)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
@ -107,6 +107,18 @@ dnl
|
||||
AC_ARG_WITH(man2html,AC_HELP_STRING([--with-man2html],[convert man pages to html using man2html (default auto)]))
|
||||
WITH_MAN2HTML
|
||||
|
||||
dnl ===
|
||||
dnl "--with-openssl"
|
||||
dnl
|
||||
AC_ARG_WITH(openssl,AC_HELP_STRING([--with-openssl],[use openssl for smtp client tls extension (default auto)]))
|
||||
WITH_OPENSSL
|
||||
|
||||
dnl ===
|
||||
dnl "--enable-static-linking"
|
||||
dnl
|
||||
AC_ARG_ENABLE(static-linking,AC_HELP_STRING([--enable-static-linking],[prefer static linking for some libraries (default no)]))
|
||||
ENABLE_STATIC_LINKING
|
||||
|
||||
dnl ===
|
||||
dnl directory tweaking and "--enable-fhs" ...
|
||||
dnl
|
||||
@ -135,5 +147,5 @@ ENABLE_FHS
|
||||
dnl ===
|
||||
dnl generate files...
|
||||
dnl
|
||||
AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gnet/Makefile src/gsmtp/Makefile src/gpop/Makefile src/main/Makefile src/win32/Makefile src/gui/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile lib/sunpro5/Makefile bin/Makefile doc/Makefile etc/Makefile test/Makefile)
|
||||
AC_OUTPUT(Makefile src/Makefile src/glib/Makefile src/gssl/Makefile src/gnet/Makefile src/gsmtp/Makefile src/gpop/Makefile src/main/Makefile src/win32/Makefile src/gui/Makefile lib/Makefile lib/gcc2.95/Makefile lib/msvc6.0/Makefile lib/sunpro5/Makefile bin/Makefile doc/Makefile etc/Makefile test/Makefile)
|
||||
|
||||
|
@ -17,15 +17,15 @@
|
||||
|
||||
stylesheet=emailrelay.css
|
||||
txt_files=developer.txt reference.txt userguide.txt windows.txt
|
||||
man_files_in=emailrelay.1 emailrelay-passwd.1 emailrelay-poke.1 emailrelay-submit.1
|
||||
man_files_out=emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailrelay-submit.1.gz
|
||||
man_files_in=emailrelay.1 emailrelay-passwd.1 emailrelay-poke.1 emailrelay-submit.1 emailrelay-filter-copy.1
|
||||
man_files_out=emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailrelay-submit.1.gz emailrelay-filter-copy.1.gz
|
||||
html_files_in=doxygen_header.html
|
||||
html_files_thru=index.html emailrelay-man.html $(stylesheet)
|
||||
html_files_out=readme.html developer.html reference.html userguide.html windows.html changelog.html
|
||||
docbook_files_out=emailrelay.docbook
|
||||
png_files=gsmtp-classes.png gnet-classes.png sequence-3.png gnet-client.png gsmtp-serverprotocol.png auth.png
|
||||
|
||||
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files)
|
||||
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files) doxygen_missing.html
|
||||
noinst_SCRIPTS = .dox .docbook
|
||||
man1_MANS = $(man_files_in)
|
||||
e_doc_DATA = $(txt_files) $(html_files_out) $(html_files_thru) $(png_files) $(docbook_files_out)
|
||||
@ -38,6 +38,7 @@ converter_txt2mu=$(top_builddir)/bin/txt2mu.sh
|
||||
converter_mu2html=$(top_builddir)/bin/mu2html.sh
|
||||
converter_expand=$(top_builddir)/bin/expand.sh
|
||||
converter_mu2docbook=$(top_builddir)/bin/mu2docbook.sh
|
||||
run_doxygen=$(top_builddir)/bin/doxygen.sh
|
||||
|
||||
.txt.html:
|
||||
$(converter_html) -a "$(AWK)" $(top_srcdir)/doc/$*.txt $(stylesheet) > $*.html
|
||||
@ -61,7 +62,7 @@ emailrelay.docbook: head.db tail.db userguide.db reference.db developer.db
|
||||
-xmlto -o docbook html emailrelay.docbook && touch .docbook && cp *.png docbook/
|
||||
|
||||
.dox:
|
||||
if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP_SRC__:$(top_srcdir):g" | sed "s:__TOP_BUILD__:$(top_builddir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi
|
||||
$(run_doxygen) "$(HAVE_DOXYGEN)" "$(top_srcdir)" "$(top_builddir)" && touch .dox
|
||||
|
||||
emailrelay-man.html: emailrelay.1
|
||||
if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html -r -L. emailrelay.1 < /dev/null > emailrelay-man.html.tmp && mv emailrelay-man.html.tmp emailrelay-man.html ; grep -v '^Content-type:' < emailrelay-man.html > emailrelay-man.html.tmp && mv emailrelay-man.html.tmp emailrelay-man.html ; fi
|
||||
@ -85,6 +86,9 @@ emailrelay-passwd.1.gz : emailrelay-passwd.1
|
||||
emailrelay-submit.1.gz : emailrelay-submit.1
|
||||
if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-submit.1 > emailrelay-submit.1.gz ; fi
|
||||
|
||||
emailrelay-filter-copy.1.gz : emailrelay-filter-copy.1
|
||||
if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-filter-copy.1 > emailrelay-filter-copy.1.gz ; fi
|
||||
|
||||
emailrelay-poke.1.gz: emailrelay-poke.1
|
||||
if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-poke.1 > emailrelay-poke.1.gz ; fi
|
||||
|
||||
|
@ -117,6 +117,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
@ -170,14 +174,14 @@ top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
stylesheet = emailrelay.css
|
||||
txt_files = developer.txt reference.txt userguide.txt windows.txt
|
||||
man_files_in = emailrelay.1 emailrelay-passwd.1 emailrelay-poke.1 emailrelay-submit.1
|
||||
man_files_out = emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailrelay-submit.1.gz
|
||||
man_files_in = emailrelay.1 emailrelay-passwd.1 emailrelay-poke.1 emailrelay-submit.1 emailrelay-filter-copy.1
|
||||
man_files_out = emailrelay.1.gz emailrelay-passwd.1.gz emailrelay-poke.1.gz emailrelay-submit.1.gz emailrelay-filter-copy.1.gz
|
||||
html_files_in = doxygen_header.html
|
||||
html_files_thru = index.html emailrelay-man.html $(stylesheet)
|
||||
html_files_out = readme.html developer.html reference.html userguide.html windows.html changelog.html
|
||||
docbook_files_out = emailrelay.docbook
|
||||
png_files = gsmtp-classes.png gnet-classes.png sequence-3.png gnet-client.png gsmtp-serverprotocol.png auth.png
|
||||
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files)
|
||||
EXTRA_DIST = $(man_files_in) $(txt_files) $(html_files_in) $(html_files_thru) $(png_files) doxygen_missing.html
|
||||
noinst_SCRIPTS = .dox .docbook
|
||||
man1_MANS = $(man_files_in)
|
||||
e_doc_DATA = $(txt_files) $(html_files_out) $(html_files_thru) $(png_files) $(docbook_files_out)
|
||||
@ -188,6 +192,7 @@ converter_txt2mu = $(top_builddir)/bin/txt2mu.sh
|
||||
converter_mu2html = $(top_builddir)/bin/mu2html.sh
|
||||
converter_expand = $(top_builddir)/bin/expand.sh
|
||||
converter_mu2docbook = $(top_builddir)/bin/mu2docbook.sh
|
||||
run_doxygen = $(top_builddir)/bin/doxygen.sh
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
@ -442,7 +447,7 @@ emailrelay.docbook: head.db tail.db userguide.db reference.db developer.db
|
||||
-xmlto -o docbook html emailrelay.docbook && touch .docbook && cp *.png docbook/
|
||||
|
||||
.dox:
|
||||
if test "$(HAVE_DOXYGEN)" = "yes" ; then cat $(top_srcdir)/src/main/doxygen.cfg | sed "s:__TOP_SRC__:$(top_srcdir):g" | sed "s:__TOP_BUILD__:$(top_builddir):g" | doxygen - && touch .dox ; else echo no doxygen ; fi
|
||||
$(run_doxygen) "$(HAVE_DOXYGEN)" "$(top_srcdir)" "$(top_builddir)" && touch .dox
|
||||
|
||||
emailrelay-man.html: emailrelay.1
|
||||
if test "$(HAVE_MAN2HTML)" = "yes" ; then man2html -r -L. emailrelay.1 < /dev/null > emailrelay-man.html.tmp && mv emailrelay-man.html.tmp emailrelay-man.html ; grep -v '^Content-type:' < emailrelay-man.html > emailrelay-man.html.tmp && mv emailrelay-man.html.tmp emailrelay-man.html ; fi
|
||||
@ -466,6 +471,9 @@ emailrelay-passwd.1.gz : emailrelay-passwd.1
|
||||
emailrelay-submit.1.gz : emailrelay-submit.1
|
||||
if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-submit.1 > emailrelay-submit.1.gz ; fi
|
||||
|
||||
emailrelay-filter-copy.1.gz : emailrelay-filter-copy.1
|
||||
if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-filter-copy.1 > emailrelay-filter-copy.1.gz ; fi
|
||||
|
||||
emailrelay-poke.1.gz: emailrelay-poke.1
|
||||
if test -n "$(GZIP)" ; then $(GZIP) -c $(top_srcdir)/doc/emailrelay-poke.1 > emailrelay-poke.1.gz ; fi
|
||||
|
||||
|
14
doc/doxygen_missing.html
Normal file
14
doc/doxygen_missing.html
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>E-MailRelay source code documentation missing</title>
|
||||
<link rel="stylesheet" href="../emailrelay.css" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="div-main">
|
||||
<h1>E-MailRelay Source Code</h1>
|
||||
<p>No <a class="a-href" href="http://www.doxygen.org">doxygen</a> documentation available locally, try <a class="a-href" href="http://emailrelay.sourceforge.net/doxygen/index.html">online</a>.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<!-- Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved. -->
|
42
doc/emailrelay-filter-copy.1
Normal file
42
doc/emailrelay-filter-copy.1
Normal file
@ -0,0 +1,42 @@
|
||||
.\" Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
.\"
|
||||
.\" This program is free software: you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation, either version 3 of the License, or
|
||||
.\" (at your option) any later version.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
.\" GNU General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License
|
||||
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
.TH EMAILRELAY-FILTER-COPY 1 local
|
||||
.SH NAME
|
||||
emailrelay-filter-copy \- an E-MailRelay filter for pop-by-name
|
||||
.SH SYNOPSIS
|
||||
.B emailrelay-filter-copy
|
||||
.I <emailrelay-content-file>
|
||||
.LP
|
||||
.B emailrelay-filter-copy
|
||||
[--help]
|
||||
.SH DESCRIPTION
|
||||
The
|
||||
.I emailrelay-filter-copy
|
||||
utility can be used as an
|
||||
.B E-MailRelay
|
||||
.I "--filter"
|
||||
pre-processor program to copy e-mail messages from the main spool
|
||||
directory into all available sub-directories. When using the
|
||||
.I "--pop-by-name"
|
||||
feature of the
|
||||
.B E-MailRelay
|
||||
server this results in messages being copied all POP clients.
|
||||
.LP
|
||||
Only the message envelope is copied; the content file stays in
|
||||
the main directory.
|
||||
.SH SEE ALSO
|
||||
.BR emailrelay (1),
|
||||
.SH AUTHOR
|
||||
Graeme Walker, mailto:graeme_walker@users.sourceforge.net
|
@ -95,15 +95,19 @@ Runs as a server: equivalent to <I>--log</I> <I>--close-stderr</I>.
|
||||
<DT><B>-C, --client-auth </B><I><file></I>
|
||||
|
||||
<DD>
|
||||
Enables smtp authentication with remote server, using the given secrets file.
|
||||
Enables smtp authentication with the remote server, using the given secrets file.
|
||||
<DT><B>-Y, --client-filter </B><I><program></I>
|
||||
|
||||
<DD>
|
||||
Specifies an external program to process messages when they are forwarded.
|
||||
<DT><B>-j, --client-tls </B>
|
||||
|
||||
<DD>
|
||||
Enables tls/ssl layer for smtp client (if openssl built in).
|
||||
<DT><B>-e, --close-stderr </B>
|
||||
|
||||
<DD>
|
||||
Closes the standard error stream after start-up.
|
||||
Closes the standard error stream soon after start-up.
|
||||
<DT><B>-U, --connection-timeout </B><I><time></I>
|
||||
|
||||
<DD>
|
||||
@ -127,7 +131,7 @@ Specifies an external program to process messages as they are stored.
|
||||
<DT><B>-W, --filter-timeout </B><I><time></I>
|
||||
|
||||
<DD>
|
||||
Sets the timeout (in seconds) for running the <I>--filter</I> processor.
|
||||
Sets the timeout (in seconds) for running the <I>--filter</I> processor (default is 300).
|
||||
<DT><B>-f, --forward </B>
|
||||
|
||||
<DD>
|
||||
@ -147,7 +151,7 @@ Enables immediate forwarding of messages as soon as they are received (requires
|
||||
<DT><B>-I, --interface </B><I><ip-address></I>
|
||||
|
||||
<DD>
|
||||
Defines the listening interface for new connections.
|
||||
Defines the listening interface for incoming connections.
|
||||
<DT><B>-l, --log </B>
|
||||
|
||||
<DD>
|
||||
@ -179,7 +183,7 @@ Enables polling of the spool directory for messages to be forwarded with the spe
|
||||
<DT><B>-B, --pop </B>
|
||||
|
||||
<DD>
|
||||
Enables the pop server if compiled-in.
|
||||
Enables the pop server.
|
||||
<DT><B>-F, --pop-auth </B><I><file></I>
|
||||
|
||||
<DD>
|
||||
@ -216,6 +220,10 @@ Sets the response timeout (in seconds) when talking to a remote server (default
|
||||
|
||||
<DD>
|
||||
Enables authentication of remote clients, using the given secrets file.
|
||||
<DT><B>-K, --server-tls </B><I><pem-file></I>
|
||||
|
||||
<DD>
|
||||
Enables tls/ssl layer for smtp server using the given openssl certificate file (if openssl built in).
|
||||
<DT><B>-s, --spool-dir </B><I><dir></I>
|
||||
|
||||
<DD>
|
||||
@ -223,7 +231,7 @@ Specifies the spool directory (default is <I>/var/spool/emailrelay</I>).
|
||||
<DT><B>-k, --syslog </B>
|
||||
|
||||
<DD>
|
||||
Force syslog output if logging is enabled (overrides <I>--no-syslog</I>).
|
||||
Forces syslog output if logging is enabled (overrides <I>--no-syslog</I>).
|
||||
<DT><B>-u, --user </B><I><username></I>
|
||||
|
||||
<DD>
|
||||
@ -372,7 +380,7 @@ Graeme Walker, mailto:<A HREF="mailto:graeme_walker@users.sourceforge.net">graem
|
||||
This document was created by
|
||||
<A HREF="lynxcgi:FOO/cgi-bin/man/man2html">man2html</A>,
|
||||
using the manual pages.<BR>
|
||||
Time: 16:32:15 GMT, August 27, 2007
|
||||
Time: 00:56:15 GMT, September 19, 2007
|
||||
</BODY>
|
||||
</HTML>
|
||||
<!-- Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>. All rights reserved. -->
|
||||
|
@ -71,13 +71,16 @@ Runs as a proxy: equivalent to \fI--log\fR \fI--close-stderr\fR \fI--immediate\f
|
||||
Runs as a server: equivalent to \fI--log\fR \fI--close-stderr\fR.
|
||||
.TP
|
||||
.B \-C, --client-auth \fI<file>\fR
|
||||
Enables smtp authentication with remote server, using the given secrets file.
|
||||
Enables smtp authentication with the remote server, using the given secrets file.
|
||||
.TP
|
||||
.B \-Y, --client-filter \fI<program>\fR
|
||||
Specifies an external program to process messages when they are forwarded.
|
||||
.TP
|
||||
.B \-j, --client-tls
|
||||
Enables tls/ssl layer for smtp client (if openssl built in).
|
||||
.TP
|
||||
.B \-e, --close-stderr
|
||||
Closes the standard error stream after start-up.
|
||||
Closes the standard error stream soon after start-up.
|
||||
.TP
|
||||
.B \-U, --connection-timeout \fI<time>\fR
|
||||
Sets the timeout (in seconds) when connecting to a remote server (default is 40).
|
||||
@ -95,7 +98,7 @@ Disables acting as a server on any port (part of \fI--as-client\fR and usually u
|
||||
Specifies an external program to process messages as they are stored.
|
||||
.TP
|
||||
.B \-W, --filter-timeout \fI<time>\fR
|
||||
Sets the timeout (in seconds) for running the \fI--filter\fR processor.
|
||||
Sets the timeout (in seconds) for running the \fI--filter\fR processor (default is 300).
|
||||
.TP
|
||||
.B \-f, --forward
|
||||
Forwards stored mail on startup (requires \fI--forward-to\fR).
|
||||
@ -110,7 +113,7 @@ Displays help text and exits.
|
||||
Enables immediate forwarding of messages as soon as they are received (requires \fI--forward-to\fR).
|
||||
.TP
|
||||
.B \-I, --interface \fI<ip-address>\fR
|
||||
Defines the listening interface for new connections.
|
||||
Defines the listening interface for incoming connections.
|
||||
.TP
|
||||
.B \-l, --log
|
||||
Writes log information on standard error and syslog.
|
||||
@ -134,7 +137,7 @@ Defines a file for storing the daemon process-id.
|
||||
Enables polling of the spool directory for messages to be forwarded with the specified period (requires \fI--forward-to\fR).
|
||||
.TP
|
||||
.B \-B, --pop
|
||||
Enables the pop server if compiled-in.
|
||||
Enables the pop server.
|
||||
.TP
|
||||
.B \-F, --pop-auth \fI<file>\fR
|
||||
Defines the pop server secrets file (default is \fI/etc/emailrelay.auth\fR).
|
||||
@ -163,11 +166,14 @@ Sets the response timeout (in seconds) when talking to a remote server (default
|
||||
.B \-S, --server-auth \fI<file>\fR
|
||||
Enables authentication of remote clients, using the given secrets file.
|
||||
.TP
|
||||
.B \-K, --server-tls \fI<pem-file>\fR
|
||||
Enables tls/ssl layer for smtp server using the given openssl certificate file (if openssl built in).
|
||||
.TP
|
||||
.B \-s, --spool-dir \fI<dir>\fR
|
||||
Specifies the spool directory (default is \fI/var/spool/emailrelay\fR).
|
||||
.TP
|
||||
.B \-k, --syslog
|
||||
Force syslog output if logging is enabled (overrides \fI--no-syslog\fR).
|
||||
Forces syslog output if logging is enabled (overrides \fI--no-syslog\fR).
|
||||
.TP
|
||||
.B \-u, --user \fI<username>\fR
|
||||
Names the effective user to switch to if started as root (default is \fIdaemon\fR).
|
||||
|
@ -34,7 +34,10 @@ div.Header h1
|
||||
div.Content
|
||||
{
|
||||
margin-left: 230px ;
|
||||
padding: 5px ;
|
||||
padding-left: 5px ;
|
||||
padding-top: 5px ;
|
||||
padding-bottom: 5px ;
|
||||
padding-right: 40px ;
|
||||
}
|
||||
|
||||
div.Menu
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 28 KiB |
@ -27,13 +27,16 @@ where <switch> is:
|
||||
Runs as a server: equivalent to "--log --close-stderr".
|
||||
|
||||
# --client-auth (-C)
|
||||
Enables smtp authentication with remote server, using the given secrets file.
|
||||
Enables smtp authentication with the remote server, using the given secrets file.
|
||||
|
||||
# --client-filter (-Y)
|
||||
Specifies an external program to process messages when they are forwarded.
|
||||
|
||||
# --client-tls (-j)
|
||||
Enables tls/ssl layer for smtp client (if openssl built in).
|
||||
|
||||
# --close-stderr (-e)
|
||||
Closes the standard error stream after start-up.
|
||||
Closes the standard error stream soon after start-up.
|
||||
|
||||
# --connection-timeout (-U)
|
||||
Sets the timeout (in seconds) when connecting to a remote server (default is 40).
|
||||
@ -51,7 +54,7 @@ where <switch> is:
|
||||
Specifies an external program to process messages as they are stored.
|
||||
|
||||
# --filter-timeout (-W)
|
||||
Sets the timeout (in seconds) for running the --filter processor.
|
||||
Sets the timeout (in seconds) for running the --filter processor (default is 300).
|
||||
|
||||
# --forward (-f)
|
||||
Forwards stored mail on startup (requires --forward-to).
|
||||
@ -66,7 +69,7 @@ where <switch> is:
|
||||
Enables immediate forwarding of messages as soon as they are received (requires --forward-to).
|
||||
|
||||
# --interface (-I)
|
||||
Defines the listening interface for new connections.
|
||||
Defines the listening interface for incoming connections.
|
||||
|
||||
# --log (-l)
|
||||
Writes log information on standard error and syslog.
|
||||
@ -90,7 +93,7 @@ where <switch> is:
|
||||
Enables polling of the spool directory for messages to be forwarded with the specified period (requires --forward-to).
|
||||
|
||||
# --pop (-B)
|
||||
Enables the pop server if compiled-in.
|
||||
Enables the pop server.
|
||||
|
||||
# --pop-auth (-F)
|
||||
Defines the pop server secrets file (default is "/etc/emailrelay.auth").
|
||||
@ -119,11 +122,14 @@ where <switch> is:
|
||||
# --server-auth (-S)
|
||||
Enables authentication of remote clients, using the given secrets file.
|
||||
|
||||
# --server-tls (-K)
|
||||
Enables tls/ssl layer for smtp server using the given openssl certificate file (if openssl built in).
|
||||
|
||||
# --spool-dir (-s)
|
||||
Specifies the spool directory (default is "/var/spool/emailrelay").
|
||||
|
||||
# --syslog (-k)
|
||||
Force syslog output if logging is enabled (overrides --no-syslog).
|
||||
Forces syslog output if logging is enabled (overrides --no-syslog).
|
||||
|
||||
# --user (-u)
|
||||
Names the effective user to switch to if started as root (default is "daemon").
|
||||
@ -421,10 +427,14 @@ E-MailRelay supports the SMTP "AUTH" extension, as defined in RFC2554, on both
|
||||
the server-side and client-side.
|
||||
|
||||
The authentication mechanisms currently supported are:
|
||||
# "LOGIN"
|
||||
# "PLAIN"
|
||||
|
||||
Passwords are stored in clear-text, sent over the network in clear-text, and
|
||||
are replayable. This is a widely used mechanism, but officially obsolete.
|
||||
are replayable. Defined in RFC2595.
|
||||
|
||||
# "LOGIN"
|
||||
|
||||
Similar to "PLAIN". Officially obsolete although widely used.
|
||||
|
||||
# "CRAM-MD5" mechanism
|
||||
|
||||
|
@ -418,6 +418,21 @@ switch:
|
||||
This might be useful if spam filtering is creating a bottleneck in the
|
||||
E-MailRelay server.
|
||||
|
||||
Google mail
|
||||
-----------
|
||||
To send mail via Google mail's SMTP gateway you will need to create a client
|
||||
secrets file containing your account details and enable TLS support in
|
||||
E-MailRelay by using the "--client-tls" switch.
|
||||
|
||||
The secrets file should contain one line of text something like this:
|
||||
|
||||
login client myname@gmail.com mypassword
|
||||
|
||||
Refer to this file using "--client-auth" on the E-MailRelay command-line and
|
||||
also add in the "--client-tls" switch:
|
||||
|
||||
emailrelay --as-proxy smtp.gmail.com:587 --client-tls --client-auth /etc/emailrelay.auth ...
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ Setup program
|
||||
Installing E-MailRelay on Windows should be straightforward if you have
|
||||
self-extracting archive program "emailrelay-setup.exe". Make sure that the
|
||||
setup program is in a writeable directory with plenty of space on the disk
|
||||
because when you run it is will extract an installation GUI program plus
|
||||
because when you run it it will extract an installation GUI program plus
|
||||
dependent DLLs in into the same directory.
|
||||
|
||||
The installation GUI program will take you through the installation options and
|
||||
@ -32,9 +32,15 @@ Running as a service
|
||||
--------------------
|
||||
To manually install E-MailRelay as a service so that it starts up automatically
|
||||
at boot-time you must first create a one-line batch file called
|
||||
"emailrelay-start.bat" in the main E-MailRelay directory. This should contain
|
||||
the full server startup command, including the "--hidden" and "--no-daemon"
|
||||
switches. Then run "emailrelay-service --install" to install the service.
|
||||
"emailrelay-start.bat" in the main E-MailRelay directory containing
|
||||
the full E-MailRelay server command-line. Then run "emailrelay-service --install"
|
||||
to install the service.
|
||||
|
||||
When the E-MailRelay server is run in this way it has the "--no-daemon" and
|
||||
"--hidden" switches added so that there is no user interface. (The "--no-daemon"
|
||||
switch on Windows changes the interface from using the system-tray to using a
|
||||
normal window, and the "--hidden" switch suppresses the window and any message
|
||||
boxes.)
|
||||
|
||||
Note that the batch file and the main E-MailRelay executable must be in the same
|
||||
directory and that the batch file is only read at install time; if you need to
|
||||
@ -43,10 +49,16 @@ properties.
|
||||
|
||||
Diagnostics
|
||||
-----------
|
||||
* Add "--log --log-time --verbose --syslog" to the E-MailRelay command-lines.
|
||||
* Check the system event log (run "eventvwr.exe") for errors and warnings.
|
||||
* Check the spool directory for ".bad" envelope files -- remove the suffix to retry.
|
||||
* Set the environment variable "GLOGOUTPUT_DIR" to (eg.) "c:\temp" and look for "glog.txt"
|
||||
E-MailRelay normally writes errors and warnings into the system event log, which
|
||||
you can view by running "eventvwr.exe". You can increase the verbosity by adding
|
||||
the "--verbose" switch to the E-MailRelay command-line.
|
||||
|
||||
The E-MailRelay server also logs to the standard error stream but the
|
||||
"--as-server" and "--as-proxy" switches implicitly incorporate "--close-stderr"
|
||||
so with these switches the standard error logging will stop soon after startup.
|
||||
To get continuous logging you should replace "--as-server" with "--log" and
|
||||
"--as-proxy" with "--immediate --forward-to". Then you will be able to redirect
|
||||
the standard error stream to a log file.
|
||||
|
||||
Building from source
|
||||
--------------------
|
||||
|
@ -1,11 +1,11 @@
|
||||
Summary: Simple e-mail message transfer agent and proxy using SMTP
|
||||
Name: emailrelay
|
||||
Version: 1.6
|
||||
Version: 1.7
|
||||
Release: 1
|
||||
License: GPL3
|
||||
Group: System Environment/Daemons
|
||||
URL: http://emailrelay.sourceforge.net/
|
||||
Source: http://sourceforge.net/sourceforge/emailrelay/emailrelay-src-1.6.tar.gz
|
||||
Source: http://sourceforge.net/sourceforge/emailrelay/emailrelay-1.7-src.tar.gz
|
||||
BuildRoot: /tmp/emailrelay-install
|
||||
|
||||
%description
|
||||
@ -30,7 +30,7 @@ Distribution is under the GNU General Public License V3.
|
||||
%setup
|
||||
|
||||
%build
|
||||
./configure --enable-fhs --disable-gui --without-man2html --without-doxygen
|
||||
./configure --enable-fhs --disable-gui --without-man2html --without-doxygen --with-openssl --enable-static-linking
|
||||
make
|
||||
|
||||
%install
|
||||
@ -50,10 +50,11 @@ test "$RPM_BUILD_ROOT" = "/" || rm -rf "$RPM_BUILD_ROOT"
|
||||
%config /etc/emailrelay.conf
|
||||
/etc/emailrelay.conf.template
|
||||
/etc/init.d/emailrelay
|
||||
/usr/share/man/man1/emailrelay-submit.1.gz
|
||||
/usr/share/man/man1/emailrelay.1.gz
|
||||
/usr/share/man/man1/emailrelay-filter-copy.1.gz
|
||||
/usr/share/man/man1/emailrelay-poke.1.gz
|
||||
/usr/share/man/man1/emailrelay-passwd.1.gz
|
||||
/usr/share/man/man1/emailrelay-submit.1.gz
|
||||
%docdir /usr/share/doc/emailrelay
|
||||
/usr/share/doc/emailrelay/index.html
|
||||
/usr/share/doc/emailrelay/windows.html
|
||||
|
@ -109,6 +109,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -111,6 +111,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -102,6 +102,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -102,6 +102,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -99,6 +99,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -15,4 +15,4 @@
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
EXTRA_DIST = mingw.mak mingw-common.mak emailrelay.dsw
|
||||
SUBDIRS = glib gnet gsmtp gpop main win32 gui
|
||||
SUBDIRS = glib gssl gnet gsmtp gpop main win32 gui
|
||||
|
@ -111,6 +111,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
@ -166,7 +170,7 @@ top_srcdir = @top_srcdir@
|
||||
#
|
||||
#
|
||||
EXTRA_DIST = mingw.mak mingw-common.mak emailrelay.dsw
|
||||
SUBDIRS = glib gnet gsmtp gpop main win32 gui
|
||||
SUBDIRS = glib gssl gnet gsmtp gpop main win32 gui
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
|
@ -132,6 +132,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -67,11 +67,9 @@ public:
|
||||
///< Destructor.
|
||||
|
||||
bool simple() const ;
|
||||
///< Returns true if the path is just a
|
||||
///< file/directory name without
|
||||
///< any separators. Note that if the path
|
||||
///< is simple() then dirname() will
|
||||
///< return the empty string.
|
||||
///< Returns true if the path is just a file/directory name without
|
||||
///< any separators. Note that if the path is simple() then dirname()
|
||||
///< will return the empty string.
|
||||
|
||||
std::string str() const ;
|
||||
///< Returns the path string.
|
||||
@ -81,9 +79,8 @@ public:
|
||||
///< Does nothing with the extension (cf. basename(1)).
|
||||
|
||||
Path dirname() const ;
|
||||
///< Returns the drive/directory parts of the path. If
|
||||
///< this path is the top of the tree then the
|
||||
///< null path is returned.
|
||||
///< Returns the drive/directory parts of the path. If this path is
|
||||
///< the top of the tree then the null path is returned.
|
||||
///<
|
||||
///< eg. "c:foo\bar.exe" -> "c:foo"
|
||||
///< eg. "c:\foo\bar.exe" -> "c:\foo"
|
||||
@ -101,20 +98,18 @@ public:
|
||||
///< eg. "\\machine\drive" -> ""
|
||||
|
||||
std::string extension() const ;
|
||||
///< Returns the path's original extension, even
|
||||
///< after removeExtension(). Returns
|
||||
///< the zero-length string if there is none.
|
||||
///< Returns the path's original extension, even after
|
||||
///< removeExtension(). Returns the zero-length string if
|
||||
///< there is none.
|
||||
|
||||
void removeExtension() ;
|
||||
///< Modifies the path by removing any extension.
|
||||
///< However, the extension returned by extension() is
|
||||
///< unchanged.
|
||||
///< Modifies the path by removing any extension. However,
|
||||
///< the extension returned by extension() is unchanged.
|
||||
|
||||
void setExtension( const std::string & extension ) ;
|
||||
///< Replaces the extension. Any leading dot in the
|
||||
///< given string is ignored. (The given extension
|
||||
///< will be returned by subsequent calls
|
||||
///< to extension().)
|
||||
///< Replaces the extension. Any leading dot in the given
|
||||
///< string is ignored. (The given extension will be returned
|
||||
///< by subsequent calls to extension().)
|
||||
|
||||
bool isAbsolute() const ;
|
||||
///< Returns !isRelative().
|
||||
@ -137,8 +132,8 @@ public:
|
||||
///< is added if necessary.
|
||||
|
||||
static G::Path join( const G::Path & p1 , const G::Path & p2 ) ;
|
||||
///< Joins two paths together. The second should
|
||||
///< be a relative path.
|
||||
///< Joins two paths together. The second should be a
|
||||
///< relative path.
|
||||
|
||||
Strings split( bool no_dot = true ) const ;
|
||||
///< Spits the path into a list of component parts.
|
||||
|
@ -142,7 +142,6 @@ public:
|
||||
void emit() { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback() ; } }
|
||||
void connect( Slot0 slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
|
||||
void disconnect() { m_slot = Slot0() ; }
|
||||
bool connected() const { return m_slot.base() != NULL ; }
|
||||
void reset() { m_emitted = false ; }
|
||||
} ;
|
||||
|
||||
@ -217,7 +216,6 @@ public:
|
||||
void emit( P p ) { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback( p ) ; } }
|
||||
void connect( Slot1<P> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
|
||||
void disconnect() { m_slot = Slot1<P>() ; }
|
||||
bool connected() const { return m_slot.base() != NULL ; }
|
||||
void reset() { m_emitted = false ; }
|
||||
} ;
|
||||
|
||||
@ -292,7 +290,6 @@ public:
|
||||
void emit( P1 p1 , P2 p2 ) { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback( p1 , p2 ) ; } }
|
||||
void connect( Slot2<P1,P2> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
|
||||
void disconnect() { m_slot = Slot2<P1,P2>() ; }
|
||||
bool connected() const { return m_slot.base() != NULL ; }
|
||||
void reset() { m_emitted = false ; }
|
||||
} ;
|
||||
|
||||
@ -367,7 +364,6 @@ public:
|
||||
void emit( P1 p1 , P2 p2 , P3 p3 ) { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback( p1 , p2 , p3 ) ; }}
|
||||
void connect( Slot3<P1,P2,P3> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
|
||||
void disconnect() { m_slot = Slot3<P1,P2,P3>() ; }
|
||||
bool connected() const { return m_slot.base() != NULL ; }
|
||||
void reset() { m_emitted = false ; }
|
||||
} ;
|
||||
|
||||
@ -380,7 +376,7 @@ Slot3<P1,P2,P3> slot( T & object , void (T::*fn)(P1,P2,P3) )
|
||||
return Slot3<P1,P2,P3>( new SlotImp3<T,P1,P2,P3>(object,fn) , SlotOp3<T,P1,P2,P3>::callback ) ;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -65,6 +65,11 @@ G_EXCEPTION( StateMachine_Error , "invalid state machine transition" ) ;
|
||||
/// same. The 'any' state is also used as a return value from
|
||||
/// apply() to signal a protocol error.
|
||||
///
|
||||
/// If the 'any' state is numerically the largest then it can be used
|
||||
/// to identify a default transition for the given event; transitions
|
||||
/// identified by an exact match with the current state will be
|
||||
/// chosen in preference to the 'any' transition.
|
||||
///
|
||||
/// The 'end' state is special in that predicates are ignored for
|
||||
/// transitions which have 'end' as their 'normal' destintation
|
||||
/// state. This is because of a special implementation feature
|
||||
@ -212,7 +217,7 @@ template <typename T, typename State, typename Event, typename Arg>
|
||||
State StateMachine<T,State,Event,Arg>::apply( T & t , Event event , const Arg & arg )
|
||||
{
|
||||
State state = m_state ;
|
||||
typename Map::iterator p = m_map.find(event) ; // look up in the multimap keyed on current-state + event
|
||||
typename Map::iterator p = m_map.find(event) ; // look up in the multimap keyed on event + current-state
|
||||
for( ; p != m_map.end() && (*p).first == event ; ++p )
|
||||
{
|
||||
if( (*p).second.from == m_any || (*p).second.from == m_state )
|
||||
|
@ -29,7 +29,7 @@ bool G::Test::enabled( const std::string & name )
|
||||
{
|
||||
bool result = false ;
|
||||
|
||||
#ifdef G_DEBUG
|
||||
#ifdef _DEBUG
|
||||
static const char * p = std::getenv("G_TEST") ;
|
||||
result = p ? ( std::string(p).find(name) != std::string::npos ) : false ; // (could do better)
|
||||
#endif
|
||||
|
@ -27,13 +27,11 @@ EXTRA_DIST=\
|
||||
gsocket_win32.cpp \
|
||||
mingw.mak
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gssl
|
||||
noinst_LIBRARIES = libgnet.a libipv4.a libipv6.a
|
||||
|
||||
libgnet_a_SOURCES = \
|
||||
gaddress.h \
|
||||
gbufferedclient.cpp \
|
||||
gbufferedclient.h \
|
||||
gbufferedserverpeer.cpp \
|
||||
gbufferedserverpeer.h \
|
||||
gclientptr.h \
|
||||
@ -67,8 +65,6 @@ libgnet_a_SOURCES = \
|
||||
gresolverinfo.cpp \
|
||||
gresolverinfo.h \
|
||||
gresolver_unix.cpp \
|
||||
gsender.cpp \
|
||||
gsender.h \
|
||||
gserver.cpp \
|
||||
gserver.h \
|
||||
gsimpleclient.cpp \
|
||||
@ -77,6 +73,8 @@ libgnet_a_SOURCES = \
|
||||
gsocket.cpp \
|
||||
gsocket.h \
|
||||
gsocket_unix.cpp \
|
||||
gsocketprotocol.cpp \
|
||||
gsocketprotocol.h \
|
||||
gtimer.cpp \
|
||||
gtimer.h \
|
||||
gtimerlist.cpp \
|
||||
|
@ -47,17 +47,17 @@ LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
libgnet_a_AR = $(AR) $(ARFLAGS)
|
||||
libgnet_a_LIBADD =
|
||||
am_libgnet_a_OBJECTS = gbufferedclient.$(OBJEXT) \
|
||||
gbufferedserverpeer.$(OBJEXT) gclient.$(OBJEXT) \
|
||||
am_libgnet_a_OBJECTS = gbufferedserverpeer.$(OBJEXT) gclient.$(OBJEXT) \
|
||||
gconnection.$(OBJEXT) gdescriptor_unix.$(OBJEXT) \
|
||||
geventhandler.$(OBJEXT) geventloop.$(OBJEXT) \
|
||||
geventloop_unix.$(OBJEXT) gheapclient.$(OBJEXT) \
|
||||
glinebuffer.$(OBJEXT) glocal.$(OBJEXT) glocal_unix.$(OBJEXT) \
|
||||
gmonitor.$(OBJEXT) gmultiserver.$(OBJEXT) gresolver.$(OBJEXT) \
|
||||
gresolverinfo.$(OBJEXT) gresolver_unix.$(OBJEXT) \
|
||||
gsender.$(OBJEXT) gserver.$(OBJEXT) gsimpleclient.$(OBJEXT) \
|
||||
gserver.$(OBJEXT) gsimpleclient.$(OBJEXT) \
|
||||
gsimpleclient_unix.$(OBJEXT) gsocket.$(OBJEXT) \
|
||||
gsocket_unix.$(OBJEXT) gtimer.$(OBJEXT) gtimerlist.$(OBJEXT)
|
||||
gsocket_unix.$(OBJEXT) gsocketprotocol.$(OBJEXT) \
|
||||
gtimer.$(OBJEXT) gtimerlist.$(OBJEXT)
|
||||
libgnet_a_OBJECTS = $(am_libgnet_a_OBJECTS)
|
||||
libipv4_a_AR = $(AR) $(ARFLAGS)
|
||||
libipv4_a_LIBADD =
|
||||
@ -144,6 +144,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
@ -207,12 +211,10 @@ EXTRA_DIST = \
|
||||
gsocket_win32.cpp \
|
||||
mingw.mak
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gssl
|
||||
noinst_LIBRARIES = libgnet.a libipv4.a libipv6.a
|
||||
libgnet_a_SOURCES = \
|
||||
gaddress.h \
|
||||
gbufferedclient.cpp \
|
||||
gbufferedclient.h \
|
||||
gbufferedserverpeer.cpp \
|
||||
gbufferedserverpeer.h \
|
||||
gclientptr.h \
|
||||
@ -246,8 +248,6 @@ libgnet_a_SOURCES = \
|
||||
gresolverinfo.cpp \
|
||||
gresolverinfo.h \
|
||||
gresolver_unix.cpp \
|
||||
gsender.cpp \
|
||||
gsender.h \
|
||||
gserver.cpp \
|
||||
gserver.h \
|
||||
gsimpleclient.cpp \
|
||||
@ -256,6 +256,8 @@ libgnet_a_SOURCES = \
|
||||
gsocket.cpp \
|
||||
gsocket.h \
|
||||
gsocket_unix.cpp \
|
||||
gsocketprotocol.cpp \
|
||||
gsocketprotocol.h \
|
||||
gtimer.cpp \
|
||||
gtimer.h \
|
||||
gtimerlist.cpp \
|
||||
@ -320,7 +322,6 @@ distclean-compile:
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gaddress_ip.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gaddress_ipv4.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gbufferedclient.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gbufferedserverpeer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gclient.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gconnection.Po@am__quote@
|
||||
@ -339,12 +340,12 @@ distclean-compile:
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gresolver_ipv4.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gresolver_unix.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gresolverinfo.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsender.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gserver.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsimpleclient.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsimpleclient_unix.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsocket.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsocket_unix.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsocketprotocol.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtimer.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtimerlist.Po@am__quote@
|
||||
|
||||
|
@ -1,85 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
//
|
||||
// gbufferedclient.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gtest.h"
|
||||
#include "gdebug.h"
|
||||
#include "gbufferedclient.h"
|
||||
|
||||
GNet::BufferedClient::BufferedClient( const ResolverInfo & remote_info ,
|
||||
const Address & local_interface , bool privileged , bool sync_dns ) :
|
||||
HeapClient(remote_info,local_interface,privileged,sync_dns) ,
|
||||
m_sender(*this)
|
||||
{
|
||||
}
|
||||
|
||||
GNet::BufferedClient::~BufferedClient()
|
||||
{
|
||||
}
|
||||
|
||||
bool GNet::BufferedClient::send( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
bool rc = true ;
|
||||
if( m_sender.send( socket() , data , offset ) )
|
||||
{
|
||||
rc = true ;
|
||||
}
|
||||
else if( m_sender.failed() )
|
||||
{
|
||||
throw SendError() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
logFlowControlAsserted() ;
|
||||
rc = false ; // onSendComplete() will be called
|
||||
}
|
||||
onSendImp() ;
|
||||
return rc ;
|
||||
}
|
||||
|
||||
void GNet::BufferedClient::onWriteable()
|
||||
{
|
||||
logFlowControlReleased() ;
|
||||
if( m_sender.resumeSending(socket()) )
|
||||
onSendComplete() ;
|
||||
else if( m_sender.failed() )
|
||||
throw SendError() ;
|
||||
}
|
||||
|
||||
void GNet::BufferedClient::onSendImp()
|
||||
{
|
||||
}
|
||||
|
||||
void GNet::BufferedClient::logFlowControlAsserted() const
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::BufferedClient::send: " << logId() << ": flow control asserted" ) ;
|
||||
}
|
||||
|
||||
void GNet::BufferedClient::logFlowControlReleased() const
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::BufferedClient::send: " << logId() << ": flow control released" ) ;
|
||||
}
|
||||
|
||||
/// \file gbufferedclient.cpp
|
@ -1,87 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
///
|
||||
/// \file gbufferedclient.h
|
||||
///
|
||||
|
||||
#ifndef G_BUFFERED_CLIENT_H
|
||||
#define G_BUFFERED_CLIENT_H
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gheapclient.h"
|
||||
#include "gexception.h"
|
||||
#include "gsender.h"
|
||||
#include <string>
|
||||
|
||||
/// \namespace GNet
|
||||
namespace GNet
|
||||
{
|
||||
class BufferedClient ;
|
||||
}
|
||||
|
||||
/// \class GNet::BufferedClient
|
||||
/// A HeapClient class that does buffered sending with flow control.
|
||||
///
|
||||
class GNet::BufferedClient : public GNet::HeapClient
|
||||
{
|
||||
public:
|
||||
G_EXCEPTION( SendError , "peer disconnected" ) ;
|
||||
|
||||
explicit BufferedClient( const ResolverInfo & remote_info , const Address & local_interface = Address(0U) ,
|
||||
bool privileged = false , bool sync_dns = synchronousDnsDefault() ) ;
|
||||
///< Constructor.
|
||||
|
||||
bool send( const std::string & data , std::string::size_type offset = 0U ) ;
|
||||
///< Sends data starting at the given offset.
|
||||
///< Returns true if all the data is sent.
|
||||
///<
|
||||
///< If flow control is asserted then a write-event
|
||||
///< handler is installed and false is returned.
|
||||
///< The onSendComplete() callback will be called
|
||||
///< when the data has been fully sent.
|
||||
///<
|
||||
///< Throws on error, eg. if disconnected.
|
||||
|
||||
protected:
|
||||
virtual ~BufferedClient() ;
|
||||
///< Destructor.
|
||||
|
||||
virtual void onSendComplete() = 0 ;
|
||||
///< Called when all residual data has been sent.
|
||||
|
||||
virtual void onSendImp() ;
|
||||
///< Called just before send() returns. The default
|
||||
///< implementation does nothing. Overridable.
|
||||
///< Overrides typically start a response timer.
|
||||
|
||||
virtual void onWriteable() ;
|
||||
///< Final override from SimpleClient.
|
||||
|
||||
private:
|
||||
void logFlowControlReleased() const ;
|
||||
void logFlowControlAsserted() const ;
|
||||
|
||||
private:
|
||||
BufferedClient( const BufferedClient& ) ; // not implemented
|
||||
void operator=( const BufferedClient& ) ; // not implemented
|
||||
|
||||
private:
|
||||
Sender m_sender ;
|
||||
} ;
|
||||
|
||||
#endif
|
@ -21,16 +21,11 @@
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gbufferedserverpeer.h"
|
||||
#include "gstr.h"
|
||||
#include "gtest.h"
|
||||
#include "gassert.h"
|
||||
#include "glog.h"
|
||||
|
||||
GNet::BufferedServerPeer::BufferedServerPeer( Server::PeerInfo peer_info , const std::string & eol , bool throw_ ) :
|
||||
GNet::BufferedServerPeer::BufferedServerPeer( Server::PeerInfo peer_info , const std::string & eol ) :
|
||||
ServerPeer(peer_info) ,
|
||||
m_sender(*this) ,
|
||||
m_line_buffer(eol) ,
|
||||
m_throw(throw_)
|
||||
m_line_buffer(eol)
|
||||
{
|
||||
}
|
||||
|
||||
@ -38,35 +33,6 @@ GNet::BufferedServerPeer::~BufferedServerPeer()
|
||||
{
|
||||
}
|
||||
|
||||
bool GNet::BufferedServerPeer::send( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
bool all_sent = m_sender.send( socket() , data , offset ) ;
|
||||
if( !all_sent && ( m_sender.failed() || m_throw ) )
|
||||
throw SendError() ;
|
||||
if( !all_sent )
|
||||
logFlowControlAsserted() ;
|
||||
return all_sent ;
|
||||
}
|
||||
|
||||
void GNet::BufferedServerPeer::writeEvent()
|
||||
{
|
||||
try
|
||||
{
|
||||
logFlowControlReleased() ;
|
||||
if( m_sender.resumeSending( socket() ) )
|
||||
onSendComplete() ;
|
||||
else if( m_sender.failed() )
|
||||
throw SendError() ;
|
||||
else
|
||||
logFlowControlReasserted() ;
|
||||
}
|
||||
catch( std::exception & e ) // strategy
|
||||
{
|
||||
G_WARNING( "GNet::BufferedServerPeer::writeEvent: exception: " << e.what() ) ;
|
||||
doDelete() ;
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::BufferedServerPeer::onData( const char * p , ServerPeer::size_type n )
|
||||
{
|
||||
for( m_line_buffer.add(p,n) ; m_line_buffer.more() ; m_line_buffer.discard() )
|
||||
@ -77,25 +43,4 @@ void GNet::BufferedServerPeer::onData( const char * p , ServerPeer::size_type n
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::BufferedServerPeer::logFlowControlAsserted() const
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::BufferedServerPeer::send: server " << logId() << ": flow control asserted" ) ;
|
||||
}
|
||||
|
||||
void GNet::BufferedServerPeer::logFlowControlReleased() const
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::BufferedServerPeer::writeEvent: server " << logId() << ": flow control released" ) ;
|
||||
}
|
||||
|
||||
void GNet::BufferedServerPeer::logFlowControlReasserted() const
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::BufferedServerPeer::writeEvent: server " << logId() << ": flow control reasserted" ) ;
|
||||
}
|
||||
|
||||
/// \file gbufferedserverpeer.cpp
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gserver.h"
|
||||
#include "gsender.h"
|
||||
#include "gsocketprotocol.h"
|
||||
#include "glinebuffer.h"
|
||||
#include "gexception.h"
|
||||
#include <string>
|
||||
@ -36,63 +36,31 @@ namespace GNet
|
||||
}
|
||||
|
||||
/// \class GNet::BufferedServerPeer
|
||||
/// A ServerPeer that does buffered sending with flow-control
|
||||
/// and line-buffered input.
|
||||
/// A ServerPeer that does line-buffering on input.
|
||||
///
|
||||
class GNet::BufferedServerPeer : public GNet::ServerPeer
|
||||
{
|
||||
public:
|
||||
G_EXCEPTION( SendError , "peer disconnected" ) ;
|
||||
|
||||
BufferedServerPeer( Server::PeerInfo , const std::string & eol , bool throw_on_flow_control = false ) ;
|
||||
///< Constructor. If the 'throw' parameter is true then
|
||||
///< a failure to send resulting from flow-control results
|
||||
///< in a SendError exception, rather than the
|
||||
///< return-false-and-on-resume mechanism.
|
||||
BufferedServerPeer( Server::PeerInfo , const std::string & eol ) ;
|
||||
///< Constructor.
|
||||
|
||||
virtual ~BufferedServerPeer() ;
|
||||
///< Destructor.
|
||||
|
||||
bool send( const std::string & data , std::string::size_type offset = 0U ) ;
|
||||
///< Sends data down the socket to the peer. Returns true
|
||||
///< if all the data is sent. If not all the data is sent
|
||||
///< because of flow control then onSendComplete() will
|
||||
///< be called when it has. Throws on error, or if
|
||||
///< flow control was asserted and the constructor's
|
||||
///< throw parameter was true.
|
||||
|
||||
virtual void writeEvent() ;
|
||||
///< Final override from EventHandler.
|
||||
|
||||
protected:
|
||||
virtual void onSendComplete() = 0 ;
|
||||
///< Called after flow-control has been released and all
|
||||
///< residual data sent.
|
||||
///<
|
||||
///< If an exception is thrown in the override then this
|
||||
///< object catches it and deletes iteself by calling
|
||||
///< doDelete().
|
||||
|
||||
virtual bool onReceive( const std::string & ) = 0 ;
|
||||
///< Called when a complete line is received from the peer.
|
||||
///< Returns false if no more lines should be delivered.
|
||||
|
||||
virtual void onData( const char * , ServerPeer::size_type ) ;
|
||||
///< Final override from ServerPeer.
|
||||
///< Final override from GNet::SocketProtocolSink.
|
||||
|
||||
private:
|
||||
BufferedServerPeer( const BufferedServerPeer & ) ;
|
||||
void operator=( const BufferedServerPeer & ) ;
|
||||
void logFlowControlAsserted() const ;
|
||||
void logFlowControlReleased() const ;
|
||||
void logFlowControlReasserted() const ;
|
||||
|
||||
private:
|
||||
Sender m_sender ;
|
||||
LineBuffer m_line_buffer ;
|
||||
bool m_throw ;
|
||||
std::string m_residue ;
|
||||
unsigned long m_n ;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
@ -25,7 +25,7 @@
|
||||
GNet::Client::Client( const ResolverInfo & remote_info , unsigned int connection_timeout ,
|
||||
unsigned int response_timeout , const std::string & eol , const Address & local_interface ,
|
||||
bool privileged , bool sync_dns ) :
|
||||
BufferedClient(remote_info,local_interface,privileged,sync_dns) ,
|
||||
HeapClient(remote_info,local_interface,privileged,sync_dns) ,
|
||||
m_done_signal(true) ,
|
||||
m_connected_signal(true) ,
|
||||
m_connection_timeout(connection_timeout) ,
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gbufferedclient.h"
|
||||
#include "gheapclient.h"
|
||||
#include "glinebuffer.h"
|
||||
#include "gtimer.h"
|
||||
#include "gslot.h"
|
||||
@ -48,7 +48,7 @@ namespace GNet
|
||||
/// are used by the containing object (in particular so that the
|
||||
/// container is informed when the client object deletes itself).
|
||||
///
|
||||
class GNet::Client : public GNet::BufferedClient
|
||||
class GNet::Client : public GNet::HeapClient
|
||||
{
|
||||
public:
|
||||
explicit Client( const ResolverInfo & remote_info , unsigned int connection_timeout = 0U ,
|
||||
@ -77,6 +77,10 @@ public:
|
||||
///< Returns a signal that incidcates that the client
|
||||
///< has successfully connected to the server.
|
||||
|
||||
G::Signal0 & secureSignal() ;
|
||||
///< Returns a signal that incidcates that the security
|
||||
///< layer has been successfully established.
|
||||
|
||||
protected:
|
||||
virtual ~Client() ;
|
||||
///< Destructor.
|
||||
@ -97,7 +101,7 @@ protected:
|
||||
///< Final override from GNet::SimpleClient.
|
||||
|
||||
virtual void onData( const char * , SimpleClient::size_type ) ;
|
||||
///< Final override from GNet::SimpleClient.
|
||||
///< Final override from GNet::SocketProtocolSink.
|
||||
|
||||
virtual void onConnecting() ;
|
||||
///< Final override from GNet::HeapClient.
|
||||
|
@ -87,11 +87,10 @@ void GNet::EventHandlerList::add( Descriptor fd , EventHandler * handler )
|
||||
|
||||
void GNet::EventHandlerList::remove( Descriptor fd )
|
||||
{
|
||||
G_DEBUG( "GNet::EventHandlerList::remove: " << m_type << "-list: " << "removing " << fd ) ;
|
||||
|
||||
Map::iterator p = m_map.find( fd ) ;
|
||||
if( p != m_map.end() )
|
||||
{
|
||||
G_DEBUG( "GNet::EventHandlerList::remove: " << m_type << "-list: " << "removing " << fd ) ;
|
||||
if( m_lock )
|
||||
{
|
||||
(*p).second = NULL ;
|
||||
|
@ -91,12 +91,6 @@ public:
|
||||
///< Postcondition: state == resolving <= returns true
|
||||
///< Postcondition: state == idle <= returns false
|
||||
|
||||
void cancelReq() ;
|
||||
///< Cancels an outstanding resolve request.
|
||||
///<
|
||||
///< Precondition: state == resolving
|
||||
///< Postcondition: state == idle
|
||||
|
||||
static std::string resolve( ResolverInfo & host_and_service , bool udp = false ) ;
|
||||
///< Does syncronous name resolution. Fills in the
|
||||
///< name and address fields of the supplied ResolverInfo
|
||||
|
@ -21,10 +21,13 @@
|
||||
#include "gdef.h"
|
||||
#include "gresolver.h"
|
||||
#include "glinebuffer.h"
|
||||
#include "gsender.h"
|
||||
#include "gsimpleclient.h"
|
||||
#include "gsocketprotocol.h"
|
||||
#include "gresolverinfo.h"
|
||||
#include "gexception.h"
|
||||
#include "gsocket.h"
|
||||
#include "gevent.h"
|
||||
#include "gmemory.h"
|
||||
#include "gstr.h"
|
||||
#include "gdebug.h"
|
||||
#include "glog.h"
|
||||
@ -37,122 +40,94 @@ namespace
|
||||
/// \class GNet::ResolverImp
|
||||
/// A pimple-pattern implementation class for GNet::Resolver.
|
||||
///
|
||||
class GNet::ResolverImp : public GNet::EventHandler
|
||||
/// Note that the implementation uses GNet::SimpleClient even though
|
||||
/// GNet::SimpleClient uses a resolver. This is possible because
|
||||
/// this class passes a fully-resolved ResolverInfo object to the
|
||||
/// client and the client class only instantiates a resolver
|
||||
/// when necessary.
|
||||
///
|
||||
class GNet::ResolverImp : public GNet::SimpleClient
|
||||
{
|
||||
public:
|
||||
ResolverImp( EventHandler & event_handler , Resolver & resolver , unsigned int port ) ;
|
||||
virtual ~ResolverImp() ;
|
||||
bool resolveReq( std::string host_part, std::string service_part , bool udp ) ;
|
||||
void cancelReq() ;
|
||||
bool busy() const ;
|
||||
|
||||
protected:
|
||||
virtual void onConnect() ;
|
||||
virtual void onSendComplete() ;
|
||||
virtual void onData( const char * , std::string::size_type ) ;
|
||||
virtual void onSecure() ;
|
||||
virtual void onException( std::exception & ) ;
|
||||
|
||||
private:
|
||||
void operator=( const ResolverImp & ) ;
|
||||
ResolverImp( const ResolverImp & ) ;
|
||||
void end() ;
|
||||
void readEvent() ;
|
||||
void writeEvent() ;
|
||||
void onException( std::exception & ) ;
|
||||
void operator=( const ResolverImp & ) ; // not implemented
|
||||
ResolverImp( const ResolverImp & ) ; // not implemented
|
||||
static ResolverInfo resolverInfo( unsigned int ) ;
|
||||
|
||||
private:
|
||||
EventHandler & m_event_handler ;
|
||||
Sender m_sender ;
|
||||
LineBuffer m_line_buffer ;
|
||||
Address m_address ;
|
||||
Resolver & m_outer ;
|
||||
StreamSocket * m_s ;
|
||||
LineBuffer m_line_buffer ;
|
||||
std::string m_request ;
|
||||
} ;
|
||||
|
||||
// ===
|
||||
|
||||
GNet::ResolverImp::ResolverImp( EventHandler & event_handler , Resolver & resolver , unsigned int port ) :
|
||||
SimpleClient(resolverInfo(port)) ,
|
||||
m_event_handler(event_handler) ,
|
||||
m_sender(event_handler) ,
|
||||
m_address(Address::localhost(port)) ,
|
||||
m_outer(resolver) ,
|
||||
m_s(NULL)
|
||||
m_outer(resolver)
|
||||
{
|
||||
}
|
||||
|
||||
GNet::ResolverImp::~ResolverImp()
|
||||
{
|
||||
delete m_s ;
|
||||
}
|
||||
|
||||
GNet::ResolverInfo GNet::ResolverImp::resolverInfo( unsigned int port )
|
||||
{
|
||||
ResolverInfo info( "localhost" , "0" ) ;
|
||||
info.update( Address::localhost(port) , "localhost" ) ;
|
||||
return info ;
|
||||
}
|
||||
|
||||
bool GNet::ResolverImp::resolveReq( std::string host_part, std::string service_part , bool udp )
|
||||
{
|
||||
if( m_s != NULL )
|
||||
if( ! m_request.empty() )
|
||||
return false ; // still busy
|
||||
|
||||
m_request = host_part + ":" + service_part + ":" + ( udp ? "udp" : "tcp" ) + "\n" ;
|
||||
m_s = new StreamSocket ;
|
||||
if( ! m_s->valid() || ! m_s->connect(m_address) )
|
||||
{
|
||||
StreamSocket * s = m_s ;
|
||||
m_s = NULL ;
|
||||
delete s ;
|
||||
return false ;
|
||||
}
|
||||
|
||||
if( connected() )
|
||||
send( m_request ) ;
|
||||
else
|
||||
{
|
||||
m_s->addWriteHandler( *this ) ;
|
||||
connect() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::onConnect()
|
||||
{
|
||||
if( ! m_request.empty() )
|
||||
send( m_request ) ;
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::writeEvent()
|
||||
void GNet::ResolverImp::onSendComplete()
|
||||
{
|
||||
G_ASSERT( m_s != NULL ) ;
|
||||
std::pair<bool,Address> peer_pair = m_s->getPeerAddress() ;
|
||||
bool connected = peer_pair.first ;
|
||||
|
||||
if( !connected )
|
||||
{
|
||||
end() ;
|
||||
m_outer.resolveCon( false , Address::invalidAddress() ,
|
||||
std::string("cannot connect to the resolver daemon at ") + m_address.displayString() ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( m_sender.busy() )
|
||||
{
|
||||
m_sender.resumeSending( *m_s ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_s->addReadHandler( *this ) ;
|
||||
m_s->dropWriteHandler() ;
|
||||
m_sender.send( *m_s , m_request ) ;
|
||||
}
|
||||
if( m_sender.failed() )
|
||||
{
|
||||
end() ;
|
||||
m_outer.resolveCon( false , Address::invalidAddress() ,
|
||||
std::string("cannot communicate with resolver daemon at ") + m_address.displayString() ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::readEvent()
|
||||
void GNet::ResolverImp::onSecure()
|
||||
{
|
||||
G_ASSERT( m_s != NULL ) ;
|
||||
|
||||
static char buffer[200U] ;
|
||||
ssize_t rc = m_s->read( buffer , sizeof(buffer) ) ;
|
||||
G_DEBUG( "GNet::ResolverImp::readEvent: " << rc << " byte(s)" ) ;
|
||||
|
||||
end() ;
|
||||
if( rc == 0 )
|
||||
{
|
||||
m_outer.resolveCon( false , Address::invalidAddress() , "disconnected" ) ;
|
||||
}
|
||||
else
|
||||
|
||||
void GNet::ResolverImp::onData( const char * p , std::string::size_type n )
|
||||
{
|
||||
std::string::size_type n = static_cast<std::string::size_type>(rc) ;
|
||||
m_line_buffer.add( buffer , n ) ;
|
||||
if( m_line_buffer.more() )
|
||||
m_line_buffer.add( p , n ) ;
|
||||
while( m_line_buffer.more() )
|
||||
{
|
||||
m_request.erase() ;
|
||||
|
||||
std::string result = m_line_buffer.line() ;
|
||||
G_DEBUG( "GNet::ResolverImp::readEvent: \"" << result << "\"" ) ;
|
||||
G::Str::trim( result , " \n\r" ) ;
|
||||
@ -172,27 +147,23 @@ void GNet::ResolverImp::readEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::onException( std::exception & e )
|
||||
{
|
||||
if( busy() )
|
||||
{
|
||||
m_request.erase() ;
|
||||
m_outer.resolveCon( false , Address::invalidAddress() , e.what() ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_event_handler.onException( e ) ;
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::cancelReq()
|
||||
{
|
||||
end() ;
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::end()
|
||||
{
|
||||
delete m_s ;
|
||||
m_s = NULL ;
|
||||
}
|
||||
|
||||
bool GNet::ResolverImp::busy() const
|
||||
{
|
||||
return m_s != NULL ;
|
||||
return ! m_request.empty() ;
|
||||
}
|
||||
|
||||
// ===
|
||||
@ -241,8 +212,4 @@ bool GNet::Resolver::busy() const
|
||||
return m_imp->busy() ;
|
||||
}
|
||||
|
||||
void GNet::Resolver::cancelReq()
|
||||
{
|
||||
m_imp->cancelReq() ;
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ public:
|
||||
bool valid() ;
|
||||
virtual ~ResolverImp() ;
|
||||
bool resolveReq( std::string host_part, std::string service_part , bool udp ) ;
|
||||
void cancelReq() ;
|
||||
bool busy() const ;
|
||||
|
||||
private:
|
||||
@ -104,11 +103,6 @@ bool GNet::ResolverImp::resolveReq( std::string host_part, std::string service_p
|
||||
return true ;
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::cancelReq()
|
||||
{
|
||||
cleanup() ;
|
||||
}
|
||||
|
||||
void GNet::ResolverImp::cleanup()
|
||||
{
|
||||
delete m_host_request ;
|
||||
@ -250,9 +244,3 @@ bool GNet::Resolver::busy() const
|
||||
return m_imp != NULL ? m_imp->busy() : true ;
|
||||
}
|
||||
|
||||
void GNet::Resolver::cancelReq()
|
||||
{
|
||||
if( m_imp != NULL )
|
||||
m_imp->cancelReq() ;
|
||||
}
|
||||
|
||||
|
@ -1,123 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
//
|
||||
// gsender.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gsender.h"
|
||||
#include "gassert.h"
|
||||
#include "glog.h"
|
||||
|
||||
GNet::Sender::Sender( EventHandler & handler ) :
|
||||
m_handler(handler) ,
|
||||
m_failed(false) ,
|
||||
m_n(0UL)
|
||||
{
|
||||
}
|
||||
|
||||
GNet::Sender::~Sender()
|
||||
{
|
||||
}
|
||||
|
||||
bool GNet::Sender::send( Socket & socket , const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
if( data.length() <= offset )
|
||||
return true ; // nothing to do
|
||||
|
||||
ssize_t rc = socket.write( data.data()+offset , data.length()-offset ) ;
|
||||
if( rc < 0 && ! socket.eWouldBlock() )
|
||||
{
|
||||
// fatal error, eg. disconnection
|
||||
m_failed = true ;
|
||||
return false ;
|
||||
}
|
||||
else if( rc < 0 || static_cast<std::string::size_type>(rc) < (data.length()-offset) )
|
||||
{
|
||||
// flow control asserted
|
||||
std::string::size_type sent = rc > 0 ? static_cast<size_t>(rc) : 0U ;
|
||||
m_n += sent ;
|
||||
|
||||
m_residue = data ;
|
||||
if( (sent+offset) != 0U )
|
||||
m_residue.erase( 0U , sent+offset ) ;
|
||||
|
||||
G_DEBUG( "GNet::Sender::send: flow control asserted: "
|
||||
<< "after " << m_n << " byte(s): "
|
||||
<< "sent " << sent << "/" << (data.length()-offset) << ": "
|
||||
<< m_residue.length() << " residue" ) ;
|
||||
|
||||
socket.addWriteHandler(m_handler) ;
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all sent
|
||||
m_n += data.length() ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
bool GNet::Sender::resumeSending( Socket & socket )
|
||||
{
|
||||
G_DEBUG( "GNet::Sender::resumeSending: flow-control released: residue " << m_residue.length() ) ;
|
||||
G_ASSERT( m_residue.length() != 0U ) ;
|
||||
|
||||
ssize_t rc = socket.write( m_residue.data() , m_residue.length() ) ;
|
||||
if( rc < 0 && ! socket.eWouldBlock() )
|
||||
{
|
||||
// fatal error, eg. disconnection
|
||||
m_failed = true ;
|
||||
return false ;
|
||||
}
|
||||
else if( rc < 0 || static_cast<std::string::size_type>(rc) < m_residue.length() )
|
||||
{
|
||||
// flow control re-asserted
|
||||
std::string::size_type sent = rc > 0 ? static_cast<std::string::size_type>(rc) : 0U ;
|
||||
m_n += sent ;
|
||||
|
||||
G_DEBUG( "GNet::Sender::resumeSending: flow-control reasserted: "
|
||||
<< "after " << m_n << " byte(s): "
|
||||
<< "sent " << sent << "/" << m_residue.length() ) ;
|
||||
|
||||
if( sent != 0U )
|
||||
m_residue.erase( 0U , sent ) ;
|
||||
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all sent
|
||||
m_n += m_residue.length() ;
|
||||
m_residue.erase() ;
|
||||
socket.dropWriteHandler() ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
bool GNet::Sender::failed() const
|
||||
{
|
||||
return m_failed ;
|
||||
}
|
||||
|
||||
bool GNet::Sender::busy() const
|
||||
{
|
||||
return ! m_residue.empty() ;
|
||||
}
|
||||
|
||||
/// \file gsender.cpp
|
@ -1,89 +0,0 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
///
|
||||
/// \file gsender.h
|
||||
///
|
||||
|
||||
#ifndef G_SENDER_H
|
||||
#define G_SENDER_H
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gserver.h"
|
||||
#include <string>
|
||||
|
||||
/// \namespace GNet
|
||||
namespace GNet
|
||||
{
|
||||
class Sender ;
|
||||
}
|
||||
|
||||
/// \class GNet::Sender
|
||||
/// A class that does buffered sending of data down a socket
|
||||
/// with flow-control.
|
||||
///
|
||||
class GNet::Sender
|
||||
{
|
||||
public:
|
||||
explicit Sender( EventHandler & handler ) ;
|
||||
///< Constructor with an event handler.
|
||||
|
||||
virtual ~Sender() ;
|
||||
///< Destructor.
|
||||
|
||||
bool send( Socket & socket , const std::string & data , std::string::size_type offset = 0U ) ;
|
||||
///< Sends data down the socket.
|
||||
///<
|
||||
///< Returns true if all the data is sent successfully.
|
||||
///<
|
||||
///< If flow control is asserted and the event handler
|
||||
///< constructor was used then the residue is saved
|
||||
///< internally, a write-event handler is installed on
|
||||
///< the socket on bahalf of the event handler
|
||||
///< and false is returned. When the socket's write-event
|
||||
///< is triggered the event handler is expected to call
|
||||
///< resumeSending() so that the residue can be sent.
|
||||
///<
|
||||
///< If there was any other error, or if flow control
|
||||
///< was asserted after default construction, then false
|
||||
///< is returned and failed() will return true.
|
||||
|
||||
bool resumeSending( Socket & ) ;
|
||||
///< To be called from the event-handler's write
|
||||
///< handler after flow-control has been released.
|
||||
///< If all residual data is sent then the socket's
|
||||
///< write handler is removed and true is returned.
|
||||
|
||||
bool failed() const ;
|
||||
///< Returns true after a fatal error when send()ing data
|
||||
///< down the socket.
|
||||
|
||||
bool busy() const ;
|
||||
///< Returns true if there is data queued up in the sender.
|
||||
|
||||
private:
|
||||
Sender( const Sender & ) ;
|
||||
void operator=( const Sender & ) ;
|
||||
|
||||
private:
|
||||
EventHandler & m_handler ;
|
||||
std::string m_residue ;
|
||||
bool m_failed ;
|
||||
unsigned long m_n ;
|
||||
} ;
|
||||
|
||||
#endif
|
@ -32,6 +32,7 @@
|
||||
GNet::ServerPeer::ServerPeer( Server::PeerInfo peer_info ) :
|
||||
m_address(peer_info.m_address) ,
|
||||
m_socket(peer_info.m_socket) ,
|
||||
m_sp(*this,*this,*m_socket.get()) ,
|
||||
m_handle(peer_info.m_handle) ,
|
||||
m_delete_timer(*this,&ServerPeer::onTimeout,*this)
|
||||
{
|
||||
@ -56,6 +57,11 @@ std::string GNet::ServerPeer::logId() const
|
||||
return m_address.displayString() + "@" + m_socket->asString() ;
|
||||
}
|
||||
|
||||
void GNet::ServerPeer::sslAccept()
|
||||
{
|
||||
m_sp.sslAccept() ;
|
||||
}
|
||||
|
||||
GNet::StreamSocket & GNet::ServerPeer::socket()
|
||||
{
|
||||
G_ASSERT( m_socket.get() != NULL ) ;
|
||||
@ -64,24 +70,14 @@ GNet::StreamSocket & GNet::ServerPeer::socket()
|
||||
|
||||
void GNet::ServerPeer::readEvent()
|
||||
{
|
||||
char buffer[c_buffer_size] ;
|
||||
buffer[0] = '\0' ;
|
||||
const size_t buffer_size = G::Test::enabled("small-server-input-buffer") ? 3 : sizeof(buffer) ;
|
||||
ssize_t rc = m_socket->read( buffer , buffer_size ) ;
|
||||
|
||||
if( rc == 0 || (rc == -1 && !m_socket->eWouldBlock()) )
|
||||
try
|
||||
{
|
||||
m_sp.readEvent() ;
|
||||
}
|
||||
catch( SocketProtocol::ReadError & ) // avoid the warning in onException()
|
||||
{
|
||||
doDelete() ;
|
||||
}
|
||||
else if( rc != -1 )
|
||||
{
|
||||
G_ASSERT( static_cast<size_t>(rc) <= buffer_size ) ;
|
||||
onData( buffer , static_cast<size_type>(rc) ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
; // no-op (windows)
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::ServerPeer::onException( std::exception & e )
|
||||
@ -117,6 +113,25 @@ void GNet::ServerPeer::doDeleteThis( int )
|
||||
delete this ;
|
||||
}
|
||||
|
||||
bool GNet::ServerPeer::send( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
return m_sp.send( data , offset ) ;
|
||||
}
|
||||
|
||||
void GNet::ServerPeer::writeEvent()
|
||||
{
|
||||
try
|
||||
{
|
||||
if( m_sp.writeEvent() )
|
||||
onSendComplete() ;
|
||||
}
|
||||
catch( std::exception & e ) // strategy
|
||||
{
|
||||
G_WARNING( "GNet::ServerPeer::writeEvent: exception: " << e.what() ) ;
|
||||
doDelete() ;
|
||||
}
|
||||
}
|
||||
|
||||
// ===
|
||||
|
||||
GNet::Server::Server( unsigned int listening_port )
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gsocket.h"
|
||||
#include "gsocketprotocol.h"
|
||||
#include "gtimer.h"
|
||||
#include "gconnection.h"
|
||||
#include "gevent.h"
|
||||
@ -184,16 +185,20 @@ private:
|
||||
/// delete themselves when the connection is lost.
|
||||
/// \see GNet::Server, GNet::EventHandler
|
||||
///
|
||||
class GNet::ServerPeer : public GNet::EventHandler , public GNet::Connection
|
||||
class GNet::ServerPeer : public GNet::EventHandler , public GNet::Connection , public GNet::SocketProtocolSink
|
||||
{
|
||||
public:
|
||||
typedef std::string::size_type size_type ;
|
||||
enum { c_buffer_size = 1500 } ;
|
||||
|
||||
explicit ServerPeer( Server::PeerInfo ) ;
|
||||
///< Constructor. This constructor is only used from within the
|
||||
///< override of GServer::newPeer().
|
||||
|
||||
bool send( const std::string & data , std::string::size_type offset = 0U ) ;
|
||||
///< Sends data down the socket to the peer. Returns
|
||||
///< false if flow control asserted (see onSendComplete()).
|
||||
///< Throws on error.
|
||||
|
||||
void doDelete() ;
|
||||
///< Does "onDelete(); delete this".
|
||||
|
||||
@ -212,6 +217,9 @@ public:
|
||||
virtual void readEvent() ;
|
||||
///< Final override from GNet::EventHandler.
|
||||
|
||||
virtual void writeEvent() ;
|
||||
///< Final override from GNet::EventHandler.
|
||||
|
||||
virtual void onException( std::exception & ) ;
|
||||
///< Final override from GNet::EventHandler.
|
||||
|
||||
@ -229,8 +237,17 @@ protected:
|
||||
///< Called just before destruction. (Note that the
|
||||
///< object typically deletes itself.)
|
||||
|
||||
virtual void onData( const char * , size_type ) = 0 ;
|
||||
///< Called on receipt of data.
|
||||
virtual void onSendComplete() = 0 ;
|
||||
///< Called after flow-control has been released and all
|
||||
///< residual data sent.
|
||||
///<
|
||||
///< If an exception is thrown in the override then this
|
||||
///< object catches it and deletes iteself by calling
|
||||
///< doDelete().
|
||||
|
||||
void sslAccept() ;
|
||||
///< Waits for the peer to start a secure session.
|
||||
///< See also GNet::SocketProtocolSink::onSecure().
|
||||
|
||||
StreamSocket & socket() ;
|
||||
///< Returns a reference to the client-server connection
|
||||
@ -247,7 +264,8 @@ private:
|
||||
|
||||
private:
|
||||
Address m_address ;
|
||||
std::auto_ptr<StreamSocket> m_socket ;
|
||||
std::auto_ptr<StreamSocket> m_socket ; // order dependency -- first
|
||||
SocketProtocol m_sp ; // order dependency -- second
|
||||
ServerPeerHandle * m_handle ;
|
||||
Timer<ServerPeer> m_delete_timer ;
|
||||
} ;
|
||||
|
@ -38,7 +38,6 @@ namespace
|
||||
const int c_retries = 10 ; // number of retries when using a privileged local port number
|
||||
const int c_port_start = 512 ;
|
||||
const int c_port_end = 1024 ;
|
||||
const size_t c_buffer_size = 1500U ; // see also gserver.h
|
||||
const char * c_cannot_connect_to = "cannot connect to " ;
|
||||
}
|
||||
|
||||
@ -46,8 +45,6 @@ namespace
|
||||
|
||||
GNet::SimpleClient::SimpleClient( const ResolverInfo & remote ,
|
||||
const Address & local_address , bool privileged , bool sync_dns ) :
|
||||
m_resolver(*this) ,
|
||||
m_s(NULL) ,
|
||||
m_remote(remote) ,
|
||||
m_local_address(local_address) ,
|
||||
m_privileged(privileged) ,
|
||||
@ -67,7 +64,7 @@ GNet::SimpleClient::~SimpleClient()
|
||||
std::string GNet::SimpleClient::logId() const
|
||||
{
|
||||
std::string s = m_remote.displayString(true) ;
|
||||
if( m_s != NULL )
|
||||
if( m_s.get() != NULL )
|
||||
s.append( std::string() + "@" + m_s->asString() ) ; // cf. ServerPeer::logId()
|
||||
return s ;
|
||||
}
|
||||
@ -86,11 +83,18 @@ void GNet::SimpleClient::updateResolverInfo( const ResolverInfo & update )
|
||||
}
|
||||
}
|
||||
|
||||
GNet::Socket & GNet::SimpleClient::socket()
|
||||
GNet::StreamSocket & GNet::SimpleClient::socket()
|
||||
{
|
||||
if( m_s == NULL )
|
||||
if( m_s.get() == NULL )
|
||||
throw NotConnected() ;
|
||||
return *m_s ;
|
||||
return *m_s.get() ;
|
||||
}
|
||||
|
||||
const GNet::StreamSocket & GNet::SimpleClient::socket() const
|
||||
{
|
||||
if( m_s.get() == NULL )
|
||||
throw NotConnected() ;
|
||||
return *m_s.get() ;
|
||||
}
|
||||
|
||||
void GNet::SimpleClient::connect()
|
||||
@ -133,10 +137,10 @@ void GNet::SimpleClient::connect()
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_resolver.resolveReq( m_remote.str() ) )
|
||||
{
|
||||
if( m_resolver.get() == NULL )
|
||||
m_resolver <<= new ClientResolver( *this ) ;
|
||||
if( !m_resolver->resolveReq( m_remote.str() ) )
|
||||
throw DnsError( m_remote.str() ) ;
|
||||
}
|
||||
setState( Resolving ) ;
|
||||
}
|
||||
}
|
||||
@ -144,8 +148,8 @@ void GNet::SimpleClient::connect()
|
||||
void GNet::SimpleClient::immediateConnection()
|
||||
{
|
||||
G_DEBUG( "GNet::SimpleClient::connect: immediate connection" ) ;
|
||||
s().addReadHandler( *this ) ;
|
||||
s().addExceptionHandler( *this ) ;
|
||||
socket().addReadHandler( *this ) ;
|
||||
socket().addExceptionHandler( *this ) ;
|
||||
setState( Connected ) ;
|
||||
onConnectImp() ; // from within connect()
|
||||
onConnect() ; // from within connect()
|
||||
@ -171,23 +175,10 @@ int GNet::SimpleClient::getRandomPort()
|
||||
return r + c_port_start ;
|
||||
}
|
||||
|
||||
GNet::StreamSocket & GNet::SimpleClient::s()
|
||||
{
|
||||
G_ASSERT( m_s != NULL ) ;
|
||||
return *m_s ;
|
||||
}
|
||||
|
||||
const GNet::StreamSocket & GNet::SimpleClient::s() const
|
||||
{
|
||||
G_ASSERT( m_s != NULL ) ;
|
||||
return *m_s ;
|
||||
}
|
||||
|
||||
void GNet::SimpleClient::close()
|
||||
{
|
||||
StreamSocket * s = m_s ;
|
||||
m_s = NULL ;
|
||||
delete s ;
|
||||
m_sp <<= 0 ;
|
||||
m_s <<= 0 ;
|
||||
}
|
||||
|
||||
bool GNet::SimpleClient::connected() const
|
||||
@ -217,15 +208,18 @@ bool GNet::SimpleClient::startConnecting()
|
||||
|
||||
// create and open a socket
|
||||
//
|
||||
delete m_s ; m_s = NULL ; // just in case -- should be null
|
||||
m_s = new StreamSocket( m_remote.address() ) ;
|
||||
if( !s().valid() )
|
||||
m_s <<= new StreamSocket( m_remote.address() ) ;
|
||||
if( !socket().valid() )
|
||||
throw ConnectError( "cannot open socket" ) ;
|
||||
|
||||
// create a socket protocol object
|
||||
//
|
||||
m_sp <<= new SocketProtocol( *this , *this , *m_s.get() ) ;
|
||||
|
||||
// specifiy this as a 'write' event handler for the socket
|
||||
// (before the connect() in case it is reentrant)
|
||||
//
|
||||
s().addWriteHandler( *this ) ;
|
||||
socket().addWriteHandler( *this ) ;
|
||||
|
||||
// bind a local address to the socket and connect
|
||||
//
|
||||
@ -256,7 +250,7 @@ bool GNet::SimpleClient::startConnecting()
|
||||
//
|
||||
bool immediate = status == ImmediateSuccess ;
|
||||
if( status != Success )
|
||||
s().dropWriteHandler() ;
|
||||
socket().dropWriteHandler() ;
|
||||
|
||||
return immediate ;
|
||||
}
|
||||
@ -264,7 +258,7 @@ bool GNet::SimpleClient::startConnecting()
|
||||
bool GNet::SimpleClient::localBind( Address local_address )
|
||||
{
|
||||
G::Root claim_root ;
|
||||
bool bound = s().bind(local_address) ;
|
||||
bool bound = socket().bind(local_address) ;
|
||||
G_DEBUG( "GNet::SimpleClient::bind: bound local address " << local_address.displayString() ) ;
|
||||
return bound ;
|
||||
}
|
||||
@ -277,7 +271,7 @@ GNet::SimpleClient::ConnectStatus GNet::SimpleClient::connectCore( Address remot
|
||||
// initiate the connection
|
||||
//
|
||||
bool immediate = false ;
|
||||
if( !s().connect( remote_address , &immediate ) )
|
||||
if( !socket().connect( remote_address , &immediate ) )
|
||||
{
|
||||
G_DEBUG( "GNet::SimpleClient::connectCore: immediate failure" ) ;
|
||||
error = c_cannot_connect_to + remote_address.displayString() ; // see canRetry()
|
||||
@ -301,14 +295,14 @@ void GNet::SimpleClient::writeEvent()
|
||||
|
||||
if( m_state == Connected )
|
||||
{
|
||||
s().dropWriteHandler() ;
|
||||
onWriteable() ;
|
||||
if( m_sp->writeEvent() )
|
||||
onSendComplete() ;
|
||||
}
|
||||
else if( m_state == Connecting && s().hasPeer() )
|
||||
else if( m_state == Connecting && socket().hasPeer() )
|
||||
{
|
||||
s().addReadHandler( *this ) ;
|
||||
s().addExceptionHandler( *this ) ;
|
||||
s().dropWriteHandler() ;
|
||||
socket().addReadHandler( *this ) ;
|
||||
socket().addExceptionHandler( *this ) ;
|
||||
socket().dropWriteHandler() ;
|
||||
|
||||
setState( Connected ) ;
|
||||
onConnectImp() ;
|
||||
@ -322,24 +316,9 @@ void GNet::SimpleClient::writeEvent()
|
||||
|
||||
void GNet::SimpleClient::readEvent()
|
||||
{
|
||||
char buffer[c_buffer_size] ;
|
||||
buffer[0] = '\0' ;
|
||||
const size_t buffer_size = G::Test::enabled("small-client-input-buffer") ? 3 : sizeof(buffer) ;
|
||||
ssize_t rc = s().read( buffer , buffer_size ) ;
|
||||
|
||||
if( rc == 0 || ( rc == -1 && !s().eWouldBlock() ) )
|
||||
{
|
||||
throw ReadError() ;
|
||||
}
|
||||
else if( rc != -1 )
|
||||
{
|
||||
G_ASSERT( static_cast<size_t>(rc) <= buffer_size ) ;
|
||||
onData( buffer , static_cast<size_type>(rc) ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
; // no-op (windows)
|
||||
}
|
||||
G_ASSERT( m_sp.get() != NULL ) ;
|
||||
if( m_sp.get() != NULL )
|
||||
m_sp->readEvent() ;
|
||||
}
|
||||
|
||||
void GNet::SimpleClient::setState( State new_state )
|
||||
@ -350,23 +329,41 @@ void GNet::SimpleClient::setState( State new_state )
|
||||
std::pair<bool,GNet::Address> GNet::SimpleClient::localAddress() const
|
||||
{
|
||||
return
|
||||
m_s != NULL ?
|
||||
s().getLocalAddress() :
|
||||
m_s.get() != NULL ?
|
||||
socket().getLocalAddress() :
|
||||
std::make_pair(false,GNet::Address::invalidAddress()) ;
|
||||
}
|
||||
|
||||
std::pair<bool,GNet::Address> GNet::SimpleClient::peerAddress() const
|
||||
{
|
||||
return
|
||||
m_s != NULL ?
|
||||
s().getPeerAddress() :
|
||||
m_s.get() != NULL ?
|
||||
socket().getPeerAddress() :
|
||||
std::make_pair(false,GNet::Address::invalidAddress()) ;
|
||||
}
|
||||
|
||||
void GNet::SimpleClient::sslConnect()
|
||||
{
|
||||
if( m_sp.get() == NULL )
|
||||
throw NotConnected( "for ssl-connect" ) ;
|
||||
m_sp->sslConnect() ;
|
||||
}
|
||||
|
||||
void GNet::SimpleClient::onConnectImp()
|
||||
{
|
||||
}
|
||||
|
||||
bool GNet::SimpleClient::send( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
bool rc = m_sp->send( data , offset ) ;
|
||||
onSendImp() ; // remove this ugly mechanism sometime
|
||||
return rc ;
|
||||
}
|
||||
|
||||
void GNet::SimpleClient::onSendImp()
|
||||
{
|
||||
}
|
||||
|
||||
// ===
|
||||
|
||||
GNet::ClientResolver::ClientResolver( SimpleClient & client ) :
|
||||
|
@ -24,12 +24,14 @@
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gaddress.h"
|
||||
#include "gmemory.h"
|
||||
#include "gconnection.h"
|
||||
#include "gexception.h"
|
||||
#include "geventhandler.h"
|
||||
#include "gresolver.h"
|
||||
#include "gresolverinfo.h"
|
||||
#include "gsocket.h"
|
||||
#include "gsocketprotocol.h"
|
||||
#include "gevent.h"
|
||||
#include <string>
|
||||
|
||||
@ -62,11 +64,10 @@ private:
|
||||
|
||||
/// \class GNet::SimpleClient
|
||||
/// A class for making an outgoing connection to a remote server.
|
||||
/// The class handles address resolution and connection issues and it reads
|
||||
/// incoming data. However, it has only minimal support for flow-control
|
||||
/// when sending.
|
||||
/// The class handles address resolution and connection issues, it reads
|
||||
/// incoming data and it manages flow-control when sending.
|
||||
///
|
||||
class GNet::SimpleClient : public GNet::EventHandler , public GNet::Connection
|
||||
class GNet::SimpleClient : public GNet::EventHandler , public GNet::Connection , public GNet::SocketProtocolSink
|
||||
{
|
||||
public:
|
||||
enum ConnectStatus { Success , Failure , Retry , ImmediateSuccess } ;
|
||||
@ -74,7 +75,6 @@ public:
|
||||
G_EXCEPTION( DnsError , "dns error" ) ;
|
||||
G_EXCEPTION( ConnectError , "connect failure" ) ;
|
||||
G_EXCEPTION( NotConnected , "socket not connected" ) ;
|
||||
G_EXCEPTION( ReadError , "read error: disconnected" ) ;
|
||||
typedef std::string::size_type size_type ;
|
||||
|
||||
SimpleClient( const ResolverInfo & remote_info ,
|
||||
@ -132,13 +132,20 @@ public:
|
||||
virtual void writeEvent() ;
|
||||
///< Final override from GNet::EventHandler.
|
||||
|
||||
bool send( const std::string & data , std::string::size_type offset = 0 ) ;
|
||||
///< Returns true if all sent, or false if flow
|
||||
///< control was asserted. Throws on error.
|
||||
|
||||
protected:
|
||||
virtual ~SimpleClient() ;
|
||||
///< Destructor.
|
||||
|
||||
Socket & socket() ;
|
||||
StreamSocket & socket() ;
|
||||
///< Returns a reference to the socket. Throws if not connected.
|
||||
|
||||
const StreamSocket & socket() const ;
|
||||
///< Returns a const reference to the socket. Throws if not connected.
|
||||
|
||||
virtual void onConnect() = 0 ;
|
||||
///< Called once connected. May (unfortunately) be
|
||||
///< called from within connect().
|
||||
@ -147,17 +154,19 @@ protected:
|
||||
///< An alternative to onConnect() for private implementation
|
||||
///< classes. The default implementation does nothing.
|
||||
|
||||
virtual void onData( const char * data , size_type size ) = 0 ;
|
||||
///< Called on receipt of data.
|
||||
virtual void onSendComplete() = 0 ;
|
||||
///< Called when all residual data from send() has been sent.
|
||||
|
||||
virtual void onWriteable() = 0 ;
|
||||
///< Called when the socket becomes writable
|
||||
///< after flow control is released.
|
||||
virtual void onSendImp() ;
|
||||
///< Called from within send().
|
||||
|
||||
void sslConnect() ;
|
||||
///< Starts TLS/SSL client-side negotiation.
|
||||
|
||||
static bool canRetry( const std::string & reason ) ;
|
||||
///< Parses the given failure reason and returns
|
||||
///< true if the client can reasonably retry
|
||||
///< at some later time.
|
||||
///< at some later time. (Not used?)
|
||||
|
||||
std::string logId() const ;
|
||||
///< Returns a identification string for logging purposes.
|
||||
@ -173,17 +182,18 @@ private:
|
||||
void operator=( const SimpleClient& ) ; // not implemented
|
||||
void close() ;
|
||||
static int getRandomPort() ;
|
||||
StreamSocket & s() ;
|
||||
const StreamSocket & s() const ;
|
||||
bool startConnecting() ;
|
||||
bool localBind( Address ) ;
|
||||
ConnectStatus connectCore( Address remote_address , std::string *error_p ) ;
|
||||
void setState( State ) ;
|
||||
void immediateConnection() ;
|
||||
void logFlowControlAsserted() const ;
|
||||
void logFlowControlReleased() const ;
|
||||
|
||||
private:
|
||||
ClientResolver m_resolver ;
|
||||
StreamSocket * m_s ;
|
||||
std::auto_ptr<ClientResolver> m_resolver ;
|
||||
std::auto_ptr<StreamSocket> m_s ;
|
||||
std::auto_ptr<SocketProtocol> m_sp ;
|
||||
ResolverInfo m_remote ;
|
||||
Address m_local_address ;
|
||||
bool m_privileged ;
|
||||
|
@ -21,9 +21,13 @@
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gclient.h"
|
||||
#include "gtest.h"
|
||||
|
||||
bool GNet::SimpleClient::synchronousDnsDefault()
|
||||
{
|
||||
if( G::Test::enabled("asynchronous-dns") )
|
||||
return false ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
@ -150,12 +150,12 @@ bool GNet::Socket::connect( const Address & address , bool *done )
|
||||
return true;
|
||||
}
|
||||
|
||||
ssize_t GNet::Socket::write( const char *buf , size_t len )
|
||||
GNet::Socket::ssize_type GNet::Socket::write( const char * buf , size_type len )
|
||||
{
|
||||
if( static_cast<ssize_t>(len) < 0 )
|
||||
if( static_cast<ssize_type>(len) < 0 )
|
||||
G_WARNING( "GNet::Socket::write: too big" ) ; // EMSGSIZE from ::send() ?
|
||||
|
||||
ssize_t nsent = ::send( m_socket , buf , len , 0 ) ;
|
||||
ssize_type nsent = ::send( m_socket , buf , len , 0 ) ;
|
||||
|
||||
if( sizeError(nsent) ) // if -1
|
||||
{
|
||||
@ -163,7 +163,7 @@ ssize_t GNet::Socket::write( const char *buf , size_t len )
|
||||
G_DEBUG( "GNet::Socket::write: write error " << m_reason ) ;
|
||||
return -1 ;
|
||||
}
|
||||
else if( nsent < 0 || static_cast<size_t>(nsent) < len )
|
||||
else if( nsent < 0 || static_cast<size_type>(nsent) < len )
|
||||
{
|
||||
m_reason = reason() ;
|
||||
}
|
||||
@ -320,17 +320,21 @@ GNet::StreamSocket::~StreamSocket()
|
||||
{
|
||||
}
|
||||
|
||||
ssize_t GNet::StreamSocket::read( char * buf , size_t len )
|
||||
GNet::Socket::ssize_type GNet::StreamSocket::read( char * buf , size_type len )
|
||||
{
|
||||
if( len == 0 ) return 0 ;
|
||||
G_ASSERT( valid() ) ;
|
||||
ssize_t nread = ::recv( m_socket , buf , len , 0 ) ;
|
||||
ssize_type nread = ::recv( m_socket , buf , len , 0 ) ;
|
||||
if( sizeError(nread) )
|
||||
{
|
||||
m_reason = reason() ;
|
||||
G_DEBUG( "GNet::StreamSocket::read: fd " << m_socket << ": read error " << m_reason ) ;
|
||||
return -1 ;
|
||||
}
|
||||
if( nread == 0 )
|
||||
{
|
||||
G_DEBUG( "GNet::StreamSocket::read: fd " << m_socket << ": read zero bytes" ) ;
|
||||
}
|
||||
return nread ;
|
||||
}
|
||||
|
||||
@ -379,11 +383,11 @@ void GNet::DatagramSocket::disconnect()
|
||||
m_reason = reason() ;
|
||||
}
|
||||
|
||||
ssize_t GNet::DatagramSocket::read( void *buf , size_t len , Address & src_address )
|
||||
GNet::Socket::ssize_type GNet::DatagramSocket::read( void *buf , size_type len , Address & src_address )
|
||||
{
|
||||
sockaddr sender ;
|
||||
socklen_t sender_len = sizeof(sender) ;
|
||||
ssize_t nread = ::recvfrom( m_socket , reinterpret_cast<char*>(buf) , len , 0 , &sender , &sender_len ) ;
|
||||
ssize_type nread = ::recvfrom( m_socket , reinterpret_cast<char*>(buf) , len , 0 , &sender , &sender_len ) ;
|
||||
if( sizeError(nread) )
|
||||
{
|
||||
m_reason = reason() ;
|
||||
@ -394,11 +398,11 @@ ssize_t GNet::DatagramSocket::read( void *buf , size_t len , Address & src_addre
|
||||
return nread ;
|
||||
}
|
||||
|
||||
ssize_t GNet::DatagramSocket::write( const char *buf , size_t len , const Address &dst )
|
||||
GNet::Socket::ssize_type GNet::DatagramSocket::write( const char *buf , size_type len , const Address &dst )
|
||||
{
|
||||
G_DEBUG( "GNet::DatagramSocket::write: sending " << len << " bytes to " << dst.displayString() ) ;
|
||||
|
||||
ssize_t nsent = ::sendto( m_socket, buf, len, 0, dst.address(), dst.length() ) ;
|
||||
ssize_type nsent = ::sendto( m_socket, buf, len, 0, dst.address(), dst.length() ) ;
|
||||
if( nsent < 0 )
|
||||
{
|
||||
m_reason = reason() ;
|
||||
|
@ -39,21 +39,24 @@ namespace GNet
|
||||
|
||||
/// \class GNet::Socket
|
||||
///
|
||||
/// The Socket class encapsulates an asynchronous
|
||||
/// (ie. non-blocking) Unix socket file descriptor or a Windows
|
||||
/// 'SOCKET' handle. The class hides all differences between BSD
|
||||
/// sockets and WinSock.
|
||||
/// The Socket class encapsulates a non-blocking
|
||||
/// Unix socket file descriptor or a Windows 'SOCKET' handle.
|
||||
/// The class hides all differences between BSD sockets and
|
||||
/// WinSock.
|
||||
///
|
||||
/// (Non-blocking network i/o is particularly appropriate for single-
|
||||
/// threaded server processes which manage multiple client connections.
|
||||
/// The main disagvantage is that flow control has to be managed
|
||||
/// explicitly: see Socket::write() and Socket::eWouldBlock().)
|
||||
///
|
||||
/// Exceptions are _not_ used for error reporting.
|
||||
/// Exceptions are not used.
|
||||
///
|
||||
class GNet::Socket
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type ;
|
||||
typedef ssize_t ssize_type ;
|
||||
|
||||
virtual ~Socket() ;
|
||||
///< Destructor.
|
||||
|
||||
@ -110,7 +113,7 @@ public:
|
||||
///< address for incoming connections or incoming
|
||||
///< datagrams.
|
||||
|
||||
virtual ssize_t write( const char * buf , size_t len ) ;
|
||||
virtual ssize_type write( const char * buf , size_type len ) ;
|
||||
///< Sends data. For datagram sockets the datagram
|
||||
///< is sent to the address specified in the
|
||||
///< previous connect(). Returns the amount
|
||||
@ -199,7 +202,7 @@ protected:
|
||||
static bool valid( Descriptor s ) ;
|
||||
static int reason() ;
|
||||
static bool error( int rc ) ;
|
||||
static bool sizeError( ssize_t size ) ;
|
||||
static bool sizeError( ssize_type size ) ;
|
||||
void prepare() ;
|
||||
void setFault() ;
|
||||
void setNoLinger() ;
|
||||
@ -259,6 +262,9 @@ public:
|
||||
class GNet::StreamSocket : public GNet::Socket
|
||||
{
|
||||
public:
|
||||
typedef Socket::size_type size_type ;
|
||||
typedef Socket::ssize_type ssize_type ;
|
||||
|
||||
StreamSocket() ;
|
||||
///< Default constructor. Check with valid().
|
||||
|
||||
@ -269,14 +275,14 @@ public:
|
||||
virtual ~StreamSocket() ;
|
||||
///< Destructor.
|
||||
|
||||
ssize_t read( char * buffer , size_t buffer_length ) ;
|
||||
///< Reads from the TCP stream. Returns
|
||||
///< 0 if the connection has been lost.
|
||||
///< Returns -1 on error, or if there is
|
||||
///< nothing to read (eWouldBlock() true).
|
||||
///< Note that under Windows there can
|
||||
///< be nothing to read even after receiving
|
||||
///< a read event.
|
||||
ssize_type read( char * buffer , size_type buffer_length ) ;
|
||||
///< Reads data from the socket stream.
|
||||
///<
|
||||
///< Returns 0 if the connection has been lost.
|
||||
///< Returns -1 on error, or if there is nothing
|
||||
///< to read (eWouldBlock() true). Note that
|
||||
///< having nothing to read is not an error,
|
||||
///< even after getting a read event.
|
||||
|
||||
AcceptPair accept() ;
|
||||
///< Accepts an incoming connection, returning
|
||||
@ -306,19 +312,19 @@ public:
|
||||
virtual ~DatagramSocket() ;
|
||||
///< Destructor.
|
||||
|
||||
ssize_t read( void * buffer , size_t len , Address & src ) ;
|
||||
ssize_type read( void * buffer , size_type len , Address & src ) ;
|
||||
///< Reads a datagram and returns the sender's address
|
||||
///< by reference. If connect() has been used then
|
||||
///< only datagrams from the address specified in the
|
||||
///< connect() call will be received.
|
||||
|
||||
ssize_t write( const char * buffer , size_t len , const Address & dst ) ;
|
||||
ssize_type write( const char * buffer , size_type len , const Address & dst ) ;
|
||||
///< Sends a datagram to the given address.
|
||||
///< This form of write() should be used
|
||||
///< if there is no connect() assocation
|
||||
///< in effect.
|
||||
|
||||
ssize_t write( const char * buffer , size_t len ) ;
|
||||
ssize_type write( const char * buffer , size_type len ) ;
|
||||
///< See Socket::write().
|
||||
|
||||
void disconnect() ;
|
||||
@ -334,7 +340,7 @@ private:
|
||||
///
|
||||
|
||||
inline
|
||||
ssize_t GNet::DatagramSocket::write( const char *buf, size_t len )
|
||||
GNet::Socket::ssize_type GNet::DatagramSocket::write( const char *buf, size_type len )
|
||||
{
|
||||
return Socket::write(buf,len) ;
|
||||
}
|
||||
|
500
src/gnet/gsocketprotocol.cpp
Normal file
500
src/gnet/gsocketprotocol.cpp
Normal file
@ -0,0 +1,500 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
//
|
||||
// gsocketprotocol.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gssl.h"
|
||||
#include "gsocketprotocol.h"
|
||||
#include "gtest.h"
|
||||
#include "gassert.h"
|
||||
#include "glog.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const size_t c_buffer_size = 1500U ;
|
||||
class LocalSocket : public GNet::StreamSocket // TODO remove access hack
|
||||
{
|
||||
public: int fd() const { return m_socket ; }
|
||||
} ;
|
||||
}
|
||||
|
||||
class GNet::SocketProtocolImp
|
||||
{
|
||||
private:
|
||||
typedef SocketProtocol::ReadError ReadError ;
|
||||
typedef SocketProtocol::SendError SendError ;
|
||||
enum State { State_raw , State_connecting , State_accepting , State_writing , State_idle } ;
|
||||
|
||||
EventHandler & m_handler ;
|
||||
SocketProtocol::Sink & m_sink ;
|
||||
StreamSocket & m_socket ;
|
||||
std::string m_raw_residue ;
|
||||
std::string m_ssl_send_data ;
|
||||
bool m_failed ;
|
||||
unsigned long m_n ;
|
||||
GSsl::Protocol * m_ssl ;
|
||||
State m_state ;
|
||||
|
||||
public:
|
||||
SocketProtocolImp( EventHandler & handler , SocketProtocol::Sink & sink , StreamSocket & socket ) ;
|
||||
~SocketProtocolImp() ;
|
||||
void readEvent() ;
|
||||
bool writeEvent() ;
|
||||
bool send( const std::string & data , std::string::size_type offset ) ;
|
||||
void sslConnect() ;
|
||||
void sslAccept() ;
|
||||
bool sslEnabled() const ;
|
||||
|
||||
private:
|
||||
SocketProtocolImp( const SocketProtocolImp & ) ;
|
||||
void operator=( const SocketProtocolImp & ) ;
|
||||
static GSsl::Protocol * newProtocol() ;
|
||||
static void log( int level , const std::string & line ) ;
|
||||
StreamSocket & socket() ;
|
||||
bool failed() const ;
|
||||
bool rawSendImp( const std::string & , std::string::size_type , std::string & ) ;
|
||||
void rawReadEvent() ;
|
||||
bool rawWriteEvent() ;
|
||||
bool rawSend( const std::string & data , std::string::size_type offset ) ;
|
||||
void sslReadImp() ;
|
||||
bool sslSendImp() ;
|
||||
void sslConnectImp() ;
|
||||
void sslAcceptImp() ;
|
||||
void logFlowControlReleased() ;
|
||||
void logFlowControlAsserted() ;
|
||||
void logFlowControlReasserted() ;
|
||||
} ;
|
||||
|
||||
GNet::SocketProtocolImp::SocketProtocolImp( EventHandler & handler ,
|
||||
SocketProtocol::Sink & sink , StreamSocket & socket ) :
|
||||
m_handler(handler) ,
|
||||
m_sink(sink) ,
|
||||
m_socket(socket) ,
|
||||
m_failed(false) ,
|
||||
m_n(0UL) ,
|
||||
m_ssl(NULL) ,
|
||||
m_state(State_raw)
|
||||
{
|
||||
}
|
||||
|
||||
GNet::SocketProtocolImp::~SocketProtocolImp()
|
||||
{
|
||||
delete m_ssl ;
|
||||
}
|
||||
|
||||
GNet::StreamSocket & GNet::SocketProtocolImp::socket()
|
||||
{
|
||||
return m_socket ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::readEvent()
|
||||
{
|
||||
G_DEBUG( "SocketProtocolImp::readEvent: state=" << m_state ) ;
|
||||
if( m_state == State_raw )
|
||||
rawReadEvent() ;
|
||||
else if( m_state == State_connecting )
|
||||
sslConnectImp() ;
|
||||
else if( m_state == State_accepting )
|
||||
sslAcceptImp() ;
|
||||
else if( m_state == State_writing )
|
||||
sslSendImp() ;
|
||||
else // State_idle
|
||||
sslReadImp() ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::writeEvent()
|
||||
{
|
||||
G_DEBUG( "GNet::SocketProtocolImp::writeEvent: state=" << m_state ) ;
|
||||
bool rc = true ;
|
||||
if( m_state == State_raw )
|
||||
rc = rawWriteEvent() ;
|
||||
else if( m_state == State_connecting )
|
||||
sslConnectImp() ;
|
||||
else if( m_state == State_accepting )
|
||||
sslAcceptImp() ;
|
||||
else
|
||||
sslSendImp() ;
|
||||
return rc ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::send( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
if( data.empty() || offset >= data.length() )
|
||||
return true ;
|
||||
|
||||
bool rc = true ;
|
||||
if( m_state == State_raw )
|
||||
{
|
||||
rc = rawSend( data , offset ) ;
|
||||
}
|
||||
else if( m_state == State_connecting || m_state == State_accepting )
|
||||
{
|
||||
throw SendError( "still busy negotiating" ) ;
|
||||
}
|
||||
else if( m_state == State_writing )
|
||||
{
|
||||
// throw here rather than add to the pending buffer because openssl
|
||||
// requires that the parameters stay the same -- we could use double
|
||||
// buffering, with a buffer switch and a call to sslSendImp()
|
||||
// rather than returning to the idle state, but in practice
|
||||
// we rely on the client code taking account of the return value
|
||||
// from send() and waiting for onSendComplete() when required
|
||||
//
|
||||
throw SendError( "still busy sending the last packet" ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = State_writing ;
|
||||
m_ssl_send_data.append( data.substr(offset) ) ;
|
||||
rc = sslSendImp() ;
|
||||
}
|
||||
return rc ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::log( int level , const std::string & line )
|
||||
{
|
||||
if( level == 2 )
|
||||
G_WARNING( "GNet::SocketProtocolImp::log: " << line ) ;
|
||||
else
|
||||
G_DEBUG( "ssl: " << line ) ;
|
||||
}
|
||||
|
||||
GSsl::Protocol * GNet::SocketProtocolImp::newProtocol()
|
||||
{
|
||||
GSsl::Library * library = GSsl::Library::instance() ;
|
||||
if( library == NULL )
|
||||
throw G::Exception( "SocketProtocolImp::newProtocol: internal error: no library instance" ) ;
|
||||
|
||||
return new GSsl::Protocol( *library , log ) ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::sslConnect()
|
||||
{
|
||||
G_DEBUG( "SocketProtocolImp::sslConnect" ) ;
|
||||
G_ASSERT( m_ssl == NULL ) ;
|
||||
|
||||
m_ssl = newProtocol() ;
|
||||
m_state = State_connecting ;
|
||||
sslConnectImp() ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::sslConnectImp()
|
||||
{
|
||||
G_DEBUG( "SocketProtocolImp::sslConnectImp" ) ;
|
||||
G_ASSERT( m_ssl != NULL ) ;
|
||||
G_ASSERT( m_state == State_connecting ) ;
|
||||
LocalSocket & p = reinterpret_cast<LocalSocket&>(socket()) ;
|
||||
GSsl::Protocol::Result rc = m_ssl->connect( p.fd() ) ;
|
||||
G_DEBUG( "SocketProtocolImp::sslConnectImp: result=" << GSsl::Protocol::str(rc) ) ;
|
||||
if( rc == GSsl::Protocol::Result_error )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_raw ;
|
||||
throw ReadError( "ssl connect" ) ;
|
||||
}
|
||||
else if( rc == GSsl::Protocol::Result_read )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
}
|
||||
else if( rc == GSsl::Protocol::Result_write )
|
||||
{
|
||||
socket().addWriteHandler( m_handler ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_idle ;
|
||||
G_DEBUG( "SocketProtocolImp::sslConnectImp: calling onSecure" ) ;
|
||||
m_sink.onSecure() ;
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::sslAccept()
|
||||
{
|
||||
G_DEBUG( "SocketProtocolImp::sslAccept" ) ;
|
||||
G_ASSERT( m_ssl == NULL ) ;
|
||||
m_ssl = newProtocol() ;
|
||||
m_state = State_accepting ;
|
||||
sslAcceptImp() ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::sslAcceptImp()
|
||||
{
|
||||
G_DEBUG( "SocketProtocolImp::sslAcceptImp" ) ;
|
||||
G_ASSERT( m_ssl != NULL ) ;
|
||||
G_ASSERT( m_state == State_accepting ) ;
|
||||
LocalSocket & p = reinterpret_cast<LocalSocket&>(socket()) ;
|
||||
GSsl::Protocol::Result rc = m_ssl->accept( p.fd() ) ;
|
||||
G_DEBUG( "SocketProtocolImp::sslAcceptImp: result=" << GSsl::Protocol::str(rc) ) ;
|
||||
if( rc == GSsl::Protocol::Result_error )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_raw ;
|
||||
throw ReadError( "ssl accept" ) ;
|
||||
}
|
||||
else if( rc == GSsl::Protocol::Result_read )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
}
|
||||
else if( rc == GSsl::Protocol::Result_write )
|
||||
{
|
||||
socket().addWriteHandler( m_handler ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_idle ;
|
||||
G_DEBUG( "SocketProtocolImp::sslAcceptImp: calling onSecure" ) ;
|
||||
m_sink.onSecure() ;
|
||||
}
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::sslEnabled() const
|
||||
{
|
||||
return m_state == State_writing || m_state == State_idle ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::sslSendImp()
|
||||
{
|
||||
G_ASSERT( m_state == State_writing ) ;
|
||||
bool rc = false ;
|
||||
GSsl::Protocol::ssize_type n = 0 ;
|
||||
GSsl::Protocol::Result result = m_ssl->write( m_ssl_send_data.data() , m_ssl_send_data.size() , n ) ;
|
||||
if( result == GSsl::Protocol::Result_error )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_idle ;
|
||||
throw SendError( "ssl write" ) ;
|
||||
}
|
||||
else if( result == GSsl::Protocol::Result_read )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
}
|
||||
else if( result == GSsl::Protocol::Result_write )
|
||||
{
|
||||
socket().addWriteHandler( m_handler ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
rc = n == static_cast<GSsl::Protocol::ssize_type>(m_ssl_send_data.size()) ;
|
||||
m_ssl_send_data.erase( 0U , n ) ;
|
||||
m_state = State_idle ;
|
||||
}
|
||||
return rc ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::sslReadImp()
|
||||
{
|
||||
G_DEBUG( "SocketProtocolImp::sslReadImp" ) ;
|
||||
G_ASSERT( m_state == State_idle ) ;
|
||||
G_ASSERT( m_ssl != NULL ) ;
|
||||
static char buffer[c_buffer_size] ;
|
||||
GSsl::Protocol::ssize_type n = 0 ;
|
||||
GSsl::Protocol::Result rc = m_ssl->read( buffer , sizeof(buffer) , n ) ;
|
||||
G_DEBUG( "SocketProtocolImp::sslReadImp: result=" << GSsl::Protocol::str(rc) ) ;
|
||||
if( rc == GSsl::Protocol::Result_error )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_idle ;
|
||||
throw ReadError( "ssl read" ) ;
|
||||
}
|
||||
else if( rc == GSsl::Protocol::Result_read )
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
}
|
||||
else if( rc == GSsl::Protocol::Result_write )
|
||||
{
|
||||
socket().addWriteHandler( m_handler ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
m_state = State_idle ;
|
||||
G_DEBUG( "SocketProtocolImp::sslReadImp: calling onData(): " << n ) ;
|
||||
m_sink.onData( buffer , static_cast<std::string::size_type>(n) ) ;
|
||||
}
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::rawReadEvent()
|
||||
{
|
||||
char buffer[c_buffer_size] ;
|
||||
buffer[0] = '\0' ;
|
||||
const size_t buffer_size = G::Test::enabled("small-client-input-buffer") ? 3 : sizeof(buffer) ;
|
||||
ssize_t rc = socket().read( buffer , buffer_size ) ;
|
||||
|
||||
if( rc == 0 || ( rc == -1 && !socket().eWouldBlock() ) )
|
||||
{
|
||||
throw ReadError() ;
|
||||
}
|
||||
else if( rc != -1 )
|
||||
{
|
||||
G_ASSERT( static_cast<size_t>(rc) <= buffer_size ) ;
|
||||
m_sink.onData( buffer , static_cast<std::string::size_type>(rc) ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
; // -1 && eWouldBlock() -- no-op (esp. for windows)
|
||||
}
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::rawSend( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
bool all_sent = rawSendImp( data , offset , m_raw_residue ) ;
|
||||
if( !all_sent && failed() )
|
||||
throw SendError() ;
|
||||
if( !all_sent )
|
||||
{
|
||||
socket().addWriteHandler( m_handler ) ;
|
||||
logFlowControlAsserted() ;
|
||||
}
|
||||
return all_sent ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::rawWriteEvent()
|
||||
{
|
||||
socket().dropWriteHandler() ;
|
||||
logFlowControlReleased() ;
|
||||
bool all_sent = rawSendImp( m_raw_residue , 0 , m_raw_residue ) ;
|
||||
if( !all_sent && failed() )
|
||||
throw SendError() ;
|
||||
if( !all_sent )
|
||||
{
|
||||
socket().addWriteHandler( m_handler ) ;
|
||||
logFlowControlReasserted() ;
|
||||
}
|
||||
return all_sent ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::rawSendImp( const std::string & data , std::string::size_type offset ,
|
||||
std::string & residue )
|
||||
{
|
||||
if( data.length() <= offset )
|
||||
return true ; // nothing to do
|
||||
|
||||
ssize_t rc = socket().write( data.data()+offset , data.length()-offset ) ;
|
||||
if( rc < 0 && ! socket().eWouldBlock() )
|
||||
{
|
||||
// fatal error, eg. disconnection
|
||||
m_failed = true ;
|
||||
residue.erase() ;
|
||||
return false ;
|
||||
}
|
||||
else if( rc < 0 || static_cast<std::string::size_type>(rc) < (data.length()-offset) )
|
||||
{
|
||||
// flow control asserted
|
||||
std::string::size_type sent = rc > 0 ? static_cast<size_t>(rc) : 0U ;
|
||||
m_n += sent ;
|
||||
|
||||
residue = data ;
|
||||
if( (sent+offset) != 0U )
|
||||
residue.erase( 0U , sent+offset ) ;
|
||||
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all sent
|
||||
m_n += data.length() ;
|
||||
residue.erase() ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocolImp::failed() const
|
||||
{
|
||||
return m_failed ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::logFlowControlAsserted()
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::SocketProtocolImp::send: @" << socket().asString() << ": flow control asserted" ) ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::logFlowControlReleased()
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::SocketProtocolImp::send: @" << socket().asString() << ": flow control released" ) ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocolImp::logFlowControlReasserted()
|
||||
{
|
||||
const bool log = G::Test::enabled("log-flow-control") ;
|
||||
if( log )
|
||||
G_LOG( "GNet::SocketProtocolImp::send: @" << socket().asString() << ": flow control reasserted" ) ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GNet::SocketProtocol::SocketProtocol( EventHandler & handler , Sink & sink , StreamSocket & socket ) :
|
||||
m_imp( new SocketProtocolImp(handler,sink,socket) )
|
||||
{
|
||||
}
|
||||
|
||||
GNet::SocketProtocol::~SocketProtocol()
|
||||
{
|
||||
delete m_imp ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocol::readEvent()
|
||||
{
|
||||
m_imp->readEvent() ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocol::writeEvent()
|
||||
{
|
||||
return m_imp->writeEvent() ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocol::send( const std::string & data , std::string::size_type offset )
|
||||
{
|
||||
return m_imp->send( data , offset ) ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocol::sslCapable()
|
||||
{
|
||||
return GSsl::Library::instance() != NULL && GSsl::Library::instance()->enabled() ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocol::sslConnect()
|
||||
{
|
||||
m_imp->sslConnect() ;
|
||||
}
|
||||
|
||||
void GNet::SocketProtocol::sslAccept()
|
||||
{
|
||||
m_imp->sslAccept() ;
|
||||
}
|
||||
|
||||
bool GNet::SocketProtocol::sslEnabled() const
|
||||
{
|
||||
return m_imp->sslEnabled() ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GNet::SocketProtocolSink::~SocketProtocolSink()
|
||||
{
|
||||
}
|
||||
|
||||
/// \file gsocketprotocol.cpp
|
113
src/gnet/gsocketprotocol.h
Normal file
113
src/gnet/gsocketprotocol.h
Normal file
@ -0,0 +1,113 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
///
|
||||
/// \file gsocketprotocol.h
|
||||
///
|
||||
|
||||
#ifndef G_SOCKET_PROTOCOL_H
|
||||
#define G_SOCKET_PROTOCOL_H
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gnet.h"
|
||||
#include "gsocket.h"
|
||||
#include "gexception.h"
|
||||
#include <string>
|
||||
|
||||
/// \namespace GNet
|
||||
namespace GNet
|
||||
{
|
||||
class SocketProtocol ;
|
||||
class SocketProtocolImp ;
|
||||
class SocketProtocolSink ;
|
||||
}
|
||||
|
||||
/// \class GNet::SocketProtocol
|
||||
/// A class for doing read() and write() on
|
||||
/// a connected socket and installing and removing event
|
||||
/// handlers as appropriate. This abstraction allows
|
||||
/// for using SSL.
|
||||
///
|
||||
class GNet::SocketProtocol
|
||||
{
|
||||
public:
|
||||
typedef SocketProtocolSink Sink ;
|
||||
G_EXCEPTION( ReadError , "read error: disconnected" ) ;
|
||||
G_EXCEPTION( SendError , "peer disconnected" ) ;
|
||||
|
||||
SocketProtocol( EventHandler & , Sink & , StreamSocket & ) ;
|
||||
///< Constructor. The references are kept.
|
||||
|
||||
~SocketProtocol() ;
|
||||
///< Destructor.
|
||||
|
||||
void readEvent() ;
|
||||
///< Called on receipt of a read event. Delivers
|
||||
///< data via the sink interface. Throws ReadError
|
||||
///< on error.
|
||||
|
||||
bool writeEvent() ;
|
||||
///< Called on receipt of a write event. Sends
|
||||
///< more pending data down the connection.
|
||||
///< Returns true if all pending data was
|
||||
///< sent. Throws SendError on error.
|
||||
|
||||
bool send( const std::string & data , std::string::size_type offset = 0U ) ;
|
||||
///< Sends data. Returns false if flow control asserted.
|
||||
///< Throws SendError on error.
|
||||
|
||||
static bool sslCapable() ;
|
||||
///< Returns true if the implementation supports SSL.
|
||||
|
||||
void sslConnect() ;
|
||||
///< Initiates the SSL protocol.
|
||||
|
||||
void sslAccept() ;
|
||||
///< Accepts the SSL protocol.
|
||||
|
||||
bool sslEnabled() const ;
|
||||
///< Returns true if SSL is active.
|
||||
|
||||
private:
|
||||
SocketProtocol( const SocketProtocol & ) ;
|
||||
void operator=( const SocketProtocol & ) ;
|
||||
|
||||
private:
|
||||
SocketProtocolImp * m_imp ;
|
||||
} ;
|
||||
|
||||
/// \class GNet::SocketProtocolSink
|
||||
/// An interface used by GNet::SocketProtocol
|
||||
/// to deliver data from a socket.
|
||||
///
|
||||
class GNet::SocketProtocolSink
|
||||
{
|
||||
public:
|
||||
virtual ~SocketProtocolSink() ;
|
||||
///< Destructor.
|
||||
|
||||
protected:
|
||||
friend class SocketProtocolImp ;
|
||||
|
||||
virtual void onData( const char * , std::string::size_type ) = 0 ;
|
||||
///< Called when data is read from the socket.
|
||||
|
||||
virtual void onSecure() = 0 ;
|
||||
///< Called once the secure socket protocol has
|
||||
///< been successfully negotiated.
|
||||
} ;
|
||||
|
||||
#endif
|
@ -20,7 +20,6 @@
|
||||
|
||||
mk_sources=\
|
||||
gaddress_ipv4.cpp \
|
||||
gbufferedclient.cpp \
|
||||
gbufferedserverpeer.cpp \
|
||||
gclient.cpp \
|
||||
gconnection.cpp \
|
||||
@ -39,12 +38,12 @@ mk_sources=\
|
||||
gresolverinfo.cpp \
|
||||
gresolver_ipv4.cpp \
|
||||
gresolver_win32.cpp \
|
||||
gsender.cpp \
|
||||
gserver.cpp \
|
||||
gsimpleclient.cpp \
|
||||
gsimpleclient_win32.cpp \
|
||||
gsocket.cpp \
|
||||
gsocket_win32.cpp \
|
||||
gsocketprotocol.cpp \
|
||||
gtimer.cpp \
|
||||
gtimerlist.cpp
|
||||
|
||||
|
@ -125,6 +125,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -50,6 +50,10 @@ void GPop::ServerPeer::onDelete()
|
||||
G_LOG_S( "GPop::ServerPeer: pop connection closed: " << peerAddress().second.displayString() ) ;
|
||||
}
|
||||
|
||||
void GPop::ServerPeer::onSecure()
|
||||
{
|
||||
}
|
||||
|
||||
bool GPop::ServerPeer::onReceive( const std::string & line )
|
||||
{
|
||||
processLine( line ) ;
|
||||
|
@ -66,6 +66,9 @@ protected:
|
||||
virtual bool onReceive( const std::string & ) ;
|
||||
///< Final override from GNet::BufferedServerPeer.
|
||||
|
||||
virtual void onSecure() ;
|
||||
///< Final override from GNet::SocketProtocolSink.
|
||||
|
||||
virtual void onSendComplete() ;
|
||||
///< Final override from GNet::BufferedServerPeer.
|
||||
|
||||
|
@ -17,10 +17,10 @@
|
||||
|
||||
EXTRA_DIST=\
|
||||
gmessagestore_win32.cpp \
|
||||
gsasl_cyrus.cpp \
|
||||
gsasl_gnu.cpp \
|
||||
mingw.mak
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gnet -DG_SPOOLDIR=\"$(e_spooldir)\"
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gssl -I$(top_srcdir)/src/gnet -DG_SPOOLDIR=\"$(e_spooldir)\"
|
||||
|
||||
noinst_LIBRARIES = libgsmtp.a
|
||||
|
||||
|
@ -138,6 +138,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
@ -191,10 +195,10 @@ top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
EXTRA_DIST = \
|
||||
gmessagestore_win32.cpp \
|
||||
gsasl_cyrus.cpp \
|
||||
gsasl_gnu.cpp \
|
||||
mingw.mak
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gnet -DG_SPOOLDIR=\"$(e_spooldir)\"
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib -I$(top_srcdir)/src/gssl -I$(top_srcdir)/src/gnet -DG_SPOOLDIR=\"$(e_spooldir)\"
|
||||
noinst_LIBRARIES = libgsmtp.a
|
||||
libgsmtp_a_SOURCES = \
|
||||
gadminserver.cpp \
|
||||
|
@ -80,6 +80,10 @@ void GSmtp::AdminServerPeer::onDelete()
|
||||
G_LOG_S( "GSmtp::AdminServerPeer: admin connection closed: " << peerAddress().second.displayString() ) ;
|
||||
}
|
||||
|
||||
void GSmtp::AdminServerPeer::onSecure()
|
||||
{
|
||||
}
|
||||
|
||||
bool GSmtp::AdminServerPeer::onReceive( const std::string & line )
|
||||
{
|
||||
if( is(line,"flush") )
|
||||
|
@ -70,6 +70,9 @@ protected:
|
||||
virtual void onDelete() ;
|
||||
///< Final override from GNet::ServerPeer.
|
||||
|
||||
virtual void onSecure() ;
|
||||
///< Final override from GNet::SocketProtocolSink.
|
||||
|
||||
private:
|
||||
AdminServerPeer( const AdminServerPeer & ) ;
|
||||
void operator=( const AdminServerPeer & ) ;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "gmemory.h"
|
||||
#include "gxtext.h"
|
||||
#include "gclientprotocol.h"
|
||||
#include "gsocketprotocol.h"
|
||||
#include "gresolver.h"
|
||||
#include "glog.h"
|
||||
#include "gassert.h"
|
||||
@ -39,7 +40,9 @@ GSmtp::ClientProtocol::ClientProtocol( Sender & sender , const Secrets & secrets
|
||||
m_thishost(config.thishost_name) ,
|
||||
m_state(sInit) ,
|
||||
m_to_accepted(0U) ,
|
||||
m_server_has_auth(false) ,
|
||||
m_server_has_8bitmime(false) ,
|
||||
m_server_has_tls(false) ,
|
||||
m_message_is_8bit(false) ,
|
||||
m_authenticated_with_server(false) ,
|
||||
m_must_authenticate(config.must_authenticate) ,
|
||||
@ -74,8 +77,15 @@ void GSmtp::ClientProtocol::start( const std::string & from , const G::Strings &
|
||||
|
||||
void GSmtp::ClientProtocol::preprocessorDone( const std::string & reason )
|
||||
{
|
||||
// sneakily convert the preprocessor response into an smtp Reply
|
||||
applyEvent( reason.empty() ? Reply::ok() : Reply::error(std::string("preprocessing: ")+reason) ) ;
|
||||
// convert the preprocessor response into a pretend smtp Reply
|
||||
applyEvent( reason.empty() ?
|
||||
Reply::ok(Reply::Internal_2xx) : Reply::error(std::string("preprocessing: ")+reason) ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ClientProtocol::secure()
|
||||
{
|
||||
// convert the event into a pretend smtp Reply
|
||||
applyEvent( Reply::ok(Reply::Internal_2yy) ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ClientProtocol::sendDone()
|
||||
@ -238,30 +248,43 @@ bool GSmtp::ClientProtocol::applyEvent( const Reply & reply , bool is_start_even
|
||||
m_state = sSentHelo ;
|
||||
sendHelo() ;
|
||||
}
|
||||
else if( (m_state==sSentEhlo || m_state==sSentHelo) && reply.is(Reply::Ok_250) )
|
||||
else if( ( m_state == sSentEhlo || m_state == sSentHelo || m_state == sSentTlsEhlo ) && reply.is(Reply::Ok_250) )
|
||||
{
|
||||
G_ASSERT( m_sasl.get() != NULL ) ;
|
||||
G_DEBUG( "GSmtp::ClientProtocol::applyEvent: ehlo reply \""
|
||||
<< G::Str::printable(reply.text()) << "\"" ) ;
|
||||
|
||||
bool server_auth = serverAuth( reply ) ;
|
||||
m_server_has_auth = serverAuth( reply ) ;
|
||||
m_server_has_8bitmime = ( m_state == sSentEhlo || m_state == sSentTlsEhlo ) && reply.textContains("\n8BITMIME");
|
||||
m_server_has_tls = m_state == sSentTlsEhlo || ( m_state == sSentEhlo && reply.textContains("\nSTARTTLS") ) ;
|
||||
m_auth_mechanism = m_sasl->preferred( serverAuthMechanisms(reply) ) ;
|
||||
m_server_has_8bitmime = m_state == sSentEhlo && reply.textContains("\n8BITMIME") ;
|
||||
|
||||
if( server_auth && !m_sasl->active() )
|
||||
if( m_server_has_tls && !GNet::SocketProtocol::sslCapable() )
|
||||
{
|
||||
std::string msg( "GSmtp::ClientProtocol::applyEvent: cannot do tls/ssl required by remote smtp server" );
|
||||
if( !m_auth_mechanism.empty() ) msg.append( ": authentication will probably fail" ) ;
|
||||
G_WARNING( msg ) ;
|
||||
}
|
||||
|
||||
if( m_state == sSentEhlo && m_server_has_tls && GNet::SocketProtocol::sslCapable() )
|
||||
{
|
||||
m_state = sStartTls ;
|
||||
send( "STARTTLS" ) ;
|
||||
}
|
||||
else if( m_server_has_auth && !m_sasl->active() )
|
||||
{
|
||||
throw AuthenticationRequired() ;
|
||||
}
|
||||
else if( server_auth && m_sasl->active() && m_auth_mechanism.empty() )
|
||||
else if( m_server_has_auth && m_sasl->active() && m_auth_mechanism.empty() )
|
||||
{
|
||||
throw NoMechanism() ;
|
||||
}
|
||||
else if( server_auth && m_sasl->active() )
|
||||
else if( m_server_has_auth && m_sasl->active() )
|
||||
{
|
||||
m_state = sAuth1 ;
|
||||
send( std::string("AUTH ") + m_auth_mechanism ) ;
|
||||
}
|
||||
else if( !server_auth && m_sasl->active() && m_must_authenticate )
|
||||
else if( !m_server_has_auth && m_sasl->active() && m_must_authenticate )
|
||||
{
|
||||
// (this makes sense if we need to propagate messages' authentication credentials)
|
||||
throw AuthenticationNotSupported() ;
|
||||
@ -272,11 +295,25 @@ bool GSmtp::ClientProtocol::applyEvent( const Reply & reply , bool is_start_even
|
||||
startPreprocessing() ;
|
||||
}
|
||||
}
|
||||
else if( m_state == sStartTls && reply.is(Reply::ServiceReady_220) )
|
||||
{
|
||||
m_sender.protocolSend( std::string() , 0U , true ) ; // go secure
|
||||
}
|
||||
else if( m_state == sStartTls && reply.is(Reply::NotAvailable_454) )
|
||||
{
|
||||
throw TlsError( reply.errorText() ) ;
|
||||
}
|
||||
else if( m_state == sStartTls && reply.is(Reply::Internal_2yy) )
|
||||
{
|
||||
m_state = sSentTlsEhlo ;
|
||||
sendEhlo() ;
|
||||
}
|
||||
else if( m_state == sAuth1 && reply.is(Reply::Challenge_334) && Base64::valid(reply.text()) )
|
||||
{
|
||||
bool done = true ;
|
||||
bool error = false ;
|
||||
std::string rsp = m_sasl->response( m_auth_mechanism , Base64::decode(reply.text()) , done , error ) ;
|
||||
bool sensitive = false ;
|
||||
std::string rsp = m_sasl->response( m_auth_mechanism , Base64::decode(reply.text()) , done , error , sensitive);
|
||||
if( error )
|
||||
{
|
||||
m_state = sAuth2 ;
|
||||
@ -285,7 +322,7 @@ bool GSmtp::ClientProtocol::applyEvent( const Reply & reply , bool is_start_even
|
||||
else
|
||||
{
|
||||
m_state = done ? sAuth2 : m_state ;
|
||||
send( Base64::encode(rsp,std::string()) ) ;
|
||||
send( Base64::encode(rsp,std::string()) , false , sensitive ) ;
|
||||
}
|
||||
}
|
||||
else if( m_state == sAuth1 && reply.is(Reply::NotAuthenticated_535) )
|
||||
@ -309,7 +346,7 @@ bool GSmtp::ClientProtocol::applyEvent( const Reply & reply , bool is_start_even
|
||||
startPreprocessing() ; // (continue with or without sucessful authentication)
|
||||
}
|
||||
}
|
||||
else if( m_state == sPreprocessing && reply.positive() )
|
||||
else if( m_state == sPreprocessing && reply.is(Reply::Internal_2xx) )
|
||||
{
|
||||
m_state = sSentMail ;
|
||||
sendMail() ;
|
||||
@ -354,14 +391,12 @@ bool GSmtp::ClientProtocol::applyEvent( const Reply & reply , bool is_start_even
|
||||
|
||||
size_t n = sendLines() ;
|
||||
|
||||
const bool log_content = false ; // set true here and in sendLine() if debugging
|
||||
if( !log_content )
|
||||
G_LOG( "GSmtp::ClientProtocol: tx>>: [" << n << " line(s) of content]" ) ;
|
||||
|
||||
if( endOfContent() )
|
||||
{
|
||||
m_state = sSentDot ;
|
||||
send( "." , true , log_content ) ;
|
||||
send( "." , true ) ;
|
||||
}
|
||||
}
|
||||
else if( m_state == sSentDataStub && !( reply.is(Reply::OkForData_354) || reply.positive() ) )
|
||||
@ -480,7 +515,7 @@ bool GSmtp::ClientProtocol::sendLine( std::string & line )
|
||||
if( !stream.fail() )
|
||||
{
|
||||
line.append( crlf() ) ;
|
||||
bool all_sent = m_sender.protocolSend( line , line.at(1U) == '.' ? 0U : 1U ) ;
|
||||
bool all_sent = m_sender.protocolSend( line , line.at(1U) == '.' ? 0U : 1U , false ) ;
|
||||
if( !all_sent && m_response_timeout != 0U )
|
||||
startTimer( m_response_timeout ) ; // use response timer for when flow-control asserted
|
||||
ok = all_sent ;
|
||||
@ -489,16 +524,21 @@ bool GSmtp::ClientProtocol::sendLine( std::string & line )
|
||||
return ok ;
|
||||
}
|
||||
|
||||
bool GSmtp::ClientProtocol::send( const std::string & line , bool eot , bool log )
|
||||
bool GSmtp::ClientProtocol::send( const std::string & line , bool eot , bool sensitive )
|
||||
{
|
||||
if( m_response_timeout != 0U )
|
||||
startTimer( m_response_timeout ) ;
|
||||
|
||||
std::string prefix( !eot && line.length() && line.at(0U) == '.' ? "." : "" ) ;
|
||||
if( log )
|
||||
if( sensitive )
|
||||
{
|
||||
G_LOG( "GSmtp::ClientProtocol: tx>>: [response not logged]" ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
G_LOG( "GSmtp::ClientProtocol: tx>>: \"" << prefix << G::Str::printable(line) << "\"" ) ;
|
||||
|
||||
return m_sender.protocolSend( prefix + line + crlf() , 0U ) ;
|
||||
}
|
||||
return m_sender.protocolSend( prefix + line + crlf() , 0U , false ) ;
|
||||
}
|
||||
|
||||
const std::string & GSmtp::ClientProtocol::crlf()
|
||||
@ -551,6 +591,19 @@ GSmtp::ClientProtocolReply GSmtp::ClientProtocolReply::ok()
|
||||
return reply ;
|
||||
}
|
||||
|
||||
GSmtp::ClientProtocolReply GSmtp::ClientProtocolReply::ok( Value v )
|
||||
{
|
||||
int i = static_cast<int>(v) ;
|
||||
G_ASSERT( i >= 200 && i <= 299 ) ;
|
||||
std::ostringstream ss ;
|
||||
ss << i << " OK" ;
|
||||
ClientProtocolReply reply( ss.str() ) ;
|
||||
G_ASSERT( reply.positive() ) ;
|
||||
G_ASSERT( reply.errorText().empty() ) ;
|
||||
G_ASSERT( reply.is(v) ) ;
|
||||
return reply ;
|
||||
}
|
||||
|
||||
GSmtp::ClientProtocolReply GSmtp::ClientProtocolReply::error( const std::string & reason )
|
||||
{
|
||||
ClientProtocolReply reply( std::string("500 ")+G::Str::printable(reason) ) ;
|
||||
@ -587,7 +640,8 @@ bool GSmtp::ClientProtocolReply::is( Value v ) const
|
||||
|
||||
std::string GSmtp::ClientProtocolReply::errorText() const
|
||||
{
|
||||
return value() == 250 ? std::string() : ( m_text.empty() ? std::string("error") : m_text ) ;
|
||||
const bool positive_completion = type() == PositiveCompletion ;
|
||||
return positive_completion ? std::string() : ( m_text.empty() ? std::string("error") : m_text ) ;
|
||||
}
|
||||
|
||||
std::string GSmtp::ClientProtocolReply::text() const
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
} ;
|
||||
enum Value
|
||||
{
|
||||
Internal_2xx = 222 ,
|
||||
Internal_2yy = 223 ,
|
||||
ServiceReady_220 = 220 ,
|
||||
Ok_250 = 250 ,
|
||||
Authenticated_235 = 235 ,
|
||||
@ -76,12 +78,16 @@ public:
|
||||
NotImplemented_502 = 502 ,
|
||||
BadSequence_503 = 503 ,
|
||||
NotAuthenticated_535 = 535 ,
|
||||
NotAvailable_454 = 454 ,
|
||||
Invalid = 0
|
||||
} ;
|
||||
|
||||
static ClientProtocolReply ok() ;
|
||||
///< Factory function for an ok reply.
|
||||
|
||||
static ClientProtocolReply ok( Value ) ;
|
||||
///< Factory function for an ok reply with a specific 2xx value.
|
||||
|
||||
static ClientProtocolReply error( const std::string & reason ) ;
|
||||
///< Factory function for a generalised error reply.
|
||||
|
||||
@ -155,16 +161,17 @@ class GSmtp::ClientProtocol : private GNet::AbstractTimer
|
||||
public:
|
||||
G_EXCEPTION( NotReady , "not ready" ) ;
|
||||
G_EXCEPTION( ResponseError , "protocol error: unexpected response" ) ;
|
||||
G_EXCEPTION( NoMechanism , "cannot do authentication mandated by the server" ) ;
|
||||
G_EXCEPTION( AuthenticationRequired , "authentication required by the server" ) ;
|
||||
G_EXCEPTION( AuthenticationNotSupported , "authentication not supported by the server" ) ;
|
||||
G_EXCEPTION( NoMechanism , "cannot do authentication mandated by the remote smtp server" ) ;
|
||||
G_EXCEPTION( AuthenticationRequired , "authentication required by the remote smtp server" ) ;
|
||||
G_EXCEPTION( AuthenticationNotSupported , "authentication not supported by the remote smtp server" ) ;
|
||||
G_EXCEPTION( AuthenticationError , "authentication error" ) ;
|
||||
G_EXCEPTION( TlsError , "tls/ssl error" ) ;
|
||||
typedef ClientProtocolReply Reply ;
|
||||
|
||||
/// An interface used by ClientProtocol to send protocol messages.
|
||||
class Sender
|
||||
{
|
||||
public: virtual bool protocolSend( const std::string & , size_t offset ) = 0 ;
|
||||
public: virtual bool protocolSend( const std::string & , size_t offset , bool go_secure ) = 0 ;
|
||||
///< Called by the Protocol class to send network data to
|
||||
///< the peer.
|
||||
///<
|
||||
@ -236,6 +243,10 @@ public:
|
||||
///< its thing. The reason string should be empty
|
||||
///< on success.
|
||||
|
||||
void secure() ;
|
||||
///< To be called when the secure socket protocol
|
||||
///< has been successfully established.
|
||||
|
||||
bool apply( const std::string & rx ) ;
|
||||
///< Called on receipt of a line of text from the server.
|
||||
///< Returns true if the protocol is done and the doneSignal()
|
||||
@ -249,7 +260,7 @@ protected:
|
||||
///< Final override from GNet::AbstractTimer.
|
||||
|
||||
private:
|
||||
bool send( const std::string & , bool eot = false , bool log = true ) ;
|
||||
bool send( const std::string & , bool eot = false , bool sensitive = false ) ;
|
||||
bool sendLine( std::string & ) ;
|
||||
size_t sendLines() ;
|
||||
void sendEhlo() ;
|
||||
@ -267,7 +278,7 @@ private:
|
||||
|
||||
private:
|
||||
enum State { sInit , sStarted , sServiceReady , sSentEhlo , sSentHelo , sAuth1 , sAuth2 , sSentMail ,
|
||||
sPreprocessing , sSentRcpt , sSentData , sSentDataStub , sData , sSentDot , sDone } ;
|
||||
sPreprocessing , sSentRcpt , sSentData , sSentDataStub , sData , sSentDot , sStartTls , sSentTlsEhlo , sDone } ;
|
||||
Sender & m_sender ;
|
||||
const Secrets & m_secrets ;
|
||||
std::string m_thishost ;
|
||||
@ -276,7 +287,9 @@ private:
|
||||
G::Strings m_to ;
|
||||
size_t m_to_accepted ;
|
||||
std::auto_ptr<std::istream> m_content ;
|
||||
bool m_server_has_auth ;
|
||||
bool m_server_has_8bitmime ;
|
||||
bool m_server_has_tls ;
|
||||
bool m_message_is_8bit ;
|
||||
std::string m_message_authentication ;
|
||||
Reply m_reply ;
|
||||
|
@ -65,7 +65,7 @@ public:
|
||||
///< content stream, creates a new envelope
|
||||
///< file (".new"), and does any local 'delivery'
|
||||
///< by creating ".local" copies. The path
|
||||
///< to the ".new" envelope file is returned.
|
||||
///< to the content file is returned.
|
||||
|
||||
virtual void commit() ;
|
||||
///< Final override from GSmtp::NewMessage.
|
||||
|
@ -89,6 +89,10 @@ void GSmtp::RequestClient::onDeleteImp( const std::string & reason , bool b )
|
||||
Base::onDeleteImp( reason , b ) ; // use typedef because of ms compiler bug
|
||||
}
|
||||
|
||||
void GSmtp::RequestClient::onSecure()
|
||||
{
|
||||
}
|
||||
|
||||
bool GSmtp::RequestClient::onReceive( const std::string & line )
|
||||
{
|
||||
G_DEBUG( "GSmtp::RequestClient::onReceive: [" << G::Str::printable(line) << "]" ) ;
|
||||
|
@ -85,6 +85,9 @@ protected:
|
||||
virtual void onDeleteImp( const std::string & , bool ) ;
|
||||
///< Final override from GNet::Client.
|
||||
|
||||
virtual void onSecure() ;
|
||||
///< Final override from GNet::SocketProtocolSink.
|
||||
|
||||
private:
|
||||
typedef GNet::Client Base ;
|
||||
RequestClient( const RequestClient & ) ; // not implemented
|
||||
|
@ -54,7 +54,7 @@ public:
|
||||
|
||||
/// \class GSmtp::SaslServer
|
||||
/// A class for implementing the server-side SASL
|
||||
/// challenge/response concept. SASL is described in RFC2222,
|
||||
/// challenge/response concept. SASL is described in RFC4422,
|
||||
/// and the SMTP extension for authentication is described
|
||||
/// in RFC2554.
|
||||
///
|
||||
@ -65,6 +65,7 @@ public:
|
||||
/// - DIGEST-MD5 [RFC2831]
|
||||
/// - KERBEROS_V5
|
||||
/// - LOGIN
|
||||
/// - PLAIN
|
||||
///
|
||||
/// Usage:
|
||||
/// \code
|
||||
@ -85,7 +86,7 @@ public:
|
||||
/// }
|
||||
/// \endcode
|
||||
///
|
||||
/// \see GSmtp::SaslClient, RFC2554, RFC2222
|
||||
/// \see GSmtp::SaslClient, RFC2554, RFC4422
|
||||
///
|
||||
class GSmtp::SaslServer
|
||||
{
|
||||
@ -99,13 +100,9 @@ public:
|
||||
private: void operator=( const Secrets & ) ; // not implemented
|
||||
} ;
|
||||
|
||||
SaslServer( const Secrets & , bool strict , bool force_one_mechanism ) ;
|
||||
SaslServer( const Secrets & , bool ignored , bool force_one_mechanism ) ;
|
||||
///< Constructor. The secrets reference is kept.
|
||||
///<
|
||||
///< If the 'strict' flag is false then LOGIN is treated
|
||||
///< as a standard mechanism and therefore advertised
|
||||
///< by mechanisms().
|
||||
///<
|
||||
///< If the 'force' flag is true then the list of
|
||||
///< mechanisms returned by mechanisms() will never
|
||||
///< be empty, even if no authentication is possible.
|
||||
@ -168,10 +165,10 @@ private:
|
||||
|
||||
/// \class GSmtp::SaslClient
|
||||
/// A class for implementing the client-side SASL
|
||||
/// challenge/response concept. SASL is described in RFC2222,
|
||||
/// challenge/response concept. SASL is described in RFC4422,
|
||||
/// and the SMTP extension for authentication is described
|
||||
/// in RFC2554.
|
||||
/// \see GSmtp::SaslServer, RFC2222, RFC2554.
|
||||
/// \see GSmtp::SaslServer, RFC4422, RFC2554.
|
||||
///
|
||||
class GSmtp::SaslClient
|
||||
{
|
||||
@ -196,7 +193,7 @@ public:
|
||||
///< is valid.
|
||||
|
||||
std::string response( const std::string & mechanism , const std::string & challenge ,
|
||||
bool & done , bool & error ) const ;
|
||||
bool & done , bool & error , bool & sensitive ) const ;
|
||||
///< Returns a response to the given challenge.
|
||||
|
||||
std::string preferred( const G::Strings & mechanisms ) const ;
|
||||
|
@ -15,6 +15,8 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
|
||||
#error not used
|
||||
// TODO ...
|
||||
|
||||
/// \file gsasl_cyrus.cpp
|
||||
// http://josefsson.org/gsasl
|
||||
|
||||
/// \file gsasl_gnu.cpp
|
@ -29,6 +29,8 @@
|
||||
#include "gmemory.h"
|
||||
#include "gdebug.h"
|
||||
#include <sstream>
|
||||
#include <algorithm> // set_intersection
|
||||
#include <set>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -50,10 +52,10 @@ public:
|
||||
bool m_authenticated ;
|
||||
std::string m_id ;
|
||||
std::string m_trustee ;
|
||||
bool m_strict ;
|
||||
bool m_advertise_force_one ;
|
||||
bool m_advertise_login ;
|
||||
bool m_advertise_plain ;
|
||||
bool m_advertise_cram_md5 ;
|
||||
bool m_advertise_force_one ;
|
||||
|
||||
public:
|
||||
SaslServerImp( const SaslServer::Secrets & , bool , bool ) ;
|
||||
@ -80,53 +82,44 @@ public:
|
||||
|
||||
// ===
|
||||
|
||||
GSmtp::SaslServerImp::SaslServerImp( const SaslServer::Secrets & secrets , bool strict , bool force_one ) :
|
||||
GSmtp::SaslServerImp::SaslServerImp( const SaslServer::Secrets & secrets , bool , bool force_one ) :
|
||||
m_first(true) ,
|
||||
m_secrets(secrets) ,
|
||||
m_authenticated(false) ,
|
||||
m_strict(strict) ,
|
||||
m_advertise_login(false) ,
|
||||
m_advertise_plain(false) ,
|
||||
m_advertise_cram_md5(false) ,
|
||||
m_advertise_force_one(force_one)
|
||||
{
|
||||
// only advertise mechanisms that appear in the secrets file
|
||||
m_advertise_login = m_secrets.contains("LOGIN") ;
|
||||
m_advertise_plain = m_secrets.contains("LOGIN") || m_secrets.contains("PLAIN") ;
|
||||
m_advertise_cram_md5 = m_secrets.contains("CRAM-MD5") ;
|
||||
if( m_strict )
|
||||
if( force_one && !m_advertise_login && !m_advertise_cram_md5 && !m_advertise_plain )
|
||||
{
|
||||
m_advertise_login = false ;
|
||||
}
|
||||
if( force_one && !m_advertise_login && !m_advertise_cram_md5 )
|
||||
{
|
||||
if( m_strict )
|
||||
m_advertise_cram_md5 = true ;
|
||||
else
|
||||
m_advertise_login = true ;
|
||||
}
|
||||
}
|
||||
|
||||
std::string GSmtp::SaslServerImp::mechanisms( const std::string & sep ) const
|
||||
{
|
||||
std::string s ;
|
||||
if( m_advertise_login )
|
||||
{
|
||||
s.append("LOGIN") ;
|
||||
}
|
||||
if( m_advertise_cram_md5 )
|
||||
{
|
||||
if( !s.empty() ) s.append( sep ) ;
|
||||
s.append("CRAM-MD5") ;
|
||||
}
|
||||
return s ;
|
||||
G::Strings m ;
|
||||
if( m_advertise_login ) m.push_back( "LOGIN" ) ;
|
||||
if( m_advertise_plain ) m.push_back( "PLAIN" ) ;
|
||||
if( m_advertise_cram_md5 ) m.push_back( "CRAM-MD5" ) ;
|
||||
return G::Str::join( m , sep ) ;
|
||||
}
|
||||
|
||||
bool GSmtp::SaslServerImp::init( const std::string & mechanism )
|
||||
{
|
||||
m_authenticated = false ;
|
||||
m_id = std::string() ;
|
||||
m_trustee = std::string() ;
|
||||
m_id.erase() ;
|
||||
m_trustee.erase() ;
|
||||
m_first = true ;
|
||||
m_challenge = std::string() ;
|
||||
m_mechanism = std::string() ;
|
||||
m_challenge.erase() ;
|
||||
m_mechanism.erase() ;
|
||||
|
||||
if( mechanism == "LOGIN" )
|
||||
if( mechanism == "LOGIN" || mechanism == "PLAIN" )
|
||||
{
|
||||
m_mechanism = mechanism ;
|
||||
return true ;
|
||||
@ -261,8 +254,11 @@ bool GSmtp::SaslServer::init( const std::string & mechanism )
|
||||
|
||||
std::string GSmtp::SaslServer::initialChallenge() const
|
||||
{
|
||||
if( m_imp->m_mechanism == "LOGIN" )
|
||||
std::string m = m_imp->m_mechanism ;
|
||||
if( m == "LOGIN" )
|
||||
return login_challenge_1 ;
|
||||
else if( m == "PLAIN" )
|
||||
return std::string() ;
|
||||
else
|
||||
return m_imp->m_challenge ;
|
||||
}
|
||||
@ -300,8 +296,23 @@ std::string GSmtp::SaslServer::apply( const std::string & response , bool & done
|
||||
}
|
||||
done = true ;
|
||||
}
|
||||
else if( m_imp->m_mechanism == "PLAIN" )
|
||||
{
|
||||
G_DEBUG( "GSmtp::SaslServer::apply: response: \"" << G::Str::printable(response) << "\"" ) ;
|
||||
std::string sep( 1U , '\0' ) ;
|
||||
std::string s = G::Str::tail( response , response.find(sep) , std::string() ) ;
|
||||
std::string id = G::Str::head( s , s.find(sep) , std::string() ) ;
|
||||
std::string pwd = G::Str::tail( s , s.find(sep) , std::string() ) ;
|
||||
std::string secret = m_imp->m_secrets.secret("PLAIN",id).empty() ?
|
||||
m_imp->m_secrets.secret("LOGIN",id) : m_imp->m_secrets.secret("PLAIN",id) ;
|
||||
|
||||
m_imp->m_id = id ;
|
||||
m_imp->m_authenticated = !id.empty() && !pwd.empty() && pwd == secret ;
|
||||
done = true ;
|
||||
}
|
||||
else if( m_imp->m_first ) // LOGIN username
|
||||
{
|
||||
G_ASSERT( m_imp->m_mechanism == "LOGIN" ) ;
|
||||
G_DEBUG( "GSmtp::SaslServer::apply: response: \"" << response << "\"" ) ;
|
||||
m_imp->m_first = false ;
|
||||
m_imp->m_id = response ;
|
||||
@ -310,6 +321,7 @@ std::string GSmtp::SaslServer::apply( const std::string & response , bool & done
|
||||
}
|
||||
else // LOGIN password
|
||||
{
|
||||
G_ASSERT( m_imp->m_mechanism == "LOGIN" ) ;
|
||||
G_DEBUG( "GSmtp::SaslServer::apply: response: \"[password not logged]\"" ) ;
|
||||
std::string secret = m_imp->m_secrets.secret(m_imp->m_mechanism,m_imp->m_id) ;
|
||||
m_imp->m_first = true ;
|
||||
@ -359,11 +371,12 @@ bool GSmtp::SaslClient::active() const
|
||||
return m_imp->m_secrets.valid() ;
|
||||
}
|
||||
|
||||
std::string GSmtp::SaslClient::response( const std::string & mechanism ,
|
||||
const std::string & challenge , bool & done , bool & error ) const
|
||||
std::string GSmtp::SaslClient::response( const std::string & mechanism , const std::string & challenge ,
|
||||
bool & done , bool & error , bool & sensitive ) const
|
||||
{
|
||||
done = false ;
|
||||
error = false ;
|
||||
sensitive = false ;
|
||||
|
||||
std::string rsp ;
|
||||
if( mechanism == "CRAM-MD5" || mechanism == "APOP" )
|
||||
@ -377,7 +390,19 @@ std::string GSmtp::SaslClient::response( const std::string & mechanism ,
|
||||
|
||||
done = true ;
|
||||
}
|
||||
else if( challenge == login_challenge_1 )
|
||||
else if( mechanism == "PLAIN" )
|
||||
{
|
||||
std::string sep( 1U , '\0' ) ;
|
||||
std::string id = m_imp->m_secrets.id(mechanism) ;
|
||||
std::string secret = m_imp->m_secrets.secret(mechanism) ;
|
||||
rsp = sep + id + sep + secret ;
|
||||
error = id.empty() || secret.empty() ;
|
||||
done = true ;
|
||||
sensitive = true ;
|
||||
}
|
||||
else if( mechanism == "LOGIN" )
|
||||
{
|
||||
if( challenge == login_challenge_1 )
|
||||
{
|
||||
rsp = m_imp->m_secrets.id(mechanism) ;
|
||||
error = rsp.empty() ;
|
||||
@ -388,13 +413,24 @@ std::string GSmtp::SaslClient::response( const std::string & mechanism ,
|
||||
rsp = m_imp->m_secrets.secret(mechanism) ;
|
||||
error = rsp.empty() ;
|
||||
done = true ;
|
||||
sensitive = true ;
|
||||
}
|
||||
else
|
||||
{
|
||||
G_WARNING( "GSmtp::SaslClient: invalid challenge" ) ;
|
||||
done = true ;
|
||||
error = true ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = true ;
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
G_WARNING( "GSmtp::SaslClient: invalid challenge" ) ;
|
||||
done = true ;
|
||||
}
|
||||
|
||||
return rsp ;
|
||||
}
|
||||
|
||||
@ -407,42 +443,33 @@ std::string GSmtp::SaslClient::preferred( const G::Strings & mechanism_list ) co
|
||||
if( !active() )
|
||||
return std::string() ;
|
||||
|
||||
// look for cram-md5 and login in the list
|
||||
//
|
||||
const std::string login( "LOGIN" ) ;
|
||||
const std::string plain( "PLAIN" ) ;
|
||||
const std::string cram( "CRAM-MD5" ) ;
|
||||
bool has_login = false ;
|
||||
bool has_cram = false ;
|
||||
|
||||
// create a them set
|
||||
std::set<std::string> them ;
|
||||
for( G::Strings::const_iterator p = mechanism_list.begin() ; p != mechanism_list.end() ; ++p )
|
||||
{
|
||||
std::string mechanism = *p ;
|
||||
G::Str::toUpper( mechanism ) ;
|
||||
if( mechanism == login )
|
||||
has_login = true ;
|
||||
else if( mechanism == cram )
|
||||
has_cram = true ;
|
||||
}
|
||||
them.insert( G::Str::upper(*p) ) ;
|
||||
|
||||
// prefer cram-md5 over login...
|
||||
//
|
||||
std::string result = has_cram ? cram : ( has_login ? login : std::string() ) ;
|
||||
G_DEBUG( "GSmtp::SaslClient::preferred: we prefer \"" << result << "\"" ) ;
|
||||
// create an us set
|
||||
std::set<std::string> us ;
|
||||
if( !m_imp->m_secrets.id(login).empty() ) us.insert(login) ;
|
||||
if( !m_imp->m_secrets.id(plain).empty() ) us.insert(plain) ;
|
||||
if( !m_imp->m_secrets.id(cram).empty() ) us.insert(cram) ;
|
||||
|
||||
// ... but only if a secret is defined for it
|
||||
//
|
||||
if( !result.empty() && m_imp->m_secrets.id(result).empty() )
|
||||
{
|
||||
G_DEBUG( "GSmtp::SaslClient::preferred: .. but no secret" ) ;
|
||||
result = std::string() ;
|
||||
if( has_cram && has_login )
|
||||
{
|
||||
result = login ;
|
||||
if( m_imp->m_secrets.id(login).empty() )
|
||||
result = std::string() ;
|
||||
}
|
||||
G_DEBUG( "GSmtp::SaslClient::preferred: we now prefer \"" << result << "\"" ) ;
|
||||
}
|
||||
return result ;
|
||||
// get the intersection
|
||||
std::set<std::string> both ;
|
||||
std::set_intersection( them.begin() , them.end() , us.begin() , us.end() , std::inserter(both,both.end()) ) ;
|
||||
|
||||
// preferred order: cram, plain, login
|
||||
std::string m ;
|
||||
if( m.empty() && both.find(cram) != both.end() ) m = cram ;
|
||||
if( m.empty() && both.find(plain) != both.end() ) m = plain ;
|
||||
if( m.empty() && both.find(login) != both.end() ) m = login ;
|
||||
G_DEBUG( "GSmtp::SaslClient::preferred: we prefer \"" << m << "\"" ) ;
|
||||
|
||||
return m ;
|
||||
}
|
||||
|
||||
// ==
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "gsmtp.h"
|
||||
#include "gserverprotocol.h"
|
||||
#include "gbase64.h"
|
||||
#include "gssl.h"
|
||||
#include "gdate.h"
|
||||
#include "gtime.h"
|
||||
#include "gdatetime.h"
|
||||
@ -39,6 +40,7 @@ GSmtp::ServerProtocol::ServerProtocol( Sender & sender , Verifier & verifier , P
|
||||
m_peer_address(peer_address) ,
|
||||
m_fsm(sStart,sEnd,s_Same,s_Any) ,
|
||||
m_authenticated(false) ,
|
||||
m_secure(false) ,
|
||||
m_sasl(secrets,false,true) ,
|
||||
m_with_vrfy(config.with_vrfy) ,
|
||||
m_preprocessor_timeout(config.preprocessor_timeout) ,
|
||||
@ -48,15 +50,17 @@ GSmtp::ServerProtocol::ServerProtocol( Sender & sender , Verifier & verifier , P
|
||||
m_pmessage.doneSignal().connect( G::slot(*this,&ServerProtocol::processDone) ) ;
|
||||
verifier.doneSignal().connect( G::slot(*this,&ServerProtocol::verifyDone) ) ;
|
||||
|
||||
// (dont send anything to the peer from this ctor -- the Sender
|
||||
// object is not fuly constructed)
|
||||
// (dont send anything to the peer from this ctor -- the Sender object is not fuly constructed)
|
||||
|
||||
m_fsm.addTransition( eQuit , s_Any , sEnd , &GSmtp::ServerProtocol::doQuit ) ;
|
||||
m_fsm.addTransition( eUnknown , s_Any , s_Same , &GSmtp::ServerProtocol::doUnknown ) ;
|
||||
m_fsm.addTransition( eRset , sStart , s_Same , &GSmtp::ServerProtocol::doNoop ) ;
|
||||
m_fsm.addTransition( eRset , s_Any , sIdle , &GSmtp::ServerProtocol::doRset ) ;
|
||||
m_fsm.addTransition( eNoop , s_Any , s_Same , &GSmtp::ServerProtocol::doNoop ) ;
|
||||
m_fsm.addTransition( eHelp , s_Any , s_Same , &GSmtp::ServerProtocol::doHelp ) ;
|
||||
m_fsm.addTransition( eExpn , s_Any , s_Same , &GSmtp::ServerProtocol::doExpn ) ;
|
||||
m_fsm.addTransition( eVrfy , sStart , sVrfyStart , &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
|
||||
m_fsm.addTransition( eVrfyReply , sVrfyStart , sStart , &GSmtp::ServerProtocol::doVrfyReply ) ;
|
||||
m_fsm.addTransition( eVrfy , sIdle , sVrfyIdle , &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
|
||||
m_fsm.addTransition( eVrfyReply , sVrfyIdle , sIdle , &GSmtp::ServerProtocol::doVrfyReply ) ;
|
||||
m_fsm.addTransition( eVrfy , sGotMail , sVrfyGotMail, &GSmtp::ServerProtocol::doVrfy , s_Same ) ;
|
||||
@ -74,13 +78,22 @@ GSmtp::ServerProtocol::ServerProtocol( Sender & sender , Verifier & verifier , P
|
||||
m_fsm.addTransition( eData , sGotRcpt , sData , &GSmtp::ServerProtocol::doData ) ;
|
||||
m_fsm.addTransition( eContent , sData , sData , &GSmtp::ServerProtocol::doContent ) ;
|
||||
m_fsm.addTransition( eEot , sData , sProcessing , &GSmtp::ServerProtocol::doEot ) ;
|
||||
m_fsm.addTransition( eDone , sProcessing , sIdle , &GSmtp::ServerProtocol::doComplete ) ;
|
||||
m_fsm.addTransition( eTimeout , sProcessing , sIdle , &GSmtp::ServerProtocol::doComplete ) ;
|
||||
|
||||
if( m_sasl.active() )
|
||||
{
|
||||
m_fsm.addTransition( eAuth , sStart , sAuth , &GSmtp::ServerProtocol::doAuth , sIdle ) ;
|
||||
m_fsm.addTransition( eAuth , sIdle , sAuth , &GSmtp::ServerProtocol::doAuth , sIdle ) ;
|
||||
m_fsm.addTransition( eAuthData, sAuth , sAuth , &GSmtp::ServerProtocol::doAuthData , sIdle ) ;
|
||||
}
|
||||
|
||||
GSsl::Library * ssl = GSsl::Library::instance() ;
|
||||
m_with_ssl = ssl != NULL && ssl->enabled(true) ;
|
||||
if( m_with_ssl )
|
||||
{
|
||||
m_fsm.addTransition( eStartTls , sIdle , sStartingTls , &GSmtp::ServerProtocol::doStartTls ) ;
|
||||
m_fsm.addTransition( eSecure , sStartingTls , sIdle , &GSmtp::ServerProtocol::doSecure ) ;
|
||||
}
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::init()
|
||||
@ -94,6 +107,24 @@ GSmtp::ServerProtocol::~ServerProtocol()
|
||||
m_verifier.doneSignal().disconnect() ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::secure()
|
||||
{
|
||||
State new_state = m_fsm.apply( *this , eSecure , std::string() ) ;
|
||||
if( new_state == s_Any )
|
||||
throw ProtocolDone( "protocol error" ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::doSecure( const std::string & , bool & )
|
||||
{
|
||||
G_DEBUG( "GSmtp::ServerProtocol::doSecure" ) ;
|
||||
m_secure = true ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::doStartTls( const std::string & , bool & )
|
||||
{
|
||||
send( "220 ready to start tls" , true ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::sendGreeting( const std::string & text )
|
||||
{
|
||||
send( std::string("220 ") + text ) ;
|
||||
@ -125,8 +156,7 @@ void GSmtp::ServerProtocol::apply( const std::string & line )
|
||||
}
|
||||
|
||||
State new_state = m_fsm.apply( *this , event , *event_data ) ;
|
||||
const bool protocol_error = new_state == s_Any ;
|
||||
if( protocol_error )
|
||||
if( new_state == s_Any )
|
||||
sendOutOfSequence( line ) ;
|
||||
}
|
||||
|
||||
@ -142,30 +172,31 @@ void GSmtp::ServerProtocol::doEot( const std::string & line , bool & )
|
||||
{
|
||||
G_LOG( "GSmtp::ServerProtocol: rx<<: [message content not logged]" ) ;
|
||||
G_LOG( "GSmtp::ServerProtocol: rx<<: \"" << G::Str::printable(line) << "\"" ) ;
|
||||
if( m_preprocessor_timeout != 0U ) startTimer( m_preprocessor_timeout ) ;
|
||||
if( m_preprocessor_timeout != 0U )
|
||||
{
|
||||
G_DEBUG( "GSmtp::ServerProtocol: starting preprocessor timer: " << m_preprocessor_timeout ) ;
|
||||
startTimer( m_preprocessor_timeout ) ;
|
||||
}
|
||||
m_pmessage.process( m_sasl.id() , m_peer_address.displayString(false) ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::processDone( bool success , unsigned long , std::string reason )
|
||||
{
|
||||
G_DEBUG( "GSmtp::ServerProtocol::processDone: " << success << ", \"" << reason << "\"" ) ;
|
||||
G_ASSERT( m_fsm.state() == sProcessing ) ; // all exit paths from sProcessing call reset()
|
||||
if( m_fsm.state() != sProcessing ) return ;
|
||||
|
||||
m_fsm.reset( sIdle ) ;
|
||||
reset() ;
|
||||
sendCompletionReply( success , reason ) ;
|
||||
reason = success ? std::string() : ( reason.empty() ? std::string("error") : reason ) ; // just in case
|
||||
|
||||
State new_state = m_fsm.apply( *this , eDone , reason ) ;
|
||||
if( new_state == s_Any )
|
||||
throw ProtocolDone( "protocol error" ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::onTimeout()
|
||||
{
|
||||
G_WARNING( "GSmtp::ServerProtocol::onTimeout: message processing timed out" ) ;
|
||||
G_ASSERT( m_fsm.state() == sProcessing ) ; // all exit paths from sProcessing call reset()
|
||||
if( m_fsm.state() != sProcessing ) return ;
|
||||
|
||||
m_fsm.reset( sIdle ) ;
|
||||
reset() ;
|
||||
sendCompletionReply( false , "message processing timed out" ) ;
|
||||
State new_state = m_fsm.apply( *this , eTimeout , "message processing timed out" ) ;
|
||||
if( new_state == s_Any )
|
||||
throw ProtocolDone( "protocol error" ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::onTimeoutException( std::exception & e )
|
||||
@ -174,6 +205,12 @@ void GSmtp::ServerProtocol::onTimeoutException( std::exception & e )
|
||||
throw ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::doComplete( const std::string & reason , bool & )
|
||||
{
|
||||
reset() ;
|
||||
sendCompletionReply( reason.empty() , reason ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::doQuit( const std::string & , bool & )
|
||||
{
|
||||
reset() ;
|
||||
@ -229,7 +266,9 @@ void GSmtp::ServerProtocol::verify( const std::string & to , const std::string &
|
||||
|
||||
void GSmtp::ServerProtocol::verifyDone( std::string mbox , Verifier::Status status )
|
||||
{
|
||||
m_fsm.apply( *this , eVrfyReply , status.str(mbox) ) ;
|
||||
State new_state = m_fsm.apply( *this , eVrfyReply , status.str(mbox) ) ;
|
||||
if( new_state == s_Any )
|
||||
throw ProtocolDone( "protocol error" ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::doVrfyReply( const std::string & line , bool & )
|
||||
@ -529,6 +568,7 @@ GSmtp::ServerProtocol::Event GSmtp::ServerProtocol::commandEvent( const std::str
|
||||
if( command == "NOOP" ) return eNoop ;
|
||||
if( command == "EXPN" ) return eExpn ;
|
||||
if( command == "HELP" ) return eHelp ;
|
||||
if( command == "STARTTLS" ) return eStartTls ;
|
||||
if( m_sasl.active() && command == "AUTH" ) return eAuth ;
|
||||
return eUnknown ;
|
||||
}
|
||||
@ -624,6 +664,8 @@ void GSmtp::ServerProtocol::sendEhloReply()
|
||||
ss << "250-" << m_text.hello(m_peer_name) << crlf() ;
|
||||
if( m_sasl.active() )
|
||||
ss << "250-AUTH " << m_sasl.mechanisms() << crlf() ;
|
||||
if( m_with_ssl && !m_secure )
|
||||
ss << "250-STARTTLS" << crlf() ;
|
||||
if( m_with_vrfy )
|
||||
ss << "250-VRFY" << crlf() ; // see RFC2821-3.5.2
|
||||
ss << "250 8BITMIME" ;
|
||||
@ -645,11 +687,11 @@ std::string GSmtp::ServerProtocol::crlf()
|
||||
return std::string( "\015\012" ) ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerProtocol::send( std::string line )
|
||||
void GSmtp::ServerProtocol::send( std::string line , bool go_secure )
|
||||
{
|
||||
G_LOG( "GSmtp::ServerProtocol: tx>>: \"" << G::Str::printable(line) << "\"" ) ;
|
||||
line.append( crlf() ) ;
|
||||
m_sender.protocolSend( line ) ;
|
||||
m_sender.protocolSend( line , go_secure ) ;
|
||||
}
|
||||
|
||||
std::pair<std::string,std::string> GSmtp::ServerProtocol::parseFrom( const std::string & line ) const
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
/// An interface used by ServerProtocol to send protocol replies.
|
||||
class Sender
|
||||
{
|
||||
public: virtual void protocolSend( const std::string & s ) = 0 ;
|
||||
public: virtual void protocolSend( const std::string & s , bool go_secure ) = 0 ;
|
||||
public: virtual ~Sender() ;
|
||||
private: void operator=( const Sender & ) ; // not implemented
|
||||
} ;
|
||||
@ -110,6 +110,10 @@ public:
|
||||
///< The string is expected to be CR-LF terminated.
|
||||
///< Throws ProtocolDone at the end of the protocol.
|
||||
|
||||
void secure() ;
|
||||
///< To be called when the transport protocol goes
|
||||
///< into secure mode.
|
||||
|
||||
protected:
|
||||
virtual void onTimeout() ;
|
||||
///< Final override from GNet::AbstractTimer.
|
||||
@ -129,6 +133,8 @@ private:
|
||||
eData ,
|
||||
eRcpt ,
|
||||
eMail ,
|
||||
eStartTls ,
|
||||
eSecure ,
|
||||
eVrfy ,
|
||||
eVrfyReply ,
|
||||
eHelp ,
|
||||
@ -136,6 +142,8 @@ private:
|
||||
eAuthData ,
|
||||
eContent ,
|
||||
eEot ,
|
||||
eDone ,
|
||||
eTimeout ,
|
||||
eUnknown
|
||||
} ;
|
||||
enum State
|
||||
@ -145,6 +153,7 @@ private:
|
||||
sIdle ,
|
||||
sGotMail ,
|
||||
sGotRcpt ,
|
||||
sVrfyStart ,
|
||||
sVrfyIdle ,
|
||||
sVrfyGotMail ,
|
||||
sVrfyGotRcpt ,
|
||||
@ -153,6 +162,7 @@ private:
|
||||
sData ,
|
||||
sProcessing ,
|
||||
sAuth ,
|
||||
sStartingTls ,
|
||||
s_Any ,
|
||||
s_Same
|
||||
} ;
|
||||
@ -161,7 +171,7 @@ private:
|
||||
private:
|
||||
ServerProtocol( const ServerProtocol & ) ; // not implemented
|
||||
void operator=( const ServerProtocol & ) ; // not implemented
|
||||
void send( std::string ) ;
|
||||
void send( std::string , bool = false ) ;
|
||||
Event commandEvent( const std::string & ) const ;
|
||||
std::string commandWord( const std::string & line ) const ;
|
||||
std::string commandLine( const std::string & line ) const ;
|
||||
@ -186,11 +196,14 @@ private:
|
||||
void doRset( const std::string & , bool & ) ;
|
||||
void doData( const std::string & , bool & ) ;
|
||||
void doContent( const std::string & , bool & ) ;
|
||||
void doComplete( const std::string & , bool & ) ;
|
||||
void doEot( const std::string & , bool & ) ;
|
||||
void doVrfy( const std::string & , bool & ) ;
|
||||
void doVrfyReply( const std::string & line , bool & ) ;
|
||||
void doVrfyToReply( const std::string & line , bool & ) ;
|
||||
void doNoRecipients( const std::string & , bool & ) ;
|
||||
void doStartTls( const std::string & , bool & ) ;
|
||||
void doSecure( const std::string & , bool & ) ;
|
||||
void verifyDone( std::string , Verifier::Status status ) ;
|
||||
void sendBadFrom( std::string ) ;
|
||||
void sendChallenge( const std::string & ) ;
|
||||
@ -231,8 +244,10 @@ private:
|
||||
Fsm m_fsm ;
|
||||
std::string m_peer_name ;
|
||||
bool m_authenticated ;
|
||||
bool m_secure ;
|
||||
SaslServer m_sasl ;
|
||||
bool m_with_vrfy ;
|
||||
bool m_with_ssl ;
|
||||
std::string m_buffer ;
|
||||
unsigned int m_preprocessor_timeout ;
|
||||
unsigned int m_bad_client_count ;
|
||||
|
@ -78,9 +78,12 @@ void GSmtp::Client::sendMessage( std::auto_ptr<StoredMessage> message )
|
||||
}
|
||||
}
|
||||
|
||||
bool GSmtp::Client::protocolSend( const std::string & line , size_t offset )
|
||||
bool GSmtp::Client::protocolSend( const std::string & line , size_t offset , bool go_secure )
|
||||
{
|
||||
return send( line , offset ) ; // BufferedClient::send()
|
||||
bool rc = send( line , offset ) ; // BufferedClient::send()
|
||||
if( go_secure )
|
||||
sslConnect() ;
|
||||
return rc ;
|
||||
}
|
||||
|
||||
void GSmtp::Client::preprocessorStart()
|
||||
@ -101,6 +104,12 @@ void GSmtp::Client::preprocessorDone( bool ok )
|
||||
m_protocol.preprocessorDone( ok ? std::string() : reason ) ;
|
||||
}
|
||||
|
||||
void GSmtp::Client::onSecure()
|
||||
{
|
||||
G_LOG( "GSmtp::Client::onSecure: tls/ssl protocol established with " << peerAddress().second.displayString() ) ;
|
||||
m_protocol.secure() ;
|
||||
}
|
||||
|
||||
void GSmtp::Client::onConnect()
|
||||
{
|
||||
if( m_store != NULL )
|
||||
|
@ -115,8 +115,11 @@ protected:
|
||||
virtual void onSendComplete() ;
|
||||
///< Final override from GNet::BufferedClient.
|
||||
|
||||
virtual void onSecure() ;
|
||||
///< Final override from GNet::SocketProtocol.
|
||||
|
||||
private:
|
||||
virtual bool protocolSend( const std::string & , size_t ) ; // override from private base class
|
||||
virtual bool protocolSend( const std::string & , size_t , bool ) ; // override from private base class
|
||||
void protocolDone( std::string ) ; // see ClientProtocol::doneSignal()
|
||||
void preprocessorStart() ;
|
||||
void preprocessorDone( bool ) ;
|
||||
|
@ -76,7 +76,7 @@ GSmtp::ServerPeer::ServerPeer( GNet::Server::PeerInfo peer_info ,
|
||||
const std::string & verifier_address , unsigned int verifier_timeout ,
|
||||
std::auto_ptr<ServerProtocol::Text> ptext ,
|
||||
ServerProtocol::Config protocol_config ) :
|
||||
GNet::BufferedServerPeer( peer_info , crlf() , true ) , // <= throw-on-flow-control
|
||||
GNet::BufferedServerPeer( peer_info , crlf() ) ,
|
||||
m_server( server ) ,
|
||||
m_verifier( VerifierFactory::newVerifier(verifier_address,verifier_timeout) ) ,
|
||||
m_pmessage( pmessage ) ,
|
||||
@ -110,9 +110,17 @@ bool GSmtp::ServerPeer::onReceive( const std::string & line )
|
||||
return true ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerPeer::protocolSend( const std::string & line )
|
||||
void GSmtp::ServerPeer::onSecure()
|
||||
{
|
||||
G_LOG( "GSmtp::ServerPeer::onSecure: tls/ssl protocol established with " << peerAddress().second.displayString() ) ;
|
||||
m_protocol.secure() ;
|
||||
}
|
||||
|
||||
void GSmtp::ServerPeer::protocolSend( const std::string & line , bool go_secure )
|
||||
{
|
||||
send( line , 0U ) ; // GNet::Sender -- may throw SendError
|
||||
if( go_secure )
|
||||
sslAccept() ;
|
||||
}
|
||||
|
||||
// ===
|
||||
|
@ -68,10 +68,13 @@ protected:
|
||||
virtual bool onReceive( const std::string & ) ;
|
||||
///< Final override from GNet::BufferedServerPeer.
|
||||
|
||||
virtual void onSecure() ;
|
||||
///< Final override from GNet::SocketProtocolSink.
|
||||
|
||||
private:
|
||||
ServerPeer( const ServerPeer & ) ;
|
||||
void operator=( const ServerPeer & ) ;
|
||||
virtual void protocolSend( const std::string & line ) ; // override from private base class
|
||||
virtual void protocolSend( const std::string & line , bool ) ; // override from private base class
|
||||
static std::string crlf() ;
|
||||
|
||||
private:
|
||||
|
@ -169,6 +169,10 @@ void GSmtp::SpamClient::turnRound()
|
||||
m_out_lines = 0UL ;
|
||||
}
|
||||
|
||||
void GSmtp::SpamClient::onSecure()
|
||||
{
|
||||
}
|
||||
|
||||
bool GSmtp::SpamClient::onReceive( const std::string & line )
|
||||
{
|
||||
if( m_in.get() != NULL )
|
||||
|
@ -85,6 +85,9 @@ protected:
|
||||
virtual void onDeleteImp( const std::string & , bool ) ;
|
||||
///< Final override from GNet::Client.
|
||||
|
||||
virtual void onSecure() ;
|
||||
///< Final override from GNet::SocketProtocol.
|
||||
|
||||
private:
|
||||
typedef GNet::Client Base ;
|
||||
SpamClient( const SpamClient & ) ; // not implemented
|
||||
|
29
src/gssl/Makefile.am
Normal file
29
src/gssl/Makefile.am
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
## Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
##
|
||||
## This program is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
EXTRA_DIST=\
|
||||
gssl_none.cpp \
|
||||
gssl_openssl.cpp \
|
||||
mingw.mak
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
|
||||
noinst_LIBRARIES = libgssl.a
|
||||
|
||||
libgssl_a_SOURCES = \
|
||||
gssl.cpp \
|
||||
gssl.h
|
||||
|
431
src/gssl/Makefile.in
Normal file
431
src/gssl/Makefile.in
Normal file
@ -0,0 +1,431 @@
|
||||
# Makefile.in generated by automake 1.10 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
|
||||
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
# This Makefile.in is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
#
|
||||
#
|
||||
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
subdir = src/gssl
|
||||
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
|
||||
$(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
$(ACLOCAL_M4)
|
||||
mkinstalldirs = $(install_sh) -d
|
||||
CONFIG_HEADER = $(top_builddir)/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
ARFLAGS = cru
|
||||
libgssl_a_AR = $(AR) $(ARFLAGS)
|
||||
libgssl_a_LIBADD =
|
||||
am_libgssl_a_OBJECTS = gssl.$(OBJEXT)
|
||||
libgssl_a_OBJECTS = $(am_libgssl_a_OBJECTS)
|
||||
DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
|
||||
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
|
||||
CXXLD = $(CXX)
|
||||
CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
|
||||
-o $@
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
SOURCES = $(libgssl_a_SOURCES)
|
||||
DIST_SOURCES = $(libgssl_a_SOURCES)
|
||||
ETAGS = etags
|
||||
CTAGS = ctags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMTAR = @AMTAR@
|
||||
AR = @AR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
COMPILER_VERSION = @COMPILER_VERSION@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CXX = @CXX@
|
||||
CXXDEPMODE = @CXXDEPMODE@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
GREP = @GREP@
|
||||
GZIP = @GZIP@
|
||||
HAVE_DOXYGEN = @HAVE_DOXYGEN@
|
||||
HAVE_MAN2HTML = @HAVE_MAN2HTML@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
IP = @IP@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAKE = @MAKE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
MOC = @MOC@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
PKG_CONFIG = @PKG_CONFIG@
|
||||
QT_CFLAGS = @QT_CFLAGS@
|
||||
QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
am__tar = @am__tar@
|
||||
am__untar = @am__untar@
|
||||
bindir = @bindir@
|
||||
build_alias = @build_alias@
|
||||
builddir = @builddir@
|
||||
datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
docdir = @docdir@
|
||||
dvidir = @dvidir@
|
||||
e_docdir = @e_docdir@
|
||||
e_examplesdir = @e_examplesdir@
|
||||
e_initdir = @e_initdir@
|
||||
e_libexecdir = @e_libexecdir@
|
||||
e_qtmoc = @e_qtmoc@
|
||||
e_spooldir = @e_spooldir@
|
||||
e_sysconfdir = @e_sysconfdir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host_alias = @host_alias@
|
||||
htmldir = @htmldir@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
pdfdir = @pdfdir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
psdir = @psdir@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
srcdir = @srcdir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
EXTRA_DIST = \
|
||||
gssl_none.cpp \
|
||||
gssl_openssl.cpp \
|
||||
mingw.mak
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/lib/$(COMPILER_VERSION) -I$(top_srcdir)/src/glib
|
||||
noinst_LIBRARIES = libgssl.a
|
||||
libgssl_a_SOURCES = \
|
||||
gssl.cpp \
|
||||
gssl.h
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .cpp .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
|
||||
@for dep in $?; do \
|
||||
case '$(am__configure_deps)' in \
|
||||
*$$dep*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
|
||||
&& exit 0; \
|
||||
exit 1;; \
|
||||
esac; \
|
||||
done; \
|
||||
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/gssl/Makefile'; \
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu src/gssl/Makefile
|
||||
.PRECIOUS: Makefile
|
||||
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
@case '$?' in \
|
||||
*config.status*) \
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
|
||||
*) \
|
||||
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
|
||||
esac;
|
||||
|
||||
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
|
||||
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libgssl.a: $(libgssl_a_OBJECTS) $(libgssl_a_DEPENDENCIES)
|
||||
-rm -f libgssl.a
|
||||
$(libgssl_a_AR) libgssl.a $(libgssl_a_OBJECTS) $(libgssl_a_LIBADD)
|
||||
$(RANLIB) libgssl.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gssl.Po@am__quote@
|
||||
|
||||
.cpp.o:
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
|
||||
|
||||
.cpp.obj:
|
||||
@am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
@am__fastdepCXX_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
tags: TAGS
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
|
||||
test -n "$$unique" || unique=$$empty_fix; \
|
||||
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique; \
|
||||
fi
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
|
||||
list='$(DISTFILES)'; \
|
||||
dist_files=`for file in $$list; do echo $$file; done | \
|
||||
sed -e "s|^$$srcdirstrip/||;t" \
|
||||
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
|
||||
case $$dist_files in \
|
||||
*/*) $(MKDIR_P) `echo "$$dist_files" | \
|
||||
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
|
||||
sort -u` ;; \
|
||||
esac; \
|
||||
for file in $$dist_files; do \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
distclean-am: clean-am distclean-compile distclean-generic \
|
||||
distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
html: html-am
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-dvi: install-dvi-am
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-html: install-html-am
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
install-pdf: install-pdf-am
|
||||
|
||||
install-ps: install-ps-am
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
-rm -rf ./$(DEPDIR)
|
||||
-rm -f Makefile
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am:
|
||||
|
||||
.MAKE: install-am install-strip
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-noinstLIBRARIES ctags distclean distclean-compile \
|
||||
distclean-generic distclean-tags distdir dvi dvi-am html \
|
||||
html-am info info-am install install-am install-data \
|
||||
install-data-am install-dvi install-dvi-am install-exec \
|
||||
install-exec-am install-html install-html-am install-info \
|
||||
install-info-am install-man install-pdf install-pdf-am \
|
||||
install-ps install-ps-am install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am
|
||||
|
||||
# Tell versions [3.59,3.63) of GNU make to not export all variables.
|
||||
# Otherwise a system limit (for SysV at least) may be exceeded.
|
||||
.NOEXPORT:
|
29
src/gssl/gssl.cpp
Normal file
29
src/gssl/gssl.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
//
|
||||
// gssl.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
|
||||
#if HAVE_OPENSSL
|
||||
#include "gssl_openssl.cpp"
|
||||
#else
|
||||
#include "gssl_none.cpp"
|
||||
#endif
|
||||
|
||||
/// \file gssl.cpp
|
131
src/gssl/gssl.h
Normal file
131
src/gssl/gssl.h
Normal file
@ -0,0 +1,131 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
///
|
||||
/// \file gssl.h
|
||||
///
|
||||
|
||||
#ifndef G_SSL_H
|
||||
#define G_SSL_H
|
||||
|
||||
#include "gdef.h"
|
||||
#include <string>
|
||||
|
||||
/// \namespace GSsl
|
||||
namespace GSsl
|
||||
{
|
||||
class Library ;
|
||||
class Protocol ;
|
||||
class LibraryImp ;
|
||||
class ProtocolImp ;
|
||||
}
|
||||
|
||||
/// \class GSsl::Protocol
|
||||
/// An SSL protocol class. The protocol object
|
||||
/// is tied to a particular socket file descriptor.
|
||||
///
|
||||
class GSsl::Protocol
|
||||
{
|
||||
public:
|
||||
typedef size_t size_type ;
|
||||
typedef ssize_t ssize_type ;
|
||||
enum Result { Result_ok , Result_read , Result_write , Result_error } ;
|
||||
typedef void (*LogFn)( int , const std::string & ) ;
|
||||
|
||||
explicit Protocol( const Library & ) ;
|
||||
///< Constructor.
|
||||
|
||||
Protocol( const Library & , LogFn , bool hexdump = defaultHexdump() ) ;
|
||||
///< Constructor.
|
||||
|
||||
~Protocol() ;
|
||||
///< Destructor.
|
||||
|
||||
Result connect( int fd ) ;
|
||||
///< Starts the protocol actively.
|
||||
|
||||
Result accept( int fd ) ;
|
||||
///< Starts the protocol passively.
|
||||
|
||||
Result stop() ;
|
||||
///< Initiates the protocol shutdown.
|
||||
|
||||
Result read( char * buffer , size_type buffer_size_in , ssize_type & data_size_out ) ;
|
||||
///< Reads data into the supplied buffer.
|
||||
///<
|
||||
///< Note that a retry will need the same buffer
|
||||
///< pointer value.
|
||||
|
||||
Result write( const char * buffer , size_type data_size_in , ssize_type & data_size_out ) ;
|
||||
///< Writes data.
|
||||
///<
|
||||
///< Note that a retry will need the same buffer
|
||||
///< pointer value.
|
||||
|
||||
static std::string str( Result result ) ;
|
||||
///< Converts a result enumeration into a
|
||||
///< printable string. Used in logging and
|
||||
///< diagnostics.
|
||||
|
||||
static bool defaultHexdump() ;
|
||||
///< Returns a default value for the constructor parameter.
|
||||
|
||||
private:
|
||||
Protocol( const Protocol & ) ;
|
||||
void operator=( const Protocol & ) ;
|
||||
|
||||
private:
|
||||
ProtocolImp * m_imp ;
|
||||
} ;
|
||||
|
||||
/// \class GSsl::Library
|
||||
/// A RAII class for initialising the underlying ssl library.
|
||||
///
|
||||
class GSsl::Library
|
||||
{
|
||||
public:
|
||||
Library() ;
|
||||
///< Constructor. Initialises the underlying ssl library.
|
||||
|
||||
Library( bool active , const std::string & pem_file ) ;
|
||||
///< Constructor. Initialises the underlying ssl library
|
||||
///< or not. The pem file is needed if acting as a
|
||||
///< server.
|
||||
|
||||
~Library() ;
|
||||
///< Destructor. Cleans up the underlying ssl library.
|
||||
|
||||
static Library * instance() ;
|
||||
///< Returns a pointer to a library object, if any.
|
||||
|
||||
bool enabled( bool for_serving = false ) const ;
|
||||
///< Returns true if this is a real and enabled
|
||||
///< ssl library.
|
||||
|
||||
static std::string credit( const std::string & prefix , const std::string & eol , const std::string & final ) ;
|
||||
///< Returns a credit string.
|
||||
|
||||
private:
|
||||
Library( const Library & ) ;
|
||||
void operator=( const Library & ) ;
|
||||
|
||||
private:
|
||||
friend class GSsl::Protocol ;
|
||||
static Library * m_this ;
|
||||
LibraryImp * m_imp ;
|
||||
} ;
|
||||
|
||||
#endif
|
109
src/gssl/gssl_none.cpp
Normal file
109
src/gssl/gssl_none.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
//
|
||||
// gssl_none.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gssl.h"
|
||||
|
||||
GSsl::Library * GSsl::Library::m_this = NULL ;
|
||||
|
||||
GSsl::Library::Library()
|
||||
{
|
||||
if( m_this == NULL )
|
||||
m_this = this ;
|
||||
}
|
||||
|
||||
GSsl::Library::Library( bool , const std::string & )
|
||||
{
|
||||
if( m_this == NULL )
|
||||
m_this = this ;
|
||||
}
|
||||
|
||||
GSsl::Library::~Library()
|
||||
{
|
||||
if( this == m_this )
|
||||
m_this = NULL ;
|
||||
}
|
||||
|
||||
GSsl::Library * GSsl::Library::instance()
|
||||
{
|
||||
return m_this ;
|
||||
}
|
||||
|
||||
bool GSsl::Library::enabled( bool ) const
|
||||
{
|
||||
return false ;
|
||||
}
|
||||
|
||||
std::string GSsl::Library::credit( const std::string & , const std::string & , const std::string & )
|
||||
{
|
||||
return std::string() ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
std::string GSsl::Protocol::str( Protocol::Result )
|
||||
{
|
||||
return std::string() ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Protocol( const Library & )
|
||||
{
|
||||
}
|
||||
|
||||
GSsl::Protocol::Protocol( const Library & , LogFn , bool )
|
||||
{
|
||||
}
|
||||
|
||||
GSsl::Protocol::~Protocol()
|
||||
{
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::connect( int )
|
||||
{
|
||||
return Result_error ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::accept( int )
|
||||
{
|
||||
return Result_error ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::stop()
|
||||
{
|
||||
return Result_error ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::read( char * , size_type , ssize_type & )
|
||||
{
|
||||
return Result_error ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::write( const char * , size_type , ssize_type & )
|
||||
{
|
||||
return Result_error ;
|
||||
}
|
||||
|
||||
bool GSsl::Protocol::defaultHexdump()
|
||||
{
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
/// \file gssl_none.cpp
|
581
src/gssl/gssl_openssl.cpp
Normal file
581
src/gssl/gssl_openssl.cpp
Normal file
@ -0,0 +1,581 @@
|
||||
//
|
||||
// Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
// ===
|
||||
//
|
||||
// gssl_openssl.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gssl.h"
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <exception>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
// debugging...
|
||||
// * network logging
|
||||
// $ sudo tcpdump -s 0 -n -i eth0 -X tcp port 587
|
||||
// * emailrelay smtp proxy to gmail
|
||||
// $ emailrelay --forward-to smtp.gmail.com:587 ...
|
||||
// * openssl smtp client to gmail
|
||||
// $ openssl s_client -tls1 -msg -debug -starttls smtp -crlf -connect smtp.gmail.com:587
|
||||
// * certificate
|
||||
// $ openssl req -x509 -nodes -days 365 -subj "/C=US/ST=Oregon/L=Portland/CN=eight.local"
|
||||
// -newkey rsa:1024 -keyout test.cert -out test.cert
|
||||
// $ cp $name /etc/ssl/certs/
|
||||
// $ cd /etc/ssl/certs && ln -s `openssl x509 -noout -hash -in test.cert`.0
|
||||
// * openssl server (without smtp)
|
||||
// $ openssl s_server -accept 10025 -cert /etc/ssl/certs/test.pem -debug -msg -tls1
|
||||
//
|
||||
|
||||
namespace GSsl
|
||||
{
|
||||
class Context ;
|
||||
class Error ;
|
||||
}
|
||||
|
||||
/// \class GSsl::Context
|
||||
/// An openssl context wrapper.
|
||||
///
|
||||
class GSsl::Context
|
||||
{
|
||||
public:
|
||||
explicit Context( const std::string & pem_file = std::string() ) ;
|
||||
~Context() ;
|
||||
SSL_CTX * p() const ;
|
||||
|
||||
private:
|
||||
Context( const Context & ) ;
|
||||
void operator=( const Context & ) ;
|
||||
void init( const std::string & pem_file ) ;
|
||||
static void check( int , const char * ) ;
|
||||
|
||||
private:
|
||||
SSL_CTX * m_ssl_ctx ;
|
||||
} ;
|
||||
|
||||
/// \class GSsl::LibraryImp
|
||||
/// A private pimple class used by GSsl::Library.
|
||||
///
|
||||
class GSsl::LibraryImp
|
||||
{
|
||||
public:
|
||||
explicit LibraryImp( const std::string & pem_file = std::string() ) ;
|
||||
~LibraryImp() ;
|
||||
Context & ctx() ;
|
||||
std::string pem() const ;
|
||||
|
||||
private:
|
||||
LibraryImp( const LibraryImp & ) ;
|
||||
void operator=( const LibraryImp & ) ;
|
||||
|
||||
private:
|
||||
Context * m_context ;
|
||||
std::string m_pem_file ;
|
||||
} ;
|
||||
|
||||
/// \class GSsl::ProtocolImp
|
||||
/// A private pimple class used by GSsl::Protocol.
|
||||
///
|
||||
class GSsl::ProtocolImp
|
||||
{
|
||||
public:
|
||||
typedef Protocol::Result Result ;
|
||||
typedef Protocol::LogFn LogFn ;
|
||||
typedef Protocol::size_type size_type ;
|
||||
typedef Protocol::ssize_type ssize_type ;
|
||||
|
||||
ProtocolImp( const Context & c ) ;
|
||||
ProtocolImp( const Context & c , LogFn log , bool hexdump ) ;
|
||||
~ProtocolImp() ;
|
||||
Result connect( int ) ;
|
||||
Result accept( int ) ;
|
||||
Result stop() ;
|
||||
Result read( char * buffer , size_type buffer_size , ssize_type & read_size ) ;
|
||||
Result write( const char * buffer , size_type size_in , ssize_type & size_out ) ;
|
||||
|
||||
private:
|
||||
ProtocolImp( const ProtocolImp & ) ;
|
||||
void operator=( const ProtocolImp & ) ;
|
||||
int error( const char * , int ) const ;
|
||||
void set( int ) ;
|
||||
Result connect() ;
|
||||
Result accept() ;
|
||||
static Result convert( int ) ;
|
||||
static unsigned long getError() ;
|
||||
static void loghex( void (*fn)(int,const std::string&) , int , const char * , const std::string & ) ;
|
||||
static void callback( int , int , int , const void * , size_t , SSL * , void * p ) ;
|
||||
static void clearErrors() ;
|
||||
|
||||
private:
|
||||
SSL * m_ssl ;
|
||||
LogFn m_log_fn ;
|
||||
bool m_fd_set ;
|
||||
} ;
|
||||
|
||||
/// \class GSsl::Error
|
||||
/// A private exception class used by ssl classes.
|
||||
///
|
||||
class GSsl::Error : public std::exception
|
||||
{
|
||||
public:
|
||||
explicit Error( const std::string & ) ;
|
||||
Error( const std::string & , unsigned long ) ;
|
||||
virtual ~Error() throw() ;
|
||||
virtual const char * what() const throw() ;
|
||||
|
||||
private:
|
||||
std::string m_what ;
|
||||
} ;
|
||||
|
||||
//
|
||||
|
||||
GSsl::LibraryImp::LibraryImp( const std::string & pem_file ) :
|
||||
m_context(NULL) ,
|
||||
m_pem_file(pem_file)
|
||||
{
|
||||
SSL_load_error_strings() ;
|
||||
SSL_library_init() ;
|
||||
|
||||
// we probably don't need entropy but make a token effort to find
|
||||
// some: "openssl automatically queries EGD when [...] the
|
||||
// status is checked via RAND_status() for the first time if [a]
|
||||
// socket is located at /var/run/edg-pool ..."
|
||||
//
|
||||
if( ! RAND_status() )
|
||||
;
|
||||
|
||||
m_context = new Context( pem_file ) ;
|
||||
}
|
||||
|
||||
GSsl::LibraryImp::~LibraryImp()
|
||||
{
|
||||
delete m_context ;
|
||||
ERR_free_strings() ;
|
||||
RAND_cleanup() ;
|
||||
}
|
||||
|
||||
GSsl::Context & GSsl::LibraryImp::ctx()
|
||||
{
|
||||
return *m_context ;
|
||||
}
|
||||
|
||||
std::string GSsl::LibraryImp::pem() const
|
||||
{
|
||||
return m_pem_file ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSsl::Library * GSsl::Library::m_this = NULL ;
|
||||
|
||||
GSsl::Library::Library() :
|
||||
m_imp(NULL)
|
||||
{
|
||||
if( m_this == NULL )
|
||||
m_this = this ;
|
||||
m_imp = new LibraryImp ;
|
||||
}
|
||||
|
||||
GSsl::Library::Library( bool active , const std::string & pem_file ) :
|
||||
m_imp(NULL)
|
||||
{
|
||||
if( m_this == NULL )
|
||||
m_this = this ;
|
||||
if( active )
|
||||
m_imp = new LibraryImp( pem_file ) ;
|
||||
}
|
||||
|
||||
GSsl::Library::~Library()
|
||||
{
|
||||
delete m_imp ;
|
||||
if( m_this == NULL )
|
||||
m_this = NULL ;
|
||||
}
|
||||
|
||||
GSsl::Library * GSsl::Library::instance()
|
||||
{
|
||||
return m_this ;
|
||||
}
|
||||
|
||||
bool GSsl::Library::enabled( bool for_server ) const
|
||||
{
|
||||
return m_imp != NULL && ( !for_server || !m_imp->pem().empty() ) ;
|
||||
}
|
||||
|
||||
std::string GSsl::Library::credit( const std::string & prefix , const std::string & eol , const std::string & final )
|
||||
{
|
||||
std::ostringstream ss ;
|
||||
ss
|
||||
<< prefix << "This product includes software developed by the OpenSSL Project" << eol
|
||||
<< prefix << "for use in the OpenSSL Toolkit (http://www.openssl.org/)" << eol
|
||||
<< final ;
|
||||
return ss.str() ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSsl::Context::Context( const std::string & pem_file )
|
||||
{
|
||||
m_ssl_ctx = SSL_CTX_new(TLSv1_method()) ;
|
||||
if( m_ssl_ctx == NULL )
|
||||
throw Error( "SSL_CTX_new" , ERR_get_error() ) ;
|
||||
|
||||
init( pem_file ) ;
|
||||
}
|
||||
|
||||
GSsl::Context::~Context()
|
||||
{
|
||||
SSL_CTX_free( m_ssl_ctx ) ;
|
||||
}
|
||||
|
||||
SSL_CTX * GSsl::Context::p() const
|
||||
{
|
||||
return m_ssl_ctx ;
|
||||
}
|
||||
|
||||
void GSsl::Context::init( const std::string & pem_file )
|
||||
{
|
||||
SSL_CTX_set_quiet_shutdown( m_ssl_ctx , 1 ) ;
|
||||
if( !pem_file.empty() )
|
||||
{
|
||||
check( SSL_CTX_use_certificate_chain_file(m_ssl_ctx,pem_file.c_str()) , "use_certificate_chain_file" ) ;
|
||||
check( SSL_CTX_use_RSAPrivateKey_file(m_ssl_ctx,pem_file.c_str(),SSL_FILETYPE_PEM) , "use_RSAPrivateKey_file" );
|
||||
check( SSL_CTX_set_cipher_list(m_ssl_ctx,"DEFAULT") , "set_cipher_list" ) ;
|
||||
}
|
||||
}
|
||||
|
||||
void GSsl::Context::check( int rc , const char * op )
|
||||
{
|
||||
if( rc != 1 )
|
||||
throw Error( std::string() + "SSL_CTX_" + op ) ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSsl::Error::Error( const std::string & s ) :
|
||||
m_what(std::string()+"ssl error: "+s)
|
||||
{
|
||||
}
|
||||
|
||||
GSsl::Error::Error( const std::string & s , unsigned long e ) :
|
||||
m_what(std::string()+"ssl error: "+s)
|
||||
{
|
||||
std::vector<char> v( 300 ) ;
|
||||
ERR_error_string_n( e , &v[0] , v.size() ) ;
|
||||
std::string reason( &v[0] , v.size() ) ;
|
||||
reason = std::string( reason.c_str() ) ; // (lazy)
|
||||
m_what.append( std::string() + ": [" + reason + "]" ) ;
|
||||
}
|
||||
|
||||
GSsl::Error::~Error() throw ()
|
||||
{
|
||||
}
|
||||
|
||||
const char * GSsl::Error::what() const throw ()
|
||||
{
|
||||
return m_what.c_str() ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSsl::Protocol::Protocol( const Library & library ) :
|
||||
m_imp( new ProtocolImp(library.m_imp->ctx()) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
GSsl::Protocol::Protocol( const Library & library , LogFn log , bool hexdump ) :
|
||||
m_imp( new ProtocolImp(library.m_imp->ctx(),log,hexdump) )
|
||||
{
|
||||
}
|
||||
|
||||
GSsl::Protocol::~Protocol()
|
||||
{
|
||||
delete m_imp ;
|
||||
}
|
||||
|
||||
std::string GSsl::Protocol::str( Protocol::Result result )
|
||||
{
|
||||
if( result == Result_ok ) return "Result_ok" ;
|
||||
if( result == Result_read ) return "Result_read" ;
|
||||
if( result == Result_write ) return "Result_write" ;
|
||||
if( result == Result_error ) return "Result_error" ;
|
||||
return "Result_undefined" ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::connect( int fd )
|
||||
{
|
||||
return m_imp->connect( fd ) ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::accept( int fd )
|
||||
{
|
||||
return m_imp->accept( fd ) ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::stop()
|
||||
{
|
||||
return m_imp->stop() ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::read( char * buffer , size_type buffer_size_in , ssize_type & data_size_out )
|
||||
{
|
||||
return m_imp->read( buffer , buffer_size_in , data_size_out ) ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::Protocol::write( const char * buffer , size_type data_size_in ,
|
||||
ssize_type & data_size_out )
|
||||
{
|
||||
return m_imp->write( buffer , data_size_in , data_size_out ) ;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
GSsl::ProtocolImp::ProtocolImp( const Context & c ) :
|
||||
m_ssl(NULL) ,
|
||||
m_log_fn(NULL) ,
|
||||
m_fd_set(false)
|
||||
{
|
||||
m_ssl = SSL_new( c.p() ) ;
|
||||
if( m_ssl == NULL )
|
||||
throw Error( "SSL_new" , ERR_get_error() ) ;
|
||||
}
|
||||
|
||||
GSsl::ProtocolImp::ProtocolImp( const Context & c , LogFn log , bool hexdump ) :
|
||||
m_ssl(NULL) ,
|
||||
m_log_fn(log) ,
|
||||
m_fd_set(false)
|
||||
{
|
||||
m_ssl = SSL_new( c.p() ) ;
|
||||
if( m_ssl == NULL )
|
||||
throw Error( "SSL_new" , ERR_get_error() ) ;
|
||||
|
||||
if( hexdump )
|
||||
{
|
||||
SSL_set_msg_callback( m_ssl , callback ) ;
|
||||
SSL_set_msg_callback_arg( m_ssl , this ) ;
|
||||
}
|
||||
}
|
||||
|
||||
GSsl::ProtocolImp::~ProtocolImp()
|
||||
{
|
||||
SSL_free( m_ssl ) ;
|
||||
}
|
||||
|
||||
void GSsl::ProtocolImp::loghex( void (*fn)(int,const std::string&) , int arg ,
|
||||
const char * prefix , const std::string & in )
|
||||
{
|
||||
std::string line ;
|
||||
unsigned int i = 0 ;
|
||||
for( std::string::const_iterator p = in.begin() ; p != in.end() ; ++p , i++ )
|
||||
{
|
||||
std::ostringstream ss ;
|
||||
if( line.empty() )
|
||||
{
|
||||
ss.width(6) ;
|
||||
ss.fill('0') ;
|
||||
ss << std::hex << i << ": " ;
|
||||
}
|
||||
ss.width(2) ;
|
||||
ss.fill('0') ;
|
||||
ss << std::hex << (static_cast<unsigned int>(*p) & 0xff) << " " ;
|
||||
line.append( ss.str() ) ;
|
||||
|
||||
if( i > 0 && ((i+1)%16) == 0 )
|
||||
{
|
||||
(*fn)( arg , std::string(prefix) + line ) ;
|
||||
line.erase() ;
|
||||
}
|
||||
}
|
||||
if( !line.empty() )
|
||||
(*fn)( arg , std::string(prefix) + line ) ;
|
||||
}
|
||||
|
||||
void GSsl::ProtocolImp::callback( int write , int v , int type , const void * buffer , size_t n , SSL * , void * p )
|
||||
{
|
||||
ProtocolImp * This = reinterpret_cast<ProtocolImp*>(p) ;
|
||||
if( This->m_log_fn != NULL )
|
||||
{
|
||||
// build the whole pdu, including the header
|
||||
unsigned int version_ = static_cast<unsigned int>(v) ;
|
||||
unsigned int version_lo = version_ & 0xff ;
|
||||
unsigned int version_hi = ( version_ >> 8 ) & 0xff ;
|
||||
unsigned int n_ = static_cast<unsigned int>(n) ;
|
||||
unsigned int length_lo = n_ & 0xff ;
|
||||
unsigned int length_hi = ( n_ >> 8 ) & 0xff ;
|
||||
std::string data( 1U , static_cast<char>(type) ) ;
|
||||
data.append( 1U , static_cast<char>(version_hi) ) ;
|
||||
data.append( 1U , static_cast<char>(version_lo) ) ;
|
||||
data.append( 1U , static_cast<char>(length_hi) ) ;
|
||||
data.append( 1U , static_cast<char>(length_lo) ) ;
|
||||
data.append( std::string(reinterpret_cast<const char*>(buffer),n) ) ;
|
||||
|
||||
loghex( This->m_log_fn , 0 , write?"ssl-tx>>: ":"ssl-rx<<: " , data ) ;
|
||||
}
|
||||
}
|
||||
|
||||
void GSsl::ProtocolImp::clearErrors()
|
||||
{
|
||||
for( int i = 0 ; ERR_get_error() && i < 10000 ; i++ )
|
||||
;
|
||||
}
|
||||
|
||||
int GSsl::ProtocolImp::error( const char * op , int rc ) const
|
||||
{
|
||||
int e = SSL_get_error( m_ssl , rc ) ;
|
||||
|
||||
if( m_log_fn != NULL )
|
||||
{
|
||||
std::ostringstream ss ;
|
||||
ss << "ssl error: " << op << ": rc=" << rc << ": error " << e << " => " << Protocol::str(convert(e)) ;
|
||||
(*m_log_fn)( 1 , ss.str() ) ;
|
||||
unsigned long ee = 0 ;
|
||||
for( int i = 2 ; i < 10000 ; i++ )
|
||||
{
|
||||
ee = ERR_get_error() ;
|
||||
if( ee == 0 ) break ;
|
||||
Error eee( op , ee ) ;
|
||||
(*m_log_fn)( i , std::string() + eee.what() ) ;
|
||||
}
|
||||
}
|
||||
|
||||
return e ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::convert( int e )
|
||||
{
|
||||
if( e == SSL_ERROR_WANT_READ ) return Protocol::Result_read ;
|
||||
if( e == SSL_ERROR_WANT_WRITE ) return Protocol::Result_write ;
|
||||
return Protocol::Result_error ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::connect( int fd )
|
||||
{
|
||||
set( fd ) ;
|
||||
return connect() ;
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::accept( int fd )
|
||||
{
|
||||
set( fd ) ;
|
||||
return accept() ;
|
||||
}
|
||||
|
||||
void GSsl::ProtocolImp::set( int fd )
|
||||
{
|
||||
if( !m_fd_set )
|
||||
{
|
||||
int rc = SSL_set_fd( m_ssl , fd ) ;
|
||||
if( rc == 0 )
|
||||
throw Error( "SSL_set_fd" , ERR_get_error() ) ;
|
||||
m_fd_set = true ;
|
||||
}
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::connect()
|
||||
{
|
||||
clearErrors() ;
|
||||
int rc = SSL_connect( m_ssl ) ;
|
||||
if( rc >= 1 )
|
||||
{
|
||||
return Protocol::Result_ok ;
|
||||
}
|
||||
else if( rc == 0 )
|
||||
{
|
||||
return convert(error("SSL_connect",rc)) ;
|
||||
}
|
||||
else // rc < 0
|
||||
{
|
||||
return convert(error("SSL_connect",rc)) ;
|
||||
}
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::accept()
|
||||
{
|
||||
clearErrors() ;
|
||||
int rc = SSL_accept( m_ssl ) ;
|
||||
if( rc >= 1 )
|
||||
{
|
||||
return Protocol::Result_ok ;
|
||||
}
|
||||
else if( rc == 0 )
|
||||
{
|
||||
return convert(error("SSL_accept",rc)) ;
|
||||
}
|
||||
else // rc < 0
|
||||
{
|
||||
return convert(error("SSL_accept",rc)) ;
|
||||
}
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::stop()
|
||||
{
|
||||
int rc = SSL_shutdown( m_ssl ) ;
|
||||
return rc == 1 ? Protocol::Result_ok : Protocol::Result_error ; // since quiet shutdown
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::read( char * buffer , size_type buffer_size , ssize_type & read_size )
|
||||
{
|
||||
read_size = 0 ;
|
||||
clearErrors() ;
|
||||
|
||||
int rc = SSL_read( m_ssl , buffer , buffer_size ) ;
|
||||
if( rc > 0 )
|
||||
{
|
||||
read_size = static_cast<ssize_type>(rc) ;
|
||||
return Protocol::Result_ok ;
|
||||
}
|
||||
else if( rc == 0 )
|
||||
{
|
||||
return convert(error("SSL_read",rc)) ;
|
||||
}
|
||||
else // rc < 0
|
||||
{
|
||||
return convert(error("SSL_read",rc)) ;
|
||||
}
|
||||
}
|
||||
|
||||
GSsl::Protocol::Result GSsl::ProtocolImp::write( const char * buffer , size_type size_in , ssize_type & size_out )
|
||||
{
|
||||
size_out = 0 ;
|
||||
|
||||
clearErrors() ;
|
||||
int rc = SSL_write( m_ssl , buffer , size_in ) ;
|
||||
if( rc > 0 )
|
||||
{
|
||||
size_out = static_cast<ssize_type>(rc) ;
|
||||
return Protocol::Result_ok ;
|
||||
}
|
||||
else if( rc == 0 )
|
||||
{
|
||||
return convert(error("SSL_write",rc)) ;
|
||||
}
|
||||
else // rc < 0
|
||||
{
|
||||
return convert(error("SSL_write",rc)) ;
|
||||
}
|
||||
}
|
||||
|
||||
bool GSsl::Protocol::defaultHexdump()
|
||||
{
|
||||
return false ; // perhaps G::Test::enabled() ?
|
||||
}
|
||||
|
34
src/gssl/mingw.mak
Normal file
34
src/gssl/mingw.mak
Normal file
@ -0,0 +1,34 @@
|
||||
#
|
||||
## Copyright (C) 2001-2007 Graeme Walker <graeme_walker@users.sourceforge.net>
|
||||
##
|
||||
## This program is free software: you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation, either version 3 of the License, or
|
||||
## (at your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#
|
||||
# mingw.mak
|
||||
#
|
||||
|
||||
mk_sources=\
|
||||
gssl_$(mk_ssl).cpp
|
||||
|
||||
mk_target=gssl.a
|
||||
|
||||
mk_includes_extra=-I$(mk_openssl)/outinc
|
||||
|
||||
all: $(mk_target)
|
||||
|
||||
include ../mingw-common.mak
|
||||
|
||||
$(mk_target): $(mk_objects)
|
||||
$(mk_ar) $(mk_target) $(mk_objects)
|
||||
|
@ -6,7 +6,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>emailrelay-gui</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.6</string>
|
||||
<string>1.7</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
<string>(c) 2001-2007 Graeme Walker</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
|
@ -138,6 +138,10 @@ QT_LIBS = @QT_LIBS@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
SSL = @SSL@
|
||||
SSL_LIBS = @SSL_LIBS@
|
||||
STATIC_END = @STATIC_END@
|
||||
STATIC_START = @STATIC_START@
|
||||
STRIP = @STRIP@
|
||||
VERSION = @VERSION@
|
||||
abs_builddir = @abs_builddir@
|
||||
|
@ -71,7 +71,7 @@ bool Boot::install( G::Path dir_boot , G::Path target , G::Strings )
|
||||
|
||||
#endif
|
||||
|
||||
bool Boot::uninstall( G::Path dir_boot , G::Path target , G::Strings args )
|
||||
bool Boot::uninstall( G::Path , G::Path , G::Strings )
|
||||
{
|
||||
return true ; // TODO
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
// See also "dir_unix.cpp" and "dir_win32.cpp".
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "dir.h"
|
||||
#include "gstr.h"
|
||||
#include "gpath.h"
|
||||
@ -40,7 +41,6 @@ Dir::Dir( const std::string & argv0 , bool installed ) :
|
||||
m_desktop = special("desktop") ;
|
||||
m_login = special("login") ;
|
||||
m_menu = special("menu") ;
|
||||
m_reskit = special("reskit") ;
|
||||
}
|
||||
|
||||
Dir::~Dir()
|
||||
@ -62,7 +62,7 @@ void Dir::read( std::istream & file )
|
||||
line = G::Str::readLineFrom(file,"\n") ; if( file.good() && !line.empty() ) m_desktop = line ;
|
||||
line = G::Str::readLineFrom(file,"\n") ; if( file.good() && !line.empty() ) m_login = line ;
|
||||
line = G::Str::readLineFrom(file,"\n") ; if( file.good() && !line.empty() ) m_menu = line ;
|
||||
line = G::Str::readLineFrom(file,"\n") ; if( file.good() && !line.empty() ) m_reskit = line ;
|
||||
line = G::Str::readLineFrom(file,"\n") ; if( file.good() && !line.empty() ) ; // reskit not used
|
||||
|
||||
// this is for completeness only...
|
||||
line = G::Str::readLineFrom(file,"\n") ; if( file.good() && !line.empty() ) m_install = line ;
|
||||
@ -93,11 +93,6 @@ G::Path Dir::menu() const
|
||||
return m_menu ;
|
||||
}
|
||||
|
||||
G::Path Dir::reskit() const
|
||||
{
|
||||
return m_reskit ;
|
||||
}
|
||||
|
||||
G::Path Dir::tmp() const
|
||||
{
|
||||
return m_tmp ;
|
||||
|
@ -77,9 +77,6 @@ public:
|
||||
G::Path menu() const ;
|
||||
///< Returns the menu path.
|
||||
|
||||
G::Path reskit() const ;
|
||||
///< Returns the windows resource kit path.
|
||||
|
||||
static std::string dotexe() ;
|
||||
///< Returns ".exe" or not.
|
||||
|
||||
@ -112,7 +109,6 @@ private:
|
||||
G::Path m_desktop ;
|
||||
G::Path m_boot ;
|
||||
G::Path m_menu ;
|
||||
G::Path m_reskit ;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,7 @@
|
||||
// dir_unix.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "dir.h"
|
||||
#include "gpath.h"
|
||||
#include "gdirectory.h"
|
||||
@ -137,13 +138,11 @@ G::Path Dir::special( const std::string & type )
|
||||
G::Path menu = data_home + "applications" ;
|
||||
G::Path login = kdeAutostart( config_home + "autostart" ) ;
|
||||
G::Path programs = "/usr/bin" ;
|
||||
G::Path reskit ;
|
||||
|
||||
if( type == "desktop" ) return desktop ;
|
||||
if( type == "menu" ) return menu ;
|
||||
if( type == "login" ) return login ;
|
||||
if( type == "programs" ) return programs ;
|
||||
if( type == "reskit" ) return reskit ;
|
||||
return G::Path() ;
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
// dir_win32.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#define _WIN32_IE 0x600
|
||||
#include <shlwapi.h>
|
||||
#include <shlobj.h>
|
||||
@ -60,7 +61,7 @@ G::Path Dir::os_install() const
|
||||
|
||||
G::Path Dir::os_config() const
|
||||
{
|
||||
return windows() ;
|
||||
return special("programs") + "emailrelay" ; // was windows()
|
||||
}
|
||||
|
||||
G::Path Dir::os_spool() const
|
||||
@ -68,6 +69,16 @@ G::Path Dir::os_spool() const
|
||||
return windows() + "spool" + "emailrelay" ;
|
||||
}
|
||||
|
||||
G::Path Dir::os_pid() const
|
||||
{
|
||||
return special("programs") + "emailrelay" ; // was windows()
|
||||
}
|
||||
|
||||
G::Path Dir::os_boot() const
|
||||
{
|
||||
return G::Path() ;
|
||||
}
|
||||
|
||||
G::Path Dir::cwd()
|
||||
{
|
||||
char buffer[10000] = { '\0' } ;
|
||||
@ -77,16 +88,6 @@ G::Path Dir::cwd()
|
||||
return G::Path( s ) ;
|
||||
}
|
||||
|
||||
G::Path Dir::os_pid() const
|
||||
{
|
||||
return windows() ;
|
||||
}
|
||||
|
||||
G::Path Dir::os_boot() const
|
||||
{
|
||||
return G::Path() ;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
int special_id( const std::string & type )
|
||||
@ -119,10 +120,6 @@ G::Path Dir::special( const std::string & type )
|
||||
buffer[sizeof(buffer)-1U] = '\0' ;
|
||||
return ok ? G::Path(std::string(buffer)) : G::Path("c:/program files") ;
|
||||
}
|
||||
else if( type == "reskit" )
|
||||
{
|
||||
return special("programs")+"resource kit";
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer[MAX_PATH] = { '\0' } ;
|
||||
@ -158,15 +155,7 @@ G::Path Dir::ntspecial( const std::string & type )
|
||||
p = "c:/program files" ;
|
||||
return p ;
|
||||
}
|
||||
if( type == "reskit" )
|
||||
{
|
||||
G::Path p = env("NTRESKIT") ;
|
||||
if( p.str().empty() )
|
||||
p = special("programs")+"resource kit";
|
||||
return p ;
|
||||
}
|
||||
return G::Path() ;
|
||||
}
|
||||
|
||||
|
||||
/// \file dir_win32.cpp
|
||||
|
@ -18,6 +18,7 @@
|
||||
// gdialog.cpp
|
||||
//
|
||||
|
||||
#include "gdef.h"
|
||||
#include "qt.h"
|
||||
#include "gdialog.h"
|
||||
#include "gdebug.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user