python multithreaded sniffer- exit from thread - python

I have created a packet sniffer in python using scapy but kind of stuck in the multithreaded stuff..
def sniffer(ip):
filter_str = "icmp and host " + ip
packets=sniff(filter=filter_str,count=20)
status= False
for p in packets:
packet_load=str(p['Raw'].load)
if packet_load.find("##")!= -1:
status=True
log_thread = Thread(target=logger,args=(packets,))
log_thread.start()
log_thread.join()
break
if status==True:
print "Suspicious Packets sniffed!!"
user_ip = raw_input("Do you want to continue sniffing???(y/n)")
while 1:
if user_ip=="y" or user_ip=="Y":
new_thread = Thread(target=sniffer, args=(ip,))
new_thread.start()
new_thread.join()
else:
#need somthing to quit the program
return
Here, my sniffer sniffs 20 packets at a time and waits for user input for further sniffing.
However if the user enters 'n' as input, then the program hangs. Ideally I would want the program to quit if the user enters 'n'. Can I know what I'm doing wrong here??

while 1 is rarely a good choice when writing a finite loop. Try using flags instead:
leaving = False
while not leaving:
user_ip = raw_input("Do you want to continue sniffing???(y/n)")
if user_ip.lower() == 'y':
new_thread = Thread(target=sniffer, args=(ip,))
new_thread.start()
new_thread.join()
elif user_ip.lower() == 'n':
print "Leaving sniffer"
leaving = True
return

Related

Is there a "better" way to do an online check with retry logic with anti-flapping? (Python)

I've got a network device that doesn't hold its WiFi connection brilliantly and occasionally drops off the network completely. Although there are dedicated network monitoring tools out there, I thought it would be a nice exercise to write a small monitoring script in Python.
I want to check the status of the device once per minute with an ICMP echo. Because the network connection is a little unreliable, I'll ignore short drop-outs and so will try up to three times to get a positive response.
Additionally, because the device can sometimes reboot, I want to ignore outages of up to two or three minutes. Once the device has missed three checks, I'll send a message to myself saying it's offline. Similarly, once it has been back online for three checks I'll send a message saying it's back online.
The following code is a test of the logic I came up with; I've applied this to the actual script and it does seem to do the job. However, it seems clunky and I'm sure there's some clever Pythonic way of doing things that I haven't thought of. Note that I'm posting this rather than the full script since this can be executed standalone and doesn't have any real network dependencies.
How can I improve this code so that it's more compact and Pythonic? Thanks!
"""Test ping logic"""
import time
def ping_device(iter_count):
"""Fake ping device function"""
# Pretend that this function tries up to three times to get a good ping response :)
if iter_count == 5:
response = False
elif 11 <= iter_count <= 14:
response = False
else:
response = True
return response
def main():
"""Main functions"""
previous_status = True
current_status_count = 0
adjusted_status = True
previous_adjusted = True
iteration_counter = 0
while True:
iteration_counter += 1
print(f"Pinging iteration {iteration_counter}... ", end="")
status = ping_device(iteration_counter)
if status:
print("OK")
else:
print("FAIL")
if status != previous_status:
current_status_count = 0
previous_status = status
else:
current_status_count += 1
if current_status_count > 2:
adjusted_status = status
if adjusted_status != previous_adjusted:
previous_adjusted = adjusted_status
if status:
print("***** Device is online *****")
else:
print("!!!!! Device is offline !!!!!")
print(f"---> Current status count is {current_status_count}")
time.sleep(1)
if __name__ == "__main__":
main()
In the actual monitoring script, the ping/retry logic looks like this:
for attempt in range(RETRIES + 1):
ping_response = ping(MONITOR_HOST)
if status is None:
if ping_response:
status = True
previous_status = True
adjusted_status = True
previous_adjusted = True
send_telegram("Current status is online.")
break
else:
status = False
previous_status = False
adjusted_status = False
previous_adjusted = False
send_telegram("Current status is offline.")
else:
if ping_response:
status = True
break
else:
status = False
As well as doing the retries, this handles sending an initial message telling me if the device is online or offline when monitoring is started (status is None on start). Note that I use 'attempt' rather than '_' in the loop as I do log the attempt number.

