I am creating a network bridge that connects two ethernet cards on the same machine. One of the cards is connected to the LAN and the other is connected to a network device. It looks something like this,
I am sniffing packets on both the interfaces and then sending them to the other using sendp(x,iface='eth0') for a packet that I sniffed on eth1 and vice versa.
I verified the packets at both the interfaces and found them to be correct, but somehow I am unable to get an IP for the device.
Below is a piece of my code, I create two threads, one for each interface:
from scapy.all import*
**THREAD1:**
pkt=sniff(iface="eth0",store=1,count=1)
outbuff=[]
outbuff+=pkt[:]
for src in outbuff[:]
srcmac=src.sprintf(r"%Ether.src%")
if srcmac==deviceMAC:
pass
else:
sendp(self.outbuff[:],iface="eth1",verbose=0)
**THREAD2:**
pkt=sniff(iface="eth1",store=1,count=1)
outbuff=[]
outbuff+=pkt[:]
for src in outbuff[:]
srcmac=src.sprintf(r"%Ether.src%")
if srcmac==deviceMAC:
sendp(self.outbuff[:],iface="eth1",verbose=0)
else:
pass
Can some one help me with the problem or suggest me an alternative solution for this implementation?
SOLVED: Combining Python+IPTABLES and using the principles of TRIGGER solves this problem.
Posting a snippet of the bridging class
from threading import Thread
import threading
import socket
import thread
class iface0(threading.Thread):
def __init__(self, MAC):
Thread.__init__(self)
pass
def run(self):
self.a = socket.gethostbyname_ex(socket.gethostname())[2]
while 1:
self.sSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.sSock.bind((self.a[1],23432))
self.iface0_sniff()
self.sSock.close()
def iface0_sniff(self):
self.sSock.sendto("THISISATESTWORLD",(self.a[1],78456))
data = ''
class iface1(threading.Thread):
def __init__(self,MAC):
Thread.__init__(self)
pass
def run(self):
self.a=socket.gethostbyname_ex(socket.gethostname())[2]
while 1:
self.sSock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
self.iface1_sniff()
self.sSock.close()
def iface1_sniff(self):
self.sSock.sendto("THISISATESTWORLD",(self.a[1],98658))
data = ''
if __name__ == '__main__':
MAC = ['XX:XX:XX:XX:XX:XX']
iface0 = iface0(MAC)
iface1 = iface1(MAC)
iface1.start()
iface0.start()
Related
we ran into a weird issue when receiving ZigBee packets on Windows.
We are currently sending packets from a drone every 0.8s, but on Windows we are receiving only every ~5s. We aren't loosing packets, as the received packet ID's increment correctly.
The strange thing is, when using an Ubuntu VM on the same computer it works perfectly, and we receive at about ~0.8s.
We are using Digi-Xbee 1.4 and a "Xbee SMT Grove Dev Board" connected by USB for both sending and receiving.
Here is the code were using to receive on both Windows and Ubuntu:
def connect(self):
self._device = XBeeDevice(self._port, self._baudRate)
self._device.open()
self._device.set_16bit_addr(XBee16BitAddress(utils.int_to_bytes(int(self._address))))
self._network = self._device.get_network()
self._device.add_packet_received_callback(self._packetReceivedCallback)
def _packetReceivedCallback(self, packet):
print("Received!")
#Processing after this
Has anyone encountered this behavior before?
Ok, in case anyone runs into the same issue, we solved it by basically implementing our own serial interface. This method is extremely basic and if you need more advanced features of Digi-Xbee Python, it probably won't help you.
In our case we are sending json.dumps() as the data, so we can seperate it by the {}. You might need to change it for other data types.
from digi.xbee.models.options import TransmitOptions
from digi.xbee.models.address import XBee64BitAddress
from digi.xbee.exception import XBeeException
from digi.xbee.packets.raw import TX64Packet
from threading import Thread
import serial
class ZigbeeConnection():
def __init__(self, port, baudRate = 230400):
self._port = port
self._baudRate = baudRate
self._packetID = 0
self._serialPort = serial.Serial(port=self._port,baudrate= self._baudRate )
self._readActive = True
self._T = Thread(target=self._startReading, daemon=True)
self._T.start()
def _startReading(self):
while(self._readActive):
rawbytes = self._serialPort.read_until(expected=b"\x02")
data=(str(rawbytes)[2:str(rawbytes).rfind("}")+1])
print(data)
def sendBroadCastMessage(self,msg:str):
try:
msg = msg.encode("utf-8")
packet = TX64Packet(self._packetID, XBee64BitAddress.BROADCAST_ADDRESS,
TransmitOptions.NONE.value, rf_data=msg)
self._serialPort.write(packet.output())
self._packetID += 1
except XBeeException as e:
pass
I' developing with python for a Raspberry Pi video application. I modified a c-program that plays full hd movies to take input from a FIFO.
Like so:
$ ./hello_video.bin test.h264 < .my_fifo
$ echo 3 > .my_fifo
I can send numbers to the FIFO and the hello_video.bin will trigger the corresponding video clip and loop it forever.
Next step should be to make the videos triggerable from remote. This is what i have:
#!/usr/bin/env python
import socket
import threading
import Queue
import subprocess
import sys
from time import sleep
host = '' # empty port = all local ports
port = 5005
buffer = 2 # small buffer sufficient
player = "/opt/vc/src/hello_pi/hello_video/hello_video.bin"
clip = "/opt/vc/src/hello_pi/hello_video/test.h264"
p = subprocess.Popen([player, clip], stdin=subprocess.PIPE)
class readFromUDPSocket(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while True:
data,addr = socketUDP.recvfrom(buffer)
try:
p.stdin.write(data)
p.stdin.flush()
except:
pass
if __name__ == '__main__':
# Create socket (IPv4 protocol, datagram (UDP)) and bind to address
socketUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
socketUDP.bind((host, port))
# Instantiate & start threads
myServer = readFromUDPSocket()
myServer.daemon = True
myServer.start()
while 1:
pass
UDPSock.close()
Unfortunately the hello_video.bin doesn't react as supposed to. The commands do not trigger any other video.
I tried to use p.communicate(input=data) instead. This works, but just once. Then it blocks and i can't receive any other data from the socket.
I have no clue how to fix this — hope you can help me,
Thank you
I have been working on an Arduino/Raspberry Pi project where I have found myself learning not just Python but Twisted Python as well; so I apologize in advance for my newbness. I am trying to keep it simple for now and just trying to send a char at any one time between the two devices.
So far I am able to send from the Raspberry Pi to the Arduino and effectively turn its LED off/on just as expected. However I cannot seem to generate Twisted code which will detect anything coming from the Arduino to the RPi on the serial port. I verified that the Arduino is sending chars every 2 seconds with a serial monitor application in the Arduino programmer running on the RPi.
The code below runs on the RPi, receives a GET request and passes some of that data through the serial port to the Arduino. I cannot seem to get this code to listen to that same serial port though. :/ I have been working on this for a bit over a month and seem to be stuck. I just cannot seem to find a good example for Twisted Python online to receive serial data; or at least an example that I understand. Anyway here is what I have so far:
import sys
from urlparse import urlparse
from twisted.web import server, resource
from twisted.internet import reactor
from twisted.internet.protocol import Factory, Protocol
from twisted.internet.serialport import SerialPort
serServ = None
class USBclient(Protocol):
def connectionMade(self):
global serServ
serServ = self
print 'Arduino device: ', serServ, ' is connected.'
def cmdReceived(self, cmd):
serServ.transport.write(cmd)
print cmd, ' - sent to Arduino.'
pass
def serialReadEvent(self): #maybe it should be: doRead()? Couldn't get either to work.
print 'data from arduino is at the serial port!'
class HTTPserver(resource.Resource):
isLeaf = True
def render_GET(self, request): #passes the data from the get request
print 'HTTP request received'
myArduino = USBclient()
stringit = str(request)
parse = stringit.split()
command, path, version = parse
myArduino.cmdReceived(path)
class cmdTransport(Protocol):
def __init__(self, factory):
self.factory = factory
class cmdTransportFactory(Factory):
protocol = cmdTransport
if __name__ == '__main__':
HTTPsetup = server.Site(HTTPserver())
reactor.listenTCP(5000, HTTPsetup)
SerialPort(USBclient(), '/dev/ttyACM0', reactor, baudrate='115200')
reactor.run()
As you can see the code is just looking for anything on the serial port but I can't seem to make that magic happen. Thanks in advance, any help is appreciated!
Judging from this: http://twistedmatrix.com/trac/browser/tags/releases/twisted-12.3.0/twisted/internet/_win32serialport.py#L84 you should be looking at dataReceived(self,...) method of your Protocol subclass
Thus:
class USBclient(Protocol):
def connectionMade(self):
global serServ
serServ = self
print 'Arduino device: ', serServ, ' is connected.'
def cmdReceived(self, cmd):
serServ.transport.write(cmd)
print cmd, ' - sent to Arduino.'
pass
def dataReceived(self,data):
print 'USBclient.dataReceived called with:'
print str(data)
try this to see if it works.
Sorry if this question is too basic - this is the first time that I try using multithreaded sockets in Python.
Basically, I'm trying to write code that gets data that's being received by a UDPServer socket; the socket itself is running inside of a thread. In order to make the data accessible to the main thread, I'm using Thread local storage (it seems that's the correct way to do it based on everything that I read). The code below is my first attempt to make it work, but the variable doesn't seem to be properly updated. Any idea about what could be happening?
EDIT: see below for a working example
Server:
import socket
import threading
import SocketServer
data = threading.local()
class UDPHandler(SocketServer.BaseRequestHandler):
def handle(self):
data.outputString = self.request[0].strip()
class ThreadedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
def __init__(self, serverAddress, handlerClass):
SocketServer.UDPServer.__init__(self, serverAddress, handlerClass)
data.outputString = ""
if __name__ == "__main__":
ReceiverSocket = ThreadedUDPServer(("localhost",11111), UDPHandler)
ServerThread = threading.Thread(target=ReceiverSocket.serve_forever)
ServerThread.daemon = True
ServerThread.start()
while 1:
if data.outputString:
print data.outputString
data.outputString = ""
Client:
import socket
import sys
HOST, PORT = "localhost", 11111
data = " ".join(sys.argv[1:])
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(data + "\n", (HOST, PORT))
Thanks!!
Made it work. And yes - Thread local has nothing to do with this... :)
I have set a global variable and defined it as global in each function modifying it (as per this very helpful answer)
import socket
import threading
import SocketServer
data = ""
class UDPHandler(SocketServer.BaseRequestHandler):
def handle(self):
global data
data = self.request[0].strip()
class ThreadedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
pass
if __name__ == "__main__":
ReceiverSocket = ThreadedUDPServer(("localhost",11111), UDPHandler)
ServerThread = threading.Thread(target=ReceiverSocket.serve_forever)
ServerThread.start()
while 1:
if data:
print data
data = ""
Try using a global variable BUT make sure that you define it as global in EVERY thread and function
Dear all, I need to implement a TCP server in Python which receives some data from a client and then sends this data to another client. I've tried many different implementations but no way to make it run. Any help would be really appreciated.
Below is my code:
import SocketServer
import sys
import threading
buffer_size = 8182
ports = {'toserver': int(sys.argv[1]), 'fromserver': int(sys.argv[2])}
class ConnectionHandler(SocketServer.BaseRequestHandler):
def handle(self):
# I need to send the data received from the client connected to port 'toserver'
# to the client connected to port 'fromserver' - see variable 'ports' above
class TwoWayConnectionServer(threading.Thread):
def __init__(self):
self.to_server = SocketServer.ThreadingTCPServer(("", ports['toserver']), ConnectionHandler)
self.from_server = SocketServer.ThreadingTCPServer(("", ports['fromserver']), ConnectionHandler)
threading.Thread.__init__(self)
def run(self):
while (1):
self.to_server.handle_request()
self.from_server.handle_request()
def serve_non_blocking():
server = TwoWayConnectionServer()
server.run()
if __name__ == '__main__':
serve_non_blocking()
See the Twisted tutorial, and also twisted.protocols.portforward. I think that portforward module does something slightly different from what you want, it opens an outgoing connection to the destination port rather than waiting for the second client to connect, but you should be able to work from there.
Can you be more specific about what you tried and what didn't work? There are lots of ways to do this. Probably the easiest would be to use the socket library - maybe looking at some examples will help:
http://docs.python.org/library/socket.html#example