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)
|
||||
# ============================================================================
|
||||
|
||||
# Common object library (sockmap, sockgetchar, common, sem, log)
|
||||
# Common object library (sockmap, sockgetchar, common, log)
|
||||
add_library(common_obj OBJECT
|
||||
src/sockmap.c
|
||||
src/sockgetchar.c
|
||||
src/common.c
|
||||
src/sem.c
|
||||
src/log.c
|
||||
)
|
||||
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
|
||||
|
||||
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 . 3proxy
|
||||
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
|
||||
|
||||
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 . 3proxy
|
||||
RUN cd 3proxy && mkdir -p bin &&\
|
||||
|
||||
@ -135,7 +135,7 @@ install: all
|
||||
install -d $(DESTDIR)$(MANDIR)/man8
|
||||
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
||||
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
|
||||
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
||||
install -d $(DESTDIR)$(MANDIR)/man5
|
||||
|
||||
@ -123,18 +123,15 @@ INSTALL_BIN = $(INSTALL) -m 755
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
INSTALL_OBJS = bin/3proxy \
|
||||
bin/$(CRYPT_PREFIX)crypt \
|
||||
bin/$(PREFIX)ftppr \
|
||||
bin/$(PREFIX)imapp \
|
||||
bin/$(PREFIX)pop3p \
|
||||
bin/$(PREFIX)proxy \
|
||||
bin/$(PREFIX)smtpp \
|
||||
bin/$(PREFIX)socks \
|
||||
bin/$(PREFIX)tcppm \
|
||||
bin/$(PREFIX)tlspr \
|
||||
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
|
||||
@ -192,7 +189,7 @@ install-man:
|
||||
$(INSTALL_DATA) man/3proxy.cfg.5 $(MANDIR5)
|
||||
$(INSTALL_DATA) man/3proxy.8 $(MANDIR8)
|
||||
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
|
||||
$(INSTALL_DATA) man/3proxy_crypt.8 $(MANDIR8)/$(CRYPT_PREFIX)crypt.8
|
||||
|
||||
|
||||
@ -130,7 +130,7 @@ install: all
|
||||
install -d $(DESTDIR)$(MANDIR)/man8
|
||||
install -m 644 man/3proxy.8 $(DESTDIR)$(MANDIR)/man8/3proxy.8
|
||||
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
|
||||
install -m 644 man/3proxy_crypt.8 $(DESTDIR)$(MANDIR)/man8/$(CRYPT_PREFIX)crypt.8
|
||||
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
|
||||
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.
|
||||
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.
|
||||
@ -36,7 +36,11 @@ make clean
|
||||
%files
|
||||
/bin/3proxy
|
||||
/bin/3proxy_crypt
|
||||
/bin/3proxy_ftppr
|
||||
/bin/3proxy_imapp
|
||||
/bin/3proxy_pop3p
|
||||
/bin/3proxy_proxy
|
||||
/bin/3proxy_smtpp
|
||||
/bin/3proxy_socks
|
||||
/bin/3proxy_tcppm
|
||||
/bin/3proxy_tlspr
|
||||
|
||||
@ -13,9 +13,6 @@ udpsockmap$(OBJSUFFICS): udpsockmap.c proxy.h structures.h
|
||||
common$(OBJSUFFICS): common.c proxy.h structures.h
|
||||
$(CC) $(CFLAGS) common.c
|
||||
|
||||
sem$(OBJSUFFICS): sem.c proxy.h structures.h
|
||||
$(CC) $(CFLAGS) sem.c
|
||||
|
||||
plugins$(OBJSUFFICS): plugins.c proxy.h structures.h
|
||||
$(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
|
||||
$(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)
|
||||
$(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)
|
||||
$(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) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)pop3p$(EXESUFFICS): sockmap$(OBJSUFFICS) pop3p$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(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)
|
||||
$(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) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)imapp$(EXESUFFICS): sockmap$(OBJSUFFICS) imapp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(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)
|
||||
$(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) base64$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)smtpp$(EXESUFFICS): sockmap$(OBJSUFFICS) smtpp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(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)
|
||||
$(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) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)ftppr$(EXESUFFICS): sockmap$(OBJSUFFICS) ftppr$(OBJSUFFICS) ftp$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(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)
|
||||
$(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) log$(OBJSUFFICS) ftp$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)socks$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) socks$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) sem$(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)
|
||||
$(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) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tcppm$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tcppm$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
||||
$(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) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)udppm$(EXESUFFICS): sockmap$(OBJSUFFICS) udpsockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) udppm$(OBJSUFFICS) common$(OBJSUFFICS) sem$(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)
|
||||
$(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) hash$(OBJSUFFICS) $(LIBS)
|
||||
|
||||
$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS): sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) log$(OBJSUFFICS)
|
||||
$(LN) $(LNOUT)$(BUILDDIR)$(PREFIX)tlspr$(EXESUFFICS) $(LDFLAGS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) tlspr$(OBJSUFFICS) log$(OBJSUFFICS) common$(OBJSUFFICS) sem$(OBJSUFFICS) $(LIBS)
|
||||
$(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) $(LIBS)
|
||||
|
||||
mainfunc$(OBJSUFFICS): proxy.h structures.h 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
|
||||
$(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)
|
||||
$(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)
|
||||
$(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) 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;
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
/* -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){
|
||||
SASIZETYPE size;
|
||||
|
||||
@ -748,7 +732,25 @@ int doconnect(struct clientparam * param){
|
||||
setopts(param->remsock, param->srv->srvsockopts);
|
||||
|
||||
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
|
||||
if(*SAFAMILY(¶m->sinsl) != AF_UNIX)
|
||||
#endif
|
||||
|
||||
@ -129,7 +129,6 @@ void * ftpprchild(struct clientparam* param) {
|
||||
clidatasock = INVALID_SOCKET;
|
||||
}
|
||||
if ((clidatasock=socket(SASOCK(¶m->sincl), SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);}
|
||||
if(intbindtodevice(param, clidatasock)){RETURN(822);}
|
||||
*SAPORT(¶m->sincl) = 0;
|
||||
if(bindwithrange(param, clidatasock, ¶m->sincl, param->intport)){RETURN(822);}
|
||||
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_lock(x) WaitForSingleObject(x, INFINITE)
|
||||
#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
|
||||
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);
|
||||
int _3proxy_sem_timedlock_f(_3proxy_sem_t *sem, unsigned ms);
|
||||
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), 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_init(x, count, maxcount) _3proxy_sem_init_f(&x, (count), (maxcount))
|
||||
#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_destroy(x) _3proxy_sem_destroy_f(&x)
|
||||
#endif
|
||||
|
||||
|
||||
@ -401,9 +391,6 @@ int readconfig(FILE * fp);
|
||||
void initcommands(void);
|
||||
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 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
|
||||
/* One regular expression implementation for the whole program: the pcre
|
||||
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;
|
||||
struct linger lg;
|
||||
int nlog = 5000;
|
||||
int haveslot = 0, nfull = 0;
|
||||
#ifdef __linux__
|
||||
int saved_nsfd = -1;
|
||||
#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));
|
||||
#endif
|
||||
}
|
||||
#if defined SO_BINDTODEVICE || defined IP_BOUND_IF
|
||||
if(bindtodevice(&srv.so, srv.so.state, sock, srv.ibindtodevice, *SAFAMILY(&srv.intsa))) {
|
||||
#if defined SO_BINDTODEVICE
|
||||
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");
|
||||
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
|
||||
}
|
||||
#ifdef WITH_UN
|
||||
@ -991,19 +1008,14 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
|
||||
for (;;) {
|
||||
for(;;){
|
||||
/* A connection is only taken with a slot of maxchild in hand, which
|
||||
goes to its child; a slot not handed on is kept for the next one.
|
||||
The wait is timed to notice a reload. */
|
||||
while(!haveslot && conf.paused == srv.paused){
|
||||
if(!_3proxy_sem_timedlock(srv.childslots, 1000)){
|
||||
haveslot = 1;
|
||||
nfull = 0;
|
||||
break;
|
||||
}
|
||||
if(!srv.silent && !(nfull++ % 5)) {
|
||||
while((conf.paused == srv.paused && srv.childcount >= srv.maxchild)){
|
||||
nlog++;
|
||||
if(!srv.silent && nlog > 5000) {
|
||||
sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", srv.childcount, srv.maxchild);
|
||||
dolog(&defparam, buf);
|
||||
nlog = 0;
|
||||
}
|
||||
usleep(SLEEPTIME);
|
||||
}
|
||||
if (iscbc) break;
|
||||
if (conf.paused != srv.paused) break;
|
||||
@ -1026,15 +1038,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
setopts(new_sock, srv.cbcsockopts);
|
||||
|
||||
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)) {
|
||||
so._closesocket(so.state, new_sock);
|
||||
new_sock = INVALID_SOCKET;
|
||||
@ -1219,7 +1222,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
}
|
||||
else {
|
||||
srv.childcount++;
|
||||
haveslot = 0;
|
||||
newparam->threadid = (uint64_t)thread;
|
||||
}
|
||||
_3proxy_mutex_unlock(&srv.counter_mutex);
|
||||
@ -1237,8 +1239,6 @@ int MODULEMAINFUNC (int argc, char** argv){
|
||||
#endif
|
||||
|
||||
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);
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -1293,7 +1293,6 @@ void srvinit(struct srvparam * srv, struct clientparam *param){
|
||||
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;
|
||||
_3proxy_mutex_init(&srv->counter_mutex);
|
||||
(void)_3proxy_sem_init_timed(srv->childslots, srv->maxchild, srv->maxchild);
|
||||
#ifndef NOUDPMAIN
|
||||
if(!udpinited){
|
||||
(void)_3proxy_sem_init(udpinit, 1, 1);
|
||||
@ -1339,8 +1338,6 @@ void srvinit2(struct srvparam * srv, struct clientparam *param){
|
||||
}
|
||||
|
||||
void srvfree(struct srvparam * srv){
|
||||
int i;
|
||||
|
||||
if(srv->srvsock != INVALID_SOCKET) {
|
||||
so._closesocket(srv->so.state, srv->srvsock);
|
||||
#ifdef WITH_UN
|
||||
@ -1351,13 +1348,7 @@ void srvfree(struct srvparam * srv){
|
||||
if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->so.state, srv->cbsock);
|
||||
srv->cbsock = INVALID_SOCKET;
|
||||
srv->service = S_ZOMBIE;
|
||||
/* Every child returns its slot as the last thing it does with the service,
|
||||
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);
|
||||
while(srv->child) usleep(SLEEPTIME * 100);
|
||||
#ifndef STDMAIN
|
||||
if(srv->filter){
|
||||
while(srv->nfilters){
|
||||
@ -1376,7 +1367,6 @@ void srvfree(struct srvparam * srv){
|
||||
if(srv->authfuncs)freeauth(srv->authfuncs);
|
||||
#endif
|
||||
_3proxy_mutex_destroy(&srv->counter_mutex);
|
||||
_3proxy_sem_destroy(srv->childslots);
|
||||
if(srv->target) free(srv->target);
|
||||
if(srv->logtarget) free(srv->logtarget);
|
||||
if(srv->logformat) free(srv->logformat);
|
||||
@ -1403,13 +1393,22 @@ void srvfree(struct srvparam * srv){
|
||||
void freeparam(struct clientparam * param) {
|
||||
if(param->srv){
|
||||
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);
|
||||
hashdelete(&udp_table, param);
|
||||
_3proxy_mutex_unlock(¶m->srv->counter_mutex);
|
||||
}
|
||||
#ifndef STDMAIN
|
||||
if(param->srv->service == S_UDPPM) hashdelete(&udp_table, param);
|
||||
#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->srvbuf) free(param->srvbuf);
|
||||
@ -1449,27 +1448,6 @@ void freeparam(struct clientparam * param) {
|
||||
}
|
||||
if(param->connlim) stopconnlims(param);
|
||||
#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->username) free(param->username);
|
||||
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 ((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);
|
||||
if(extbindtodevice(param, param->remsock)) {RETURN (12);}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -245,7 +244,6 @@ fflush(stderr);
|
||||
#else
|
||||
fcntl(param->clisock, F_SETFL, O_NONBLOCK | fcntl(param->clisock, F_GETFL));
|
||||
#endif
|
||||
if(intbindtodevice(param, param->clisock)) {RETURN (12);}
|
||||
sin = param->sincl;
|
||||
*SAPORT(&sin) = 0;
|
||||
/* the port the client is told to send its datagrams to */
|
||||
|
||||
@ -47,7 +47,6 @@ typedef struct _3proxy_sem_s {
|
||||
pthread_cond_t cond;
|
||||
unsigned count;
|
||||
unsigned maxcount;
|
||||
int monotonic; /* timed waits measured on CLOCK_MONOTONIC */
|
||||
} _3proxy_sem_t;
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
@ -636,7 +635,6 @@ struct srvparam {
|
||||
#endif
|
||||
PROXYSOCKADDRTYPE extsa;
|
||||
_3proxy_mutex_t counter_mutex;
|
||||
_3proxy_sem_t childslots; /* maxchild of them, one held by each child */
|
||||
struct pollfd fds;
|
||||
FILE *stdlog;
|
||||
unsigned char * target;
|
||||
|
||||
@ -121,11 +121,6 @@ int udpbind(struct clientparam *param)
|
||||
fcntl(s, F_SETFL, O_NONBLOCK | fcntl(s, F_GETFL));
|
||||
#endif
|
||||
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 (param->extport) {
|
||||
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
|
||||
|
||||
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,
|
||||
-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
|
||||
@ -78,13 +78,12 @@ covers, and how much of a fixture it needs.
|
||||
### Traffic limits and accounting
|
||||
|
||||
`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
|
||||
bandwidth limit, and the admin counters page already shows what a counter
|
||||
holds. `countin` appears in a configuration today but nothing checks that it
|
||||
counts. `connlim` needs concurrent connections, held open the way the
|
||||
`maxconn` case holds them.
|
||||
counts. `connlim` and `maxconn` need concurrent connections.
|
||||
|
||||
### 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