Run a loop while waiting for a user input

I want to run a loop in my script while the user has not input anything. But when they have input something I want the loop to break.
The issue I am currently having is that when using the input() function, the script will stop and wait for an input, but I want to run another part of the script while waiting for the user input.
I have tried using try: with a raw_input():
while True:
try:
print('SCAN BARCODE')
userInput= raw_input()
#doing something with input
except:
#run this while there is no input
With this, I find that whatever is in the except: will always run, but it will not run try: even when there is a user input. If I change raw_input() to input() the script just waits at input() and doesn't run anything in the except:.
How do I achieve what I am after?
you can use python threads:
from threading import Thread
import time
thread_running = True
def my_forever_while():
global thread_running
start_time = time.time()
# run this while there is no input
while thread_running:
time.sleep(0.1)
if time.time() - start_time >= 5:
start_time = time.time()
print('Another 5 seconds has passed')
def take_input():
user_input = input('Type user input: ')
# doing something with the input
print('The user input is: ', user_input)
if __name__ == '__main__':
t1 = Thread(target=my_forever_while)
t2 = Thread(target=take_input)
t1.start()
t2.start()
t2.join() # interpreter will wait until your process get completed or terminated
thread_running = False
print('The end')
In my example you have 2 threads, the first thread is up and executes code until you have some input from the user, thread 2 is waiting for some input from the user. After you got the user input thread 1 and 2 will stop.
It simple bro u use flag boolean values
Flag = True
while Flag:
try:
Print('scan bar code')
User_inp = input()
if User_inp != '':
Flag = False
Except:
Print('except part')
I suggest you to look for select
it allow you to check if a file descriptor is ready for read/write/expect operation

Dynamically changing the message of raw_input

I'm looking to move a motorised slider using a Raspberry Pi. However, while debugging the system I was wondering if it is possible to use:
target = int(raw_input(<message>))
In a way that message could dynamically change before the user inputs a value. For me, it would be great to see the current value that is read from the slider in this <message> for example.
And if that isn't possible, is it possible to have a line printed above or below the raw_input that remains changing while the system waits for the users' input?
You can find that as a non-blocking input.
Here is a solution from stack overflow, which uses threads
I did a little modified solution, it still needs some tweaking, but its more or less what you have to do.
python
import threading
import time
import random
userInput = ""
finished = False
sensorValue = 100
previousValue = 0
def Listener():
global userInput, finished, sensorValue
userInput = raw_input(sensorValue)
if len(userInput) > 0:
print(len(userInput))
finished = True
else:
finished = False
while True:
if sensorValue != previousValue:
print("Received new slider info. SliderValue is {}".format(sensorValue))
previousValue = sensorValue
else:
print("No new info from slider. Sleeping two seconds.")
if not finished:
listener = threading.Thread(target=Listener)
listener.start()
else:
break
if random.randint(0,1) == 1:
sensorValue += 10
time.sleep(2)
See if that answers your question! :)

How to kill old thread and start new thread?

I'm just start learning about python and I have problem with my project to blink LED. when I get new message and start new thread. The old thread is still running.
I want to kill old thread and start new thread. How to solve my problem?
(Sorry if I'm not good in english but I'm trying)
def led_action(topic,message):
print topic+" "+message
if message == 'OFF':
#state = False
print ("Stoping...")
while message == 'OFF':
GPIO.output(8,GPIO.LOW)
elif message == 'ON':
#state = True
print ("Opening...")
while message == 'ON':
GPIO.output(8,GPIO.HIGH) #Set LED pin 8 to HIGH
time.sleep(1) #Delay 1 second
GPIO.output(8,GPIO.LOW) #Set LED pin 8 to LOW
time.sleep(1)
# Get message form NETPIE and Do something
def subscription(topic,message):
set = thread.start_new_thread(led_action, (topic,message))
def connection():
print "Now I am connected with netpie"
def disconnect():
print "disconnect is work"
microgear.setalias("test")
microgear.on_connect = connection
microgear.on_message = subscription
microgear.on_disconnect = disconnect
microgear.subscribe("/mails")
microgear.connect(True)
To terminate a python thread you need to exit your function. You can do this by removing your while message == 'ON'/'OFF' checks. As message doesn't change anyways (it is passed to the function led_action) those checks are unnecessary.

