Metadata-Version: 2.4
Name: opensip
Version: 0.1.0
Summary: Pure-Python SIP/RTP user-agent library (UAC + UAS) with asyncio
Project-URL: Homepage, https://github.com/artan/opensip
Project-URL: Issues, https://github.com/artan/opensip/issues
Author: artan
License: MIT
License-File: LICENSE
Keywords: asyncio,rtp,sip,telephony,voip
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Telecommunications Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Internet Phone
Classifier: Topic :: Communications :: Telephony
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: audio
Requires-Dist: numpy>=1.24; extra == 'audio'
Requires-Dist: sounddevice>=0.4.6; extra == 'audio'
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=7; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# opensip

Pure-Python SIP/RTP user-agent library. Asyncio tabanlı, UAC + UAS + REGISTER + digest auth desteği ile. G.711 (PCMU/PCMA) codec'ler numpy varsa vektörize edilmiş LUT ile çalışır (~13–25× hızlanma, 20 ms ptime başına ~1 µs); opsiyonel `sounddevice` extras ile gerçek mikrofon/hoparlör.

> Durum: erken alfa. API değişebilir. Gerçek bir Türk bulut-PBX provider'ı (netsantral.com) üzerinden uçtan uca iki yönlü ses ile test edildi; aşağıdaki "Bilinen sınırlamalar" bölümünü okumadan production'a almayın.

## Kurulum

Henüz PyPI'de değil; doğrudan git'ten kurun:

```bash
pip install git+https://github.com/artan/opensip.git
pip install "git+https://github.com/artan/opensip.git#egg=opensip[audio]"   # + ses
```

## Hızlı başlangıç — giden arama

```python
import asyncio
from opensip import UserAgent, Account

async def main():
    ua = UserAgent(local_addr=("0.0.0.0", 5060))
    await ua.start()

    acc = Account(
        username="alice",
        domain="sip.example.com",
        password="s3cret",
        server=("sip.example.com", 5060),
    )
    await ua.register(acc)

    call = await ua.invite(acc, "sip:bob@sip.example.com")
    await call.wait_answered()
    await asyncio.sleep(10)
    await call.hangup()

    await ua.stop()

asyncio.run(main())
```

## Gelen arama

```python
import asyncio
from opensip import UserAgent, Account

async def main():
    ua = UserAgent(local_addr=("0.0.0.0", 5060))

    @ua.on_incoming_call
    async def handle(call):
        await call.answer()
        await call.wait_ended()

    await ua.start()
    acc = Account(username="alice", domain="sip.example.com",
                  password="s3cret", server=("sip.example.com", 5060))
    await ua.register(acc)
    await asyncio.Event().wait()  # forever

asyncio.run(main())
```

## Mimari

```
opensip/
├── message.py     # SIP request/response parser + serializer
├── headers.py     # Via, From, To, Contact, Call-ID, CSeq...
├── auth.py        # Digest authentication (MD5, qop=auth, SHA-256)
├── sdp.py         # SDP offer/answer
├── transport.py   # asyncio UDP transport
├── ua.py          # UserAgent — UAC + UAS facade, dialog state inline
├── rtp.py         # RTP packetization + sender loop
├── codecs.py      # G.711 µ-law / A-law (numpy hot path)
└── audio.py       # sounddevice wrapper (opsiyonel)
```

## Bilinen sınırlamalar

`opensip` v0.1 minimal-viable bir UA: gerçek bir provider ile çağrı yapar ama RFC 3261'in birkaç önemli parçası **henüz yok**. Bunlar üzerine bir telefon altyapısı kurmadan önce farkında olun.

- **Transaction katmanı yok** (RFC 3261 §17). UDP retransmission timer'ları (Timer A–K) yok — paket düşerse istek timeout'a düşer. LAN / kayıpsız ağda fark edilmez; internet üzerinden kaybedilen ilk INVITE'ı tekrar göndermez.
- **Dialog state machine sınırlı.** Re-INVITE (hold/resume), UPDATE, target refresh çalışmaz; route set INVITE/BYE/ACK'te kullanılmaz — uzun proxy zincirleri kırılır.
- **NAT handling client-side yok.** SDP `c=` satırına LAN IP yazılır; iki yönlü RTP yalnızca provider symmetric-RTP / SBC NAT handling yapıyorsa çalışır (netsantral yapıyor, çoğu yapmaz). rport/received Contact'a yansıtılmaz, STUN/ICE yok.
- **Yalnızca UDP.** TCP ve TLS yok; TLS-only provider'lar (örn. bazı Twilio konfigürasyonları) için kullanılamaz.
- **RTCP yok.** Jitter buffer yok — gelen RTP doğrudan callback'e gönderilir, out-of-order paket / sıralama boşluğu metrikleri yok.
- **DTMF yok.** RFC 2833 payload type 101 alınır ama sessizce düşürülür.
- **Codec sınırlı.** PCMU + PCMA + telephone-event (gönderme yok). Opus / G.722 / G.729 yok.
- **`Authorization` re-use yok.** Her INVITE/BYE'da yeniden challenge — küçük gecikme katar.

Tam yol haritası ve önceliklendirme için issue tracker'a bakın.

## Geliştirme

```bash
python3.12 -m venv .venv
.venv/bin/pip install -e ".[dev,audio]"
.venv/bin/pytest
```

Python 3.10+ gerekiyor. macOS Homebrew kullanıyorsan `brew install python@3.12`.

G.711 codec mikrobenchmark'ı için:

```bash
.venv/bin/python tests/bench_codecs.py
```

## Lisans

MIT
