[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Mldonkey-commits] mldonkey config/Makefile.config.in config/Makef...
From: |
mldonkey-commits |
Subject: |
[Mldonkey-commits] mldonkey config/Makefile.config.in config/Makef... |
Date: |
Mon, 01 Nov 2010 17:19:23 +0000 |
CVSROOT: /sources/mldonkey
Module name: mldonkey
Changes by: spiralvoice <spiralvoice> 10/11/01 17:19:23
Modified files:
config : Makefile.config.in Makefile.in config.h.in
configure.in
distrib : ChangeLog
src/daemon/common: commonGlobals.ml commonInteractive.ml
commonOptions.ml
src/daemon/driver: driverCommands.ml driverInteractive.ml
driverMain.ml
src/utils/lib : autoconf.ml.new.in
Added files:
src/utils/net : upnpClient.ml upnpClient.mli upnp_stubs.c
Log message:
patch #7303
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/mldonkey/config/Makefile.config.in?cvsroot=mldonkey&r1=1.65&r2=1.66
http://cvs.savannah.gnu.org/viewcvs/mldonkey/config/Makefile.in?cvsroot=mldonkey&r1=1.195&r2=1.196
http://cvs.savannah.gnu.org/viewcvs/mldonkey/config/config.h.in?cvsroot=mldonkey&r1=1.28&r2=1.29
http://cvs.savannah.gnu.org/viewcvs/mldonkey/config/configure.in?cvsroot=mldonkey&r1=1.340&r2=1.341
http://cvs.savannah.gnu.org/viewcvs/mldonkey/distrib/ChangeLog?cvsroot=mldonkey&r1=1.1496&r2=1.1497
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonGlobals.ml?cvsroot=mldonkey&r1=1.92&r2=1.93
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonInteractive.ml?cvsroot=mldonkey&r1=1.108&r2=1.109
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/common/commonOptions.ml?cvsroot=mldonkey&r1=1.235&r2=1.236
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/driver/driverCommands.ml?cvsroot=mldonkey&r1=1.258&r2=1.259
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/driver/driverInteractive.ml?cvsroot=mldonkey&r1=1.142&r2=1.143
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/daemon/driver/driverMain.ml?cvsroot=mldonkey&r1=1.145&r2=1.146
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/lib/autoconf.ml.new.in?cvsroot=mldonkey&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/upnpClient.ml?cvsroot=mldonkey&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/upnpClient.mli?cvsroot=mldonkey&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/mldonkey/src/utils/net/upnp_stubs.c?cvsroot=mldonkey&rev=1.1
Patches:
Index: config/Makefile.config.in
===================================================================
RCS file: /sources/mldonkey/mldonkey/config/Makefile.config.in,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -b -r1.65 -r1.66
--- config/Makefile.config.in 29 Aug 2010 20:11:20 -0000 1.65
+++ config/Makefile.config.in 1 Nov 2010 17:19:23 -0000 1.66
@@ -66,6 +66,10 @@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
address@hidden@
+
address@hidden@
address@hidden@
Index: config/Makefile.in
===================================================================
RCS file: /sources/mldonkey/mldonkey/config/Makefile.in,v
retrieving revision 1.195
retrieving revision 1.196
diff -u -b -r1.195 -r1.196
--- config/Makefile.in 1 Nov 2010 17:06:15 -0000 1.195
+++ config/Makefile.in 1 Nov 2010 17:19:23 -0000 1.196
@@ -245,6 +245,8 @@
$(COMMON)/commonHasher_c.c
COMMON_CLIENT_SRCS= \
+ $(NET)/upnpClient.ml \
+ $(NET)/upnp_stubs.c \
$(COMMON)/commonUser.ml \
$(COMMON)/commonNetwork.ml \
$(COMMON)/commonServer.ml \
@@ -555,6 +557,11 @@
$(DRIVER)/driverGraphics_nogd.ml
endif
+ifeq ("$(UPNP_NATPMP)", "yes")
+ UPNP_NATPMP_LIBS_flags=-cclib "$(UPNP_NATPMP_LIBS)" -ccopt
"$(UPNP_NATPMP_LDFLAGS)"
+ UPNP_NATPMP_STATIC_LIBS_flags=-cclib "$(UPNP_NATPMP_STATIC_LIBS)" -ccopt
"$(UPNP_NATPMP_LDFLAGS)"
+endif
+
DRIVER_SRCS+= \
$(DRIVER)/driverGraphics.ml \
$(DRIVER)/driverInteractive.ml \
@@ -1222,6 +1229,7 @@
EXPAND_LIB(libcdk,cdk)
EXPAND_LIB(libmagic,magic)
EXPAND_LIB(libbitstring,bitstring)
+EXPAND_LIB(libupnp_natpmp,upnp_natpmp)
EXPAND_LIB(libcommon,common)
EXPAND_LIB(libclient,client)
EXPAND_LIB(DRIVER,driver)
@@ -1268,6 +1276,7 @@
$($6_LIBS_opt) $($6_LIBS_flags) \
$($7_LIBS_opt) $($7_LIBS_flags) \
$($8_LIBS_opt) $($8_LIBS_flags) \
+ $($9_LIBS_opt) $($9_LIBS_flags) \
-I build $($1_CMXAS) $($1_CMXS)
$2.byte: $($1_OBJS) $($1_CMOS) $($1_CMAS)
@@ -1278,6 +1287,7 @@
$($6_LIBS_byte) $($6_LIBS_flags) \
$($7_LIBS_byte) $($7_LIBS_flags) \
$($8_LIBS_byte) $($8_LIBS_flags) \
+ $($9_LIBS_byte) $($9_LIBS_flags) \
-I build $($1_CMAS) $($1_CMOS)
$2.static: $($1_OBJS) $($1_CMXS) $($1_CMXAS)
@@ -1288,6 +1298,7 @@
$($6_LIBS_flags) $($6_STATIC_LIBS_opt) \
$($7_LIBS_flags) $($7_STATIC_LIBS_opt) \
$($8_LIBS_flags) $($8_STATIC_LIBS_opt) \
+ $($9_LIBS_flags) $($9_STATIC_LIBS_opt) \
-I build $($1_CMXAS) $($1_CMXS)
$2.byte.static: $($1_OBJS) $($1_CMOS) $($1_CMAS)
@@ -1298,6 +1309,7 @@
$($6_LIBS_flags) $($6_STATIC_LIBS_opt) \
$($7_LIBS_flags) $($7_STATIC_LIBS_opt) \
$($8_LIBS_flags) $($8_STATIC_LIBS_opt) \
+ $($9_LIBS_flags) $($9_STATIC_LIBS_opt) \
-I build $($1_CMAS) $($1_CMOS)
]])
@@ -1309,9 +1321,10 @@
# $6 = if set link CryptoPP code (only for targets mlnet, mldonkey)
# $7 = if set link libmagic code (only for p2p core, not for GUIs, tools etc.)
# $8 = if set link libbitstring code (only for Bittorrent p2p core)
+# $9 = if set link libminiupnpc & libnatpmp code
-EXPAND(mldonkey,mldonkey,NO,mldonkey,GD,CRYPTOPP,MAGIC,BITSTRING)
-EXPAND(mldonkey+gui,mldonkey+gui,GTK,mldonkey+gui,GD,CRYPTOPP,MAGIC,BITSTRING)
+EXPAND(mldonkey,mldonkey,NO,mldonkey,GD,CRYPTOPP,MAGIC,BITSTRING,UPNP_NATPMP)
+EXPAND(mldonkey+gui,mldonkey+gui,GTK,mldonkey+gui,GD,CRYPTOPP,MAGIC,BITSTRING,UPNP_NATPMP)
EXPAND(MLPROGRESS, mlprogress,GTK, MLPROGRESS)
EXPAND(MLDONKEYGUI,mlgui,GTK,MLDONKEYGUI)
@@ -1319,29 +1332,29 @@
EXPAND(MLDONKEYGUI2,mlgui2,GTK,MLDONKEYGUI2)
endif
-EXPAND(mldc,mldc,NO,mldc,GD,NO,MAGIC)
-EXPAND(mldc+gui,mldc+gui,GTK,mldc+gui,GD,NO,MAGIC)
-EXPAND(mlnap,mlnap,NO,mlnap,GD,NO,MAGIC)
-EXPAND(mlnap+gui,mlnap+gui,GTK,mlnap+gui,GD,NO,MAGIC)
-EXPAND(MLNET,mlnet,NO,MLNET,GD,CRYPTOPP,MAGIC,BITSTRING)
-EXPAND(mlnet+gui,mlnet+gui,GTK,mlnet+gui,GD,CRYPTOPP,MAGIC,BITSTRING)
-EXPAND(mlgnut,mlgnut,NO,mlgnut,GD,NO,MAGIC)
-EXPAND(mlgnut+gui,mlgnut+gui,GTK,mlgnut+gui,GD,NO,MAGIC)
-EXPAND(mlg2,mlg2,NO,mlg2,GD,NO,MAGIC)
-EXPAND(mlg2+gui,mlg2+gui,GTK,mlg2+gui,GD,NO,MAGIC)
-EXPAND(mlbt,mlbt,NO,mlbt,GD,NO,MAGIC,BITSTRING)
-EXPAND(mlbt+gui,mlbt+gui,GTK,mlbt+gui,GD,NO,MAGIC,BITSTRING)
-EXPAND(mlfasttrack,mlfasttrack,NO,mlfasttrack,GD,NO,MAGIC)
-EXPAND(mlfasttrack+gui,mlfasttrack+gui,GTK,mlfasttrack+gui,GD,NO,MAGIC)
-EXPAND(mlfileTP,mlfiletp,NO,mlfileTP,GD,NO,MAGIC)
-EXPAND(mlfileTP+gui,mlfiletp+gui,GTK,mlfileTP+gui,GD,NO,MAGIC)
-EXPAND(mlslsk,mlslsk,NO,mlslsk,GD,NO,MAGIC)
-EXPAND(mlslsk+gui,mlslsk+gui,GTK,mlslsk+gui,GD,NO,MAGIC)
+EXPAND(mldc,mldc,NO,mldc,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mldc+gui,mldc+gui,GTK,mldc+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlnap,mlnap,NO,mlnap,GD,NO,MAGIC,UPNP_NATPMP)
+EXPAND(mlnap+gui,mlnap+gui,GTK,mlnap+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(MLNET,mlnet,NO,MLNET,GD,CRYPTOPP,MAGIC,BITSTRING,UPNP_NATPMP)
+EXPAND(mlnet+gui,mlnet+gui,GTK,mlnet+gui,GD,CRYPTOPP,MAGIC,BITSTRING,UPNP_NATPMP)
+EXPAND(mlgnut,mlgnut,NO,mlgnut,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlgnut+gui,mlgnut+gui,GTK,mlgnut+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlg2,mlg2,NO,mlg2,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlg2+gui,mlg2+gui,GTK,mlg2+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlbt,mlbt,NO,mlbt,GD,NO,MAGIC,BITSTRING,UPNP_NATPMP)
+EXPAND(mlbt+gui,mlbt+gui,GTK,mlbt+gui,GD,NO,MAGIC,BITSTRING,UPNP_NATPMP)
+EXPAND(mlfasttrack,mlfasttrack,NO,mlfasttrack,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlfasttrack+gui,mlfasttrack+gui,GTK,mlfasttrack+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlfileTP,mlfiletp,NO,mlfileTP,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlfileTP+gui,mlfiletp+gui,GTK,mlfileTP+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlslsk,mlslsk,NO,mlslsk,GD,NO,MAGIC,NO,UPNP_NATPMP)
+EXPAND(mlslsk+gui,mlslsk+gui,GTK,mlslsk+gui,GD,NO,MAGIC,NO,UPNP_NATPMP)
EXPAND(STARTER,mlguistarter,GTK)
EXPAND(OBSERVER,observer)
EXPAND(MLD_HASH,mld_hash)
EXPAND(OCAMLPP,ocamlpp)
-EXPAND(MAKE_TORRENT,make_torrent,NO,NO,NO,NO,MAGIC,BITSTRING)
+EXPAND(MAKE_TORRENT,make_torrent,NO,NO,NO,NO,MAGIC,BITSTRING,UPNP_NATPMP)
EXPAND(SUBCONV,subconv)
EXPAND(MLSPLIT,mlsplit)
EXPAND(CONTESTER,contester,CRYPT)
Index: config/config.h.in
===================================================================
RCS file: /sources/mldonkey/mldonkey/config/config.h.in,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -b -r1.28 -r1.29
--- config/config.h.in 17 Oct 2007 18:27:25 -0000 1.28
+++ config/config.h.in 1 Nov 2010 17:19:23 -0000 1.29
@@ -147,3 +147,6 @@
/* Define to 1 if you have strerror_r() */
#undef HAVE_STRERROR_R
+
+/* Define to 1 if you want to use libminiupnpc + libnatpmp */
+#undef ENABLE_UPNP_NATPMP
Index: config/configure.in
===================================================================
RCS file: /sources/mldonkey/mldonkey/config/configure.in,v
retrieving revision 1.340
retrieving revision 1.341
diff -u -b -r1.340 -r1.341
--- config/configure.in 26 Sep 2010 14:20:30 -0000 1.340
+++ config/configure.in 1 Nov 2010 17:19:23 -0000 1.341
@@ -326,6 +326,8 @@
MAGIC=yes
ICONV=yes
USE_PTHREAD=yes
+UPNP_NATPMP=no
+UPNP_NATPMP_FORCE=no
# **********
@@ -411,6 +413,8 @@
AC_ARG_ENABLE(gd, [ --disable-gd disable the use of
gd], [GD="$enableval"])
AC_ARG_ENABLE(bzip2, [ --disable-bzip2 disable the use of
bzip2], [BZIP2="$enableval"])
AC_ARG_ENABLE(magic, [ --disable-magic disable the use of
libmagic (GNU file)], [MAGIC="$enableval"])
+AC_ARG_ENABLE(upnp-natpmp, [ --enable-upnp-natpmp enable the use of
libminiupnpc and libnatpmp], [UPNP_NATPMP="$enableval"])
+AC_ARG_ENABLE(force-upnp-natpmp, [ --enable-force-upnp-natpmp force
local compilation of libminiupnpc and libnatpmp],
[UPNP_NATPMP_FORCE="$enableval"])
if test "$FORCE_MINGW" = "yes"; then
CC="$CC -mno-cygwin"
@@ -783,6 +787,42 @@
AC_MSG_NOTICE(bzlib not available)
fi
+if test "$UPNP_NATPMP_FORCE" = "yes"; then
+ UPNP_NATPMP=yes
+ cd $PATCH_DIR
+ $WGET http://miniupnp.tuxfamily.org/files/miniupnpc-1.4.20100609.tar.gz
+ $WGET http://miniupnp.tuxfamily.org/files/libnatpmp-20100202.tar.gz
+ mkdir -p $BUILD_DIR $LOCAL_DIR/usr/bin $LOCAL_DIR/usr/lib
$LOCAL_DIR/usr/include/miniupnpc
+ cd $BUILD_DIR
+ rm -rf libnatpmp-20100202 miniupnpc-1.4.20100609
+ tar -xzf $PATCH_DIR/miniupnpc-1.4.20100609.tar.gz
+ tar -xzf $PATCH_DIR/libnatpmp-20100202.tar.gz
+ cd $BUILD_DIR/libnatpmp-20100202
+ make all install PREFIX=$LOCAL_DIR
+ cd $BUILD_DIR/miniupnpc-1.4.20100609
+ make all install PREFIX=$LOCAL_DIR
+ cd $CONFIG_DIR
+ rm -rf $BUILD_DIR/libnatpmp-20100202 $BUILD_DIR/miniupnpc-1.4.20100609
+ CPPFLAGS="${CPPFLAGS} -I$LOCAL_DIR/usr/include"
+ LDFLAGS="${LDFLAGS} -L$LOCAL_DIR/usr/lib"
+fi
+
+if test "$UPNP_NATPMP" = "yes"; then
+ echo "----- checking libminiupnpc >= 1.4.20100609 (optional)"
+
AC_CHECK_HEADERS(miniupnpc/miniupnpc.h,[AC_CHECK_LIB(miniupnpc,upnpDiscover,[UPNP_NATPMP=yes],[UPNP_NATPMP=no])],[UPNP_NATPMP=no])
+fi
+
+if test "$UPNP_NATPMP" = "yes"; then
+ echo "----- checking libnatpmp >= 20100202 (optional)"
+
AC_CHECK_HEADERS(natpmp.h,[AC_CHECK_LIB(natpmp,initnatpmp,[UPNP_NATPMP=yes],[UPNP_NATPMP=no])],[UPNP_NATPMP=no])
+fi
+
+if test "$UPNP_NATPMP" = "yes"; then
+ AC_DEFINE(ENABLE_UPNP_NATPMP, 1, [Define to 1 if you have libminiupnpc &
libnatpmp for port forwarding support.])
+ UPNP_NATPMP_LIBS="-lminiupnpc -lnatpmp $LIBS"
+ UPNP_NATPMP_STATIC_LIBS="-lminiupnpc -lnatpmp $LIBS"
+fi
+
if test "$MAGIC" != "no"; then
echo "----- checking libmagic (GNU file) (optional)"
AC_CHECK_HEADERS(magic.h,
@@ -1443,6 +1483,9 @@
AC_SUBST(BZIP2)
AC_SUBST(MAGIC)
AC_SUBST(MAGICLIB)
+AC_SUBST(UPNP_NATPMP)
+AC_SUBST(UPNP_NATPMP_LIBS)
+AC_SUBST(UPNP_NATPMP_STATIC_LIBS)
BUILD_SYSTEM="`uname -s` `uname -m` `uname -r`"
AC_SUBST(BUILD_SYSTEM)
AC_SUBST(GLIBC_VERSION)
@@ -1585,6 +1628,13 @@
echo " disabled"
fi
+echo -n " - upnp & natpmp "
+if test "$UPNP_NATPMP" = "yes"; then
+ echo "enabled"
+else
+ echo " disabled"
+fi
+
echo -n " - graphical stats "
if test "$GD" = "yes"; then
echo "enabled"
Index: distrib/ChangeLog
===================================================================
RCS file: /sources/mldonkey/mldonkey/distrib/ChangeLog,v
retrieving revision 1.1496
retrieving revision 1.1497
diff -u -b -r1.1496 -r1.1497
--- distrib/ChangeLog 1 Nov 2010 17:09:28 -0000 1.1496
+++ distrib/ChangeLog 1 Nov 2010 17:19:23 -0000 1.1497
@@ -15,6 +15,10 @@
=========
2010/11/01
+7303: UPNP support (zzpptt)
+- to compile using pre-installed libs: configure --enable-upnp-natpmp
+- to compile UPNP libs during MLDonkey compile use --enable-force-upnp-natpmp
+- ToDo: MinGW support
7365: HTML: improve code for sorting tables (ygrek)
7364: KAD: parse new nodes.dat formats (ygrek)
Index: src/daemon/common/commonGlobals.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonGlobals.ml,v
retrieving revision 1.92
retrieving revision 1.93
diff -u -b -r1.92 -r1.93
--- src/daemon/common/commonGlobals.ml 23 Oct 2010 18:25:13 -0000 1.92
+++ src/daemon/common/commonGlobals.ml 1 Nov 2010 17:19:23 -0000 1.93
@@ -108,6 +108,8 @@
in an option, and then change the option accordingly. ?> *)
let find_other_port = ref false
+let upnp_port_forwarding () = !!upnp_port_forwarding && Autoconf.upnp_natpmp
+
let shorten str limit =
(* TODO: we should change all strings to utf8 when
they come into the core instead. *)
Index: src/daemon/common/commonInteractive.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonInteractive.ml,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -b -r1.108 -r1.109
--- src/daemon/common/commonInteractive.ml 7 Aug 2010 14:51:15 -0000
1.108
+++ src/daemon/common/commonInteractive.ml 1 Nov 2010 17:19:23 -0000
1.109
@@ -503,6 +503,7 @@
lprintf_nl "Exception in contact_remove: %s" (Printexc2.to_string e)
let clean_exit n =
+ begin
let can_exit = networks_for_all network_clean_exit in
if can_exit then exit_properly n
else
@@ -512,7 +513,15 @@
if can_exit || retry_counter > !!shutdown_timeout then
exit_properly n
else retry_later (retry_counter + 1)) in
- retry_later 0
+ retry_later 0;
+
+ if (upnp_port_forwarding ()) then
+ begin
+ if !!clear_upnp_port_at_exit then
+ UpnpClient.remove_all_maps 0 ;
+ UpnpClient.job_stop 3;
+ end;
+ end
let time_of_sec sec =
let hours = sec / 60 / 60 in
Index: src/daemon/common/commonOptions.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/common/commonOptions.ml,v
retrieving revision 1.235
retrieving revision 1.236
diff -u -b -r1.235 -r1.236
--- src/daemon/common/commonOptions.ml 23 Oct 2010 18:25:13 -0000 1.235
+++ src/daemon/common/commonOptions.ml 1 Nov 2010 17:19:23 -0000 1.236
@@ -539,6 +539,15 @@
"exit", "q";
]
+let upnp_port_forwarding = define_option current_section
["upnp_port_forwarding"]
+ ~restart: true
+ "upnp port forwarding"
+ bool_option false
+
+let clear_upnp_port_at_exit = define_option current_section
["clear_upnp_port_at_exit"]
+ "clear all upnp port forwarding before mldonkey exit"
+ bool_option true
+
let verbosity = define_expert_option current_section ["verbosity"]
"A space-separated list of keywords. Each keyword triggers
printing information on the corresponding messages:
Index: src/daemon/driver/driverCommands.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverCommands.ml,v
retrieving revision 1.258
retrieving revision 1.259
diff -u -b -r1.258 -r1.259
--- src/daemon/driver/driverCommands.ml 1 Nov 2010 17:09:28 -0000 1.258
+++ src/daemon/driver/driverCommands.ml 1 Nov 2010 17:19:23 -0000 1.259
@@ -43,6 +43,7 @@
open CommonUserDb
open CommonInteractive
open CommonEvent
+open UpnpClient
open DriverInteractive
@@ -2147,6 +2148,12 @@
] @
(if Autoconf.filetp = "yes" then [(strings_of_option
enable_fileTP)] else [])
@ [
+ ] @
+ (if Autoconf.upnp_natpmp then [(strings_of_option
upnp_port_forwarding)] else [])
+ @ [
+ ] @
+ (if Autoconf.upnp_natpmp then [(strings_of_option
clear_upnp_port_at_exit)] else [])
+ @ [
strings_of_option tcpip_packet_size;
strings_of_option mtu_packet_size;
strings_of_option minimal_packet_size;
@@ -4195,4 +4202,43 @@
CommonPictures.compute_ocaml_code dir output;
_s "done"
), ":\t\t\tfor debugging only";
+
+ "debug_upnp", Arg_multiple ( fun args o ->
+ match args with
+ | ["init"] ->
+ UpnpClient.init_maps ();
+
+ | ["add"; intPort; extPort; isTcp; notes ] ->
+ UpnpClient.maps_add_item 1 (int_of_string
intPort) (int_of_string extPort) (int_of_string isTcp) notes;
+
+ | ["start"] ->
+ UpnpClient.job_start ();
+
+ | ["remove"; intPort; extPort; isTcp; notes] ->
+ UpnpClient.maps_remove_item 1 (int_of_string
intPort) (int_of_string extPort) (int_of_string isTcp) notes;
+
+ | ["clear"] ->
+ UpnpClient.remove_all_maps 0 ;
+
+ | ["stop"] ->
+ UpnpClient.job_stop 0;
+
+ | ["show"] | [] ->
+ let buf = o.conn_buf in
+ let maps = UpnpClient.maps_get () in
+ Printf.bprintf buf "upnp port
forwarding status:\n";
+ List.iter (fun map ->
+ let msg =
UpnpClient.strings_port_map map in
+ Printf.bprintf buf "%s\n" msg;
+ ) maps;
+
+ | _ -> ();
+ ;
+ _s "done"
+ ), ":\t\t\t\t\t$debugging upnp\n"
+ ^"\t\t\t\t\tfor example: \"add 4662 4662 1 ed_port\" add port
forwarding intPort extPort isTcp notes\n"
+ ^"\t\t\t\t\t\"remove 4662 4662 1 ed_port\" remove port forwarding
intPort extPort isTcp notes\n"
+ ^"\t\t\t\t\t\"clear\" clear all port forwarding\n"
+ ^"\t\t\t\t\t\"show\" show all port forwarding info $n";
+
]
Index: src/daemon/driver/driverInteractive.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverInteractive.ml,v
retrieving revision 1.142
retrieving revision 1.143
diff -u -b -r1.142 -r1.143
--- src/daemon/driver/driverInteractive.ml 1 Nov 2010 17:09:28 -0000
1.142
+++ src/daemon/driver/driverInteractive.ml 1 Nov 2010 17:19:23 -0000
1.143
@@ -1940,6 +1940,7 @@
| true, true -> " magic(active)"
| true, false -> " magic(inactive)"
| false, _ -> " no-magic") ^
+ (if Autoconf.upnp_natpmp then " upnp natpmp" else " no-upnp no-natpmp") ^
(if Autoconf.check_bounds then " check-bounds" else " no-check-bounds")
);
let list = List.rev !list in
Index: src/daemon/driver/driverMain.ml
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/daemon/driver/driverMain.ml,v
retrieving revision 1.145
retrieving revision 1.146
diff -u -b -r1.145 -r1.146
--- src/daemon/driver/driverMain.ml 23 May 2010 09:12:14 -0000 1.145
+++ src/daemon/driver/driverMain.ml 1 Nov 2010 17:19:23 -0000 1.146
@@ -458,10 +458,31 @@
lprintf_nl (_b "Check http://www.mldonkey.org for updates");
networks_iter (fun r -> network_load_complex_options r);
lprintf_nl (_b "enabling networks: ");
+ if (upnp_port_forwarding ()) then
+ UpnpClient.init_maps ();
+ let add_upnp_port p s=
+ lprintf_nl "using port %d (%s)" p s;
+ if ((upnp_port_forwarding ())) then
+ match String2.split_simplify s ' ' with
+ | [ "client_port" ; tcpudp ]
+ | [ "overnet_port" ; tcpudp ]
+ | [ "kademlia_port" ; tcpudp ] ->
+ if (String2.contains tcpudp "TCP") then
+ begin
+ UpnpClient.maps_add_item 1 p p 1 "" ;
+ lprintf_nl "add upnp port forwarding %d TCP" p;
+ end;
+ if (String2.contains tcpudp "UDP") then
+ begin
+ UpnpClient.maps_add_item 1 p p 0 "" ;
+ lprintf_nl "add upnp port forwarding %d UDP" p;
+ end
+ | _ -> ()
+ in
networks_iter (fun r ->
lprintf_nl (_b "---- enabling %s ----") r.network_name;
network_enable r;
- List.iter (fun (p,s) -> if p <> 0 then lprintf_nl "using port %d (%s)" p
s) (network_ports r);
+ List.iter (fun (p,s) -> if p <> 0 then add_upnp_port p s) (network_ports
r);
(* are there drawbacks to start recover_temp unconditionally here ? *)
if !!recover_temp_on_startup then
network_recover_temp r;
@@ -479,6 +500,8 @@
end);
if not !found then lprintf (_b "none");
lprint_newline ();
+ if (upnp_port_forwarding ()) then
+ UpnpClient.job_start ();
networks_iter_all (fun n -> network_update_options n);
CommonOptions.start_running_plugins := true;
CommonInteractive.force_download_quotas ();
Index: src/utils/lib/autoconf.ml.new.in
===================================================================
RCS file: /sources/mldonkey/mldonkey/src/utils/lib/autoconf.ml.new.in,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- src/utils/lib/autoconf.ml.new.in 17 Jun 2007 02:08:16 -0000 1.27
+++ src/utils/lib/autoconf.ml.new.in 1 Nov 2010 17:19:23 -0000 1.28
@@ -48,3 +48,4 @@
let bzip2 = "@BZIP2@" = "yes"
let magic = "@MAGIC@" = "yes"
let magic_works = ref false
+let upnp_natpmp = "@UPNP_NATPMP@" = "yes"
Index: src/utils/net/upnpClient.ml
===================================================================
RCS file: src/utils/net/upnpClient.ml
diff -N src/utils/net/upnpClient.ml
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/utils/net/upnpClient.ml 1 Nov 2010 17:19:23 -0000 1.1
@@ -0,0 +1,67 @@
+(**************************************************************************)
+(* Copyright (c) 2010 zzz <address@hidden> *)
+(* *)
+(* mlupnp, a ocaml wraps of libminiupnpc & libnatpmp for mldonkey *)
+(* *)
+(* Permission is hereby granted, free of charge, to any person *)
+(* obtaining a copy of this software and associated documentation files *)
+(* (the "Software"), to deal in the Software without restriction, *)
+(* including without limitation the rights to use, copy, modify, merge, *)
+(* publish, distribute, sublicense, and/or sell copies of the Software, *)
+(* and to permit persons to whom the Software is furnished to do so, *)
+(* subject to the following conditions: *)
+(* *)
+(* The above copyright notice and this permission notice shall be *)
+(* included in all copies or substantial portions of the Software. *)
+(* *)
+(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *)
+(* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *)
+(* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *)
+(* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS *)
+(* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN *)
+(* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *)
+(* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *)
+(* SOFTWARE. *)
+(**************************************************************************)
+
+(* upnp port map zzz++*)
+type ml_port_map = {
+ mutable enabled : int;
+ mutable intPort : int;
+ mutable extPort : int;
+ mutable isTcp : int;
+ mutable natpmpStatus : int;
+ mutable upnpStatus : int;
+ mutable notes : string;
+}
+
+let string_of_map_status status =
+ match status with
+ | 0 -> "ERROR"
+ | 1 -> "UNMAPPED"
+ | 2 -> "UNMAPPING"
+ | 3 -> "MAPPING"
+ | 4 -> "MAPPED"
+ | _ -> "N/A"
+
+let strings_port_map map =
+ Printf.sprintf "enable:%d ,intPort:%d ,extPort:%d ,isTcp:%d
,natpmpStatus:\"%s\" ,upnpStatus:\"%s\" ,notes:\"%s\""
+ map.enabled map.intPort map.extPort map.isTcp (string_of_map_status
map.natpmpStatus) (string_of_map_status map.upnpStatus) map.notes
+
+
+external init_maps : unit -> unit = "ml_upnpInitMaps" "noalloc"
+(*external set_maps : unit -> unit = "ml_upnpSetMaps" *)
+external dump_maps : unit -> unit = "ml_upnpDumpMaps" "noalloc"
+external job_start : unit -> unit = "ml_upnp_job_start" "noalloc"
+
+(* job_stop max_wait_seconds, 0=system default wait seconds *)
+external job_stop : int -> unit = "ml_upnp_job_stop"
+
+external maps_add_item : int -> int -> int -> int -> string -> unit =
"ml_upnpAddMap"
+external maps_remove_item : int -> int -> int -> int -> string -> unit =
"ml_upnpRemoveMap"
+
+(* remove_all_maps max_wait_seconds, 0=system default wait seconds *)
+external remove_all_maps : int -> unit = "ml_upnpRemoveAllMaps"
+
+(* maps_get , get all maps info to a list *)
+external maps_get : unit -> ml_port_map list = "ml_upnpGetMaps"
Index: src/utils/net/upnpClient.mli
===================================================================
RCS file: src/utils/net/upnpClient.mli
diff -N src/utils/net/upnpClient.mli
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/utils/net/upnpClient.mli 1 Nov 2010 17:19:23 -0000 1.1
@@ -0,0 +1,29 @@
+(* simples pure c api now
+(type ml_port_map
+val upnp_map_list_add : ml_port_map -> unit
+val upnp_map_list_remove : ml_port_map -> unit
+val create_ml_port_map : int -> int -> int -> int -> string -> ml_port_map
+*)
+
+type ml_port_map = {
+ mutable enabled : int;
+ mutable intPort : int;
+ mutable extPort : int;
+ mutable isTcp : int;
+ mutable natpmpStatus : int;
+ mutable upnpStatus : int;
+ mutable notes : string;
+}
+
+val string_of_map_status : int -> string
+val strings_port_map : ml_port_map -> string
+
+external init_maps : unit -> unit = "ml_upnpInitMaps" "noalloc"
+(*external set_maps : unit -> unit = "ml_upnpSetMaps" *)
+external dump_maps : unit -> unit = "ml_upnpDumpMaps" "noalloc"
+external job_start : unit -> unit = "ml_upnp_job_start" "noalloc"
+external job_stop : int -> unit = "ml_upnp_job_stop"
+external maps_add_item : int -> int -> int -> int -> string -> unit =
"ml_upnpAddMap"
+external maps_remove_item : int -> int -> int -> int -> string -> unit =
"ml_upnpRemoveMap"
+external remove_all_maps : int -> unit = "ml_upnpRemoveAllMaps"
+external maps_get : unit -> ml_port_map list = "ml_upnpGetMaps"
\ No newline at end of file
Index: src/utils/net/upnp_stubs.c
===================================================================
RCS file: src/utils/net/upnp_stubs.c
diff -N src/utils/net/upnp_stubs.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/utils/net/upnp_stubs.c 1 Nov 2010 17:19:23 -0000 1.1
@@ -0,0 +1,1185 @@
+/**************************************************************************/
+/* Copyright (c) 2010 zzz <address@hidden> */
+/* */
+/* mlupnp, a ocaml wraps of libminiupnpc & libnatpmp for mldonkey */
+/* */
+/* Permission is hereby granted, free of charge, to any person */
+/* obtaining a copy of this software and associated documentation files */
+/* (the "Software"), to deal in the Software without restriction, */
+/* including without limitation the rights to use, copy, modify, merge, */
+/* publish, distribute, sublicense, and/or sell copies of the Software, */
+/* and to permit persons to whom the Software is furnished to do so, */
+/* subject to the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
+/* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
+/* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS */
+/* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN */
+/* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN */
+/* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */
+/* SOFTWARE. */
+/**************************************************************************/
+/* wraps for libminiupnpc libnatpmp*/
+
+#include "../../../config/config.h"
+#include "../../utils/lib/os_stubs.h"
+
+#ifdef ENABLE_UPNP_NATPMP
+
+#include <string.h>
+#include <ctype.h>
+
+#ifdef __MORPHOS__
+#include <inttypes.h>
+#endif /* __MORPHOS__ */
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif /* HAVE_SYS_RESOURCE_H */
+
+#include <pthread.h>
+#include <signal.h>
+#include <sys/time.h>
+
+#ifdef WIN32
+ #include <inttypes.h>
+ #include <winsock2.h>
+ #include <WS2tcpip.h>
+ typedef int socklen_t;
+#else
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+#endif
+
+#ifdef WIN32
+ #define ECONNREFUSED WSAECONNREFUSED
+ #define ECONNRESET WSAECONNRESET
+ #define EHOSTUNREACH WSAEHOSTUNREACH
+ #define EINPROGRESS WSAEINPROGRESS
+ #define ENOTCONN WSAENOTCONN
+ #define EWOULDBLOCK WSAEWOULDBLOCK
+ #define EAFNOSUPPORT WSAEAFNOSUPPORT
+ #define ENETUNREACH WSAENETUNREACH
+ #define sockerrno WSAGetLastError( )
+#else
+ #include <errno.h>
+ #define sockerrno errno
+#endif
+
+#include <miniupnpc/miniupnpc.h>
+#include <miniupnpc/upnpcommands.h>
+#define ENABLE_STRNATPMPERR
+#include <natpmp.h>
+
+#undef DEBUG_PRINTF_UPNP
+#ifdef DEBUG_PRINTF_UPNP
+#define dbg_printf printf
+#else
+static void dbg_printf (const char *str, ... ){}
+#endif
+
+/* can hold max 20 port forwarding, is it enough for all mldonkey
bt/ed2k/kad/ft clients I think */
+#define MAX_MAPS 20
+#define MAX_THREAD_WAIT 30
+#define COMMAND_WAIT_SECS 8
+#define LIFETIME_SECS 3600
+
+enum
+{
+ UPNP_IGD_NONE = 0,
+ UPNP_IGD_VALID_CONNECTED = 1,
+ UPNP_IGD_VALID_NOT_CONNECTED = 2,
+ UPNP_IGD_INVALID = 3
+};
+
+typedef enum
+{
+ ML_UPNP_IDLE = 0,
+ ML_UPNP_ERR,
+ ML_UPNP_DISCOVER,
+ ML_UPNP_MAP,
+ ML_UPNP_UNMAP
+}
+ml_upnp_state;
+
+typedef enum
+{
+ ML_NATPMP_IDLE = 0,
+ ML_NATPMP_ERR,
+ ML_NATPMP_DISCOVER,
+ ML_NATPMP_RECV_PUB,
+ ML_NATPMP_SEND_MAP,
+ ML_NATPMP_RECV_MAP,
+ ML_NATPMP_SEND_UNMAP,
+ ML_NATPMP_RECV_UNMAP
+}
+ml_natpmp_state;
+
+typedef enum
+{
+ ML_PORT_ERROR = 0,
+ ML_PORT_UNMAPPED,
+ ML_PORT_UNMAPPING,
+ ML_PORT_MAPPING,
+ ML_PORT_MAPPED
+}
+ml_port_forwarding;
+
+typedef struct ml_upnpmp_t
+{
+ int enabled;
+ unsigned short int intPort;
+ unsigned short int extPort;
+ int isTcp; /*tcp=1, udp=0*/
+ char notes[32];
+ char lanaddr[16];
+ int doPortCheck;
+ time_t overTime;
+ ml_port_forwarding natpmpStatus;
+ ml_port_forwarding upnpStatus;
+
+ int upnpDiscovered;
+ unsigned int upnpMapped;
+ ml_upnp_state upnpState;
+ struct UPNPUrls upnpUrls;
+ struct IGDdatas upnpData;
+
+ unsigned int natpmpMapped;
+ int natpmpDiscovered;
+ ml_upnp_state natpmpState;
+ time_t renewTime;
+ time_t commandTime;
+ natpmp_t natpmp;
+}ml_upnpmp_t;
+
+static ml_upnpmp_t g_maps[MAX_MAPS];
+static ml_upnpmp_t g_unmaps[MAX_MAPS];
+static int g_inited = 0;
+static int g_running = 0;
+static int g_stop = 0;
+static pthread_t g_pthread;
+//static pthread_cond_t cond;
+static pthread_mutex_t g_mutex;
+static pthread_mutex_t g_delay_mutex;
+
+
+/** @brief init memset 0 g_maps g_unmaps */
+static void init_maps()
+{
+ if ( ! g_inited ){
+ memset( g_maps, 0, sizeof(g_maps) );
+ memset( g_unmaps, 0, sizeof(g_unmaps) );
+ g_inited = 1;
+ }
+}
+
+/** @brief add a ml_upnpmp_t item to g_maps */
+static int maps_add_item( ml_upnpmp_t * map )
+{
+ int i;
+ int found;
+
+ if ( ! g_inited ){
+ dbg_printf("g_maps not initialize!\n");
+ return -1;
+ }
+
+ found = 0;
+ for (i = 0; i < MAX_MAPS; i++){
+ if ( ! g_maps[i].enabled ){
+ continue;
+ }
+ if (g_maps[i].intPort == map->intPort && \
+ g_maps[i].extPort == map->extPort && \
+ g_maps[i].isTcp == map->isTcp){
+ found = 1;
+ dbg_printf("intPort %d, extPort %d, isTcp %d
existed\n", map->intPort, map->extPort, map->isTcp);
+ break;
+ }
+ }
+
+ if ( ! found ){
+ for(i = 0; i < MAX_MAPS; i++){
+ if ( ! g_maps[i].enabled ){
+ pthread_mutex_lock(&g_mutex);
+ memcpy(&g_maps[i], map, sizeof(ml_upnpmp_t));
+ g_maps[i].enabled = 1;
+ g_maps[i].upnpState = ML_UPNP_DISCOVER;
+ g_maps[i].natpmpState = ML_NATPMP_DISCOVER;
+ g_maps[i].natpmp.s = -1; /* socket */
+ g_maps[i].upnpStatus = ML_PORT_UNMAPPED;
+ g_maps[i].natpmpStatus = ML_PORT_UNMAPPED;
+ g_maps[i].overTime = 0;
+ pthread_mutex_unlock(&g_mutex);
+ dbg_printf("intPort %d, extPort %d, isTcp %d
added\n", map->intPort, map->extPort, map->isTcp);
+ return 0;
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+/** @brief remove a ml_upnpmp_t item form g_maps, and add to g_unmaps */
+static int maps_remove_item( ml_upnpmp_t * map )
+{
+ int i,j;
+ int found;
+
+ if ( ! g_inited ){
+ dbg_printf("g_maps not initialize!\n");
+ return -1;
+ }
+
+ found = 0;
+ for (i = 0; i < MAX_MAPS; i++){
+ if ( ! g_maps[i].enabled ){
+ continue;
+ }
+ if (g_maps[i].intPort == map->intPort && \
+ g_maps[i].extPort == map->extPort && \
+ g_maps[i].isTcp == map->isTcp){
+ found = 1;
+ for(j = 0; j < MAX_MAPS; j++){
+ if ( !g_unmaps[j].extPort ){
+ pthread_mutex_lock(&g_mutex);
+ memcpy(&g_unmaps[j], &g_maps[i],
sizeof(ml_upnpmp_t));
+ g_unmaps[j].enabled = 0;
+ g_unmaps[j].overTime = 0;
+ memset(&g_maps[i], 0,
sizeof(ml_upnpmp_t));
+ pthread_mutex_unlock(&g_mutex);
+ dbg_printf("intPort %d, extPort %d,
isTcp %d moved from maps to unmaps\n", map->intPort, map->extPort, map->isTcp);
+ return 0;
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ if ( ! found ){
+ for (i = 0; i < MAX_MAPS; i++){
+ if (g_unmaps[i].intPort == map->intPort && \
+ g_unmaps[i].extPort == map->extPort && \
+ g_unmaps[i].isTcp == map->isTcp){
+ dbg_printf("intPort %d, extPort %d, isTcp %d
existed in unmaps\n", map->intPort, map->extPort, map->isTcp);
+ return 0;
+ break;
+ }
+ }
+ for(j = 0; j < MAX_MAPS; j++){
+ if ( !g_unmaps[j].extPort ){
+ pthread_mutex_lock(&g_mutex);
+ memcpy(&g_unmaps[j], map, sizeof(ml_upnpmp_t));
+ g_unmaps[j].enabled = 0;
+ g_unmaps[j].overTime = 0;
+ pthread_mutex_unlock(&g_mutex);
+ dbg_printf("intPort %d, extPort %d, isTcp %d
add to unmaps\n", map->intPort, map->extPort, map->isTcp);
+ return 0;
+ break;
+ }
+ }
+ }
+
+ return 1;
+}
+
+#if 0
+/** @brief new ml_upnpmp_t struct from int_port, ext_port, type, notes */
+value
+ml_upnpSetMaps(value map_list_v) {
+ ml_upnpmp_t map;
+ int i,j;
+ int found;
+ char *s = NULL;
+ value map_v;
+
+ if ( ! g_inited ){
+ dbg_printf("g_maps not initialize!\n");
+ return Val_unit;
+ }
+ const int len = Wosize_val(map_list_v);
+ //move the map from g_maps to g_unmaps that noexist in new map_list_v
+ for (i = 0; i < MAX_MAPS; i++){
+ if ( ! g_maps[i].enabled ){
+ continue;
+ }
+ found = 0;
+ for(j = 0; j<len && j < MAX_MAPS; j++){
+ //memset((void*) &map, 0, sizeof(map));
+ map_v = Field(map_list_v, j);
+ map.enabled = Int_val(Field(map_v, 0));
+ if ( ! map.enabled ){
+ continue;
+ }
+ map.intPort = Int_val(Field(map_v, 1));
+ map.extPort = Int_val(Field(map_v, 2));
+ map.isTcp = Int_val(Field(map_v, 3));
+ //strncpy(map.notes, String_val(Field(map_v, 4)), 32-1);
+
+ if (g_maps[i].intPort == map.intPort && \
+ g_maps[i].extPort == map.extPort && \
+ g_maps[i].isTcp == map.isTcp){
+ found = 1;
+ break;
+ }
+ }
+
+ if ( ! found ){
+ for(j = 0; j < MAX_MAPS; j++){
+ if ( ! g_unmaps[j].enabled && !
g_unmaps[j].extPort ){
+ pthread_mutex_lock(&g_mutex);
+ memcpy(&g_unmaps[j], &g_maps[i],
sizeof(ml_upnpmp_t));
+ g_unmaps[j].enabled = 0;
+ memset(&g_maps[i], 0,
sizeof(ml_upnpmp_t));
+ pthread_mutex_unlock(&g_mutex);
+ break;
+ }
+ }
+ }
+ }
+
+ //add the new map from map_list_v to g_maps that noexist in g_maps
+ for (i = 0; i < len && i<MAX_MAPS; i++){
+ memset((void*) &map, 0, sizeof(map));
+ map_v = Field(map_list_v, i);
+ map.enabled = Int_val(Field(map_v, 0));
+ if ( ! map.enabled ){
+ continue;
+ }
+ map.intPort = Int_val(Field(map_v, 1));
+ map.extPort = Int_val(Field(map_v, 2));
+ map.isTcp = Int_val(Field(map_v, 3));
+ s = String_val(Field(map_v, 4));
+ if (s && *s){
+ strncpy(map.notes, s, 32-1);
+ }else{
+ strncpy(map.notes, "mldonkey", 32-1);
+ }
+
+ found = 0;
+ for(j = 0; j < MAX_MAPS; j++){
+ if (g_maps[j].intPort == map.intPort && \
+ g_maps[j].extPort == map.extPort && \
+ g_maps[j].isTcp == map.isTcp){
+ found = 1;
+ break;
+ }
+ }
+ if ( ! found ){
+ maps_add_item( &map );
+ }
+ }
+
+ return Val_unit;
+}
+#endif
+
+/** @brief dump ml_upnpmp_t struct */
+static void
+dumpMap(const ml_upnpmp_t * map, int type)
+{
+ if (type){
+ printf("map->enabled = %d\n", map->enabled);
+ printf("map->intPort = %d\n", map->intPort);
+ printf("map->extPort = %d\n", map->extPort);
+ printf("map->isTcp = %d\n", map->isTcp);
+ printf("map->notes = %s\n", map->notes);
+ printf("map->lanaddr = %02x:%02x:%02x::::%02x:%02x:%02x\n",
map->lanaddr[0], map->lanaddr[1], map->lanaddr[2], map->lanaddr[13],
map->lanaddr[14], map->lanaddr[15]);
+
+ printf("map->upnpDscv = %d\n", map->upnpDiscovered);
+ printf("map->upnpMapped = %d\n", map->upnpMapped);
+ printf("map->upnpState = %d\n", map->upnpState);
+
+ printf("map->natpmpDscv = %d\n", map->natpmpDiscovered);
+ printf("map->natpmpMapped= %d\n", map->natpmpMapped);
+ printf("map->natpmpState = %d\n", map->natpmpState);
+
+ printf("map->overTime = %d\n", (unsigned int)map->overTime);
+ printf("map->natpmpStatus= %d\n", map->natpmpStatus);
+ printf("map->upnpStatus = %d\n", map->upnpStatus);
+ }else{
+ printf("%1d ", map->enabled);
+ printf("%6d ", map->intPort);
+ printf("%6d ", map->extPort);
+ printf("%1d ", map->isTcp);
+ printf("%16s ", map->notes);
+ printf("%02x:%02x:%02x::::%02x:%02x:%02x ", map->lanaddr[0],
map->lanaddr[1], map->lanaddr[2], map->lanaddr[13], map->lanaddr[14],
map->lanaddr[15]);
+
+ printf("%1d ", map->upnpDiscovered);
+ printf("%1d ", map->upnpMapped);
+ printf("%1d ", map->upnpState);
+
+ printf("%1d ", map->natpmpDiscovered);
+ printf("%1d ", map->natpmpMapped);
+ printf("%1d ", map->natpmpState);
+ printf("%10d ", (unsigned int)map->overTime);
+ printf("%1d ", map->natpmpStatus);
+ printf("%1d ", map->upnpStatus);
+ printf("\n");
+ }
+}
+
+value
+ml_upnpDumpMaps(value unused)
+{
+ int i;
+ ml_upnpmp_t * map;
+
+ printf("=============== g_unmaps ===============\n");
+ printf("enabled intPort extPort isTcp notes lanaddr upnpDscv upnpMapped
upnpState natpmpDscv natpmpMapped natpmpState overTime natpmpStatus
upnpStatus\n");
+ for(i = 0; i < MAX_MAPS; i++ ){
+ map = &g_unmaps[i];
+ dumpMap( map, 0 );
+ }
+ printf("=============== g_maps ===============\n");
+ printf("enabled intPort extPort isTcp notes lanaddr upnpDscv upnpMapped
upnpState natpmpDscv natpmpMapped natpmpState overTime natpmpStatus
upnpStatus\n");
+ for(i = 0; i < MAX_MAPS; i++ ){
+ map = &g_maps[i];
+ dumpMap( map, 0 );
+ }
+
+ return Val_unit;
+}
+
+
+static inline int
+getStatus( const ml_upnpmp_t * map )
+{
+ if (map->natpmpStatus > map->upnpStatus)
+ return map->natpmpStatus;
+ else
+ return map->upnpStatus;
+}
+
+static const char*
+getNatStateStr( const int state )
+{
+ switch( state )
+ {
+ case ML_PORT_MAPPING: return "Starting";
+ case ML_PORT_MAPPED: return "Forwarded";
+ case ML_PORT_UNMAPPING: return "Stopping";
+ case ML_PORT_UNMAPPED: return "Not forwarded";
+ default: return "???";
+ }
+}
+
+const char*
+str_errno( const int i )
+{
+ const char * ret = strerror( i );
+
+ if( ret == NULL )
+ ret = "Unknown Error";
+ return ret;
+}
+
+static int
+canSendCommand( ml_upnpmp_t * map )
+{
+ return time(NULL) >= map->commandTime;
+}
+
+static void
+setCommandTime( ml_upnpmp_t * map )
+{
+ map->commandTime = time(NULL) + COMMAND_WAIT_SECS;
+}
+
+static int
+natpmpPulse( ml_upnpmp_t * map )
+{
+ int ret;
+
+ if( map->enabled && ( map->natpmpState == ML_NATPMP_DISCOVER ) )
+ {
+ int val = initnatpmp( &map->natpmp );
+ dbg_printf( "initnatpmp = %d\n", val );
+ val = sendpublicaddressrequest( &map->natpmp );
+ dbg_printf( "sendpublicaddressrequest = %d\n", val );
+ map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_PUB;
+ map->natpmpDiscovered = 1;
+ setCommandTime( map );
+ }
+
+ if( ( map->natpmpState == ML_NATPMP_RECV_PUB ) && canSendCommand( map ) )
+ {
+ natpmpresp_t response;
+ const int val = readnatpmpresponseorretry( &map->natpmp,
+ &response );
+ dbg_printf( "readnatpmpresponseorretry = %d\n", val );
+ if( val >= 0 )
+ {
+ dbg_printf( "Found public address \"%s\"\n", inet_ntoa(
response.pnu.publicaddress.addr ) );
+ map->natpmpState = ML_NATPMP_IDLE;
+ }
+ else if( val != NATPMP_TRYAGAIN )
+ {
+ map->natpmpState = ML_NATPMP_ERR;
+ }
+ }
+
+ if( ( map->natpmpState == ML_NATPMP_IDLE ) || ( map->natpmpState ==
ML_NATPMP_ERR ) )
+ {
+ if( map->natpmpMapped && ( ! map->enabled ) )
+ map->natpmpState = ML_NATPMP_SEND_UNMAP;
+ }
+
+ if( ( map->natpmpState == ML_NATPMP_SEND_UNMAP ) && canSendCommand( map ) )
+ {
+ const int val =
+ sendnewportmappingrequest( &map->natpmp, NATPMP_PROTOCOL_TCP,
+ map->intPort, map->extPort,
+ 0 );
+ dbg_printf( "sendnewportmappingrequest = %d\n", val );
+ map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_UNMAP;
+ setCommandTime( map );
+ }
+
+ if( map->natpmpState == ML_NATPMP_RECV_UNMAP )
+ {
+ natpmpresp_t resp;
+ const int val = readnatpmpresponseorretry( &map->natpmp, &resp );
+ dbg_printf( "readnatpmpresponseorretry = %d\n", val );
+ if( val >= 0 )
+ {
+ const int p = resp.pnu.newportmapping.privateport;
+ dbg_printf( "no longer forwarding port %d\n", p );
+ if( map->extPort == p )
+ {
+ map->extPort = 0;
+ map->natpmpState = ML_NATPMP_IDLE;
+ map->natpmpMapped = 0;
+ }
+ }
+ else if( val != NATPMP_TRYAGAIN )
+ {
+ map->natpmpState = ML_NATPMP_ERR;
+ }
+ }
+
+ if( map->natpmpState == ML_NATPMP_IDLE )
+ {
+ if( map->enabled && !map->natpmpMapped && map->natpmpDiscovered )
+ map->natpmpState = ML_NATPMP_SEND_MAP;
+
+ else if( map->natpmpMapped && time(NULL) >= map->renewTime )
+ map->natpmpState = ML_NATPMP_SEND_MAP;
+ }
+
+ if( ( map->natpmpState == ML_NATPMP_SEND_MAP ) && canSendCommand( map ) )
+ {
+ const int val =
+ sendnewportmappingrequest( &map->natpmp, NATPMP_PROTOCOL_TCP,
+ map->intPort,
+ map->extPort,
+ LIFETIME_SECS );
+ dbg_printf( "sendnewportmappingrequest = %d\n", val );
+ map->natpmpState = val < 0 ? ML_NATPMP_ERR : ML_NATPMP_RECV_MAP;
+ setCommandTime( map );
+ }
+
+ if( map->natpmpState == ML_NATPMP_RECV_MAP )
+ {
+ natpmpresp_t resp;
+ const int val = readnatpmpresponseorretry( &map->natpmp, &resp );
+ dbg_printf( "readnatpmpresponseorretry = %d\n", val );
+ if( val >= 0 )
+ {
+ map->natpmpState = ML_NATPMP_IDLE;
+ map->natpmpMapped = 1;
+ map->renewTime = time(NULL) + LIFETIME_SECS;
+ map->extPort = resp.pnu.newportmapping.privateport;
+ dbg_printf( "Port %d forwarded successfully\n", map->extPort );
+ }
+ else if( val != NATPMP_TRYAGAIN )
+ {
+ map->natpmpState = ML_NATPMP_ERR;
+ }
+ }
+
+ switch( map->natpmpState )
+ {
+ case ML_NATPMP_IDLE:
+ ret = map->natpmpMapped ? ML_PORT_MAPPED : ML_PORT_UNMAPPED; break;
+
+ case ML_NATPMP_DISCOVER:
+ ret = ML_PORT_UNMAPPED; break;
+
+ case ML_NATPMP_RECV_PUB:
+ case ML_NATPMP_SEND_MAP:
+ case ML_NATPMP_RECV_MAP:
+ ret = ML_PORT_MAPPING; break;
+
+ case ML_NATPMP_SEND_UNMAP:
+ case ML_NATPMP_RECV_UNMAP:
+ ret = ML_PORT_UNMAPPING; break;
+
+ default:
+ ret = ML_PORT_ERROR; break;
+ }
+ return ret;
+}
+
+
+static int
+upnpPulse( ml_upnpmp_t * map )
+{
+ int ret;
+
+ if( map->enabled && ( map->upnpState == ML_UPNP_DISCOVER ) )
+ {
+ struct UPNPDev * devlist;
+ errno = 0;
+ devlist = upnpDiscover( 2000, NULL, NULL, 0 );
+ if( devlist == NULL )
+ {
+ dbg_printf( "upnpDiscover failed (errno %d - %s)\n", errno,
str_errno( errno ) );
+ }
+ errno = 0;
+ if( UPNP_IGD_VALID_CONNECTED == UPNP_GetValidIGD( devlist,
&map->upnpUrls, &map->upnpData,
+ map->lanaddr, sizeof( map->lanaddr ) ) )
+ {
+ dbg_printf( "Found Internet Gateway Device \"%s\" \n",
map->upnpUrls.controlURL );
+ dbg_printf( "Local Address is \"%s\" \n", map->lanaddr );
+ map->upnpState = ML_UPNP_IDLE;
+ map->upnpDiscovered = 1;
+ }
+ else
+ {
+ map->upnpState = ML_UPNP_ERR;
+ dbg_printf( "UPNP_GetValidIGD failed (errno %d - %s)\n", errno,
str_errno( errno ) );
+ dbg_printf( "If your router supports UPnP, please make sure UPnP
is enabled!\n" );
+ }
+ freeUPNPDevlist( devlist );
+ }
+
+ if( map->upnpState == ML_UPNP_IDLE )
+ {
+ if( map->upnpMapped && ( !map->enabled ) )
+ map->upnpState = ML_UPNP_UNMAP;
+ }
+
+ if( map->enabled && map->upnpMapped && map->doPortCheck )
+ {
+ char portStr[8];
+ char intPort[8];
+ char intClient[16];
+ char type[8];
+ int i;
+
+ snprintf( portStr, sizeof( portStr ), "%d", map->extPort );
+ snprintf( type, sizeof( type ), "%s", ( map->isTcp ? "TCP" : "UDP" ) );
+ i = UPNP_GetSpecificPortMappingEntry( map->upnpUrls.controlURL,
+ map->upnpData.first.servicetype,
portStr,
+ type, intClient, intPort );
+ if( i != UPNPCOMMAND_SUCCESS )
+ {
+ dbg_printf( "Port %d isn't forwarded\n", map->extPort );
+ map->upnpMapped = 0;
+ }
+ map->doPortCheck = 0;
+ }
+
+ if( map->upnpState == ML_UPNP_UNMAP )
+ {
+ char portStr[16];
+ char type[8];
+ snprintf( portStr, sizeof( portStr ), "%d", map->extPort );
+ snprintf( type, sizeof( type ), "%s", ( map->isTcp ? "TCP" : "UDP" ) );
+ UPNP_DeletePortMapping( map->upnpUrls.controlURL,
+ map->upnpData.first.servicetype,
+ portStr, type, NULL );
+ dbg_printf( "Stopping port forwarding through \"%s\", service
\"%s\"\n", map->upnpUrls.controlURL, map->upnpData.first.servicetype );
+ map->upnpMapped = 0;
+ map->upnpState = ML_UPNP_IDLE;
+ map->extPort = 0;
+ }
+
+ if( map->upnpState == ML_UPNP_IDLE )
+ {
+ if( map->enabled && !map->upnpMapped )
+ map->upnpState = ML_UPNP_MAP;
+ }
+
+ if( map->upnpState == ML_UPNP_MAP )
+ {
+ int err = -1;
+ errno = 0;
+
+ if( !map->upnpUrls.controlURL || !map->upnpData.first.servicetype )
+ map->upnpMapped = 0;
+ else
+ {
+ char intPortStr[16];
+ char extPortStr[16];
+ char desc[64];
+ char type[8];
+ snprintf( intPortStr, sizeof( intPortStr ), "%d", map->intPort );
+ snprintf( extPortStr, sizeof( extPortStr ), "%d", map->extPort );
+ snprintf( desc, sizeof( desc ), "%s", map->notes );
+ snprintf( type, sizeof( type ), "%s", ( map->isTcp ? "TCP" : "UDP"
) );
+ err = UPNP_AddPortMapping( map->upnpUrls.controlURL,
+ map->upnpData.first.servicetype,
+ extPortStr, intPortStr, map->lanaddr,
+ desc, type, NULL );
+ map->upnpMapped = !err;
+ }
+ dbg_printf( "Port forwarding through \"%s\", service \"%s\". (local
address[%s:%d])\n", map->upnpUrls.controlURL, map->upnpData.first.servicetype,
map->lanaddr, map->intPort );
+ if( map->upnpMapped )
+ {
+ dbg_printf( "Port forwarding successful!\n" );
+ //handle->port = port;
+ map->upnpState = ML_UPNP_IDLE;
+ }
+ else
+ {
+ dbg_printf( "Port forwarding failed with error %d (errno %d -
%s)\n", err, errno, str_errno( errno ) );
+ dbg_printf( "If your router supports UPnP, please make sure UPnP
is enabled!\n" );
+ //handle->port = -1;
+ map->upnpState = ML_UPNP_ERR;
+ }
+ }
+
+ switch( map->upnpState )
+ {
+ case ML_UPNP_DISCOVER:
+ ret = ML_PORT_UNMAPPED; break;
+
+ case ML_UPNP_MAP:
+ ret = ML_PORT_MAPPING; break;
+
+ case ML_UPNP_UNMAP:
+ ret = ML_PORT_UNMAPPING; break;
+
+ case ML_UPNP_IDLE:
+ ret = map->upnpMapped ? ML_PORT_MAPPED
+ : ML_PORT_UNMAPPED; break;
+
+ default:
+ ret = ML_PORT_ERROR; break;
+ }
+
+ return ret;
+}
+
+
+static void *
+upnpNatpmpThread( )
+{
+ int oldStatus, newStatus;
+ int i, err;
+ time_t now;
+ struct timespec deltatime;
+
+ pthread_mutex_lock(&g_mutex);
+ g_stop = 0;
+ pthread_mutex_unlock(&g_mutex);
+
+ while( g_running ){
+ //clear in g_unmaps
+ now = time(NULL);
+ for(i = 0; i < MAX_MAPS; i++){
+ if ( ! g_running ) break;
+
+ if ( ! g_unmaps[i].enabled && g_unmaps[i].extPort > 0 ){
+ if ( g_unmaps[i].overTime < now ){
+ oldStatus = getStatus( &g_unmaps[i] );
+
+ pthread_mutex_lock(&g_mutex);
+
+ switch (oldStatus){
+ case ML_PORT_MAPPED:
+ g_unmaps[i].overTime = now + 60 * 20;
+ break;
+ case ML_PORT_ERROR:
+ g_unmaps[i].overTime = now + 60;
+ break;
+ default:
+ /* in progress. pulse frequently. */
+ g_unmaps[i].overTime = now + 333;
+ break;
+ }
+ g_unmaps[i].natpmpStatus = natpmpPulse(
&g_unmaps[i] );
+ g_unmaps[i].doPortCheck = 0;
+ g_unmaps[i].upnpStatus = upnpPulse(
&g_unmaps[i]);
+ dbg_printf( "upnpNatpmpThread
g_unmaps[%d]\n", i);
+
+#ifdef DEBUG_PRINTF_UPNP
+ dumpMap(&g_unmaps[i], 1);
+#endif
+ newStatus = getStatus( &g_unmaps[i]
);
+
+ if( newStatus != oldStatus )
+ dbg_printf( "port forwarding
state changed from \"%s\" to \"%s\"\n", getNatStateStr( oldStatus ),
getNatStateStr( newStatus ) );
+ if( newStatus == ML_PORT_UNMAPPED ){
+ memset(&g_unmaps[i], 0,
sizeof(ml_upnpmp_t));
+ }
+ pthread_mutex_unlock(&g_mutex);
+ }
+ }
+ }
+ //create,check in g_maps
+ now = time(NULL);
+ for(i = 0; i < MAX_MAPS; i++){
+ if ( ! g_running ) break;
+
+ if ( g_maps[i].enabled && g_maps[i].extPort ){
+ if ( g_maps[i].overTime < now ){
+ oldStatus = getStatus( &g_maps[i] );
+
+ pthread_mutex_lock(&g_mutex);
+
+ switch (oldStatus){
+ case ML_PORT_MAPPED:
+ g_maps[i].overTime = now + 60 * 20;
+ break;
+ case ML_PORT_ERROR:
+ g_maps[i].overTime = now + 60;
+ break;
+ default:
+ /* in progress. pulse frequently. */
+ g_maps[i].overTime = now + 333;
+ break;
+ }
+ g_maps[i].natpmpStatus = natpmpPulse(
&g_maps[i] );
+ g_maps[i].doPortCheck = 1;
+ g_maps[i].upnpStatus = upnpPulse(
&g_maps[i] );
+
+ pthread_mutex_unlock(&g_mutex);
+
+ dbg_printf( "upnpNatpmpThread
g_maps[%d]\n", i);
+#ifdef DEBUG_PRINTF_UPNP
+ dumpMap(&g_maps[i], 1);
+#endif
+
+ newStatus = getStatus( &g_maps[i] );
+
+ if( newStatus != oldStatus )
+ dbg_printf( "port forwarding
state changed from \"%s\" to \"%s\"\n", getNatStateStr( oldStatus ),
getNatStateStr( newStatus ) );
+ }
+ }
+ }
+ if ( g_running ){
+ deltatime.tv_sec = time(NULL) + 30;
+ deltatime.tv_nsec = 0;
+ err = pthread_mutex_timedlock(&g_delay_mutex,
&deltatime);
+ dbg_printf("%d seconds timedlock err=%d, running...\n",
deltatime.tv_sec, err);
+ }else{
+ break;
+ }
+ }
+ pthread_mutex_lock(&g_mutex);
+ g_stop = 1;
+ pthread_mutex_unlock(&g_mutex);
+ dbg_printf("upnp thread stopped!\n");
+
+ return NULL;
+}
+
+static void
+upnp_thread_start( )
+{
+ int err;
+ if ( ! g_inited ){
+ init_maps();
+ }
+
+ if ( ! g_running ){
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+ //pthread_cond_init(&cond, NULL);
+ pthread_mutex_init(&g_mutex, NULL);
+ pthread_mutex_init(&g_delay_mutex, NULL);
+ pthread_mutex_unlock(&g_mutex);
+
+ err = pthread_create(&g_pthread, &attr, upnpNatpmpThread, NULL);
+
+ if(err){
+ perror("Error while starting upnp thread\n");
+ exit(2);
+ }
+ g_inited = 1;
+ pthread_mutex_lock(&g_mutex);
+ g_running = 1;
+ g_stop = 0;
+ pthread_mutex_unlock(&g_mutex);
+ }else{
+ dbg_printf("threading had started\n");
+ }
+ return;
+}
+
+static void
+upnp_thread_stop( int wait_seconds )
+{
+ int i = 0;
+ int wait = wait_seconds;
+
+ if (wait < 1) wait = MAX_THREAD_WAIT;
+
+ pthread_mutex_lock(&g_mutex);
+ g_stop = 0;
+ g_running = 0;
+ pthread_mutex_unlock(&g_mutex);
+ pthread_mutex_unlock(&g_delay_mutex);
+
+ for (i=0; i<wait; i++){
+ if (g_stop){
+ pthread_mutex_lock(&g_mutex);
+ g_stop = 0;
+ pthread_mutex_unlock(&g_mutex);
+ break;
+ }else{
+ sleep(1);
+ }
+ }
+
+ if (i >= wait){
+ pthread_cancel(g_pthread);
+ }
+ pthread_mutex_destroy(&g_mutex);
+ pthread_mutex_destroy(&g_delay_mutex);
+ return;
+}
+
+/** @brief ocaml api, init memset g_maps g_unmaps to 0 */
+value
+ml_upnpInitMaps(value unused)
+{
+ init_maps();
+ return Val_unit;
+}
+
+
+/** @brief ocaml api, start the upnp thread */
+value
+ml_upnp_job_start( value unused )
+{
+ upnp_thread_start( );
+ return Val_unit;
+}
+
+
+/** @brief ocaml api, stop the upnp thread */
+value
+ml_upnp_job_stop( value wait_v )
+{
+ int wait;
+ wait = Val_int( wait_v );
+
+ upnp_thread_stop( wait );
+ return Val_unit;
+}
+
+/** @brief caml api, new ml_upnpmp_t struct from int_port, ext_port, type,
notes, and add to g_maps */
+value
+ml_upnpAddMap(value m_enabled, value m_intPort, value m_extPort, value m_type,
value m_notes)
+{
+ ml_upnpmp_t map;
+ char *s = NULL;
+
+ memset(&map, 0, sizeof(ml_upnpmp_t));
+
+ map.enabled = Int_val(m_enabled);
+ map.intPort = Int_val(m_intPort);
+ map.extPort = Int_val(m_extPort);
+ map.isTcp = Int_val(m_type);
+ s = String_val(m_notes);
+ if (s && *s){
+ strncpy(map.notes, s, 32-1);
+ }else{
+ strncpy(map.notes, "mldonkey", 32-1);
+ }
+
+ maps_add_item( &map );
+
+ return Val_unit;
+}
+
+/** @brief caml api, new ml_upnpmp_t struct from int_port, ext_port, type,
notes, and remove from g_maps, add to g_unmaps */
+value
+ml_upnpRemoveMap(value m_enabled, value m_intPort, value m_extPort, value
m_type, value m_notes)
+{
+ ml_upnpmp_t map;
+ char *s = NULL;
+
+ memset(&map, 0, sizeof(ml_upnpmp_t));
+
+ map.enabled = Int_val(m_enabled);
+ map.intPort = Int_val(m_intPort);
+ map.extPort = Int_val(m_extPort);
+ map.isTcp = Int_val(m_type);
+ s = String_val(m_notes);
+ if (s && *s){
+ strncpy(map.notes, s, 32-1);
+ }else{
+ strncpy(map.notes, "mldonkey", 32-1);
+ }
+ maps_remove_item( &map );
+
+ return Val_unit;
+}
+
+/** @brief caml api, stop all maps in g_maps, call before mldonkey exit to
clear router */
+value
+ml_upnpRemoveAllMaps(value wait_v)
+{
+ int i,j;
+ int found;
+ int wait;
+ wait = Val_int( wait_v );
+ if (wait < 1) wait = MAX_THREAD_WAIT;
+
+ if ( ! g_inited ){
+ dbg_printf("g_maps not initialize!\n");
+ return Val_unit;
+ }
+
+ for (i = 0; i < MAX_MAPS; i++){
+ if ( ! g_maps[i].enabled ){
+ continue;
+ }
+ found = 0;
+ for(j = 0; j < MAX_MAPS; j++){
+ if (g_maps[i].intPort == g_unmaps[j].intPort && \
+ g_maps[i].extPort == g_unmaps[j].extPort && \
+ g_maps[i].isTcp == g_unmaps[j].isTcp){
+ found = 1;
+ break;
+ }
+ }
+
+ if ( ! found ){
+ for(j = 0; j < MAX_MAPS; j++){
+ if ( ! g_unmaps[j].enabled && !
g_unmaps[j].extPort ){
+ pthread_mutex_lock(&g_mutex);
+ memcpy(&g_unmaps[j], &g_maps[i],
sizeof(ml_upnpmp_t));
+ g_unmaps[j].enabled = 0;
+ g_unmaps[j].overTime = 0;
+ memset(&g_maps[i], 0,
sizeof(ml_upnpmp_t));
+ pthread_mutex_unlock(&g_mutex);
+ break;
+ }
+ }
+ }
+ }
+ pthread_mutex_unlock( &g_delay_mutex );
+
+ for (i=0; i<wait; i++){
+ sleep(1);
+ found = 0;
+ for(j = 0; j < MAX_MAPS; j++){
+ if (g_unmaps[j].extPort){
+ found = 1;
+ break;
+ }
+ }
+ if ( ! found ){
+ break;
+ }
+ }
+ return Val_unit;
+}
+
+/** @brief caml api, reutrn all maps in g_maps to a list[tuple(7 items)] */
+value
+ml_upnpGetMaps(value unused)
+{
+ CAMLparam0 ();
+ int i;
+
+ CAMLlocal3( maps, map, cons );
+ maps = Val_emptylist;
+
+ if ( ! g_inited ){
+ dbg_printf("g_maps not initialize!\n");
+ CAMLreturn( Val_unit );
+ }
+
+ for (i = MAX_MAPS - 1; i > 0; i--){
+ if ( ! g_maps[i].enabled ){
+ continue;
+ }
+
+ map = caml_alloc_tuple( 7 );
+ Store_field( map, 0, Val_int(g_maps[i].enabled) );
+ Store_field( map, 1, Val_int(g_maps[i].intPort) );
+ Store_field( map, 2, Val_int(g_maps[i].extPort) );
+ Store_field( map, 3, Val_int(g_maps[i].isTcp) );
+ Store_field( map, 4, Val_int(g_maps[i].natpmpStatus) );
+ Store_field( map, 5, Val_int(g_maps[i].upnpStatus) );
+ Store_field( map, 6, caml_copy_string(g_maps[i].notes) );
+
+ cons = caml_alloc( 2, 0 );
+ Store_field( cons, 0, map ); // head
+ Store_field( cons, 1, maps ); // tail
+ maps = cons;
+ }
+ CAMLreturn( maps );
+}
+
+
+#else /* for ifdef ENABLE_UPNP_NATPMP */
+/* no include upnp natpmp, dummy api here */
+value
+ml_upnpInitMaps(value unused)
+{
+ return Val_unit;
+}
+
+/** @brief ocaml api, start the upnp thread */
+value
+ml_upnp_job_start( value unused )
+{
+ return Val_unit;
+}
+
+/** @brief ocaml api, stop the upnp thread */
+value
+ml_upnp_job_stop( value wait_v )
+{
+ return Val_unit;
+}
+
+value
+ml_upnpDumpMaps(value unused)
+{
+ return Val_unit;
+}
+
+value
+ml_upnpAddMap(value m_enabled, value m_intPort, value m_extPort, value m_type,
value m_notes)
+{
+ return Val_unit;
+}
+
+value
+ml_upnpRemoveMap(value m_enabled, value m_intPort, value m_extPort, value
m_type, value m_notes)
+{
+ return Val_unit;
+}
+
+value
+ml_upnpRemoveAllMaps(value wait_v)
+{
+ return Val_unit;
+}
+
+value
+ml_upnpGetMaps(value unused)
+{
+ return Val_emptylist;
+}
+
+#endif
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Mldonkey-commits] mldonkey config/Makefile.config.in config/Makef...,
mldonkey-commits <=