From cb4a46e7fbe62d788e66ed6121c717a2d22a4d7c Mon Sep 17 00:00:00 2001 From: watcherhd Date: Thu, 21 Apr 2011 14:14:52 +0000 Subject: svn.miranda.im is moving to a new home! git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@7 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- miranda-wine/src/modules/netlib/netlibopenconn.c | 569 +++++++++++++++++++++++ 1 file changed, 569 insertions(+) create mode 100644 miranda-wine/src/modules/netlib/netlibopenconn.c (limited to 'miranda-wine/src/modules/netlib/netlibopenconn.c') diff --git a/miranda-wine/src/modules/netlib/netlibopenconn.c b/miranda-wine/src/modules/netlib/netlibopenconn.c new file mode 100644 index 0000000..6d19e1c --- /dev/null +++ b/miranda-wine/src/modules/netlib/netlibopenconn.c @@ -0,0 +1,569 @@ +/* + +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2006 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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 "commonheaders.h" +#include "netlib.h" + +extern CRITICAL_SECTION csNetlibUser; +extern DWORD g_LastConnectionTick; // protected by csNetlibUser + +//returns in network byte order +DWORD DnsLookup(struct NetlibUser *nlu,const char *szHost) +{ + DWORD ip; + HOSTENT *host; + + ip=inet_addr(szHost); + if(ip!=INADDR_NONE) return ip; + host=gethostbyname(szHost); + if(host) return *(u_long *)host->h_addr_list[0]; + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"gethostbyname",WSAGetLastError()); + return 0; +} + +int WaitUntilReadable(SOCKET s,DWORD dwTimeout) +{ + fd_set readfd; + TIMEVAL tv; + + tv.tv_sec=dwTimeout/1000; + tv.tv_usec=(dwTimeout%1000)*1000; + FD_ZERO(&readfd); + FD_SET(s,&readfd); + switch(select(0,&readfd,0,0,&tv)) { + case 0: + SetLastError(ERROR_TIMEOUT); + case SOCKET_ERROR: + return 0; + } + return 1; +} + +static int WaitUntilWritable(SOCKET s,DWORD dwTimeout) +{ + fd_set writefd; + TIMEVAL tv; + + tv.tv_sec=dwTimeout/1000; + tv.tv_usec=(dwTimeout%1000)*1000; + FD_ZERO(&writefd); + FD_SET(s,&writefd); + switch(select(0,0,&writefd,0,&tv)) { + case 0: + SetLastError(ERROR_TIMEOUT); + case SOCKET_ERROR: + return 0; + } + return 1; +} + +static int NetlibInitSocks4Connection(struct NetlibConnection *nlc,struct NetlibUser *nlu,NETLIBOPENCONNECTION *nloc) +{ //http://www.socks.nec.com/protocol/socks4.protocol and http://www.socks.nec.com/protocol/socks4a.protocol + PBYTE pInit; + int nUserLen,nHostLen,len; + BYTE reply[8]; + + nUserLen=lstrlenA(nlu->settings.szProxyAuthUser); + nHostLen=lstrlenA(nloc->szHost); + pInit=(PBYTE)mir_alloc(10+nUserLen+nHostLen); + pInit[0]=4; //SOCKS4 + pInit[1]=1; //connect + *(PWORD)(pInit+2)=htons(nloc->wPort); + if(nlu->settings.szProxyAuthUser==NULL) pInit[8]=0; + else lstrcpyA(pInit+8,nlu->settings.szProxyAuthUser); + if(nlu->settings.dnsThroughProxy) { + if((*(PDWORD)(pInit+4)=inet_addr(nloc->szHost))==INADDR_NONE) { + *(PDWORD)(pInit+4)=0x01000000; + lstrcpyA(pInit+9+nUserLen,nloc->szHost); + len=10+nUserLen+nHostLen; + } + else len=9+nUserLen; + } + else { + *(PDWORD)(pInit+4)=DnsLookup(nlu,nloc->szHost); + if(*(PDWORD)(pInit+4)==0) { + mir_free(pInit); + return 0; + } + len=9+nUserLen; + } + if(NLSend(nlc,pInit,len,MSG_DUMPPROXY)==SOCKET_ERROR) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError()); + mir_free(pInit); + return 0; + } + mir_free(pInit); + + if(!WaitUntilReadable(nlc->s,30000)) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"WaitUntilReadable",GetLastError()); + return 0; + } + + len=NLRecv(nlc,reply,SIZEOF(reply),MSG_DUMPPROXY); + if(len < sizeof(reply) || reply[1]!=90) { + if(len != SOCKET_ERROR) { + if (len < SIZEOF(reply)) SetLastError(ERROR_BAD_FORMAT); + else switch(reply[1]) { + case 91: SetLastError(ERROR_ACCESS_DENIED); break; + case 92: SetLastError(ERROR_CONNECTION_UNAVAIL); break; + case 93: SetLastError(ERROR_INVALID_ACCESS); break; + default: SetLastError(ERROR_INVALID_DATA); break; + } + } + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLRecv",GetLastError()); + return 0; + } + //connected + return 1; +} + +static int NetlibInitSocks5Connection(struct NetlibConnection *nlc,struct NetlibUser *nlu,NETLIBOPENCONNECTION *nloc) +{ //rfc1928 + int len; + BYTE buf[256]; + + buf[0]=5; //yep, socks5 + buf[1]=1; //one auth method + buf[2]=nlu->settings.useProxyAuth?2:0; + if(NLSend(nlc,buf,3,MSG_DUMPPROXY)==SOCKET_ERROR) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError()); + return 0; + } + + if(!WaitUntilReadable(nlc->s,10000)) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"WaitUntilReadable",GetLastError()); + return 0; + } + + len=NLRecv(nlc,buf,2,MSG_DUMPPROXY); //confirmation of auth method + if(len<2 || (buf[1]!=0 && buf[1]!=2)) { + if(len!=SOCKET_ERROR) { + if(len<2) SetLastError(ERROR_BAD_FORMAT); + else SetLastError(ERROR_INVALID_ID_AUTHORITY); + } + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLRecv",GetLastError()); + return 0; + } + + if(buf[1]==2) { //rfc1929 + int nUserLen,nPassLen; + PBYTE pAuthBuf; + + nUserLen=lstrlenA(nlu->settings.szProxyAuthUser); + nPassLen=lstrlenA(nlu->settings.szProxyAuthPassword); + pAuthBuf=(PBYTE)mir_alloc(3+nUserLen+nPassLen); + pAuthBuf[0]=1; //auth version + pAuthBuf[1]=nUserLen; + memcpy(pAuthBuf+2,nlu->settings.szProxyAuthUser,nUserLen); + pAuthBuf[2+nUserLen]=nPassLen; + memcpy(pAuthBuf+3+nUserLen,nlu->settings.szProxyAuthPassword,nPassLen); + if(NLSend(nlc,pAuthBuf,3+nUserLen+nPassLen,MSG_DUMPPROXY)==SOCKET_ERROR) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError()); + mir_free(pAuthBuf); + return 0; + } + mir_free(pAuthBuf); + + if(!WaitUntilReadable(nlc->s,10000)) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"WaitUntilReadable",GetLastError()); + return 0; + } + + len=NLRecv(nlc,buf,SIZEOF(buf),MSG_DUMPPROXY); + if(len<2 || buf[1]) { + if(len!=SOCKET_ERROR) { + if(len<2) SetLastError(ERROR_BAD_FORMAT); + else SetLastError(ERROR_ACCESS_DENIED); + } + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLRecv",GetLastError()); + return 0; + } + } + + { PBYTE pInit; + int nHostLen; + DWORD hostIP; + + if(nlu->settings.dnsThroughProxy) { + if((hostIP=inet_addr(nloc->szHost))==INADDR_NONE) + nHostLen=lstrlenA(nloc->szHost)+1; + else nHostLen=4; + } + else { + if((hostIP=DnsLookup(nlu,nloc->szHost))==0) + return 0; + nHostLen=4; + } + pInit=(PBYTE)mir_alloc(6+nHostLen); + pInit[0]=5; //SOCKS5 + pInit[1]=1; //connect + pInit[2]=0; //reserved + if(hostIP==INADDR_NONE) { //DNS lookup through proxy + pInit[3]=3; + pInit[4]=nHostLen-1; + memcpy(pInit+5,nloc->szHost,nHostLen-1); + } + else { + pInit[3]=1; + *(PDWORD)(pInit+4)=hostIP; + } + *(PWORD)(pInit+4+nHostLen)=htons(nloc->wPort); + if(NLSend(nlc,pInit,6+nHostLen,MSG_DUMPPROXY)==SOCKET_ERROR) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLSend",GetLastError()); + mir_free(pInit); + return 0; + } + mir_free(pInit); + } + + if(!WaitUntilReadable(nlc->s,30000)) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"WaitUntilReadable",GetLastError()); + return 0; + } + + len=NLRecv(nlc,buf,SIZEOF(buf),MSG_DUMPPROXY); + if(len<7 || buf[0]!=5 || buf[1]) { + if(len!=SOCKET_ERROR) { + if(len<7 || buf[0]!=5) SetLastError(ERROR_BAD_FORMAT); + else switch(buf[1]) { + case 1: SetLastError(ERROR_GEN_FAILURE); break; + case 2: SetLastError(ERROR_ACCESS_DENIED); break; + case 3: SetLastError(WSAENETUNREACH); break; + case 4: SetLastError(WSAEHOSTUNREACH); break; + case 5: SetLastError(WSAECONNREFUSED); break; + case 6: SetLastError(WSAETIMEDOUT); break; + case 7: SetLastError(ERROR_CALL_NOT_IMPLEMENTED); break; + case 8: SetLastError(ERROR_INVALID_ADDRESS); break; + default: SetLastError(ERROR_INVALID_DATA); break; + } + } + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"NLRecv",GetLastError()); + return 0; + } + //connected + return 1; +} + +static int NetlibInitHttpsConnection(struct NetlibConnection *nlc,struct NetlibUser *nlu,NETLIBOPENCONNECTION *nloc) +{ //rfc2817 + NETLIBHTTPHEADER httpHeaders[3]; + NETLIBHTTPREQUEST nlhrSend={0},*nlhrReply; + char szUrl[512]; + + memset(httpHeaders,0,sizeof(httpHeaders)); + + nlhrSend.cbSize=sizeof(nlhrSend); + nlhrSend.requestType=REQUEST_CONNECT; + nlhrSend.flags=NLHRF_DUMPPROXY|NLHRF_SMARTAUTHHEADER|NLHRF_HTTP11; + if(nlu->settings.dnsThroughProxy) { + mir_snprintf(szUrl,SIZEOF(szUrl),"%s:%u",nloc->szHost,nloc->wPort); + if(inet_addr(nloc->szHost)==INADDR_NONE) { + httpHeaders[0].szName="Host"; + httpHeaders[0].szValue=szUrl; + nlhrSend.headersCount++; + } + } + else { + struct in_addr addr; + DWORD ip=DnsLookup(nlu,nloc->szHost); + if(ip==0) return 0; + addr.S_un.S_addr=ip; + mir_snprintf(szUrl,SIZEOF(szUrl),"%s:%u",inet_ntoa(addr),nloc->wPort); + } + nlhrSend.szUrl=szUrl; + nlhrSend.headers=httpHeaders; + nlhrSend.headersCount=0; + if(NetlibHttpSendRequest((WPARAM)nlc,(LPARAM)&nlhrSend)==SOCKET_ERROR) + return 0; + nlhrReply=(NETLIBHTTPREQUEST*)NetlibHttpRecvHeaders((WPARAM)nlc,MSG_DUMPPROXY); + if(nlhrReply==NULL) return 0; + if(nlhrReply->resultCode<200 || nlhrReply->resultCode>=300) { + NetlibHttpSetLastErrorUsingHttpResult(nlhrReply->resultCode); + Netlib_Logf(nlu,"%s %d: %s request failed (%u %s)",__FILE__,__LINE__,nlu->settings.proxyType==PROXYTYPE_HTTP?"HTTP":"HTTPS",nlhrReply->resultCode,nlhrReply->szResultDescr); + NetlibHttpFreeRequestStruct(0,(LPARAM)nlhrReply); + return 0; + } + NetlibHttpFreeRequestStruct(0,(LPARAM)nlhrReply); + //connected + return 1; +} + +static void FreePartiallyInitedConnection(struct NetlibConnection *nlc) +{ + DWORD dwOriginalLastError=GetLastError(); + + if(nlc->s!=INVALID_SOCKET) closesocket(nlc->s); + if(nlc->nlhpi.szHttpPostUrl) mir_free(nlc->nlhpi.szHttpPostUrl); + if(nlc->nlhpi.szHttpGetUrl) mir_free(nlc->nlhpi.szHttpGetUrl); + if(nlc->hInstSecurityDll) FreeLibrary(nlc->hInstSecurityDll); + NetlibDeleteNestedCS(&nlc->ncsSend); + NetlibDeleteNestedCS(&nlc->ncsRecv); + CloseHandle(nlc->hOkToCloseEvent); + DeleteCriticalSection(&nlc->csHttpSequenceNums); + mir_free(nlc); + SetLastError(dwOriginalLastError); +} + +#define PortInMask(mask,p) ((mask)[((p)&0xFFFF)>>3]&(1<<((p)&7))) + +static int my_connect(SOCKET s, const struct sockaddr * name, int namelen, NETLIBOPENCONNECTION * nloc) +{ + int rc=0; + unsigned int dwTimeout=( nloc->cbSize==sizeof(NETLIBOPENCONNECTION) && nloc->flags&NLOCF_V2 ) ? nloc->timeout : 0; + u_long notblocking=1; + TIMEVAL tv; + DWORD lasterr = 0; + int waitdiff; + // if dwTimeout is zero then its an old style connection or new with a 0 timeout, select() will error quicker anyway + if ( dwTimeout == 0 ) + dwTimeout += 60; + // return the socket to non blocking + if ( ioctlsocket(s, FIONBIO, ¬blocking) != 0 ) { + return SOCKET_ERROR; + } + // this is for XP SP2 where there is a default connection attempt limit of 10/second + EnterCriticalSection(&csNetlibUser); + waitdiff=GetTickCount() - g_LastConnectionTick; + g_LastConnectionTick=GetTickCount(); + LeaveCriticalSection(&csNetlibUser); + if ( waitdiff < 1000 ) { + // last connection was less than 1 second ago, wait 1.2 seconds + SleepEx(1200,TRUE); + } + // might of died in between the wait + if ( Miranda_Terminated() ) { + rc=SOCKET_ERROR; + lasterr=ERROR_TIMEOUT; + goto unblock; + } + // try a connect + if ( connect(s, name, namelen) == 0 ) { + goto unblock; + } + // didn't work, was it cos of nonblocking? + if ( WSAGetLastError() != WSAEWOULDBLOCK ) { + rc=SOCKET_ERROR; + lasterr=WSAGetLastError(); + goto unblock; + } + // setup select() + tv.tv_sec=1; + tv.tv_usec=0; + for (;;) { + fd_set r, w, e; + FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e); + FD_SET(s, &r); + FD_SET(s, &w); + FD_SET(s, &e); + if ( (rc=select(0, &r, &w, &e, &tv)) == SOCKET_ERROR ) { + break; + } + if ( rc > 0 ) { + if ( FD_ISSET(s, &r) ) { + // connection was closed + rc=SOCKET_ERROR; + lasterr=WSAECONNRESET; + } + if ( FD_ISSET(s, &w) ) { + // connection was successful + rc=0; + } + if ( FD_ISSET(s, &e) ) { + // connection failed. + int len=sizeof(lasterr); + rc=SOCKET_ERROR; + getsockopt(s,SOL_SOCKET,SO_ERROR,(char*)&lasterr,&len); + } + goto unblock; + } else if ( Miranda_Terminated() ) { + rc=SOCKET_ERROR; + lasterr=ERROR_TIMEOUT; + goto unblock; + } else if ( nloc->cbSize==sizeof(NETLIBOPENCONNECTION) && nloc->flags&NLOCF_V2 && nloc->waitcallback != NULL + && nloc->waitcallback(&dwTimeout) == 0) { + rc=SOCKET_ERROR; + lasterr=ERROR_TIMEOUT; + goto unblock; + } + if ( --dwTimeout == 0 ) { + rc=SOCKET_ERROR; + lasterr=ERROR_TIMEOUT; + goto unblock; + } + } +unblock: + notblocking=0; + ioctlsocket(s, FIONBIO, ¬blocking); + SetLastError(lasterr); + return rc; +} + +int NetlibOpenConnection(WPARAM wParam,LPARAM lParam) +{ + NETLIBOPENCONNECTION *nloc=(NETLIBOPENCONNECTION*)lParam; + struct NetlibUser *nlu=(struct NetlibUser*)wParam; + struct NetlibConnection *nlc; + SOCKADDR_IN sin; + + if(GetNetlibHandleType(nlu)!=NLH_USER || !(nlu->user.flags&NUF_OUTGOING) || nloc==NULL + || !(nloc->cbSize==NETLIBOPENCONNECTION_V1_SIZE||nloc->cbSize==sizeof(NETLIBOPENCONNECTION)) || nloc->szHost==NULL || nloc->wPort==0) { + SetLastError(ERROR_INVALID_PARAMETER); + return (int)(HANDLE)NULL; + } + nlc=(struct NetlibConnection*)mir_calloc(sizeof(struct NetlibConnection)); + nlc->handleType=NLH_CONNECTION; + nlc->nlu=nlu; + nlc->s=socket(AF_INET,SOCK_STREAM,0); + if(nlc->s==INVALID_SOCKET) { + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"socket",WSAGetLastError()); + mir_free(nlc); + return (int)(HANDLE)NULL; + } + if (nlu->settings.specifyOutgoingPorts && nlu->settings.szOutgoingPorts) + { + BYTE portsMask[0x2000]; + int startPort,portNum,i,j,portsCount; + + sin.sin_family=AF_INET; + sin.sin_addr.s_addr=htonl(INADDR_ANY); + sin.sin_port=0; + + portsCount=StringToPortsMask(nlu->settings.szOutgoingPorts,portsMask); + if (portsCount) { + startPort=rand() % portsCount; + for (i=0;i<0x02000;i++) { + if(portsMask[i]==0) continue; + if(portsMask[i]==0xFF && startPort>=8) {startPort-=8; continue;} + for(j=0;j<8;j++) + if(portsMask[i]&(1<s,(SOCKADDR*)&sin,sizeof(sin))==0) break; + for(portNum++;!PortInMask(portsMask,portNum);portNum++) + if(portNum==0xFFFF) portNum=0; + } while (portNum!=startPort); + } //if + } //if + } + InitializeCriticalSection(&nlc->csHttpSequenceNums); + nlc->hOkToCloseEvent=CreateEvent(NULL,TRUE,TRUE,NULL); + nlc->dontCloseNow=0; + NetlibInitializeNestedCS(&nlc->ncsSend); + NetlibInitializeNestedCS(&nlc->ncsRecv); + if(nlu->settings.useProxy && (nlu->settings.proxyType==PROXYTYPE_HTTP || nlu->settings.proxyType==PROXYTYPE_HTTPS) && nlu->settings.useProxyAuth && nlu->settings.useProxyAuthNtlm) + nlc->hInstSecurityDll=LoadLibraryA("security.dll"); + + nlc->sinProxy.sin_family=AF_INET; + if(nlu->settings.useProxy) { + nlc->sinProxy.sin_port=htons((short)nlu->settings.wProxyPort); + nlc->sinProxy.sin_addr.S_un.S_addr=DnsLookup(nlu,nlu->settings.szProxyServer); + } + else { + nlc->sinProxy.sin_port=htons((short)nloc->wPort); + nlc->sinProxy.sin_addr.S_un.S_addr=DnsLookup(nlu,nloc->szHost); + } + if(nlc->sinProxy.sin_addr.S_un.S_addr==0 + || my_connect(nlc->s,(SOCKADDR *)&nlc->sinProxy,sizeof(nlc->sinProxy), nloc)==SOCKET_ERROR) { + if(nlc->sinProxy.sin_addr.S_un.S_addr) + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"connect",WSAGetLastError()); + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + + if(nlu->settings.useProxy + && !(nloc->flags&NLOCF_HTTP + && (nlu->settings.proxyType==PROXYTYPE_HTTP || nlu->settings.proxyType==PROXYTYPE_HTTPS))) + { + if(!WaitUntilWritable(nlc->s,30000)) { + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + + switch(nlu->settings.proxyType) { + case PROXYTYPE_SOCKS4: + if(!NetlibInitSocks4Connection(nlc,nlu,nloc)) { + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + break; + + case PROXYTYPE_SOCKS5: + if(!NetlibInitSocks5Connection(nlc,nlu,nloc)) { + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + break; + + case PROXYTYPE_HTTPS: + if(!NetlibInitHttpsConnection(nlc,nlu,nloc)) { + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + break; + + case PROXYTYPE_HTTP: + if(!(nlu->user.flags&NUF_HTTPGATEWAY)) { + //NLOCF_HTTP not specified and no HTTP gateway available: try HTTPS + if(!NetlibInitHttpsConnection(nlc,nlu,nloc)) { + //can't do HTTPS: try direct + if(nlc->s!=INVALID_SOCKET) closesocket(nlc->s); + + nlc->s=socket(AF_INET,SOCK_STREAM,0); + if(nlc->s==INVALID_SOCKET) { + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + nlc->sinProxy.sin_family=AF_INET; + nlc->sinProxy.sin_port=htons((short)nloc->wPort); + nlc->sinProxy.sin_addr.S_un.S_addr=DnsLookup(nlu,nloc->szHost); + if(nlc->sinProxy.sin_addr.S_un.S_addr==0 + || my_connect(nlc->s,(SOCKADDR *)&nlc->sinProxy,sizeof(nlc->sinProxy), nloc)==SOCKET_ERROR) { + if(nlc->sinProxy.sin_addr.S_un.S_addr) + Netlib_Logf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"connect",WSAGetLastError()); + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + } + } + else if(!NetlibInitHttpConnection(nlc,nlu,nloc)) { + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + break; + + default: + SetLastError(ERROR_INVALID_PARAMETER); + FreePartiallyInitedConnection(nlc); + return (int)(HANDLE)NULL; + } + } + Netlib_Logf(nlu,"(%d) Connected to %s:%d",nlc->s,nloc->szHost,nloc->wPort); + return (int)nlc; +} -- cgit v1.2.3