Hello community,

here is the log from the commit of package 2ping for openSUSE:Factory checked 
in at 2018-10-08 17:49:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/2ping (Old)
 and      /work/SRC/openSUSE:Factory/.2ping.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "2ping"

Mon Oct  8 17:49:05 2018 rev:7 rq:640532 version:4.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/2ping/2ping.changes      2018-08-12 
20:56:26.221596982 +0200
+++ /work/SRC/openSUSE:Factory/.2ping.new/2ping.changes 2018-10-08 
17:50:52.986066430 +0200
@@ -1,0 +2,7 @@
+Mon Oct 08 05:58:03 UTC 2018 - s...@suspend.net
+
+- Update to version 4.2
+  * Added SIGHUP handling of listener processes
+  * Added an example bash_completion script
+  * Better cleanup handling of peer information
+-------------------------------------------------------------------

Old:
----
  2ping-4.1.2.tar.gz
  2ping-4.1.2.tar.gz.asc

New:
----
  2ping-4.2.tar.gz
  2ping-4.2.tar.gz.asc

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ 2ping.spec ++++++
--- /var/tmp/diff_new_pack.AqgMpS/_old  2018-10-08 17:50:53.390065915 +0200
+++ /var/tmp/diff_new_pack.AqgMpS/_new  2018-10-08 17:50:53.390065915 +0200
@@ -12,12 +12,12 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 Name:           2ping
-Version:        4.1.2
+Version:        4.2
 Release:        0
 Summary:        Bi-directional ping utility
 License:        GPL-2.0-or-later

++++++ 2ping-4.1.2.tar.gz -> 2ping-4.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/2ping.bash_completion 
new/2ping-4.2/2ping.bash_completion
--- old/2ping-4.1.2/2ping.bash_completion       1970-01-01 01:00:00.000000000 
+0100
+++ new/2ping-4.2/2ping.bash_completion 2018-08-11 23:06:16.000000000 +0200
@@ -0,0 +1,26 @@
+# 2ping(1) completion                                       -*- shell-script 
-*-
+
+_2ping()
+{
+    local cur prev words cword
+    _init_completion -n = || return
+
+    local ipvx
+
+    case $prev in
+        -4|-6)
+            ipvx=$prev
+            ;;
+    esac
+
+    if [[ $cur == -* ]]; then
+        COMPREPLY=( $( compgen -W '$( _parse_usage "$1" )' -- "$cur" ) )
+        return
+    fi
+
+    [[ $1 == *6 ]] && ipvx=-6
+    _known_hosts_real $ipvx -- "$cur"
+} &&
+complete -F _2ping 2ping 2ping6
+
+# ex: filetype=sh
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/2ping.spec new/2ping-4.2/2ping.spec
--- old/2ping-4.1.2/2ping.spec  2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/2ping.spec    2018-08-11 23:06:16.000000000 +0200
@@ -1,5 +1,5 @@
 Name:           2ping
-Version:        4.1
+Version:        4.2
 Release:        1%{?dist}
 Summary:        Bi-directional ping utility
 License:        GPLv2+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/ChangeLog new/2ping-4.2/ChangeLog
