1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00
Commit graph

8724 commits

Author SHA1 Message Date
winlin
7b20e58272 Refine makefile. 2024-09-09 11:22:14 +08:00
winlin
2e7f2c2d78 Refine comments. 2024-09-09 11:17:30 +08:00
winlin
79161b91f0 Refine names. 2024-09-09 11:12:28 +08:00
winlin
62c280cbb3 Support SRT listen ep in UDP. 2024-09-09 10:56:22 +08:00
winlin
d5032f66fd Support parse listen endpoint. 2024-09-09 10:56:22 +08:00
winlin
79f090cc8f Refine comments. 2024-09-09 10:56:22 +08:00
winlin
8b64ebe901 Support static files. 2024-09-09 10:56:22 +08:00
winlin
e982852173 WaitGroup: Do not wait automatically. 2024-09-09 10:56:22 +08:00
winlin
1c10756200 Support proxy SRT media server. 2024-09-09 10:56:22 +08:00
winlin
ebdb0787b8 Support redis LB for WebRTC. 2024-09-09 10:56:22 +08:00
winlin
bf4b973093 Refine the logs. 2024-09-09 10:56:22 +08:00
winlin
5b6c9df785 Support proxy to webrtc media. 2024-09-09 10:56:22 +08:00
winlin
17f836a886 Support proxy to webrtc api. 2024-09-09 10:56:22 +08:00
winlin
68595a587d Refine RTMP streaming error. 2024-09-09 10:56:22 +08:00
winlin
d053b8101e Refine HTTP streaming error. 2024-09-09 10:56:22 +08:00
winlin
3d5db62132 Refine HLS error. 2024-09-09 10:56:22 +08:00
winlin
0dc47d9ec1 Support hls proxy via redis LB. 2024-09-09 10:56:22 +08:00
winlin
f05d3fe407 Refine HLS streaming. 2024-09-09 10:56:22 +08:00
winlin
3c5f6a4b23 Support HLS streaming with memory LB. 2024-09-09 10:56:22 +08:00
winlin
cc4fdb659f Fix bugs. 2024-09-09 10:56:22 +08:00
winlin
e3119286ac Refine errors for HTTP streaming. 2024-09-09 10:56:22 +08:00
winlin
2242bf05cd Refine error for HTTP stream. 2024-09-09 10:56:22 +08:00
winlin
1f6894799f Support proxy HTTP-FLV to backend. 2024-09-09 10:56:22 +08:00
winlin
c13e757030 Refine proxy error handler. 2024-09-09 10:56:22 +08:00
winlin
ef7020411c Support multiple errors. 2024-09-09 10:56:22 +08:00
winlin
960d1e69f7 Always set stream id. 2024-09-09 10:56:22 +08:00
winlin
e3cfc3b898 Support RTMP play or view client. 2024-09-09 10:56:22 +08:00
winlin
688bc56228 Support redis LB for large scale use scenarios. 2024-09-09 10:56:22 +08:00
winlin
82707ebd76 Use memory LB for simple use scenarios. 2024-09-09 10:56:22 +08:00
winlin
3269228e64 Support redis load balancer. 2024-09-09 10:56:22 +08:00
winlin
b8ded5a681 Refine the amf0 any API and RTMP. 2024-09-09 10:56:22 +08:00
winlin
fa39d74752 Refine default ports. 2024-09-09 10:56:22 +08:00
winlin
fc4b657901 Support proxy RTMP to backend. 2024-09-09 10:56:22 +08:00
winlin
b62b1e35fc Add SRS load balancer. 2024-09-09 10:56:22 +08:00
winlin
73a16e3239 Add system api server for proxy. 2024-09-09 10:56:22 +08:00
winlin
e00fcae0ee Support HTTP API server proxy. 2024-09-09 10:56:22 +08:00
winlin
9e43187762 Support FFmpeg RTMP publisher. 2024-09-09 10:56:22 +08:00
winlin
9b2e7343a5 Support RTMP proxy server. 2024-09-09 10:56:22 +08:00
winlin
a3aaa0b1c0 Add RTMP and AMF0 protocol stack. 2024-09-09 10:56:22 +08:00
winlin
650befdfa4 Refine code to files. 2024-09-09 10:56:22 +08:00
winlin
2eae020a94 Add HTTP server versions. 2024-09-09 10:56:22 +08:00
winlin
df04a8e6d1 Add errors for proxy server. 2024-09-09 10:56:22 +08:00
winlin
7aba30a27c Add version and signature. 2024-09-09 10:56:22 +08:00
winlin
19d6d54227 Add logger with context ID. 2024-09-09 10:56:22 +08:00
winlin
fdcd86c5d8 Proxy: Support proxy server for SRS. 2024-09-09 10:56:22 +08:00
Winlin
b475d552aa
Heartbeat: Report ports for proxy server. v5.0.215 v6.0.156 v7.0.15 (#4171)
The heartbeat of SRS is a timer that requests an HTTP URL. We can use
this heartbeat to report the necessary information for registering the
backend server with the proxy server.

```text
SRS(backend) --heartbeat---> Proxy server
```

A proxy server is a specialized load balancer for media servers. It
operates at the application level rather than the TCP level. For more
information about the proxy server, see issue #4158.

Note that we will merge this PR into SRS 5.0+, allowing the use of SRS
5.0+ as the backend server, not limited to SRS 7.0. However, the proxy
server is introduced in SRS 7.0.

It's also possible to implement a registration service, allowing you to
use other media servers as backend servers. For example, if you gather
information about an nginx-rtmp server and register it with the proxy
server, the proxy will forward RTMP streams to nginx-rtmp. The backend
server is not limited to SRS.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-09 10:37:41 +08:00
winlin
d70e7357cf Release v6.0-a1, 6.0 alpha1, v6.0.155, 169636 lines. 2024-09-01 17:04:13 +08:00
Winlin
15fbe45a9a
FLV: Refine source and http handler. v6.0.155 v7.0.14 (#4165)
1. Do not create a source when mounting FLV because it may not unmount
FLV when freeing the source. If you access the FLV stream without any
publisher, then wait for source cleanup and review the FLV stream again,
there is an annoying warning message.

```bash
# View HTTP FLV stream by curl, wait for stream to be ready.
# curl http://localhost:8080/live/livestream.flv -v >/dev/null
HTTP #0 127.0.0.1:58026 GET http://localhost:8080/live/livestream.flv, content-length=-1
new live source, stream_url=/live/livestream
http: mount flv stream for sid=/live/livestream, mount=/live/livestream.flv

# Cancel the curl and trigger source cleanup without http unmount.
client disconnect peer. ret=1007
Live: cleanup die source, id=[], total=1

# View the stream again, it fails.
# curl http://localhost:8080/live/livestream.flv -v >/dev/null
HTTP #0 127.0.0.1:58040 GET http://localhost:8080/live/livestream.flv, content-length=-1
serve error code=1097(NoSource)(No source found) : process request=0 : cors serve : serve http : no source for /live/livestream
serve_http() [srs_app_http_stream.cpp:641]
```

> Note: There is an inconsistency. The first time, you can access the
FLV stream and wait for the publisher, but the next time, you cannot.

2. Create a source when starting to serve the FLV client. We do not need
to create the source when creating the HTTP handler. Instead, we should
try to create the source in the cache or stream. Because the source
cleanup does not unmount the HTTP handler, the handler remains after the
source is destroyed. The next time you access the FLV stream, the source
is not found.

```cpp
srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(r.get(), server, live_source)) != srs_success) { }
    if ((err = http_mount(r.get())) != srs_success) { }

srs_error_t SrsBufferCache::cycle() {
    SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req);
    if (!live_source.get()) {
        return srs_error_new(ERROR_NO_SOURCE, "no source for %s", req->get_stream_url().c_str());
    }

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req);
    if (!live_source.get()) {
        return srs_error_new(ERROR_NO_SOURCE, "no source for %s", req->get_stream_url().c_str());
    }
```

> Note: We should not create the source in hijack, instead, we create it
in cache or stream:

```cpp
srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) {
    if ((err = http_mount(r.get())) != srs_success) { }

srs_error_t SrsBufferCache::cycle() {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) { }

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) { }
```

> Note: This fixes the failure and annoying warning message, and
maintains consistency by always waiting for the stream to be ready if
there is no publisher.

3. Fail the http request if the HTTP handler is disposing, and also keep
the handler entry when disposing the stream, because we should dispose
the handler entry and stream at the same time.

```cpp
srs_error_t SrsHttpStreamServer::http_mount(SrsRequest* r) {
        entry = streamHandlers[sid];
        if (entry->disposing) {
            return srs_error_new(ERROR_STREAM_DISPOSING, "stream is disposing");
        }

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    std::map<std::string, SrsLiveEntry*>::iterator it = streamHandlers.find(sid);
    SrsUniquePtr<SrsLiveEntry> entry(it->second);
    entry->disposing = true;
```

> Note: If the disposal process takes a long time, this will prevent
unexpected behavior or access to the resource that is being disposed of.

4. In edge mode, the edge ingester will unpublish the source when the
last consumer quits, which is actually triggered by the HTTP stream.
While it also waits for the stream to quit when the HTTP unmounts, there
is a self-destruction risk: the HTTP live stream object destroys itself.

```cpp
srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw); // Trigger destroy.

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    for (;;) { if (!cache->alive() && !stream->alive()) { break; } // A circle reference.
    mux.unhandle(entry->mount, stream.get()); // Free the SrsLiveStream itself.
```

> Note: It also introduces a circular reference in the object
relationships, the stream reference to itself when unmount:

```text
SrsLiveStream::serve_http 
    -> SrsLiveConsumer::~SrsLiveConsumer -> SrsEdgeIngester::stop 
    -> SrsLiveSource::on_unpublish -> SrsHttpStreamServer::http_unmount 
        -> SrsLiveStream::alive
```

> Note: We should use an asynchronous worker to perform the cleanup to
avoid the stream destroying itself and to prevent self-referencing.

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    entry->disposing = true;
    if ((err = async_->execute(new SrsHttpStreamDestroy(&mux, &streamHandlers, sid))) != srs_success) { }
```

> Note: This also ensures there are no circular references and no
self-destruction.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-01 13:02:07 +08:00
Winlin
740f0d38ec
Edge: Fix flv edge crash when http unmount. v6.0.154 v7.0.13 (#4166)
Edge FLV is not working because it is stuck in an infinite loop waiting.
Previously, there was no need to wait for exit since resources were not
being cleaned up. Now, since resources need to be cleaned up, it must
wait for all active connections to exit, which causes this issue.

To reproduce the issue, start SRS edge, run the bellow command and press
`CTRL+C` to stop the request:

```bash
curl http://localhost:8080/live/livestream.flv -v >/dev/null
```

It will cause edge to fetch stream from origin, and free the consumer
when client quit. When `SrsLiveStream::do_serve_http` return, it will
free the consumer:

```cpp
srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw);
```

Keep in mind that in this moment, the stream is alive, because only set
to not alive after this function return:

```cpp
    alive_viewers_++;
    err = do_serve_http(w, r); // Free 'this' alive stream.
    alive_viewers_--; // Crash here, because 'this' is freed.
```

When freeing the consumer, it will cause the source to unpublish and
attempt to free the HTTP handler, which ultimately waits for the stream
not to be alive:

```cpp
SrsLiveConsumer::~SrsLiveConsumer() {
    source_->on_consumer_destroy(this);

void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer* consumer) {
    if (consumers.empty()) {
        play_edge->on_all_client_stop();

void SrsLiveSource::on_unpublish() {
    handler->on_unpublish(req);

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    if (stream->entry) stream->entry->enabled = false;

    for (; i < 1024; i++) {
        if (!cache->alive() && !stream->alive()) {
            break;
        }
        srs_usleep(100 * SRS_UTIME_MILLISECONDS);
    }
```

After 120 seconds, it will free the stream and cause SRS to crash
because the stream is still active. In order to track this potential
issue, also add an important warning log:

```cpp
srs_warn("http: try to free a alive stream, cache=%d, stream=%d", cache->alive(), stream->alive());
```

SRS may crash if got this log.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-01 06:44:35 +08:00
Winlin
a7aa2eaf76
Fix #3767: RTMP: Do not response empty data packet. v6.0.153 v7.0.12 (#4162)
If SRS responds with this empty data packet, FFmpeg will receive an
empty stream, like `Stream #0:0: Data: none` in following logs:

```bash
ffmpeg -i rtmp://localhost:11935/live/livestream
#  Stream #0:0: Data: none
#  Stream #0:1: Audio: aac (LC), 44100 Hz, stereo, fltp, 30 kb/s
#  Stream #0:2: Video: h264 (High), yuv420p(progressive), 768x320 [SAR 1:1 DAR 12:5], 212 kb/s, 25 fps, 25 tbr, 1k tbn
```

This won't cause the player to fail, but it will inconvenience the user
significantly. It may also cause FFmpeg slower to analysis the stream,
see #3767

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-01 06:40:16 +08:00