void udp_populate_opts( obe_udp_opts_t *udp_opts, char *uri ) { char buf[256]; const char *p = strchr( uri, '?' ); memset( udp_opts, 0, sizeof(*udp_opts) ); if( p ) { if( av_find_info_tag( buf, sizeof(buf), "reuse", p ) ) { const char *endptr = NULL; udp_opts->reuse_socket = strtol( buf, (char **)&endptr, 10 ); /* assume if no digits were found it is a request to enable it */ if( buf == endptr ) udp_opts->reuse_socket = 1; } if( av_find_info_tag( buf, sizeof(buf), "ttl", p ) ) udp_opts->ttl = strtol( buf, NULL, 10 ); if( av_find_info_tag( buf, sizeof(buf), "localport", p ) ) udp_opts->local_port = strtol( buf, NULL, 10 ); if( av_find_info_tag( buf, sizeof(buf), "buffer_size", p ) ) udp_opts->buffer_size = strtol( buf, NULL, 10 ); if( av_find_info_tag( buf, sizeof(buf), "miface", p ) ) udp_opts->miface = if_nametoindex( buf ); } /* fill the dest addr */ av_url_split( NULL, 0, NULL, 0, udp_opts->hostname, sizeof(udp_opts->hostname), &udp_opts->port, NULL, 0, uri ); }
static int mtc_open(URLContext * h, const char *uri, int flags) { char path[1024]; char buf[1024]; const char *p; int error; MTCContext *c = h->priv_data; av_url_split(NULL, 0, NULL, 0, c->hostname, sizeof(c->hostname), &c->server_control_port, path, sizeof(path), uri); p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "authorization", p)) { av_strlcpy(c->credencials, buf, sizeof(c->credencials)); } } if (!s->conn_control) { ff_url_join(buf, sizeof(buf), "tcp", NULL, c->hostname, c->server_control_port,NULL); error = ffurl_open(&c->conn_control, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, NULL); if (erro < 0) { av_log(h, AV_LOG_ERROR, "Cannot open control connection\n"); return error; } } //授权 return 0; }
int ff_rtp_set_remote_url(URLContext *h, const char *uri) { RTPContext *s = h->priv_data; char hostname[256]; int port, rtcp_port; const char *p; char buf[1024]; char path[1024]; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); rtcp_port = port + 1; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { rtcp_port = strtol(buf, NULL, 10); } } ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path); ff_udp_set_remote_url(s->rtp_hd, buf); ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, rtcp_port, "%s", path); ff_udp_set_remote_url(s->rtcp_hd, buf); return 0; }
/** * If no filename is given to av_open_input_file because you want to * get the local port first, then you must call this function to set * the remote server address. * * url syntax: udp://host:port[?option=val...] * option: 'ttl=n' : set the ttl value (for multicast only) * 'localport=n' : set the local port * 'pkt_size=n' : set max packet size * 'reuse=1' : enable reusing the socket * * @param h media file context * @param uri of the remote server * @return zero if no error. */ int ff_udp_set_remote_url(URLContext *h, const char *uri) { UDPContext *s = h->priv_data; char hostname[256], buf[10]; int port; const char *p; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* set the destination address */ s->dest_addr_len = udp_set_url(&s->dest_addr, hostname, port); if (s->dest_addr_len < 0) { return AVERROR(EIO); } s->is_multicast = ff_is_multicast_address((struct sockaddr*) &s->dest_addr); p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { int was_connected = s->is_connected; s->is_connected = strtol(buf, NULL, 10); if (s->is_connected && !was_connected) { if (connect(s->udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { s->is_connected = 0; av_log(h, AV_LOG_ERROR, "connect: %s\n", strerror(errno)); return AVERROR(EIO); } } } } return 0; }
int main(int argc, const char * argv[]) { // insert code here... const char *uri = "?cafile=file1"; char buf[1024]; const char *p = strchr(uri, '?'); if (!p) return 0 ; char *ca_file; if ( av_find_info_tag(buf, sizeof(buf), "cafile", p)) ca_file = av_strdupll(buf); printf("%s\n",ca_file); AVCodecContext context; AVCodecContext *dec = &context; char *canvas_size = "qntsc"; if (canvas_size && av_parse_video_size(&dec->width, &dec->height, canvas_size) < 0) { } return 0; }
static void test_av_find_info_tag(void) { static const char args[] = "?tag1=val1&tag2=val2&tag3=val3&tag41=value 41&tag42=random1"; static const char *tags[] = {"tag1", "tag2", "tag3", "tag4", "tag41", "41", "random1"}; char buff[16]; int i; for (i = 0; i < FF_ARRAY_ELEMS(tags); ++i) { if (av_find_info_tag(buff, sizeof(buff), tags[i], args)) printf("%d. %s found: %s\n", i, tags[i], buff); else printf("%d. %s not found\n", i, tags[i]); } }
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options) { int port; const char *p; char buf[200], opts[50] = ""; struct addrinfo hints = { 0 }, *ai = NULL; const char *proxy_path; int use_proxy; if (c->listen) snprintf(opts, sizeof(opts), "?listen=1"); av_url_split(NULL, 0, NULL, 0, c->host, sizeof(c->host), &port, NULL, 0, uri); p = strchr(uri, '?'); if (!p) { p = opts; } else { if (av_find_info_tag(opts, sizeof(opts), "listen", p)) c->listen = 1; } ff_url_join(buf, sizeof(buf), "tcp", NULL, c->host, port, "%s", p); hints.ai_flags = AI_NUMERICHOST; if (!getaddrinfo(c->host, NULL, &hints, &ai)) { c->numerichost = 1; freeaddrinfo(ai); } proxy_path = getenv("http_proxy"); use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), c->host) && proxy_path && av_strstart(proxy_path, "http://", NULL); if (use_proxy) { char proxy_host[200], proxy_auth[200], dest[200]; int proxy_port; av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, proxy_path); ff_url_join(dest, sizeof(dest), NULL, NULL, c->host, port, NULL); ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, proxy_port, "/%s", dest); } return ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, &parent->interrupt_callback, options, parent->protocols, parent); }
static void set_options(URLContext *h, const char *uri) { TLSContext *c = h->priv_data; char buf[1024]; const char *p = strchr(uri, '?'); if (!p) return; if (!c->ca_file && av_find_info_tag(buf, sizeof(buf), "cafile", p)) c->ca_file = av_strdup(buf); if (!c->verify && av_find_info_tag(buf, sizeof(buf), "verify", p)) { char *endptr = NULL; c->verify = strtol(buf, &endptr, 10); if (buf == endptr) c->verify = 1; } if (!c->cert_file && av_find_info_tag(buf, sizeof(buf), "cert", p)) c->cert_file = av_strdup(buf); if (!c->key_file && av_find_info_tag(buf, sizeof(buf), "key", p)) c->key_file = av_strdup(buf); }
static int sctp_open(URLContext *h, const char *uri, int flags) { struct addrinfo *ai, *cur_ai; struct addrinfo hints = { 0 }; struct sctp_event_subscribe event = { 0 }; struct sctp_initmsg initparams = { 0 }; int port; int fd = -1; SCTPContext *s = h->priv_data; const char *p; char buf[256]; int ret, listen_socket = 0; char hostname[1024], proto[1024], path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto, "sctp")) return AVERROR(EINVAL); if (port <= 0 || port >= 65536) { av_log(s, AV_LOG_ERROR, "Port missing in uri\n"); return AVERROR(EINVAL); } s->max_streams = 0; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; if (av_find_info_tag(buf, sizeof(buf), "max_streams", p)) s->max_streams = strtol(buf, NULL, 10); } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; fd = socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP); if (fd < 0) goto fail; s->dest_addr_len = sizeof(s->dest_addr); if (listen_socket) { int fd1; ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); listen(fd, 100); fd1 = accept(fd, NULL, NULL); closesocket(fd); fd = fd1; } else ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); ff_socket_nonblock(fd, 1); event.sctp_data_io_event = 1; /* TODO: Subscribe to more event types and handle them */ if (setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS, &event, sizeof(event)) != 0) { av_log(h, AV_LOG_ERROR, "SCTP ERROR: Unable to subscribe to events\n"); goto fail; } if (s->max_streams) { initparams.sinit_max_instreams = s->max_streams; initparams.sinit_num_ostreams = s->max_streams; if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initparams, sizeof(initparams)) < 0) av_log(h, AV_LOG_ERROR, "SCTP ERROR: Unable to initialize socket max streams %d\n", s->max_streams); } h->priv_data = s; h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: ret = AVERROR(EIO); freeaddrinfo(ai); return ret; }
static int rtp_open(URLContext *h, const char *uri, int flags) { RTPContext *s = h->priv_data; int rtp_port, rtcp_port, ttl, connect, local_rtp_port, local_rtcp_port, max_packet_size; char hostname[256], include_sources[1024] = "", exclude_sources[1024] = ""; char buf[1024]; char path[1024]; const char *p; int i, max_retry_count = 3; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); /* extract parameters */ ttl = -1; rtcp_port = rtp_port+1; local_rtp_port = -1; local_rtcp_port = -1; max_packet_size = -1; connect = 0; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { rtcp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { local_rtp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) { local_rtp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { local_rtcp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { max_packet_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { connect = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { s->write_to_source = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { av_strlcpy(include_sources, buf, sizeof(include_sources)); rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); } if (av_find_info_tag(buf, sizeof(buf), "block", p)) { av_strlcpy(exclude_sources, buf, sizeof(exclude_sources)); rtp_parse_addr_list(h, buf, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); } } for (i = 0;i < max_retry_count;i++) { build_udp_url(buf, sizeof(buf), hostname, rtp_port, local_rtp_port, ttl, max_packet_size, connect, include_sources, exclude_sources); if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; local_rtp_port = ff_udp_get_local_port(s->rtp_hd); if(local_rtp_port == 65535) { local_rtp_port = -1; continue; } if (local_rtcp_port<0) { local_rtcp_port = local_rtp_port + 1; build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, connect, include_sources, exclude_sources); if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) { local_rtp_port = local_rtcp_port = -1; continue; } break; } build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, connect, include_sources, exclude_sources); if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; break; } /* just to ease handle access. XXX: need to suppress direct handle access */ s->rtp_fd = ffurl_get_file_handle(s->rtp_hd); s->rtcp_fd = ffurl_get_file_handle(s->rtcp_hd); h->max_packet_size = s->rtp_hd->max_packet_size; h->is_streamed = 1; return 0; fail: if (s->rtp_hd) ffurl_close(s->rtp_hd); if (s->rtcp_hd) ffurl_close(s->rtcp_hd); return AVERROR(EIO); }
/* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) { char hostname[1024], localaddr[1024] = ""; int port, udp_fd = -1, tmp, bind_ret = -1, dscp = -1; UDPContext *s = h->priv_data; int is_output; const char *p; char buf[256]; struct sockaddr_storage my_addr; socklen_t len; int i, num_include_sources = 0, num_exclude_sources = 0; char *include_sources[32], *exclude_sources[32]; h->is_streamed = 1; is_output = !(flags & AVIO_FLAG_READ); if (s->buffer_size < 0) s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE; if (s->sources) { if (parse_source_list(s->sources, include_sources, &num_include_sources, FF_ARRAY_ELEMS(include_sources))) goto fail; } if (s->block) { if (parse_source_list(s->block, exclude_sources, &num_exclude_sources, FF_ARRAY_ELEMS(exclude_sources))) goto fail; } if (s->pkt_size > 0) h->max_packet_size = s->pkt_size; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { char *endptr = NULL; s->reuse_socket = strtol(buf, &endptr, 10); /* assume if no digits were found it is a request to enable it */ if (buf == endptr) s->reuse_socket = 1; } if (av_find_info_tag(buf, sizeof(buf), "overrun_nonfatal", p)) { char *endptr = NULL; s->overrun_nonfatal = strtol(buf, &endptr, 10); /* assume if no digits were found it is a request to enable it */ if (buf == endptr) s->overrun_nonfatal = 1; if (!HAVE_PTHREAD_CANCEL) av_log(h, AV_LOG_WARNING, "'overrun_nonfatal' option was set but it is not supported " "on this build (pthread support is required)\n"); } if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) { s->udplite_coverage = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { s->local_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { s->pkt_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) { s->buffer_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->is_connected = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) { dscp = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "fifo_size", p)) { s->circular_buffer_size = strtol(buf, NULL, 10); if (!HAVE_PTHREAD_CANCEL) av_log(h, AV_LOG_WARNING, "'circular_buffer_size' option was set but it is not supported " "on this build (pthread support is required)\n"); } if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { av_strlcpy(localaddr, buf, sizeof(localaddr)); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { if (parse_source_list(buf, include_sources, &num_include_sources, FF_ARRAY_ELEMS(include_sources))) goto fail; } if (av_find_info_tag(buf, sizeof(buf), "block", p)) { if (parse_source_list(buf, exclude_sources, &num_exclude_sources, FF_ARRAY_ELEMS(exclude_sources))) goto fail; } if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p)) s->timeout = strtol(buf, NULL, 10); if (is_output && av_find_info_tag(buf, sizeof(buf), "broadcast", p)) s->is_broadcast = strtol(buf, NULL, 10); } /* handling needed to support options picking from both AVOption and URL */ s->circular_buffer_size *= 188; if (flags & AVIO_FLAG_WRITE) { h->max_packet_size = s->pkt_size; } else { h->max_packet_size = UDP_MAX_PKT_SIZE; } h->rw_timeout = s->timeout; /* fill the dest addr */ av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* XXX: fix av_url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { /* only accepts null hostname if input */ if (!(flags & AVIO_FLAG_READ)) goto fail; } else { if (ff_udp_set_remote_url(h, uri) < 0) goto fail; } if ((s->is_multicast || s->local_port <= 0) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; if (localaddr[0]) udp_fd = udp_socket_create(s, &my_addr, &len, localaddr); else udp_fd = udp_socket_create(s, &my_addr, &len, s->localaddr); if (udp_fd < 0) goto fail; s->local_addr_storage=my_addr; //store for future multicast join /* Follow the requested reuse option, unless it's multicast in which * case enable reuse unless explicitly disabled. */ if (s->reuse_socket > 0 || (s->is_multicast && s->reuse_socket < 0)) { s->reuse_socket = 1; if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0) goto fail; } if (s->is_broadcast) { #ifdef SO_BROADCAST if (setsockopt (udp_fd, SOL_SOCKET, SO_BROADCAST, &(s->is_broadcast), sizeof(s->is_broadcast)) != 0) #endif goto fail; } /* Set the checksum coverage for UDP-Lite (RFC 3828) for sending and receiving. * The receiver coverage has to be less than or equal to the sender coverage. * Otherwise, the receiver will drop all packets. */ if (s->udplite_coverage) { if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0) av_log(h, AV_LOG_WARNING, "socket option UDPLITE_SEND_CSCOV not available"); if (setsockopt (udp_fd, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV, &(s->udplite_coverage), sizeof(s->udplite_coverage)) != 0) av_log(h, AV_LOG_WARNING, "socket option UDPLITE_RECV_CSCOV not available"); } if (dscp >= 0) { dscp <<= 2; if (setsockopt (udp_fd, IPPROTO_IP, IP_TOS, &dscp, sizeof(dscp)) != 0) goto fail; } /* If multicast, try binding the multicast address first, to avoid * receiving UDP packets from other sources aimed at the same UDP * port. This fails on windows. This makes sending to the same address * using sendto() fail, so only do it if we're opened in read-only mode. */ if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) { bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len); } /* bind to the local address if not multicast or if the multicast * bind failed */ /* the bind is needed to give a port to the socket now */ if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) { log_net_error(h, AV_LOG_ERROR, "bind failed"); goto fail; } len = sizeof(my_addr); getsockname(udp_fd, (struct sockaddr *)&my_addr, &len); s->local_port = udp_port(&my_addr, len); if (s->is_multicast) { if (h->flags & AVIO_FLAG_WRITE) { /* output */ if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0) goto fail; } if (h->flags & AVIO_FLAG_READ) { /* input */ if (num_include_sources && num_exclude_sources) { av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n"); goto fail; } if (num_include_sources) { if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0) goto fail; } else { if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr,(struct sockaddr *)&s->local_addr_storage) < 0) goto fail; } if (num_exclude_sources) { if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0) goto fail; } } } if (is_output) { /* limit the tx buf size to limit latency */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)"); goto fail; } } else { /* set udp recv buffer size to the requested value (default 64K) */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) { log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)"); } len = sizeof(tmp); if (getsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, &len) < 0) { log_net_error(h, AV_LOG_WARNING, "getsockopt(SO_RCVBUF)"); } else { av_log(h, AV_LOG_DEBUG, "end receive buffer size reported is %d\n", tmp); if(tmp < s->buffer_size) av_log(h, AV_LOG_WARNING, "attempted to set receive buffer to size %d but it only ended up set as %d", s->buffer_size, tmp); } /* make the socket non-blocking */ ff_socket_nonblock(udp_fd, 1); } if (s->is_connected) { if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { log_net_error(h, AV_LOG_ERROR, "connect"); goto fail; } } for (i = 0; i < num_include_sources; i++) av_freep(&include_sources[i]); for (i = 0; i < num_exclude_sources; i++) av_freep(&exclude_sources[i]); s->udp_fd = udp_fd; #if HAVE_PTHREAD_CANCEL if (!is_output && s->circular_buffer_size) { int ret; /* start the task going */ s->fifo = av_fifo_alloc(s->circular_buffer_size); ret = pthread_mutex_init(&s->mutex, NULL); if (ret != 0) { av_log(h, AV_LOG_ERROR, "pthread_mutex_init failed : %s\n", strerror(ret)); goto fail; } ret = pthread_cond_init(&s->cond, NULL); if (ret != 0) { av_log(h, AV_LOG_ERROR, "pthread_cond_init failed : %s\n", strerror(ret)); goto cond_fail; } ret = pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h); if (ret != 0) { av_log(h, AV_LOG_ERROR, "pthread_create failed : %s\n", strerror(ret)); goto thread_fail; } s->thread_started = 1; } #endif return 0; #if HAVE_PTHREAD_CANCEL thread_fail: pthread_cond_destroy(&s->cond); cond_fail: pthread_mutex_destroy(&s->mutex); #endif fail: if (udp_fd >= 0) closesocket(udp_fd); av_fifo_freep(&s->fifo); for (i = 0; i < num_include_sources; i++) av_freep(&include_sources[i]); for (i = 0; i < num_exclude_sources; i++) av_freep(&exclude_sources[i]); return AVERROR(EIO); }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd = -1; TCPContext *s = h->priv_data; int listen_socket = 0; const char *p; char buf[256]; int ret; int timeout = 100, listen_timeout = -1; char hostname[1024],proto[1024],path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto, "tcp")) return AVERROR(EINVAL); if (port <= 0 || port >= 65536) { av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); return AVERROR(EINVAL); } p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { timeout = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { listen_timeout = strtol(buf, NULL, 10); } } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); if (listen_socket) hints.ai_flags |= AI_PASSIVE; if (!hostname[0]) ret = getaddrinfo(NULL, portstr, &hints, &ai); else ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; restart: fd = ff_socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) { ret = ff_neterrno(); goto fail; } if (listen_socket) { if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, listen_timeout, h)) < 0) { ret = fd; goto fail1; } } else { if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, timeout * 100, h, !!cur_ai->ai_next)) < 0) { if (ret == AVERROR_EXIT) goto fail1; else goto fail; } } h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); ret = 0; goto restart; } fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
static int sap_write_header(AVFormatContext *s) { struct SAPState *sap = s->priv_data; char host[1024], path[1024], url[1024], announce_addr[50] = ""; char *option_list; int port = 9875, base_port = 5004, i, pos = 0, same_port = 0, ttl = 255; AVFormatContext **contexts = NULL; int ret = 0; struct sockaddr_storage localaddr; socklen_t addrlen = sizeof(localaddr); int udp_fd; if (!ff_network_init()) return AVERROR(EIO); /* extract hostname and port */ av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &base_port, path, sizeof(path), s->filename); if (base_port < 0) base_port = 5004; /* search for options */ option_list = strrchr(path, '?'); if (option_list) { char buf[50]; if (av_find_info_tag(buf, sizeof(buf), "announce_port", option_list)) { port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "same_port", option_list)) { same_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "ttl", option_list)) { ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "announce_addr", option_list)) { av_strlcpy(announce_addr, buf, sizeof(announce_addr)); } } if (!announce_addr[0]) { struct addrinfo hints = { 0 }, *ai = NULL; hints.ai_family = AF_UNSPEC; if (getaddrinfo(host, NULL, &hints, &ai)) { av_log(s, AV_LOG_ERROR, "Unable to resolve %s\n", host); ret = AVERROR(EIO); goto fail; } if (ai->ai_family == AF_INET) { /* Also known as sap.mcast.net */ av_strlcpy(announce_addr, "224.2.127.254", sizeof(announce_addr)); #if HAVE_STRUCT_SOCKADDR_IN6 } else if (ai->ai_family == AF_INET6) { /* With IPv6, you can use the same destination in many different * multicast subnets, to choose how far you want it routed. * This one is intended to be routed globally. */ av_strlcpy(announce_addr, "ff0e::2:7ffe", sizeof(announce_addr)); #endif } else { freeaddrinfo(ai); av_log(s, AV_LOG_ERROR, "Host %s resolved to unsupported " "address family\n", host); ret = AVERROR(EIO); goto fail; } freeaddrinfo(ai); } contexts = av_mallocz(sizeof(AVFormatContext*) * s->nb_streams); if (!contexts) { ret = AVERROR(ENOMEM); goto fail; } s->start_time_realtime = av_gettime(); for (i = 0; i < s->nb_streams; i++) { URLContext *fd; ff_url_join(url, sizeof(url), "rtp", NULL, host, base_port, "?ttl=%d", ttl); if (!same_port) base_port += 2; ret = ffurl_open(&fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; } s->streams[i]->priv_data = contexts[i] = ff_rtp_chain_mux_open(s, s->streams[i], fd, 0); av_strlcpy(contexts[i]->filename, url, sizeof(contexts[i]->filename)); } ff_url_join(url, sizeof(url), "udp", NULL, announce_addr, port, "?ttl=%d&connect=1", ttl); ret = ffurl_open(&sap->ann_fd, url, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL); if (ret) { ret = AVERROR(EIO); goto fail; } udp_fd = ffurl_get_file_handle(sap->ann_fd); if (getsockname(udp_fd, (struct sockaddr*) &localaddr, &addrlen)) { ret = AVERROR(EIO); goto fail; } if (localaddr.ss_family != AF_INET #if HAVE_STRUCT_SOCKADDR_IN6 && localaddr.ss_family != AF_INET6 #endif ) { av_log(s, AV_LOG_ERROR, "Unsupported protocol family\n"); ret = AVERROR(EIO); goto fail; } sap->ann_size = 8192; sap->ann = av_mallocz(sap->ann_size); if (!sap->ann) { ret = AVERROR(EIO); goto fail; } sap->ann[pos] = (1 << 5); #if HAVE_STRUCT_SOCKADDR_IN6 if (localaddr.ss_family == AF_INET6) sap->ann[pos] |= 0x10; #endif pos++; sap->ann[pos++] = 0; /* Authentication length */ AV_WB16(&sap->ann[pos], av_get_random_seed()); pos += 2; if (localaddr.ss_family == AF_INET) { memcpy(&sap->ann[pos], &((struct sockaddr_in*)&localaddr)->sin_addr, sizeof(struct in_addr)); pos += sizeof(struct in_addr); #if HAVE_STRUCT_SOCKADDR_IN6 } else { memcpy(&sap->ann[pos], &((struct sockaddr_in6*)&localaddr)->sin6_addr, sizeof(struct in6_addr)); pos += sizeof(struct in6_addr); #endif } av_strlcpy(&sap->ann[pos], "application/sdp", sap->ann_size - pos); pos += strlen(&sap->ann[pos]) + 1; if (av_sdp_create(contexts, s->nb_streams, &sap->ann[pos], sap->ann_size - pos)) { ret = AVERROR_INVALIDDATA; goto fail; } av_freep(&contexts); av_log(s, AV_LOG_VERBOSE, "SDP:\n%s\n", &sap->ann[pos]); pos += strlen(&sap->ann[pos]); sap->ann_size = pos; if (sap->ann_size > sap->ann_fd->max_packet_size) { av_log(s, AV_LOG_ERROR, "Announcement too large to send in one " "packet\n"); goto fail; } return 0; fail: av_free(contexts); sap_write_close(s); return ret; }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints, *ai, *cur_ai; int port, fd = -1; TCPContext *s = NULL; int listen_socket = 0; const char *p; char buf[256]; int ret; socklen_t optlen; int timeout = 500, listen_timeout = -1; char hostname[1024],proto[1024],path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto, "tcp")) return AVERROR(EINVAL); if (port <= 0 || port >= 65536) { av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); return AVERROR(EINVAL); } p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { timeout = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { listen_timeout = strtol(buf, NULL, 10); } } memset(&hints, 0, sizeof(hints)); if(am_getconfig_bool_def("media.libplayer.ipv4only",1)) hints.ai_family = AF_INET; else hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); av_log(h, AV_LOG_INFO,"tcp will get address from dns!\n"); if (listen_socket) hints.ai_flags |= AI_PASSIVE; if (!hostname[0]) ret = getaddrinfo(NULL, portstr, &hints, &ai); else ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } av_log(h, AV_LOG_INFO,"resolved %s's ipaddress \n",hostname); cur_ai = ai; restart: ret = AVERROR(EIO); fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; if (listen_socket) { int fd1; int reuse = 1; struct pollfd lp = { fd, POLLIN, 0 }; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); if (ret) { ret = ff_neterrno(); goto fail1; } ret = listen(fd, 1); if (ret) { ret = ff_neterrno(); goto fail1; } ret = poll(&lp, 1, listen_timeout >= 0 ? listen_timeout : -1); if (ret <= 0) { ret = AVERROR(ETIMEDOUT); goto fail1; } fd1 = accept(fd, NULL, NULL); if (fd1 < 0) { ret = ff_neterrno(); goto fail1; } closesocket(fd); fd = fd1; ff_socket_nonblock(fd, 1); } else { redo: ff_socket_nonblock(fd, 1); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); } if (ret < 0) { struct pollfd p = {fd, POLLOUT, 0}; ret = ff_neterrno(); if (ret == AVERROR(EINTR)) { if (url_interrupt_cb()) { ret = AVERROR_EXIT; goto fail1; } goto redo; } if (ret != AVERROR(EINPROGRESS) && ret != AVERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ while(timeout--) { if (url_interrupt_cb()) { ret = AVERROR_EXIT; goto fail1; } ret = poll(&p, 1, 100); if (ret > 0) break; } if (ret <= 0) { av_log(h, AV_LOG_ERROR, "TCP connection to %s:%d timeout failed!\n", hostname, port); ret = AVERROR(ETIMEDOUT); goto fail; } /* test error */ optlen = sizeof(ret); if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) ret = AVUNERROR(ff_neterrno()); if (ret != 0) { char errbuf[100]; ret = AVERROR(ret); av_strerror(ret, errbuf, sizeof(errbuf)); av_log(h, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s, ret = %d\n", hostname, port, errbuf, ret); ret = AVERROR(ret); if(ret>0) ret = AVERROR(EIO); goto fail; } } av_log(h, AV_LOG_INFO,"tcp connect %s ok!\n",hostname); s = av_malloc(sizeof(TCPContext)); if (!s) { freeaddrinfo(ai); return AVERROR(ENOMEM); } h->priv_data = s; h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); goto restart; } fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
static int rtp_open(URLContext *h, const char *uri, int flags) { RTPContext *s = h->priv_data; int rtp_port, rtcp_port, ttl, connect, local_rtp_port, local_rtcp_port, max_packet_size; char hostname[256]; char buf[1024]; char path[1024]; const char *p; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); /* extract parameters */ ttl = -1; rtcp_port = rtp_port+1; local_rtp_port = -1; local_rtcp_port = -1; max_packet_size = -1; connect = 0; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { rtcp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { local_rtp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) { local_rtp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { local_rtcp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { max_packet_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { connect = strtol(buf, NULL, 10); } } build_udp_url(buf, sizeof(buf), hostname, rtp_port, local_rtp_port, ttl, max_packet_size, connect); if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; if (local_rtp_port>=0 && local_rtcp_port<0) local_rtcp_port = ff_udp_get_local_port(s->rtp_hd) + 1; build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, connect); if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle access */ s->rtp_fd = ffurl_get_file_handle(s->rtp_hd); s->rtcp_fd = ffurl_get_file_handle(s->rtcp_hd); h->max_packet_size = s->rtp_hd->max_packet_size; h->is_streamed = 1; return 0; fail: if (s->rtp_hd) ffurl_close(s->rtp_hd); if (s->rtcp_hd) ffurl_close(s->rtcp_hd); return AVERROR(EIO); }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd = -1; TCPContext *s = h->priv_data; int listen_socket = 0; const char *p; char buf[256]; int ret; socklen_t optlen; int timeout = 50; char hostname[1024],proto[1024],path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { timeout = strtol(buf, NULL, 10); } } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; restart: ret = AVERROR(EIO); fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; if (listen_socket) { int fd1; int reuse = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); if (ret) { ret = ff_neterrno(); goto fail1; } ret = listen(fd, 1); if (ret) { ret = ff_neterrno(); goto fail1; } fd1 = accept(fd, NULL, NULL); if (fd1 < 0) { ret = ff_neterrno(); goto fail1; } closesocket(fd); fd = fd1; ff_socket_nonblock(fd, 1); } else { redo: ff_socket_nonblock(fd, 1); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); } if (ret < 0) { struct pollfd p = {fd, POLLOUT, 0}; ret = ff_neterrno(); if (ret == AVERROR(EINTR)) { if (ff_check_interrupt(&h->interrupt_callback)) { ret = AVERROR_EXIT; goto fail1; } goto redo; } if (ret != AVERROR(EINPROGRESS) && ret != AVERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ while(timeout--) { if (ff_check_interrupt(&h->interrupt_callback)) { ret = AVERROR_EXIT; goto fail1; } ret = poll(&p, 1, 100); if (ret > 0) break; } if (ret <= 0) { ret = AVERROR(ETIMEDOUT); goto fail; } /* test error */ optlen = sizeof(ret); if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) ret = AVUNERROR(ff_neterrno()); if (ret != 0) { char errbuf[100]; ret = AVERROR(ret); av_strerror(ret, errbuf, sizeof(errbuf)); av_log(h, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s\n", hostname, port, errbuf); goto fail; } } h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); goto restart; } fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
static int rtp_open(URLContext *h, const char *uri, int flags) { RTPContext *s = h->priv_data; int rtp_port; char hostname[256], include_sources[1024] = "", exclude_sources[1024] = ""; char *sources = include_sources, *block = exclude_sources; char buf[1024]; char path[1024]; const char *p; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &rtp_port, path, sizeof(path), uri); /* extract parameters */ if (s->rtcp_port < 0) s->rtcp_port = rtp_port + 1; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { s->rtcp_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { s->local_rtpport = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) { s->local_rtpport = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { s->local_rtcpport = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { s->pkt_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->connect = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { s->write_to_source = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { av_strlcpy(include_sources, buf, sizeof(include_sources)); rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); } else { rtp_parse_addr_list(h, s->sources, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); sources = s->sources; } if (av_find_info_tag(buf, sizeof(buf), "block", p)) { av_strlcpy(exclude_sources, buf, sizeof(exclude_sources)); rtp_parse_addr_list(h, buf, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); } else { rtp_parse_addr_list(h, s->block, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); block = s->block; } } build_udp_url(s, buf, sizeof(buf), hostname, rtp_port, s->local_rtpport, sources, block); if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL, h->protocols, h) < 0) goto fail; if (s->local_rtpport >= 0 && s->local_rtcpport < 0) s->local_rtcpport = ff_udp_get_local_port(s->rtp_hd) + 1; build_udp_url(s, buf, sizeof(buf), hostname, s->rtcp_port, s->local_rtcpport, sources, block); if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL, h->protocols, h) < 0) goto fail; /* just to ease handle access. XXX: need to suppress direct handle access */ s->rtp_fd = ffurl_get_file_handle(s->rtp_hd); s->rtcp_fd = ffurl_get_file_handle(s->rtcp_hd); h->max_packet_size = s->rtp_hd->max_packet_size; h->is_streamed = 1; return 0; fail: if (s->rtp_hd) ffurl_close(s->rtp_hd); if (s->rtcp_hd) ffurl_close(s->rtcp_hd); return AVERROR(EIO); }
/* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) { char hostname[1024], localaddr[1024] = ""; int port, udp_fd = -1, tmp, bind_ret = -1; UDPContext *s = h->priv_data; int is_output; const char *p; char buf[256]; struct sockaddr_storage my_addr; socklen_t len; int reuse_specified = 0; int i, num_include_sources = 0, num_exclude_sources = 0; char *include_sources[32], *exclude_sources[32]; h->is_streamed = 1; h->max_packet_size = 1472; is_output = !(flags & AVIO_FLAG_READ); s->ttl = 16; s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { char *endptr = NULL; s->reuse_socket = strtol(buf, &endptr, 10); /* assume if no digits were found it is a request to enable it */ if (buf == endptr) s->reuse_socket = 1; reuse_specified = 1; } if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { s->local_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { h->max_packet_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) { s->buffer_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->is_connected = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { av_strlcpy(localaddr, buf, sizeof(localaddr)); } if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { if (parse_source_list(buf, include_sources, &num_include_sources, FF_ARRAY_ELEMS(include_sources))) goto fail; } if (av_find_info_tag(buf, sizeof(buf), "block", p)) { if (parse_source_list(buf, exclude_sources, &num_exclude_sources, FF_ARRAY_ELEMS(exclude_sources))) goto fail; } } /* fill the dest addr */ av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* XXX: fix av_url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { /* only accepts null hostname if input */ if (!(flags & AVIO_FLAG_READ)) goto fail; } else { if (ff_udp_set_remote_url(h, uri) < 0) goto fail; } if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; udp_fd = udp_socket_create(s, &my_addr, &len, localaddr); if (udp_fd < 0) goto fail; /* Follow the requested reuse option, unless it's multicast in which * case enable reuse unless explicitly disabled. */ if (s->reuse_socket || (s->is_multicast && !reuse_specified)) { s->reuse_socket = 1; if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0) goto fail; } /* If multicast, try binding the multicast address first, to avoid * receiving UDP packets from other sources aimed at the same UDP * port. This fails on windows. This makes sending to the same address * using sendto() fail, so only do it if we're opened in read-only mode. */ if (s->is_multicast && !(h->flags & AVIO_FLAG_WRITE)) { bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len); } /* bind to the local address if not multicast or if the multicast * bind failed */ /* the bind is needed to give a port to the socket now */ if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) { log_net_error(h, AV_LOG_ERROR, "bind failed"); goto fail; } len = sizeof(my_addr); getsockname(udp_fd, (struct sockaddr *)&my_addr, &len); s->local_port = udp_port(&my_addr, len); if (s->is_multicast) { if (h->flags & AVIO_FLAG_WRITE) { /* output */ if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0) goto fail; } if (h->flags & AVIO_FLAG_READ) { /* input */ if (num_include_sources && num_exclude_sources) { av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n"); goto fail; } if (num_include_sources) { if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0) goto fail; } else { if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) goto fail; } if (num_exclude_sources) { if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0) goto fail; } } } if (is_output) { /* limit the tx buf size to limit latency */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { log_net_error(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF)"); goto fail; } } else { /* set udp recv buffer size to the largest possible udp packet size to * avoid losing data on OSes that set this too low by default. */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) { log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF)"); } /* make the socket non-blocking */ ff_socket_nonblock(udp_fd, 1); } if (s->is_connected) { if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { log_net_error(h, AV_LOG_ERROR, "connect"); goto fail; } } for (i = 0; i < num_include_sources; i++) av_freep(&include_sources[i]); for (i = 0; i < num_exclude_sources; i++) av_freep(&exclude_sources[i]); s->udp_fd = udp_fd; return 0; fail: if (udp_fd >= 0) closesocket(udp_fd); for (i = 0; i < num_include_sources; i++) av_freep(&include_sources[i]); for (i = 0; i < num_exclude_sources; i++) av_freep(&exclude_sources[i]); return AVERROR(EIO); }
static int tls_open(URLContext *h, const char *uri, int flags) { TLSContext *c = h->priv_data; int ret; int port; const char *p; char buf[200], host[200], opts[50] = ""; int numerichost = 0; struct addrinfo hints = { 0 }, *ai = NULL; const char *proxy_path; int use_proxy; if ((ret = ff_tls_init()) < 0) return ret; if (c->listen) snprintf(opts, sizeof(opts), "?listen=1"); av_url_split(NULL, 0, NULL, 0, host, sizeof(host), &port, NULL, 0, uri); p = strchr(uri, '?'); if (!p) { p = opts; } else { if (av_find_info_tag(opts, sizeof(opts), "listen", p)) c->listen = 1; } ff_url_join(buf, sizeof(buf), "tcp", NULL, host, port, "%s", p); hints.ai_flags = AI_NUMERICHOST; if (!getaddrinfo(host, NULL, &hints, &ai)) { numerichost = 1; freeaddrinfo(ai); } proxy_path = getenv("http_proxy"); use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), host) && proxy_path && av_strstart(proxy_path, "http://", NULL); if (use_proxy) { char proxy_host[200], proxy_auth[200], dest[200]; int proxy_port; av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, proxy_path); ff_url_join(dest, sizeof(dest), NULL, NULL, host, port, NULL); ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, proxy_port, "/%s", dest); } ret = ffurl_open(&c->tcp, buf, AVIO_FLAG_READ_WRITE, &h->interrupt_callback, NULL); if (ret) goto fail; c->fd = ffurl_get_file_handle(c->tcp); #if CONFIG_GNUTLS gnutls_init(&c->session, c->listen ? GNUTLS_SERVER : GNUTLS_CLIENT); if (!c->listen && !numerichost) gnutls_server_name_set(c->session, GNUTLS_NAME_DNS, host, strlen(host)); gnutls_certificate_allocate_credentials(&c->cred); set_options(h, uri); if (c->ca_file) { ret = gnutls_certificate_set_x509_trust_file(c->cred, c->ca_file, GNUTLS_X509_FMT_PEM); if (ret < 0) av_log(h, AV_LOG_ERROR, "%s\n", gnutls_strerror(ret)); } #if GNUTLS_VERSION_MAJOR >= 3 else gnutls_certificate_set_x509_system_trust(c->cred); #endif gnutls_certificate_set_verify_flags(c->cred, c->verify ? GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT : 0); if (c->cert_file && c->key_file) { ret = gnutls_certificate_set_x509_key_file(c->cred, c->cert_file, c->key_file, GNUTLS_X509_FMT_PEM); if (ret < 0) { av_log(h, AV_LOG_ERROR, "Unable to set cert/key files %s and %s: %s\n", c->cert_file, c->key_file, gnutls_strerror(ret)); ret = AVERROR(EIO); goto fail; } } else if (c->cert_file || c->key_file) av_log(h, AV_LOG_ERROR, "cert and key required\n"); gnutls_credentials_set(c->session, GNUTLS_CRD_CERTIFICATE, c->cred); gnutls_transport_set_ptr(c->session, (gnutls_transport_ptr_t) (intptr_t) c->fd); gnutls_priority_set_direct(c->session, "NORMAL", NULL); while (1) { ret = gnutls_handshake(c->session); if (ret == 0) break; if ((ret = do_tls_poll(h, ret)) < 0) goto fail; } if (c->verify) { unsigned int status, cert_list_size; gnutls_x509_crt_t cert; const gnutls_datum_t *cert_list; if ((ret = gnutls_certificate_verify_peers2(c->session, &status)) < 0) { av_log(h, AV_LOG_ERROR, "Unable to verify peer certificate: %s\n", gnutls_strerror(ret)); ret = AVERROR(EIO); goto fail; } if (status & GNUTLS_CERT_INVALID) { av_log(h, AV_LOG_ERROR, "Peer certificate failed verification\n"); ret = AVERROR(EIO); goto fail; } if (gnutls_certificate_type_get(c->session) != GNUTLS_CRT_X509) { av_log(h, AV_LOG_ERROR, "Unsupported certificate type\n"); ret = AVERROR(EIO); goto fail; } gnutls_x509_crt_init(&cert); cert_list = gnutls_certificate_get_peers(c->session, &cert_list_size); gnutls_x509_crt_import(cert, cert_list, GNUTLS_X509_FMT_DER); ret = gnutls_x509_crt_check_hostname(cert, host); gnutls_x509_crt_deinit(cert); if (!ret) { av_log(h, AV_LOG_ERROR, "The certificate's owner does not match hostname %s\n", host); ret = AVERROR(EIO); goto fail; } } #elif CONFIG_OPENSSL c->ctx = SSL_CTX_new(c->listen ? TLSv1_server_method() : TLSv1_client_method()); if (!c->ctx) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } set_options(h, uri); if (c->ca_file) { if (!SSL_CTX_load_verify_locations(c->ctx, c->ca_file, NULL)) av_log(h, AV_LOG_ERROR, "SSL_CTX_load_verify_locations %s\n", ERR_error_string(ERR_get_error(), NULL)); } if (c->cert_file && !SSL_CTX_use_certificate_chain_file(c->ctx, c->cert_file)) { av_log(h, AV_LOG_ERROR, "Unable to load cert file %s: %s\n", c->cert_file, ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } if (c->key_file && !SSL_CTX_use_PrivateKey_file(c->ctx, c->key_file, SSL_FILETYPE_PEM)) { av_log(h, AV_LOG_ERROR, "Unable to load key file %s: %s\n", c->key_file, ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } // Note, this doesn't check that the peer certificate actually matches // the requested hostname. if (c->verify) SSL_CTX_set_verify(c->ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); c->ssl = SSL_new(c->ctx); if (!c->ssl) { av_log(h, AV_LOG_ERROR, "%s\n", ERR_error_string(ERR_get_error(), NULL)); ret = AVERROR(EIO); goto fail; } SSL_set_fd(c->ssl, c->fd); if (!c->listen && !numerichost) SSL_set_tlsext_host_name(c->ssl, host); while (1) { ret = c->listen ? SSL_accept(c->ssl) : SSL_connect(c->ssl); if (ret > 0) break; if (ret == 0) { av_log(h, AV_LOG_ERROR, "Unable to negotiate TLS/SSL session\n"); ret = AVERROR(EIO); goto fail; } if ((ret = do_tls_poll(h, ret)) < 0) goto fail; } #endif return 0; fail: TLS_free(c); if (c->tcp) ffurl_close(c->tcp); ff_tls_deinit(); return ret; }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints, *ai, *cur_ai; int port, fd = -1; TCPContext *s = NULL; int listen_socket = 0; const char *p; char buf[256]; int ret; socklen_t optlen; char hostname[1024],proto[1024],path[1024]; char portstr[10]; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) return AVERROR(EINVAL); p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) listen_socket = 1; } memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(NULL, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; restart: fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) goto fail; if (listen_socket) { int fd1; ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); listen(fd, 1); fd1 = accept(fd, NULL, NULL); closesocket(fd); fd = fd1; } else { redo: ff_socket_nonblock(fd, 1); //av_log (NULL, AV_LOG_INFO, "connecting....\n"); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); //av_log (NULL, AV_LOG_INFO, "connecting done.\n"); } if (ret < 0) { int timeout = 10; //1s timeout struct pollfd p = {fd, POLLOUT, 0}; if (ff_neterrno() == AVERROR(EINTR)) { if (url_interrupt_cb()) { ret = AVERROR_EXIT; goto fail1; } goto redo; } if (ff_neterrno() != AVERROR(EINPROGRESS) && ff_neterrno() != AVERROR(EAGAIN)) goto fail; /* wait until we are connected or until abort */ for(;;) { if (url_interrupt_cb()) { ret = AVERROR_EXIT; goto fail1; } ret = poll(&p, 1, 100); if (ret > 0) break; if(!--timeout){ av_log(NULL, AV_LOG_ERROR, "TCP open %s:%d timeout\n", hostname, port); goto fail; } } /* test error */ optlen = sizeof(ret); getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); if (ret != 0) { av_log(NULL, AV_LOG_ERROR, "TCP connection to %s:%d failed: %s\n", hostname, port, strerror(ret)); goto fail; } } s = av_malloc(sizeof(TCPContext)); if (!s) { ret = AVERROR(ENOMEM); goto fail1; } h->priv_data = s; h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); goto restart; } ret = AVERROR(EIO); fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd = -1; TCPContext *s = h->priv_data; const char *p; char buf[256]; int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; s->open_timeout = 5000000; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto, "tcp")) return AVERROR(EINVAL); if (port <= 0 || port >= 65536) { av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); return AVERROR(EINVAL); } p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) { char *endptr = NULL; s->listen = strtol(buf, &endptr, 10); /* assume if no digits were found it is a request to enable it */ if (buf == endptr) s->listen = 1; } if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { s->rw_timeout = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { s->listen_timeout = strtol(buf, NULL, 10); } } if (s->rw_timeout >= 0) { s->open_timeout = h->rw_timeout = s->rw_timeout; } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); if (s->listen) hints.ai_flags |= AI_PASSIVE; if (!hostname[0]) ret = getaddrinfo(NULL, portstr, &hints, &ai); else ret = getaddrinfo(hostname, portstr, &hints, &ai); if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; #if HAVE_STRUCT_SOCKADDR_IN6 // workaround for IOS9 getaddrinfo in IPv6 only network use hardcode IPv4 address can not resolve port number. if (cur_ai->ai_family == AF_INET6){ struct sockaddr_in6 * sockaddr_v6 = (struct sockaddr_in6 *)cur_ai->ai_addr; if (!sockaddr_v6->sin6_port){ sockaddr_v6->sin6_port = htons(port); } } #endif if (s->listen > 0) { while (cur_ai && fd < 0) { fd = ff_socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) { ret = ff_neterrno(); cur_ai = cur_ai->ai_next; } } if (fd < 0) goto fail1; customize_fd(s, fd); } if (s->listen == 2) { // multi-client if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0) goto fail1; } else if (s->listen == 1) { // single client if ((ret = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, s->listen_timeout, h)) < 0) goto fail1; // Socket descriptor already closed here. Safe to overwrite to client one. fd = ret; } else { ret = ff_connect_parallel(ai, s->open_timeout / 1000, 3, h, &fd, customize_fd, s); if (ret < 0) goto fail1; } h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }
/* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) { char hostname[1024]; int port, udp_fd = -1, tmp, bind_ret = -1; UDPContext *s = NULL; int is_output; const char *p; char buf[256]; struct sockaddr_storage my_addr; int len; int reuse_specified = 0; h->is_streamed = 1; h->max_packet_size = 1472; is_output = !(flags & AVIO_FLAG_READ); s = av_mallocz(sizeof(UDPContext)); if (!s) return AVERROR(ENOMEM); h->priv_data = s; s->ttl = 16; s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_MAX_PKT_SIZE; s->circular_buffer_size = 7*188*4096; p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { char *endptr=NULL; s->reuse_socket = strtol(buf, &endptr, 10); /* assume if no digits were found it is a request to enable it */ if (buf == endptr) s->reuse_socket = 1; reuse_specified = 1; } if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { s->ttl = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { s->local_port = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { h->max_packet_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) { s->buffer_size = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->is_connected = strtol(buf, NULL, 10); } if (av_find_info_tag(buf, sizeof(buf), "buf_size", p)) { s->circular_buffer_size = strtol(buf, NULL, 10)*188; } } /* fill the dest addr */ av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0, uri); /* XXX: fix av_url_split */ if (hostname[0] == '\0' || hostname[0] == '?') { /* only accepts null hostname if input */ if (!(flags & AVIO_FLAG_READ)) goto fail; } else { if (ff_udp_set_remote_url(h, uri) < 0) goto fail; } if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) s->local_port = port; udp_fd = udp_socket_create(s, &my_addr, &len); if (udp_fd < 0) goto fail; /* Follow the requested reuse option, unless it's multicast in which * case enable reuse unless explicitely disabled. */ if (s->reuse_socket || (s->is_multicast && !reuse_specified)) { s->reuse_socket = 1; if (setsockopt (udp_fd, SOL_SOCKET, SO_REUSEADDR, &(s->reuse_socket), sizeof(s->reuse_socket)) != 0) goto fail; } /* the bind is needed to give a port to the socket now */ /* if multicast, try the multicast address bind first */ if (s->is_multicast && (h->flags & AVIO_FLAG_READ)) { bind_ret = bind(udp_fd,(struct sockaddr *)&s->dest_addr, len); } /* bind to the local address if not multicast or if the multicast * bind failed */ if (bind_ret < 0 && bind(udp_fd,(struct sockaddr *)&my_addr, len) < 0) goto fail; len = sizeof(my_addr); getsockname(udp_fd, (struct sockaddr *)&my_addr, &len); s->local_port = udp_port(&my_addr, len); if (s->is_multicast) { if (!(h->flags & AVIO_FLAG_READ)) { /* output */ if (udp_set_multicast_ttl(udp_fd, s->ttl, (struct sockaddr *)&s->dest_addr) < 0) goto fail; } else { /* input */ if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) goto fail; } } if (is_output) { /* limit the tx buf size to limit latency */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp)) < 0) { av_log(h, AV_LOG_ERROR, "setsockopt(SO_SNDBUF): %s\n", strerror(errno)); goto fail; } } else { /* set udp recv buffer size to the largest possible udp packet size to * avoid losing data on OSes that set this too low by default. */ tmp = s->buffer_size; if (setsockopt(udp_fd, SOL_SOCKET, SO_RCVBUF, &tmp, sizeof(tmp)) < 0) { av_log(h, AV_LOG_WARNING, "setsockopt(SO_RECVBUF): %s\n", strerror(errno)); } /* make the socket non-blocking */ ff_socket_nonblock(udp_fd, 1); } if (s->is_connected) { if (connect(udp_fd, (struct sockaddr *) &s->dest_addr, s->dest_addr_len)) { av_log(h, AV_LOG_ERROR, "connect: %s\n", strerror(errno)); goto fail; } } s->udp_fd = udp_fd; #if 0 && HAVE_PTHREADS if (!is_output && s->circular_buffer_size) { /* start the task going */ s->fifo = av_fifo_alloc(s->circular_buffer_size); if (pthread_create(&s->circular_buffer_thread, NULL, circular_buffer_task, h)) { av_log(h, AV_LOG_ERROR, "pthread_create failed\n"); goto fail; } } #endif return 0; fail: if (udp_fd >= 0) closesocket(udp_fd); av_fifo_free(s->fifo); av_free(s); return AVERROR(EIO); }
/* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd = -1; TCPContext *s = h->priv_data; const char *p; char buf[256]; int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; s->open_timeout = 5000000; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); if (strcmp(proto, "tcp")) return AVERROR(EINVAL); if (port <= 0 || port >= 65536) { av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); return AVERROR(EINVAL); } p = strchr(uri, '?'); if (p) { if (av_find_info_tag(buf, sizeof(buf), "listen", p)) s->listen = 1; if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { s->rw_timeout = strtol(buf, NULL, 10); // av_log(NULL,AV_LOG_ERROR,"TCPopen:OPTtimeout=%lld",s->rw_timeout); } if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { s->listen_timeout = strtol(buf, NULL, 10); } } if (s->rw_timeout >= 0) { s->open_timeout = s->rw_timeout; h->rw_timeout = s->rw_timeout; // av_log(NULL,AV_LOG_ERROR,"TCPopen:timeout=%lld",h->rw_timeout); } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); //add by xhr, in order for add timeout prevent block too many time /* if (signal(SIGALRM, sig_alrm) == SIG_ERR) av_log(NULL,AV_LOG_ERROR,"Hery, signal err"); canjump = 1; if (sigsetjmp(jmpbuf, 1)) { av_log(NULL,AV_LOG_ERROR,"Hery, getaddrinfo err"); return -1; } alarm(8); */ if (s->listen) hints.ai_flags |= AI_PASSIVE; if (!hostname[0]) ret = getaddrinfo(NULL, portstr, &hints, &ai); else ret = getaddrinfo(hostname, portstr, &hints, &ai); // canjump = 0; add by xhr // alarm(0); add by xhr if (ret) { av_log(h, AV_LOG_ERROR, "Failed to resolve hostname %s: %s\n", hostname, gai_strerror(ret)); return AVERROR(EIO); } cur_ai = ai; restart: fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); if (fd < 0) { ret = ff_neterrno(); goto fail; } if (s->listen) { if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, s->listen_timeout, h)) < 0) { ret = fd; goto fail1; } } else { if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, s->open_timeout / 1000, h)) < 0) { if (ret == AVERROR_EXIT) goto fail1; else goto fail; } //Notify ip , IPV4 only for fjcmcc SQM if(cur_ai->ai_family == AF_INET) { char* ipaddr = inet_ntoa(((struct sockaddr_in *)(ai->ai_addr))->sin_addr); int int_addr = inet_addr(ipaddr); ff_send_message(&(h->interrupt_callback), MEDIA_INFO_SERVER_CHANGE, int_addr); } } h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); return 0; fail: if (cur_ai->ai_next) { /* Retry with the next sockaddr */ cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); ret = 0; goto restart; } fail1: if (fd >= 0) closesocket(fd); freeaddrinfo(ai); return ret; }