bisocket 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bisocket-0.0.1/LICENSE +21 -0
- bisocket-0.0.1/MANIFEST.in +3 -0
- bisocket-0.0.1/PKG-INFO +234 -0
- bisocket-0.0.1/README.md +203 -0
- bisocket-0.0.1/bisocket/__init__.py +15 -0
- bisocket-0.0.1/bisocket/cython/c_main.c +43526 -0
- bisocket-0.0.1/bisocket/main.py +741 -0
- bisocket-0.0.1/bisocket.egg-info/PKG-INFO +234 -0
- bisocket-0.0.1/bisocket.egg-info/SOURCES.txt +14 -0
- bisocket-0.0.1/bisocket.egg-info/dependency_links.txt +1 -0
- bisocket-0.0.1/bisocket.egg-info/requires.txt +1 -0
- bisocket-0.0.1/bisocket.egg-info/top_level.txt +1 -0
- bisocket-0.0.1/pyproject.toml +2 -0
- bisocket-0.0.1/requirements.txt +1 -0
- bisocket-0.0.1/setup.cfg +4 -0
- bisocket-0.0.1/setup.py +55 -0
bisocket-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Daniel Olson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
bisocket-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bisocket
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: bisocket is a high-level Python library for simple, secure, and truly bidirectional socket communication, using a dual-socket architecture to enable non-blocking, full-duplex I/O. It provides automatic AES-GCM encryption and supports both synchronous (threading) and asynchronous (asyncio) client-server applications
|
|
5
|
+
Home-page:
|
|
6
|
+
Author: Daniel Olson
|
|
7
|
+
Author-email: daniel@orphos.cloud
|
|
8
|
+
Keywords: socket bidirectional
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: cryptography
|
|
21
|
+
Dynamic: author
|
|
22
|
+
Dynamic: author-email
|
|
23
|
+
Dynamic: classifier
|
|
24
|
+
Dynamic: description
|
|
25
|
+
Dynamic: description-content-type
|
|
26
|
+
Dynamic: keywords
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
|
30
|
+
Dynamic: summary
|
|
31
|
+
|
|
32
|
+
# `bisocket`: Simple, Secure, Bidirectional Python Sockets
|
|
33
|
+
|
|
34
|
+
[](https://www.google.com/search?q=https://badge.fury.io/py/bisocket)
|
|
35
|
+
[](https://opensource.org/licenses/MIT)
|
|
36
|
+
|
|
37
|
+
`bisocket` is a high-level Python library that simplifies bidirectional (two-way) communication over sockets. It provides a robust framework for building client-server applications that require sending and receiving data simultaneously without blocking.
|
|
38
|
+
|
|
39
|
+
It comes with built-in **AES-GCM end-to-end encryption** and **bz2 compression**, ensuring your data is secure and transmitted efficiently. The library offers both synchronous (threading-based) and asynchronous (`asyncio`) APIs, making it versatile for various application architectures.
|
|
40
|
+
|
|
41
|
+
-----
|
|
42
|
+
|
|
43
|
+
## β¨ Features
|
|
44
|
+
|
|
45
|
+
- **True Bidirectional Communication**: Uses separate sockets for sending and receiving, enabling non-blocking, full-duplex communication.
|
|
46
|
+
- **End-to-End Encryption**: Automatic AES-GCM encryption for all messages ensures data privacy and integrity.
|
|
47
|
+
- **Data Compression**: Automatic `bz2` compression reduces bandwidth usage for large payloads.
|
|
48
|
+
- **Sync & Async Support**: Provides both a standard threading API and a modern `asyncio` API.
|
|
49
|
+
- **Simple Handler-Based API**: Use a clean handler function on the server and an `on_receive` callback on the client to process messages.
|
|
50
|
+
- **Unique Client Identification**: Manages clients using unique UUIDs, making it easy to track connections.
|
|
51
|
+
|
|
52
|
+
-----
|
|
53
|
+
|
|
54
|
+
## βοΈ Installation
|
|
55
|
+
|
|
56
|
+
Install `bisocket` directly from PyPI:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
pip install bisocket
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The only dependency is the `cryptography` library for encryption.
|
|
63
|
+
|
|
64
|
+
-----
|
|
65
|
+
|
|
66
|
+
## π Quick Start
|
|
67
|
+
|
|
68
|
+
Hereβs a simple echo client and server to get you started.
|
|
69
|
+
|
|
70
|
+
### 1\. Set the Encryption Key
|
|
71
|
+
|
|
72
|
+
For security, `bisocket` requires an encryption key. Set it as an environment variable. If it's not set, the library will use a default, **insecure** key suitable only for testing.
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
export CRYPTO_KEY='your-super-secret-and-long-encryption-key'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2\. Synchronous Example
|
|
79
|
+
|
|
80
|
+
#### Server (`server.py`)
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from bisocket import Server, ServerRequest
|
|
84
|
+
|
|
85
|
+
# Define a handler to process incoming requests.
|
|
86
|
+
def handler(request: ServerRequest):
|
|
87
|
+
print(f"Received method '{request.method}' with data: {request.data.decode()}")
|
|
88
|
+
|
|
89
|
+
if request.method == 'echo':
|
|
90
|
+
# Send the received data back to the client.
|
|
91
|
+
request.send_data(request.data)
|
|
92
|
+
elif request.method == 'ping':
|
|
93
|
+
request.send_data(b'pong')
|
|
94
|
+
|
|
95
|
+
# Create and start the server.
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
server = Server(host='127.0.0.1', port=65432, handler=handler)
|
|
98
|
+
print("Starting synchronous server on port 65432...")
|
|
99
|
+
server.start()
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### Client (`client.py`)
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
import time
|
|
106
|
+
from bisocket import Client, Message
|
|
107
|
+
|
|
108
|
+
# Define a callback to handle messages from the server.
|
|
109
|
+
def on_receive(msg: Message):
|
|
110
|
+
print(f"Received response for request ID {msg.request_id}: {msg.data.decode()}")
|
|
111
|
+
|
|
112
|
+
# Use the Client as a context manager for clean connection handling.
|
|
113
|
+
with Client(host='127.0.0.1', port=65432, on_receive=on_receive) as client:
|
|
114
|
+
print("Client connected.")
|
|
115
|
+
|
|
116
|
+
# Send an 'echo' request.
|
|
117
|
+
request_id_1 = client.send('echo', b'Hello, World!')
|
|
118
|
+
print(f"Sent 'echo' request with ID: {request_id_1}")
|
|
119
|
+
|
|
120
|
+
time.sleep(1) # Wait for the response.
|
|
121
|
+
|
|
122
|
+
# Send a 'ping' request.
|
|
123
|
+
request_id_2 = client.send('ping', b'')
|
|
124
|
+
print(f"Sent 'ping' request with ID: {request_id_2}")
|
|
125
|
+
|
|
126
|
+
time.sleep(2) # Give time for messages to be processed before exiting.
|
|
127
|
+
|
|
128
|
+
print("Client disconnected.")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
-----
|
|
132
|
+
|
|
133
|
+
### 3\. Asynchronous Example
|
|
134
|
+
|
|
135
|
+
#### Async Server (`async_server.py`)
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
import asyncio
|
|
139
|
+
from bisocket import Server, ServerRequest
|
|
140
|
+
|
|
141
|
+
# Define an async handler for non-blocking operations.
|
|
142
|
+
async def ahandler(request: ServerRequest):
|
|
143
|
+
print(f"Received method '{request.method}' with data: {request.data.decode()}")
|
|
144
|
+
|
|
145
|
+
if request.method == 'echo':
|
|
146
|
+
await asyncio.sleep(0.5) # Simulate I/O-bound work.
|
|
147
|
+
request.send_data(request.data)
|
|
148
|
+
|
|
149
|
+
# Create and run the async server.
|
|
150
|
+
async def main():
|
|
151
|
+
server = Server(host='127.0.0.1', port=65432, handler=ahandler)
|
|
152
|
+
print("Starting asynchronous server on port 65432...")
|
|
153
|
+
await server.astart()
|
|
154
|
+
|
|
155
|
+
if __name__ == "__main__":
|
|
156
|
+
try:
|
|
157
|
+
asyncio.run(main())
|
|
158
|
+
except KeyboardInterrupt:
|
|
159
|
+
print("Server shutting down.")
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
#### Async Client (`async_client.py`)
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
import asyncio
|
|
166
|
+
from bisocket import Client, Message
|
|
167
|
+
|
|
168
|
+
# Define an async callback to process server messages.
|
|
169
|
+
async def aon_receive(msg: Message):
|
|
170
|
+
print(f"Received response for request ID {msg.request_id}: {msg.data.decode()}")
|
|
171
|
+
|
|
172
|
+
async def main():
|
|
173
|
+
# Use the async context manager for the client.
|
|
174
|
+
async with Client(host='127.0.0.1', port=65432, on_receive=aon_receive) as client:
|
|
175
|
+
print("Async client connected.")
|
|
176
|
+
|
|
177
|
+
# Send multiple requests concurrently.
|
|
178
|
+
tasks = [
|
|
179
|
+
client.asend('echo', b'First async message'),
|
|
180
|
+
client.asend('echo', b'Second async message')
|
|
181
|
+
]
|
|
182
|
+
request_ids = await asyncio.gather(*tasks)
|
|
183
|
+
print(f"Sent requests with IDs: {request_ids}")
|
|
184
|
+
|
|
185
|
+
await asyncio.sleep(2) # Keep client running to receive responses.
|
|
186
|
+
|
|
187
|
+
if __name__ == "__main__":
|
|
188
|
+
asyncio.run(main())
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
-----
|
|
192
|
+
|
|
193
|
+
## π§ How It Works
|
|
194
|
+
|
|
195
|
+
Traditional socket programming can be tricky when you need to send and receive data at the same time, often leading to blocking calls or complex multiplexing.
|
|
196
|
+
|
|
197
|
+
`bisocket` simplifies this by establishing **two separate socket connections** for each client:
|
|
198
|
+
|
|
199
|
+
1. **Send Socket**: The client uses this connection exclusively to send data *to* the server.
|
|
200
|
+
2. **Receive Socket**: The client uses this connection exclusively to receive data *from* the server.
|
|
201
|
+
|
|
202
|
+
This architecture allows the client and server to communicate in full-duplex mode without one operation blocking the other. The library manages these connections, message framing, encryption, and compression internally, so you can focus on your application logic.
|
|
203
|
+
|
|
204
|
+
- **On the Client**: The `Client` runs a background thread (or `asyncio` task) to listen for incoming messages on the receive socket. These messages are passed to your `on_receive` callback.
|
|
205
|
+
- **On the Server**: The `Server` manages a pool of client connections. It receives a request from a client's "send" socket, processes it in your handler, and then queues the response to be sent back via that same client's "receive" socket.
|
|
206
|
+
|
|
207
|
+
-----
|
|
208
|
+
|
|
209
|
+
## π Security
|
|
210
|
+
|
|
211
|
+
All data transmitted by `bisocket` is encrypted using **AES-256-GCM**, an authenticated encryption scheme that provides confidentiality and integrity. The 256-bit encryption key is derived from the string you provide via the `CRYPTO_KEY` environment variable using SHA-256.
|
|
212
|
+
|
|
213
|
+
**β οΈ It is crucial to set a strong, unique secret key for your application.**
|
|
214
|
+
|
|
215
|
+
You can generate a cryptographically secure key using OpenSSL:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# This command generates a 32-byte (256-bit) random key in hex format.
|
|
219
|
+
export CRYPTO_KEY=$(openssl rand -hex 32)
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
If `CRYPTO_KEY` is not set, a default, insecure key (`'secret-lol'`) is used, and a warning is printed. This is intended **only for local testing and development**.
|
|
223
|
+
|
|
224
|
+
-----
|
|
225
|
+
|
|
226
|
+
## π License
|
|
227
|
+
|
|
228
|
+
This project is licensed under the MIT License. See the `LICENSE` file for details.
|
|
229
|
+
|
|
230
|
+
-----
|
|
231
|
+
|
|
232
|
+
## π Contributing
|
|
233
|
+
|
|
234
|
+
Contributions are welcome\! Please feel free to submit a pull request or open an issue to discuss new features or bugs.
|
bisocket-0.0.1/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# `bisocket`: Simple, Secure, Bidirectional Python Sockets
|
|
2
|
+
|
|
3
|
+
[](https://www.google.com/search?q=https://badge.fury.io/py/bisocket)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
|
|
6
|
+
`bisocket` is a high-level Python library that simplifies bidirectional (two-way) communication over sockets. It provides a robust framework for building client-server applications that require sending and receiving data simultaneously without blocking.
|
|
7
|
+
|
|
8
|
+
It comes with built-in **AES-GCM end-to-end encryption** and **bz2 compression**, ensuring your data is secure and transmitted efficiently. The library offers both synchronous (threading-based) and asynchronous (`asyncio`) APIs, making it versatile for various application architectures.
|
|
9
|
+
|
|
10
|
+
-----
|
|
11
|
+
|
|
12
|
+
## β¨ Features
|
|
13
|
+
|
|
14
|
+
- **True Bidirectional Communication**: Uses separate sockets for sending and receiving, enabling non-blocking, full-duplex communication.
|
|
15
|
+
- **End-to-End Encryption**: Automatic AES-GCM encryption for all messages ensures data privacy and integrity.
|
|
16
|
+
- **Data Compression**: Automatic `bz2` compression reduces bandwidth usage for large payloads.
|
|
17
|
+
- **Sync & Async Support**: Provides both a standard threading API and a modern `asyncio` API.
|
|
18
|
+
- **Simple Handler-Based API**: Use a clean handler function on the server and an `on_receive` callback on the client to process messages.
|
|
19
|
+
- **Unique Client Identification**: Manages clients using unique UUIDs, making it easy to track connections.
|
|
20
|
+
|
|
21
|
+
-----
|
|
22
|
+
|
|
23
|
+
## βοΈ Installation
|
|
24
|
+
|
|
25
|
+
Install `bisocket` directly from PyPI:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install bisocket
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The only dependency is the `cryptography` library for encryption.
|
|
32
|
+
|
|
33
|
+
-----
|
|
34
|
+
|
|
35
|
+
## π Quick Start
|
|
36
|
+
|
|
37
|
+
Hereβs a simple echo client and server to get you started.
|
|
38
|
+
|
|
39
|
+
### 1\. Set the Encryption Key
|
|
40
|
+
|
|
41
|
+
For security, `bisocket` requires an encryption key. Set it as an environment variable. If it's not set, the library will use a default, **insecure** key suitable only for testing.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
export CRYPTO_KEY='your-super-secret-and-long-encryption-key'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2\. Synchronous Example
|
|
48
|
+
|
|
49
|
+
#### Server (`server.py`)
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from bisocket import Server, ServerRequest
|
|
53
|
+
|
|
54
|
+
# Define a handler to process incoming requests.
|
|
55
|
+
def handler(request: ServerRequest):
|
|
56
|
+
print(f"Received method '{request.method}' with data: {request.data.decode()}")
|
|
57
|
+
|
|
58
|
+
if request.method == 'echo':
|
|
59
|
+
# Send the received data back to the client.
|
|
60
|
+
request.send_data(request.data)
|
|
61
|
+
elif request.method == 'ping':
|
|
62
|
+
request.send_data(b'pong')
|
|
63
|
+
|
|
64
|
+
# Create and start the server.
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
server = Server(host='127.0.0.1', port=65432, handler=handler)
|
|
67
|
+
print("Starting synchronous server on port 65432...")
|
|
68
|
+
server.start()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Client (`client.py`)
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import time
|
|
75
|
+
from bisocket import Client, Message
|
|
76
|
+
|
|
77
|
+
# Define a callback to handle messages from the server.
|
|
78
|
+
def on_receive(msg: Message):
|
|
79
|
+
print(f"Received response for request ID {msg.request_id}: {msg.data.decode()}")
|
|
80
|
+
|
|
81
|
+
# Use the Client as a context manager for clean connection handling.
|
|
82
|
+
with Client(host='127.0.0.1', port=65432, on_receive=on_receive) as client:
|
|
83
|
+
print("Client connected.")
|
|
84
|
+
|
|
85
|
+
# Send an 'echo' request.
|
|
86
|
+
request_id_1 = client.send('echo', b'Hello, World!')
|
|
87
|
+
print(f"Sent 'echo' request with ID: {request_id_1}")
|
|
88
|
+
|
|
89
|
+
time.sleep(1) # Wait for the response.
|
|
90
|
+
|
|
91
|
+
# Send a 'ping' request.
|
|
92
|
+
request_id_2 = client.send('ping', b'')
|
|
93
|
+
print(f"Sent 'ping' request with ID: {request_id_2}")
|
|
94
|
+
|
|
95
|
+
time.sleep(2) # Give time for messages to be processed before exiting.
|
|
96
|
+
|
|
97
|
+
print("Client disconnected.")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
-----
|
|
101
|
+
|
|
102
|
+
### 3\. Asynchronous Example
|
|
103
|
+
|
|
104
|
+
#### Async Server (`async_server.py`)
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import asyncio
|
|
108
|
+
from bisocket import Server, ServerRequest
|
|
109
|
+
|
|
110
|
+
# Define an async handler for non-blocking operations.
|
|
111
|
+
async def ahandler(request: ServerRequest):
|
|
112
|
+
print(f"Received method '{request.method}' with data: {request.data.decode()}")
|
|
113
|
+
|
|
114
|
+
if request.method == 'echo':
|
|
115
|
+
await asyncio.sleep(0.5) # Simulate I/O-bound work.
|
|
116
|
+
request.send_data(request.data)
|
|
117
|
+
|
|
118
|
+
# Create and run the async server.
|
|
119
|
+
async def main():
|
|
120
|
+
server = Server(host='127.0.0.1', port=65432, handler=ahandler)
|
|
121
|
+
print("Starting asynchronous server on port 65432...")
|
|
122
|
+
await server.astart()
|
|
123
|
+
|
|
124
|
+
if __name__ == "__main__":
|
|
125
|
+
try:
|
|
126
|
+
asyncio.run(main())
|
|
127
|
+
except KeyboardInterrupt:
|
|
128
|
+
print("Server shutting down.")
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
#### Async Client (`async_client.py`)
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
import asyncio
|
|
135
|
+
from bisocket import Client, Message
|
|
136
|
+
|
|
137
|
+
# Define an async callback to process server messages.
|
|
138
|
+
async def aon_receive(msg: Message):
|
|
139
|
+
print(f"Received response for request ID {msg.request_id}: {msg.data.decode()}")
|
|
140
|
+
|
|
141
|
+
async def main():
|
|
142
|
+
# Use the async context manager for the client.
|
|
143
|
+
async with Client(host='127.0.0.1', port=65432, on_receive=aon_receive) as client:
|
|
144
|
+
print("Async client connected.")
|
|
145
|
+
|
|
146
|
+
# Send multiple requests concurrently.
|
|
147
|
+
tasks = [
|
|
148
|
+
client.asend('echo', b'First async message'),
|
|
149
|
+
client.asend('echo', b'Second async message')
|
|
150
|
+
]
|
|
151
|
+
request_ids = await asyncio.gather(*tasks)
|
|
152
|
+
print(f"Sent requests with IDs: {request_ids}")
|
|
153
|
+
|
|
154
|
+
await asyncio.sleep(2) # Keep client running to receive responses.
|
|
155
|
+
|
|
156
|
+
if __name__ == "__main__":
|
|
157
|
+
asyncio.run(main())
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
-----
|
|
161
|
+
|
|
162
|
+
## π§ How It Works
|
|
163
|
+
|
|
164
|
+
Traditional socket programming can be tricky when you need to send and receive data at the same time, often leading to blocking calls or complex multiplexing.
|
|
165
|
+
|
|
166
|
+
`bisocket` simplifies this by establishing **two separate socket connections** for each client:
|
|
167
|
+
|
|
168
|
+
1. **Send Socket**: The client uses this connection exclusively to send data *to* the server.
|
|
169
|
+
2. **Receive Socket**: The client uses this connection exclusively to receive data *from* the server.
|
|
170
|
+
|
|
171
|
+
This architecture allows the client and server to communicate in full-duplex mode without one operation blocking the other. The library manages these connections, message framing, encryption, and compression internally, so you can focus on your application logic.
|
|
172
|
+
|
|
173
|
+
- **On the Client**: The `Client` runs a background thread (or `asyncio` task) to listen for incoming messages on the receive socket. These messages are passed to your `on_receive` callback.
|
|
174
|
+
- **On the Server**: The `Server` manages a pool of client connections. It receives a request from a client's "send" socket, processes it in your handler, and then queues the response to be sent back via that same client's "receive" socket.
|
|
175
|
+
|
|
176
|
+
-----
|
|
177
|
+
|
|
178
|
+
## π Security
|
|
179
|
+
|
|
180
|
+
All data transmitted by `bisocket` is encrypted using **AES-256-GCM**, an authenticated encryption scheme that provides confidentiality and integrity. The 256-bit encryption key is derived from the string you provide via the `CRYPTO_KEY` environment variable using SHA-256.
|
|
181
|
+
|
|
182
|
+
**β οΈ It is crucial to set a strong, unique secret key for your application.**
|
|
183
|
+
|
|
184
|
+
You can generate a cryptographically secure key using OpenSSL:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# This command generates a 32-byte (256-bit) random key in hex format.
|
|
188
|
+
export CRYPTO_KEY=$(openssl rand -hex 32)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
If `CRYPTO_KEY` is not set, a default, insecure key (`'secret-lol'`) is used, and a warning is printed. This is intended **only for local testing and development**.
|
|
192
|
+
|
|
193
|
+
-----
|
|
194
|
+
|
|
195
|
+
## π License
|
|
196
|
+
|
|
197
|
+
This project is licensed under the MIT License. See the `LICENSE` file for details.
|
|
198
|
+
|
|
199
|
+
-----
|
|
200
|
+
|
|
201
|
+
## π Contributing
|
|
202
|
+
|
|
203
|
+
Contributions are welcome\! Please feel free to submit a pull request or open an issue to discuss new features or bugs.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Import modules from subpackages
|
|
2
|
+
try:
|
|
3
|
+
from .cython import c_main as main
|
|
4
|
+
except:
|
|
5
|
+
from . import main
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from .cython.c_main import Client, Server, Message, ServerRequest, server_handler_example
|
|
9
|
+
except:
|
|
10
|
+
from .main import Client, Server, Message, ServerRequest, server_handler_example
|
|
11
|
+
|
|
12
|
+
# Define the public API
|
|
13
|
+
__all__ = [
|
|
14
|
+
'main',
|
|
15
|
+
]
|