Skip to content

Commit 4fbc2ad

Browse files
committed
Adding asynchronous servers with callbacks
1 parent a65818b commit 4fbc2ad

5 files changed

Lines changed: 82 additions & 16 deletions

File tree

rawsocketpy/__init__.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
# Package init
2+
from __future__ import print_function
3+
try:
4+
from gevent import monkey; monkey.patch_all()
5+
from .asyncserver import RawAsyncServer, RawAsyncServerCallback
6+
except ImportError:
7+
print("Gevent could not be loaded; the sockets will not be cooperative.")
28

39
from .util import get_hw, protocol_to_ethertype, to_bytes, to_str
410
from .main import RawPacket, RawSocket
11+
from .server import RawServer, RawRequestHandler, RawServerCallback

rawsocketpy/asyncserver.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from .server import RawServer, RawServerCallback
2+
from gevent import pool, Greenlet
3+
4+
class RawAsyncServer(RawServer):
5+
pool = pool.Pool()
6+
def handle_handler(self, handler):
7+
self.pool.start(Greenlet(handler.run))
8+
9+
class RawAsyncServerCallback(RawServerCallback, RawAsyncServer):
10+
def handle_handler(self, handler):
11+
self.pool.start(Greenlet(self.callback, handler, self))

rawsocketpy/main.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ class RawSocket(object):
2727
def __init__(self, interface, protocol, sock=None, no_recv_protocol=False):
2828
if not 0x0000 < protocol < 0xFFFF:
2929
raise ValueError("Protocol has to be in the range 0 to 65535")
30+
self.no_recv_protocol = no_recv_protocol
31+
self.non_processed_protocol = protocol
3032
self.protocol = socket.htons(protocol)
3133
self.ethertype = protocol_to_ethertype(protocol)
3234
self.interface = interface
@@ -35,6 +37,10 @@ def __init__(self, interface, protocol, sock=None, no_recv_protocol=False):
3537
self.sock = self.sock_create(self.interface, 0, sock)
3638
else:
3739
self.sock = self.sock_create(self.interface, self.protocol, sock)
40+
self.close = self.sock.close
41+
42+
def dup(self):
43+
return RawSocket(self.interface, self.non_processed_protocol, self.sock.dup(), self.no_recv_protocol)
3844

3945
@staticmethod
4046
def sock_create(interface, protocol, sock=None):
@@ -55,17 +61,3 @@ def recv(self):
5561

5662
def __str__(self):
5763
return self.interface
58-
59-
def main():
60-
na = NetworkAdapter("wlp2s0", 0xAA42)
61-
i = 0
62-
while True:
63-
try:
64-
na.send(str(i))
65-
time.sleep(0.1)
66-
i += 1
67-
except:
68-
break
69-
70-
if __name__ == '__main__':
71-
main()

rawsocketpy/server.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from .main import RawPacket, RawSocket
2+
from .util import get_hw, to_bytes, protocol_to_ethertype
3+
4+
class RawServer(object):
5+
def __init__(self, interface, protocol, RequestHandlerClass):
6+
self.RequestHandlerClass = RequestHandlerClass
7+
self.socket = RawSocket(interface, protocol)
8+
self.recv = self.socket.recv
9+
self.running = False
10+
11+
def spin_once(self):
12+
packet = self.recv()
13+
handler = self.RequestHandlerClass(packet, self)
14+
self.handle_handler(handler)
15+
16+
def handle_handler(self, handler):
17+
handler.run()
18+
19+
def spin(self):
20+
self.running = True
21+
while self.running:
22+
self.spin_once()
23+
24+
25+
class RawServerCallback(RawServer):
26+
def __init__(self, interface, protocol, RequestHandlerClass, callback):
27+
self.callback = callback
28+
RawServer.__init__(self, interface, protocol, RequestHandlerClass)
29+
30+
def handle_handler(self, handler):
31+
self.callback(handler, self)
32+
33+
34+
class RawRequestHandler(object):
35+
def __init__(self, packet, server):
36+
self.packet = packet
37+
self.server = server
38+
# self.server.socket.sock = low level socket
39+
40+
def finish(self):
41+
pass
42+
43+
def setup(self):
44+
pass
45+
46+
def handle(self):
47+
print(self.packet)
48+
49+
def run(self):
50+
try:
51+
self.setup()
52+
self.handle()
53+
except Exception as e:
54+
print(e)
55+
finally:
56+
self.finish()

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
long_description = fh.read()
55

66
setuptools.setup(name='rawsocketpy',
7-
version='0.1',
8-
description='This library allows you to implemnet a custom layer 2 communication using raw sockets in Python',
7+
version='0.2',
8+
description='This library allows you to implemnet a custom layer 2 communication using raw sockets in Python 2 and Python 3, synchronous and asynchronous, with and without callbacks.',
99
long_description=long_description,
1010
long_description_content_type="text/markdown",
1111
url='https://github.com/AlexisTM/rawsocket_python',

0 commit comments

Comments
 (0)