Twisted multiple peers - python

I'm currently working with twisted in python and I'm trying to make a multicast between many peers(each of them can send and receive messages, send acks etc). My main looks like this :
if __name__ == '__main__':
serial_process_num, address = parse_args()
if serial_process_num == '0':
factory = PeerFactory('0', 'log')
reactor.listenTCP(address[1], factory)
reactor.listenTCP(address[1]+1, factory)
print "Process 0 is listening #" + address[0] + " port " + str(address[1])
print "Process 0 is listening #" + address[0] + " port " + str(address[1]+1)
elif serial_process_num == '1':
factory = PeerFactory('1', '')
host, port = address
print "Connecting to process 0 " + host + " port " + str(port)
reactor.connectTCP(host, port, factory)
print "Process 1 is listening #" + address[0] + " port " + str(address[1]+2)
reactor.listenTCP(port+2, factory)
else:
factory = PeerFactory('2', '')
host, port = address
print "Connecting to process 0 " + host + " port " + str(port+1)
reactor.connectTCP(host, port+1, factory)
print "Connecting to process 1 " + host + " port " + str(port+2)
reactor.connectTCP(host, port+2, factory)
reactor.run()
I kept this one simple because I want to understand my mistake, so im using only 3 peers.I start the first one with serial_process_num 0 from the cmd (ex py example.py 0), then the 1 and 2.Am I setting up the listeners/connecttcp correctly? Whenever I send messages between those 3, I only receive half of them in every peer. (i use self.transport.write('example')
Is there an alternative way to multicast through TCPconnect in twisted?(im following krondos tutorial) and how can I make multiple connections between multiple peers with twisted?

Multicast is a datagram protocol, which means that you do not have a stream of bytes in the same way that you do with TCP; in other words, it's a kind of UDP. So no, you cannot use TCP with it, in Twisted or otherwise.

Related

python UDP socket client need to send twice so that the server can receive the package

i have a client will send some string to my server. However, i need to send twice so that the server get the package. So for every package client wants to send the server, it needs to send twice. I do not understand why it went in this way.
my server's code that does listening:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
myIp = "0x2A"
myPort = 2222
targetPort = 0
myAddress = ("localhost",myPort)
bufferSize = 1024
def listen():
print('starting up on {} port {}'.format(*myAddress))
sock.bind(myAddress)
# sock.listen(1)
print("waiting for message")
# connection, client_address = sock.accept()
while True:
received = sock.recvfrom(bufferSize)[0]
address = sock.recvfrom(bufferSize)[1]
received = json.loads(received.decode())
source = received.get("source")
destination = received.get("destination")
length = received.get("length")
message = received.get("message")
protocol = received.get("protocol")
print("the source is: " + source)
if destination == myIp:
print("the message is: " + message)
print('sending back to sender...')
sock.sendto(message.encode(),address)
if protocol == 0:
print("protocol is: " + str(protocol))
elif protocol == 1:
print("protocol is: " + str(protocol))
print("write data to log file....")
f = open("log.txt","w")
f.write(message)
print('done!')
elif protocol == 2:
print("protocol is: " + str(protocol))
# sock.close()
print("exit")
sock.close()
sys.exit()
else:
print("this is not my package: \n" + "destination Ip is: " + destination + "\n my Ip is: " + myIp)
if not received:
break
my client's code that does the sending:
def send():
try:
sock.sendto(message.encode(),serverAddress)
print("message: " + message + " is sent")
finally:
print('closing socket')
sock.close()
received = sock.recvfrom(bufferSize)[0]
address = sock.recvfrom(bufferSize)[1]
The first recvfrom will do the first read. The second recvfrom will do another read. Voila: you need two reads. Instead you should do a single read:
received, address = socket.recvfrom(bufferSize)

Sending Client Data With a Timer

So I have a simple Client-Server.
They properly connect with command line arguments, send and receiving data.
When the server isn't up and running but the client executes: Attempt to connect, after 1 second display message that it timed out (3 times) before closing.
the closest i can come to it, is simply attempting it 3 times.
import sys
from socket import *
# Get the server hostname, port and data length as command line arguments
argv = sys.argv
host = argv[1]
port = argv[2]
count = argv[3]
# Command line argument is a string, change the port and count into integer
port = int(port)
count = int(count)
data = 'X' * count # Initialize data to be sent
# Create UDP client socket. Note the use of SOCK_DGRAM
clientsocket = socket(AF_INET, SOCK_DGRAM)
# Sending data to server
# times out after 1 second (?)
for i in range(3):
try:
print("Sending data to " + host + ", " + str(port) + ": " + data)
clientsocket.sendto(data.encode(),(host, port))
# Receive the server response
dataEcho, address = clientsocket.recvfrom(count)
# Display the server response as an output
print("Receive data from " + address[0] + ", " + str(address[1]) + ": " + dataEcho.decode())
break
except:
print("timed out")
finally:
#Close the client socket
clientsocket.close()
How would I add a timer to it? Just adding 1 second between each attempt instead of how I coded.
If you just want the program to sleep for x seconds you could import time, and then add time.sleep(num_of_seconds_to_sleep) after your clientsocket.close() line.

Python socket.bind() to host does not show incoming packets with SIO_RCVALL while sniffing for traffic on an interface

I'm attempting to read incoming/outgoing TCP packets through an interface on the host for a project I'm working on. I really want this to be done using sockets instead of using a library like scapy or pypcap. To have a better understanding of what is happening as well as more control over what is happening. This is on a Windows10 system.
import socket
import threading
from PacketParse import PacketParse
host = socket.gethostbyname(socket.gethostname())
sniff = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
sniff.bind((host, 0))
#include ip headers - IP PROTOCOL, IP HEADER INCLUDE
sniff.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
#receive all packages - INPUT OUTPUT CONTROL
sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
def start_sniffing():
while True:
raw_packet = sniff.recvfrom(2000)
packet = PacketParse(raw_packet)
if packet:
print(packet.src_addr + ":" + str(packet.src_port) + " --> " + packet.dst_addr + ":" + str(packet.dst_port) + " Protocol: " + packet.ip_prot + "(" + str(packet.ip_prot_raw) + ")")
print("Data(" + str(packet.data_size) + "): " + str(packet.data))
#file.write(packet.src_addr + ":" + str(packet.src_port) + " --> " + packet.dst_addr + ":" + str(packet.dst_port) + " Protocol: " + packet.ip_prot + "(" + str(packet.ip_prot_raw) + ")")
#file.write("Data(" + str(packet.data_size) + "): " + str(packet.data))'''
file = open("dump.txt", "a")
t = threading.Thread(target=start_sniffing)
t.start()
t.join()
file.close()
sniff.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)
PacketParse is a class I made to 'unpack' the packet. I've been using Python documentation for most of this script and tutorials for sniffing packets from many sources.
from struct import unpack
class PacketParse:
def __init__(self, packet):
self.extract(packet)
def extract(self, packet):
# extract ip header
packet = packet[0]
self.packet_raw = packet
'''
eth_raw = packet[:14]
eth_hdr = unpack('!6s6sH', eth_raw)
self.eth_prot = socket.ntohs(eth_hdr[2])
self.src_mac =
'''
ip_raw = packet[0:20]
ip_hdr = unpack('!BBHHHBBH4s4s', ip_raw)
#self.ip_length = ip_hdr[5]
self.ip_prot_raw = ip_hdr[6]
self.ip_prot = self.ip_prot_parse(ip_hdr[6])
self.src_addr = socket.inet_ntoa(ip_hdr[8])
self.dst_addr = socket.inet_ntoa(ip_hdr[9])
version = ip_hdr[0] >> 4
ihl_length = version & 0xF
iph_len = ihl_length * 4
tcp_raw = packet[20:40]
tcp_hdr = unpack('!HHLLBBHHH', tcp_raw)
self.src_port = tcp_hdr[0]
self.dst_port = tcp_hdr[1]
self.seq_num = tcp_hdr[2]
self.ack_num = tcp_hdr[3]
doff_reserved = tcp_hdr[4]
tcp_length = doff_reserved >> 4
header_size = (iph_len) + (tcp_length * 4)
self.data_size = len(packet) - header_size
self.data = packet[header_size:]
def ip_prot_parse(self, num):
return {
1: 'ICMP',
6: 'TCP',
17: 'UDP',
}.get(num, "Unknown")
The issue is this only shows packets being sent out from this host. Incoming packets are not displayed. A different script I've tried using scapy is capable of displaying incoming packets as well. Why is this happening? SIO_RCVALL should be allowing ALL packets being touched by the interface to be seen. I haven't tried a Linux equivalent of this script... so I don't know if the problem is specific on Windows. Most TCP reading scripts I've found have been Linux specific.
Alright... so it seems the problem was my firewall. When I turn it off, I can see all incoming packets just fine. That was a bit annoying. I believe there is a python library that allows you to edit firewall settings.
https://github.com/austin-taylor/bluewall
I haven't played around with it yet... it could be interesting. I haven't read into it enough yet to understand if this is what it seems. I believe it only gives you the configuration on Windows without changing anything. It could be fun on a Linux system.

