Basic support for IPv6

master
Richard Stanway 2015-01-21 23:07:39 +01:00
parent 577f6c7861
commit 9f0503a24b
5 changed files with 103 additions and 57 deletions

View File

@ -787,7 +787,7 @@ void RTMPPublisher::BeginPublishing()
void LogInterfaceType (RTMP *rtmp)
{
MIB_IPFORWARDROW route;
DWORD destAddr;
DWORD destAddr, sourceAddr;
CHAR hostname[256];
if (rtmp->Link.hostname.av_len >= sizeof(hostname)-1)
@ -802,7 +802,14 @@ void LogInterfaceType (RTMP *rtmp)
destAddr = *(DWORD *)h->h_addr_list[0];
if (!GetBestRoute (destAddr, rtmp->m_bindIP.addr.sin_addr.S_un.S_addr, &route))
if (rtmp->m_bindIP.addrLen == 0)
sourceAddr = 0;
else if (rtmp->m_bindIP.addr.ss_family == AF_INET)
sourceAddr = (*(struct sockaddr_in *)&rtmp->m_bindIP).sin_addr.S_un.S_addr;
else
return; // getting route for IPv6 is far more complex, ignore for now
if (!GetBestRoute (destAddr, sourceAddr, &route))
{
MIB_IFROW row;
zero (&row, sizeof(row));
@ -1041,9 +1048,14 @@ DWORD WINAPI RTMPPublisher::CreateConnectionThread(RTMPPublisher *publisher)
if (scmp(strBindIP, TEXT("Default")))
{
Log(TEXT(" Binding to non-default IP %s"), strBindIP.Array());
rtmp->m_bindIP.addr.sin_family = AF_INET;
if (schr(strBindIP.Array(), ':'))
rtmp->m_bindIP.addr.ss_family = AF_INET6;
else
rtmp->m_bindIP.addr.ss_family = AF_INET;
rtmp->m_bindIP.addrLen = sizeof(rtmp->m_bindIP.addr);
if (WSAStringToAddress(strBindIP.Array(), AF_INET, NULL, (LPSOCKADDR)&rtmp->m_bindIP.addr, &rtmp->m_bindIP.addrLen) == SOCKET_ERROR)
if (WSAStringToAddress(strBindIP.Array(), rtmp->m_bindIP.addr.ss_family, NULL, (LPSOCKADDR)&rtmp->m_bindIP.addr, &rtmp->m_bindIP.addrLen) == SOCKET_ERROR)
{
// no localization since this should rarely/never happen
failReason = TEXT("WSAStringToAddress: Could not parse address");

View File

@ -484,49 +484,48 @@ INT_PTR SettingsAdvanced::ProcMessage(UINT message, WPARAM wParam, LPARAM lParam
//------------------------------------
MIB_IPADDRTABLE tempTable;
DWORD dwSize = 0;
if (GetIpAddrTable (&tempTable, &dwSize, TRUE) == ERROR_INSUFFICIENT_BUFFER)
IP_ADAPTER_ADDRESSES *ipTable;
DWORD dwSize = 65536;
ipTable = (IP_ADAPTER_ADDRESSES *)Allocate(dwSize);
DWORD flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER;
hwndTemp = GetDlgItem(hwnd, IDC_BINDIP);
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("Default"));
if (!GetAdaptersAddresses(AF_UNSPEC, flags, NULL, ipTable, &dwSize))
{
PMIB_IPADDRTABLE ipTable;
IP_ADAPTER_ADDRESSES *pCurrAddresses = ipTable;
ipTable = (PMIB_IPADDRTABLE)Allocate(dwSize);
if (GetIpAddrTable (ipTable, &dwSize, TRUE) == NO_ERROR)
while (pCurrAddresses)
{
DWORD i;
hwndTemp = GetDlgItem(hwnd, IDC_BINDIP);
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)TEXT("Default"));
for (i=0; i < ipTable->dwNumEntries; i++)
if (pCurrAddresses->OperStatus == IfOperStatusUp && pCurrAddresses->IfType != IF_TYPE_SOFTWARE_LOOPBACK)
{
String strAddress;
DWORD strLength = 32;
// don't allow binding to localhost
if ((ipTable->table[i].dwAddr & 0xFF) == 127)
continue;
strAddress.SetLength(strLength);
SOCKADDR_IN IP;
IP.sin_addr.S_un.S_addr = ipTable->table[i].dwAddr;
IP.sin_family = AF_INET;
IP.sin_port = 0;
zero(&IP.sin_zero, sizeof(IP.sin_zero));
WSAAddressToString ((LPSOCKADDR)&IP, sizeof(IP), NULL, strAddress.Array(), &strLength);
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)strAddress.Array());
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = pCurrAddresses->FirstUnicastAddress;
while (pUnicast)
{
if (pUnicast->Address.lpSockaddr->sa_family == AF_INET || pUnicast->Address.lpSockaddr->sa_family == AF_INET6)
{
TCHAR friendlyAddress[256];
DWORD friendlyAddressLen = _countof(friendlyAddress);
if (!WSAAddressToString(pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength, NULL, friendlyAddress, &friendlyAddressLen))
{
SendMessage(hwndTemp, CB_ADDSTRING, 0, (LPARAM)friendlyAddress);
}
}
pUnicast = pUnicast->Next;
}
}
LoadSettingComboString(hwndTemp, TEXT("Publish"), TEXT("BindToIP"), TEXT("Default"));
pCurrAddresses = pCurrAddresses->Next;
}
Free(ipTable);
}
LoadSettingComboString(hwndTemp, TEXT("Publish"), TEXT("BindToIP"), TEXT("Default"));
//need this as some of the dialog item sets above trigger the notifications
ShowWindow(GetDlgItem(hwnd, IDC_INFO), SW_HIDE);
SetChangedSettings(invalidSettings);

