@@ -52,6 +52,9 @@ def send(self, source_socket):
5252 :type source_socket: network.Socket"""
5353 source_socket .send (self .packet .packet )
5454
55+ def __repr__ (self ):
56+ return repr (self .packet )
57+
5558
5659def represent_seconds_in_ms (seconds ):
5760 """Converts seconds into human-readable milliseconds with 2 digits decimal precision
@@ -65,15 +68,21 @@ def represent_seconds_in_ms(seconds):
6568
6669class Response :
6770 """Represents a response to an ICMP message, with metadata like timing"""
68- def __init__ (self , message , time_elapsed ):
71+ def __init__ (self , message , time_elapsed , source_request = None , repr_format = None ):
6972 """Creates a representation of ICMP message received in response
7073
7174 :param message: The message received
7275 :type message: Union[None, Message]
7376 :param time_elapsed: Time elapsed since the original request was sent, in seconds
74- :type time_elapsed: float"""
77+ :type time_elapsed: float
78+ :param source_request: ICMP packet represeting the request that originated this response
79+ :type source_request: ICMP
80+ :param repr_format: How to __repr__ the response. Allowed: legacy, None
81+ :type repr_format: str"""
7582 self .message = message
7683 self .time_elapsed = time_elapsed
84+ self .source_request = source_request
85+ self .repr_format = repr_format
7786
7887 @property
7988 def success (self ):
@@ -119,17 +128,31 @@ def error_message(self):
119128 def time_elapsed_ms (self ):
120129 return represent_seconds_in_ms (self .time_elapsed )
121130
122- def __repr__ (self ):
131+ def legacy_repr (self ):
123132 if self .message is None :
124133 return 'Request timed out'
125134 elif self .success :
126135 return 'Reply from {0}, {1} bytes in {2}ms' .format (self .message .source ,
127- len (self .message .packet .payload ),
136+ len (self .message .packet .raw ),
128137 self .time_elapsed_ms )
129138 else :
130139 # Not successful, but with some code (e.g. destination unreachable)
131140 return '{0} from {1} in {2}ms' .format (self .error_message , self .message .source , self .time_elapsed_ms )
132141
142+ def __repr__ (self ):
143+ if self .repr_format == 'legacy' :
144+ return self .legacy_repr ()
145+ if self .message is None :
146+ return 'Timed out'
147+ elif self .success :
148+ return 'status=OK\t from={0}\t ms={1}\t \t bytes\t snt={2}\t rcv={3}' .format (
149+ self .message .source ,
150+ self .time_elapsed_ms ,
151+ len (self .source_request .raw )+ 20 ,
152+ len (self .message .packet .raw )
153+ )
154+ else :
155+ return 'status=ERR\t from={1}\t error="{0}"' .format (self .message .source , self .error_message )
133156
134157class ResponseList :
135158 """Represents a series of ICMP responses"""
@@ -228,7 +251,7 @@ def __iter__(self):
228251class Communicator :
229252 """Instance actually communicating over the network, sending messages and handling responses"""
230253 def __init__ (self , target , payload_provider , timeout , interval , socket_options = (), seed_id = None ,
231- verbose = False , output = sys .stdout ):
254+ verbose = False , output = sys .stdout , repr_format = None ):
232255 """Creates an instance that can handle communication with the target device
233256
234257 :param target: IP or hostname of the remote device
@@ -246,13 +269,16 @@ def __init__(self, target, payload_provider, timeout, interval, socket_options=(
246269 :param verbose: Flag to enable verbose mode, defaults to False
247270 :type verbose: bool
248271 :param output: File where to write verbose output, defaults to stdout
249- :type output: file"""
272+ :type output: file
273+ :param repr_format: How to __repr__ the response. Allowed: legacy, None
274+ :type repr_format: str"""
250275 self .socket = network .Socket (target , 'icmp' , source = None , options = socket_options )
251276 self .provider = payload_provider
252277 self .timeout = timeout
253278 self .interval = interval
254279 self .responses = ResponseList (verbose = verbose , output = output )
255280 self .seed_id = seed_id
281+ self .repr_format = repr_format
256282 # note that to make Communicator instances thread safe, the seed ID must be unique per thread
257283 if self .seed_id is None :
258284 self .seed_id = os .getpid () & 0xFFFF
@@ -269,15 +295,15 @@ def send_ping(self, packet_id, sequence_number, payload):
269295 :type sequence_number: int
270296 :param payload: The payload of the ICMP message
271297 :type payload: Union[str, bytes]
272- :rtype: bytes """
298+ :rtype: ICMP """
273299 i = icmp .ICMP (
274300 icmp .Types .EchoRequest ,
275301 payload = payload ,
276302 identifier = packet_id , sequence_number = sequence_number )
277303 self .socket .send (i .packet )
278- return i . payload
304+ return i
279305
280- def listen_for (self , packet_id , timeout , payload_pattern = None ):
306+ def listen_for (self , packet_id , timeout , payload_pattern = None , source_request = None ):
281307 """Listens for a packet of a given id for a given timeout
282308
283309 :param packet_id: The ID of the packet to listen for, the same for request and response
@@ -307,8 +333,8 @@ def listen_for(self, packet_id, timeout, payload_pattern=None):
307333 payload_matched = (payload_pattern == response .payload )
308334
309335 if payload_matched :
310- return Response (Message ('' , response , source_socket [0 ]), timeout - time_left )
311- return Response (None , timeout )
336+ return Response (Message ('' , response , source_socket [0 ]), timeout - time_left , source_request , repr_format = self . repr_format )
337+ return Response (None , timeout , source_request , repr_format = self . repr_format )
312338
313339 @staticmethod
314340 def increase_seq (sequence_number ):
@@ -332,11 +358,11 @@ def run(self, match_payloads=False):
332358 identifier = self .seed_id
333359 seq = 1
334360 for payload in self .provider :
335- payload_bytes_sent = self .send_ping (identifier , seq , payload )
361+ icmp_out = self .send_ping (identifier , seq , payload )
336362 if not match_payloads :
337- self .responses .append (self .listen_for (identifier , self .timeout ))
363+ self .responses .append (self .listen_for (identifier , self .timeout , None , icmp_out ))
338364 else :
339- self .responses .append (self .listen_for (identifier , self .timeout , payload_bytes_sent ))
365+ self .responses .append (self .listen_for (identifier , self .timeout , icmp_out . payload , icmp_out ))
340366
341367 seq = self .increase_seq (seq )
342368
0 commit comments