📄 obextransportconnection.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 "ObexTransportConnection.h"
#include "ObexDevice.h"
#include "PropertyBag.h"
#include "obexstream.h"
DWORD g_ResponseTimeout;
int RecvHelper(SOCKET s, unsigned char *buf, int len, int flags);
extern CRITICAL_SECTION g_TransportSocketCS;
CObexTransportConnection::CObexTransportConnection(IObexTransportSocket *_pSocket, LPTSTR pszName, SOCKET _sMySock) :
_refCount(1),
sMySock(_sMySock),
pSocket(_pSocket),
fHasClosed(FALSE)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::CObexTransportConnection()\n"));
pSocket->AddRef();
pbstrName = SysAllocString(pszName);
pbstrNameField = SysAllocString(L"Name");
nameVar.bstrVal = pbstrName;
}
CObexTransportConnection::~CObexTransportConnection()
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::~CObexTransportConnection()\n"));
if(pbstrName)
SysFreeString(pbstrName);
if(pbstrNameField)
SysFreeString(pbstrNameField);
if(sMySock != INVALID_SOCKET)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE, (L"CObexTransportConnection::~CObexTransportConnection() -->Closing socket\n"));
closesocket(sMySock);
sMySock = INVALID_SOCKET;
}
pSocket->Close();
pSocket->Release();
}
HRESULT STDMETHODCALLTYPE
CObexTransportConnection::Close()
{
/*DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::Close()\n"));
if(pSocket && !fHasClosed)
{
fHasClose = TRUE;
pSocket->Close();
} */
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObexTransportConnection::Read(ULONG ulNumBytes, BYTE *pPacket, ULONG *pulBytesRead, DWORD dwTimeout)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::Read()\n"));
CCritSection TransportCS(&g_TransportSocketCS);
TransportCS.Lock();
*pPacket = 0;
*pulBytesRead = 0;
if(INVALID_SOCKET == sMySock || ulNumBytes < 3)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::Read() -- invalid socket or requesting fewer thn 3 bytes\n"));
return E_FAIL;
}
WORD wPacketSize;
//get the opcode and packetsize
int iRet = RecvHelper(sMySock, pPacket, 3, 0);
if(iRet == 0 || iRet!= 3 || iRet == SOCKET_ERROR)
{
closesocket(sMySock);
sMySock=INVALID_SOCKET;
DEBUGMSG(OBEX_OBEXDEVICE_ZONE, (L"Socket error recieving...\n"));
return E_FAIL;
}
//get the opcode and the header size
((char *)&wPacketSize)[0] = pPacket[1];
((char *)&wPacketSize)[1] = pPacket[2];
wPacketSize = ntohs(wPacketSize);
SVSUTIL_ASSERT(wPacketSize <= g_uiMaxFileChunk);
if(ulNumBytes < wPacketSize)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::Read() -- invalid packet size!\n"));
return E_FAIL;
}
if(wPacketSize > 3)
{
//fetch the remainder of the packet
int retVal = RecvHelper(sMySock, pPacket+3, wPacketSize - 3, 0);
SVSUTIL_ASSERT(retVal == wPacketSize - 3);
if(retVal == 0 || retVal != wPacketSize-3 || retVal == SOCKET_ERROR)
{
closesocket(sMySock);
sMySock=INVALID_SOCKET;
DEBUGMSG(OBEX_OBEXDEVICE_ZONE, (L"CObexTransportConnection::Read() Socket error recieving...\n"));
return E_FAIL;
}
}
//do a quick test to make sure nothing is on the wire
#ifdef OBEX_NETWORK_SANITY_CHECKS
FD_SET fd;
FD_ZERO (&fd);
FD_SET (sMySock, &fd);
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
int val = select (0, &fd, NULL, NULL, &tv);
SVSUTIL_ASSERT(val == 0);
DEBUGMSG(OBEX_OBEXDEVICE_ZONE, (L">Nothing on wire... life is good\n"));
#endif
*pulBytesRead = wPacketSize;
return S_OK;
}
HRESULT STDMETHODCALLTYPE
CObexTransportConnection::Write(ULONG wPacketSize, BYTE *pbData)
{
CCritSection TransportCS(&g_TransportSocketCS);
TransportCS.Lock();
if(INVALID_SOCKET == sMySock)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::Write() -- invalid socket\n"));
return E_FAIL;
}
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE, (L"CObexTransportConnection::Write\n"));
HRESULT hRet = S_OK;
char *pPacketTemp = (char *)pbData;
while(wPacketSize)
{
int retCode = send(sMySock, pPacketTemp, wPacketSize, 0);
if(retCode == 0 || retCode == SOCKET_ERROR)
{
closesocket(sMySock);
sMySock = INVALID_SOCKET;
DEBUGMSG(OBEX_OBEXDEVICE_ZONE, (L"Error(0x%08x)--send failed\n", WSAGetLastError()));
hRet = E_FAIL;
break;
}
pPacketTemp += retCode;
wPacketSize -= retCode;
}
return hRet;
}
/******************************************************************************/
/* NOTE: VERY IMPORTANT! --- this MUST be under a critical section
/* We do a write of a packet, then a read --- we MUST do both under
/* a crit section since the received packet doesnt have a connection ID
/******************************************************************************/
HRESULT STDMETHODCALLTYPE
CObexTransportConnection::SendRecv(ULONG ulSendBytes, BYTE *pbSendData,
ULONG ulRecvBytes, BYTE *pbRecvData,
ULONG *pulBytesRecvd, DWORD dwRecvTimeout)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::SendRecv()\n"));
CCritSection TransportCS(&g_TransportSocketCS);
TransportCS.Lock();
//send off the packet
HRESULT hRet;
hRet = Write(ulSendBytes, pbSendData);
if(SUCCEEDED(hRet))
{
hRet = Read(ulRecvBytes, pbRecvData, pulBytesRecvd, INFINITE);
if(FAILED(hRet))
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::SendRecv -- Read FAILED\n"));
}
}
else
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::SendRecv -- Write FAILED\n"));
}
return hRet;
}
HRESULT STDMETHODCALLTYPE
CObexTransportConnection::EnumProperties(LPPROPERTYBAG2 *pprops)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::EnumProperties()\n"));
CPropertyBag *pProps = new CPropertyBag();
if(NULL == pProps)
return E_OUTOFMEMORY;
//create a name field and save the property
pProps->Write(pbstrNameField, &nameVar);
*pprops = pProps;
return S_OK;
}
ULONG STDMETHODCALLTYPE
CObexTransportConnection::AddRef()
{
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CObexTransportConnection::AddRef()\n"));
return InterlockedIncrement((LONG *)&_refCount);
}
ULONG STDMETHODCALLTYPE
CObexTransportConnection::Release()
{
DEBUGMSG(OBEX_ADDREFREL_ZONE,(L"CObexTransportConnection::Release()\n"));
SVSUTIL_ASSERT(_refCount != 0xFFFFFFFF && _refCount != 0);
ULONG ret = InterlockedDecrement((LONG *)&_refCount);
if(!ret)
delete this;
return ret;
}
HRESULT STDMETHODCALLTYPE
CObexTransportConnection::QueryInterface(REFIID riid, void** ppv)
{
DEBUGMSG(OBEX_TRASPORTCONNECTION_ZONE,(L"CObexTransportConnection::QueryInterface()\n"));
if(!ppv)
return E_POINTER;
if(riid == IID_IObexTransportConnection)
*ppv = static_cast<IObexTransportConnection*>(this);
else
return *ppv = 0, E_NOINTERFACE;
return AddRef(), S_OK;
}
int RecvHelper(SOCKET s, unsigned char *buf, int len, int flags)
{
ASSERT(INVALID_SOCKET != s);
int iTimeLeft = g_ResponseTimeout;
int received = 0;
int retValue = SOCKET_ERROR;
DEBUGMSG(OBEX_OBEXDEVICE_ZONE,(L"CObexDevice::RecvHelper()\n"));
SVSUTIL_ASSERT(s != INVALID_SOCKET && buf);
DWORD dwNow = GetTickCount ();
FD_SET fd;
FD_ZERO (&fd);
FD_SET (s, &fd);
#if defined(DEBUG) || defined(_DEBUG)
UCHAR *pBufOrig = buf;
#endif
//while we still need data, try to get it
while(received < len && iTimeLeft >= 0)
{
int iJustRead;
timeval tv;
tv.tv_sec = iTimeLeft;
tv.tv_usec = 0;
if (1 != select (0, &fd, NULL, NULL, &tv))
{
retValue = SOCKET_ERROR;
goto recvHelperDone;
}
//if there is something available, fetch it
if(FD_ISSET(s, &fd))
{
iJustRead = recv(s, (char *)buf, len - received, flags);
}
else
{
DEBUGMSG(OBEX_OBEXDEVICE_ZONE, (L"[OBEX] recv timed out!\n"));
retValue = SOCKET_ERROR;
goto recvHelperDone;
}
//either the socket closed, or error'ed... so return that
if(iJustRead == 0 || iJustRead == SOCKET_ERROR)
{
retValue = iJustRead;
goto recvHelperDone;
}
buf += iJustRead;
received += iJustRead;
iTimeLeft = g_ResponseTimeout - (GetTickCount () - dwNow) / 1000;
}
#if defined(DEBUG) || defined(_DEBUG)
void DumpBuff (unsigned char *lpBuffer, unsigned int cBuffer);
DEBUGMSG(OBEX_DUMP_PACKETS_ZONE, (L"Recv'ed -------------------------------"));
DumpBuff (pBufOrig, received);
#endif
SVSUTIL_ASSERT(iTimeLeft);
SVSUTIL_ASSERT(received == len);
DEBUGMSG(OBEX_OBEXDEVICE_ZONE, (L"RECV'ed: %d bytes\n", received));
retValue = received;
recvHelperDone:
return retValue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -