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 --- src/modules/netlib/netlibsock.cpp | 280 +++++++++++++++++++++++++++++--------- 1 file changed, 214 insertions(+), 66 deletions(-) (limited to 'src/modules/netlib/netlibsock.cpp') 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(); +} -- cgit v1.2.3