View File

@ -1087,7 +1087,7 @@ int RTMP_SetupURL2(RTMP *r, char *url, char *playpath)
}
static int
add_addr_info(struct sockaddr_in *service, AVal *host, int port)
add_addr_info(struct sockaddr_storage *service, AVal *host, int port)
{
char *hostname;
int ret = TRUE;
@ -1102,20 +1102,50 @@ add_addr_info(struct sockaddr_in *service, AVal *host, int port)
hostname = host->av_val;
}
service->sin_addr.s_addr = inet_addr(hostname);
if (service->sin_addr.s_addr == INADDR_NONE)
struct addrinfo hints;
struct addrinfo *result = NULL;
struct addrinfo *ptr = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
service->ss_family = AF_UNSPEC;
char portStr[8];
itoa(port, portStr, 10);
int err = getaddrinfo(hostname, portStr, &hints, &result);
if (err)
{
struct hostent *host = gethostbyname(hostname);
if (host == NULL || host->h_addr == NULL)
{
RTMP_Log(RTMP_LOGERROR, "Problem accessing the DNS. (addr: %s, error: %d)", hostname, GetSockError());
ret = FALSE;
goto finish;
}
service->sin_addr = *(struct in_addr *)host->h_addr;
RTMP_Log(RTMP_LOGERROR, "Could not resolve %s: %s (%d)", hostname, gai_strerrorA(GetSockError()), GetSockError());
ret = FALSE;
goto finish;
}
// they should come back in OS preferred order
for (ptr = result; ptr != NULL; ptr = ptr->ai_next)
{
if (ptr->ai_family == AF_INET || ptr->ai_family == AF_INET6)
{
memcpy(service, ptr->ai_addr, ptr->ai_addrlen);
break;
}
}
freeaddrinfo(result);
if (service->ss_family == AF_UNSPEC)
{
RTMP_Log(RTMP_LOGERROR, "Could not resolve server '%s': no valid address found", hostname);
ret = FALSE;
goto finish;
}
service->sin_port = htons(port);
finish:
if (hostname != host->av_val)
free(hostname);
@ -1132,7 +1162,7 @@ RTMP_Connect0(RTMP *r, struct sockaddr * service)
//best to be explicit, we need overlapped socket
//r->m_sb.sb_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
r->m_sb.sb_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
r->m_sb.sb_socket = WSASocket(service->sa_family, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (r->m_sb.sb_socket != -1)
{
@ -1148,7 +1178,7 @@ RTMP_Connect0(RTMP *r, struct sockaddr * service)
}
}
if (connect(r->m_sb.sb_socket, service, sizeof(struct sockaddr)) < 0)
if (connect(r->m_sb.sb_socket, service, sizeof(struct sockaddr_storage)) < 0)
{
int err = GetSockError();
if (err == 10061)
@ -1274,7 +1304,7 @@ int
RTMP_Connect(RTMP *r, RTMPPacket *cp)
{
HOSTENT *h;
struct sockaddr_in service;
struct sockaddr_storage service;
if (!r->Link.hostname.av_len)
return FALSE;
@ -1286,8 +1316,7 @@ RTMP_Connect(RTMP *r, RTMPPacket *cp)
return FALSE;
}
memset(&service, 0, sizeof(struct sockaddr_in));
service.sin_family = AF_INET;
memset(&service, 0, sizeof(service));
if (r->Link.socksport)
{
@ -1314,11 +1343,16 @@ static int
SocksNegotiate(RTMP *r)
{
unsigned long addr;
struct sockaddr_in service;
memset(&service, 0, sizeof(struct sockaddr_in));
struct sockaddr_storage service;
memset(&service, 0, sizeof(service));
add_addr_info(&service, &r->Link.hostname, r->Link.port);
addr = htonl(service.sin_addr.s_addr);
// not doing IPv6 socks
if (service.ss_family == AF_INET6)
return FALSE;
addr = htonl((*(struct sockaddr_in *)&service).sin_addr.s_addr);
{
char packet[] =

View File

@ -243,7 +243,7 @@ extern "C"
typedef struct RTMP_BINDINFO
{
struct sockaddr_in addr;
struct sockaddr_storage addr;
int addrLen;
} RTMP_BINDINFO;

View File

@ -37,6 +37,7 @@
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Mstcpip.h>
#include "stdint.h"