diff options
Diffstat (limited to 'src/modules/netlib/netlibopenconn.cpp')
| -rw-r--r-- | src/modules/netlib/netlibopenconn.cpp | 204 | 
1 files changed, 117 insertions, 87 deletions
diff --git a/src/modules/netlib/netlibopenconn.cpp b/src/modules/netlib/netlibopenconn.cpp index b9d4753b9a..f24906b20c 100644 --- a/src/modules/netlib/netlibopenconn.cpp +++ b/src/modules/netlib/netlibopenconn.cpp @@ -219,15 +219,19 @@ static int NetlibInitSocks5Connection(struct NetlibConnection *nlc,struct Netlib  		int nHostLen;
  		DWORD hostIP;
 -		if(nlc->dnsThroughProxy) {
 -			if((hostIP=inet_addr(nloc->szHost))==INADDR_NONE)
 -				nHostLen=lstrlenA(nloc->szHost)+1;
 -			else nHostLen=4;
 +		if (nlc->dnsThroughProxy) 
 +		{
 +			hostIP = inet_addr(nloc->szHost);
 +			if(hostIP == INADDR_NONE)
 +				nHostLen = lstrlenA(nloc->szHost)+1;
 +			else nHostLen = 4;
  		}
 -		else {
 -			if((hostIP=DnsLookup(nlu,nloc->szHost))==0)
 +		else 
 +		{
 +			hostIP = DnsLookup(nlu,nloc->szHost);
 +			if (hostIP == 0)
  				return 0;
 -			nHostLen=4;
 +			nHostLen = 4;
  		}
  		pInit=(PBYTE)mir_alloc(6+nHostLen);
  		pInit[0]=5;   //SOCKS5
 @@ -394,8 +398,9 @@ static bool my_connectIPv4(NetlibConnection *nlc, NETLIBOPENCONNECTION * nloc)  		if (Miranda_Terminated()) return false;
  	}
 -    SOCKADDR_IN sin = {0};
 -   	sin.sin_family = AF_INET;
 +	PHOSTENT he;
 +	SOCKADDR_IN sin = {0};
 +	sin.sin_family = AF_INET;
  	if (nlc->proxyType)
  	{
 @@ -405,107 +410,124 @@ static bool my_connectIPv4(NetlibConnection *nlc, NETLIBOPENCONNECTION * nloc)  			NetlibLogf(nlc->nlu,"(%p) Connecting to proxy %s:%d for %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort, nloc->szHost, nloc->wPort);
  		else
  			NetlibLogf(nlc->nlu,"(%p) Connecting to proxy %s:%d ....", nlc, nlc->szProxyServer, nlc->wProxyPort);
 -		
 +
  		sin.sin_port = htons(nlc->wProxyPort);
 -		sin.sin_addr.s_addr = DnsLookup(nlc->nlu, nlc->szProxyServer);
 +		he = gethostbyname(nlc->szProxyServer);
  	}
  	else
  	{
 -		if (!nloc || !nloc->szHost) return false;
 +		if (!nloc || !nloc->szHost || nloc->szHost[0] == '[' || strchr(nloc->szHost, ':')) return false;
  		NetlibLogf(nlc->nlu,"(%p) Connecting to server %s:%d....", nlc, nloc->szHost, nloc->wPort);
  		sin.sin_port = htons(nloc->wPort);
 -		sin.sin_addr.s_addr = DnsLookup(nlc->nlu, nloc->szHost);
 +		he = gethostbyname(nloc->szHost);
  	}
 -retry:
 -	nlc->s = socket(AF_INET,nloc->flags & NLOCF_UDP ? SOCK_DGRAM : SOCK_STREAM, 0);
 -	if (nlc->s == INVALID_SOCKET) return false;
 +	for (char** har = he->h_addr_list; *har && !Miranda_Terminated(); ++har)
 +	{
 +		sin.sin_addr.s_addr = *(u_long*)*har;
 -	// return the socket to non blocking
 -	if (ioctlsocket(nlc->s, FIONBIO, ¬blocking) != 0) return false;
 +		char* szIp = NetlibAddressToString((SOCKADDR_INET_M*)&sin);
 +		NetlibLogf(nlc->nlu,"(%p) Connecting to ip %s ....", nlc, szIp);
 +		mir_free(szIp);
 -	if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts  && nlc->nlu->settings.szOutgoingPorts[0]) 
 -	{
 -		if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, nlc->s, &nlc->nlu->inportnum))
 -			NetlibLogf(nlc->nlu,"Netlib connect: Not enough ports for outgoing connections specified");
 -	} 
 +retry:
 +		nlc->s = socket(AF_INET, nloc->flags & NLOCF_UDP ? SOCK_DGRAM : SOCK_STREAM, 0);
 +		if (nlc->s == INVALID_SOCKET) return false;
 -	// try a connect
 -	if (connect(nlc->s, (LPSOCKADDR)&sin, sizeof(sin)) == 0) 
 -	{
 -		goto unblock;
 -	}
 +		// return the socket to non blocking
 +		if (ioctlsocket(nlc->s, FIONBIO, ¬blocking) != 0) return false;
 -	// didn't work, was it cos of nonblocking?
 -	if (WSAGetLastError() != WSAEWOULDBLOCK) 
 -	{
 -		rc = SOCKET_ERROR;
 -		goto unblock;
 -	}
 +		if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts  && nlc->nlu->settings.szOutgoingPorts[0]) 
 +		{
 +			if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, nlc->s, INVALID_SOCKET, &nlc->nlu->inportnum))
 +				NetlibLogf(nlc->nlu,"Netlib connect: Not enough ports for outgoing connections specified");
 +		} 
 -	for (;;) 
 -	{		
 -		fd_set r, w, e;
 -		FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e);
 -		FD_SET(nlc->s, &r);
 -		FD_SET(nlc->s, &w);
 -		FD_SET(nlc->s, &e);		
 -		if ((rc = select(0, &r, &w, &e, &tv)) == SOCKET_ERROR) 
 +		// try a connect
 +		if (connect(nlc->s, (LPSOCKADDR)&sin, sizeof(sin)) == 0) 
 +		{
 +			rc = 0;
  			break;
 +		}
 +
 +		// didn't work, was it cos of nonblocking?
 +		if (WSAGetLastError() != WSAEWOULDBLOCK) 
 +		{
 +			rc = SOCKET_ERROR;
 +
 +			closesocket(nlc->s);
 +			nlc->s = INVALID_SOCKET;
 +			continue;
 +		}
 +
 +		for (;;) 
 +		{		
 +			fd_set r, w, e;
 +			FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e);
 +			FD_SET(nlc->s, &r);
 +			FD_SET(nlc->s, &w);
 +			FD_SET(nlc->s, &e);
 +			if ((rc = select(0, &r, &w, &e, &tv)) == SOCKET_ERROR) 
 +				break;
 -		if (rc > 0) 
 -		{			
 -			if (FD_ISSET(nlc->s, &w))
 +			if (rc > 0) 
 +			{			
 +				if (FD_ISSET(nlc->s, &w))
 +				{
 +					// connection was successful
 +					rc = 0;
 +				}
 +				if (FD_ISSET(nlc->s, &r)) 
 +				{
 +					// connection was closed
 +					rc = SOCKET_ERROR;
 +					lasterr = WSAECONNRESET;
 +				}
 +				if (FD_ISSET(nlc->s, &e)) 
 +				{
 +					// connection failed.
 +					int len = sizeof(lasterr);
 +					rc = SOCKET_ERROR;
 +					getsockopt(nlc->s, SOL_SOCKET, SO_ERROR, (char*)&lasterr, &len);
 +					if (lasterr == WSAEADDRINUSE && ++retrycnt <= 2) 
 +					{
 +						closesocket(nlc->s);
 +						goto retry;
 +					}
 +				}
 +				break;
 +			} 
 +			else if (Miranda_Terminated()) 
  			{
 -				// connection was successful
 -				rc = 0;
 -			}
 -			if (FD_ISSET(nlc->s, &r)) 
 +				rc = SOCKET_ERROR;
 +				lasterr = ERROR_TIMEOUT;
 +				break;
 +			} 
 +			else if (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2 && 
 +				nloc->waitcallback != NULL && nloc->waitcallback(&dwTimeout) == 0)
  			{
 -				// connection was closed
  				rc = SOCKET_ERROR;
 -				lasterr = WSAECONNRESET;
 +				lasterr = ERROR_TIMEOUT;
 +				break;
  			}
 -			if (FD_ISSET(nlc->s, &e)) 
 +			if (--dwTimeout == 0) 
  			{
 -				// connection failed.
 -				int len = sizeof(lasterr);
  				rc = SOCKET_ERROR;
 -				getsockopt(nlc->s, SOL_SOCKET, SO_ERROR, (char*)&lasterr, &len);
 -				if (lasterr == WSAEADDRINUSE && ++retrycnt <= 2) 
 -				{
 -					closesocket(nlc->s);
 -					goto retry;
 -				}
 +				lasterr = ERROR_TIMEOUT;
 +				break;
  			}
 -			break;
 -		} 
 -		else if (Miranda_Terminated()) 
 -		{
 -			rc = SOCKET_ERROR;
 -			lasterr = ERROR_TIMEOUT;
 -			break;
 -		} 
 -		else if (nloc->cbSize == sizeof(NETLIBOPENCONNECTION) && nloc->flags & NLOCF_V2 && 
 -			nloc->waitcallback != NULL && nloc->waitcallback(&dwTimeout) == 0)
 -		{
 -			rc = SOCKET_ERROR;
 -			lasterr = ERROR_TIMEOUT;
 -			break;
 -		}
 -		if (--dwTimeout == 0) 
 -		{
 -			rc = SOCKET_ERROR;
 -			lasterr = ERROR_TIMEOUT;
 -			break;
  		}
 +
 +		if (rc == 0) break;
 +
 +		closesocket(nlc->s);
 +		nlc->s = INVALID_SOCKET;
  	}
 -unblock:	
  	notblocking = 0;
 -	ioctlsocket(nlc->s, FIONBIO, ¬blocking);
 -	if (lasterr) SetLastError(lasterr);
 +	if (nlc->s != INVALID_SOCKET) ioctlsocket(nlc->s, FIONBIO, ¬blocking);
 +	if (rc && lasterr) SetLastError(lasterr);
  	return rc == 0;
  }
 @@ -548,7 +570,7 @@ static bool my_connectIPv6(NetlibConnection *nlc, NETLIBOPENCONNECTION * nloc)  		hints.ai_socktype = SOCK_STREAM;
  		hints.ai_protocol = IPPROTO_TCP;
  	}
 -	
 +
  	if (nlc->proxyType)
  	{
  		if (!nlc->szProxyServer) return false;
 @@ -579,8 +601,11 @@ static bool my_connectIPv6(NetlibConnection *nlc, NETLIBOPENCONNECTION * nloc)  		}
  	}
 -    for (ai = air; ai && !Miranda_Terminated(); ai = ai->ai_next)
 +	for (ai = air; ai && !Miranda_Terminated(); ai = ai->ai_next)
  	{
 +		char* szIp = NetlibAddressToString((SOCKADDR_INET_M*)ai->ai_addr);
 +		NetlibLogf(nlc->nlu,"(%p) Connecting to ip %s ....", nlc, szIp);
 +		mir_free(szIp);
  retry:
  		nlc->s = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
  		if (nlc->s == INVALID_SOCKET) return false;
 @@ -590,7 +615,9 @@ retry:  		if (nlc->nlu->settings.specifyOutgoingPorts && nlc->nlu->settings.szOutgoingPorts  && nlc->nlu->settings.szOutgoingPorts[0]) 
  		{
 -			if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, nlc->s, &nlc->nlu->inportnum))
 +			SOCKET s = ai->ai_family == AF_INET ? nlc->s : INVALID_SOCKET;
 +			SOCKET s6 = ai->ai_family == AF_INET6 ? nlc->s : INVALID_SOCKET;
 +			if (!BindSocketToPort(nlc->nlu->settings.szOutgoingPorts, s, s6, &nlc->nlu->inportnum))
  				NetlibLogf(nlc->nlu,"Netlib connect: Not enough ports for outgoing connections specified");
  		} 
 @@ -605,7 +632,10 @@ retry:  		if (WSAGetLastError() != WSAEWOULDBLOCK) 
  		{
  			rc = SOCKET_ERROR;
 -			break;
 +
 +			closesocket(nlc->s);
 +			nlc->s = INVALID_SOCKET;
 +			continue;
  		}
  		for (;;) // timeout loop 
  | 
