summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavformat/network.h38
-rw-r--r--libavformat/os_support.c70
2 files changed, 108 insertions, 0 deletions
diff --git a/libavformat/network.h b/libavformat/network.h
index 7af77991d4..43c2544031 100644
--- a/libavformat/network.h
+++ b/libavformat/network.h
@@ -68,4 +68,42 @@ static inline void ff_network_close(void)
int inet_aton (const char * str, struct in_addr * add);
#endif
+#if !HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+ int ai_flags;
+ int ai_family;
+ int ai_socktype;
+ int ai_protocol;
+ int ai_addrlen;
+ struct sockaddr *ai_addr;
+ char *ai_canonname;
+ struct addrinfo *ai_next;
+};
+#endif
+
+/* getaddrinfo constants */
+#ifndef EAI_FAIL
+#define EAI_FAIL 4
+#endif
+
+#ifndef AI_PASSIVE
+#define AI_PASSIVE 1
+#endif
+
+#ifndef AI_CANONNAME
+#define AI_CANONNAME 2
+#endif
+
+#ifndef AI_NUMERICHOST
+#define AI_NUMERICHOST 4
+#endif
+
+#if !HAVE_GETADDRINFO
+int ff_getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res);
+void ff_freeaddrinfo(struct addrinfo *res);
+#define getaddrinfo ff_getaddrinfo
+#define freeaddrinfo ff_freeaddrinfo
+#endif
+
#endif /* AVFORMAT_NETWORK_H */
diff --git a/libavformat/os_support.c b/libavformat/os_support.c
index 87481d674e..62fd183afd 100644
--- a/libavformat/os_support.c
+++ b/libavformat/os_support.c
@@ -60,6 +60,76 @@ int inet_aton (const char * str, struct in_addr * add)
}
#endif /* !HAVE_INET_ATON */
+#if !HAVE_GETADDRINFO
+int ff_getaddrinfo(const char *node, const char *service,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct hostent *h = NULL;
+ struct addrinfo *ai;
+ struct sockaddr_in *sin;
+
+ sin = av_mallocz(sizeof(struct sockaddr_in));
+ if (!sin)
+ return EAI_FAIL;
+ sin->sin_family = AF_INET;
+
+ if (node) {
+ if (!inet_aton(node, &sin->sin_addr)) {
+ if (hints && (hints->ai_flags & AI_NUMERICHOST)) {
+ av_free(sin);
+ return EAI_FAIL;
+ }
+ h = gethostbyname(node);
+ if (!h) {
+ av_free(sin);
+ return EAI_FAIL;
+ }
+ memcpy(&sin->sin_addr, h->h_addr_list[0], sizeof(struct in_addr));
+ }
+ } else {
+ if (hints && (hints->ai_flags & AI_PASSIVE)) {
+ sin->sin_addr.s_addr = INADDR_ANY;
+ } else
+ sin->sin_addr.s_addr = INADDR_LOOPBACK;
+ }
+
+ /* Note: getaddrinfo allows service to be a string, which
+ * should be looked up using getservbyname. */
+ if (service)
+ sin->sin_port = htons(atoi(service));
+
+ ai = av_mallocz(sizeof(struct addrinfo));
+ if (!ai) {
+ av_free(sin);
+ return EAI_FAIL;
+ }
+
+ *res = ai;
+ ai->ai_family = AF_INET;
+ ai->ai_socktype = hints ? hints->ai_socktype : 0;
+ switch (ai->ai_socktype) {
+ case SOCK_STREAM: ai->ai_protocol = IPPROTO_TCP; break;
+ case SOCK_DGRAM: ai->ai_protocol = IPPROTO_UDP; break;
+ default: ai->ai_protocol = 0; break;
+ }
+
+ ai->ai_addr = (struct sockaddr *)sin;
+ ai->ai_addrlen = sizeof(struct sockaddr_in);
+ if (hints && (hints->ai_flags & AI_CANONNAME))
+ ai->ai_canonname = h ? av_strdup(h->h_name) : NULL;
+
+ ai->ai_next = NULL;
+ return 0;
+}
+
+void ff_freeaddrinfo(struct addrinfo *res)
+{
+ av_free(res->ai_canonname);
+ av_free(res->ai_addr);
+ av_free(res);
+}
+#endif
+
/* resolve host with also IP address parsing */
int resolve_host(struct in_addr *sin_addr, const char *hostname)
{