Skip to content

Commit a17fa00

Browse files
committed
Docs: Full API documentation
1 parent 9f62225 commit a17fa00

8 files changed

Lines changed: 261 additions & 125 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,4 @@ venv.bak/
104104
.mypy_cache/
105105
.idea
106106
*/.vscode*
107+
.vscode*

rawsocketpy/__init__.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
"""A Raw socket implementation allowing any ethernet type to be used/sniffed.
55
6-
.. moduleauthor:: Alexis Paques <alexis.paques@gmail.com>
6+
If gevent is available, sockets are monkey patched and two additionnal asynchronous server implementations are available: :class:`RawAsyncServer`, :class:`RawAsyncServerCallback`
77
8+
.. moduleauthor:: Alexis Paques <alexis.paques@gmail.com>
89
"""
10+
911
from __future__ import print_function
1012
try:
1113
from gevent import monkey; monkey.patch_all()
@@ -14,5 +16,6 @@
1416
print("Gevent could not be loaded; the sockets will not be cooperative.")
1517

1618
from .util import get_hw, protocol_to_ethertype, to_bytes, to_str
17-
from .main import RawPacket, RawSocket
19+
from .socket import RawSocket
20+
from .packet import RawPacket
1821
from .server import RawServer, RawRequestHandler, RawServerCallback

rawsocketpy/asyncserver.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,27 @@
55
from gevent import pool, Greenlet
66

77
class RawAsyncServer(RawServer):
8+
"""
9+
Prefered server instead of RawServer.
10+
Async server using :class:`gevent.Greenlet` in a :class:`gevent.pool` to allow asynchronous calls.
11+
12+
This will ensure you are not loosing data because the handler is too long.
13+
"""
814
pool = pool.Pool()
915
def handle_handler(self, handler):
16+
"""Add the Greenlet to the pool with ``handler.run()``, the function to run.
17+
18+
:param handler: The RawRequestHandler provided in the constructor
19+
:type handler: RawRequestHandler"""
1020
self.pool.start(Greenlet(handler.run))
1121

1222
class RawAsyncServerCallback(RawServerCallback, RawAsyncServer):
23+
"""
24+
Async server using :class:`gevent.Greenlet` in a :class:`gevent.pool` to allow asynchronous calls.
25+
"""
1326
def handle_handler(self, handler):
27+
"""Add the Greenlet to the pool with ``self.callback(handler, self)``: the function to run.
28+
29+
:param handler: The RawRequestHandler provided in the constructor
30+
:type handler: RawRequestHandler"""
1431
self.pool.start(Greenlet(self.callback, handler, self))

rawsocketpy/main.py

Lines changed: 0 additions & 115 deletions
This file was deleted.

rawsocketpy/packet.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
from .util import to_str, to_bytes
5+
6+
class RawPacket():
7+
"""RawPacket is the resulting data container of the RawSocket class.
8+
9+
It reads raw data and stores the MAC source, MAC destination, the Ethernet type and the data payload.
10+
11+
RawPacket.success is true if the packet is successfuly read.
12+
"""
13+
def __init__(self, data):
14+
"""A really simple class.
15+
16+
:param data: raw ethernet II frame coming from the socket library, either **bytes in Python3** or **str in Python2**
17+
:type data: str/bytes/bytearray
18+
"""
19+
self.dest = ""
20+
""":description: Destination MAC address
21+
:type: str/bytes/bytearray"""
22+
self.src = ""
23+
""":description: Source MAC address
24+
:type: str/bytes/bytearray"""
25+
self.type = ""
26+
""":description: Ethertype
27+
:type: str/bytes/bytearray"""
28+
self.data = ""
29+
""":description: Payload received
30+
:type: str/bytes/bytearray"""
31+
self.success = False
32+
""":description: True if the packet has been successfully unmarshalled
33+
:type: bool"""
34+
try:
35+
self.dest, self.src, self.type = data[0:6], data[6:12], data[12:14]
36+
self.data = data[14:]
37+
self.success = True
38+
except Exception as e:
39+
print("rawsocket: ", e)
40+
self.success = False
41+
42+
def __repr__(self):
43+
return "".join([to_str(self.src), " == 0x", to_str(self.type, separator=""), " => ", to_str(self.dest), " - ", "OK" if self.success else "FAILED"])
44+
45+
def __str__(self):
46+
return "".join([self.__repr__(), ":\n", self.data.decode('utf-8')])

