From: "Rémi Denis-Courmont" <remi@remlab.net> To: ffmpeg-devel@ffmpeg.org Subject: Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option Date: Thu, 02 Mar 2023 20:47:52 +0200 Message-ID: <2370995.qZ0jSbpfxB@basile.remlab.net> (raw) In-Reply-To: <20230301154456.3407862-1-jack.wgm@gmail.com> Le keskiviikkona 1. maaliskuuta 2023, 17.44.56 EET jackarain a écrit : > Signed-off-by: jackarain <jack.wgm@gmail.com> > --- > doc/protocols.texi | 6 +++++ > libavformat/network.c | 14 ++++++++---- > libavformat/network.h | 2 +- > libavformat/tcp.c | 53 ++++++++++++++++++++++++++++++++++++++++++- > 4 files changed, 69 insertions(+), 6 deletions(-) > > diff --git a/doc/protocols.texi b/doc/protocols.texi > index 21ae6181a0..b3fad55591 100644 > --- a/doc/protocols.texi > +++ b/doc/protocols.texi > @@ -1882,6 +1882,12 @@ The list of supported options follows. > Listen for an incoming connection. 0 disables listen, 1 enables listen in > single client mode, 2 enables listen in multi-client mode. Default value is > 0. > > +@item local_addr=@var{addr} > +Local IP address of a network interface used for tcp socket connect. > + > +@item local_port=@var{port} > +Local port used for tcp socket connect. > + > @item timeout=@var{microseconds} > Set raise error timeout, expressed in microseconds. > > diff --git a/libavformat/network.c b/libavformat/network.c > index 21e20b3e9a..de8b14be82 100644 > --- a/libavformat/network.c > +++ b/libavformat/network.c > @@ -356,7 +356,7 @@ struct ConnectionAttempt { > static int start_connect_attempt(struct ConnectionAttempt *attempt, > struct addrinfo **ptr, int timeout_ms, > URLContext *h, > - void (*customize_fd)(void *, int), void > *customize_ctx) + int (*customize_fd)(void > *, int), void *customize_ctx) { > struct addrinfo *ai = *ptr; > int ret; > @@ -371,8 +371,14 @@ static int start_connect_attempt(struct > ConnectionAttempt *attempt, > > ff_socket_nonblock(attempt->fd, 1); > > - if (customize_fd) > - customize_fd(customize_ctx, attempt->fd); > + if (customize_fd) { > + ret = customize_fd(customize_ctx, attempt->fd); > + if (ret) { > + closesocket(attempt->fd); > + attempt->fd = -1; > + return ret; > + } > + } > > while ((ret = connect(attempt->fd, ai->ai_addr, ai->ai_addrlen))) { > ret = ff_neterrno(); > @@ -402,7 +408,7 @@ static int start_connect_attempt(struct > ConnectionAttempt *attempt, > > int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address, > int parallel, URLContext *h, int *fd, > - void (*customize_fd)(void *, int), void > *customize_ctx) + int (*customize_fd)(void *, int), > void *customize_ctx) { > struct ConnectionAttempt attempts[3]; > struct pollfd pfd[3]; > diff --git a/libavformat/network.h b/libavformat/network.h > index 71c49a73fb..8a8cbe672e 100644 > --- a/libavformat/network.h > +++ b/libavformat/network.h > @@ -336,6 +336,6 @@ void ff_log_net_error(void *ctx, int level, const char* > prefix); */ > int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address, > int parallel, URLContext *h, int *fd, > - void (*customize_fd)(void *, int), void > *customize_ctx); + int (*customize_fd)(void *, int), > void *customize_ctx); > > #endif /* AVFORMAT_NETWORK_H */ > diff --git a/libavformat/tcp.c b/libavformat/tcp.c > index a11ccbb913..a897174f6c 100644 > --- a/libavformat/tcp.c > +++ b/libavformat/tcp.c > @@ -36,6 +36,8 @@ typedef struct TCPContext { > const AVClass *class; > int fd; > int listen; > + char *local_port; > + char *local_addr; > int open_timeout; > int rw_timeout; > int listen_timeout; > @@ -52,6 +54,8 @@ typedef struct TCPContext { > #define E AV_OPT_FLAG_ENCODING_PARAM > static const AVOption options[] = { > { "listen", "Listen for incoming connections", > OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, > .flags = D|E }, + { "local_port", "Local port", > OFFSET(local_port), AV_OPT_TYPE_STRING, { .str = > NULL }, 0, 0, .flags = D|E }, + { "local_addr", "Local > address", OFFSET(local_addr), > AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, .flags = D|E }, { > "timeout", "set timeout (in microseconds) of socket I/O operations", > OFFSET(rw_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, > INT_MAX, .flags = D|E }, { "listen_timeout", "Connection awaiting timeout > (in milliseconds)", OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = > -1 }, -1, INT_MAX, .flags = D|E }, { "send_buffer_size", "Socket > send buffer size (in bytes)", OFFSET(send_buffer_size), > AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, .flags = D|E }, @@ > -70,9 +74,42 @@ static const AVClass tcp_class = { > .version = LIBAVUTIL_VERSION_INT, > }; > > -static void customize_fd(void *ctx, int fd) > +static int customize_fd(void *ctx, int fd) > { > TCPContext *s = ctx; > + > + if (s->local_addr || s->local_port) { > + struct addrinfo hints = { 0 }, *ai, *cur_ai; > + int ret; > + > + hints.ai_family = AF_UNSPEC; That needs to match the socket protocol family, or bind() will fail. > + hints.ai_socktype = SOCK_STREAM; > + > + ret = getaddrinfo(s->local_addr, s->local_port, &hints, &ai); > + if (ret) { > + av_log(ctx, AV_LOG_ERROR, > + "Failed to getaddrinfo local addr: %s port: %s err: %s\n", > + s->local_addr, s->local_port, gai_strerror(ret)); > + return ret; > + } > + > + cur_ai = ai; > + while (cur_ai) { > + ret = bind(fd, (struct sockaddr *)cur_ai->ai_addr, > (int)cur_ai->ai_addrlen); + if (ret) > + cur_ai = cur_ai->ai_next; > + else > + break; > + } > + freeaddrinfo(ai); > + > + if (ret) { > + av_log(ctx, AV_LOG_ERROR, > + "Failed to bind local addr: %s port: %s err: %s\n", > + s->local_addr, s->local_port, gai_strerror(ret)); > + return ret; > + } > + } > /* Set the socket's send or receive buffer sizes, if specified. > If unspecified or setting fails, system default is used. */ > if (s->recv_buffer_size > 0) { > @@ -97,6 +134,8 @@ static void customize_fd(void *ctx, int fd) > } > } > #endif /* !HAVE_WINSOCK2_H */ > + > + return 0; > } > > /* return non zero if error */ > @@ -129,6 +168,18 @@ static int tcp_open(URLContext *h, const char *uri, int > flags) if (buf == endptr) > s->listen = 1; > } > + if (av_find_info_tag(buf, sizeof(buf), "local_port", p)) { > + av_freep(&s->local_port); > + s->local_port = av_strdup(buf); > + if (!s->local_addr) > + return AVERROR(ENOMEM); > + } > + if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) { > + av_freep(&s->local_addr); > + s->local_addr = av_strdup(buf); > + if (!s->local_addr) > + return AVERROR(ENOMEM); > + } > if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { > s->rw_timeout = strtol(buf, NULL, 10); > } -- レミ・デニ-クールモン http://www.remlab.net/ _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
next prev parent reply other threads:[~2023-03-02 18:48 UTC|newest] Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-02-28 10:16 jack 2023-02-28 10:57 ` Nicolas George 2023-02-28 14:27 ` jackarain 2023-02-28 15:44 ` jackarain 2023-03-01 14:44 ` Anton Khirnov 2023-03-01 14:56 ` jackarain 2023-03-01 15:07 ` jackarain 2023-03-01 15:44 ` jackarain 2023-03-02 18:47 ` Rémi Denis-Courmont [this message] 2023-03-02 18:51 ` Nicolas George 2023-03-03 9:49 ` jackarain 2023-03-30 10:11 ` Anton Khirnov 2023-02-28 14:24 jackarain
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=2370995.qZ0jSbpfxB@basile.remlab.net \ --to=remi@remlab.net \ --cc=ffmpeg-devel@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git