Pause and resume a running script in Python 3.42 in Windows

I'm new to Python and have been googling for a couple of days and read all I can find on this forum. Might be that I don't understand it all but I haven't found a solution to my problem yet. Ask for forgiveness already if there's an answer already to my problem, then I haven't understood it.
I want to make a Pause function for my program Tennismatch. The program will when it's being run print the score of a tennis match like this: "15-0, 15-15 etc ongoing till the match ends. It will print the score line by line.
I want the user to be able to pause after x number of balls, games, etc. So I don't know when the user wants to pause and after the user has paused I want the user to be able to resume the tennismatch where it was.
Have seen the time.sleep() but as I have understood it you must know when you want to pause to use this and it also ain't an indefinetie pause like I want. With input() it's the same.
Am going to make a GUI later on when the code is finished. Happy for anything that leads me to solving my problem.
I use Windows and Python 3.42 and run the program in Shell.
A piece of the code (haven't written it all yet, it's more of a general situation when something is being printed line after line for some time and want to be able do pause in the CIL:
#self.__points = [0,0]
def playGame(self):
if self.server == True: #self.server is either True or False when someone calls playGame()
server = self.player_1.get_win_serve() #self.player_1 = an object of a class Player():
else:
server = self.player_2.get_win_serve() #get_win_serve() method returns the probability to win his serv (1-0)
while (0 < self.__points[0] - self.__points[1] >= 2 or 0 < self.__points[1] - self.__points[0] >= 2) and (self.__points[1] >= 4 or self.__points[0] >= 4):
x = random.uniform(0,1)
if x > 0 and x < server:
self.__points[0] += 1
else:
self.__points[1] += 1
# print('The score, by calling a score() function that I haven't written yet')
For dealing with events in main loop you need to make a separated thread which capture input or any other event.
import sys
from sys import stdin
from time import sleep
from threading import Thread
from Queue import Queue, Empty
def do_something():
sleep(1)
print 42
def enqueue_output(queue):
while True:
# reading line from stdin and pushing to shared queue
input = stdin.readline()
print "got input ", input
queue.put(input)
queue = Queue()
t = Thread(target=enqueue_output, args=(queue,))
t.daemon = True
t.start()
pause = False
try:
while True:
try:
command = queue.get_nowait().strip()
print 'got from queue ', command
except Empty:
print "queue is empty"
command = None
if command:
if command == 'p':
pause = True
if command == 'u':
pause = False
if not pause:
print pause
do_something()
except KeyboardInterrupt:
sys.exit(0)
I came up with the following.
while True:
try:
## Keep doing something here
## your regular code
print '.',
except KeyboardInterrupt:
## write or call pause function which could be time.sleep()
print '\nPausing... (Hit ENTER to continue, type quit to exit.)'
try:
response = raw_input()
if response.lower() == 'quit':
break
print 'Quitting...'
except KeyboardInterrupt:
print 'Resuming...'
continue
The Event loop might as well be the code I wrote with.
I don't see any user input so I assume that x emulates it. To pause the game if x < 0.1 and to unpause(/resume) it if x > 0.9, you could:
while your_condition(self.__points):
x = random.random()
if x < 0.1: # pause
self.pause()
elif x > 0.9: # resume
self.resume()
if self.is_paused:
continue # do nothing else only wait for input (`x`)
# assume your_condition() has no side-effects
# here's what the resumed version does:
print("...")
# change self.__points, etc
where pause(), resume(), is_paused() methods could be implemented as:
def __init__(self):
self.is_paused = False
def pause(self):
self.is_paused = True
def resume(self):
self.is_paused = False
as you can see the implementation is very simple.

Categories