windows-nt/Source/XPSP1/NT/net/irda/irtranp/io.cpp
2020-09-26 16:20:57 +08:00

368 lines
9.8 KiB
C++

//--------------------------------------------------------------------
// Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
//
// io.cpp
//
// Author:
//
// Edward Reus (edwardr) 02-27-98 Initial coding.
//
//--------------------------------------------------------------------
#include "precomp.h"
#ifdef DBG_MEM
static LONG g_lCIoPacketCount = 0;
#endif
//--------------------------------------------------------------------
// CIOPACKET::CIOPACKET()
//
//--------------------------------------------------------------------
CIOPACKET::CIOPACKET()
{
m_dwKind = PACKET_KIND_LISTEN;
m_hIoCompletionPort = INVALID_HANDLE_VALUE;
m_ListenSocket = INVALID_SOCKET;
m_Socket = INVALID_SOCKET;
m_hFile = INVALID_HANDLE_VALUE;
m_pLocalAddr = 0;
m_pFromAddr = 0;
m_pAcceptBuffer = 0;
m_pReadBuffer = 0;
m_pvWritePdu = 0;
m_dwReadBufferSize = 0;
}
//--------------------------------------------------------------------
// CIOPACKET::~CIOPACKET()
//
//--------------------------------------------------------------------
CIOPACKET::~CIOPACKET()
{
// NOTE: Don't free m_pLocalAddr or m_pFromAddr, they just point
// into m_pAcceptBuffer.
if (m_pAcceptBuffer)
{
FreeMemory(m_pAcceptBuffer);
}
if (m_pReadBuffer)
{
FreeMemory(m_pReadBuffer);
}
// NOTE: Don't delete the write PDU (m_pvWritePdu), its free'd by
// somebody else (when the IO completes)...
}
//------------------------------------------------------------------------
// CIOPACKET::operator new()
//
//------------------------------------------------------------------------
void *CIOPACKET::operator new( IN size_t Size )
{
void *pObj = AllocateMemory(Size);
#ifdef DBG_MEM
if (pObj)
{
InterlockedIncrement(&g_lCIoPacketCount);
}
DbgPrint("new CIOPACKET: Count: %d\n",g_lCIoPacketCount);
#endif
return pObj;
}
//------------------------------------------------------------------------
// CIOPACKET::operator delete()
//
//------------------------------------------------------------------------
void CIOPACKET::operator delete( IN void *pObj,
IN size_t Size )
{
if (pObj)
{
DWORD dwStatus = FreeMemory(pObj);
#ifdef DBG_MEM
if (dwStatus)
{
DbgPrint("IrXfer: IrTran-P: CIOPACKET::delete: FreeMemory Failed: %d\n",dwStatus);
}
InterlockedDecrement(&g_lCIoPacketCount);
if (g_lCIoPacketCount < 0)
{
DbgPrint("IrXfer: IrTran-P: CIOPACKET::delete Count: %d\n",
g_lCIoPacketCount);
}
#endif
}
}
//--------------------------------------------------------------------
// CIOPACKET::Initialize()
//
//--------------------------------------------------------------------
DWORD CIOPACKET::Initialize( IN DWORD dwKind,
IN SOCKET ListenSocket,
IN SOCKET Socket,
IN HANDLE hIoCP )
{
DWORD dwStatus = NO_ERROR;
m_dwKind = dwKind;
m_hIoCompletionPort = hIoCP;
if (dwKind == PACKET_KIND_LISTEN)
{
// The accept buffer needs to be large enough to hold
// the "from" and "to" addresses:
m_pAcceptBuffer = AllocateMemory(2*(16+sizeof(SOCKADDR_IRDA)));
if (!m_pAcceptBuffer)
{
return ERROR_IRTRANP_OUT_OF_MEMORY;
}
}
m_ListenSocket = ListenSocket;
m_Socket = Socket;
return dwStatus;
}
//--------------------------------------------------------------------
// CIOPACKET::PostIoListen()
//
//--------------------------------------------------------------------
DWORD CIOPACKET::PostIoListen()
{
DWORD dwStatus = NO_ERROR;
DWORD dwBytes;
HANDLE hIoCP;
m_Socket = WSASocketW( AF_IRDA,
SOCK_STREAM,
IPPROTO_IP,
0,
0,
WSA_FLAG_OVERLAPPED );
if (m_Socket == INVALID_SOCKET)
{
dwStatus = WSAGetLastError();
return dwStatus;
}
hIoCP = CreateIoCompletionPort( (void*)m_Socket,
m_hIoCompletionPort,
m_Socket,
0 );
if (!hIoCP)
{
dwStatus = GetLastError();
#ifdef DBG_ERROR
DbgPrint("CIOPACKET::PostIoListen(): CreateIoCompletionPort() failed: %d\n",dwStatus);
#endif
closesocket(m_Socket);
m_Socket = INVALID_SOCKET;
return dwStatus;
}
memset(&m_Overlapped,0,sizeof(m_Overlapped));
if (!AcceptEx(m_ListenSocket,
m_Socket,
m_pAcceptBuffer,
0,
16 + sizeof(SOCKADDR_IRDA),
16 + sizeof(SOCKADDR_IRDA),
&dwBytes, // Never actually used in this case...
&m_Overlapped ))
{
// This is the normal execution path, with dwStatus == ERROR_IO_PENDING
dwStatus = WSAGetLastError();
if (dwStatus == ERROR_IO_PENDING)
{
dwStatus = NO_ERROR;
}
}
else
{
// Should get here only if a client is trying to connect just as
// the AcceptEx() is called...
dwStatus = NO_ERROR;
}
#ifdef DBG_IO
DbgPrint("CIOPACKET::PostIoListen(): AcceptEx(): Socket: %d\n",
m_ListenSocket );
#endif
return dwStatus;
}
//--------------------------------------------------------------------
// CIOPACKET::PostIoRead()
//
//--------------------------------------------------------------------
DWORD CIOPACKET::PostIoRead()
{
DWORD dwStatus = NO_ERROR;
DWORD dwBytes;
if (!m_pReadBuffer)
{
m_pReadBuffer = AllocateMemory(DEFAULT_READ_BUFFER_SIZE);
m_dwReadBufferSize = DEFAULT_READ_BUFFER_SIZE;
if (!m_pReadBuffer)
{
return ERROR_IRTRANP_OUT_OF_MEMORY;
}
}
memset(&m_Overlapped,0,sizeof(m_Overlapped));
BOOL b = ReadFile( (HANDLE)m_Socket,
m_pReadBuffer,
m_dwReadBufferSize,
0, // Can be zero for overlapped IO.
&m_Overlapped );
if (!b)
{
dwStatus = GetLastError();
if ((dwStatus == ERROR_HANDLE_EOF)||(dwStatus == ERROR_IO_PENDING))
{
dwStatus = NO_ERROR;
}
}
#ifdef DBG_IO
DbgPrint("CIOPACKET::PostIoListen(): ReadFile(): Socket: %d\n",
m_Socket );
#endif
return dwStatus;
}
//--------------------------------------------------------------------
// CIOPACKET::PostIoWrite()
//
//--------------------------------------------------------------------
DWORD CIOPACKET::PostIoWrite( IN void *pvBuffer,
IN DWORD dwBufferSize,
IN DWORD dwOffset )
{
DWORD dwStatus = NO_ERROR;
DWORD dwBytes;
HANDLE hFile;
memset(&m_Overlapped,0,sizeof(m_Overlapped));
if (m_dwKind == PACKET_KIND_WRITE_SOCKET)
{
hFile = (HANDLE)m_Socket;
}
else if (m_dwKind == PACKET_KIND_WRITE_FILE)
{
hFile = m_hFile;
m_Overlapped.Offset = dwOffset;
}
else
{
#ifdef DBG_ERROR
DbgPrint("CIOPACKET::PostIoWrite(): Invalid m_dwKind: %d.\n",m_dwKind);
#endif
dwStatus = ERROR_INVALID_PARAMETER;
}
BOOL b = WriteFile( hFile,
pvBuffer,
dwBufferSize,
0, // Can be zero for overlapped IO.
&m_Overlapped );
if (!b)
{
dwStatus = GetLastError();
if (dwStatus == ERROR_IO_PENDING)
{
dwStatus = NO_ERROR;
}
}
#ifdef DBG_IO
DbgPrint("CIOPACKET::PostIoWrite(): WriteFile(): Handle: %d Bytes: %d\n",
hFile, dwBufferSize );
#endif
return dwStatus;
}
//--------------------------------------------------------------------
// CIOPACKET::PostIo()
//
//--------------------------------------------------------------------
DWORD CIOPACKET::PostIo()
{
DWORD dwStatus = NO_ERROR;
DWORD dwBytes;
if (m_dwKind == PACKET_KIND_LISTEN)
{
dwStatus = PostIoListen();
}
else if (m_dwKind == PACKET_KIND_READ)
{
dwStatus = PostIoRead();
}
else
{
// Packet writes back to the camera (via socket) and writes to
// the image (jpeg) file are posted only when data is ready to
// send...
ASSERT( (m_dwKind == PACKET_KIND_WRITE_SOCKET)
|| (m_dwKind == PACKET_KIND_WRITE_FILE) );
}
return dwStatus;
}
//--------------------------------------------------------------------
// CIOPACKET::GetSockAddrs()
//
// NOTE: Don't free the memory addresses returned, they point into
// m_AcceptBuffer.
//--------------------------------------------------------------------
void CIOPACKET::GetSockAddrs( OUT SOCKADDR_IRDA **ppLocalAddr,
OUT SOCKADDR_IRDA **ppFromAddr )
{
int iLocalAddrSize;
int iFromAddrSize;
if (!m_pLocalAddr)
{
GetAcceptExSockaddrs(m_pAcceptBuffer,
0,
16 + sizeof(SOCKADDR_IRDA),
16 + sizeof(SOCKADDR_IRDA),
(struct sockaddr **)&m_pLocalAddr,
&iLocalAddrSize,
(struct sockaddr **)&m_pFromAddr,
&iFromAddrSize );
}
*ppLocalAddr = m_pLocalAddr;
*ppFromAddr = m_pFromAddr;
}