--- old/2ping-4.1.2/ChangeLog   2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/ChangeLog     2018-08-11 23:06:16.000000000 +0200
@@ -1,3 +1,8 @@
+2ping 4.2 (2018-08-11)
+ * Added SIGHUP handling of listener processes
+ * Added an example bash_completion script
+ * Better cleanup handling of peer information
+
 2ping 4.1.2 (2018-08-09)
  * Fix UTF-8 tests when run with invalid locale (Debian Bug#897498)
  * Fix cleanup on non-encrypted sessions (GitHub rfinnie/2ping#5)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/MANIFEST.in new/2ping-4.2/MANIFEST.in
--- old/2ping-4.1.2/MANIFEST.in 2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/MANIFEST.in   2018-08-11 23:06:16.000000000 +0200
@@ -7,5 +7,6 @@
 include 2ping
 include 2ping.spec
 include 2ping6
+include 2ping.bash_completion
 include tests/*.py
 include wireshark/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/doc/2ping.1 new/2ping-4.2/doc/2ping.1
--- old/2ping-4.1.2/doc/2ping.1 2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/doc/2ping.1   2018-08-11 23:06:16.000000000 +0200
@@ -1,4 +1,4 @@
-.\" Automatically generated by Pandoc 1.17.2
+.\" Automatically generated by Pandoc 1.19.2.4
 .\"
 .TH "2PING" "1" "" "" "2ping"
 .hy
@@ -7,7 +7,7 @@
 2ping \- A bi\-directional ping utility
 .SH SYNOPSIS
 .PP
-2ping [\f[I]options\f[]] \f[I]\-\-listen\f[] | host/IP
+2ping [\f[I]options\f[]] \f[I]\-\-listen\f[] | host/IP [host/IP [...]]
 .SH DESCRIPTION
 .PP
 \f[C]2ping\f[] is a bi\-directional ping utility.
@@ -250,6 +250,8 @@
 The listener will not send out ping requests at regular intervals, and
 will instead wait for the far end to initiate ping requests.
 A listener is required as the remote end for a client.
+When run as a listener, a SIGHUP will reload the configuration on all
+interfaces.
 .RS
 .RE
 .TP
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/doc/2ping.md new/2ping-4.2/doc/2ping.md
--- old/2ping-4.1.2/doc/2ping.md        2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/doc/2ping.md  2018-08-11 23:06:16.000000000 +0200
@@ -6,7 +6,7 @@
 
 # SYNOPSIS
 
-2ping [*options*] *--listen* | host/IP
+2ping [*options*] *--listen* | host/IP [host/IP [...]]
 
 # DESCRIPTION
 
@@ -144,6 +144,7 @@
 :   Start as a listener.
     The listener will not send out ping requests at regular intervals, and 
will instead wait for the far end to initiate ping requests.
     A listener is required as the remote end for a client.
+    When run as a listener, a SIGHUP will reload the configuration on all 
interfaces.
 
 --min-packet-size=*min*
 :   Set the minimum total payload size to *min* bytes, default 128.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/setup.py new/2ping-4.2/setup.py
--- old/2ping-4.1.2/setup.py    2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/setup.py      2018-08-11 23:06:16.000000000 +0200
@@ -15,7 +15,7 @@
     name='2ping',
     description='2ping a bi-directional ping utility',
     long_description=read('README'),
-    version='4.1',
+    version='4.2',
     license='GPLv2+',
     platforms=['Unix'],
     author='Ryan Finnie',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/twoping/__init__.py 
new/2ping-4.2/twoping/__init__.py
--- old/2ping-4.1.2/twoping/__init__.py 2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/twoping/__init__.py   2018-08-11 23:06:16.000000000 +0200
@@ -16,4 +16,4 @@
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 
-__version__ = '4.1'
+__version__ = '4.2'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/twoping/best_poller.py 
new/2ping-4.2/twoping/best_poller.py
--- old/2ping-4.1.2/twoping/best_poller.py      2018-08-10 05:29:17.000000000 
+0200
+++ new/2ping-4.2/twoping/best_poller.py        2018-08-11 23:06:16.000000000 
+0200
@@ -35,6 +35,13 @@
             self.poller.register(fileno, select.EPOLLIN)
         self.f_dict[fileno] = f
 
+    def unregister(self, f):
+        fileno = f.fileno()
+        if fileno not in self.f_dict:
+            return
+        self.poller.unregister(fileno)
+        del(self.f_dict[fileno])
+
     def close(self):
         return self.poller.close()
 
@@ -57,25 +64,32 @@
 
     def __init__(self):
         self.poller = select.kqueue()
-        self.kevents = []
+        self.kevents = {}
         self.f_dict = {}
 
     def register(self, f):
         fileno = f.fileno()
         if fileno not in self.f_dict:
-            self.kevents.append(select.kevent(
+            self.kevents[fileno] = select.kevent(
                 fileno,
                 filter=select.KQ_FILTER_READ,
                 flags=select.KQ_EV_ADD | select.KQ_EV_ENABLE,
-            ))
+            )
         self.f_dict[fileno] = f
 
+    def unregister(self, f):
+        fileno = f.fileno()
+        if fileno not in self.f_dict:
+            return
+        del(self.kevents[fileno])
+        del(self.f_dict[fileno])
+
     def close(self):
         return self.poller.close()
 
     def poll(self, timeout):
         try:
-            poll_res = self.poller.control(self.kevents, 10, timeout)
+            poll_res = self.poller.control(self.kevents.values(), 10, timeout)
         except (select.error, IOError, OSError) as e:
             if e.args[0] not in (errno.EINTR,):
                 raise
@@ -100,6 +114,13 @@
             self.poller.register(fileno, select.POLLIN)
         self.f_dict[fileno] = f
 
+    def unregister(self, f):
+        fileno = f.fileno()
+        if fileno not in self.f_dict:
+            return
+        self.poller.unregister(fileno)
+        del(self.f_dict[fileno])
+
     def close(self):
         return self.poller.close()
 
@@ -126,6 +147,12 @@
     def register(self, f):
         self.f_dict[f.fileno()] = f
 
+    def unregister(self, f):
+        fileno = f.fileno()
+        if fileno not in self.f_dict:
+            return
+        del(self.f_dict[fileno])
+
     def close(self):
         pass
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/twoping/cli.py 
new/2ping-4.2/twoping/cli.py
--- old/2ping-4.1.2/twoping/cli.py      2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/twoping/cli.py        2018-08-11 23:06:16.000000000 +0200
@@ -62,35 +62,11 @@
     def __init__(self, sock):
         self.sock = sock
 
-        # In-flight outbound messages.  Added in the following conditions:
-        #   * Outbound packet with OpcodeReplyRequested sent.
-        # Removed in following conditions:
-        #   * Inbound packet with OpcodeInReplyTo set to it.
-        #   * Inbound packet with it in OpcodeInvestigationSeen or 
OpcodeInvestigationUnseen.
-        #   * Cleanup after 10 minutes.
-        # If it remains for more than <10> seconds, it it sent as part of
-        # OpcodeInvestigate with the next outbound packet with 
OpcodeReplyRequested set.
-        self.sent_messages = {}
-        # Seen inbound messages.  Added in the following conditions:
-        #   * Inbound packet with OpcodeReplyRequested set.
-        # Referenced in the following conditions:
-        #   * Inbound packet with it in OpcodeInvestigate.
-        # Removed in the following conditions:
-        #   * Inbound packet with it in OpcodeCourtesyExpiration.
-        #   * Cleanup after 10 minutes.
-        self.seen_messages = {}
-        # Courtesy messages waiting to be sent.  Added in the following 
conditions:
-        #   * Inbound packet with OpcodeInReplyTo set.
-        # Removed in the following conditions:
-        #   * Outbound packet where there is room to send it as part of 
OpcodeCourtesyExpiration.
-        #   * Cleanup after 2 minutes.
-        self.courtesy_messages = {}
-        # Current position of a peer tuple's incrementing ping integer.
-        self.ping_positions = {}
         # Used during client mode for the host tuple to send UDP packets to.
         self.client_host = None
-        # Current session of a 5-tuple for encrypted sessions
-        self.encrypted_sessions = {}
+
+        # Dict of PeerState instances, indexed by peer tuple
+        self.peer_states = {}
 
         # Statistics
         self.pings_transmitted = 0
@@ -117,6 +93,44 @@
         return self.sock.fileno()
 
 
+class PeerState():
+    def __init__(self, peer_tuple, sock_class):
+        self.peer_tuple = peer_tuple
+        self.sock_class = sock_class
+
+        # In-flight outbound messages.  Added in the following conditions:
+        #   * Outbound packet with OpcodeReplyRequested sent.
+        # Removed in following conditions:
+        #   * Inbound packet with OpcodeInReplyTo set to it.
+        #   * Inbound packet with it in OpcodeInvestigationSeen or 
OpcodeInvestigationUnseen.
+        #   * Cleanup after 10 minutes.
+        # If it remains for more than <10> seconds, it it sent as part of
+        # OpcodeInvestigate with the next outbound packet with 
OpcodeReplyRequested set.
+        self.sent_messages = {}
+        # Seen inbound messages.  Added in the following conditions:
+        #   * Inbound packet with OpcodeReplyRequested set.
+        # Referenced in the following conditions:
+        #   * Inbound packet with it in OpcodeInvestigate.
+        # Removed in the following conditions:
+        #   * Inbound packet with it in OpcodeCourtesyExpiration.
+        #   * Cleanup after 10 minutes.
+        self.seen_messages = {}
+        # Courtesy messages waiting to be sent.  Added in the following 
conditions:
+        #   * Inbound packet with OpcodeInReplyTo set.
+        # Removed in the following conditions:
+        #   * Outbound packet where there is room to send it as part of 
OpcodeCourtesyExpiration.
+        #   * Cleanup after 2 minutes.
+        self.courtesy_messages = {}
+        # Current position of a peer tuple's incrementing ping integer.
+        self.ping_position = 0
+        # Current encrypted session ID
+        self.encrypted_session_id = None
+        # Seen encrypted session IVs
+        self.encrypted_session_ivs = {}
+        # Last time a peer was sent to or received from
+        self.last_seen = clock()
+
+
 class TwoPing():
     def __init__(self, args):
         now = clock()
@@ -168,6 +182,8 @@
                 else:
                     raise
 
+        self.is_reload = False
+
         if self.args.send_monotonic_clock and (not clock_info.monotonic):
             self.args.send_monotonic_clock = False
 
@@ -238,16 +254,10 @@
         peer_tuple = (socket_address, peer_address, sock.type)
 
         # Preload state tables if the client has not been seen (or has been 
cleaned).
-        if peer_tuple not in sock_class.seen_messages:
-            sock_class.seen_messages[peer_tuple] = {}
-        if peer_tuple not in sock_class.sent_messages:
-            sock_class.sent_messages[peer_tuple] = {}
-        if peer_tuple not in sock_class.courtesy_messages:
-            sock_class.courtesy_messages[peer_tuple] = {}
-        if peer_tuple not in sock_class.ping_positions:
-            sock_class.ping_positions[peer_tuple] = 0
-        if peer_tuple not in sock_class.encrypted_sessions:
-            sock_class.encrypted_sessions[peer_tuple] = None
+        if peer_tuple not in sock_class.peer_states:
+            sock_class.peer_states[peer_tuple] = PeerState(peer_tuple, 
sock_class)
+        peer_state = sock_class.peer_states[peer_tuple]
+        peer_state.last_seen = time_begin
 
         # Load/parse the packet.
         packet_in = packets.Packet()
@@ -277,24 +287,20 @@
             encrypted_packet_in = packet_in
             packet_in = packets.Packet()
             packet_in.load(data)
-            if sock_class.encrypted_sessions[peer_tuple] is None:
-                sock_class.encrypted_sessions[peer_tuple] = (
-                    time_begin,
-                    [],
-                    
encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].session,
-                )
-            if encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].session 
!= sock_class.encrypted_sessions[peer_tuple][2]:
+            if peer_state.encrypted_session_id is None:
+                peer_state.encrypted_session_id = 
encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].session
+            if encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].session 
!= peer_state.encrypted_session_id:
                 self.errors_received += 1
                 sock_class.errors_received += 1
                 self.print_out(
                     _('Encryption session mismatch from {address} (expected 
{expected}, got {got})').format(
                         address=peer_address[0],
-                        
expected=repr(sock_class.encrypted_sessions[peer_tuple][2]),
+                        expected=repr(peer_state.encrypted_session_id),
                         
got=repr(encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].session),
                     )
                 )
                 return
-            if encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].iv in 
sock_class.encrypted_sessions[peer_tuple][1]:
+            if encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].iv in 
peer_state.encrypted_session_ivs:
                 self.errors_received += 1
                 sock_class.errors_received += 1
                 self.print_out(
@@ -304,7 +310,7 @@
                     )
                 )
                 return
-            
sock_class.encrypted_sessions[peer_tuple][1].append(encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].iv)
+            
peer_state.encrypted_session_ivs[encrypted_packet_in.opcodes[packets.OpcodeEncrypted.id].iv]
 = (time_begin,)
             if self.args.verbose:
                 self.print_out('DECR: {}'.format(repr(packet_in)))
 
@@ -351,9 +357,9 @@
         if packets.OpcodeInReplyTo.id in packet_in.opcodes:
             replied_message_id = 
packet_in.opcodes[packets.OpcodeInReplyTo.id].message_id
             replied_message_id_int = nunpack(replied_message_id)
-            if replied_message_id_int in sock_class.sent_messages[peer_tuple]:
-                (sent_time, _unused, ping_position) = 
sock_class.sent_messages[peer_tuple][replied_message_id_int]
-                
del(sock_class.sent_messages[peer_tuple][replied_message_id_int])
+            if replied_message_id_int in peer_state.sent_messages:
+                (sent_time, _unused, ping_position) = 
peer_state.sent_messages[replied_message_id_int]
+                del(peer_state.sent_messages[replied_message_id_int])
                 calculated_rtt = (time_begin - sent_time) * 1000
                 self.pings_received += 1
                 sock_class.pings_received += 1
@@ -369,7 +375,7 @@
                         self.print_out(
                             _('{bytes} bytes from {address}: ping_seq={seq} 
time={ms:0.03f} ms peertime={peerms:0.03f} ms').format(
                                 bytes=len(data),
-                                address=peer_tuple[1][0],
+                                address=peer_state.peer_tuple[1][0],
                                 seq=ping_position,
                                 ms=calculated_rtt,
                                 
peerms=(packet_in.opcodes[packets.OpcodeRTTEnclosed.id].rtt_us / 1000.0),
@@ -379,7 +385,7 @@
                         self.print_out(
                             _('{bytes} bytes from {address}: ping_seq={seq} 
time={ms:0.03f} ms').format(
                                 bytes=len(data),
-                                address=peer_tuple[1][0],
+                                address=peer_state.peer_tuple[1][0],
                                 seq=ping_position,
                                 ms=calculated_rtt,
                             )
@@ -390,22 +396,22 @@
                     ):
                         notice = 
packet_in.opcodes[packets.OpcodeExtended.id].segments[packets.ExtendedNotice.id].text
                         self.print_out('  ' + _('Peer notice: 
{notice}').format(notice=notice))
-            sock_class.courtesy_messages[peer_tuple][replied_message_id_int] = 
(time_begin, replied_message_id)
+            peer_state.courtesy_messages[replied_message_id_int] = 
(time_begin, replied_message_id)
 
         # Check if any invesitgations results have come back.
-        self.check_investigations(sock_class, peer_tuple, packet_in)
+        self.check_investigations(peer_state, packet_in)
 
         # Process courtesy expirations
         if packets.OpcodeCourtesyExpiration.id in packet_in.opcodes:
             for message_id in 
packet_in.opcodes[packets.OpcodeCourtesyExpiration.id].message_ids:
                 message_id_int = nunpack(message_id)
-                if message_id_int in sock_class.seen_messages[peer_tuple]:
-                    del(sock_class.seen_messages[peer_tuple][message_id_int])
+                if message_id_int in peer_state.seen_messages:
+                    del(peer_state.seen_messages[message_id_int])
 
         # If the peer requested a reply, prepare one.
         if packets.OpcodeReplyRequested.id in packet_in.opcodes:
             # Populate seen_messages.
-            
sock_class.seen_messages[peer_tuple][nunpack(packet_in.message_id)] = time_begin
+            peer_state.seen_messages[nunpack(packet_in.message_id)] = 
(time_begin,)
 
             # Basic packet configuration.
             packet_out = self.base_packet()
@@ -427,7 +433,7 @@
             # Check for any investigations the peer requested.
             if packets.OpcodeInvestigate.id in packet_in.opcodes:
                 for message_id in 
packet_in.opcodes[packets.OpcodeInvestigate.id].message_ids:
-                    if nunpack(message_id) in 
sock_class.seen_messages[peer_tuple]:
+                    if nunpack(message_id) in peer_state.seen_messages:
                         if packets.OpcodeInvestigationSeen.id not in 
packet_out.opcodes:
                             
packet_out.opcodes[packets.OpcodeInvestigationSeen.id] = 
packets.OpcodeInvestigationSeen()
                         
packet_out.opcodes[packets.OpcodeInvestigationSeen.id].message_ids.append(message_id)
@@ -442,12 +448,12 @@
                 packet_out.opcodes[packets.OpcodeReplyRequested.id] = 
packets.OpcodeReplyRequested()
 
             # Send any investigations we would like to know about.
-            self.start_investigations(sock_class, peer_tuple, packet_out)
+            self.start_investigations(peer_state, packet_out)
 
             # Any courtesy expirations we have waiting should be sent.
-            if len(sock_class.courtesy_messages[peer_tuple]) > 0:
+            if len(peer_state.courtesy_messages) > 0:
                 packet_out.opcodes[packets.OpcodeCourtesyExpiration.id] = 
packets.OpcodeCourtesyExpiration()
-                for (courtesy_time, courtesy_message_id) in 
sock_class.courtesy_messages[peer_tuple].values():
+                for (courtesy_time, courtesy_message_id) in 
peer_state.courtesy_messages.values():
                     
packet_out.opcodes[packets.OpcodeCourtesyExpiration.id].message_ids.append(courtesy_message_id)
 
             # Calculate the host latency as late as possible.
@@ -478,11 +484,11 @@
             if packets.OpcodeReplyRequested.id in packet_out.opcodes:
                 self.pings_transmitted += 1
                 sock_class.pings_transmitted += 1
-                sock_class.ping_positions[peer_tuple] += 1
-                
sock_class.sent_messages[peer_tuple][nunpack(packet_out.message_id)] = (
+                peer_state.ping_position += 1
+                peer_state.sent_messages[nunpack(packet_out.message_id)] = (
                     time_send,
                     packet_out.message_id,
-                    sock_class.ping_positions[peer_tuple]
+                    peer_state.ping_position
                 )
 
             # Examine the sent packet.
@@ -493,8 +499,8 @@
             if packets.OpcodeCourtesyExpiration.id in 
packet_out_examine.opcodes:
                 for courtesy_message_id in 
packet_out_examine.opcodes[packets.OpcodeCourtesyExpiration.id].message_ids:
                     courtesy_message_id_int = nunpack(courtesy_message_id)
-                    if courtesy_message_id_int in 
sock_class.courtesy_messages[peer_tuple]:
-                        
del(sock_class.courtesy_messages[peer_tuple][courtesy_message_id_int])
+                    if courtesy_message_id_int in peer_state.courtesy_messages:
+                        
del(peer_state.courtesy_messages[courtesy_message_id_int])
 
             if self.args.verbose:
                 if self.args.encrypt:
@@ -517,16 +523,16 @@
         except socket.error as e:
             self.handle_socket_error(e, sock_class, peer_address=address)
 
-    def start_investigations(self, sock_class, peer_tuple, packet_check):
-        if len(sock_class.sent_messages[peer_tuple]) == 0:
+    def start_investigations(self, peer_state, packet_check):
+        if len(peer_state.sent_messages) == 0:
             return
         if packets.OpcodeInvestigate.id in packet_check.opcodes:
             iobj = packet_check.opcodes[packets.OpcodeInvestigate.id]
         else:
             iobj = None
         now = clock()
-        for message_id_str in sock_class.sent_messages[peer_tuple]:
-            (sent_time, message_id, _unused) = 
sock_class.sent_messages[peer_tuple][message_id_str]
+        for message_id_str in peer_state.sent_messages:
+            (sent_time, message_id, _unused) = 
peer_state.sent_messages[message_id_str]
             if now >= (sent_time + self.args.inquire_wait):
                 if iobj is None:
                     iobj = packets.OpcodeInvestigate()
@@ -535,32 +541,32 @@
         if iobj is not None:
             packet_check.opcodes[packets.OpcodeInvestigate.id] = iobj
 
-    def check_investigations(self, sock_class, peer_tuple, packet_check):
+    def check_investigations(self, peer_state, packet_check):
         found = {}
 
         # Inbound
         if packets.OpcodeInvestigationSeen.id in packet_check.opcodes:
             for message_id in 
packet_check.opcodes[packets.OpcodeInvestigationSeen.id].message_ids:
                 message_id_int = nunpack(message_id)
-                if message_id_int not in sock_class.sent_messages[peer_tuple]:
+                if message_id_int not in peer_state.sent_messages:
                     continue
-                (_unused, _unused, ping_seq) = 
sock_class.sent_messages[peer_tuple][message_id_int]
-                found[ping_seq] = ('inbound', peer_tuple[1][0])
-                del(sock_class.sent_messages[peer_tuple][message_id_int])
+                (_unused, _unused, ping_seq) = 
peer_state.sent_messages[message_id_int]
+                found[ping_seq] = ('inbound', peer_state.peer_tuple[1][0])
+                del(peer_state.sent_messages[message_id_int])
                 self.lost_inbound += 1
-                sock_class.lost_inbound += 1
+                peer_state.sock_class.lost_inbound += 1
 
         # Outbound
         if packets.OpcodeInvestigationUnseen.id in packet_check.opcodes:
             for message_id in 
packet_check.opcodes[packets.OpcodeInvestigationUnseen.id].message_ids:
                 message_id_int = nunpack(message_id)
-                if message_id_int not in sock_class.sent_messages[peer_tuple]:
+                if message_id_int not in peer_state.sent_messages:
                     continue
-                (_unused, _unused, ping_seq) = 
sock_class.sent_messages[peer_tuple][message_id_int]
-                found[ping_seq] = ('outbound', peer_tuple[1][0])
-                del(sock_class.sent_messages[peer_tuple][message_id_int])
+                (_unused, _unused, ping_seq) = 
peer_state.sent_messages[message_id_int]
+                found[ping_seq] = ('outbound', peer_state.peer_tuple[1][0])
+                del(peer_state.sent_messages[message_id_int])
                 self.lost_outbound += 1
-                sock_class.lost_outbound += 1
+                peer_state.sock_class.lost_outbound += 1
 
         if self.args.quiet:
             return
@@ -585,6 +591,12 @@
                     ))
 
     def setup_listener(self):
+        # If called idempotently, destroy all listeners first
+        for sock_class in self.sock_classes:
+            self.poller.unregister(sock_class)
+            sock_class.sock.close()
+
+        self.sock_classes = []
         bound_addresses = []
         if self.args.all_interfaces:
             if not has_netifaces:
@@ -745,14 +757,14 @@
         sock = sock_class.sock
         socket_address = sock.getsockname()
         peer_tuple = (socket_address, peer_address, sock.type)
-        if peer_tuple not in sock_class.sent_messages:
-            sock_class.sent_messages[peer_tuple] = {}
-        if peer_tuple not in sock_class.ping_positions:
-            sock_class.ping_positions[peer_tuple] = 0
+        if peer_tuple not in sock_class.peer_states:
+            sock_class.peer_states[peer_tuple] = PeerState(peer_tuple, 
sock_class)
+        peer_state = sock_class.peer_states[peer_tuple]
+        peer_state.last_seen = clock()
 
         packet_out = self.base_packet()
         packet_out.opcodes[packets.OpcodeReplyRequested.id] = 
packets.OpcodeReplyRequested()
-        self.start_investigations(sock_class, peer_tuple, packet_out)
+        self.start_investigations(peer_state, packet_out)
         dump_out = packet_out.dump()
 
         # If enabled, encrypt the packet and wrap it in a stub packet.
@@ -772,11 +784,11 @@
         sock_class.packets_transmitted += 1
         self.pings_transmitted += 1
         sock_class.pings_transmitted += 1
-        sock_class.ping_positions[peer_tuple] += 1
-        sock_class.sent_messages[peer_tuple][nunpack(packet_out.message_id)] = 
(
+        peer_state.ping_position += 1
+        peer_state.sent_messages[nunpack(packet_out.message_id)] = (
             now,
             packet_out.message_id,
-            sock_class.ping_positions[peer_tuple]
+            peer_state.ping_position
         )
         packet_out_examine = packets.Packet()
         packet_out_examine.load(dump_out)
@@ -807,6 +819,10 @@
     def sigquit_handler(self, signum, frame):
         self.print_stats(short=True)
 
+    def sighup_handler(self, signum, frame):
+        self.print_debug('Received SIGHUP, scheduling reload')
+        self.is_reload = True
+
     def stats_time(self, seconds):
         conversion = (
             (1000, 'ms'),
@@ -964,6 +980,8 @@
         self.print_debug('Poller: {}'.format(self.poller.poller_type))
         if hasattr(signal, 'SIGQUIT'):
             signal.signal(signal.SIGQUIT, self.sigquit_handler)
+        if hasattr(signal, 'SIGHUP'):
+            signal.signal(signal.SIGHUP, self.sighup_handler)
 
         try:
             if self.args.listen:
@@ -1021,36 +1039,23 @@
 
     def scheduled_cleanup_sock_class(self, sock_class):
         now = clock()
-        for peer_tuple in tuple(sock_class.sent_messages.keys()):
-            for message_id_int in 
tuple(sock_class.sent_messages[peer_tuple].keys()):
-                if now > 
(sock_class.sent_messages[peer_tuple][message_id_int][0] + 600.0):
-                    del(sock_class.sent_messages[peer_tuple][message_id_int])
-                    self.print_debug('Cleanup: Removed sent_messages {} 
{}'.format(repr(peer_tuple), message_id_int))
-            if len(sock_class.sent_messages[peer_tuple]) == 0:
-                del(sock_class.sent_messages[peer_tuple])
-                self.print_debug('Cleanup: Removed sent_messages empty 
{}'.format(repr(peer_tuple)))
-        for peer_tuple in tuple(sock_class.seen_messages.keys()):
-            for message_id_int in 
tuple(sock_class.seen_messages[peer_tuple].keys()):
-                if now > (sock_class.seen_messages[peer_tuple][message_id_int] 
+ 600.0):
-                    del(sock_class.seen_messages[peer_tuple][message_id_int])
-                    self.print_debug('Cleanup: Removed seen_messages {} 
{}'.format(repr(peer_tuple), message_id_int))
-            if len(sock_class.seen_messages[peer_tuple]) == 0:
-                del(sock_class.seen_messages[peer_tuple])
-                self.print_debug('Cleanup: Removed seen_messages empty 
{}'.format(repr(peer_tuple)))
-        for peer_tuple in tuple(sock_class.courtesy_messages.keys()):
-            for message_id_int in 
tuple(sock_class.courtesy_messages[peer_tuple].keys()):
-                if now > 
(sock_class.courtesy_messages[peer_tuple][message_id_int][0] + 120.0):
-                    
del(sock_class.courtesy_messages[peer_tuple][message_id_int])
-                    self.print_debug('Cleanup: Removed courtesy_messages {} 
{}'.format(repr(peer_tuple), message_id_int))
-            if len(sock_class.courtesy_messages[peer_tuple]) == 0:
-                del(sock_class.courtesy_messages[peer_tuple])
-                self.print_debug('Cleanup: Removed courtesy_messages empty 
{}'.format(repr(peer_tuple)))
-        for peer_tuple in tuple(sock_class.encrypted_sessions.keys()):
-            if sock_class.encrypted_sessions[peer_tuple] is None:
+        for peer_tuple in tuple(sock_class.peer_states.keys()):
+            peer_state = sock_class.peer_states[peer_tuple]
+            if now > peer_state.last_seen + 600.0:
+                del(sock_class.peer_states[peer_tuple])
+                self.print_debug('Cleanup: Removed 
{}'.format(repr(peer_tuple)))
                 continue
-            if now > (sock_class.encrypted_sessions[peer_tuple][0] + 600.0):
-                del(sock_class.encrypted_sessions[peer_tuple])
-                self.print_debug('Cleanup: Removed encrypted_sessions 
{}'.format(repr(peer_tuple)))
+            for table_name, max_time in (
+                ('sent_messages', 600.0),
+                ('seen_messages', 600.0),
+                ('courtesy_messages', 120.0),
+                ('encrypted_session_ivs', 600.0),
+            ):
+                table = getattr(peer_state, table_name)
+                for table_key_name in tuple(table.keys()):
+                    if now > (table[table_key_name][0] + max_time):
+                        del(table[table_key_name])
+                        self.print_debug('Cleanup: Removed {} {} 
{}'.format(repr(peer_tuple), table_name, table_key_name))
 
     def new_socket(self, family, type, bind):
         sock = socket.socket(family, type)
@@ -1150,6 +1155,11 @@
             if all_shutdown:
                 self.shutdown()
 
+            if self.is_reload:
+                self.is_reload = False
+                if self.args.listen:
+                    self.setup_listener()
+
 
 def main():
     args = parse_args()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/2ping-4.1.2/twoping/packets.py 
new/2ping-4.2/twoping/packets.py
--- old/2ping-4.1.2/twoping/packets.py  2018-08-10 05:29:17.000000000 +0200
+++ new/2ping-4.2/twoping/packets.py    2018-08-11 23:06:16.000000000 +0200
@@ -169,7 +169,7 @@
         return '<Batteries ({}): [{}]>'.format(
             len(self.batteries),
             ', '.join(
-                ['{}: {:0.03f}%'.format(x, (self.batteries[x] / 65535.0 * 
100.0)) for x in sorted(self.batteries)]
+                ['{}: {:0.03%}'.format(x, self.batteries[x] / 65535.0) for x 
in sorted(self.batteries)]
             ),
         )
 



Reply via email to