[FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-03 Thread jackarain
Signed-off-by: jackarain 
---
 doc/protocols.texi|  6 +
 libavformat/network.c | 14 
 libavformat/network.h |  2 +-
 libavformat/tcp.c | 53 +--
 4 files changed, 68 insertions(+), 7 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..f752efc411 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, 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, ai->ai_family);
+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, int), void 
*customize_ctx)
 {
 struct ConnectionAttempt attempts[3];
 struct pollfd pfd[3];
diff --git a/libavformat/network.h b/libavformat/network.h
index 71c49a73fb..ca214087fc 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, int), void 
*customize_ctx);
 
 #endif /* AVFORMAT_NETWORK_H */
diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index a11ccbb913..a889633457 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,40 @@ 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, int family)
 {
 TCPContext *s = ctx;
+
+if (s->local_addr || s->local_port) {
+struct addrinfo hints = { 0 }, *ai, *cur_ai;
+int ret;
+
+hints.ai_family = 

Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-02 Thread Nicolas George
Rémi Denis-Courmont (12023-03-02):
> That needs to match the socket protocol family, or bind() will fail.

Oh, right! The proper way to work with getaddrinfo is to create the
socket afterwards based on its return, but staying within a family is a
good second best choice. Thanks for noticing.

Regards,

-- 
  Nicolas George


signature.asc
Description: PGP signature
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-02 Thread Rémi Denis-Courmont
Le keskiviikkona 1. maaliskuuta 2023, 17.44.56 EET jackarain a écrit :
> Signed-off-by: jackarain 
> ---
>  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)
>  {
>  

[FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-01 Thread jackarain
Signed-off-by: jackarain 
---
 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;
+hints.ai_socktype = 

[FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-01 Thread jackarain
Signed-off-by: jackarain 
---
 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..1987861353 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;
+int ret;
+
+hints.ai_family = AF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+
+

Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-01 Thread jackarain
Ok, thanks.

Anton Khirnov  于2023年3月1日周三 22:44写道:

> Quoting jackarain (2023-02-28 16:44:20)
> > -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;
> > +int ret;
> > +
> > +hints.ai_family = AF_UNSPEC;
> > +hints.ai_socktype = SOCK_STREAM;
> > +
> > +ret = getaddrinfo(s->local_addr, s->local_port, , );
> > +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;
> > +} else {
>
> nit: the else clause pointlessly adds an indentation level and serves no
> useful purpose
>
> > +struct addrinfo *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,14 @@ 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(>local_port);
> > +s->local_port = av_strndup(buf, strlen(buf));
>
> This does memory allocation, so the result should be checked. Also, it
> av_str_n_dup() gives you no advantages since you call strlen anyway.
> Just use av_strdup(). Same below.
>
> --
> Anton Khirnov
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-03-01 Thread Anton Khirnov
Quoting jackarain (2023-02-28 16:44:20)
> -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;
> +int ret;
> +
> +hints.ai_family = AF_UNSPEC;
> +hints.ai_socktype = SOCK_STREAM;
> +
> +ret = getaddrinfo(s->local_addr, s->local_port, , );
> +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;
> +} else {

nit: the else clause pointlessly adds an indentation level and serves no
useful purpose

> +struct addrinfo *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,14 @@ 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(>local_port);
> +s->local_port = av_strndup(buf, strlen(buf));

This does memory allocation, so the result should be checked. Also, it
av_str_n_dup() gives you no advantages since you call strlen anyway.
Just use av_strdup(). Same below.

-- 
Anton Khirnov
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-02-28 Thread jackarain
Signed-off-by: jackarain 
---
 doc/protocols.texi|  6 ++
 libavformat/network.c | 14 +
 libavformat/network.h |  2 +-
 libavformat/tcp.c | 49 ++-
 4 files changed, 65 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..f9900c56a7 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;
+int ret;
+
+hints.ai_family = AF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+
+  

Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-02-28 Thread jackarain
Done.

Nicolas George  于2023年2月28日周二 18:57写道:

> jack (12023-02-28):
> > Signed-off-by: jack 
> > ---
> >  libavformat/tcp.c | 44 
> >  1 file changed, 44 insertions(+)
>
> Thanks for the patch
>
> You neglected to update the documentation, and a few remarks below.
>
> >
> > diff --git a/libavformat/tcp.c b/libavformat/tcp.c
> > index a11ccbb913..598d61067e 100644
> > --- a/libavformat/tcp.c
> > +++ b/libavformat/tcp.c
> > @@ -36,6 +36,8 @@ typedef struct TCPContext {
> >  const AVClass *class;
> >  int fd;
> >  int listen;
> > +int 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_INT,{ .i64 = -1 },  -1,
> INT_MAX, .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 },
> > @@ -73,6 +77,39 @@ static const AVClass tcp_class = {
> >  static void customize_fd(void *ctx, int fd)
> >  {
> >  TCPContext *s = ctx;
> > +
>
> > +if (s->local_addr) {
>
> s->local_addr || s->local_port
>
> > +struct addrinfo hints = { 0 }, *ai;
> > +int ret;
> > +int port = 0;
> > +
> > +hints.ai_family = AF_UNSPEC;
> > +hints.ai_socktype = SOCK_STREAM;
> > +
> > +if (s->local_port > 0)
> > +port = s->local_port;
> > +
>
> > +ret = getaddrinfo(s->local_addr, "0", , );
>
> The provided port should be used instead of this "0", and be a string,
> and named service.
>
> (The remote port should be a string too, alas.)
>
> > +if (ret) {
>
> > +av_log(ctx, AV_LOG_WARNING,
> > +   "Failed to bind local addr: %s port: %d err: %s\n",
> > +s->local_addr, s->local_port, gai_strerror(ret));
>
> Should be an error: failing to bind on the specified address can be a
> security issue. And the error message is misleading.
>
> > +} else {
>
> > +if (ai->ai_family == AF_INET6) {
> > +struct sockaddr_in6 * sockaddr_v6 = (struct
> sockaddr_in6 *)ai->ai_addr;
> > +sockaddr_v6->sin6_port = htons(port);
> > +} else {
> > +struct sockaddr_in * sockaddr = (struct sockaddr_in
> *)ai->ai_addr;
> > +sockaddr->sin_port = htons(port);
> > +}
>
> Do not distinguish between protocols: ai_addr already contains all that
> is needed.
>
> > +ret = bind(fd, (struct sockaddr *)ai->ai_addr,
> (int)ai->ai_addrlen);
> > +if (ret) {
> > +av_log(ctx, AV_LOG_WARNING,
> > +"Failed to bind local addr: %s port: %d err: %s\n",
> > +s->local_addr, s->local_port, gai_strerror(ret));
> > +}
>
> You should be looping over the returned addresses.
>
> > +}
> > +}
> >  /* 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) {
> > @@ -129,6 +166,13 @@ 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)) {
> > +s->local_port = strtol(buf, NULL, 10);
> > +}
> > +if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) {
> > +av_freep(>local_addr);
> > +s->local_addr = av_strndup(buf, strlen(buf));
> > +}
> >  if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
> >  s->rw_timeout = strtol(buf, NULL, 10);
> >  }
>
> Regards,
>
> --
>   Nicolas George
>
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-02-28 Thread jackarain
Signed-off-by: jackarain 
---
 doc/protocols.texi|  6 ++
 libavformat/network.c | 14 +
 libavformat/network.h |  2 +-
 libavformat/tcp.c | 48 ++-
 4 files changed, 64 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..ceb5a10426 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,41 @@ 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;
+int ret;
+
+hints.ai_family = AF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+
+  

Re: [FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-02-28 Thread Nicolas George
jack (12023-02-28):
> Signed-off-by: jack 
> ---
>  libavformat/tcp.c | 44 
>  1 file changed, 44 insertions(+)

Thanks for the patch

You neglected to update the documentation, and a few remarks below.

> 
> diff --git a/libavformat/tcp.c b/libavformat/tcp.c
> index a11ccbb913..598d61067e 100644
> --- a/libavformat/tcp.c
> +++ b/libavformat/tcp.c
> @@ -36,6 +36,8 @@ typedef struct TCPContext {
>  const AVClass *class;
>  int fd;
>  int listen;
> +int 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_INT,{ .i64 = -1 },  -1, 
> INT_MAX, .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 },
> @@ -73,6 +77,39 @@ static const AVClass tcp_class = {
>  static void customize_fd(void *ctx, int fd)
>  {
>  TCPContext *s = ctx;
> +

> +if (s->local_addr) {

s->local_addr || s->local_port

> +struct addrinfo hints = { 0 }, *ai;
> +int ret;
> +int port = 0;
> +
> +hints.ai_family = AF_UNSPEC;
> +hints.ai_socktype = SOCK_STREAM;
> +
> +if (s->local_port > 0)
> +port = s->local_port;
> +

> +ret = getaddrinfo(s->local_addr, "0", , );

The provided port should be used instead of this "0", and be a string,
and named service.

(The remote port should be a string too, alas.)

> +if (ret) {

> +av_log(ctx, AV_LOG_WARNING,
> +   "Failed to bind local addr: %s port: %d err: %s\n",
> +s->local_addr, s->local_port, gai_strerror(ret));

Should be an error: failing to bind on the specified address can be a
security issue. And the error message is misleading.

> +} else {

> +if (ai->ai_family == AF_INET6) {
> +struct sockaddr_in6 * sockaddr_v6 = (struct sockaddr_in6 
> *)ai->ai_addr;
> +sockaddr_v6->sin6_port = htons(port);
> +} else {
> +struct sockaddr_in * sockaddr = (struct sockaddr_in 
> *)ai->ai_addr;
> +sockaddr->sin_port = htons(port);
> +}

Do not distinguish between protocols: ai_addr already contains all that
is needed.

> +ret = bind(fd, (struct sockaddr *)ai->ai_addr, 
> (int)ai->ai_addrlen);
> +if (ret) {
> +av_log(ctx, AV_LOG_WARNING,
> +"Failed to bind local addr: %s port: %d err: %s\n",
> +s->local_addr, s->local_port, gai_strerror(ret));
> +}

You should be looping over the returned addresses.

> +}
> +}
>  /* 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) {
> @@ -129,6 +166,13 @@ 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)) {
> +s->local_port = strtol(buf, NULL, 10);
> +}
> +if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) {
> +av_freep(>local_addr);
> +s->local_addr = av_strndup(buf, strlen(buf));
> +}
>  if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
>  s->rw_timeout = strtol(buf, NULL, 10);
>  }

Regards,

-- 
  Nicolas George
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".


[FFmpeg-devel] [PATCH] libavformat/tcp: add local_addr/local_port for network option

2023-02-28 Thread jack
Signed-off-by: jack 
---
 libavformat/tcp.c | 44 
 1 file changed, 44 insertions(+)

diff --git a/libavformat/tcp.c b/libavformat/tcp.c
index a11ccbb913..598d61067e 100644
--- a/libavformat/tcp.c
+++ b/libavformat/tcp.c
@@ -36,6 +36,8 @@ typedef struct TCPContext {
 const AVClass *class;
 int fd;
 int listen;
+int 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_INT,{ .i64 = -1 },  -1, INT_MAX, 
.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 },
@@ -73,6 +77,39 @@ static const AVClass tcp_class = {
 static void customize_fd(void *ctx, int fd)
 {
 TCPContext *s = ctx;
+
+if (s->local_addr) {
+struct addrinfo hints = { 0 }, *ai;
+int ret;
+int port = 0;
+
+hints.ai_family = AF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+
+if (s->local_port > 0)
+port = s->local_port;
+
+ret = getaddrinfo(s->local_addr, "0", , );
+if (ret) {
+av_log(ctx, AV_LOG_WARNING,
+   "Failed to bind local addr: %s port: %d err: %s\n",
+s->local_addr, s->local_port, gai_strerror(ret));
+} else {
+if (ai->ai_family == AF_INET6) {
+struct sockaddr_in6 * sockaddr_v6 = (struct sockaddr_in6 
*)ai->ai_addr;
+sockaddr_v6->sin6_port = htons(port);
+} else {
+struct sockaddr_in * sockaddr = (struct sockaddr_in 
*)ai->ai_addr;
+sockaddr->sin_port = htons(port);
+}
+ret = bind(fd, (struct sockaddr *)ai->ai_addr, 
(int)ai->ai_addrlen);
+if (ret) {
+av_log(ctx, AV_LOG_WARNING,
+"Failed to bind local addr: %s port: %d err: %s\n",
+s->local_addr, s->local_port, gai_strerror(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) {
@@ -129,6 +166,13 @@ 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)) {
+s->local_port = strtol(buf, NULL, 10);
+}
+if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) {
+av_freep(>local_addr);
+s->local_addr = av_strndup(buf, strlen(buf));
+}
 if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) {
 s->rw_timeout = strtol(buf, NULL, 10);
 }
-- 
2.39.2

___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".