Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"astisrt: Connection setup failure: connection timed out" while connecting for the second time #6

Closed
leandromoreira opened this issue Jan 29, 2024 · 9 comments

Comments

@leandromoreira
Copy link

leandromoreira commented Jan 29, 2024

Hi folks 👋 ,

Thanks for the library. I'm not sure if this is an issue or even related to the lib. Anyway, I'm using your library to learn a little bit of srt and web rtc.

A user inputs information about the SRT streaming, and the browser creates an p2p communication with the server. The server connects to the SRT and reads its stream and send it back to the web rtc channel.

sequenceDiagram
    actor User

    box Navy Browser
        participant browser
        participant donut-video
    end

    locahost8080->>+locahost8080: setup local ICE 8081/udp and 8081/tcp
    browser->>+locahost8080: GET /
    locahost8080->>+browser: 200 /index.html
    User->>+browser: feed SRT host, port, and id
    User->>+browser: click on [connect]
    browser->>+donut-video: play

    Note over locahost8080,donut-video: WebRTC connection setup

    donut-video->>+donut-video: web rtc createOffer
    donut-video->>+locahost8080: POST /doSignaling {srtOffer}
    locahost8080->>+locahost8080: process {srtOffer}
    locahost8080->>+locahost8080: create video track
    locahost8080->>+locahost8080: set remote {srtOffer}
    locahost8080->>+locahost8080: set local {answer}
    locahost8080->>+donut-video: {local description}

    Note over locahost8080,donut-video: WebRTC connection setup

    locahost8080->>+SRT: connect

    loop SRT to WebRTC
        locahost8080-->SRT: SRT | WebRTC
        locahost8080-->browser: WebRTC.WriteSample(SRT.PES.Data)
    end

    donut-video-->>donut-video: WebRTC.ontrack(video)
    donut-video-->>browser: renders video at the <video> tag
    browser-->>User: show frames
Loading

You can test that right now, it's working. For the first client.

git clone https://github.com/leandromoreira/donut
cd donut
git checkout refactor
make run
# open chrome on http://localhost:8080 and click on [connect]

But when I try to connect another browser tab, or even when I try to refresh the current page; it doesn't work, it raises an seemingly time out error.

astisrt: connecting failed: astisrt: connecting failed: astisrt: Connection setup failure: connection timed out

Just to help you see how the code flows:

  1. Here's where I connect to the SRT server
  2. Then I run a go routine to stream the data (from SRT to WebRTC) noticed that I finish the request cycle for the browser but the go routine keeps running in background streaming the data.
  3. Here's the unattached go routine that keep pulling data from SRT and sending to the WebRTC peer.

I have an hypothesis of unclosed stream, does SRT auto-closes an open stream after the listener stop pulling data? Or have any limitation about number of clients connecting at the same time?

Do you have any idea of why the program is raising an SRT timeout for the second time?

Thanks

@asticode
Copy link
Owner

When I run make run I get the following errors:

 > [app stage-1 7/7] RUN go build .:
0.207 go: downloading go.uber.org/zap v1.23.0
0.207 go: downloading github.com/kelseyhightower/envconfig v1.4.0
0.209 go: downloading go.uber.org/fx v1.20.1
0.234 go: downloading github.com/pion/webrtc/v3 v3.1.47
0.237 go: downloading github.com/asticode/go-astisrt v0.3.0
0.240 go: downloading github.com/asticode/go-astits v1.11.0
0.362 go: downloading github.com/szatmary/gocaption v0.0.0-20220607192049-fdd59655f0c3
1.326 go: downloading golang.org/x/sys v0.2.0
1.729 go: downloading go.uber.org/atomic v1.7.0
1.729 go: downloading go.uber.org/multierr v1.6.0
2.068 go: downloading go.uber.org/dig v1.17.0
2.073 go: downloading github.com/pion/rtp v1.7.13
2.073 go: downloading github.com/pion/dtls/v2 v2.1.5
2.074 go: downloading github.com/pion/datachannel v1.5.2
2.842 go: downloading github.com/pion/ice/v2 v2.2.11
3.011 go: downloading github.com/pion/interceptor v0.1.12
3.608 go: downloading github.com/pion/logging v0.2.2
3.662 go: downloading github.com/pion/randutil v0.1.0
3.989 go: downloading github.com/pion/rtcp v1.2.10
4.166 go: downloading github.com/pion/sctp v1.8.3
4.166 go: downloading github.com/pion/sdp/v3 v3.0.6
4.166 go: downloading github.com/pion/srtp/v2 v2.0.10
4.167 go: downloading github.com/pion/transport v0.13.1
4.622 go: downloading golang.org/x/net v0.2.0
4.657 go: downloading github.com/asticode/go-astikit v0.36.0
5.336 go: downloading github.com/pion/udp v0.1.1
5.336 go: downloading github.com/google/uuid v1.3.0
5.336 go: downloading github.com/pion/stun v0.3.5
5.337 go: downloading github.com/pion/mdns v0.0.5
5.338 go: downloading github.com/pion/turn/v2 v2.0.8
5.677 go: downloading golang.org/x/crypto v0.2.0
24.41 # github.com/flavioribeiro/donut
24.41 /usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
24.41 /usr/bin/ld: warning: libcrypto.so.1.1, needed by /opt/srt/lib//libsrt.so, not found (try using -rpath or -rpath-link)
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `AES_set_encrypt_key@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `PKCS5_PBKDF2_HMAC_SHA1@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `AES_encrypt@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `CRYPTO_ctr128_encrypt@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `AES_set_decrypt_key@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `AES_unwrap_key@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `RAND_bytes@OPENSSL_1_1_0'
24.41 /usr/bin/ld: /opt/srt/lib//libsrt.so: undefined reference to `AES_wrap_key@OPENSSL_1_1_0'
24.41 collect2: error: ld returned 1 exit status
24.41