rawsocketpy/server.py

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,113 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
from .main import RawPacket, RawSocket
4+
from .packet import RawPacket
5+
from .socket import RawSocket
56
from .util import get_hw, to_bytes, protocol_to_ethertype
67

78
class RawServer(object):
9+
"""A **Blocking** base server implementation of a server on top of the RawSocket.
10+
It waits for data, encapsulate the data in the RequestHandlerClass provided and blocks until the RequestHandlerClass run() function finishes.
11+
12+
:note: packet = recv()
13+
-> RequestHandlerClass(packet)
14+
-> RequestHandlerClass.run()
15+
-> loop
16+
"""
817
def __init__(self, interface, protocol, RequestHandlerClass):
18+
"""
19+
20+
:param interface: interface to be used.
21+
:type interface: str
22+
:param protocol: Ethernet II protocol, RawSocket [1536-65535]
23+
:type protocol: int
24+
:param RequestHandlerClass: The class that will handle the requests
25+
:type RequestHandlerClass: RawServerCallback
26+
"""
927
self.RequestHandlerClass = RequestHandlerClass
1028
self.socket = RawSocket(interface, protocol)
1129
self.recv = self.socket.recv
1230
self.running = False
1331

1432
def spin_once(self):
33+
"""Handles the next message"""
1534
packet = self.recv()
1635
handler = self.RequestHandlerClass(packet, self)
1736
self.handle_handler(handler)
1837

1938
def handle_handler(self, handler):
39+
"""Manage the handler, can be overwritten"""
2040
handler.run()
2141

2242
def spin(self):
43+
"""Loops until self.running becomes False (from a Request Handler or another thread/coroutine)"""
2344
self.running = True
2445
while self.running:
2546
self.spin_once()
2647

2748

2849
class RawServerCallback(RawServer):
50+
"""A blocking server implementation that uses a centralized callback. This is useful for a stateful server.
51+
52+
:note: packet = recv()
53+
-> RequestHandlerClass(packet, self)
54+
-> callback(RequestHandlerClass, self)
55+
-> loop
56+
"""
2957
def __init__(self, interface, protocol, RequestHandlerClass, callback):
58+
"""
59+
:param interface: interface to be used.
60+
:type interface: str
61+
:param protocol: Ethernet II protocol, RawSocket [1536-65535]
62+
:type protocol: int
63+
:param RequestHandlerClass: The class that will handle the requests
64+
:type RequestHandlerClass: RawServerCallback
65+
:param callback: callback to be used.
66+
:type callback: function
67+
"""
3068
self.callback = callback
3169
RawServer.__init__(self, interface, protocol, RequestHandlerClass)
3270

3371
def handle_handler(self, handler):
72+
"""
73+
Overwritten: Calls callback(handler, self) instead.
74+
"""
3475
self.callback(handler, self)
3576

3677

3778
class RawRequestHandler(object):
79+
"""The class that handles the request.
80+
It has access to the packet and the server data.
81+
"""
3882
def __init__(self, packet, server):
3983
self.packet = packet
84+
""":description: Packet received
85+
:type: RawPacket"""
4086
self.server = server
41-
# self.server.socket.sock = low level socket
87+
""":description: Server from which the packet comes
88+
:type: RawServer"""
4289

4390
def finish(self):
91+
"""empty: To be **overwritten**"""
4492
pass
4593

4694
def setup(self):
95+
"""empty: To be **overwritten**"""
4796
pass
4897

4998
def handle(self):
50-
print(self.packet)
99+
"""empty: To be **overwritten**"""
100+
pass
51101

52102
def run(self):
103+
"""Run the request handling process:
104+
105+
try:
106+
* self.setup()
107+
* self.handle()
108+
finally:
109+
* self.finish()
110+
"""
53111
try:
54112
self.setup()
55113
self.handle()

0 commit comments

Comments
 (0)