Python icmp socket server (not tcp\udp)

I'm trying to write a socket server in Python that can receive ICMP packets.
Here's my code:
s = socket.socket(socket.AF_INET,socket.SOCK_RAW, socket.IPPROTO_ICMP)
host = socket.gethostbyname(socket.gethostname())
s.bind((host,0))
s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
However, I dont know how to receive the packets - I tried using s.listen but it failed.
What am I missing or am I completly in the wrong direction?
Thanks!
I've done this before in twisted and I set the socket up like this:
import socket
def listen():
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
s.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
while 1:
data, addr = s.recvfrom(1508)
print "Packet from %r: %r" % (addr,data)
Building on the accepted answer, this code unpacks the received ICMP header and displays its data (ICMP type, code, etc)
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_ICMP)
s.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
while 1:
recPacket, addr = s.recvfrom(1024)
icmp_header = recPacket[20:28]
type, code, checksum, p_id, sequence = struct.unpack('bbHHh', icmp_header)
print "type: [" + str(type) + "] code: [" + str(code) + "] checksum: [" + str(checksum) + "] p_id: [" + str(p_id) + "] sequence: [" + str(sequence) + "]"

MIRC Port Scanner

if data.find('!scan') != -1:
nick = data.split('!')[ 0 ].replace(':','')
targetip = str(socket.gethostbyname(args))
sck.send('PRIVMSG ' + chan + " :" ' scanning host' + " " + targetip + '\r\n')
for i in range(20, 1025):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = s.connect_ex((targetip, i))
if (result == 0) :
s.send('PRIVMSG ' + chan + " :" 'port %d: OPEN' % (i,) + '\r\n')
s.close()
The script works, but it ping timeout before it can get an open port, how can I make it so it can scan a few ports then check for a ping from the server and send a pong then scan a few more ports so that it wont ping timeout.
The best solution is to use multiple threads, with the main thread parsing input from IRC and responding to PINGs, while other threads do actual command processing and anything that could take a long time.
skybot, my IRC bot, spawns a new thread whenever a command is issued, and uses thread-safe queues to pass messages between them.

Categories

Resources