Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

599 lines
13 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: sock.cxx
//
//--------------------------------------------------------------------------
#include "precomp.h"
#include <malloc.h>
#include <mswsock.h>
#include <irmonftp.h>
#define dwENUM_REST 100 // time to rest between successive
// IRLMP_ENUMDEVICES queries
#define dwCONN_REST 100 // time to rest between successive
// connect() calls
#define MAX_DEVICE_COUNT 20
#define nMAX_TARGETS 8
#define nMAX_ENUM_RETRIES 100
#define nMAX_CONN_RETRIES 10
#define nSOCKET_MAXCONN 8
#define dwWRITEABLE_TIMEOUT 10000
#define SOCKET_RECEIVE_TIMEOUT (1000 * 60 * 10)
#define SINGLE_INST_MUTEX L"IRMutex_1A8452B5_A526_443C_8172_D29657B89F57"
FILE_TRANSFER*
InitializeSocket(
char ServiceName[]
)
{
int nSize;
INT nRet;
WORD wWinsockVersion;
WSADATA wsadata;
SOCKET listenSocket=INVALID_SOCKET;
FILE_TRANSFER* Transfer;
HANDLE FileMapping;
PVOID FileView=NULL;
LPWSAPROTOCOL_INFO ProtocolInfo;
wWinsockVersion = MAKEWORD( 2, 0 );
nRet = WSAStartup( wWinsockVersion, &wsadata );
if ( 0 != nRet ) {
goto lErr;
}
FileMapping=OpenFileMapping(
FILE_MAP_READ,
FALSE,
TEXT("Global\\Irmon-shared-memory")
);
if (FileMapping != NULL) {
FileView=MapViewOfFile(
FileMapping,
FILE_MAP_READ,
0,
0,
0
);
CloseHandle(FileMapping);
} else {
DbgPrint("irftp: could not open shared mem %d\n",GetLastError());
}
ProtocolInfo=(LPWSAPROTOCOL_INFO)FileView;
if (ProtocolInfo != NULL) {
if (lstrcmpA(ServiceName,SERVICE_NAME_2) == 0) {
ProtocolInfo++;
}
listenSocket=WSASocket(FROM_PROTOCOL_INFO,FROM_PROTOCOL_INFO ,FROM_PROTOCOL_INFO ,ProtocolInfo, NULL, 0);
UnmapViewOfFile(FileView);
}
if (listenSocket == INVALID_SOCKET) {
//
// establish listen socket
//
SOCKADDR_IRDA saListen;
DbgPrint("irftp: WSASocketFailed %d\n",WSAGetLastError());
listenSocket = socket( AF_IRDA, SOCK_STREAM, 0 );
if( INVALID_SOCKET == listenSocket ) {
UINT uErr = (UINT)WSAGetLastError();
DbgLog3( SEV_ERROR, "listen on %s socket() failed with %d [0x%x]", ServiceName, uErr, uErr);
goto lErr;
}
DbgLog2( SEV_INFO, "listen on %s socket ID: %ld", ServiceName, (DWORD)listenSocket );
saListen.irdaAddressFamily = AF_IRDA;
*(UINT *)saListen.irdaDeviceID = 0;
StringCbCopyA(saListen.irdaServiceName,sizeof(saListen.irdaServiceName), ServiceName );
nRet = bind( listenSocket, (const struct sockaddr *)&saListen, sizeof(saListen) );
if( SOCKET_ERROR == nRet ) {
UINT uErr = (UINT)WSAGetLastError();
DbgLog3( SEV_ERROR, "listen on %s setsockopt failed with %d [0x%x]", ServiceName, uErr, uErr);
closesocket(listenSocket);
goto lErr;
}
nRet = listen( listenSocket, nSOCKET_MAXCONN );
if( SOCKET_ERROR == nRet ) {
UINT uErr = (UINT)WSAGetLastError();
DbgLog3( SEV_ERROR, "listen on %s listen() failed with %d [0x%x]", ServiceName, uErr, uErr);
closesocket(listenSocket);
goto lErr;
}
} else {
}
Transfer=ListenForTransfer(listenSocket,TYPE_IRDA);
if (Transfer == NULL) {
closesocket(listenSocket);
}
return Transfer;
lErr:
return NULL;
}
DWORD
FILE_TRANSFER::Sock_EstablishConnection(
DWORD dwDeviceID,
OBEX_DEVICE_TYPE DeviceType
)
{
FILE_TRANSFER * transfer;
_state = CONNECTING;
if (DeviceType == TYPE_IRDA) {
SOCKADDR_IRDA saRemote;
saRemote.irdaAddressFamily = AF_IRDA;
*(UINT *)saRemote.irdaDeviceID = dwDeviceID;
StringCbCopyA(saRemote.irdaServiceName,sizeof(saRemote.irdaServiceName), SERVICE_NAME_1 );
if ( 0 == connect( _socket, (const struct sockaddr *) &saRemote, sizeof(saRemote))) {
return 0;
}
StringCbCopyA(saRemote.irdaServiceName,sizeof(saRemote.irdaServiceName), SERVICE_NAME_2 );
if ( 0 == connect( _socket, (const struct sockaddr *) &saRemote, sizeof(saRemote))) {
return 0;
}
} else {
sockaddr_in Address;
ZeroMemory(&Address,sizeof(Address));
Address.sin_family=AF_INET;
Address.sin_port=650;
Address.sin_addr.S_un.S_addr=dwDeviceID;
if ( 0 == connect( _socket, (const struct sockaddr *) &Address, sizeof(Address))) {
return 0;
}
}
return WSAGetLastError();
}
DWORD
FILE_TRANSFER::SyncAccept(
VOID
)
{
DWORD status = 0;
DWORD bytes = 0;
DWORD dwEventStatus = 0;
EVENT_LOG EventLog(WS_EVENT_SOURCE,&dwEventStatus);
int size;
SOCKADDR_IRDA s;
sockaddr_in Address;
BOOL bResult;
status = 0;
while (!m_StopListening) {
_state = ACCEPTING;
_dataXferRecv.dwFileSent = 0;
if (m_DeviceType == TYPE_IRDA) {
size = sizeof(SOCKADDR_IRDA);
_socket = accept( m_ListenSocket, (sockaddr *) &s, &size );
} else {
size=sizeof(Address);
_socket = accept( m_ListenSocket, (sockaddr *) &Address, &size );
}
if ( INVALID_SOCKET == _socket ) {
if (!m_StopListening) {
//
// the thread has been request to stop listening for incoming connection
//
if (!dwEventStatus) {
EventLog.ReportError(CAT_IRXFER, MC_IRXFER_LISTEN_FAILED, WSAGetLastError());
}
Sleep(1 * 1000);
}
continue;
}
//
// we are handling an incoming connection, don't suspend on timeout during the transfer
//
SetThreadExecutionState( ES_SYSTEM_REQUIRED | ES_CONTINUOUS );
_state = READING;
//
// Record the machine name for later use.
//
RecordDeviceName( &s );
_fCancelled=FALSE;
do {
if (_fCancelled) {
#if DBG
DbgPrint("irmon: receive canceled\n");
#endif
status = ERROR_CANCELLED;
break;
}
DWORD BytesToRead=Store_GetSize(_dataRecv.lpStore)-Store_GetDataUsed(_dataRecv.lpStore);
bytes = recv( _socket, (char *) _buffer, BytesToRead, 0 );
if (SOCKET_ERROR == bytes) {
if (_dataRecv.state == osCONN) {
//
// workaround for nokia cell phones that drop the irda connection after sending
// the file. If we are not in the middle of a file transfer then just left it close
// normally
//
status = 0;
break;
} else {
if (!dwEventStatus) {
EventLog.ReportError(CAT_IRXFER, MC_IRXFER_RECV_FAILED, WSAGetLastError());
}
}
status = GetLastError();
break;
}
if (0 == bytes) {
status = 0;
break;
}
HANDLE MutexHandle;
MutexHandle=OpenMutex(SYNCHRONIZE,FALSE,SINGLE_INST_MUTEX);
if (MutexHandle == NULL) {
//
// start the ui app, so we have something to rpc to.
//
LaunchUi( NULL);
} else {
//
// The app is already running
//
CloseHandle(MutexHandle);
}
DbgLog1(SEV_FUNCTION,"SyncAccept(): Recv: %d bytes", bytes);
ASSERT( _guard == GUARD_MAGIC );
_dataXferRecv.dwFileSent += bytes;
Obex_ReceiveData( xferRECV, _buffer, bytes );
while (Obex_ConsumePackets( xferRECV, &status )) {
if (status != ERROR_SUCCESS) {
break;
}
}
if (status == 0xffffffff) {
status = 0;
}
} while (status == STATUS_SUCCESS);
DbgLog1( status ? SEV_ERROR : SEV_INFO, "Obex_Consume returned %d", status);
//
// Clean up OBEX data.
//
HandleClosure( status );
status = 0;
if (_socket != INVALID_SOCKET) {
closesocket(_socket);
_socket=INVALID_SOCKET;
}
//
// done with this connection, allow idle suspend
//
SetThreadExecutionState( ES_CONTINUOUS );
}
#if DBG
DbgPrint("IRMON: accept thread exiting\n");
#endif
DecrementRefCount();
return 0;
}
error_status_t
FILE_TRANSFER::Sock_CheckForReply(
long timeout
)
{
int bytes;
long seconds;
long msec;
fd_set FdSet;
timeval BerkeleyTimeout;
FD_ZERO( &FdSet );
FD_SET( _socket, &FdSet );
if (timeout == TIMEOUT_INFINITE) {
int Result=0;
while (Result == 0) {
msec = 0;
seconds = 5;
BerkeleyTimeout.tv_sec = seconds;
BerkeleyTimeout.tv_usec = msec * 1000;
Result=select(0, &FdSet, NULL, NULL, &BerkeleyTimeout);
// if (0 == Result) {
//
// return ERROR_TIMEOUT;
// }
if (_fCancelled) {
return ERROR_OPERATION_ABORTED;
}
}
} else {
msec = timeout % 1000;
seconds = timeout / 1000;
BerkeleyTimeout.tv_sec = seconds;
BerkeleyTimeout.tv_usec = msec * 1000;
DbgLog1(SEV_INFO, "sock_checkForReply: timeout %ld", timeout);
if (0 == select(0, &FdSet, NULL, NULL, &BerkeleyTimeout)) {
return ERROR_TIMEOUT;
}
}
bytes = recv( _socket, (char *) _buffer, cbSOCK_BUFFER_SIZE, 0 );
if (bytes == SOCKET_ERROR) {
return GetLastError();
} else if (bytes == 0) {
return WSAECONNRESET;
} else {
DbgLog1(SEV_FUNCTION,"Sock_CheckForReply(): Recv: %d bytes", bytes);
Obex_ReceiveData( xferSEND, _buffer, bytes );
return 0;
}
return 0;
}
DWORD
AcceptThreadStartRoutine(
PVOID Context
)
{
FILE_TRANSFER * transfer=(FILE_TRANSFER *)Context;
return transfer->SyncAccept();
}
FILE_TRANSFER *
ListenForTransfer(
SOCKET ListenSocket,
OBEX_DEVICE_TYPE DeviceType
)
{
FILE_TRANSFER * transfer;
BOOL bResult;
ULONG ThreadId;
HANDLE ThreadHandle;
transfer = new FILE_TRANSFER;
if (transfer == NULL) {
return NULL;
}
bResult=transfer->Xfer_Init(0, 0, dialWin95,DeviceType,FALSE,ListenSocket);
if (!bResult) {
delete transfer;
return NULL;
}
ThreadHandle=CreateThread(
NULL,
80000,
AcceptThreadStartRoutine,
(PVOID) transfer,
STACK_SIZE_PARAM_IS_A_RESERVATION,
&ThreadId
);
if (ThreadHandle == NULL) {
delete transfer;
return NULL;
}
CloseHandle(ThreadHandle);
return transfer;
}
void
FILE_TRANSFER::HandleClosure(
DWORD error
)
{
if (!error)
{
_state = CLOSING;
}
if (_state == ACCEPTING ||
_state == READING )
{
SendReplyWin32( 0, error );
}
if (_fInUiReceiveList)
{
_fInUiReceiveList = FALSE;
_ReceiveFinished( rpcBinding, _cookie, error );
}
if (error)
{
Xfer_FileAbort(); // just in case a file is being received
}
Obex_Reset(); // reset the state machine
}
error_status_t
FILE_TRANSFER::Sock_Request( LPVOID lpvData, DWORD dwDataSize )
{
if (send( _socket, (char *) lpvData, dwDataSize, 0) != (int) dwDataSize)
{
return GetLastError();
}
DbgLog1(SEV_FUNCTION,"Sock_Request(): Send: %d bytes", dwDataSize);
return 0;
}
error_status_t
FILE_TRANSFER::Sock_Respond(
LPVOID lpvData,
DWORD dwDataSize
)
{
if (send( _socket, (char *) lpvData, dwDataSize, 0) != (int) dwDataSize)
{
return GetLastError();
}
DbgLog1(SEV_FUNCTION,"Sock_Respond(): Send: %d bytes", dwDataSize);
return 0;
}