mirror of
https://github.com/3proxy/3proxy.git
synced 2026-10-30 14:45:49 +08:00
Compare commits
No commits in common. "98e8dfb004ca7ee129e2270bb811a61d35174b0c" and "3883a51969907f604b8e213cb50fb5b8c352c04d" have entirely different histories.
98e8dfb004
...
3883a51969
@ -415,12 +415,11 @@ set(3PROXY_CORE_SOURCES
|
|||||||
# Object libraries for common sources (shared between executables)
|
# Object libraries for common sources (shared between executables)
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
# Common object library (sockmap, sockgetchar, common, sem, log)
|
# Common object library (sockmap, sockgetchar, common, log)
|
||||||
add_library(common_obj OBJECT
|
add_library(common_obj OBJECT
|
||||||
src/sockmap.c
|
src/sockmap.c
|
||||||
src/sockgetchar.c
|
src/sockgetchar.c
|
||||||
src/common.c
|
src/common.c
|
||||||
src/sem.c
|
|
||||||
src/log.c
|
src/log.c
|
||||||
)
|
)
|
||||||
target_include_directories(common_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
target_include_directories(common_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||||
|
|||||||
@ -35,7 +35,7 @@ RUN TAG=$(curl -s https://api.github.com/repos/wolfSSL/wolfssl/releases/latest \
|
|||||||
make -j$(nproc) && make install
|
make -j$(nproc) && make install
|
||||||
|
|
||||||
FROM docker.io/alpine:latest AS buildenv
|
FROM docker.io/alpine:latest AS buildenv
|
||||||
RUN apk add --no-cache gcc make musl-dev linux-headers pcre2-dev
|
RUN apk add --no-cache gcc make musl-dev pcre2-dev
|
||||||
COPY --from=wolfssl /usr/local /usr/local
|
COPY --from=wolfssl /usr/local /usr/local
|
||||||
COPY . 3proxy
|
COPY . 3proxy
|
||||||
RUN cd 3proxy && mkdir -p bin &&\
|
RUN cd 3proxy && mkdir -p bin &&\
|
||||||
|
|||||||
@ -41,7 +41,7 @@ RUN TAG=$(curl -s https://api.github.com/repos/wolfSSL/wolfssl/releases/latest \
|
|||||||
make -j$(nproc) && make install
|
make -j$(nproc) && make install
|
||||||
|
|
||||||
FROM docker.io/alpine:latest AS buildenv
|
FROM docker.io/alpine:latest AS buildenv
|
||||||
RUN apk add --no-cache gcc make musl-dev linux-headers
|
RUN apk add --no-cache gcc make musl-dev
|
||||||
COPY --from=wolfssl /usr/local /usr/local
|
COPY --from=wolfssl /usr/local /usr/local
|
||||||
COPY . 3proxy
|
COPY . 3proxy
|
||||||
RUN cd 3proxy && mkdir -p bin &&\
|
RUN cd 3proxy && mkdir -p bin &&\
|
||||||
|
|||||||
@ -135,7 +135,7 @@ install: all
|
|||||||
install -d $(DESTDIR)$(MANDIR)/man8
|
install -d $(DESTDIR)$(MANDIR)/man8
|
||||||
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
||||||
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
|
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
|
||||||
if [ -f man/$$f.8 ] && [ -f bin/$(PREFIX)$$f ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
|
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
|
||||||
done
|
done
|
||||||
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
||||||
install -d $(DESTDIR)$(MANDIR)/man5
|
install -d $(DESTDIR)$(MANDIR)/man5
|
||||||
|
|||||||
@ -123,18 +123,15 @@ INSTALL_BIN = $(INSTALL) -m 755
|
|||||||
INSTALL_DATA = $(INSTALL) -m 644
|
INSTALL_DATA = $(INSTALL) -m 644
|
||||||
INSTALL_OBJS = bin/3proxy \
|
INSTALL_OBJS = bin/3proxy \
|
||||||
bin/$(CRYPT_PREFIX)crypt \
|
bin/$(CRYPT_PREFIX)crypt \
|
||||||
|
bin/$(PREFIX)ftppr \
|
||||||
|
bin/$(PREFIX)imapp \
|
||||||
|
bin/$(PREFIX)pop3p \
|
||||||
bin/$(PREFIX)proxy \
|
bin/$(PREFIX)proxy \
|
||||||
|
bin/$(PREFIX)smtpp \
|
||||||
bin/$(PREFIX)socks \
|
bin/$(PREFIX)socks \
|
||||||
bin/$(PREFIX)tcppm \
|
bin/$(PREFIX)tcppm \
|
||||||
bin/$(PREFIX)tlspr \
|
bin/$(PREFIX)tlspr \
|
||||||
bin/$(PREFIX)udppm
|
bin/$(PREFIX)udppm
|
||||||
# the mail proxies and ftppr are only there when they were built
|
|
||||||
ifeq ($(MAILPROXY),true)
|
|
||||||
INSTALL_OBJS += bin/$(PREFIX)imapp bin/$(PREFIX)pop3p bin/$(PREFIX)smtpp
|
|
||||||
endif
|
|
||||||
ifeq ($(FTP),true)
|
|
||||||
INSTALL_OBJS += bin/$(PREFIX)ftppr
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
INSTALL_CFG = scripts/3proxy.cfg.chroot
|
INSTALL_CFG = scripts/3proxy.cfg.chroot
|
||||||
@ -192,7 +189,7 @@ install-man:
|
|||||||
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
|
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
|
||||||
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
|
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
|
||||||
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
|
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
|
||||||
if [ -f man/$$f.8 ] && [ -f bin/$(PREFIX)$$f ]; then $(INSTALL_DATA) man/$$f.8 $(MANDIR8)/$(PREFIX)$$f.8; fi; \
|
if [ -f man/$$f.8 ]; then $(INSTALL_DATA) man/$$f.8 $(MANDIR8)/$(PREFIX)$$f.8; fi; \
|
||||||
done
|
done
|
||||||
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8
|
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,7 @@ install: all
|
|||||||
install -d $(DESTDIR)$(MANDIR)/man8
|
install -d $(DESTDIR)$(MANDIR)/man8
|
||||||
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
||||||
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
|
for f in proxy socks pop3p imapp smtpp ftppr tcppm udppm tlspr; do \
|
||||||
if [ -f man/$$f.8 ] && [ -f bin/$(PREFIX)$$f ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
|
if [ -f man/$$f.8 ]; then install -m 644 man/$$f.8 $(DESTDIR)$(MANDIR)/man8/$(PREFIX)$$f.8; fi; \
|
||||||
done
|
done
|
||||||
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
||||||
install -d $(DESTDIR)$(MANDIR)/man5
|
install -d $(DESTDIR)$(MANDIR)/man5
|
||||||
|
|||||||
2
debian/control
vendored
2
debian/control
vendored
@ -14,5 +14,5 @@ Depends: ${shlibs:Depends}, ${misc:Depends}
|
|||||||
Description: tiny free proxy server
|
Description: tiny free proxy server
|
||||||
3Proxy tiny free proxy server is really tiny freeware proxy servers set.
|
3Proxy tiny free proxy server is really tiny freeware proxy servers set.
|
||||||
It includes HTTP proxy with HTTPS and FTP support, SOCKSv4/SOCKSv4.5/SOCKSv5 proxy (socks/socks.exe), POP3 proxy, SMTP proxy, FTP proxy, caching DNS proxy, TCP and UDP portmappers.
|
It includes HTTP proxy with HTTPS and FTP support, SOCKSv4/SOCKSv4.5/SOCKSv5 proxy (socks/socks.exe), POP3 proxy, SMTP proxy, FTP proxy, caching DNS proxy, TCP and UDP portmappers.
|
||||||
You can use every proxy as a standalone program (socks, proxy, tcppm, udppm, tlspr) or use combined program (3proxy). Combined proxy additionally supports features like access control, bandwidth limiting, limiting daily/weekly/monthly traffic amount, proxy chaining, log rotation, syslog and ODBC logging, etc.
|
You can use every proxy as a standalone program (socks, proxy, tcppm, udppm, pop3p) or use combined program (3proxy). Combined proxy additionally supports features like access control, bandwidth limiting, limiting daily/weekly/monthly traffic amount, proxy chaining, log rotation, syslog and ODBC logging, etc.
|
||||||
It's created to be small, simple and yet very functional.
|
It's created to be small, simple and yet very functional.
|
||||||
@ -36,7 +36,11 @@ make clean
|
|||||||
%files
|
%files
|
||||||
/bin/3proxy
|
/bin/3proxy
|
||||||
/bin/3proxy_crypt
|
/bin/3proxy_crypt
|
||||||
|
/bin/3proxy_ftppr
|
||||||
|
/bin/3proxy_imapp
|
||||||
|
/bin/3proxy_pop3p
|
||||||
/bin/3proxy_proxy
|
/bin/3proxy_proxy
|
||||||
|
/bin/3proxy_smtpp
|
||||||
/bin/3proxy_socks
|
/bin/3proxy_socks
|
||||||
/bin/3proxy_tcppm
|
/bin/3proxy_tcppm
|
||||||
/bin/3proxy_tlspr
|
/bin/3proxy_tlspr
|
||||||
|
|||||||
@ -13,9 +13,6 @@ udpsockmap$(OBJSUFFICS): udpsockmap.c proxy.h structures.h
|
|||||||
common$(OBJSUFFICS): common.c proxy.h structures.h
|
common$(OBJSUFFICS): common.c proxy.h structures.h
|
||||||
$(CC) $(CFLAGS) common.c
|
$(CC) $(CFLAGS) common.c
|
||||||
|
|
||||||
sem$(OBJSUFFICS): sem.c proxy.h structures.h
|
|
||||||
$(CC) $(CFLAGS) sem.c
|
|
||||||
|
|
||||||
plugins$(OBJSUFFICS): plugins.c proxy.h structures.h
|
plugins$(OBJSUFFICS): plugins.c proxy.h structures.h
|
||||||
$(CC) $(CFLAGS) plugins.c
|
$(CC) $(CFLAGS) plugins.c
|
||||||
|
|
||||||
@ -59,32 +56,32 @@ socks$(OBJSUFFICS): socks.c proxy.h structures.h proxymain.c
|
|||||||
3proxy$(OBJSUFFICS): 3proxy.c proxy.h structures.h
|
3proxy$(OBJSUFFICS): 3proxy.c proxy.h structures.h
|
||||||
$(CC) $(CFLAGS) 3proxy.c
|
$(CC) $(CFLAGS) 3proxy.c
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS)
|
$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS): sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)proxy$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) proxy$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) base64$(OBJSUFFICS) $(COMPATLIBS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) base64$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) $(COMPATLIBS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
|
$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) hash$(OBJSUFFICS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) hash$(OBJSUFFICS) $(LIBS)
|
||||||
|
|
||||||
$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) $(LIBS)
|
||||||
|
|
||||||
mainfunc$(OBJSUFFICS): proxy.h structures.h proxymain.c
|
mainfunc$(OBJSUFFICS): proxy.h structures.h proxymain.c
|
||||||
$(CC) $(COUT)mainfunc$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)MODULEMAINFUNC=mainfunc proxymain.c
|
$(CC) $(COUT)mainfunc$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)MODULEMAINFUNC=mainfunc proxymain.c
|
||||||
@ -197,6 +194,6 @@ ssl$(OBJSUFFICS): ssl.c structures.h proxy.h ssl.h
|
|||||||
pcre$(OBJSUFFICS): pcre.c structures.h
|
pcre$(OBJSUFFICS): pcre.c structures.h
|
||||||
$(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE pcre.c
|
$(CC) $(COUT)pcre$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITH_PCRE pcre.c
|
||||||
|
|
||||||
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(VERSIONDEP)
|
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(VERSIONDEP)
|
||||||
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)
|
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) acl$(OBJSUFFICS) limiter$(OBJSUFFICS) redirect$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) hashtables$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvimapp$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) $(HTTPSRV_OBJS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) mdhash$(OBJSUFFICS) $(SSL_OBJS) $(PCRE_OBJS) $(TRANSPARENT_OBJS) $(COMPATLIBS) $(LIBS) $(PCRE_LIBS)
|
||||||
|
|
||||||
|
|||||||
90
src/common.c
90
src/common.c
@ -187,6 +187,33 @@ size_t threadstacksize(int extra){
|
|||||||
if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN;
|
if(size < (long)PTHREAD_STACK_MIN) size = (long)PTHREAD_STACK_MIN;
|
||||||
return (size_t)size;
|
return (size_t)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount){
|
||||||
|
sem->count = count;
|
||||||
|
sem->maxcount = maxcount;
|
||||||
|
if(pthread_mutex_init(&sem->mutex, NULL)) return 1;
|
||||||
|
if(pthread_cond_init(&sem->cond, NULL)){
|
||||||
|
pthread_mutex_destroy(&sem->mutex);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _3proxy_sem_lock_f(_3proxy_sem_t *sem){
|
||||||
|
pthread_mutex_lock(&sem->mutex);
|
||||||
|
while(!sem->count) pthread_cond_wait(&sem->cond, &sem->mutex);
|
||||||
|
sem->count--;
|
||||||
|
pthread_mutex_unlock(&sem->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem){
|
||||||
|
pthread_mutex_lock(&sem->mutex);
|
||||||
|
if(sem->count < sem->maxcount){
|
||||||
|
sem->count++;
|
||||||
|
pthread_cond_signal(&sem->cond);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&sem->mutex);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct extparam conf = {
|
struct extparam conf = {
|
||||||
@ -656,49 +683,6 @@ int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa,
|
|||||||
|
|
||||||
static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries);
|
static int bindrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range, int *tries);
|
||||||
|
|
||||||
/* -Di / -De: ties a socket to the interface asked for, for TCP and UDP alike.
|
|
||||||
Where the option is set per protocol, family is the one of the address the
|
|
||||||
socket will be bound to. */
|
|
||||||
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family){
|
|
||||||
if(!device) return 0;
|
|
||||||
#if defined SO_BINDTODEVICE
|
|
||||||
if(sf->_setsockopt(state, sock, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device) + 1))
|
|
||||||
return 1;
|
|
||||||
#elif defined IP_BOUND_IF
|
|
||||||
{
|
|
||||||
int idx;
|
|
||||||
idx = if_nametoindex(device);
|
|
||||||
if(!idx || (family == AF_INET && sf->_setsockopt(state, sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
|
||||||
return 1;
|
|
||||||
#ifndef NOIPV6
|
|
||||||
#ifndef IPV6_BOUND_IF
|
|
||||||
#define IPV6_BOUND_IF 125
|
|
||||||
#endif
|
|
||||||
if(family == AF_INET6 && sf->_setsockopt(state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 1;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the external side, a socket to be bound to sinsl */
|
|
||||||
int extbindtodevice(struct clientparam *param, SOCKET sock){
|
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
|
||||||
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->obindtodevice, *SAFAMILY(¶m->sinsl));
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the internal side, a socket to be bound to sincl */
|
|
||||||
int intbindtodevice(struct clientparam *param, SOCKET sock){
|
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
|
||||||
return bindtodevice(¶m->srv->so, param->sostate, sock, param->srv->ibindtodevice, *SAFAMILY(¶m->sincl));
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int doconnect(struct clientparam * param){
|
int doconnect(struct clientparam * param){
|
||||||
SASIZETYPE size;
|
SASIZETYPE size;
|
||||||
|
|
||||||
@ -748,7 +732,25 @@ int doconnect(struct clientparam * param){
|
|||||||
setopts(param->remsock, param->srv->srvsockopts);
|
setopts(param->remsock, param->srv->srvsockopts);
|
||||||
|
|
||||||
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_LINGER, (char *)&lg, sizeof(lg));
|
||||||
if(extbindtodevice(param, param->remsock)) return 12;
|
#if defined SO_BINDTODEVICE
|
||||||
|
if(param->srv->obindtodevice) {
|
||||||
|
if(param->srv->so._setsockopt(param->sostate, param->remsock, SOL_SOCKET, SO_BINDTODEVICE, param->srv->obindtodevice, strlen(param->srv->obindtodevice) + 1))
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
if(param->srv->obindtodevice) {
|
||||||
|
int idx;
|
||||||
|
idx = if_nametoindex(param->srv->obindtodevice);
|
||||||
|
if(!idx || (*SAFAMILY(¶m->sinsl) == AF_INET && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx))))
|
||||||
|
return 12;
|
||||||
|
#ifndef NOIPV6
|
||||||
|
#ifndef IPV6_BOUND_IF
|
||||||
|
#define IPV6_BOUND_IF 125
|
||||||
|
#endif
|
||||||
|
if(*SAFAMILY(¶m->sinsl) == AF_INET6 && param->srv->so._setsockopt(param->sostate, param->remsock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx))) return 12;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -129,7 +129,6 @@ void * ftpprchild(struct clientparam* param) {
|
|||||||
clidatasock = INVALID_SOCKET;
|
clidatasock = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||||
if(intbindtodevice(param, clidatasock)){RETURN(822);}
|
|
||||||
*SAPORT(¶m->sincl) = 0;
|
*SAPORT(¶m->sincl) = 0;
|
||||||
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
||||||
if (pasv) {
|
if (pasv) {
|
||||||
|
|||||||
17
src/proxy.h
17
src/proxy.h
@ -322,23 +322,13 @@ extern _3proxy_sem_t udpinit;
|
|||||||
#define _3proxy_sem_init(x, count, maxcount) (((x) = CreateSemaphore(NULL, (count), (maxcount), NULL))? 0 : 1)
|
#define _3proxy_sem_init(x, count, maxcount) (((x) = CreateSemaphore(NULL, (count), (maxcount), NULL))? 0 : 1)
|
||||||
#define _3proxy_sem_lock(x) WaitForSingleObject(x, INFINITE)
|
#define _3proxy_sem_lock(x) WaitForSingleObject(x, INFINITE)
|
||||||
#define _3proxy_sem_unlock(x) ReleaseSemaphore(x, 1, NULL)
|
#define _3proxy_sem_unlock(x) ReleaseSemaphore(x, 1, NULL)
|
||||||
#define _3proxy_sem_init_timed(x, count, maxcount) _3proxy_sem_init(x, (count), (maxcount))
|
|
||||||
#define _3proxy_sem_timedlock(x, ms) (WaitForSingleObject(x, ms) != WAIT_OBJECT_0)
|
|
||||||
#define _3proxy_sem_destroy(x) CloseHandle(x)
|
|
||||||
#else
|
#else
|
||||||
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount, int timed);
|
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount);
|
||||||
void _3proxy_sem_lock_f(_3proxy_sem_t *sem);
|
void _3proxy_sem_lock_f(_3proxy_sem_t *sem);
|
||||||
int _3proxy_sem_timedlock_f(_3proxy_sem_t *sem, unsigned ms);
|
|
||||||
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem);
|
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem);
|
||||||
void _3proxy_sem_destroy_f(_3proxy_sem_t *sem);
|
#define _3proxy_sem_init(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount))
|
||||||
#define _3proxy_sem_init(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount), 0)
|
|
||||||
/* for a semaphore waited on with a timeout: the wait is not stretched or cut
|
|
||||||
short by the system time being changed, where the platform allows it */
|
|
||||||
#define _3proxy_sem_init_timed(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount), 1)
|
|
||||||
#define _3proxy_sem_lock(x) _3proxy_sem_lock_f(&x)
|
#define _3proxy_sem_lock(x) _3proxy_sem_lock_f(&x)
|
||||||
#define _3proxy_sem_timedlock(x, ms) _3proxy_sem_timedlock_f(&x, (ms))
|
|
||||||
#define _3proxy_sem_unlock(x) _3proxy_sem_unlock_f(&x)
|
#define _3proxy_sem_unlock(x) _3proxy_sem_unlock_f(&x)
|
||||||
#define _3proxy_sem_destroy(x) _3proxy_sem_destroy_f(&x)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -401,9 +391,6 @@ int readconfig(FILE * fp);
|
|||||||
void initcommands(void);
|
void initcommands(void);
|
||||||
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
int connectwithpoll(struct clientparam *param, SOCKET sock, struct sockaddr *sa, SASIZETYPE size, int to);
|
||||||
int bindwithrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range);
|
int bindwithrange(struct clientparam *param, SOCKET sock, PROXYSOCKADDRTYPE *sa, uint32_t range);
|
||||||
int bindtodevice(struct sockfuncs *sf, void *state, SOCKET sock, const char *device, int family);
|
|
||||||
int extbindtodevice(struct clientparam *param, SOCKET sock);
|
|
||||||
int intbindtodevice(struct clientparam *param, SOCKET sock);
|
|
||||||
#ifdef WITH_PCRE
|
#ifdef WITH_PCRE
|
||||||
/* One regular expression implementation for the whole program: the pcre
|
/* One regular expression implementation for the whole program: the pcre
|
||||||
commands and every pattern that carries a pcre: prefix. */
|
commands and every pattern that carries a pcre: prefix. */
|
||||||
|
|||||||
102
src/proxymain.c
102
src/proxymain.c
@ -308,7 +308,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
struct linger lg;
|
struct linger lg;
|
||||||
int nlog = 5000;
|
int nlog = 5000;
|
||||||
int haveslot = 0, nfull = 0;
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
int saved_nsfd = -1;
|
int saved_nsfd = -1;
|
||||||
#endif
|
#endif
|
||||||
@ -863,11 +862,29 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
#if defined SO_BINDTODEVICE
|
||||||
if(bindtodevice(&srv.so, srv.so.state, sock, srv.ibindtodevice, *SAFAMILY(&srv.intsa))) {
|
if(srv.ibindtodevice && srv.so._setsockopt(srv.so.state, sock, SOL_SOCKET, SO_BINDTODEVICE, srv.ibindtodevice, strlen(srv.ibindtodevice) + 1)) {
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
return -12;
|
return -12;
|
||||||
}
|
}
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
if(srv.ibindtodevice){
|
||||||
|
int idx;
|
||||||
|
idx = if_nametoindex(srv.ibindtodevice);
|
||||||
|
if(!idx || (*SAFAMILY(&srv.intsa) == AF_INET && setsockopt(sock, IPPROTO_IP, IP_BOUND_IF, &idx, sizeof(idx)))) {
|
||||||
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
|
return -12;
|
||||||
|
}
|
||||||
|
#ifndef NOIPV6
|
||||||
|
#ifndef IPV6_BOUND_IF
|
||||||
|
#define IPV6_BOUND_IF 125
|
||||||
|
#endif
|
||||||
|
if((*SAFAMILY(&srv.intsa) == AF_INET6 && srv.so._setsockopt(srv.so.state, sock, IPPROTO_IPV6, IPV6_BOUND_IF, &idx, sizeof(idx)))) {
|
||||||
|
dolog(&defparam, (unsigned char *)"failed to bind device");
|
||||||
|
return -12;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
@ -991,19 +1008,14 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
for(;;){
|
for(;;){
|
||||||
/* A connection is only taken with a slot of maxchild in hand, which
|
while((conf.paused == srv.paused && srv.childcount >= srv.maxchild)){
|
||||||
goes to its child; a slot not handed on is kept for the next one.
|
nlog++;
|
||||||
The wait is timed to notice a reload. */
|
if(!srv.silent && nlog > 5000) {
|
||||||
while(!haveslot && conf.paused == srv.paused){
|
|
||||||
if(!_3proxy_sem_timedlock(srv.childslots, 1000)){
|
|
||||||
haveslot = 1;
|
|
||||||
nfull = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!srv.silent && !(nfull++ % 5)) {
|
|
||||||
sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
|
sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
|
||||||
dolog(&defparam, buf);
|
dolog(&defparam, buf);
|
||||||
|
nlog = 0;
|
||||||
}
|
}
|
||||||
|
usleep(SLEEPTIME);
|
||||||
}
|
}
|
||||||
if (iscbc) break;
|
if (iscbc) break;
|
||||||
if (conf.paused != srv.paused) break;
|
if (conf.paused != srv.paused) break;
|
||||||
@ -1026,15 +1038,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
setopts(new_sock, srv.cbcsockopts);
|
setopts(new_sock, srv.cbcsockopts);
|
||||||
|
|
||||||
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr);
|
||||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
|
||||||
/* as for a listening socket, an interface that cannot be
|
|
||||||
bound to is not worth retrying */
|
|
||||||
if(bindtodevice(&so, so.state, new_sock, srv.ibindtodevice, *SAFAMILY(&defparam.sincr))) {
|
|
||||||
dolog(&defparam, (unsigned char *)"failed to bind device");
|
|
||||||
so._closesocket(so.state, new_sock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
if(connectwithpoll(NULL, new_sock,(struct sockaddr *)&defparam.sincr,SASIZE(&defparam.sincr),CONNBACK_TO)) {
|
||||||
so._closesocket(so.state, new_sock);
|
so._closesocket(so.state, new_sock);
|
||||||
new_sock = INVALID_SOCKET;
|
new_sock = INVALID_SOCKET;
|
||||||
@ -1219,7 +1222,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
srv.childcount++;
|
srv.childcount++;
|
||||||
haveslot = 0;
|
|
||||||
newparam->threadid = (uint64_t)thread;
|
newparam->threadid = (uint64_t)thread;
|
||||||
}
|
}
|
||||||
_3proxy_mutex_unlock(&srv.counter_mutex);
|
_3proxy_mutex_unlock(&srv.counter_mutex);
|
||||||
@ -1237,8 +1239,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!srv.silent) srv.logfunc(&defparam, (unsigned char *)"Exiting thread");
|
if(!srv.silent) srv.logfunc(&defparam, (unsigned char *)"Exiting thread");
|
||||||
/* srvfree() waits for every slot to come back, this one included */
|
|
||||||
if(haveslot) _3proxy_sem_unlock(srv.childslots);
|
|
||||||
srvfree(&srv);
|
srvfree(&srv);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@ -1293,7 +1293,6 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
|||||||
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
|
param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET;
|
||||||
*SAFAMILY(¶m->req) = *SAFAMILY(¶m->sinsl) = *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->sincr) = *SAFAMILY(¶m->sincl) = AF_INET;
|
*SAFAMILY(¶m->req) = *SAFAMILY(¶m->sinsl) = *SAFAMILY(¶m->sinsr) = *SAFAMILY(¶m->sincr) = *SAFAMILY(¶m->sincl) = AF_INET;
|
||||||
_3proxy_mutex_init(&srv->counter_mutex);
|
_3proxy_mutex_init(&srv->counter_mutex);
|
||||||
(void)_3proxy_sem_init_timed(srv->childslots, srv->maxchild, srv->maxchild);
|
|
||||||
#ifndef NOUDPMAIN
|
#ifndef NOUDPMAIN
|
||||||
if(!udpinited){
|
if(!udpinited){
|
||||||
(void)_3proxy_sem_init(udpinit, 1, 1);
|
(void)_3proxy_sem_init(udpinit, 1, 1);
|
||||||
@ -1339,8 +1338,6 @@ void srvinit2(struct srvparam * srv, struct clientparam *param){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void srvfree(struct srvparam * srv){
|
void srvfree(struct srvparam * srv){
|
||||||
int i;
|
|
||||||
|
|
||||||
if(srv->srvsock != INVALID_SOCKET) {
|
if(srv->srvsock != INVALID_SOCKET) {
|
||||||
so._closesocket(srv->so.state, srv->srvsock);
|
so._closesocket(srv->so.state, srv->srvsock);
|
||||||
#ifdef WITH_UN
|
#ifdef WITH_UN
|
||||||
@ -1351,13 +1348,7 @@ void srvfree(struct srvparam * srv){
|
|||||||
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
||||||
srv->cbsock = INVALID_SOCKET;
|
srv->cbsock = INVALID_SOCKET;
|
||||||
srv->service = S_ZOMBIE;
|
srv->service = S_ZOMBIE;
|
||||||
/* Every child returns its slot as the last thing it does with the service,
|
while(srv->child) usleep(SLEEPTIME * 100);
|
||||||
so once all of them are back no child is left. A child posts its slot
|
|
||||||
holding the mutex: taking the mutex once more waits for the last one to
|
|
||||||
have let go of both before they are destroyed. */
|
|
||||||
for(i = srv->maxchild; i; i--) _3proxy_sem_lock(srv->childslots);
|
|
||||||
_3proxy_mutex_lock(&srv->counter_mutex);
|
|
||||||
_3proxy_mutex_unlock(&srv->counter_mutex);
|
|
||||||
#ifndef STDMAIN
|
#ifndef STDMAIN
|
||||||
if(srv->filter){
|
if(srv->filter){
|
||||||
while(srv->nfilters){
|
while(srv->nfilters){
|
||||||
@ -1376,7 +1367,6 @@ void srvfree(struct srvparam * srv){
|
|||||||
if(srv->authfuncs)freeauth(srv->authfuncs);
|
if(srv->authfuncs)freeauth(srv->authfuncs);
|
||||||
#endif
|
#endif
|
||||||
_3proxy_mutex_destroy(&srv->counter_mutex);
|
_3proxy_mutex_destroy(&srv->counter_mutex);
|
||||||
_3proxy_sem_destroy(srv->childslots);
|
|
||||||
if(srv->target) free(srv->target);
|
if(srv->target) free(srv->target);
|
||||||
if(srv->logtarget) free(srv->logtarget);
|
if(srv->logtarget) free(srv->logtarget);
|
||||||
if(srv->logformat) free(srv->logformat);
|
if(srv->logformat) free(srv->logformat);
|
||||||
@ -1403,13 +1393,22 @@ void srvfree(struct srvparam * srv){
|
|||||||
void freeparam(struct clientparam * param) {
|
void freeparam(struct clientparam * param) {
|
||||||
if(param->srv){
|
if(param->srv){
|
||||||
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
if(param->srv->so.freefunc) param->srv->so.freefunc(param->sostate);
|
||||||
#ifndef STDMAIN
|
|
||||||
if(param->srv->service == S_UDPPM){
|
|
||||||
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
||||||
hashdelete(&udp_table, param);
|
#ifndef STDMAIN
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
if(param->srv->service == S_UDPPM) hashdelete(&udp_table, param);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
if(param->prev || param->next || param->srv->child == param){
|
||||||
|
if(param->prev){
|
||||||
|
param->prev->next = param->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
param->srv->child = param->next;
|
||||||
|
if(param->next){
|
||||||
|
param->next->prev = param->prev;
|
||||||
|
}
|
||||||
|
(param->srv->childcount)--;
|
||||||
|
}
|
||||||
|
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||||
}
|
}
|
||||||
if(param->clibuf) free(param->clibuf);
|
if(param->clibuf) free(param->clibuf);
|
||||||
if(param->srvbuf) free(param->srvbuf);
|
if(param->srvbuf) free(param->srvbuf);
|
||||||
@ -1449,27 +1448,6 @@ void freeparam(struct clientparam * param) {
|
|||||||
}
|
}
|
||||||
if(param->connlim) stopconnlims(param);
|
if(param->connlim) stopconnlims(param);
|
||||||
#endif
|
#endif
|
||||||
/* Leaving the service comes last. Once its last child is gone, srvfree()
|
|
||||||
frees the service along with its socket functions, filters and mutex,
|
|
||||||
and a close above may have lingered for seconds before getting here. */
|
|
||||||
if(param->srv){
|
|
||||||
_3proxy_mutex_lock(¶m->srv->counter_mutex);
|
|
||||||
if(param->prev || param->next || param->srv->child == param){
|
|
||||||
if(param->prev){
|
|
||||||
param->prev->next = param->next;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
param->srv->child = param->next;
|
|
||||||
if(param->next){
|
|
||||||
param->next->prev = param->prev;
|
|
||||||
}
|
|
||||||
(param->srv->childcount)--;
|
|
||||||
/* under the mutex too: srvfree() may destroy the semaphore as
|
|
||||||
soon as the mutex shows the last child gone */
|
|
||||||
_3proxy_sem_unlock(param->srv->childslots);
|
|
||||||
}
|
|
||||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
|
||||||
}
|
|
||||||
if(param->hostname) free(param->hostname);
|
if(param->hostname) free(param->hostname);
|
||||||
if(param->username) free(param->username);
|
if(param->username) free(param->username);
|
||||||
if(param->password) free(param->password);
|
if(param->password) free(param->password);
|
||||||
|
|||||||
110
src/sem.c
110
src/sem.c
@ -1,110 +0,0 @@
|
|||||||
/*
|
|
||||||
3APA3A simplest proxy server
|
|
||||||
(c) 2002-2026 by Vladimir Dubrovin <vlad@3proxy.org>
|
|
||||||
|
|
||||||
please read License Agreement
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Counting semaphores for POSIX systems, built on a mutex and a condition
|
|
||||||
variable: unnamed POSIX semaphores are not available everywhere (macOS)
|
|
||||||
and have no timed wait there. Windows uses its own semaphores, see proxy.h. */
|
|
||||||
|
|
||||||
#include "proxy.h"
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
|
||||||
/* macOS has CLOCK_MONOTONIC but no pthread_condattr_setclock(); a relative
|
|
||||||
wait is used there instead, which the system time does not affect either */
|
|
||||||
#if defined(CLOCK_MONOTONIC) && !defined(__APPLE__)
|
|
||||||
#define SEM_MONOTONIC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int _3proxy_sem_init_f(_3proxy_sem_t *sem, unsigned count, unsigned maxcount, int timed){
|
|
||||||
int res;
|
|
||||||
|
|
||||||
sem->count = count;
|
|
||||||
sem->maxcount = maxcount;
|
|
||||||
sem->monotonic = 0;
|
|
||||||
if(pthread_mutex_init(&sem->mutex, NULL)) return 1;
|
|
||||||
#ifdef SEM_MONOTONIC
|
|
||||||
if(timed){
|
|
||||||
pthread_condattr_t attr;
|
|
||||||
|
|
||||||
if(!pthread_condattr_init(&attr)){
|
|
||||||
if(!pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) sem->monotonic = 1;
|
|
||||||
res = pthread_cond_init(&sem->cond, &attr);
|
|
||||||
pthread_condattr_destroy(&attr);
|
|
||||||
}
|
|
||||||
else res = pthread_cond_init(&sem->cond, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
res = pthread_cond_init(&sem->cond, NULL);
|
|
||||||
if(res){
|
|
||||||
pthread_mutex_destroy(&sem->mutex);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3proxy_sem_lock_f(_3proxy_sem_t *sem){
|
|
||||||
pthread_mutex_lock(&sem->mutex);
|
|
||||||
while(!sem->count) pthread_cond_wait(&sem->cond, &sem->mutex);
|
|
||||||
sem->count--;
|
|
||||||
pthread_mutex_unlock(&sem->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns 0 with the semaphore taken, nonzero if ms passed first. */
|
|
||||||
int _3proxy_sem_timedlock_f(_3proxy_sem_t *sem, unsigned ms){
|
|
||||||
struct timespec ts;
|
|
||||||
int res = 0;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
ts.tv_sec = ms / 1000;
|
|
||||||
ts.tv_nsec = (long)(ms % 1000) * 1000000;
|
|
||||||
pthread_mutex_lock(&sem->mutex);
|
|
||||||
while(!sem->count && !res) res = pthread_cond_timedwait_relative_np(&sem->cond, &sem->mutex, &ts);
|
|
||||||
#else
|
|
||||||
/* the deadline is on the clock the condition variable was set up with */
|
|
||||||
#ifdef SEM_MONOTONIC
|
|
||||||
if(sem->monotonic) clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
ts.tv_sec = tv.tv_sec;
|
|
||||||
ts.tv_nsec = tv.tv_usec * 1000;
|
|
||||||
}
|
|
||||||
ts.tv_sec += ms / 1000;
|
|
||||||
ts.tv_nsec += (long)(ms % 1000) * 1000000;
|
|
||||||
if(ts.tv_nsec >= 1000000000){
|
|
||||||
ts.tv_sec++;
|
|
||||||
ts.tv_nsec -= 1000000000;
|
|
||||||
}
|
|
||||||
pthread_mutex_lock(&sem->mutex);
|
|
||||||
while(!sem->count && !res) res = pthread_cond_timedwait(&sem->cond, &sem->mutex, &ts);
|
|
||||||
#endif
|
|
||||||
if(sem->count){
|
|
||||||
sem->count--;
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&sem->mutex);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3proxy_sem_unlock_f(_3proxy_sem_t *sem){
|
|
||||||
pthread_mutex_lock(&sem->mutex);
|
|
||||||
if(sem->count < sem->maxcount){
|
|
||||||
sem->count++;
|
|
||||||
pthread_cond_signal(&sem->cond);
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&sem->mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3proxy_sem_destroy_f(_3proxy_sem_t *sem){
|
|
||||||
pthread_cond_destroy(&sem->cond);
|
|
||||||
pthread_mutex_destroy(&sem->mutex);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@ -185,7 +185,6 @@ void * sockschild(struct clientparam* param) {
|
|||||||
if(command == 2){
|
if(command == 2){
|
||||||
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
if ((param->remsock=param->srv->so._socket(param->sostate, SASOCK(¶m->req), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);}
|
||||||
setopts(param->remsock, param->srv->lissockopts);
|
setopts(param->remsock, param->srv->lissockopts);
|
||||||
if(extbindtodevice(param, param->remsock)) {RETURN (12);}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -245,7 +244,6 @@ fflush(stderr);
|
|||||||
#else
|
#else
|
||||||
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
if(intbindtodevice(param, param->clisock)) {RETURN (12);}
|
|
||||||
sin = param->sincl;
|
sin = param->sincl;
|
||||||
*SAPORT(&sin) = 0;
|
*SAPORT(&sin) = 0;
|
||||||
/* the port the client is told to send its datagrams to */
|
/* the port the client is told to send its datagrams to */
|
||||||
|
|||||||
@ -47,7 +47,6 @@ typedef struct _3proxy_sem_s {
|
|||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
unsigned count;
|
unsigned count;
|
||||||
unsigned maxcount;
|
unsigned maxcount;
|
||||||
int monotonic; /* timed waits measured on CLOCK_MONOTONIC */
|
|
||||||
} _3proxy_sem_t;
|
} _3proxy_sem_t;
|
||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@ -636,7 +635,6 @@ struct srvparam {
|
|||||||
#endif
|
#endif
|
||||||
PROXYSOCKADDRTYPE extsa;
|
PROXYSOCKADDRTYPE extsa;
|
||||||
_3proxy_mutex_t counter_mutex;
|
_3proxy_mutex_t counter_mutex;
|
||||||
_3proxy_sem_t childslots; /* maxchild of them, one held by each child */
|
|
||||||
struct pollfd fds;
|
struct pollfd fds;
|
||||||
FILE *stdlog;
|
FILE *stdlog;
|
||||||
unsigned char * target;
|
unsigned char * target;
|
||||||
|
|||||||
@ -121,11 +121,6 @@ int udpbind(struct clientparam *param)
|
|||||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||||
#endif
|
#endif
|
||||||
param->remsock = s;
|
param->remsock = s;
|
||||||
if (extbindtodevice(param, param->remsock)) {
|
|
||||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
|
||||||
param->remsock = INVALID_SOCKET;
|
|
||||||
return 12;
|
|
||||||
}
|
|
||||||
if (bindwithrange(param, param->remsock, ¶m->sinsl, param->extport)) {
|
if (bindwithrange(param, param->remsock, ¶m->sinsl, param->extport)) {
|
||||||
if (param->extport) {
|
if (param->extport) {
|
||||||
param->srv->so._closesocket(param->sostate, param->remsock);
|
param->srv->so._closesocket(param->sostate, param->remsock);
|
||||||
|
|||||||
@ -69,7 +69,7 @@ means to stand on its own should start with one - otherwise an earlier
|
|||||||
|
|
||||||
## What is not covered yet
|
## What is not covered yet
|
||||||
|
|
||||||
42 of the 112 configuration commands appear in a test, and the count says
|
41 of the 112 configuration commands appear in a test, and the count says
|
||||||
nothing about service options: the IPv6 case, for instance, exercises -4,
|
nothing about service options: the IPv6 case, for instance, exercises -4,
|
||||||
-6, -46, -64 and -i without adding a command to it. What follows is
|
-6, -46, -64 and -i without adding a command to it. What follows is
|
||||||
roughly the order worth working through: how much of the product a gap
|
roughly the order worth working through: how much of the product a gap
|
||||||
@ -78,13 +78,12 @@ covers, and how much of a fixture it needs.
|
|||||||
### Traffic limits and accounting
|
### Traffic limits and accounting
|
||||||
|
|
||||||
`bandlimin` `bandlimout` `nobandlimin` `nobandlimout` `connlim` `noconnlim`
|
`bandlimin` `bandlimout` `nobandlimin` `nobandlimout` `connlim` `noconnlim`
|
||||||
`countin` `countout` `countall` and the `no*` forms.
|
`countin` `countout` `countall` and the `no*` forms, `maxconn`.
|
||||||
|
|
||||||
Cheap and worth doing first: `data?size=` and a stopwatch measure a
|
Cheap and worth doing first: `data?size=` and a stopwatch measure a
|
||||||
bandwidth limit, and the admin counters page already shows what a counter
|
bandwidth limit, and the admin counters page already shows what a counter
|
||||||
holds. `countin` appears in a configuration today but nothing checks that it
|
holds. `countin` appears in a configuration today but nothing checks that it
|
||||||
counts. `connlim` needs concurrent connections, held open the way the
|
counts. `connlim` and `maxconn` need concurrent connections.
|
||||||
`maxconn` case holds them.
|
|
||||||
|
|
||||||
### The mail proxies
|
### The mail proxies
|
||||||
|
|
||||||
|
|||||||
@ -1,107 +0,0 @@
|
|||||||
"""maxconn: a service serves at most that many connections at once, and a
|
|
||||||
connection over the limit waits for one of them to finish."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
import socket
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
def run(t):
|
|
||||||
# The origin runs in a process of its own, so the limit only applies to
|
|
||||||
# the mapper in front of it.
|
|
||||||
origin = t.free_port()
|
|
||||||
t.start("maxconn_origin", f"""
|
|
||||||
auth iponly
|
|
||||||
allow *
|
|
||||||
http echo * /echo**
|
|
||||||
httpsrv -p{origin}
|
|
||||||
""", ports=[origin])
|
|
||||||
|
|
||||||
mapped = t.free_port()
|
|
||||||
server = t.start("maxconn", f"""
|
|
||||||
log
|
|
||||||
maxconn 2
|
|
||||||
auth iponly
|
|
||||||
allow *
|
|
||||||
tcppm {mapped} 127.0.0.1 {origin}
|
|
||||||
""", ports=[mapped])
|
|
||||||
|
|
||||||
def connect():
|
|
||||||
sock = socket.create_connection(("127.0.0.1", mapped), 5)
|
|
||||||
opened.append(sock)
|
|
||||||
return sock
|
|
||||||
|
|
||||||
def served(sock, timeout):
|
|
||||||
"""Ask over a kept alive connection; True once the whole reply is in,
|
|
||||||
so the connection is ready for the next request."""
|
|
||||||
sock.sendall(b"GET /echo HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n")
|
|
||||||
sock.settimeout(timeout)
|
|
||||||
data = b""
|
|
||||||
try:
|
|
||||||
while b"\r\n\r\n" not in data:
|
|
||||||
chunk = sock.recv(4096)
|
|
||||||
if not chunk:
|
|
||||||
return False
|
|
||||||
data += chunk
|
|
||||||
head, body = data.split(b"\r\n\r\n", 1)
|
|
||||||
length = 0
|
|
||||||
for line in head.split(b"\r\n")[1:]:
|
|
||||||
name, _, value = line.partition(b":")
|
|
||||||
if name.strip().lower() == b"content-length":
|
|
||||||
length = int(value)
|
|
||||||
while len(body) < length:
|
|
||||||
chunk = sock.recv(4096)
|
|
||||||
if not chunk:
|
|
||||||
return False
|
|
||||||
body += chunk
|
|
||||||
return head.startswith(b"HTTP/1.1 200")
|
|
||||||
except OSError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
opened = []
|
|
||||||
try:
|
|
||||||
# the probe that saw the port open holds a slot until its session
|
|
||||||
# ends, so wait for both slots to be free before taking them
|
|
||||||
deadline = time.time() + 5
|
|
||||||
while True:
|
|
||||||
first, second = connect(), connect()
|
|
||||||
both = served(first, 1) and served(second, 1)
|
|
||||||
if both or time.time() > deadline:
|
|
||||||
break
|
|
||||||
first.close()
|
|
||||||
second.close()
|
|
||||||
t.eq(True, both, "two connections are served under maxconn 2")
|
|
||||||
|
|
||||||
third = connect()
|
|
||||||
t.eq(False, served(third, 1.5),
|
|
||||||
"a third connection waits while both slots are held")
|
|
||||||
t.contains(t.wait_output(server, "too many connected clients"),
|
|
||||||
"too many connected clients",
|
|
||||||
"a service at its limit says so in the log")
|
|
||||||
|
|
||||||
first.close()
|
|
||||||
t.eq(True, served(third, 5),
|
|
||||||
"the waiting connection is served once a slot is freed")
|
|
||||||
t.eq(True, served(second, 5),
|
|
||||||
"a connection holding a slot keeps being served")
|
|
||||||
|
|
||||||
if os.name == "nt":
|
|
||||||
t.skip("reload while at the limit (no SIGUSR1 on Windows)")
|
|
||||||
else:
|
|
||||||
waiting = connect()
|
|
||||||
t.eq(False, served(waiting, 1),
|
|
||||||
"the limit holds again with two connections open")
|
|
||||||
server.proc.send_signal(signal.SIGUSR1)
|
|
||||||
# A connection made the instant the signal arrives can land on
|
|
||||||
# the listener being replaced and be reset; give the new service
|
|
||||||
# the moment it needs.
|
|
||||||
time.sleep(1.5)
|
|
||||||
fresh = connect()
|
|
||||||
t.eq(True, served(fresh, 5),
|
|
||||||
"a reload while the limit is reached starts a service with "
|
|
||||||
"its slots free")
|
|
||||||
t.eq(None, server.proc.poll(), "the process survives the reload")
|
|
||||||
finally:
|
|
||||||
for sock in opened:
|
|
||||||
sock.close()
|
|
||||||
Loading…
Reference in New Issue
Block a user