* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <fcntl.h>
#include "network.h"
+#include "tls.h"
#include "url.h"
#include "libavcodec/internal.h"
#include "libavutil/mem.h"
-#if HAVE_THREADS
-#if HAVE_PTHREADS
-#include <pthread.h>
-#else
-#include "compat/w32pthreads.h"
-#endif
-#endif
-
-#if CONFIG_OPENSSL
-#include <openssl/ssl.h>
-static int openssl_init;
-#if HAVE_THREADS
-#include <openssl/crypto.h>
-#include "libavutil/avutil.h"
-pthread_mutex_t *openssl_mutexes;
-static void openssl_lock(int mode, int type, const char *file, int line)
-{
- if (mode & CRYPTO_LOCK)
- pthread_mutex_lock(&openssl_mutexes[type]);
- else
- pthread_mutex_unlock(&openssl_mutexes[type]);
-}
-#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
-static unsigned long openssl_thread_id(void)
-{
- return (intptr_t) pthread_self();
-}
-#endif
-#endif
-#endif
-#if CONFIG_GNUTLS
-#include <gnutls/gnutls.h>
-#if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00
-#include <gcrypt.h>
-#include <errno.h>
-GCRY_THREAD_OPTION_PTHREAD_IMPL;
-#endif
-#endif
-
void ff_tls_init(void)
{
- avpriv_lock_avformat();
-#if CONFIG_OPENSSL
- if (!openssl_init) {
- SSL_library_init();
- SSL_load_error_strings();
-#if HAVE_THREADS
- if (!CRYPTO_get_locking_callback()) {
- int i;
- openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks());
- for (i = 0; i < CRYPTO_num_locks(); i++)
- pthread_mutex_init(&openssl_mutexes[i], NULL);
- CRYPTO_set_locking_callback(openssl_lock);
-#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000
- CRYPTO_set_id_callback(openssl_thread_id);
-#endif
- }
-#endif
- }
- openssl_init++;
-#endif
-#if CONFIG_GNUTLS
-#if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00
- if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0)
- gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
+#if CONFIG_TLS_OPENSSL_PROTOCOL
+ ff_openssl_init();
#endif
- gnutls_global_init();
+#if CONFIG_TLS_GNUTLS_PROTOCOL
+ ff_gnutls_init();
#endif
- avpriv_unlock_avformat();
}
void ff_tls_deinit(void)
{
- avpriv_lock_avformat();
-#if CONFIG_OPENSSL
- openssl_init--;
- if (!openssl_init) {
-#if HAVE_THREADS
- if (CRYPTO_get_locking_callback() == openssl_lock) {
- int i;
- CRYPTO_set_locking_callback(NULL);
- for (i = 0; i < CRYPTO_num_locks(); i++)
- pthread_mutex_destroy(&openssl_mutexes[i]);
- av_free(openssl_mutexes);
- }
-#endif
- }
+#if CONFIG_TLS_OPENSSL_PROTOCOL
+ ff_openssl_deinit();
#endif
-#if CONFIG_GNUTLS
- gnutls_global_deinit();
+#if CONFIG_TLS_GNUTLS_PROTOCOL
+ ff_gnutls_deinit();
#endif
- avpriv_unlock_avformat();
}
int ff_network_inited_globally;
return ret;
}
+int ff_socket(int af, int type, int proto)
+{
+ int fd;
+
+#ifdef SOCK_CLOEXEC
+ fd = socket(af, type | SOCK_CLOEXEC, proto);
+ if (fd == -1 && errno == EINVAL)
+#endif
+ {
+ fd = socket(af, type, proto);
+#if HAVE_FCNTL
+ if (fd != -1)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+ }
+#ifdef SO_NOSIGPIPE
+ if (fd != -1)
+ setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int));
+#endif
+ return fd;
+}
+
int ff_listen_bind(int fd, const struct sockaddr *addr,
socklen_t addrlen, int timeout, URLContext *h)
{
}
int ff_listen_connect(int fd, const struct sockaddr *addr,
- socklen_t addrlen, int timeout, URLContext *h)
+ socklen_t addrlen, int timeout, URLContext *h,
+ int will_try_next)
{
struct pollfd p = {fd, POLLOUT, 0};
int ret;
char errbuf[100];
ret = AVERROR(ret);
av_strerror(ret, errbuf, sizeof(errbuf));
- av_log(h, AV_LOG_ERROR,
- "Connection to %s failed: %s\n",
- h->filename, errbuf);
+ if (will_try_next)
+ av_log(h, AV_LOG_WARNING,
+ "Connection to %s failed (%s), trying next address\n",
+ h->filename, errbuf);
+ else
+ av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
+ h->filename, errbuf);
}
default:
return ret;
}
return ret;
}
+
+static int match_host_pattern(const char *pattern, const char *hostname)
+{
+ int len_p, len_h;
+ if (!strcmp(pattern, "*"))
+ return 1;
+ // Skip a possible *. at the start of the pattern
+ if (pattern[0] == '*')
+ pattern++;
+ if (pattern[0] == '.')
+ pattern++;
+ len_p = strlen(pattern);
+ len_h = strlen(hostname);
+ if (len_p > len_h)
+ return 0;
+ // Simply check if the end of hostname is equal to 'pattern'
+ if (!strcmp(pattern, &hostname[len_h - len_p])) {
+ if (len_h == len_p)
+ return 1; // Exact match
+ if (hostname[len_h - len_p - 1] == '.')
+ return 1; // The matched substring is a domain and not just a substring of a domain
+ }
+ return 0;
+}
+
+int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
+{
+ char *buf, *start;
+ int ret = 0;
+ if (!no_proxy)
+ return 0;
+ if (!hostname)
+ return 0;
+ buf = av_strdup(no_proxy);
+ if (!buf)
+ return 0;
+ start = buf;
+ while (start) {
+ char *sep, *next = NULL;
+ start += strspn(start, " ,");
+ sep = start + strcspn(start, " ,");
+ if (*sep) {
+ next = sep + 1;
+ *sep = '\0';
+ }
+ if (match_host_pattern(start, hostname)) {
+ ret = 1;
+ break;
+ }
+ start = next;
+ }
+ av_free(buf);
+ return ret;
+}