pythonwiresharkpyshark

Why does PyShark continue a LiveCapture with a timeout?


I mean, I suppose PyShark continues listening. My code is (within a class):

 def Capture(self, incoming):

    capture = pyshark.LiveCapture()
    capture.sniff(timeout=int(incoming))
    print('TIMEOUT: ' + str(int(incoming)))
    print(capture)

    print("Len" + str(len(capture)))
    pktList = [] 
    count=0
    for pkt in capture:
        count=count+1
        pktList.append([int(pkt.layers[1].version), pkt.layers[2].layer_name, pkt.length])
        print(f"Saved packet #{count}")
        print(pktList)
    print("Job is done.")

Output shows that despite after the timeout of 2 seconds the capture consists of a single packet, the program somehow continues reading some data. Output:

TIMEOUT: 2
<LiveCapture (0 packets)>
Len 0
Saved packet #1
[[4, 'tcp', '108']]
Saved packet #2
[[4, 'tcp', '108'], [4, 'tcp', '112']]
Saved packet #3
[[4, 'tcp', '108'], [4, 'tcp', '112'], [4, 'tcp', '108']]
Saved packet #4
[[4, 'tcp', '108'], [4, 'tcp', '112'], [4, 'tcp', '108'], [4, 'tcp', '112']]
Saved packet #5
[[4, 'tcp', '108'], [4, 'tcp', '112'], [4, 'tcp', '108'], [4, 'tcp', '112'], [4, 'tcp', '54']]

...............

How can I fix it?


Solution

  • I tried to use your code, but I couldn't get it to work correctly.

    I know that there are some known issues with the way that capture.sniff(timeout=x) works, so I put together some other code that is using apply_on_packets with a timeout.

    import pyshark
    import asyncio
    
    packet_list = []
    
    
    def process_packets(packet):
        global packet_list
        try:
            packet_version = packet.layers[1].version
            layer_name = packet.layers[2].layer_name
            packet_list.append(f'{packet_version}, {layer_name}, {packet.length}')
        except AttributeError:
            pass
    
    
    def capture_packets(timeout):
        capture = pyshark.LiveCapture(interface='en0')
        try:
          capture.apply_on_packets(process_packets, timeout=timeout)
        except asyncio.TimeoutError:
            pass
        finally:
            global packet_list
            for item in packet_list:
                print(item)
    
    
    capture_packets(2)
    

    I decided to rework your code. The code below works with capture.sniff(timeout=x).

    import pyshark
    
    packet_list = []
    
    def capture_packets(timeout):
        global packet_list
    
        capture = pyshark.LiveCapture(interface='en0')
        capture.sniff(timeout=timeout)
        packets = [pkt for pkt in capture._packets]
        capture.close()
    
        try:
            for packet in packets:
                packet_version = packet.layers[1].version
                layer_name = packet.layers[2].layer_name
                packet_list.append(f'{packet_version}, {layer_name}, {packet.length}')
        except AttributeError:
            pass
        finally:
            return packet_list
    
    
    packets = capture_packets(2)
    print(packets)
    ['4, tcp, 54', '6, icmpv6, 86', '6, icmpv6, 78', '4, tcp, 66']
    

    I will answer any questions you have about the code examples above.

    ----------------------------------------
    My system information
    ----------------------------------------
    Platform:    macOS
    Python:      3.8.0
    Pyshark:     0.4.3
    ----------------------------------------