📄 bthtransportsocket.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 "BTHTransportSocket.h"
#include "obextransportconnection.h"
#include "ObexStrings.h"
#include "ObexBTHTransport.h"
//globals
extern CRITICAL_SECTION g_TransportSocketCS;
static BTH_CONNECTION_HOLDER *g_pConnectionList = 0;
CBTHTransportSocket::CBTHTransportSocket():
_refCount(1)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CBTHTransportSocket::CBTHTransportSocket()\n"));
//initilize the socket libs
WSADATA wsd;
WSAStartup (MAKEWORD(2,2), &wsd);
}
CBTHTransportSocket::~CBTHTransportSocket()
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CBTHTransportSocket::~CBTHTransportSocket()\n"));
Close();
//clean up winsock
WSACleanup();
}
HRESULT STDMETHODCALLTYPE
CBTHTransportSocket::Close()
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CBTHTransportSocket::Close()\n"));
CCritSection TransportCS(&g_TransportSocketCS);
TransportCS.Lock();
HRESULT hRes = E_FAIL;
BTH_CONNECTION_HOLDER *pTemp = 0;
BTH_CONNECTION_HOLDER *pPrev = 0;
if(g_pConnectionList)
{
pTemp = g_pConnectionList->pNext;
pPrev = g_pConnectionList;
}
else
{
return S_OK;
}
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(pPrev->b_addr == b_addr)
{
BTH_CONNECTION_HOLDER *pDel = pPrev;
g_pConnectionList = pPrev->pNext;
delete pDel;
pTemp = 0;
hRes = S_OK;
}
}
while(pTemp && pTemp->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(pTemp->pNext->b_addr == b_addr)
{
BTH_CONNECTION_HOLDER *pDel = pTemp;
pPrev->pNext = pTemp->pNext;
delete pDel;
hRes = S_OK;
break;
}
pPrev = pTemp;
pTemp = pTemp->pNext;
}
return hRes;
}
HRESULT STDMETHODCALLTYPE
CBTHTransportSocket::Listen(LPTRANSPORTCONNECTION *ppConnection)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CBTHTransportSocket::Listen()\n"));
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE
CBTHTransportSocket::Connect(LPPROPERTYBAG2 pDeviceProps,DWORD dwCapability, LPTRANSPORTCONNECTION * ppConnection)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CBTHTransportSocket::Connect()\n"));
PREFAST_ASSERT(pDeviceProps);
*ppConnection = NULL;
VARIANT DeviceVar;
VARIANT NameVar;
VARIANT Channel;
HRESULT hr = E_FAIL;
SOCKET sMySock = INVALID_SOCKET;
BTH_CONNECTION_HOLDER *pTemp = NULL;
VariantInit(&DeviceVar);
VariantInit(&NameVar);
VariantInit(&Channel);
CCritSection TransportCS(&g_TransportSocketCS);
if( FAILED(pDeviceProps->Read(c_szDevicePropAddress, &DeviceVar, 0)) ||
FAILED(pDeviceProps->Read(c_szPort, &Channel, 0))
)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - BT] ERROR - not enough params to connect\n"));
hr = E_FAIL;
goto Done;
}
if(FAILED(pDeviceProps->Read(c_szDevicePropName, &NameVar, 0)))
{
NameVar.vt = VT_BSTR;
NameVar.bstrVal = SysAllocString(L"UNKNOWN_BT_NAME");
}
//make sure the params are of the right type
if(!(VT_I4 == V_VT(&Channel) &&
VT_BSTR == V_VT(&NameVar) &&
VT_BSTR == V_VT(&DeviceVar)))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - BT] a parameter is of the wrong type!\n"));
hr = E_FAIL;
goto Done;
}
TransportCS.Lock();
//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)
{
BT_ADDR TestBTA;
if(CObexBTHTransport::GetBA(DeviceVar.bstrVal, &TestBTA) &&
pTemp->b_addr == TestBTA)
{
//get a copy of the id for our records
b_addr = pTemp->b_addr;
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - BT] -----> reusing connection!\n"));
(*ppConnection) = pTemp->pItem;
(*ppConnection)->AddRef();
hr = S_OK;
goto Done;
}
pTemp = pTemp->pNext;
}
//since we DONT have the instance, make one create a socket
sMySock = socket(AF_BT, SOCK_STREAM, BTHPROTO_RFCOMM);
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX-BT] -->Created Socket\n"));
if(INVALID_SOCKET == sMySock) {
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX - BT] ERROR - invalid socket\n"));
SetLastError (ERROR_DEVICE_NOT_CONNECTED);
hr = E_FAIL;
goto Done;
}
//information on the BTH to connect to
SOCKADDR_BTH DestSockAddr;
memset(&DestSockAddr, 0, sizeof(SOCKADDR_BTH));
//move in the appropriate values (telling the service name and address family)
DestSockAddr.addressFamily = AF_BT;
// move in the device id for the selected device
if(!CObexBTHTransport::GetBA(DeviceVar.bstrVal, &DestSockAddr.btAddr))
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX-BT] Error getting BT_ADDR from BSTR!\n"));
hr = E_FAIL;
goto Done;
}
b_addr = DestSockAddr.btAddr;
DestSockAddr.port = Channel.lVal;
//connect to that device
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX-BT] Connecting to: %s:%d\n", DeviceVar.bstrVal, Channel.lVal));
if (SOCKET_ERROR == connect(sMySock, (const struct sockaddr *) &DestSockAddr,
sizeof(SOCKADDR_BTH))) {
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE, (L"[OBEX-BT] Error connecting: 0x%x\n", WSAGetLastError()));
hr = E_FAIL;
goto Done;
}
//if we are here, we dont have a connecction, so make one
*ppConnection = new CObexTransportConnection(this, NameVar.bstrVal, sMySock);
if( !(*ppConnection) )
{
hr = E_OUTOFMEMORY;
goto Done;
}
//create and insert a new connection holder
pTemp = new BTH_CONNECTION_HOLDER();
if( !pTemp )
{
delete *ppConnection;
*ppConnection = NULL;
hr = E_OUTOFMEMORY;
goto Done;
}
pTemp->pItem = *ppConnection;
pTemp->b_addr = b_addr;
pTemp->pNext = g_pConnectionList;
g_pConnectionList = pTemp;
hr = S_OK;
Done:
if(FAILED(hr) && INVALID_SOCKET != sMySock) {
closesocket(sMySock);
}
VariantClear(&DeviceVar);
VariantClear(&NameVar);
VariantClear(&Channel);
return hr;
}
HRESULT STDMETHODCALLTYPE
CBTHTransportSocket::GetProperties(LPPROPERTYBAG2 * ppListenProps)
{
return E_NOTIMPL;
}
ULONG STDMETHODCALLTYPE
CBTHTransportSocket::AddRef()
{
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CBTHTransportSocket::AddRef()\n"));
return InterlockedIncrement((LONG *)&_refCount);
}
ULONG STDMETHODCALLTYPE
CBTHTransportSocket::Release()
{
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CBTHTransportSocket::Release()\n"));
SVSUTIL_ASSERT(_refCount != 0xFFFFFFFF);
ULONG ret = InterlockedDecrement((LONG *)&_refCount);
if(!ret)
delete this;
return ret;
}
HRESULT STDMETHODCALLTYPE
CBTHTransportSocket::QueryInterface(REFIID riid, void** ppv)
{
DEBUGMSG(OBEX_TRANSPORTSOCKET_ZONE,(L"CBTHTransportSocket::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 + -