summaryrefslogtreecommitdiff
path: root/src/modules/netlib/netlibsock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/netlib/netlibsock.cpp')
-rw-r--r--src/modules/netlib/netlibsock.cpp280
1 files changed, 214 insertions, 66 deletions
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 && i<FD_SETSIZE;i++) {
- nlcCheck=(struct NetlibConnection*)hConns[i];
- if (nlcCheck->handleType!=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; j<FD_SETSIZE; j++) {
- conn=(struct NetlibConnection*)nls->hReadConns[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; j<FD_SETSIZE; j++) {
- conn=(struct NetlibConnection*)nls->hWriteConns[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; j<FD_SETSIZE; j++) {
- conn=(struct NetlibConnection*)nls->hExceptConns[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();
+}