Is there anything else I need to do? Without being able to reproduce the issue, it's pretty hard to pinpoint where the problem may be coming from.

@leandromoreira
Copy link
Author

leandromoreira commented Jan 30, 2024

Thanks. If you have a docker-compose you can run make run, but if you want to run it locally you must:

  1. make sure to install srt
  2. find where the headers and libraries are
    2.a sudo find / -name srt.h and sudo find / -name libsrt.so or libsrt.a
  3. pass the proper flags while running
    4.a CGO_LDFLAGS="-L/path/to/srt/1.5.3/lib -lsrt" CGO_CFLAGS="-I/path/to/srt/1.5.3/include/" go run main.go

@asticode
Copy link
Owner

I'm using docker compose and make run, that's when I see the errors I've shared 🤔 It seems they are openssl-related errors 🤔

@asticode
Copy link
Owner

FYI I had to change Dockerfile to the following to make it work:

FROM golang:1.19

ENV WD=/usr/src/app
ENV SRT_VERSION="v1.5.3"
ENV SRT_FOLDER="/opt/srt_lib"
WORKDIR ${WD}

RUN apt-get clean && apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
      tclsh pkg-config cmake libssl-dev build-essential git \
    && apt-get clean

RUN \
  mkdir -p "${SRT_FOLDER}" && \
  git clone --depth 1 --branch "${SRT_VERSION}" https://github.com/Haivision/srt && \
  cd srt && \
  ./configure --prefix=${SRT_FOLDER} $(configure) && \
  make && \
  make install

# To find where the srt.h and libsrt.so were you can
# find / -name srt.h
# find / -name libsrt.so
# inside the container docker run -it --rm -t <TAG_YOU_BUILT> bash
ENV GOPROXY=direct
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${SRT_FOLDER}/lib/"
ENV CGO_CFLAGS="-I${SRT_FOLDER}/include/"
ENV CGO_LDFLAGS="-L${SRT_FOLDER}/lib/"

COPY . ./donut
WORKDIR ${WD}/donut
RUN go build .
CMD ["/usr/src/app/donut/donut", "--enable-ice-mux=true"]

@asticode
Copy link
Owner

OK it seems to be related to srt-live-transmit that you're using as your srt server. Per their doc, if you use it in listener mode (which you are):

the "agent" waits to be contacted by any peer caller. Note that a listener can accept multiple callers, but srt-live-transmit does not use this ability; after the first connection, it no longer accepts new connections.

The important part being "after the first connection, it no longer accepts new connections".

Since you never seem to close the srt connection, even when webrtc connection closes (on page reload for instance), the second connection gets rejected. If I manually close the srt connection after 5 seconds for instance, reloading the page properly works.

You have several options here:

  • close the srt connection properly when the webrtc connection closes, it will allow you to handle pages reload. However it won't allow you to handle multiple tabs (if that were my project I wouldn't consider closing the srt connection properly an option, I would do it whatever happens)
  • use another srt server that does allow several connections at the same time (I don't know whether that's possible but why not simply output your ffmpeg command to srt directly and let ffmpeg be the srt server?)

@leandromoreira
Copy link
Author

leandromoreira commented Jan 30, 2024

Thanks a lot @asticode

close the srt connection properly when the webrtc connection closes

I think this is sensible regardless of the server situation, I'll do that.

I don't know whether that's possible but why not simply output your ffmpeg command to srt directly and let ffmpeg be the srt server?

That was my first attempt, I'll try it again and let you know.

@leandromoreira
Copy link
Author

FYI I had to change Dockerfile to the following to make it work:

FROM golang:1.19

ENV WD=/usr/src/app
ENV SRT_VERSION="v1.5.3"
ENV SRT_FOLDER="/opt/srt_lib"
WORKDIR ${WD}

RUN apt-get clean && apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
      tclsh pkg-config cmake libssl-dev build-essential git \
    && apt-get clean

RUN \
  mkdir -p "${SRT_FOLDER}" && \
  git clone --depth 1 --branch "${SRT_VERSION}" https://github.com/Haivision/srt && \
  cd srt && \
  ./configure --prefix=${SRT_FOLDER} $(configure) && \
  make && \
  make install

# To find where the srt.h and libsrt.so were you can
# find / -name srt.h
# find / -name libsrt.so
# inside the container docker run -it --rm -t <TAG_YOU_BUILT> bash
ENV GOPROXY=direct
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${SRT_FOLDER}/lib/"
ENV CGO_CFLAGS="-I${SRT_FOLDER}/include/"
ENV CGO_LDFLAGS="-L${SRT_FOLDER}/lib/"

COPY . ./donut
WORKDIR ${WD}/donut
RUN go build .
CMD ["/usr/src/app/donut/donut", "--enable-ice-mux=true"]

Weird, it's working locally, what did you have to change? the image source?

@asticode
Copy link
Owner

Weird, it's working locally, what did you have to change? the image source?

Initially there were 2 parts in the Dockerfile, one that built the srt library and the other, in which the built srt library was copied, that built the GO binary: I merged the 2. But I made the simplest changes to make the whole thing work, it didn't allow me to pinpoint what was the real problem.

@leandromoreira
Copy link
Author

Thanks a lot @asticode, I'll close this issue!

Just out of curiosity:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants