📄 tcptransportsocket.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "common.h"
#include "TCPTransportSocket.h"
#include "ObexTransportConnection.h"
#include "ObexTCPTransport.h"
#include "ObexStrings.h"
#include <Ws2tcpip.h>
/******globals******/
extern CRITICAL_SECTION g_TransportSocketCS;
static TCP_CONNECTION_HOLDER *g_pConnectionList = 0;
CTCPTransportSocket::CTCPTransportSocket():
_refCount(1)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CTCPTransportSocket::CTCPTransportSocket()\n"));
VariantInit(&m_varName);
VariantInit(&m_varPort);
V_BSTR(&m_varName) = NULL;
V_BSTR(&m_varPort) = NULL;
//initilize the socket libs
WSADATA wsd;
WSAStartup (MAKEWORD(1,1), &wsd);
}
CTCPTransportSocket::~CTCPTransportSocket()
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CTCPTransportSocket::~CTCPTransportSocket()\n"));
Close();
VariantClear(&m_varName);
VariantClear(&m_varPort);
//clean up winsock
WSACleanup();
}
HRESULT STDMETHODCALLTYPE
CTCPTransportSocket::Close()
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CTCPTransportSocket::Close()\n"));
CCritSection TransportCS(&g_TransportSocketCS);
TransportCS.Lock();
HRESULT hRes = E_FAIL;
TCP_CONNECTION_HOLDER *pTemp = 0;
TCP_CONNECTION_HOLDER *pPrev = 0;
if(g_pConnectionList)
{
pTemp = g_pConnectionList->m_pNext;
pPrev = g_pConnectionList;
}
else
{
hRes = S_OK;
goto Done;
}
if(!V_BSTR(&this->m_varPort) || !V_BSTR(&this->m_varName))
{
hRes = S_OK;
goto Done;
}
if(pPrev)
{
//its okay that we dont free up the memory pointed to here!
// actually we CANT because we dont own a reference to it
// to prevent a loop of refcounts
if(0 == wcscmp(V_BSTR(&(this->m_varPort)), V_BSTR(&(pPrev->m_varPort))) &&
0 == wcscmp(V_BSTR(&(this->m_varName)), V_BSTR(&(pPrev->m_varName))))
{
TCP_CONNECTION_HOLDER *pDel = pPrev;
g_pConnectionList = pPrev->m_pNext;
VariantClear(&(pDel->m_varPort));
VariantClear(&(pDel->m_varName));
delete pDel;
pTemp = 0;
hRes = S_OK;
goto Done;
}
}
while(pTemp && pTemp->m_pNext)
{
//its okay that we dont free up the memory pointed to here!
// actually we CANT because we dont own a reference to it
// to prevent a loop of refcounts
if(0 == wcscmp(V_BSTR(&(this->m_varPort)), V_BSTR(&(pTemp->m_varPort))) &&
0 == wcscmp(V_BSTR(&(this->m_varName)), V_BSTR(&(pTemp->m_varName))))
{
TCP_CONNECTION_HOLDER *pDel = pTemp;
pPrev->m_pNext = pTemp->m_pNext;
VariantClear(&(pDel->m_varPort));
VariantClear(&(pDel->m_varName));
delete pDel;
hRes = S_OK;
break;
}
pPrev = pTemp;
pTemp = pTemp->m_pNext;
}
Done:
return hRes;
}
HRESULT STDMETHODCALLTYPE
CTCPTransportSocket::Listen(LPTRANSPORTCONNECTION *ppConnection)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CTCPTransportSocket::Listen()\n"));
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE
CTCPTransportSocket::Connect(LPPROPERTYBAG2 pDeviceProps,DWORD dwCapability, LPTRANSPORTCONNECTION * ppConnection)
{
#if defined (SDK_BUILD)
return E_NOTIMPL;
#else
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CTCPTransportSocket::Connect()\n"));
CCritSection TransportCS(&g_TransportSocketCS);
TransportCS.Lock();
PREFAST_ASSERT(pDeviceProps);
*ppConnection = NULL;
//set the default error to return
HRESULT hRet = E_FAIL;
//variables
SOCKET sMySock = INVALID_SOCKET;
TCP_CONNECTION_HOLDER *pTemp = NULL;
ADDRINFO aiHints, *paiRemote=NULL, *paiTmp;
char *pRemote = NULL;
char *pPort = NULL;
//fetch the device ID from the property bag
VARIANT pNameVar;
VARIANT pPortVar;
VariantInit(&pNameVar);
VariantInit(&pPortVar);
//get the device name from the property bag (on error, exit)
if(FAILED(pDeviceProps->Read(c_szDevicePropName, &pNameVar, 0)) || VT_BSTR != V_VT(&pNameVar))
{
hRet = E_FAIL;
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX] ----- could not read device name\n"));
goto connect_error;
}
//read the port BSTR
if(FAILED(pDeviceProps->Read(c_szPort, &pPortVar, 0)))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX] ----- could not read port name\n"));
goto connect_error;
}
//see if the port is BSTR / NAME
if(VT_BSTR != V_VT(&pNameVar) ||
VT_BSTR != V_VT(&pPortVar))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX] ----- name or var is of incorrect type\n"));
ASSERT(FALSE);
goto connect_error;
}
//figure out if we already have this guy allocated...
pTemp = g_pConnectionList;
//if we DO have it allocated, this loop will return an instance
while(pTemp)
{
if(0 == wcscmp(V_BSTR(&pPortVar), V_BSTR(&(pTemp->m_varPort))) &&
0 == wcscmp(V_BSTR(&pNameVar), V_BSTR(&(pTemp->m_varName))))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> reusing connection!\n"));
(*ppConnection) = pTemp->m_pItem;
(*ppConnection)->AddRef();
hRet = S_OK;
goto connect_done;
}
pTemp = pTemp->m_pNext;
}
//
// Since we are here, there isnt an existing instance to the server -- go make one
//
// call getaddrinfo to get the IP's (V6 or V4 depending on their setup)
memset(&aiHints,0,sizeof(aiHints));
aiHints.ai_family = PF_UNSPEC; // Accept v4 or v6
aiHints.ai_socktype = SOCK_STREAM; // or SOCK_DGRAM for UDP
int uiRemoteLen, uiPortLen;
uiRemoteLen = WideCharToMultiByte(CP_ACP,
0,
V_BSTR(&pNameVar),
-1,
NULL,
0,
NULL,
NULL);
uiPortLen = WideCharToMultiByte(CP_ACP,
0,
V_BSTR(&pPortVar),
-1,
NULL,
0,
NULL,
NULL);
if(!uiRemoteLen || !uiPortLen)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> port or address is too short!\n"));
ASSERT(FALSE);
hRet = E_FAIL;
goto connect_error;;
}
pRemote = new char[uiRemoteLen + 1];
pPort = new char[uiPortLen + 1];
if(!pRemote || !pPort)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> error out of memory!\n"));
hRet = E_FAIL;
goto connect_error;
}
if(uiRemoteLen != WideCharToMultiByte(CP_ACP,
0,
V_BSTR(&pNameVar),
-1,
pRemote,
uiRemoteLen+1,
NULL,
NULL))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> error doing multibyte conversion!\n"));
hRet = E_FAIL;
goto connect_error;
}
if(uiPortLen != WideCharToMultiByte(CP_ACP,
0,
V_BSTR(&pPortVar),
-1,
pPort,
uiPortLen+1,
NULL,
NULL))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> error doing multibyte conversion!\n"));
hRet = E_FAIL;
goto connect_error;
}
if (getaddrinfo(pRemote,pPort,&aiHints,&paiRemote) != 0)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> error getting addrinfo()!\n"));
goto connect_error;
}
// Try each address returned until we connect
for (paiTmp = paiRemote; paiTmp != NULL; paiTmp = paiTmp->ai_next)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> creating socket()!\n"));
sMySock = socket( paiTmp->ai_family, paiTmp->ai_socktype, paiTmp->ai_protocol);
if (sMySock == INVALID_SOCKET)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> invalid socket()!\n"));
continue;
}
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> atempting connect()!\n"));
if (SOCKET_ERROR == connect(sMySock, paiTmp->ai_addr, paiTmp->ai_addrlen))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> connect failed (%d)!\n", WSAGetLastError()));
closesocket(sMySock);
sMySock = INVALID_SOCKET;
continue;
}
break;
}
if (INVALID_SOCKET == sMySock)
{
SetLastError (ERROR_DEVICE_NOT_CONNECTED);
hRet = E_FAIL;
goto connect_error;
}
//get a copy of the name/port for our records
if(FAILED(hRet = VariantCopy(&(this->m_varName), &pNameVar)))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> error copying variant()!\n"));
goto connect_error;
}
if(FAILED(hRet = VariantCopy(&(this->m_varPort), &pPortVar)))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - TCP] -----> error copying variant()!\n"));
goto connect_error;
}
//if we are here, we dont have a transport connecction, so make one
*ppConnection = new CObexTransportConnection(this, V_BSTR(&pNameVar), sMySock);
if( !(*ppConnection) )
{
hRet = E_OUTOFMEMORY;
goto connect_error;
}
//create and insert a new connection holder
pTemp = new TCP_CONNECTION_HOLDER();
if( !pTemp )
{
hRet = E_OUTOFMEMORY;
goto connect_error;
}
pTemp->m_pItem = *ppConnection;
VariantInit(&(pTemp->m_varName));
VariantInit(&(pTemp->m_varPort));
//copy variants into
if(FAILED(hRet = VariantCopy(&(pTemp->m_varName), &pNameVar)))
goto connect_error;
if(FAILED(hRet = VariantCopy(&(pTemp->m_varPort), &pPortVar)))
goto connect_error;
//chain in the node
pTemp->m_pNext = g_pConnectionList;
g_pConnectionList = pTemp;
hRet = S_OK;
goto connect_done;
connect_error:
ASSERT(FAILED(hRet));
if(*ppConnection)
(*ppConnection)->Release();
if(pTemp)
delete pTemp;
*ppConnection = NULL;
connect_done:
VariantClear(&pNameVar);
VariantClear(&pPortVar);
if(paiRemote)
freeaddrinfo(paiRemote);
if(pRemote)
delete [] pRemote;
if(pPort)
delete [] pPort;
return hRet;
#endif
}
HRESULT STDMETHODCALLTYPE
CTCPTransportSocket::GetProperties(LPPROPERTYBAG2 * ppListenProps)
{
return E_NOTIMPL;
}
ULONG STDMETHODCALLTYPE
CTCPTransportSocket::AddRef()
{
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CTCPTransportSocket::AddRef()\n"));
return InterlockedIncrement((LONG *)&_refCount);
}
ULONG STDMETHODCALLTYPE
CTCPTransportSocket::Release()
{
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CTCPTransportSocket::Release()\n"));
SVSUTIL_ASSERT(_refCount != 0xFFFFFFFF);
ULONG ret = InterlockedDecrement((LONG *)&_refCount);
if(!ret)
delete this;
return ret;
}
HRESULT STDMETHODCALLTYPE
CTCPTransportSocket::QueryInterface(REFIID riid, void** ppv)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CTCPTransportSocket::QueryInterface()\n"));
if(!ppv)
return E_POINTER;
if(riid == IID_IPropertyBag)
*ppv = static_cast<IObexTransportSocket*>(this);
else
return *ppv = 0, E_NOINTERFACE;
return AddRef(), S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -