From 8549e48fbb8520027d4d8ba74b6f12f3042faebc Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sun, 27 May 2012 21:30:30 +0000 Subject: ipv6 sync git-svn-id: http://svn.miranda-ng.org/main/trunk@205 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- include/m_netlib.h | 42 ++++ protocols/AimOscar/client.cpp | 9 +- protocols/IcqOscarJ/oscar_filetransfer.cpp | 2 +- protocols/JabberG/jabber_byte.cpp | 54 ++--- protocols/JabberG/jabber_file.cpp | 43 ++-- protocols/JabberG/jabber_proto.h | 1 - protocols/JabberG/jabber_thread.cpp | 22 +- protocols/MSN/msn_commands.cpp | 30 +-- protocols/MSN/msn_global.h | 1 + protocols/MSN/msn_mime.cpp | 2 + protocols/MSN/msn_misc.cpp | 106 +++++----- protocols/MSN/msn_p2p.cpp | 311 +++++++++++++++-------------- protocols/MSN/msn_proto.h | 2 +- src/core/commonheaders.h | 2 + src/core/miranda.cpp | 12 +- src/core/miranda.h | 9 +- src/modules/netlib/netlib.cpp | 56 +++++- src/modules/netlib/netlib.h | 14 +- src/modules/netlib/netlibbind.cpp | 129 ++++++++---- src/modules/netlib/netlibhttp.cpp | 4 +- src/modules/netlib/netlibopenconn.cpp | 204 +++++++++++-------- src/modules/netlib/netlibsock.cpp | 280 ++++++++++++++++++++------ src/modules/updatenotify/updatenotify.cpp | 14 +- 23 files changed, 831 insertions(+), 518 deletions(-) diff --git a/include/m_netlib.h b/include/m_netlib.h index af9f21e51e..34a6647c66 100644 --- a/include/m_netlib.h +++ b/include/m_netlib.h @@ -424,6 +424,48 @@ typedef struct { #define Netlib_GetBase64EncodedBufferSize(cbDecoded) (((cbDecoded)*4+11)/12*4+1) #define MS_NETLIB_BASE64ENCODE "Netlib/Base64Encode" +// Converts string representation of IP and port into numerical SOCKADDR_INET +// IPv4 could supplied in formats address:port or address +// IPv6 could supplied in formats [address]:port or [address] +// wParam=(WPARAM)(char*) string to convert +// lParam=(LPARAM)(SOCKADDR_INET*) numeric IP address structure +// Returns 0 on success +#define MS_NETLIB_STARINGTOADDRESS "Netlib/StringToAddress" + +// Converts numerical representation of IP in SOCKADDR_INET into string representation with IP and port +// IPv4 will be supplied in formats address:port or address +// IPv6 will be supplied in formats [address]:port or [address] +// wParam=(WPARAM)(int) 0 - lParam - (sockaddr_gen*); 1 - lParam - (unsigned) in host byte order +// lParam=(LPARAM)(sockaddr_gen*) or (unsigned) numeric IP address structure +// Returns pointer to the string or NULL if not successful +#define MS_NETLIB_ADDRESSTOSTRING "Netlib/AddressToString" + +typedef struct { + int cbSize; + char szIpPort[64]; + unsigned dwIpv4; + WORD wPort; +} NETLIBCONNINFO; + +// Get connection Information +// IPv4 will be supplied in formats address:port or address +// IPv6 will be supplied in formats [address]:port or [address] +// wParam=(WPARAM)(HANDLE)hConnection +// lParam=(LPARAM)(NETLIBCONNINFO*) pointer to the connection information structure to fill +// Returns 0 if successful +#define MS_NETLIB_GETCONNECTIONINFO "Netlib/GetConnectionInfo" + +typedef struct { + unsigned cbNum; + char szIp[1][64]; +} NETLIBIPLIST; + +// Get connection Information +// wParam=(WPARAM)IP filter 1 - return global only IPv6 address, 0 all IPs +// Returns (INT_PTR)(NETLIBIPLIST*) numeric IP address address array +// the last element of the array is all 0s, 0 if not successful +#define MS_NETLIB_GETMYIP "Netlib/GetMyIP" + //Send an HTTP request over a connection //wParam=(WPARAM)(HANDLE)hConnection //lParam=(LPARAM)(NETLIBHTTPREQUEST*)&nlhr diff --git a/protocols/AimOscar/client.cpp b/protocols/AimOscar/client.cpp index 6c3dbfb86a..2fc4333728 100644 --- a/protocols/AimOscar/client.cpp +++ b/protocols/AimOscar/client.cpp @@ -260,12 +260,15 @@ int CAimProto::aim_client_ready(HANDLE hServerConn,unsigned short &seqno) if (hDirectBoundPort == NULL) { ShowPopup(LPGEN("Aim was unable to bind to a port. File transfers may not succeed in some cases."), ERROR_POPUP); + local_port = 0; } else - { local_port = nlb.wPort; - internal_ip = nlb.dwInternalIP; - } + + NETLIBCONNINFO connInfo = { sizeof(connInfo) }; + CallService(MS_NETLIB_GETCONNECTIONINFO, (WPARAM)hServerConn, (LPARAM)&connInfo); + + internal_ip = connInfo.dwIpv4; char buf[SNAC_SIZE+TLV_HEADER_SIZE*22]; aim_writesnac(0x01,0x02,offset,buf); diff --git a/protocols/IcqOscarJ/oscar_filetransfer.cpp b/protocols/IcqOscarJ/oscar_filetransfer.cpp index b6dd52cf5f..bc359f0fa1 100644 --- a/protocols/IcqOscarJ/oscar_filetransfer.cpp +++ b/protocols/IcqOscarJ/oscar_filetransfer.cpp @@ -885,7 +885,7 @@ HANDLE CIcqProto::oftInitTransfer(HANDLE hContact, DWORD dwUin, char* szUid, con } } - for (int i = 0; i < filesCount; i++) + for (i = 0; i < filesCount; i++) SAFE_FREE(&filesUtf[i]); SAFE_FREE((void**)&filesUtf); diff --git a/protocols/JabberG/jabber_byte.cpp b/protocols/JabberG/jabber_byte.cpp index 67015b3bcd..aa030aa7e8 100644 --- a/protocols/JabberG/jabber_byte.cpp +++ b/protocols/JabberG/jabber_byte.cpp @@ -85,10 +85,6 @@ void CJabberProto::IqResultProxyDiscovery( HXML iqNode, CJabberIqInfo* pInfo ) void JabberByteSendConnection( HANDLE hConn, DWORD /*dwRemoteIP*/, void* extra ) { CJabberProto* ppro = ( CJabberProto* )extra; - SOCKET s; - SOCKADDR_IN saddr; - int len; - WORD localPort; TCHAR szPort[8]; JABBER_BYTE_TRANSFER *jbt; int recvResult, bytesParsed; @@ -97,20 +93,11 @@ void JabberByteSendConnection( HANDLE hConn, DWORD /*dwRemoteIP*/, void* extra ) char* buffer; int datalen; - localPort = 0; - if (( s = JCallService( MS_NETLIB_GETSOCKET, ( WPARAM ) hConn, 0 )) != INVALID_SOCKET ) { - len = sizeof( saddr ); - if ( getsockname( s, ( SOCKADDR * ) &saddr, &len ) != SOCKET_ERROR ) - localPort = ntohs( saddr.sin_port ); - } - if ( localPort == 0 ) { - ppro->Log( "bytestream_send_connection unable to determine the local port, connection closed." ); - Netlib_CloseHandle( hConn ); - return; - } + NETLIBCONNINFO connInfo = { sizeof(connInfo) }; + CallService(MS_NETLIB_GETCONNECTIONINFO, (WPARAM)hConn, (LPARAM)&connInfo); - mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), localPort ); - ppro->Log( "bytestream_send_connection incoming connection accepted: local_port=" TCHAR_STR_PARAM, szPort ); + mir_sntprintf( szPort, SIZEOF( szPort ), _T("%u"), connInfo.wPort ); + ppro->Log( "bytestream_send_connection incoming connection accepted: %s", connInfo.szIpPort ); if (( item = ppro->ListGetItemPtr( LIST_BYTE, szPort )) == NULL ) { ppro->Log( "No bytestream session is currently active, connection closed." ); @@ -157,9 +144,7 @@ void JabberByteSendConnection( HANDLE hConn, DWORD /*dwRemoteIP*/, void* extra ) void CJabberProto::ByteSendThread( JABBER_BYTE_TRANSFER *jbt ) { - char* localAddr; - char* localAddrInternal; - struct in_addr in; + char* localAddr = NULL; DBVARIANT dbv; TCHAR szPort[8]; HANDLE hEvent = NULL; @@ -216,12 +201,10 @@ void CJabberProto::ByteSendThread( JABBER_BYTE_TRANSFER *jbt ) HXML query = iq << XQUERY( _T(JABBER_FEAT_BYTESTREAMS)) << XATTR( _T("sid"), jbt->sid ); if ( bDirect ) { - localAddr = NULL; - if ( m_options.BsDirectManual == TRUE ) { - if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) { - localAddr = NEWSTR_ALLOCA( dbv.pszVal ); - JFreeVariant( &dbv ); - } } + if ( m_options.BsDirectManual ) { + if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) + localAddr = dbv.pszVal; + } NETLIBBIND nlb = {0}; nlb.cbSize = sizeof( NETLIBBIND ); @@ -234,12 +217,9 @@ void CJabberProto::ByteSendThread( JABBER_BYTE_TRANSFER *jbt ) delete jbt; return; } - if ( localAddr == NULL ) { - in.S_un.S_addr = htonl(nlb.dwExternalIP); - localAddr = NEWSTR_ALLOCA( inet_ntoa( in )); - } - in.S_un.S_addr = htonl(nlb.dwInternalIP); - localAddrInternal = NEWSTR_ALLOCA( inet_ntoa( in )); + + if ( localAddr == NULL ) + localAddr = (char*)CallService( MS_NETLIB_ADDRESSTOSTRING, 1, nlb.dwExternalIP ); mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), nlb.wPort ); JABBER_LIST_ITEM *item = ListAdd( LIST_BYTE, szPort ); @@ -248,8 +228,14 @@ void CJabberProto::ByteSendThread( JABBER_BYTE_TRANSFER *jbt ) jbt->hEvent = hEvent; jbt->hSendEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); query << XCHILD( _T("streamhost")) << XATTR( _T("jid"), m_ThreadInfo->fullJID ) << XATTR( _T("host"), _A2T(localAddr)) << XATTRI( _T("port"), nlb.wPort ); - if ( strcmp( localAddr, localAddrInternal )) - query << XCHILD( _T("streamhost")) << XATTR( _T("jid"), m_ThreadInfo->fullJID ) << XATTR( _T("host"), _A2T(localAddrInternal)) << XATTRI( _T("port"), nlb.wPort ); + + NETLIBIPLIST* ihaddr = ( NETLIBIPLIST* )CallService( MS_NETLIB_GETMYIP, 1, 0 ); + for ( unsigned i = 0; i < ihaddr->cbNum; ++i ) + if ( strcmp( localAddr, ihaddr->szIp[i] )) + query << XCHILD( _T("streamhost")) << XATTR( _T("jid"), m_ThreadInfo->fullJID ) << XATTR( _T("host"), _A2T(ihaddr->szIp[i])) << XATTRI( _T("port"), nlb.wPort ); + + mir_free( ihaddr ); + mir_free( localAddr ); } if ( jbt->bProxyDiscovered ) diff --git a/protocols/JabberG/jabber_file.cpp b/protocols/JabberG/jabber_file.cpp index 9577c310e9..3cce546bef 100644 --- a/protocols/JabberG/jabber_file.cpp +++ b/protocols/JabberG/jabber_file.cpp @@ -196,24 +196,13 @@ int CJabberProto::FileReceiveParse( filetransfer* ft, char* buffer, int datalen void JabberFileServerConnection( JABBER_SOCKET hConnection, DWORD /*dwRemoteIP*/, void* extra ) { CJabberProto* ppro = ( CJabberProto* )extra; - WORD localPort = 0; - SOCKET s = JCallService( MS_NETLIB_GETSOCKET, ( WPARAM ) hConnection, 0 ); - if ( s != INVALID_SOCKET ) { - SOCKADDR_IN saddr; - int len = sizeof( saddr ); - if ( getsockname( s, ( SOCKADDR * ) &saddr, &len ) != SOCKET_ERROR ) { - localPort = ntohs( saddr.sin_port ); - } - } - if ( localPort == 0 ) { - ppro->Log( "Unable to determine the local port, file server connection closed." ); - Netlib_CloseHandle( hConnection ); - return; - } - TCHAR szPort[20]; - mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), localPort ); - ppro->Log( "File server incoming connection accepted: local_port=" TCHAR_STR_PARAM, szPort ); + NETLIBCONNINFO connInfo = { sizeof(connInfo) }; + CallService(MS_NETLIB_GETCONNECTIONINFO, (WPARAM)hConnection, (LPARAM)&connInfo); + + TCHAR szPort[10]; + mir_sntprintf( szPort, SIZEOF( szPort ), _T("%d"), connInfo.wPort ); + ppro->Log( "File server incoming connection accepted: %s", connInfo.szIpPort ); JABBER_LIST_ITEM *item = ppro->ListGetItemPtr( LIST_FILE, szPort ); if ( item == NULL ) { @@ -311,9 +300,6 @@ void __cdecl CJabberProto::FileServerThread( filetransfer* ft ) else p = ft->std.ptszFiles[i]; - in_addr in; - in.S_un.S_addr = m_dwJabberLocalIP; - TCHAR* pFileName = JabberHttpUrlEncode( p ); if ( pFileName != NULL ) { int id = SerialNext(); @@ -321,20 +307,22 @@ void __cdecl CJabberProto::FileServerThread( filetransfer* ft ) ft->iqId = ( TCHAR* )mir_alloc( sizeof(TCHAR)*( strlen( JABBER_IQID )+20 )); wsprintf( ft->iqId, _T(JABBER_IQID)_T("%d"), id ); - char *myAddr; + char *myAddr = NULL; DBVARIANT dbv; if (m_options.BsDirect && m_options.BsDirectManual) { - if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) { - myAddr = NEWSTR_ALLOCA( dbv.pszVal ); - JFreeVariant( &dbv ); - } - else myAddr = inet_ntoa( in ); + if ( !DBGetContactSettingString( NULL, m_szModuleName, "BsDirectAddr", &dbv )) + myAddr = dbv.pszVal; } - else myAddr = inet_ntoa( in ); + + if ( myAddr == NULL ) + myAddr = (char*)CallService( MS_NETLIB_ADDRESSTOSTRING, 1, nlb.dwExternalIP ); char szAddr[ 256 ]; mir_snprintf( szAddr, sizeof(szAddr), "http://%s:%d/%s", myAddr, nlb.wPort, pFileName ); + mir_free( pFileName ); + mir_free( myAddr ); + int len = lstrlen(ptszResource) + lstrlen(ft->jid) + 2; TCHAR* fulljid = ( TCHAR* )alloca( sizeof( TCHAR )*len ); wsprintf( fulljid, _T("%s/%s"), ft->jid, ptszResource ); @@ -347,7 +335,6 @@ void __cdecl CJabberProto::FileServerThread( filetransfer* ft ) Log( "Waiting for the file to be sent..." ); WaitForSingleObject( hEvent, INFINITE ); - mir_free( pFileName ); } Log( "File sent, advancing to the next file..." ); JSendBroadcast( ft->std.hContact, ACKTYPE_FILE, ACKRESULT_NEXTFILE, ft, 0 ); diff --git a/protocols/JabberG/jabber_proto.h b/protocols/JabberG/jabber_proto.h index 9947fd155b..663c1d3ecd 100644 --- a/protocols/JabberG/jabber_proto.h +++ b/protocols/JabberG/jabber_proto.h @@ -260,7 +260,6 @@ struct CJabberProto : public PROTO_INTERFACE TCHAR* m_szJabberJID; char* m_szStreamId; - DWORD m_dwJabberLocalIP; BOOL m_bJabberConnected; // TCP connection to jabber server established BOOL m_bJabberOnline; // XMPP connection initialized and we can send XMPP packets int m_nJabberSearchID; diff --git a/protocols/JabberG/jabber_thread.cpp b/protocols/JabberG/jabber_thread.cpp index 68712157ab..3c343600c8 100644 --- a/protocols/JabberG/jabber_thread.cpp +++ b/protocols/JabberG/jabber_thread.cpp @@ -132,7 +132,8 @@ void CJabberProto::OnPingReply( HXML, CJabberIqInfo* pInfo ) return; if ( pInfo->GetIqType() == JABBER_IQ_TYPE_FAIL ) { // disconnect because of timeout - SetStatus(ID_STATUS_OFFLINE); + m_ThreadInfo->send( "" ); + m_ThreadInfo->shutdown(); } } @@ -428,17 +429,6 @@ LBL_FatalError: } // Determine local IP - int socket = JCallService( MS_NETLIB_GETSOCKET, ( WPARAM ) info->s, 0 ); - if ( info->type==JABBER_SESSION_NORMAL && socket!=INVALID_SOCKET ) { - struct sockaddr_in saddr; - int len; - - len = sizeof( saddr ); - getsockname( socket, ( struct sockaddr * ) &saddr, &len ); - m_dwJabberLocalIP = saddr.sin_addr.S_un.S_addr; - Log( "Local IP = %s", inet_ntoa( saddr.sin_addr )); - } - if ( info->useSSL ) { Log( "Intializing SSL connection" ); if (!JCallService( MS_NETLIB_STARTSSL, ( WPARAM )info->s, 0)) { @@ -1012,12 +1002,8 @@ void CJabberProto::OnProcessProceed( HXML node, ThreadData* info ) ssl.host = isHosted ? info->manualHost : info->server; if (!JCallService( MS_NETLIB_STARTSSL, ( WPARAM )info->s, ( LPARAM )&ssl)) { Log( "SSL initialization failed" ); - if (info->type == JABBER_SESSION_REGISTER) { - info->send( "" ); - info->shutdown(); - } - else - SetStatus(ID_STATUS_OFFLINE); + info->send( "" ); + info->shutdown(); } else xmlStreamInitialize( "after successful StartTLS" ); diff --git a/protocols/MSN/msn_commands.cpp b/protocols/MSN/msn_commands.cpp index 04d2ad7981..a85ff46fe4 100644 --- a/protocols/MSN/msn_commands.cpp +++ b/protocols/MSN/msn_commands.cpp @@ -30,30 +30,20 @@ void MSN_ConnectionProc(HANDLE hNewConnection, DWORD /* dwRemoteIP */, void* ext proto->MSN_DebugLog("File transfer connection accepted"); - WORD localPort = 0; - SOCKET s = MSN_CallService(MS_NETLIB_GETSOCKET, (WPARAM)hNewConnection, 0); - if (s != INVALID_SOCKET) + NETLIBCONNINFO connInfo = { sizeof(connInfo) }; + CallService(MS_NETLIB_GETCONNECTIONINFO, (WPARAM)hNewConnection, (LPARAM)&connInfo); + + ThreadData* T = proto->MSN_GetThreadByPort(connInfo.wPort); + if (T != NULL && T->s == NULL) { - SOCKADDR_IN saddr; - int len = sizeof(saddr); - if (getsockname(s, (SOCKADDR*)&saddr, &len) != SOCKET_ERROR) - localPort = ntohs(saddr.sin_port); + T->s = hNewConnection; + ReleaseSemaphore(T->hWaitEvent, 1, NULL); } - - if (localPort != 0) + else { - ThreadData* T = proto->MSN_GetThreadByPort(localPort); - if (T != NULL && T->s == NULL) - { - T->s = hNewConnection; - ReleaseSemaphore(T->hWaitEvent, 1, NULL); - return; - } - proto->MSN_DebugLog("There's no registered file transfers for incoming port #%d, connection closed", localPort); + proto->MSN_DebugLog("There's no registered file transfers for incoming port #%u, connection closed", connInfo.wPort); + Netlib_CloseHandle(hNewConnection); } - else proto->MSN_DebugLog("Unable to determine the local port, file server connection closed."); - - Netlib_CloseHandle(hNewConnection); } diff --git a/protocols/MSN/msn_global.h b/protocols/MSN/msn_global.h index 317b834afa..a2c1ba6dd6 100644 --- a/protocols/MSN/msn_global.h +++ b/protocols/MSN/msn_global.h @@ -167,6 +167,7 @@ void stripColorCode(char* src); void parseWLID(char* wlid, char** net, char** email, char** inst); char* MSN_Base64Decode(const char* str); +char* GetGlobalIp(void); template void UrlDecode(chartype* str); diff --git a/protocols/MSN/msn_mime.cpp b/protocols/MSN/msn_mime.cpp index 8351673308..b925e101bb 100644 --- a/protocols/MSN/msn_mime.cpp +++ b/protocols/MSN/msn_mime.cpp @@ -71,6 +71,8 @@ unsigned MimeHeaders::allocSlot(void) void MimeHeaders::addString(const char* name, const char* szValue, unsigned flags) { + if (szValue == NULL) return; + MimeHeader& H = mVals[allocSlot()]; H.name = name; H.value = szValue; diff --git a/protocols/MSN/msn_misc.cpp b/protocols/MSN/msn_misc.cpp index 0780361b2c..80d9fd46ec 100644 --- a/protocols/MSN/msn_misc.cpp +++ b/protocols/MSN/msn_misc.cpp @@ -125,7 +125,7 @@ void CMsnProto::MSN_AddAuthRequest(const char *email, const char *nick, const c //blob is: UIN=0(DWORD), hContact(DWORD), nick(ASCIIZ), ""(ASCIIZ), ""(ASCIIZ), email(ASCIIZ), ""(ASCIIZ) HANDLE hContact = MSN_HContactFromEmail(email, nick, true, true); - + int emaillen = (int)strlen(email); if (nick == NULL) nick = ""; @@ -294,7 +294,7 @@ void CMsnProto::MSN_GetAvatarFileName(HANDLE hContact, TCHAR* pszDest, size_t c } while(_tfindnext(hFile, &c_file) == 0); _findclose( hFile ); } - + if (!found) pszDest[0] = 0; } else @@ -334,17 +334,17 @@ int MSN_GetImageFormat(void* buf, const TCHAR** ext) int MSN_GetImageFormat(const TCHAR* file) { - const TCHAR *ext = _tcsrchr(file, '.'); - if (ext == NULL) - return PA_FORMAT_UNKNOWN; - if (_tcsicmp(ext, _T(".gif")) == 0) - return PA_FORMAT_GIF; - else if (_tcsicmp(ext, _T(".bmp")) == 0) - return PA_FORMAT_BMP; - else if (_tcsicmp(ext, _T(".png")) == 0) - return PA_FORMAT_PNG; - else - return PA_FORMAT_JPEG; + const TCHAR *ext = _tcsrchr(file, '.'); + if (ext == NULL) + return PA_FORMAT_UNKNOWN; + if (_tcsicmp(ext, _T(".gif")) == 0) + return PA_FORMAT_GIF; + else if (_tcsicmp(ext, _T(".bmp")) == 0) + return PA_FORMAT_BMP; + else if (_tcsicmp(ext, _T(".png")) == 0) + return PA_FORMAT_PNG; + else + return PA_FORMAT_JPEG; } int CMsnProto::MSN_SetMyAvatar(const TCHAR* sztFname, void* pData, size_t cbLen) @@ -363,10 +363,10 @@ int CMsnProto::MSN_SetMyAvatar(const TCHAR* sztFname, void* pData, size_t cbLen NETLIBBASE64 nlb = { szSha1d, sizeof(szSha1d), (PBYTE)sha1d, sizeof(sha1d) }; MSN_CallService(MS_NETLIB_BASE64ENCODE, 0, LPARAM(&nlb)); } - + mir_sha1_init(&sha1ctx); ezxml_t xmlp = ezxml_new("msnobj"); - + mir_sha1_append(&sha1ctx, (PBYTE)"Creator", 7); mir_sha1_append(&sha1ctx, (PBYTE)MyOptions.szEmail, (int)strlen(MyOptions.szEmail)); ezxml_set_attr(xmlp, "Creator", MyOptions.szEmail); @@ -392,15 +392,15 @@ int CMsnProto::MSN_SetMyAvatar(const TCHAR* sztFname, void* pData, size_t cbLen mir_sha1_append(&sha1ctx, (PBYTE)"SHA1D", 5); mir_sha1_append(&sha1ctx, (PBYTE)szSha1d, (int)strlen(szSha1d)); ezxml_set_attr(xmlp, "SHA1D", szSha1d); - + mir_sha1_finish(&sha1ctx, sha1c); { NETLIBBASE64 nlb = { szSha1c, sizeof(szSha1c), (PBYTE)sha1c, sizeof(sha1c) }; MSN_CallService(MS_NETLIB_BASE64ENCODE, 0, LPARAM(&nlb)); } - -// ezxml_set_attr(xmlp, "SHA1C", szSha1c); + + // ezxml_set_attr(xmlp, "SHA1C", szSha1c); char* szBuffer = ezxml_toxml(xmlp, false); ezxml_free(xmlp); @@ -475,7 +475,7 @@ void CMsnProto::MSN_GetCustomSmileyFileName(HANDLE hContact, TCHAR* pszDest, si dbv.ptszVal = (TCHAR*)mir_alloc(11); _ui64tot((UINT_PTR)hContact, dbv.ptszVal, 10); } - + tPathLen += mir_sntprintf(pszDest + tPathLen, cbLen - tPathLen, _T("\\%s"), dbv.ptszVal); DBFreeVariant(&dbv); } @@ -485,9 +485,9 @@ void CMsnProto::MSN_GetCustomSmileyFileName(HANDLE hContact, TCHAR* pszDest, si tPathLen += mir_sntprintf(pszDest + tPathLen, cbLen - tPathLen, _T("\\%s"), tszModuleName); mir_free(tszModuleName); } - + bool exist = _taccess(pszDest, 0) == 0; - + if (type == 0) { if (!exist) pszDest[0] = 0; @@ -607,10 +607,10 @@ int ThreadData::sendMessage(int msgType, const char* email, int netId, const cha int seq; if (netId == NETID_YAHOO || netId == NETID_MOB || (parFlags & MSG_OFFLINE)) seq = sendPacket("UUM", "%s %d %c %d\r\n%s%s", email, netId, msgType, - strlen(parMsg)+off, buf, parMsg); + strlen(parMsg)+off, buf, parMsg); else seq = sendPacket("MSG", "%c %d\r\n%s%s", msgType, - strlen(parMsg)+off, buf, parMsg); + strlen(parMsg)+off, buf, parMsg); return seq; } @@ -699,8 +699,8 @@ void CMsnProto::MSN_StartStopTyping(ThreadData* info, bool start) MSN_SendTyping(info, NULL, 1); } else if (!start && info->mTimerId != 0) { - KillTimer(NULL, info->mTimerId); - info->mTimerId = 0; + KillTimer(NULL, info->mTimerId); + info->mTimerId = 0; } } @@ -770,10 +770,10 @@ void CMsnProto::MSN_SendStatusMessage(const char* msg) sz = mir_snprintf(szMsg, sizeof szMsg, "" - "%s" - "%s\\0%s\\01\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0\\0" - "%s" - "" + "%s" + "%s\\0%s\\01\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0%s\\0\\0" + "%s" + "" "", msgEnc, szPlayer, szType, szFormatEnc, szTitle, szArtist, szAlbum, szTrack, szYear, szGenre, szLength, szPlayer, szType, MyOptions.szMachineGuid); @@ -856,7 +856,7 @@ void CMsnProto::MSN_SetServerStatus(int newStatus) { DBVARIANT msnObject = {0}; if (ServiceExists(MS_AV_SETMYAVATAR)) - getString("PictObject", &msnObject); + getString("PictObject", &msnObject); // Capabilties: WLM 2009, Chunking, UUN Bootstrap myFlags = 0xA0000000 | cap_SupportsChunking | cap_SupportsP2PBootstrap | cap_SupportsSipInvite; @@ -898,10 +898,10 @@ void CMsnProto::MSN_SetServerStatus(int newStatus) int sz = mir_snprintf(szMsg, sizeof(szMsg), "" - "%s" - "%s" - "1" - "%s" + "%s" + "%s" + "1" + "%s" "", szPlace, newStatus == ID_STATUS_IDLE ? "true" : "false", szStatusName); msnNsThread->sendPacket("UUX", "%d\r\n%s", sz, szMsg); @@ -932,7 +932,7 @@ void CMsnProto::MsnInvokeMyURL(bool ismail, const char* url) static const char postdataM[] = "ct=%u&bver=7&wa=wsignin1.0&ru=%s&pl=MBI"; static const char postdataS[] = "ct=%u&bver=7&id=73625&ru=%s&js=yes&pl=%%3Fid%%3D73625"; const char *postdata = ismail ? postdataM : postdataS; - + char passport[256]; if (getStaticString(NULL, "MsnPassportHost", passport, 256)) strcpy(passport, "https://login.live.com/"); @@ -943,7 +943,7 @@ void CMsnProto::MsnInvokeMyURL(bool ismail, const char* url) char ruenc[256]; UrlEncode(url, ruenc, sizeof(ruenc)); - + const size_t fnpstlen = strlen(postdata) + strlen(ruenc) + 30; char* fnpst = (char*)alloca(fnpstlen); @@ -1121,7 +1121,7 @@ void CALLBACK sttMainThreadCallback(PVOID dwParam) ppd.ptszText = pud->text; ppd.PluginData = pud; ppd.pszClassName = name; - + if (pud->flags & MSN_SHOW_ERROR) mir_snprintf(name, SIZEOF(name), "%s_%s", pud->proto->m_szModuleName, "Error"); else if (pud->flags & (MSN_HOTMAIL_POPUP | MSN_ALERT_POPUP)) @@ -1228,8 +1228,8 @@ int filetransfer::create(void) if (fileId == -1) proto->MSN_ShowError("Cannot create file '%s' during a file transfer", std.tszCurrentFile); -// else if (std.currentFileSize != 0) -// _chsize(fileId, std.currentFileSize); + // else if (std.currentFileSize != 0) + // _chsize(fileId, std.currentFileSize); return fileId; } @@ -1261,7 +1261,7 @@ int filetransfer::openNext(void) { std.currentFileSize = _filelengthi64(fileId); std.currentFileProgress = 0; - + p2p_sendmsgid = 0; p2p_byemsgid = 0; tType = SERVER_NOTIFICATION; @@ -1343,8 +1343,7 @@ void directconnection::xNonceToBin(UUID* nonce) ///////////////////////////////////////////////////////////////////////////////////////// // TWinErrorCode class -TWinErrorCode::TWinErrorCode() : - mErrorText(NULL) +TWinErrorCode::TWinErrorCode() : mErrorText(NULL) { mErrorCode = ::GetLastError(); } @@ -1363,8 +1362,8 @@ char* TWinErrorCode::getText() if (tBytes == 0) tBytes = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM, NULL, - mErrorCode, LANG_NEUTRAL, mErrorText, 256, NULL); + FORMAT_MESSAGE_FROM_SYSTEM, NULL, + mErrorCode, LANG_NEUTRAL, mErrorText, 256, NULL); if (tBytes == 0) { @@ -1424,14 +1423,14 @@ bool CMsnProto::MSN_IsMeByContact(HANDLE hContact, char* szEmail) *emailPtr = 0; if (getStaticString(hContact, "e-mail", emailPtr, sizeof(tEmail))) return false; - + return _stricmp(emailPtr, MyOptions.szEmail) == 0; } bool MSN_MsgWndExist(HANDLE hContact) { MessageWindowInputData msgWinInData = - { sizeof(MessageWindowInputData), hContact, MSG_WINDOW_UFLAG_MSG_BOTH }; + { sizeof(MessageWindowInputData), hContact, MSG_WINDOW_UFLAG_MSG_BOTH }; MessageWindowData msgWinData = {0}; msgWinData.cbSize = sizeof(MessageWindowData); @@ -1471,7 +1470,8 @@ void MSN_MakeDigest(const char* chl, char* dgst) LONGLONG high=0, low=0; int* chlStringArray = (int*)chlString; - for (i=0; i < strlen(chlString)/4; i += 2) { + for (i=0; i < strlen(chlString) / 4; i += 2) + { LONGLONG temp = chlStringArray[i]; temp = (0x0E79A9C1 * temp) % 0x7FFFFFFF; @@ -1498,3 +1498,15 @@ void MSN_MakeDigest(const char* chl, char* dgst) strcpy(dgst, str); mir_free(str); } + +char* GetGlobalIp(void) +{ + NETLIBIPLIST* ihaddr = (NETLIBIPLIST*)CallService(MS_NETLIB_GETMYIP, 1, 0); + for (unsigned i = 0; i < ihaddr->cbNum; ++i) + { + if (strchr(ihaddr->szIp[i], ':')) + return mir_strdup(ihaddr->szIp[i]); + } + mir_free(ihaddr); + return NULL; +} diff --git a/protocols/MSN/msn_p2p.cpp b/protocols/MSN/msn_p2p.cpp index 1e3215b2e5..9c805eb530 100644 --- a/protocols/MSN/msn_p2p.cpp +++ b/protocols/MSN/msn_p2p.cpp @@ -81,7 +81,7 @@ void P2PV2_Header::logHeader(CMsnProto *ppro) bool CMsnProto::p2p_createListener(filetransfer* ft, directconnection *dc, MimeHeaders& chdrs) { if (MyConnection.extIP == 0) return false; - + NETLIBBIND nlb = {0}; nlb.cbSize = sizeof(nlb); nlb.pfnNewConnectionV2 = MSN_ConnectionProc; @@ -103,22 +103,29 @@ bool CMsnProto::p2p_createListener(filetransfer* ft, directconnection *dc, MimeH newThread->startThread(&CMsnProto::p2p_filePassiveThread, this); - char hostname[256] = ""; - - gethostname(hostname, sizeof(hostname)); - PHOSTENT he = gethostbyname(hostname); + char szIpv4[256] = ""; + char szIpv6[256] = ""; + const char *szExtIp = MyConnection.GetMyExtIPStr(); - hostname[0] = 0; bool ipInt = false; - for (unsigned i = 0; i < sizeof(hostname) / 16; ++i) - { - const PIN_ADDR addr = (PIN_ADDR)he->h_addr_list[i]; + int i4 = 0, i6 = 0; - if (addr == NULL) break; - if (i != 0) strcat(hostname, " "); - ipInt |= (addr->S_un.S_addr == MyConnection.extIP); - strcat(hostname, inet_ntoa(*addr)); + NETLIBIPLIST* ihaddr = (NETLIBIPLIST*)CallService(MS_NETLIB_GETMYIP, 1, 0); + for (unsigned i = 0; i < ihaddr->cbNum; ++i) + { + if (strchr(ihaddr->szIp[i], ':')) + { + if (i6++ != 0) strcat(szIpv6, " "); + strcat(szIpv6, ihaddr->szIp[i]); + } + else + { + if (i4++ != 0) strcat(szIpv4, " "); + ipInt |= (strcmp(ihaddr->szIp[i], szExtIp) == 0); + strcat(szIpv4, ihaddr->szIp[i]); + } } + mir_free(ihaddr); chdrs.addString("Bridge", "TCPv1"); chdrs.addBool("Listening", true); @@ -135,8 +142,13 @@ bool CMsnProto::p2p_createListener(filetransfer* ft, directconnection *dc, MimeH chdrs.addString("IPv4External-Addrs", mir_strdup(MyConnection.GetMyExtIPStr()), bUbnCall ? 6 : 2); chdrs.addLong("IPv4External-Port", nlb.wExPort, bUbnCall ? 4 : 0); } - chdrs.addString("IPv4Internal-Addrs", mir_strdup(hostname), bUbnCall ? 6 : 2); + chdrs.addString("IPv4Internal-Addrs", mir_strdup(szIpv4), bUbnCall ? 6 : 2); chdrs.addLong("IPv4Internal-Port", nlb.wPort, bUbnCall ? 4 : 0); + if (szIpv6[0]) + { + chdrs.addString("IPv6-Addrs", mir_strdup(szIpv6), 2); + chdrs.addLong("IPv6-Port", nlb.wPort); + } chdrs.addULong("SessionID", ft->p2p_sessionid); chdrs.addString("SChannelState", "0"); chdrs.addString("Capabilities-Flags", "1"); @@ -382,19 +394,19 @@ void CMsnProto::p2p_sendMsg(ThreadData* info, const char *wlid, unsigned appId, char* szEmail; switch (msgType) { - case 0: - parseWLID(NEWSTR_ALLOCA(wlid), NULL, &szEmail, NULL); - MsgQueue_Add(szEmail, 'D', buf, p - buf); - break; + case 0: + parseWLID(NEWSTR_ALLOCA(wlid), NULL, &szEmail, NULL); + MsgQueue_Add(szEmail, 'D', buf, p - buf); + break; - case 1: - *(unsigned*)buf = (unsigned)(p - buf - sizeof(unsigned)); - info->send(buf, p - buf); - break; + case 1: + *(unsigned*)buf = (unsigned)(p - buf - sizeof(unsigned)); + info->send(buf, p - buf); + break; - case 2: - info->sendRawMessage('D', buf, p - buf); - break; + case 2: + info->sendRawMessage('D', buf, p - buf); + break; } offset += portion; } @@ -522,7 +534,7 @@ void CMsnProto::p2p_sendSlp(int iKind, filetransfer *ft, MimeHeaders &pHeaders, case 1603: p += sprintf(p, "MSNSLP/1.0 603 Decline"); break; default: return; } - + if (iKind < 0) { mir_free(ft->p2p_branch); @@ -565,9 +577,9 @@ void CMsnProto::p2p_sendSlp(int iKind, filetransfer *ft, MimeHeaders &pHeaders, switch (iKind) { - case -1: case 500: case 603: - ft->p2p_byemsgid = tHdr.mID; - break; + case -1: case 500: case 603: + ft->p2p_byemsgid = tHdr.mID; + break; } } @@ -622,7 +634,7 @@ void CMsnProto::p2p_sendNoCall(filetransfer* ft) MSN_DebugLog(sttVoidSession); return; } - + MimeHeaders tHeaders(8); tHeaders.addString("CSeq", "0 "); tHeaders.addString("Call-ID", ft->p2p_callID); @@ -882,7 +894,7 @@ LONG CMsnProto::p2p_sendPortion(filetransfer* ft, ThreadData* T, bool isV2) // Compute the amount of data to send unsigned fportion = T->mType == SERVER_P2P_DIRECT ? 1352 : 1202; if (isV2) fportion += 4; - + const unsigned __int64 dt = ft->std.currentFileSize - ft->std.currentFileProgress; const unsigned portion = dt > fportion ? fportion : dt; @@ -975,9 +987,9 @@ void __cdecl CMsnProto::p2p_sendFeedThread(void* arg) switch(WaitForSingleObject(info->hWaitEvent, 6000)) { - case WAIT_FAILED: - MSN_DebugLog("File send wait failed"); - return; + case WAIT_FAILED: + MSN_DebugLog("File send wait failed"); + return; } HANDLE hLockHandle = NULL; @@ -1036,7 +1048,7 @@ void __cdecl CMsnProto::p2p_sendFeedThread(void* arg) WaitForSingleObject(T->hWaitEvent, 5000); } ReleaseMutex(hLockHandle); - + if (ft->p2p_appID == MSN_APPID_FILE) SendBroadcast(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_DATA, ft, (LPARAM)&ft->std); @@ -1213,7 +1225,7 @@ void CMsnProto::p2p_InitFileTransfer( replaceStr(ft->p2p_branch, szBranch); ft->p2p_dest = mir_strdup(wlid); ft->p2p_isV2 = strchr(wlid, ';') != NULL; - ft->std.hContact = MSN_HContactFromEmail(wlid); + ft->std.hContact = MSN_HContactFromEmail(wlid); p2p_registerSession(ft); @@ -1292,15 +1304,14 @@ void CMsnProto::p2p_InitFileTransfer( if (!_stricmp(szEufGuid, "{5D3E02AB-6190-11D3-BBBB-00C04F795683}")) { wchar_t* wszFileName = ((HFileContext*)szContext)->wszFileName; - { for (wchar_t* p = wszFileName; *p != 0; p++) - { - switch(*p) - { - case ':': case '?': case '/': case '\\': case '*': - *p = '_'; - } + for (wchar_t* p = wszFileName; *p != 0; p++) + { + switch(*p) + { + case ':': case '?': case '/': case '\\': case '*': + *p = '_'; } - } + } mir_free(ft->std.tszCurrentFile); ft->std.tszCurrentFile = mir_u2t(wszFileName); @@ -1363,12 +1374,12 @@ void CMsnProto::p2p_InitFileTransfer( void CMsnProto::p2p_InitDirectTransfer(MimeHeaders& tFileInfo, MimeHeaders& tFileInfo2, const char* wlid) { - const char *szCallID = tFileInfo["Call-ID"], - *szBranch = tFileInfo["Via"], - *szConnType = tFileInfo2["Conn-Type"], - *szUPnPNat = tFileInfo2["UPnPNat"], - *szNetID = tFileInfo2["NetID"], - *szICF = tFileInfo2["ICF"], + const char *szCallID = tFileInfo["Call-ID"], + *szBranch = tFileInfo["Via"], + *szConnType = tFileInfo2["Conn-Type"], + *szUPnPNat = tFileInfo2["UPnPNat"], + *szNetID = tFileInfo2["NetID"], + *szICF = tFileInfo2["ICF"], *szHashedNonce = tFileInfo2["Hashed-Nonce"]; if (szBranch != NULL) @@ -1408,8 +1419,8 @@ void CMsnProto::p2p_InitDirectTransfer(MimeHeaders& tFileInfo, MimeHeaders& tFil /* if (p2p_isAvatarOnly(ft->std.hContact)) { - // p2p_sendStatus(ft, 1603); - // return; + p2p_sendStatus(ft, 1603); + return; } else SendBroadcast(ft->std.hContact, ACKTYPE_FILE, ACKRESULT_INITIALISING, ft, 0); @@ -1475,7 +1486,7 @@ void CMsnProto::p2p_InitDirectTransfer(MimeHeaders& tFileInfo, MimeHeaders& tFil } -void CMsnProto::p2p_startConnect(const char* wlid, const char* szCallID, const char* addr, const char* port) +void CMsnProto::p2p_startConnect(const char* wlid, const char* szCallID, const char* addr, const char* port, bool ipv6) { if (port == NULL) return; @@ -1489,7 +1500,8 @@ void CMsnProto::p2p_startConnect(const char* wlid, const char* szCallID, const c newThread->mType = SERVER_P2P_DIRECT; newThread->mInitialContactWLID = mir_strdup(wlid); mir_snprintf(newThread->mCookie, sizeof(newThread->mCookie), "%s", szCallID); - mir_snprintf(newThread->mServer, sizeof(newThread->mServer), "%s:%s", addr, port); + mir_snprintf(newThread->mServer, sizeof(newThread->mServer), + ipv6 ? "[%s]:%s" : "%s:%s", addr, port); newThread->startThread(&CMsnProto::p2p_fileActiveThread, this); @@ -1499,14 +1511,16 @@ void CMsnProto::p2p_startConnect(const char* wlid, const char* szCallID, const c void CMsnProto::p2p_InitDirectTransfer2(MimeHeaders& tFileInfo, MimeHeaders& tFileInfo2, const char* wlid) { - const char *szCallID = tFileInfo["Call-ID"], + const char *szCallID = tFileInfo["Call-ID"], *szInternalAddress = tFileInfo2["IPv4Internal-Addrs"], - *szInternalPort = tFileInfo2["IPv4Internal-Port"], + *szInternalPort = tFileInfo2["IPv4Internal-Port"], *szExternalAddress = tFileInfo2["IPv4External-Addrs"], - *szExternalPort = tFileInfo2["IPv4External-Port"], - *szNonce = tFileInfo2["Nonce"], - *szHashedNonce = tFileInfo2["Hashed-Nonce"], - *szListening = tFileInfo2["Listening"]; + *szExternalPort = tFileInfo2["IPv4External-Port"], + *szNonce = tFileInfo2["Nonce"], + *szHashedNonce = tFileInfo2["Hashed-Nonce"], + *szListening = tFileInfo2["Listening"], + *szV6Address = tFileInfo2["IPv6-Addrs"], + *szV6Port = tFileInfo2["IPv6-Port" ]; if ((szNonce == NULL && szHashedNonce == NULL) || szListening == NULL) { @@ -1526,8 +1540,9 @@ void CMsnProto::p2p_InitDirectTransfer2(MimeHeaders& tFileInfo, MimeHeaders& tFi if (!strcmp(szListening, "true") && strcmp(dc->xNonce, sttVoidUid)) { - p2p_startConnect(wlid, szCallID, szInternalAddress, szInternalPort); - p2p_startConnect(wlid, szCallID, szExternalAddress, szExternalPort); + p2p_startConnect(wlid, szCallID, szV6Address, szV6Port, true); + p2p_startConnect(wlid, szCallID, szInternalAddress, szInternalPort, false); + p2p_startConnect(wlid, szCallID, szExternalAddress, szExternalPort, false); } } @@ -1622,6 +1637,7 @@ LBL_Close: chdrs.addString("Conn-Type", MyConnection.GetMyUdpConStr()); chdrs.addBool("UPnPNat", MyConnection.upnpNAT); chdrs.addBool("ICF", MyConnection.icf); + chdrs.addString("IPv6-global", GetGlobalIp(), 2); chdrs.addString("Hashed-Nonce", dc->mNonceToHash(), 2); } else if (!strcmp(szOldContentType, "application/x-msnmsgr-transrespbody")) @@ -1632,7 +1648,10 @@ LBL_Close: *szExternalAddress = tFileInfo2["IPv4External-Addrs"], *szExternalPort = tFileInfo2["IPv4External-Port" ], *szInternalAddress = tFileInfo2["IPv4Internal-Addrs"], - *szInternalPort = tFileInfo2["IPv4Internal-Port" ]; + *szInternalPort = tFileInfo2["IPv4Internal-Port" ], + *szV6Address = tFileInfo2["IPv6-Addrs"], + *szV6Port = tFileInfo2["IPv6-Port" ]; + if ((szNonce == NULL && szHashedNonce == NULL) || szListening == NULL) { MSN_DebugLog("Invalid data packet, exiting..."); @@ -1653,8 +1672,9 @@ LBL_Close: // another side reported that it will be a server. if (!strcmp(szListening, "true") && (szNonce == NULL || strcmp(szNonce, sttVoidUid))) { - p2p_startConnect(ft->p2p_dest, szCallID, szInternalAddress, szInternalPort); - p2p_startConnect(ft->p2p_dest, szCallID, szExternalAddress, szExternalPort); + p2p_startConnect(ft->p2p_dest, szCallID, szV6Address, szV6Port, true); + p2p_startConnect(ft->p2p_dest, szCallID, szInternalAddress, szInternalPort, false); + p2p_startConnect(ft->p2p_dest, szCallID, szExternalAddress, szExternalPort, false); return; } @@ -1788,8 +1808,8 @@ void CMsnProto::p2p_processSIP(ThreadData* info, char* msgbody, P2PB_Header* hdr const char* callID = tFileInfo["Call-ID"]; // application/x-msnmsgr-session-failure-respbody - - directconnection *dc = p2p_getDCByCallID(callID, wlid); + + directconnection *dc = p2p_getDCByCallID(callID, wlid); if (dc != NULL) { p2p_unregisterDC(dc); @@ -1830,7 +1850,7 @@ void CMsnProto::p2p_processSIP(ThreadData* info, char* msgbody, P2PB_Header* hdr void CMsnProto::p2p_processMsgV2(ThreadData* info, char* msgbody, const char* wlid) { P2PV2_Header hdrdata; - + char *msg = hdrdata.parseMsg(msgbody); hdrdata.logHeader(this); @@ -1864,7 +1884,7 @@ void CMsnProto::p2p_processMsgV2(ThreadData* info, char* msgbody, const char* if (hdrdata.mRemSize == 0) { - size_t newsize; + size_t newsize; if (getCachedMsg(idx, msgbody, newsize)) { unsigned id = hdrdata.mID; @@ -1942,9 +1962,9 @@ void CMsnProto::p2p_processMsg(ThreadData* info, char* msgbody, const char* wl //---- if we got a message if (LOWORD(hdrdata.mFlags) == 0 && hdrdata.mSessionID == 0) { -// MsnContact *cont = Lists_Get(wlid); -// if (cont && cont->places.getCount()) -// return; + // MsnContact *cont = Lists_Get(wlid); + // if (cont && cont->places.getCount()) + // return; if (hdrdata.mPacketLen < hdrdata.mTotalSize) { @@ -2039,7 +2059,7 @@ void CMsnProto::p2p_processMsg(ThreadData* info, char* msgbody, const char* wl if (LOWORD(hdrdata.mFlags) == 0) { //---- accept the data preparation message ------ -// const unsigned* pLongs = (unsigned*)msgbody; + // const unsigned* pLongs = (unsigned*)msgbody; if (hdrdata.mPacketLen == 4 && hdrdata.mTotalSize == 4) { p2p_sendAck(ft->p2p_dest, &hdrdata); @@ -2151,84 +2171,84 @@ void CMsnProto::p2p_invite(unsigned iAppID, filetransfer* ft, const char *wlid) switch (iAppID) { - case MSN_APPID_FILE: + case MSN_APPID_FILE: + { + cbContext = sizeof(HFileContext); + pContext = (char*)malloc(cbContext); + HFileContext* ctx = (HFileContext*)pContext; + memset(pContext, 0, cbContext); + if (ft->p2p_isV2) { - cbContext = sizeof(HFileContext); - pContext = (char*)malloc(cbContext); - HFileContext* ctx = (HFileContext*)pContext; - memset(pContext, 0, cbContext); - if (ft->p2p_isV2) - { - cbContext -= 64; - ctx->ver = 2; - } - else - { - ctx->ver = 3; - ctx->id = 0xffffffff; - } - ctx->len = (unsigned)cbContext; - ctx->type = MSN_TYPEID_FTNOPREVIEW; - ctx->dwSize = ft->std.currentFileSize; + cbContext -= 64; + ctx->ver = 2; + } + else + { + ctx->ver = 3; + ctx->id = 0xffffffff; + } + ctx->len = (unsigned)cbContext; + ctx->type = MSN_TYPEID_FTNOPREVIEW; + ctx->dwSize = ft->std.currentFileSize; - TCHAR* pszFiles = _tcsrchr(ft->std.tszCurrentFile, '\\'); - if (pszFiles) - pszFiles++; - else - pszFiles = ft->std.tszCurrentFile; + TCHAR* pszFiles = _tcsrchr(ft->std.tszCurrentFile, '\\'); + if (pszFiles) + pszFiles++; + else + pszFiles = ft->std.tszCurrentFile; - wchar_t *fname = mir_t2u(pszFiles); - wcsncpy(ctx->wszFileName, fname, MAX_PATH); - mir_free(fname); + wchar_t *fname = mir_t2u(pszFiles); + wcsncpy(ctx->wszFileName, fname, MAX_PATH); + mir_free(fname); - ft->p2p_appID = MSN_APPID_FILE; - } - break; + ft->p2p_appID = MSN_APPID_FILE; + } + break; - default: - ft->p2p_appID = MSN_APPID_AVATAR2; + default: + ft->p2p_appID = MSN_APPID_AVATAR2; - if (ft->p2p_object == NULL) - { - delete ft; - return; - } + if (ft->p2p_object == NULL) + { + delete ft; + return; + } - ezxml_t xmlo = ezxml_parse_str(NEWSTR_ALLOCA(ft->p2p_object), strlen(ft->p2p_object)); - ezxml_t xmlr = ezxml_new("msnobj"); - - const char* p; - p = ezxml_attr(xmlo, "Creator"); - if (p != NULL) - ezxml_set_attr(xmlr, "Creator", p); - p = ezxml_attr(xmlo, "Size"); - if (p != NULL) { - ezxml_set_attr(xmlr, "Size", p); - ft->std.totalBytes = ft->std.currentFileSize = _atoi64(p); - } - p = ezxml_attr(xmlo, "Type"); - if (p != NULL) - ezxml_set_attr(xmlr, "Type", p); - p = ezxml_attr(xmlo, "Location"); - if (p != NULL) - ezxml_set_attr(xmlr, "Location", p); - p = ezxml_attr(xmlo, "Friendly"); - if (p != NULL) - ezxml_set_attr(xmlr, "Friendly", p); - p = ezxml_attr(xmlo, "SHA1D"); - if (p != NULL) - ezxml_set_attr(xmlr, "SHA1D", p); - p = ezxml_attr(xmlo, "SHA1C"); - if (p != NULL) - ezxml_set_attr(xmlr, "SHA1C", p); - - pContext = ezxml_toxml(xmlr, false); - cbContext = strlen(pContext)+1; - - ezxml_free(xmlr); - ezxml_free(xmlo); + ezxml_t xmlo = ezxml_parse_str(NEWSTR_ALLOCA(ft->p2p_object), strlen(ft->p2p_object)); + ezxml_t xmlr = ezxml_new("msnobj"); + + const char* p; + p = ezxml_attr(xmlo, "Creator"); + if (p != NULL) + ezxml_set_attr(xmlr, "Creator", p); + p = ezxml_attr(xmlo, "Size"); + if (p != NULL) { + ezxml_set_attr(xmlr, "Size", p); + ft->std.totalBytes = ft->std.currentFileSize = _atoi64(p); + } + p = ezxml_attr(xmlo, "Type"); + if (p != NULL) + ezxml_set_attr(xmlr, "Type", p); + p = ezxml_attr(xmlo, "Location"); + if (p != NULL) + ezxml_set_attr(xmlr, "Location", p); + p = ezxml_attr(xmlo, "Friendly"); + if (p != NULL) + ezxml_set_attr(xmlr, "Friendly", p); + p = ezxml_attr(xmlo, "SHA1D"); + if (p != NULL) + ezxml_set_attr(xmlr, "SHA1D", p); + p = ezxml_attr(xmlo, "SHA1C"); + if (p != NULL) + ezxml_set_attr(xmlr, "SHA1C", p); + + pContext = ezxml_toxml(xmlr, false); + cbContext = strlen(pContext)+1; + + ezxml_free(xmlr); + ezxml_free(xmlo); - break; + break; } bool sessionExist = p2p_sessionRegistered(ft); @@ -2335,6 +2355,7 @@ void CMsnProto::p2p_inviteDc(filetransfer* ft, const char *wlid) chdrs.addString("Conn-Type", MyConnection.GetMyUdpConStr()); chdrs.addBool("UPnPNat", MyConnection.upnpNAT); chdrs.addBool("ICF", MyConnection.icf); + chdrs.addString("IPv6-global", GetGlobalIp(), 2); chdrs.addString("Hashed-Nonce", dc->mNonceToHash(), 2); chdrs.addString("SessionID", "0"); chdrs.addString("SChannelState", "0"); @@ -2452,7 +2473,7 @@ char* P2PV2_Header::createMsg(char *buf, const char* wlid, CMsnProto *ppro) *(unsigned*)(buf + 4) = _htonl(mID); char *buf1 = buf + 8; - + if (mAckUniqueID) { *(unsigned char*)buf1 = 2; @@ -2475,7 +2496,7 @@ char* P2PV2_Header::createMsg(char *buf, const char* wlid, CMsnProto *ppro) *(unsigned char*)(buf1 + 1) = mTFCode; *(unsigned short*)(buf1 + 2) = _htons(mPacketNum); *(unsigned*)(buf1 + 4) = _htonl(mSessionID); - + if (mRemSize) { *(unsigned char*)(buf1 + 8) = 1; diff --git a/protocols/MSN/msn_proto.h b/protocols/MSN/msn_proto.h index f09ec82ef7..8f6ddfbfd4 100644 --- a/protocols/MSN/msn_proto.h +++ b/protocols/MSN/msn_proto.h @@ -369,7 +369,7 @@ struct CMsnProto : public PROTO_INTERFACE void p2p_savePicture2disk(filetransfer* ft); bool p2p_createListener(filetransfer* ft, directconnection *dc, MimeHeaders& chdrs); - void p2p_startConnect(const char* wlid, const char* szCallID, const char* addr, const char* port); + void p2p_startConnect(const char* wlid, const char* szCallID, const char* addr, const char* port, bool ipv6); void p2p_sendAbortSession(filetransfer* ft); void p2p_sendAck(const char *wlid, P2PB_Header* hdrdata); diff --git a/src/core/commonheaders.h b/src/core/commonheaders.h index b70c0bab04..8603a42ffd 100644 --- a/src/core/commonheaders.h +++ b/src/core/commonheaders.h @@ -31,6 +31,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define _WIN32_WINNT 0x0700 #define _WIN32_IE 0x0601 +#define INCL_WINSOCK_API_TYPEDEFS 1 + #include "m_stdhdr.h" #include diff --git a/src/core/miranda.cpp b/src/core/miranda.cpp index fe38d096e1..8ce9c0b0be 100644 --- a/src/core/miranda.cpp +++ b/src/core/miranda.cpp @@ -77,8 +77,10 @@ pfnGetBufferedPaintBits getBufferedPaintBits; pfnDwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea; pfnDwmIsCompositionEnabled dwmIsCompositionEnabled; -pfnGetaddrinfo MyGetaddrinfo; -pfnFreeaddrinfo MyFreeaddrinfo; +LPFN_GETADDRINFO MyGetaddrinfo; +LPFN_FREEADDRINFO MyFreeaddrinfo; +LPFN_WSASTRINGTOADDRESSA MyWSAStringToAddress; +LPFN_WSAADDRESSTOSTRINGA MyWSAAddressToString; ITaskbarList3 * pTaskbarInterface; @@ -630,8 +632,10 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int ) } HMODULE hWinSock = GetModuleHandleA("ws2_32"); - MyGetaddrinfo = (pfnGetaddrinfo)GetProcAddress(hWinSock, "getaddrinfo"); - MyFreeaddrinfo = (pfnFreeaddrinfo)GetProcAddress(hWinSock, "freeaddrinfo"); + MyGetaddrinfo = (LPFN_GETADDRINFO)GetProcAddress(hWinSock, "getaddrinfo"); + MyFreeaddrinfo = (LPFN_FREEADDRINFO)GetProcAddress(hWinSock, "freeaddrinfo"); + MyWSAStringToAddress = (LPFN_WSASTRINGTOADDRESSA)GetProcAddress(hWinSock, "WSAStringToAddressA"); + MyWSAAddressToString = (LPFN_WSAADDRESSTOSTRINGA)GetProcAddress(hWinSock, "WSAAddressToStringA"); if (bufferedPaintInit) bufferedPaintInit(); diff --git a/src/core/miranda.h b/src/core/miranda.h index 850e2a78c8..81c7c6d41f 100644 --- a/src/core/miranda.h +++ b/src/core/miranda.h @@ -108,11 +108,10 @@ typedef HRESULT ( STDAPICALLTYPE *pfnDwmIsCompositionEnabled )( BOOL * ); extern pfnDwmExtendFrameIntoClientArea dwmExtendFrameIntoClientArea; extern pfnDwmIsCompositionEnabled dwmIsCompositionEnabled; -typedef INT (STDAPICALLTYPE *pfnGetaddrinfo)(PCSTR pNodeName, PCSTR pServiceName, const ADDRINFOA * pHints, PADDRINFOA * ppResult); -typedef INT (STDAPICALLTYPE *pfnFreeaddrinfo)(PADDRINFOA pAddrInfo); - -extern pfnGetaddrinfo MyGetaddrinfo; -extern pfnFreeaddrinfo MyFreeaddrinfo; +extern LPFN_GETADDRINFO MyGetaddrinfo; +extern LPFN_FREEADDRINFO MyFreeaddrinfo; +extern LPFN_WSASTRINGTOADDRESSA MyWSAStringToAddress; +extern LPFN_WSAADDRESSTOSTRINGA MyWSAAddressToString; /**** file.c ***************************************************************************/ diff --git a/src/modules/netlib/netlib.cpp b/src/modules/netlib/netlib.cpp index 000639474f..7cd39b1d7a 100644 --- a/src/modules/netlib/netlib.cpp +++ b/src/modules/netlib/netlib.cpp @@ -242,9 +242,11 @@ void NetlibDoClose(NetlibConnection *nlc, bool noShutdown) INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) { - switch(GetNetlibHandleType(wParam)) { + switch(GetNetlibHandleType(wParam)) + { case NLH_USER: - { struct NetlibUser *nlu=(struct NetlibUser*)wParam; + { + struct NetlibUser *nlu=(struct NetlibUser*)wParam; int i; EnterCriticalSection(&csNetlibUser); @@ -323,21 +325,24 @@ INT_PTR NetlibCloseHandle(WPARAM wParam, LPARAM) static INT_PTR NetlibGetSocket(WPARAM wParam, LPARAM) { SOCKET s; - if(wParam==0) { - s=INVALID_SOCKET; + if (wParam == 0) + { + s = INVALID_SOCKET; SetLastError(ERROR_INVALID_PARAMETER); } - else { + else + { WaitForSingleObject(hConnectionHeaderMutex,INFINITE); - switch(GetNetlibHandleType(wParam)) { + switch (GetNetlibHandleType(wParam)) + { case NLH_CONNECTION: - s=((struct NetlibConnection*)wParam)->s; + s = ((struct NetlibConnection*)wParam)->s; break; case NLH_BOUNDPORT: - s=((struct NetlibBoundPort*)wParam)->s; + s = ((struct NetlibBoundPort*)wParam)->s; break; default: - s=INVALID_SOCKET; + s = INVALID_SOCKET; SetLastError(ERROR_INVALID_PARAMETER); break; } @@ -346,6 +351,35 @@ static INT_PTR NetlibGetSocket(WPARAM wParam, LPARAM) return s; } +INT_PTR NetlibStringToAddressSrv(WPARAM wParam, LPARAM lParam) +{ + return (INT_PTR)!NetlibStringToAddress((char*)wParam, (SOCKADDR_INET_M*)lParam); +} + +INT_PTR NetlibAddressToStringSrv(WPARAM wParam, LPARAM lParam) +{ + if (wParam) + { + SOCKADDR_INET_M iaddr = {0}; + iaddr.Ipv4.sin_family = AF_INET; + iaddr.Ipv4.sin_addr.s_addr = htonl((unsigned)lParam); + return (INT_PTR)NetlibAddressToString(&iaddr); + } + else + return (INT_PTR)NetlibAddressToString((SOCKADDR_INET_M*)lParam); +} + +INT_PTR NetlibGetConnectionInfoSrv(WPARAM wParam, LPARAM lParam) +{ + NetlibGetConnectionInfo((NetlibConnection*)wParam, (NETLIBCONNINFO*)lParam); + return 0; +} + +INT_PTR NetlibGetMyIp(WPARAM wParam, LPARAM) +{ + return (INT_PTR)GetMyIp((unsigned)wParam); +} + INT_PTR NetlibShutdown(WPARAM wParam, LPARAM) { if (wParam) @@ -623,6 +657,10 @@ int LoadNetlibModule(void) CreateServiceFunction(MS_NETLIB_GETMOREPACKETS,NetlibPacketRecverGetMore); CreateServiceFunction(MS_NETLIB_SETPOLLINGTIMEOUT,NetlibHttpSetPollingTimeout); CreateServiceFunction(MS_NETLIB_STARTSSL,NetlibStartSsl); + CreateServiceFunction(MS_NETLIB_STARINGTOADDRESS,NetlibStringToAddressSrv); + CreateServiceFunction(MS_NETLIB_ADDRESSTOSTRING,NetlibAddressToStringSrv); + CreateServiceFunction(MS_NETLIB_GETCONNECTIONINFO,NetlibGetConnectionInfoSrv); + CreateServiceFunction(MS_NETLIB_GETMYIP,NetlibGetMyIp); hRecvEvent = CreateHookableEvent(ME_NETLIB_FASTRECV); hSendEvent = CreateHookableEvent(ME_NETLIB_FASTSEND); diff --git a/src/modules/netlib/netlib.h b/src/modules/netlib/netlib.h index 575e77f18c..8939e7fafc 100644 --- a/src/modules/netlib/netlib.h +++ b/src/modules/netlib/netlib.h @@ -52,6 +52,12 @@ struct NetlibHTTPProxyPacketQueue int dataBufferLen; }; +typedef union _SOCKADDR_INET_M { + SOCKADDR_IN Ipv4; + SOCKADDR_IN6 Ipv6; + USHORT si_family; +} SOCKADDR_INET_M, *PSOCKADDR_INET_M; + struct NetlibConnection { int handleType; @@ -83,6 +89,7 @@ struct NetlibConnection struct NetlibBoundPort { int handleType; SOCKET s; + SOCKET s6; WORD wPort; WORD wExPort; struct NetlibUser *nlu; @@ -123,7 +130,7 @@ bool NetlibGetIeProxyConn(NetlibConnection *nlc, bool forceHttps); //netlibbind.c int NetlibFreeBoundPort(struct NetlibBoundPort *nlbp); INT_PTR NetlibBindPort(WPARAM wParam,LPARAM lParam); -bool BindSocketToPort(const char *szPorts, SOCKET s, int* portn); +bool BindSocketToPort(const char *szPorts, SOCKET s, SOCKET s6, int* portn); //netlibhttp.c INT_PTR NetlibHttpSendRequest(WPARAM wParam,LPARAM lParam); @@ -179,6 +186,11 @@ INT_PTR NetlibSelect(WPARAM wParam,LPARAM lParam); INT_PTR NetlibSelectEx(WPARAM wParam,LPARAM lParam); INT_PTR NetlibShutdown(WPARAM wParam,LPARAM lParam); +bool NetlibStringToAddress(const char* str, SOCKADDR_INET_M* addr); +char* NetlibAddressToString(SOCKADDR_INET_M* addr); +void NetlibGetConnectionInfo(NetlibConnection* nlc, NETLIBCONNINFO *connInfo); +NETLIBIPLIST* GetMyIp(unsigned flags); + //netlibupnp.c bool NetlibUPnPAddPortMapping(WORD intport, char *proto, WORD *extport, DWORD *extip, bool search); diff --git a/src/modules/netlib/netlibbind.cpp b/src/modules/netlib/netlibbind.cpp index 6c0c4c19e9..5fb9c252cc 100644 --- a/src/modules/netlib/netlibbind.cpp +++ b/src/modules/netlib/netlibbind.cpp @@ -2,7 +2,7 @@ Miranda IM: the free IM client for Microsoft* Windows* -Copyright 2000-2009 Miranda ICQ/IM project, +Copyright 2000-2012 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. @@ -23,17 +23,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" #include "netlib.h" -bool BindSocketToPort(const char *szPorts, SOCKET s, int* portn) +bool BindSocketToPort(const char *szPorts, SOCKET s, SOCKET s6, int* portn) { SOCKADDR_IN sin = {0}; sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_ANY); + + SOCKADDR_IN6 sin6 = {0}; + sin6.sin6_family = AF_INET6; EnterCriticalSection(&csNetlibUser); - if (--*portn < 0 && s != INVALID_SOCKET) + if (--*portn < 0 && (s != INVALID_SOCKET || s6 != INVALID_SOCKET)) { - BindSocketToPort(szPorts, INVALID_SOCKET, portn); + BindSocketToPort(szPorts, INVALID_SOCKET, INVALID_SOCKET, portn); if (*portn == 0) { LeaveCriticalSection(&csNetlibUser); @@ -88,7 +90,12 @@ bool BindSocketToPort(const char *szPorts, SOCKET s, int* portn) } sin.sin_port = htons((WORD)port); - if (bind(s, (SOCKADDR*)&sin, sizeof(sin)) == 0) + bool bV4Mapped = s == INVALID_SOCKET || bind(s, (SOCKADDR*)&sin, sizeof(sin)) == 0; + + sin6.sin6_port = htons((WORD)port); + bool bV6Mapped = s6 == INVALID_SOCKET || bind(s6, (PSOCKADDR)&sin6, sizeof(sin6)) == 0; + + if (bV4Mapped && bV6Mapped) { LeaveCriticalSection(&csNetlibUser); *portn = portnum + 1; @@ -111,10 +118,10 @@ bool BindSocketToPort(const char *szPorts, SOCKET s, int* portn) } } - int NetlibFreeBoundPort(struct NetlibBoundPort *nlbp) { closesocket(nlbp->s); + closesocket(nlbp->s6); WaitForSingleObject(nlbp->hThread,INFINITE); CloseHandle(nlbp->hThread); NetlibLogf(nlbp->nlu, "(%u) Port %u closed for incoming connections", nlbp->s, nlbp->wPort); @@ -125,18 +132,39 @@ int NetlibFreeBoundPort(struct NetlibBoundPort *nlbp) static unsigned __stdcall NetlibBindAcceptThread(void* param) { SOCKET s; - SOCKADDR_IN sin; + SOCKADDR_INET_M sin; int sinLen; struct NetlibConnection *nlc; struct NetlibBoundPort *nlbp = (NetlibBoundPort*)param; NetlibLogf(nlbp->nlu, "(%u) Port %u opened for incoming connections", nlbp->s, nlbp->wPort); - for(;;) + for (;;) { + fd_set r; + FD_ZERO(&r); + FD_SET(nlbp->s, &r); + FD_SET(nlbp->s6, &r); + + if (select(0, &r, NULL, NULL, NULL) == SOCKET_ERROR) + break; + sinLen = sizeof(sin); - s = accept(nlbp->s, (struct sockaddr*)&sin, &sinLen); - if (s == INVALID_SOCKET) break; - NetlibLogf(nlbp->nlu, "New incoming connection on port %u from %s (%d)", nlbp->wPort, inet_ntoa(sin.sin_addr), s); + memset(&sin, 0, sizeof(sin)); + + if (FD_ISSET(nlbp->s, &r)) + { + s = accept(nlbp->s, (struct sockaddr*)&sin, &sinLen); + if (s == INVALID_SOCKET) break; + } + else if (FD_ISSET(nlbp->s6, &r)) + { + s = accept(nlbp->s6, (struct sockaddr*)&sin, &sinLen); + if (s == INVALID_SOCKET) break; + } + + char *szHostA = NetlibAddressToString(&sin); + NetlibLogf(nlbp->nlu, "New incoming connection on port %u from %s (%p )", nlbp->wPort, szHostA, s); + mir_free(szHostA); nlc = (NetlibConnection*)mir_calloc(sizeof(NetlibConnection)); nlc->handleType = NLH_CONNECTION; nlc->nlu = nlbp->nlu; @@ -144,21 +172,22 @@ static unsigned __stdcall NetlibBindAcceptThread(void* param) nlc->s2 = INVALID_SOCKET; InitializeCriticalSection(&nlc->csHttpSequenceNums); nlc->hOkToCloseEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - nlc->dontCloseNow = 0; NetlibInitializeNestedCS(&nlc->ncsSend); NetlibInitializeNestedCS(&nlc->ncsRecv); - nlbp->pfnNewConnectionV2((HANDLE)nlc,ntohl(sin.sin_addr.S_un.S_addr), nlbp->pExtra); + + if (nlbp->pfnNewConnectionV2) nlbp->pfnNewConnectionV2(nlc, ntohl(sin.Ipv4.sin_addr.S_un.S_addr), nlbp->pExtra); } NetlibUPnPDeletePortMapping(nlbp->wExPort, "TCP"); return 0; } -INT_PTR NetlibBindPort(WPARAM wParam,LPARAM lParam) +INT_PTR NetlibBindPort(WPARAM wParam, LPARAM lParam) { NETLIBBIND *nlb = (NETLIBBIND*)lParam; struct NetlibUser *nlu = (struct NetlibUser*)wParam; struct NetlibBoundPort *nlbp; - SOCKADDR_IN sin; + SOCKADDR_IN sin = {0}; + SOCKADDR_IN6 sin6 = {0}; int foundPort = 0; UINT dwThreadId; @@ -178,23 +207,24 @@ INT_PTR NetlibBindPort(WPARAM wParam,LPARAM lParam) nlbp->handleType = NLH_BOUNDPORT; nlbp->nlu = nlu; nlbp->pfnNewConnectionV2 = nlb->pfnNewConnectionV2; - nlbp->s = socket(AF_INET, SOCK_STREAM, 0); + + nlbp->s = socket(PF_INET, SOCK_STREAM, 0); + nlbp->s6 = socket(PF_INET6, SOCK_STREAM, 0); nlbp->pExtra = (nlb->cbSize != NETLIBBIND_SIZEOF_V1) ? nlb->pExtra : NULL; - if (nlbp->s == INVALID_SOCKET) + if (nlbp->s == INVALID_SOCKET && nlbp->s6 == INVALID_SOCKET) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"socket",WSAGetLastError()); mir_free(nlbp); return 0; } sin.sin_family = AF_INET; - sin.sin_addr.s_addr = htonl(INADDR_ANY); - sin.sin_port = 0; + sin6.sin6_family = AF_INET6; /* if the netlib user wanted a free port given in the range, then they better have given wPort==0, let's hope so */ if (nlu->settings.specifyIncomingPorts && nlu->settings.szIncomingPorts && nlb->wPort == 0) { - if (!BindSocketToPort(nlu->settings.szIncomingPorts, nlbp->s, &nlu->outportnum)) + if (!BindSocketToPort(nlu->settings.szIncomingPorts, nlbp->s, nlbp->s6, &nlu->outportnum)) { NetlibLogf(nlu, "Netlib bind: Not enough ports for incoming connections specified"); SetLastError(WSAEADDRINUSE); @@ -210,52 +240,78 @@ INT_PTR NetlibBindPort(WPARAM wParam,LPARAM lParam) { NetlibLogf(nlu,"%s %d: trying to bind port %d, this 'feature' can be abused, please be sure you want to allow it.",__FILE__,__LINE__,nlb->wPort); sin.sin_port = htons(nlb->wPort); + sin6.sin6_port = htons(nlb->wPort); } if (bind(nlbp->s, (PSOCKADDR)&sin, sizeof(sin)) == 0) + { + SOCKADDR_IN sin = {0}; + int len = sizeof(sin); + if (!getsockname(nlbp->s, (PSOCKADDR)&sin, &len)) + sin6.sin6_port = sin.sin_port; + foundPort = 1; + } + + if (bind(nlbp->s6, (PSOCKADDR)&sin6, sizeof(sin6)) == 0) foundPort = 1; } if (!foundPort) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"bind",WSAGetLastError()); closesocket(nlbp->s); + closesocket(nlbp->s6); mir_free(nlbp); return 0; } - if (listen(nlbp->s, 5)) + if (nlbp->s != INVALID_SOCKET && listen(nlbp->s, 5)) { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"listen",WSAGetLastError()); closesocket(nlbp->s); + closesocket(nlbp->s6); mir_free(nlbp); return 0; } - { int len; - DWORD extIP; + if (nlbp->s6 != INVALID_SOCKET && listen(nlbp->s6, 5)) + { + NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"listen",WSAGetLastError()); + closesocket(nlbp->s); + closesocket(nlbp->s6); + mir_free(nlbp); + return 0; + } - ZeroMemory(&sin,sizeof(sin)); - len = sizeof(sin); - if (getsockname(nlbp->s,(SOCKADDR *)&sin,&len)) + { + SOCKADDR_INET_M sin = {0}; + int len = sizeof(sin); + if (!getsockname(nlbp->s, (PSOCKADDR)&sin, &len)) + { + nlb->wPort = ntohs(sin.Ipv4.sin_port); + nlb->dwInternalIP = ntohl(sin.Ipv4.sin_addr.S_un.S_addr); + } + else if (!getsockname(nlbp->s6, (PSOCKADDR)&sin, &len)) + nlb->wPort = ntohs(sin.Ipv6.sin6_port); + else { NetlibLogf(nlu,"%s %d: %s() failed (%u)",__FILE__,__LINE__,"getsockname",WSAGetLastError()); closesocket(nlbp->s); + closesocket(nlbp->s6); mir_free(nlbp); return 0; } - nlb->wPort = ntohs(sin.sin_port); nlbp->wPort = nlb->wPort; - nlb->dwInternalIP = ntohl(sin.sin_addr.S_un.S_addr); if (nlb->dwInternalIP == 0) { - char hostname[64]; - struct hostent *he; - + char hostname[64] = ""; gethostname(hostname, SIZEOF(hostname)); - he = gethostbyname(hostname); - if (he && he->h_addr_list[0]) - nlb->dwInternalIP = ntohl(*(PDWORD)he->h_addr_list[0]); - } + + PHOSTENT he = gethostbyname(hostname); + if (he && he->h_addr) + nlb->dwInternalIP = ntohl(*(PDWORD)he->h_addr); + } + + DWORD extIP; if (nlu->settings.enableUPnP && NetlibUPnPAddPortMapping(nlb->wPort, "TCP", &nlbp->wExPort, &extIP, nlb->cbSize > NETLIBBIND_SIZEOF_V2)) { @@ -282,6 +338,7 @@ INT_PTR NetlibBindPort(WPARAM wParam,LPARAM lParam) } } } + nlbp->hThread = (HANDLE)forkthreadex(NULL, 0, NetlibBindAcceptThread, 0, nlbp, &dwThreadId); return (INT_PTR)nlbp; } diff --git a/src/modules/netlib/netlibhttp.cpp b/src/modules/netlib/netlibhttp.cpp index 970a28cb10..2893344ade 100644 --- a/src/modules/netlib/netlibhttp.cpp +++ b/src/modules/netlib/netlibhttp.cpp @@ -525,9 +525,9 @@ INT_PTR NetlibHttpSendRequest(WPARAM wParam, LPARAM lParam) if (ip && szHost) { mir_free(szHost); - szHost = (char*)mir_alloc(30); + szHost = (char*)mir_alloc(64); if (cln) *cln = ':'; - mir_snprintf(szHost, 30, "%s%s", inet_ntoa(*(PIN_ADDR)&ip), cln ? cln : ""); + mir_snprintf(szHost, 64, "%s%s", inet_ntoa(*(PIN_ADDR)&ip), cln ? cln : ""); } /* if (ip && pszUrl[0] != '/') 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 diff --git a/src/modules/netlib/netlibsock.cpp b/src/modules/netlib/netlibsock.cpp index 875c47b0a1..8ec6a473f5 100644 --- a/src/modules/netlib/netlibsock.cpp +++ b/src/modules/netlib/netlibsock.cpp @@ -2,7 +2,7 @@ Miranda IM: the free IM client for Microsoft* Windows* -Copyright 2000-2009 Miranda ICQ/IM project, +Copyright 2000-2012 Miranda ICQ/IM project, all portions of this codebase are copyrighted to the people listed in contributors.txt. @@ -23,69 +23,73 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "commonheaders.h" #include "netlib.h" -extern HANDLE hConnectionHeaderMutex,hSendEvent,hRecvEvent; +extern HANDLE hConnectionHeaderMutex, hSendEvent, hRecvEvent; -INT_PTR NetlibSend(WPARAM wParam,LPARAM lParam) +INT_PTR NetlibSend(WPARAM wParam, LPARAM lParam) { - struct NetlibConnection *nlc=(struct NetlibConnection*)wParam; - NETLIBBUFFER *nlb=(NETLIBBUFFER*)lParam; + NetlibConnection *nlc = (NetlibConnection*)wParam; + NETLIBBUFFER *nlb = (NETLIBBUFFER*)lParam; INT_PTR result; - if ( nlb == NULL ) { + if (nlb == NULL) + { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } - if ( !NetlibEnterNestedCS( nlc, NLNCS_SEND )) + if (!NetlibEnterNestedCS(nlc, NLNCS_SEND)) return SOCKET_ERROR; - if ( nlc->usingHttpGateway && !( nlb->flags & MSG_RAW )) { - if ( !( nlb->flags & MSG_NOHTTPGATEWAYWRAP ) && nlc->nlu->user.pfnHttpGatewayWrapSend ) { - NetlibDumpData( nlc, ( PBYTE )nlb->buf, nlb->len, 1, nlb->flags ); - result = nlc->nlu->user.pfnHttpGatewayWrapSend(( HANDLE )nlc, ( PBYTE )nlb->buf, nlb->len, nlb->flags | MSG_NOHTTPGATEWAYWRAP, NetlibSend ); + if (nlc->usingHttpGateway && !(nlb->flags & MSG_RAW)) + { + if (!(nlb->flags & MSG_NOHTTPGATEWAYWRAP) && nlc->nlu->user.pfnHttpGatewayWrapSend) + { + NetlibDumpData(nlc, (PBYTE)nlb->buf, nlb->len, 1, nlb->flags); + result = nlc->nlu->user.pfnHttpGatewayWrapSend((HANDLE)nlc, (PBYTE)nlb->buf, nlb->len, nlb->flags | MSG_NOHTTPGATEWAYWRAP, NetlibSend); } - else result = NetlibHttpGatewayPost( nlc, nlb->buf, nlb->len, nlb->flags ); + else result = NetlibHttpGatewayPost(nlc, nlb->buf, nlb->len, nlb->flags); } else { - NetlibDumpData( nlc, ( PBYTE )nlb->buf, nlb->len, 1, nlb->flags ); + NetlibDumpData(nlc, (PBYTE)nlb->buf, nlb->len, 1, nlb->flags); if (nlc->hSsl) - result = si.write( nlc->hSsl, nlb->buf, nlb->len ); + result = si.write(nlc->hSsl, nlb->buf, nlb->len); else - result = send( nlc->s, nlb->buf, nlb->len, nlb->flags & 0xFFFF ); + result = send(nlc->s, nlb->buf, nlb->len, nlb->flags & 0xFFFF); } - NetlibLeaveNestedCS( &nlc->ncsSend ); + NetlibLeaveNestedCS(&nlc->ncsSend); - if ((( THook* )hSendEvent)->subscriberCount ) { + if (((THook*)hSendEvent)->subscriberCount) + { NETLIBNOTIFY nln = { nlb, result }; - CallHookSubscribers( hSendEvent, (WPARAM)&nln, (LPARAM)&nlc->nlu->user ); + CallHookSubscribers(hSendEvent, (WPARAM)&nln, (LPARAM)&nlc->nlu->user); } return result; } -INT_PTR NetlibRecv(WPARAM wParam,LPARAM lParam) +INT_PTR NetlibRecv(WPARAM wParam, LPARAM lParam) { - struct NetlibConnection *nlc = (struct NetlibConnection*)wParam; - NETLIBBUFFER* nlb = ( NETLIBBUFFER* )lParam; + NetlibConnection *nlc = (NetlibConnection*)wParam; + NETLIBBUFFER* nlb = (NETLIBBUFFER*)lParam; int recvResult; - if ( nlb == NULL ) { - SetLastError( ERROR_INVALID_PARAMETER ); + if (nlb == NULL) { + SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } - if ( !NetlibEnterNestedCS( nlc, NLNCS_RECV )) + if (!NetlibEnterNestedCS(nlc, NLNCS_RECV)) return SOCKET_ERROR; - if ( nlc->usingHttpGateway && !( nlb->flags & MSG_RAW )) - recvResult = NetlibHttpGatewayRecv( nlc, nlb->buf, nlb->len, nlb->flags ); + if (nlc->usingHttpGateway && !(nlb->flags & MSG_RAW)) + recvResult = NetlibHttpGatewayRecv(nlc, nlb->buf, nlb->len, nlb->flags); else { if (nlc->hSsl) - recvResult = si.read( nlc->hSsl, nlb->buf, nlb->len, (nlb->flags & MSG_PEEK) != 0 ); + recvResult = si.read(nlc->hSsl, nlb->buf, nlb->len, (nlb->flags & MSG_PEEK) != 0); else - recvResult = recv( nlc->s, nlb->buf, nlb->len, nlb->flags & 0xFFFF ); + recvResult = recv(nlc->s, nlb->buf, nlb->len, nlb->flags & 0xFFFF); } - NetlibLeaveNestedCS( &nlc->ncsRecv ); + NetlibLeaveNestedCS(&nlc->ncsRecv); if (recvResult <= 0) return recvResult; @@ -101,18 +105,20 @@ INT_PTR NetlibRecv(WPARAM wParam,LPARAM lParam) static int ConnectionListToSocketList(HANDLE *hConns, fd_set *fd, int& pending) { - struct NetlibConnection *nlcCheck; + NetlibConnection *nlcCheck; int i; FD_ZERO(fd); - for(i=0;hConns[i] && hConns[i]!=INVALID_HANDLE_VALUE && ihandleType!=NLH_CONNECTION && nlcCheck->handleType!=NLH_BOUNDPORT) { + for (i = 0; hConns[i] && hConns[i] != INVALID_HANDLE_VALUE && i < FD_SETSIZE; i++) + { + nlcCheck = (NetlibConnection*)hConns[i]; + if (nlcCheck->handleType != NLH_CONNECTION && nlcCheck->handleType != NLH_BOUNDPORT) + { SetLastError(ERROR_INVALID_DATA); return 0; } FD_SET(nlcCheck->s,fd); - if ( si.pending( nlcCheck->hSsl )) + if (si.pending(nlcCheck->hSsl)) pending++; } return 1; @@ -120,8 +126,9 @@ static int ConnectionListToSocketList(HANDLE *hConns, fd_set *fd, int& pending) INT_PTR NetlibSelect(WPARAM,LPARAM lParam) { - NETLIBSELECT *nls=(NETLIBSELECT*)lParam; - if (nls==NULL || nls->cbSize!=sizeof(NETLIBSELECT)) { + NETLIBSELECT *nls = (NETLIBSELECT*)lParam; + if (nls == NULL || nls->cbSize != sizeof(NETLIBSELECT)) + { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } @@ -132,54 +139,58 @@ INT_PTR NetlibSelect(WPARAM,LPARAM lParam) int pending = 0; fd_set readfd, writefd, exceptfd; - WaitForSingleObject(hConnectionHeaderMutex,INFINITE); - if (!ConnectionListToSocketList(nls->hReadConns,&readfd,pending) - || !ConnectionListToSocketList(nls->hWriteConns,&writefd,pending) - || !ConnectionListToSocketList(nls->hExceptConns,&exceptfd,pending)) { - ReleaseMutex(hConnectionHeaderMutex); - return SOCKET_ERROR; + WaitForSingleObject(hConnectionHeaderMutex, INFINITE); + if (!ConnectionListToSocketList(nls->hReadConns, &readfd, pending) + || !ConnectionListToSocketList(nls->hWriteConns, &writefd, pending) + || !ConnectionListToSocketList(nls->hExceptConns, &exceptfd, pending)) + { + ReleaseMutex(hConnectionHeaderMutex); + return SOCKET_ERROR; } ReleaseMutex(hConnectionHeaderMutex); if (pending) return 1; - return select(0,&readfd,&writefd,&exceptfd,nls->dwTimeout==INFINITE?NULL:&tv); + return select(0, &readfd, &writefd, &exceptfd, nls->dwTimeout == INFINITE ? NULL : &tv); } INT_PTR NetlibSelectEx(WPARAM, LPARAM lParam) { - NETLIBSELECTEX *nls=(NETLIBSELECTEX*)lParam; - if (nls==NULL || nls->cbSize!=sizeof(NETLIBSELECTEX)) { + NETLIBSELECTEX *nls = (NETLIBSELECTEX*)lParam; + if (nls == NULL || nls->cbSize != sizeof(NETLIBSELECTEX)) + { SetLastError(ERROR_INVALID_PARAMETER); return SOCKET_ERROR; } TIMEVAL tv; - tv.tv_sec=nls->dwTimeout/1000; - tv.tv_usec=(nls->dwTimeout%1000)*1000; - WaitForSingleObject(hConnectionHeaderMutex,INFINITE); + tv.tv_sec = nls->dwTimeout / 1000; + tv.tv_usec = (nls->dwTimeout % 1000) * 1000; + WaitForSingleObject(hConnectionHeaderMutex, INFINITE); int pending = 0; - fd_set readfd,writefd,exceptfd; - if (!ConnectionListToSocketList(nls->hReadConns,&readfd,pending) - || !ConnectionListToSocketList(nls->hWriteConns,&writefd,pending) - || !ConnectionListToSocketList(nls->hExceptConns,&exceptfd,pending)) { - ReleaseMutex(hConnectionHeaderMutex); - return SOCKET_ERROR; + fd_set readfd, writefd, exceptfd; + if (!ConnectionListToSocketList(nls->hReadConns, &readfd, pending) + || !ConnectionListToSocketList(nls->hWriteConns, &writefd, pending) + || !ConnectionListToSocketList(nls->hExceptConns, &exceptfd, pending)) + { + ReleaseMutex(hConnectionHeaderMutex); + return SOCKET_ERROR; } ReleaseMutex(hConnectionHeaderMutex); - int rc = (pending) ? pending : select(0,&readfd,&writefd,&exceptfd,nls->dwTimeout==INFINITE?NULL:&tv); + int rc = (pending) ? pending : select(0, &readfd, &writefd, &exceptfd, nls->dwTimeout == INFINITE ? NULL : &tv); - WaitForSingleObject(hConnectionHeaderMutex,INFINITE); + WaitForSingleObject(hConnectionHeaderMutex, INFINITE); /* go thru each passed HCONN array and grab its socket handle, then give it to FD_ISSET() to see if an event happened for that socket, if it has it will be returned as TRUE (otherwise not) This happens for read/write/except */ - struct NetlibConnection *conn=NULL; + NetlibConnection *conn = NULL; int j; - for (j=0; jhReadConns[j]; - if (conn==NULL || conn==INVALID_HANDLE_VALUE) break; + for (j = 0; j < FD_SETSIZE; j++) + { + conn = (NetlibConnection*)nls->hReadConns[j]; + if (conn == NULL || conn == INVALID_HANDLE_VALUE) break; if (si.pending(conn->hSsl)) nls->hReadStatus[j] = TRUE; @@ -188,16 +199,153 @@ INT_PTR NetlibSelectEx(WPARAM, LPARAM lParam) else nls->hReadStatus[j] = FD_ISSET(conn->s,&readfd); } - for (j=0; jhWriteConns[j]; - if (conn==NULL || conn==INVALID_HANDLE_VALUE) break; + for (j = 0; j < FD_SETSIZE; j++) + { + conn = (NetlibConnection*)nls->hWriteConns[j]; + if (conn == NULL || conn == INVALID_HANDLE_VALUE) break; nls->hWriteStatus[j] = FD_ISSET(conn->s,&writefd); } - for (j=0; jhExceptConns[j]; - if (conn==NULL || conn==INVALID_HANDLE_VALUE) break; + for (j = 0; j < FD_SETSIZE; j++) + { + conn = (NetlibConnection*)nls->hExceptConns[j]; + if (conn == NULL || conn == INVALID_HANDLE_VALUE) break; nls->hExceptStatus[j] = FD_ISSET(conn->s,&exceptfd); } ReleaseMutex(hConnectionHeaderMutex); return rc; } + +bool NetlibStringToAddress(const char* str, SOCKADDR_INET_M* addr) +{ + if (!str) return false; + + if (MyWSAStringToAddress) + { + int len = sizeof(SOCKADDR_INET_M); + return !MyWSAStringToAddress((char*)str, AF_INET6, NULL, (PSOCKADDR)addr, &len); + } + else + { + unsigned iaddr = inet_addr(str); + if (!iaddr) return false; + + addr->Ipv4.sin_addr.s_addr = iaddr; + addr->Ipv4.sin_family = AF_INET; + return true; + } +} + +char* NetlibAddressToString(SOCKADDR_INET_M* addr) +{ + char saddr[128]; + + if (MyWSAAddressToString) + { + DWORD len = sizeof(saddr); + if (!MyWSAAddressToString((PSOCKADDR)addr, sizeof(*addr), NULL, saddr, &len)) + return mir_strdup(saddr); + } + else if (addr->si_family == AF_INET) + { + char *szIp = inet_ntoa(addr->Ipv4.sin_addr); + if (addr->Ipv4.sin_port != 0) + { + mir_snprintf(saddr, sizeof(saddr), "%s:%d", szIp, htons(addr->Ipv4.sin_port)); + return mir_strdup(saddr); + } + else + return mir_strdup(szIp); + } + return NULL; +} + +void NetlibGetConnectionInfo(NetlibConnection* nlc, NETLIBCONNINFO *connInfo) +{ + if (!nlc || !connInfo || connInfo->cbSize < sizeof(NETLIBCONNINFO)) return; + + SOCKADDR_INET_M sin = {0}; + int len = sizeof(sin); + + if (!getsockname(nlc->s, (PSOCKADDR)&sin, &len)) + { + connInfo->wPort = ntohs(sin.Ipv4.sin_port); + connInfo->dwIpv4 = sin.si_family == AF_INET ? htonl(sin.Ipv4.sin_addr.s_addr) : 0; + + char *szTmp = NetlibAddressToString(&sin); + strncpy(connInfo->szIpPort, szTmp, sizeof(connInfo->szIpPort)); + connInfo->szIpPort[sizeof(connInfo->szIpPort) - 1] = 0; + mir_free(szTmp); + } +} + +inline bool IsAddrGlobal(const IN6_ADDR *a) +{ + unsigned char High = a->s6_bytes[0] & 0xf0; + return High != 0 && High != 0xf0; +} + +static NETLIBIPLIST* GetMyIpv6(unsigned flags) +{ + addrinfo *air = NULL, *ai, hints = {0}; + const char *szMyHost = ""; + + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + + if (MyGetaddrinfo(szMyHost, NULL, &hints, &air)) + return NULL; + + unsigned n = 0; + for (ai = air; ai; ai = ai->ai_next) + { + SOCKADDR_INET_M* iaddr = (SOCKADDR_INET_M*)ai->ai_addr; + if (ai->ai_family == AF_INET || + (ai->ai_family == AF_INET6 && + (!(flags & 1) || IsAddrGlobal(&iaddr->Ipv6.sin6_addr)))) + ++n; + } + + NETLIBIPLIST *addr = (NETLIBIPLIST*)mir_calloc(n * 64 + 4); + addr->cbNum = n; + + unsigned i = 0; + for (ai = air; ai; ai = ai->ai_next) + { + SOCKADDR_INET_M* iaddr = (SOCKADDR_INET_M*)ai->ai_addr; + if (ai->ai_family == AF_INET || + (ai->ai_family == AF_INET6 && + (!(flags & 1) || IsAddrGlobal(&iaddr->Ipv6.sin6_addr)))) + { + + char* szIp = NetlibAddressToString(iaddr); + if (szIp) strcpy(addr->szIp[i++], szIp); + mir_free(szIp); + } + } + MyFreeaddrinfo(air); + return addr; +} + +static NETLIBIPLIST* GetMyIpv4(void) +{ + char hostname[256] = ""; + + gethostname(hostname, sizeof(hostname)); + PHOSTENT he = gethostbyname(hostname); + + unsigned n; + for (n = 0; he->h_addr_list[n]; ++n) ; + + NETLIBIPLIST *addr = (NETLIBIPLIST*)mir_calloc(n * 64 + 4); + addr->cbNum = n; + + for (unsigned i = 0; i < n; ++i) + strcpy(addr->szIp[i], inet_ntoa(*(PIN_ADDR)he->h_addr_list[i])); + + return addr; +} + +NETLIBIPLIST* GetMyIp(unsigned flags) +{ + return (MyGetaddrinfo && MyFreeaddrinfo) ? GetMyIpv6(flags) : GetMyIpv4(); +} diff --git a/src/modules/updatenotify/updatenotify.cpp b/src/modules/updatenotify/updatenotify.cpp index ef955ba3c5..5b2162a041 100644 --- a/src/modules/updatenotify/updatenotify.cpp +++ b/src/modules/updatenotify/updatenotify.cpp @@ -214,17 +214,11 @@ static DWORD UpdateNotifyMakeVersion(char *str) { return PLUGIN_MAKE_VERSION(a1, a2, a3, a4); } -static int UpdateNotifyIsNewer(DWORD dwCurrent, DWORD dwTest) { - if (dwTest>dwCurrent) - return 1; - return 0; -} +inline bool UpdateNotifyIsNewer(DWORD dwCurrent, DWORD dwTest) +{ return dwTest > dwCurrent; } -static int UpdateNotifyReleaseDataValid(UpdateNotifyReleaseData *d) { - if (d&&d->szVersionPublic&&d->szVersion&&d->szDownload&&d->szNotes) - return 1; - return 0; -} +inline bool UpdateNotifyReleaseDataValid(UpdateNotifyReleaseData *d) +{ return d && d->szVersionPublic && d->szVersion && d->szDownload && d->szNotes; } static void UpdateNotifyFreeReleaseData(UpdateNotifyReleaseData *d) { if (!d) -- cgit v1.2.3