* #27232: jni: added pjproject checkout as regular git content

We will remove it once the next release of pjsip (with Android support)
comes out and is merged into SFLphone.
diff --git a/jni/pjproject-android/pjlib/src/pj/ip_helper_win32.c b/jni/pjproject-android/pjlib/src/pj/ip_helper_win32.c
new file mode 100644
index 0000000..a924606
--- /dev/null
+++ b/jni/pjproject-android/pjlib/src/pj/ip_helper_win32.c
@@ -0,0 +1,441 @@
+/* $Id: ip_helper_win32.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* 
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#include <pj/config.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* PMIB_ICMP_EX is not declared in VC6, causing error.
+ * But EVC4, which also claims to be VC6, does have it! 
+ */
+#if defined(_MSC_VER) && _MSC_VER==1200 && !defined(PJ_WIN32_WINCE)
+#   define PMIB_ICMP_EX void*
+#endif
+#include <winsock2.h>
+
+/* If you encounter error "Cannot open include file: 'Iphlpapi.h' here,
+ * you need to install newer Platform SDK. Presumably you're using
+ * Microsoft Visual Studio 6?
+ */
+#include <Iphlpapi.h>
+
+#include <pj/ip_helper.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <pj/string.h>
+
+/* Dealing with Unicode quirks:
+
+ There seems to be a difference with GetProcAddress() API signature between
+ Windows (i.e. Win32) and Windows CE (e.g. Windows Mobile). On Windows, the
+ API is declared as:
+
+   FARPROC GetProcAddress(
+     HMODULE hModule,
+     LPCSTR lpProcName);
+ 
+ while on Windows CE:
+
+   FARPROC GetProcAddress(
+     HMODULE hModule,
+     LPCWSTR lpProcName);
+
+ Notice the difference with lpProcName argument type. This means that on 
+ Windows, even on Unicode Windows, the lpProcName always takes ANSI format, 
+ while on Windows CE, the argument follows the UNICODE setting.
+
+ Because of this, we use a different Unicode treatment here than the usual
+ PJ_NATIVE_STRING_IS_UNICODE PJLIB setting (<pj/unicode.h>):
+   - GPA_TEXT macro: convert literal string to platform's native literal 
+         string
+   - gpa_char: the platform native character type
+
+ Note that "GPA" and "gpa" are abbreviations for GetProcAddress.
+*/
+#if defined(PJ_WIN32_WINCE) && PJ_WIN32_WINCE!=0
+    /* on CE, follow the PJLIB Unicode setting */
+#   define GPA_TEXT(x)	PJ_T(x)
+#   define gpa_char	pj_char_t
+#else
+    /* on non-CE, always use ANSI format */
+#   define GPA_TEXT(x)	x
+#   define gpa_char	char
+#endif
+
+
+typedef DWORD (WINAPI *PFN_GetIpAddrTable)(PMIB_IPADDRTABLE pIpAddrTable, 
+					   PULONG pdwSize, 
+					   BOOL bOrder);
+typedef DWORD (WINAPI *PFN_GetAdapterAddresses)(ULONG Family,
+					        ULONG Flags,
+					        PVOID Reserved,
+					        PIP_ADAPTER_ADDRESSES AdapterAddresses,
+					        PULONG SizePointer);
+typedef DWORD (WINAPI *PFN_GetIpForwardTable)(PMIB_IPFORWARDTABLE pIpForwardTable,
+					      PULONG pdwSize, 
+					      BOOL bOrder);
+typedef DWORD (WINAPI *PFN_GetIfEntry)(PMIB_IFROW pIfRow);
+
+static HANDLE s_hDLL;
+static PFN_GetIpAddrTable s_pfnGetIpAddrTable;
+static PFN_GetAdapterAddresses s_pfnGetAdapterAddresses;
+static PFN_GetIpForwardTable s_pfnGetIpForwardTable;
+static PFN_GetIfEntry s_pfnGetIfEntry;
+
+
+static void unload_iphlp_module(void)
+{
+    FreeLibrary(s_hDLL);
+    s_hDLL = NULL;
+    s_pfnGetIpAddrTable = NULL;
+    s_pfnGetIpForwardTable = NULL;
+    s_pfnGetIfEntry = NULL;
+    s_pfnGetAdapterAddresses = NULL;
+}
+
+static FARPROC GetIpHlpApiProc(gpa_char *lpProcName)
+{
+    if(NULL == s_hDLL) {
+	s_hDLL = LoadLibrary(PJ_T("IpHlpApi"));
+	if(NULL != s_hDLL) {
+	    pj_atexit(&unload_iphlp_module);
+	}
+    }
+	
+    if(NULL != s_hDLL)
+	return GetProcAddress(s_hDLL, lpProcName);
+    
+    return NULL;
+}
+
+static DWORD MyGetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, 
+			      PULONG pdwSize, 
+			      BOOL bOrder)
+{
+    if(NULL == s_pfnGetIpAddrTable) {
+	s_pfnGetIpAddrTable = (PFN_GetIpAddrTable) 
+	    GetIpHlpApiProc(GPA_TEXT("GetIpAddrTable"));
+    }
+    
+    if(NULL != s_pfnGetIpAddrTable) {
+	return s_pfnGetIpAddrTable(pIpAddrTable, pdwSize, bOrder);
+    }
+    
+    return ERROR_NOT_SUPPORTED;
+}
+
+static DWORD MyGetAdapterAddresses(ULONG Family,
+				   ULONG Flags,
+				   PVOID Reserved,
+				   PIP_ADAPTER_ADDRESSES AdapterAddresses,
+				   PULONG SizePointer)
+{
+    if(NULL == s_pfnGetAdapterAddresses) {
+	s_pfnGetAdapterAddresses = (PFN_GetAdapterAddresses) 
+	    GetIpHlpApiProc(GPA_TEXT("GetAdaptersAddresses"));
+    }
+    
+    if(NULL != s_pfnGetAdapterAddresses) {
+	return s_pfnGetAdapterAddresses(Family, Flags, Reserved,
+					AdapterAddresses, SizePointer);
+    }
+    
+    return ERROR_NOT_SUPPORTED;
+}
+
+#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
+static DWORD MyGetIfEntry(MIB_IFROW *pIfRow)
+{
+    if(NULL == s_pfnGetIfEntry) {
+	s_pfnGetIfEntry = (PFN_GetIfEntry) 
+	    GetIpHlpApiProc(GPA_TEXT("GetIfEntry"));
+    }
+    
+    if(NULL != s_pfnGetIfEntry) {
+	return s_pfnGetIfEntry(pIfRow);
+    }
+    
+    return ERROR_NOT_SUPPORTED;
+}
+#endif
+
+
+static DWORD MyGetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable, 
+				 PULONG pdwSize, 
+				 BOOL bOrder)
+{
+    if(NULL == s_pfnGetIpForwardTable) {
+	s_pfnGetIpForwardTable = (PFN_GetIpForwardTable) 
+	    GetIpHlpApiProc(GPA_TEXT("GetIpForwardTable"));
+    }
+    
+    if(NULL != s_pfnGetIpForwardTable) {
+	return s_pfnGetIpForwardTable(pIpForwardTable, pdwSize, bOrder);
+    }
+    
+    return ERROR_NOT_SUPPORTED;
+}
+
+/* Enumerate local IP interface using GetIpAddrTable()
+ * for IPv4 addresses only.
+ */
+static pj_status_t enum_ipv4_interface(unsigned *p_cnt,
+				       pj_sockaddr ifs[])
+{
+    char ipTabBuff[512];
+    MIB_IPADDRTABLE *pTab = (MIB_IPADDRTABLE*)ipTabBuff;
+    ULONG tabSize = sizeof(ipTabBuff);
+    unsigned i, count;
+    DWORD rc = NO_ERROR;
+
+    PJ_ASSERT_RETURN(p_cnt && ifs, PJ_EINVAL);
+
+    /* Get IP address table */
+    rc = MyGetIpAddrTable(pTab, &tabSize, FALSE);
+    if (rc != NO_ERROR) {
+	if (rc == ERROR_INSUFFICIENT_BUFFER) {
+	    /* Retry with larger buffer */
+	    pTab = (MIB_IPADDRTABLE*)malloc(tabSize);
+	    if (pTab)
+		rc = MyGetIpAddrTable(pTab, &tabSize, FALSE);
+	}
+
+	if (rc != NO_ERROR) {
+	    if (pTab != (MIB_IPADDRTABLE*)ipTabBuff)
+		free(pTab);
+	    return PJ_RETURN_OS_ERROR(rc);
+	}
+    }
+
+    /* Reset result */
+    pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt));
+
+    /* Now fill out the entries */
+    count = (pTab->dwNumEntries < *p_cnt) ? pTab->dwNumEntries : *p_cnt;
+    *p_cnt = 0;
+    for (i=0; i<count; ++i) {
+	MIB_IFROW ifRow;
+
+	/* Ignore 0.0.0.0 address (interface is down?) */
+	if (pTab->table[i].dwAddr == 0)
+	    continue;
+
+	/* Ignore 0.0.0.0/8 address. This is a special address
+	 * which doesn't seem to have practical use.
+	 */
+	if ((pj_ntohl(pTab->table[i].dwAddr) >> 24) == 0)
+	    continue;
+
+#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
+	/* Investigate the type of this interface */
+	pj_bzero(&ifRow, sizeof(ifRow));
+	ifRow.dwIndex = pTab->table[i].dwIndex;
+	if (MyGetIfEntry(&ifRow) != 0)
+	    continue;
+
+	if (ifRow.dwType == MIB_IF_TYPE_LOOPBACK)
+	    continue;
+#endif
+
+	ifs[*p_cnt].ipv4.sin_family = PJ_AF_INET;
+	ifs[*p_cnt].ipv4.sin_addr.s_addr = pTab->table[i].dwAddr;
+	(*p_cnt)++;
+    }
+
+    if (pTab != (MIB_IPADDRTABLE*)ipTabBuff)
+	free(pTab);
+
+    return (*p_cnt) ? PJ_SUCCESS : PJ_ENOTFOUND;
+}
+
+/* Enumerate local IP interface using GetAdapterAddresses(),
+ * which works for both IPv4 and IPv6.
+ */
+static pj_status_t enum_ipv4_ipv6_interface(int af,
+					    unsigned *p_cnt,
+					    pj_sockaddr ifs[])
+{
+    pj_uint8_t buffer[600];
+    IP_ADAPTER_ADDRESSES *adapter = (IP_ADAPTER_ADDRESSES*)buffer;
+    void *adapterBuf = NULL;
+    ULONG size = sizeof(buffer);
+    ULONG flags;
+    unsigned i;
+    DWORD rc;
+
+    flags = GAA_FLAG_SKIP_FRIENDLY_NAME |
+	    GAA_FLAG_SKIP_DNS_SERVER |
+	    GAA_FLAG_SKIP_MULTICAST;
+
+    rc = MyGetAdapterAddresses(af, flags, NULL, adapter, &size);
+    if (rc != ERROR_SUCCESS) {
+	if (rc == ERROR_BUFFER_OVERFLOW) {
+	    /* Retry with larger memory size */
+	    adapterBuf = malloc(size);
+	    adapter = (IP_ADAPTER_ADDRESSES*) adapterBuf;
+	    if (adapter != NULL)
+		rc = MyGetAdapterAddresses(af, flags, NULL, adapter, &size);
+	} 
+
+	if (rc != ERROR_SUCCESS) {
+	    if (adapterBuf)
+		free(adapterBuf);
+	    return PJ_RETURN_OS_ERROR(rc);
+	}
+    }
+
+    /* Reset result */
+    pj_bzero(ifs, sizeof(ifs[0]) * (*p_cnt));
+
+    /* Enumerate interface */
+    for (i=0; i<*p_cnt && adapter; adapter = adapter->Next) {
+	if (adapter->FirstUnicastAddress) {
+	    SOCKET_ADDRESS *pAddr = &adapter->FirstUnicastAddress->Address;
+
+	    /* Ignore address family which we didn't request, just in case */
+	    if (pAddr->lpSockaddr->sa_family != PJ_AF_INET &&
+		pAddr->lpSockaddr->sa_family != PJ_AF_INET6)
+	    {
+		continue;
+	    }
+
+	    /* Apply some filtering to known IPv4 unusable addresses */
+	    if (pAddr->lpSockaddr->sa_family == PJ_AF_INET) {
+		const pj_sockaddr_in *addr_in = 
+		    (const pj_sockaddr_in*)pAddr->lpSockaddr;
+
+		/* Ignore 0.0.0.0 address (interface is down?) */
+		if (addr_in->sin_addr.s_addr == 0)
+		    continue;
+
+		/* Ignore 0.0.0.0/8 address. This is a special address
+		 * which doesn't seem to have practical use.
+		 */
+		if ((pj_ntohl(addr_in->sin_addr.s_addr) >> 24) == 0)
+		    continue;
+	    }
+
+#if PJ_IP_HELPER_IGNORE_LOOPBACK_IF
+	    /* Ignore loopback interfaces */
+	    /* This should have been IF_TYPE_SOFTWARE_LOOPBACK according to
+	     * MSDN, and this macro should have been declared in Ipifcons.h, 
+	     * but some SDK versions don't have it.
+	     */
+	    if (adapter->IfType == MIB_IF_TYPE_LOOPBACK)
+		continue;
+#endif
+
+	    /* Ignore down interface */
+	    if (adapter->OperStatus != IfOperStatusUp)
+		continue;
+
+	    ifs[i].addr.sa_family = pAddr->lpSockaddr->sa_family;
+	    pj_memcpy(&ifs[i], pAddr->lpSockaddr, pAddr->iSockaddrLength);
+	    ++i;
+	}
+    }
+
+    if (adapterBuf)
+	free(adapterBuf);
+
+    *p_cnt = i;
+    return (*p_cnt) ? PJ_SUCCESS : PJ_ENOTFOUND;
+}
+
+
+/*
+ * Enumerate the local IP interface currently active in the host.
+ */
+PJ_DEF(pj_status_t) pj_enum_ip_interface(int af,
+					 unsigned *p_cnt,
+					 pj_sockaddr ifs[])
+{
+    pj_status_t status = -1;
+
+    PJ_ASSERT_RETURN(p_cnt && ifs, PJ_EINVAL);
+    PJ_ASSERT_RETURN(af==PJ_AF_UNSPEC || af==PJ_AF_INET || af==PJ_AF_INET6,
+		     PJ_EAFNOTSUP);
+
+    status = enum_ipv4_ipv6_interface(af, p_cnt, ifs);
+    if (status != PJ_SUCCESS && (af==PJ_AF_INET || af==PJ_AF_UNSPEC))
+	status = enum_ipv4_interface(p_cnt, ifs);
+    return status;
+}
+
+/*
+ * Enumerate the IP routing table for this host.
+ */
+PJ_DEF(pj_status_t) pj_enum_ip_route(unsigned *p_cnt,
+				     pj_ip_route_entry routes[])
+{
+    char ipTabBuff[1024];
+    MIB_IPADDRTABLE *pIpTab;
+    char rtabBuff[1024];
+    MIB_IPFORWARDTABLE *prTab;
+    ULONG tabSize;
+    unsigned i, count;
+    DWORD rc = NO_ERROR;
+
+    PJ_ASSERT_RETURN(p_cnt && routes, PJ_EINVAL);
+
+    pIpTab = (MIB_IPADDRTABLE *)ipTabBuff;
+    prTab = (MIB_IPFORWARDTABLE *)rtabBuff;
+
+    /* First get IP address table */
+    tabSize = sizeof(ipTabBuff);
+    rc = MyGetIpAddrTable(pIpTab, &tabSize, FALSE);
+    if (rc != NO_ERROR)
+	return PJ_RETURN_OS_ERROR(rc);
+
+    /* Next get IP route table */
+    tabSize = sizeof(rtabBuff);
+
+    rc = MyGetIpForwardTable(prTab, &tabSize, 1);
+    if (rc != NO_ERROR)
+	return PJ_RETURN_OS_ERROR(rc);
+
+    /* Reset routes */
+    pj_bzero(routes, sizeof(routes[0]) * (*p_cnt));
+
+    /* Now fill out the route entries */
+    count = (prTab->dwNumEntries < *p_cnt) ? prTab->dwNumEntries : *p_cnt;
+    *p_cnt = 0;
+    for (i=0; i<count; ++i) {
+	unsigned j;
+
+	/* Find interface entry */
+	for (j=0; j<pIpTab->dwNumEntries; ++j) {
+	    if (pIpTab->table[j].dwIndex == prTab->table[i].dwForwardIfIndex)
+		break;
+	}
+
+	if (j==pIpTab->dwNumEntries)
+	    continue;	/* Interface not found */
+
+	routes[*p_cnt].ipv4.if_addr.s_addr = pIpTab->table[j].dwAddr;
+	routes[*p_cnt].ipv4.dst_addr.s_addr = prTab->table[i].dwForwardDest;
+	routes[*p_cnt].ipv4.mask.s_addr = prTab->table[i].dwForwardMask;
+
+	(*p_cnt)++;
+    }
+
+    return PJ_SUCCESS;
+}
+