npien 1.0.0__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.
npien-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 npien contributors
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.
npien-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,235 @@
1
+ Metadata-Version: 2.4
2
+ Name: npien
3
+ Version: 1.0.0
4
+ Summary: NAT-piercing NET: serverless P2P UDP hole punching with rooms, STUN and optional end-to-end encryption
5
+ Author: npien contributors
6
+ License: MIT
7
+ Keywords: p2p,nat,stun,udp,hole-punching,networking,e2ee
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Operating System :: POSIX
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Internet
18
+ Classifier: Topic :: Security :: Cryptography
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE
22
+ Requires-Dist: cryptography>=41
23
+ Dynamic: license-file
24
+
25
+ # npien
26
+
27
+ **NAT-piercing NET** — sunucusuz (serverless) P2P UDP hole punching, oda sistemi,
28
+ Google STUN sunucuları ve isteğe bağlı uçtan uca şifreleme.
29
+
30
+ `npien`, iki Python sürecinin NAT arkasından doğrudan birbirine UDP paketi
31
+ göndermesini sağlar. STUN keşfi, delik açma (hole punching), paket çerçeveleme,
32
+ parçalama (fragmentation), keep-alive ve şifreleme kütüphanenin içinde yapılır.
33
+
34
+ ## Özellikler
35
+
36
+ - Google STUN sunucuları ile dış IP/port keşfi (RFC 5389, yerleşik istemci)
37
+ - UDP hole punching: aynı anda iki tarafa HELLO paketleri ile NAT eşlemesi açma
38
+ - Oda (room) sistemi: `npien.connect("492109")`
39
+ - Peer ticket: sunucu olmadan uç nokta paylaşımı (`npn1.<payload>.<hmac>`)
40
+ - Yerel keşif: aynı makinede kayıt defteri (registry), LAN'de UDP broadcast
41
+ - İsteğe bağlı E2EE: X25519 anahtar anlaşması + AES-256-GCM (`npien.advsecure()`)
42
+ - Büyük mesajlar için otomatik parçalama ve birleştirme
43
+ - Keep-alive / zaman aşımı yönetimi ve `on_message` callback'leri
44
+ - IPv4, Python 3.10+
45
+
46
+ ## Kurulum
47
+
48
+ ```bash
49
+ pip install -e .
50
+ ```
51
+
52
+ Bağımlılık: `cryptography` (E2EE için). STUN istemcisi kütüphanenin içindedir;
53
+ `pystun3` gerekmez.
54
+
55
+ ## Hızlı başlangıç
56
+
57
+ ### Aynı odada iki taraf
58
+
59
+ ```python
60
+ import npien
61
+
62
+ npien.set_appid("testprogram")
63
+ npien.connect("492109")
64
+ npien.send("merhaba")
65
+ veri, adres = npien.receive(timeout=10)
66
+ print(adres, veri.decode())
67
+ ```
68
+
69
+ `connect("492109")` önce yerel kayıt defterine ve LAN'e bakar. İnternet üzerinden
70
+ iki farklı ağ arasında uç noktaların bir şekilde paylaşılması gerekir; bunun için
71
+ ticket kullanın:
72
+
73
+ ### Ticket ile bağlanma
74
+
75
+ ```python
76
+ # B tarafı: dinle ve ticket üret
77
+ import npien
78
+
79
+ npien.set_appid("testprogram")
80
+ npien.listen("492109")
81
+ print("TICKET:", npien.create_ticket("492109"))
82
+ ```
83
+
84
+ ```python
85
+ # A tarafı: ticket'ı paylaşılan kanaldan (sohbet, e-posta, QR...) al
86
+ import npien
87
+
88
+ npien.set_appid("testprogram")
89
+ npien.connect("492109", ticket="npn1....")
90
+ npien.send("selam")
91
+ ```
92
+
93
+ Ticket, hedefin dış IP/portu, yerel adresi ve açık anahtarını taşır. Aynı ticket
94
+ ile iki taraf aynı anda `connect(...)` de çağırabilir; delik açma simetriktir.
95
+
96
+ ### Uçtan uca şifreleme
97
+
98
+ ```python
99
+ import npien
100
+
101
+ npien.set_appid("testprogram")
102
+ npien.connect("492109", ticket=ticket)
103
+ npien.advsecure() # giden mesajlar AES-256-GCM ile şifrelenir
104
+ npien.send("gizli mesaj")
105
+ ```
106
+
107
+ Anahtarlar X25519 ECDH ile her iki tarafta bağımsız olarak türetilir; mesajlar
108
+ ağda asla açık metin olarak dolaşmaz. Karşı taraf `advsecure()` çağırmasa bile
109
+ şifreli paketleri çözebilir; iki yönlü gizlilik için iki taraf da açmalıdır.
110
+
111
+ ### Sınıf tabanlı kullanım (çoklu örnek)
112
+
113
+ ```python
114
+ from npien import Npien
115
+
116
+ sunucu = Npien(appid="testprogram", name="sunucu")
117
+ sunucu.listen("492109")
118
+ ticket = sunucu.create_ticket("492109")
119
+
120
+ istemci = Npien(appid="testprogram", name="istemci")
121
+ istemci.connect("492109", ticket=ticket)
122
+ istemci.advsecure()
123
+ istemci.send(b"merhaba")
124
+ veri, adres = sunucu.receive(timeout=10)
125
+
126
+ istemci.close()
127
+ sunucu.close()
128
+ ```
129
+
130
+ ### Callback ile mesaj alma
131
+
132
+ ```python
133
+ @npien.on_message
134
+ def mesaj_geldi(veri: bytes, adres: tuple[str, int]):
135
+ print(adres, veri.decode(errors="replace"))
136
+ ```
137
+
138
+ Callback'ler transport thread'inde çalışır; ağır işleri ayrı bir thread/kuyruğa
139
+ devredin.
140
+
141
+ ## API
142
+
143
+ ### Modül seviyesi (varsayılan örnek)
144
+
145
+ | Fonksiyon | Açıklama |
146
+ | --- | --- |
147
+ | `set_appid(appid)` | Uygulama kimliğini ayarlar. Ticket HMAC'i ve oda ad alanı buna bağlıdır. |
148
+ | `set_name(name)` | Görünen ad (HELLO/ticket içinde taşınır). |
149
+ | `listen(room, advertise=True)` | Odayı dinlemeye başlar; `advertise` ise kendi ticket'ını kayıt defterine yazar. |
150
+ | `join_room(room)` | `listen` ile aynı. |
151
+ | `connect(room, peer=None, ticket=None, tickets=None, timeout=8.0, discover=True)` | Odaya bağlanır; bağlı peer'ların listesini döner. |
152
+ | `send(data, to=None)` | Varsayılan olarak odadaki tüm peer'lara gönderir. `to` bir oda adı veya `(ip, port)` olabilir. |
153
+ | `sendto(data, peer)` | Belirli bir peer'a gönderir. |
154
+ | `receive(timeout=None)` | `(bytes, (ip, port))` döner. |
155
+ | `receive_nowait()` | Bloklamadan dener; mesaj yoksa `TimeoutError`. |
156
+ | `advsecure(enabled=True)` | Giden mesajlarda E2EE'yi açar/kapatır. |
157
+ | `create_ticket(room)` | Paylaşılabilir ticket üretir; STUN keşfini tetikler. |
158
+ | `add_peer(ticket)` | Ticket'ı kayıt defterine ekler (odadaki diğer süreçler bulabilir). |
159
+ | `known_peers(room)` | Kayıt defterindeki ticket'ları döner. |
160
+ | `peers(room=None)` | Bağlı/bağlanan peer'ların `PeerInfo` listesi. |
161
+ | `on_message(callback)` | Gelen her mesaj için callback kaydeder. |
162
+ | `get_stun_info()` | Dış IP/port, yerel adres, NAT tipi ve STUN sunucuları. |
163
+ | `connection_info()` | Uygulama, oda, güvenlik ve peer özeti. |
164
+ | `disconnect(target=None)` | Peer/peer'ları ayırır. |
165
+ | `close()` | Kaynakları kapatır ve kayıt defteri girdilerini siler. |
166
+
167
+ ### `connect` parametreleri
168
+
169
+ - `peer`: `("1.2.3.4", 5678)` veya `"1.2.3.4:5678"` ya da bunların listesi.
170
+ - `ticket` / `tickets`: `create_ticket` çıktısı; açık anahtar pinlenir.
171
+ - `timeout`: delik açma için toplam süre (saniye).
172
+ - `discover`: `True` ise kayıt defteri + LAN broadcast keşfi yapılır.
173
+
174
+ ## Nasıl çalışır?
175
+
176
+ 1. **STUN**: Ana UDP soketi ile Google STUN sunucularına Binding Request
177
+ gönderilir; XOR-MAPPED-ADDRESS'ten dış uç nokta öğrenilir. Aynı soket
178
+ kullanıldığı için NAT eşlemesi hole punching ile birebir aynıdır.
179
+ 2. **Ticket**: Dış adres, yerel adres, uygulama kimliği, oda ve X25519 açık
180
+ anahtarı HMAC-SHA256 ile imzalanarak tek bir metne paketlenir.
181
+ 3. **Hole punching**: Her iki taraf aday adreslere (dış + yerel) 250 ms'de bir
182
+ HELLO gönderir. NAT eşlemesi açılınca HELLO/HELLO_ACK alışverişi oturumu kurar.
183
+ 4. **Oturum**: Oturum kimliği iki açık anahtarın sıralı hash'inden türer. Anahtar
184
+ X25519 + HKDF-SHA256 ile türetilir.
185
+ 5. **Veri**: `NPN1` başlıklı paketler; 1200 baytlık datagramlara parçalanır.
186
+ Şifreli modda AES-256-GCM (12 baytlık nonce, oturuma bağlı AAD) kullanılır.
187
+ 6. **Canlılık**: 10 saniyede bir PING/PONG; 45 saniye sessiz peer düşürülür.
188
+ 7. **Keşif**: Aynı makinede `~/.npien/registry` altındaki kilitli JSON kayıtları;
189
+ LAN'de 47777/UDP broadcast ve ticket yanıtları. `NPIEN_HOME` ve
190
+ `NPIEN_DISCOVERY_PORT` ile değiştirilebilir.
191
+
192
+ Paket başlığı (28 bayt):
193
+
194
+ ```text
195
+ NPN1 | version | type | flags | reserved | session(8) | msg_id(8) | frag_index(2) | frag_count(2)
196
+ ```
197
+
198
+ ## Sınırlamalar
199
+
200
+ - **Simetrik NAT**: Her hedef için farklı dış port atayan NAT'larda doğrudan
201
+ hole punching çoğu zaman başarısız olur. Bu durumda TURN benzeri bir relay
202
+ gerekir; `npien` şu an relay içermez.
203
+ - **Sinyalleşme**: İnternet üzerinde iki tarafın uç noktalarını öğrenmesi için
204
+ bir paylaşım kanalı (ticket) gerekir. LAN içinde broadcast, aynı makinede
205
+ kayıt defteri otomatik çalışır.
206
+ - **Güvenilirlik**: UDP semantiği geçerlidir; sıralama/teslim garantisi yoktur.
207
+ Uygulama katmanında gerekirse yeniden gönderim ekleyin.
208
+ - **Kimlik doğrulama**: Ticket ile açık anahtar pinlenir. Ticket'ı güvenilir bir
209
+ kanaldan paylaşın; aksi halde TOFU (ilk kullanımda güven) geçerlidir ve aktif
210
+ MITM engellenemez.
211
+ - IPv4 ve tek ağ arayüzü varsayılır.
212
+
213
+ ## Test
214
+
215
+ ```bash
216
+ python -m pytest -q
217
+ ```
218
+
219
+ Testler; paket çerçeveleme, şifreleme/ticket doğrulama, STUN ayrıştırma, kayıt
220
+ defteri ve gerçek UDP loopback üzerinden hole punching + şifreli mesajlaşmayı
221
+ kapsar.
222
+
223
+ ## Örnek uygulama
224
+
225
+ `examples/chat.py`:
226
+
227
+ ```bash
228
+ python examples/chat.py --room 492109 --name ali --secure
229
+ # başka terminal / makine:
230
+ python examples/chat.py --room 492109 --name ayse --ticket "npn1...." --secure
231
+ ```
232
+
233
+ ## Lisans
234
+
235
+ MIT
npien-1.0.0/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # npien
2
+
3
+ **NAT-piercing NET** — sunucusuz (serverless) P2P UDP hole punching, oda sistemi,
4
+ Google STUN sunucuları ve isteğe bağlı uçtan uca şifreleme.
5
+
6
+ `npien`, iki Python sürecinin NAT arkasından doğrudan birbirine UDP paketi
7
+ göndermesini sağlar. STUN keşfi, delik açma (hole punching), paket çerçeveleme,
8
+ parçalama (fragmentation), keep-alive ve şifreleme kütüphanenin içinde yapılır.
9
+
10
+ ## Özellikler
11
+
12
+ - Google STUN sunucuları ile dış IP/port keşfi (RFC 5389, yerleşik istemci)
13
+ - UDP hole punching: aynı anda iki tarafa HELLO paketleri ile NAT eşlemesi açma
14
+ - Oda (room) sistemi: `npien.connect("492109")`
15
+ - Peer ticket: sunucu olmadan uç nokta paylaşımı (`npn1.<payload>.<hmac>`)
16
+ - Yerel keşif: aynı makinede kayıt defteri (registry), LAN'de UDP broadcast
17
+ - İsteğe bağlı E2EE: X25519 anahtar anlaşması + AES-256-GCM (`npien.advsecure()`)
18
+ - Büyük mesajlar için otomatik parçalama ve birleştirme
19
+ - Keep-alive / zaman aşımı yönetimi ve `on_message` callback'leri
20
+ - IPv4, Python 3.10+
21
+
22
+ ## Kurulum
23
+
24
+ ```bash
25
+ pip install -e .
26
+ ```
27
+
28
+ Bağımlılık: `cryptography` (E2EE için). STUN istemcisi kütüphanenin içindedir;
29
+ `pystun3` gerekmez.
30
+
31
+ ## Hızlı başlangıç
32
+
33
+ ### Aynı odada iki taraf
34
+
35
+ ```python
36
+ import npien
37
+
38
+ npien.set_appid("testprogram")
39
+ npien.connect("492109")
40
+ npien.send("merhaba")
41
+ veri, adres = npien.receive(timeout=10)
42
+ print(adres, veri.decode())
43
+ ```
44
+
45
+ `connect("492109")` önce yerel kayıt defterine ve LAN'e bakar. İnternet üzerinden
46
+ iki farklı ağ arasında uç noktaların bir şekilde paylaşılması gerekir; bunun için
47
+ ticket kullanın:
48
+
49
+ ### Ticket ile bağlanma
50
+
51
+ ```python
52
+ # B tarafı: dinle ve ticket üret
53
+ import npien
54
+
55
+ npien.set_appid("testprogram")
56
+ npien.listen("492109")
57
+ print("TICKET:", npien.create_ticket("492109"))
58
+ ```
59
+
60
+ ```python
61
+ # A tarafı: ticket'ı paylaşılan kanaldan (sohbet, e-posta, QR...) al
62
+ import npien
63
+
64
+ npien.set_appid("testprogram")
65
+ npien.connect("492109", ticket="npn1....")
66
+ npien.send("selam")
67
+ ```
68
+
69
+ Ticket, hedefin dış IP/portu, yerel adresi ve açık anahtarını taşır. Aynı ticket
70
+ ile iki taraf aynı anda `connect(...)` de çağırabilir; delik açma simetriktir.
71
+
72
+ ### Uçtan uca şifreleme
73
+
74
+ ```python
75
+ import npien
76
+
77
+ npien.set_appid("testprogram")
78
+ npien.connect("492109", ticket=ticket)
79
+ npien.advsecure() # giden mesajlar AES-256-GCM ile şifrelenir
80
+ npien.send("gizli mesaj")
81
+ ```
82
+
83
+ Anahtarlar X25519 ECDH ile her iki tarafta bağımsız olarak türetilir; mesajlar
84
+ ağda asla açık metin olarak dolaşmaz. Karşı taraf `advsecure()` çağırmasa bile
85
+ şifreli paketleri çözebilir; iki yönlü gizlilik için iki taraf da açmalıdır.
86
+
87
+ ### Sınıf tabanlı kullanım (çoklu örnek)
88
+
89
+ ```python
90
+ from npien import Npien
91
+
92
+ sunucu = Npien(appid="testprogram", name="sunucu")
93
+ sunucu.listen("492109")
94
+ ticket = sunucu.create_ticket("492109")
95
+
96
+ istemci = Npien(appid="testprogram", name="istemci")
97
+ istemci.connect("492109", ticket=ticket)
98
+ istemci.advsecure()
99
+ istemci.send(b"merhaba")
100
+ veri, adres = sunucu.receive(timeout=10)
101
+
102
+ istemci.close()
103
+ sunucu.close()
104
+ ```
105
+
106
+ ### Callback ile mesaj alma
107
+
108
+ ```python
109
+ @npien.on_message
110
+ def mesaj_geldi(veri: bytes, adres: tuple[str, int]):
111
+ print(adres, veri.decode(errors="replace"))
112
+ ```
113
+
114
+ Callback'ler transport thread'inde çalışır; ağır işleri ayrı bir thread/kuyruğa
115
+ devredin.
116
+
117
+ ## API
118
+
119
+ ### Modül seviyesi (varsayılan örnek)
120
+
121
+ | Fonksiyon | Açıklama |
122
+ | --- | --- |
123
+ | `set_appid(appid)` | Uygulama kimliğini ayarlar. Ticket HMAC'i ve oda ad alanı buna bağlıdır. |
124
+ | `set_name(name)` | Görünen ad (HELLO/ticket içinde taşınır). |
125
+ | `listen(room, advertise=True)` | Odayı dinlemeye başlar; `advertise` ise kendi ticket'ını kayıt defterine yazar. |
126
+ | `join_room(room)` | `listen` ile aynı. |
127
+ | `connect(room, peer=None, ticket=None, tickets=None, timeout=8.0, discover=True)` | Odaya bağlanır; bağlı peer'ların listesini döner. |
128
+ | `send(data, to=None)` | Varsayılan olarak odadaki tüm peer'lara gönderir. `to` bir oda adı veya `(ip, port)` olabilir. |
129
+ | `sendto(data, peer)` | Belirli bir peer'a gönderir. |
130
+ | `receive(timeout=None)` | `(bytes, (ip, port))` döner. |
131
+ | `receive_nowait()` | Bloklamadan dener; mesaj yoksa `TimeoutError`. |
132
+ | `advsecure(enabled=True)` | Giden mesajlarda E2EE'yi açar/kapatır. |
133
+ | `create_ticket(room)` | Paylaşılabilir ticket üretir; STUN keşfini tetikler. |
134
+ | `add_peer(ticket)` | Ticket'ı kayıt defterine ekler (odadaki diğer süreçler bulabilir). |
135
+ | `known_peers(room)` | Kayıt defterindeki ticket'ları döner. |
136
+ | `peers(room=None)` | Bağlı/bağlanan peer'ların `PeerInfo` listesi. |
137
+ | `on_message(callback)` | Gelen her mesaj için callback kaydeder. |
138
+ | `get_stun_info()` | Dış IP/port, yerel adres, NAT tipi ve STUN sunucuları. |
139
+ | `connection_info()` | Uygulama, oda, güvenlik ve peer özeti. |
140
+ | `disconnect(target=None)` | Peer/peer'ları ayırır. |
141
+ | `close()` | Kaynakları kapatır ve kayıt defteri girdilerini siler. |
142
+
143
+ ### `connect` parametreleri
144
+
145
+ - `peer`: `("1.2.3.4", 5678)` veya `"1.2.3.4:5678"` ya da bunların listesi.
146
+ - `ticket` / `tickets`: `create_ticket` çıktısı; açık anahtar pinlenir.
147
+ - `timeout`: delik açma için toplam süre (saniye).
148
+ - `discover`: `True` ise kayıt defteri + LAN broadcast keşfi yapılır.
149
+
150
+ ## Nasıl çalışır?
151
+
152
+ 1. **STUN**: Ana UDP soketi ile Google STUN sunucularına Binding Request
153
+ gönderilir; XOR-MAPPED-ADDRESS'ten dış uç nokta öğrenilir. Aynı soket
154
+ kullanıldığı için NAT eşlemesi hole punching ile birebir aynıdır.
155
+ 2. **Ticket**: Dış adres, yerel adres, uygulama kimliği, oda ve X25519 açık
156
+ anahtarı HMAC-SHA256 ile imzalanarak tek bir metne paketlenir.
157
+ 3. **Hole punching**: Her iki taraf aday adreslere (dış + yerel) 250 ms'de bir
158
+ HELLO gönderir. NAT eşlemesi açılınca HELLO/HELLO_ACK alışverişi oturumu kurar.
159
+ 4. **Oturum**: Oturum kimliği iki açık anahtarın sıralı hash'inden türer. Anahtar
160
+ X25519 + HKDF-SHA256 ile türetilir.
161
+ 5. **Veri**: `NPN1` başlıklı paketler; 1200 baytlık datagramlara parçalanır.
162
+ Şifreli modda AES-256-GCM (12 baytlık nonce, oturuma bağlı AAD) kullanılır.
163
+ 6. **Canlılık**: 10 saniyede bir PING/PONG; 45 saniye sessiz peer düşürülür.
164
+ 7. **Keşif**: Aynı makinede `~/.npien/registry` altındaki kilitli JSON kayıtları;
165
+ LAN'de 47777/UDP broadcast ve ticket yanıtları. `NPIEN_HOME` ve
166
+ `NPIEN_DISCOVERY_PORT` ile değiştirilebilir.
167
+
168
+ Paket başlığı (28 bayt):
169
+
170
+ ```text
171
+ NPN1 | version | type | flags | reserved | session(8) | msg_id(8) | frag_index(2) | frag_count(2)
172
+ ```
173
+
174
+ ## Sınırlamalar
175
+
176
+ - **Simetrik NAT**: Her hedef için farklı dış port atayan NAT'larda doğrudan
177
+ hole punching çoğu zaman başarısız olur. Bu durumda TURN benzeri bir relay
178
+ gerekir; `npien` şu an relay içermez.
179
+ - **Sinyalleşme**: İnternet üzerinde iki tarafın uç noktalarını öğrenmesi için
180
+ bir paylaşım kanalı (ticket) gerekir. LAN içinde broadcast, aynı makinede
181
+ kayıt defteri otomatik çalışır.
182
+ - **Güvenilirlik**: UDP semantiği geçerlidir; sıralama/teslim garantisi yoktur.
183
+ Uygulama katmanında gerekirse yeniden gönderim ekleyin.
184
+ - **Kimlik doğrulama**: Ticket ile açık anahtar pinlenir. Ticket'ı güvenilir bir
185
+ kanaldan paylaşın; aksi halde TOFU (ilk kullanımda güven) geçerlidir ve aktif
186
+ MITM engellenemez.
187
+ - IPv4 ve tek ağ arayüzü varsayılır.
188
+
189
+ ## Test
190
+
191
+ ```bash
192
+ python -m pytest -q
193
+ ```
194
+
195
+ Testler; paket çerçeveleme, şifreleme/ticket doğrulama, STUN ayrıştırma, kayıt
196
+ defteri ve gerçek UDP loopback üzerinden hole punching + şifreli mesajlaşmayı
197
+ kapsar.
198
+
199
+ ## Örnek uygulama
200
+
201
+ `examples/chat.py`:
202
+
203
+ ```bash
204
+ python examples/chat.py --room 492109 --name ali --secure
205
+ # başka terminal / makine:
206
+ python examples/chat.py --room 492109 --name ayse --ticket "npn1...." --secure
207
+ ```
208
+
209
+ ## Lisans
210
+
211
+ MIT
@@ -0,0 +1,148 @@
1
+ from __future__ import annotations
2
+
3
+ from .core import Npien, PeerInfo
4
+ from .crypto import Ticket
5
+ from .exceptions import (
6
+ ConnectionTimeoutError,
7
+ NotConnectedError,
8
+ NpienError,
9
+ PeerNotFoundError,
10
+ ProtocolError,
11
+ TicketError,
12
+ )
13
+
14
+ __version__ = "1.0.0"
15
+
16
+ _default: Npien | None = None
17
+
18
+
19
+ def default() -> Npien:
20
+ global _default
21
+ if _default is None:
22
+ _default = Npien()
23
+ return _default
24
+
25
+
26
+ def set_appid(appid: str) -> Npien:
27
+ return default().set_appid(appid)
28
+
29
+
30
+ def set_name(name: str) -> Npien:
31
+ return default().set_name(name)
32
+
33
+
34
+ def connect(room: str, peer=None, ticket: str | None = None, tickets=None,
35
+ timeout: float = 8.0, discover: bool = True):
36
+ return default().connect(
37
+ room,
38
+ peer=peer,
39
+ ticket=ticket,
40
+ tickets=tickets,
41
+ timeout=timeout,
42
+ discover=discover,
43
+ )
44
+
45
+
46
+ def listen(room: str, advertise: bool = True) -> Npien:
47
+ return default().listen(room, advertise=advertise)
48
+
49
+
50
+ def join_room(room: str, advertise: bool = True) -> Npien:
51
+ return default().join_room(room, advertise=advertise)
52
+
53
+
54
+ def send(data, to=None) -> int:
55
+ return default().send(data, to=to)
56
+
57
+
58
+ def sendto(data, peer) -> int:
59
+ return default().sendto(data, peer)
60
+
61
+
62
+ def receive(timeout: float | None = None):
63
+ return default().receive(timeout=timeout)
64
+
65
+
66
+ def receive_nowait():
67
+ return default().receive_nowait()
68
+
69
+
70
+ def advsecure(enabled: bool = True) -> Npien:
71
+ return default().advsecure(enabled)
72
+
73
+
74
+ def disablesecure() -> Npien:
75
+ return default().disablesecure()
76
+
77
+
78
+ def create_ticket(room: str | None = None) -> str:
79
+ return default().create_ticket(room)
80
+
81
+
82
+ def add_peer(ticket: str) -> None:
83
+ return default().add_peer(ticket)
84
+
85
+
86
+ def known_peers(room: str | None = None):
87
+ return default().known_peers(room)
88
+
89
+
90
+ def peers(room: str | None = None):
91
+ return default().peers(room)
92
+
93
+
94
+ def on_message(callback):
95
+ return default().on_message(callback)
96
+
97
+
98
+ def get_stun_info() -> dict:
99
+ return default().get_stun_info()
100
+
101
+
102
+ def connection_info() -> dict:
103
+ return default().connection_info()
104
+
105
+
106
+ def disconnect(target=None) -> None:
107
+ return default().disconnect(target)
108
+
109
+
110
+ def close() -> None:
111
+ global _default
112
+ if _default is not None:
113
+ _default.close()
114
+ _default = None
115
+
116
+
117
+ __all__ = [
118
+ "Npien",
119
+ "PeerInfo",
120
+ "Ticket",
121
+ "NpienError",
122
+ "ProtocolError",
123
+ "TicketError",
124
+ "NotConnectedError",
125
+ "PeerNotFoundError",
126
+ "ConnectionTimeoutError",
127
+ "default",
128
+ "set_appid",
129
+ "set_name",
130
+ "connect",
131
+ "listen",
132
+ "join_room",
133
+ "send",
134
+ "sendto",
135
+ "receive",
136
+ "receive_nowait",
137
+ "advsecure",
138
+ "disablesecure",
139
+ "create_ticket",
140
+ "add_peer",
141
+ "known_peers",
142
+ "peers",
143
+ "on_message",
144
+ "get_stun_info",
145
+ "connection_info",
146
+ "disconnect",
147
+ "close",
148
+ ]