Provide fallback implementations of getaddrinfo() and freeaddrinfo().
authorMartin Storsjö <martin@martin.st>
Mon, 11 Jan 2010 17:27:07 +0000 (17:27 +0000)
committerRonald S. Bultje <rsbultje@gmail.com>
Mon, 11 Jan 2010 17:27:07 +0000 (17:27 +0000)
Patch by Martin Storsjö <$firstname()$firstname,st>.

Originally committed as revision 21145 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavformat/network.h
libavformat/os_support.c

index 7af7799..43c2544 100644 (file)
@@ -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 */
index 87481d6..62fd183 100644 (file)
@@ -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)
 {