//
// 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.
//
/*****************************************************************************/
/**                            Microsoft Windows                            **/
/*****************************************************************************/

/*

comm.c

communications related winsock2 functions


FILE HISTORY:
	OmarM     22-Sep-2000

*/


#include "winsock2p.h"
#include <mswsock.h>
#include <perfcomm.h>

int WSAAPI WSARecv(
	SOCKET s,
	LPWSABUF lpBuffers,
	DWORD dwBufferCount,
	LPDWORD lpNumberOfBytesRecvd,
	LPDWORD lpFlags,
	LPWSAOVERLAPPED lpOverlapped,
	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE) {

	int			Err, Status;
	WsSocket	*pSock;
	WSATHREADID	WsaThreadId;

	PerfCommBegin(WINSOCK_DurRecv);

	if (! (Err = RefSocketHandle(s, &pSock))) {

		WsaThreadId.ThreadHandle = (HANDLE)GetCurrentThreadId();

		Status = pSock->pProvider->ProcTable.lpWSPRecv(pSock->hWSPSock, 
			lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, 
			lpOverlapped, lpCompletionROUTINE, &WsaThreadId, &Err);

		if (Status && ! Err)
			Err = WSASYSCALLFAILURE;

		DerefSocket(pSock);
	}

	if (Err) {
		Status = SOCKET_ERROR;
		SetLastError(Err);
		PerfCommEndError(WINSOCK_DurRecv, Err);
	} else {
		Status = 0;
		PerfCommEnd(WINSOCK_DurRecv);
	}

	return Status;

}	// WSARecv()


// WSARecvMsg
int WSPAPI WSARecvMsg (
	SOCKET s,
	LPWSAMSG lpMsg,
	LPDWORD lpNumberOfBytesRecvd,
	LPWSAOVERLAPPED lpOverlapped,
	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) {

    int			Err, Status;
	WsSocket	*pSock;
	WSATHREADID	WsaThread;

	if (! (Err = RefSocketHandle(s, &pSock))) {

		WsaThread.ThreadHandle = (HANDLE)GetCurrentThreadId();

		Status = pSock->pProvider->ProcTable.lpWSPIoctl(pSock->hWSPSock, 
				SIO_RECV_MSG, lpMsg, sizeof(*lpMsg), NULL, 
				0, lpNumberOfBytesRecvd, lpOverlapped, 
				lpCompletionRoutine, &WsaThread, &Err);

		if (Status && ! Err) {
			ASSERT(0);
			Err = WSASYSCALLFAILURE;
		}
        
		DerefSocketHandle(pSock->hSock);
	}

	if (Err) {
		SetLastError(Err);
		Status = SOCKET_ERROR;
	} else
		Status = 0;

	return Status;
} // WSARecvMsg()	


int WSAAPI recv(
	SOCKET s,
	char * buf,
	int len,
	int flags) {

	WSABUF	WsaBuf;
	DWORD	cRcvd;
	DWORD	dwFlags;
	int		Status;

	WsaBuf.len = len;
	WsaBuf.buf = buf;
	dwFlags = flags;

	Status = WSARecv(s, &WsaBuf, 1, &cRcvd, &dwFlags, NULL, NULL);

	if (!Status)
		Status = cRcvd;

	return Status;

}	// recv()


int WSAAPI WSARecvFrom(
	SOCKET s,
	LPWSABUF lpBuffers,
	DWORD dwBufferCount,
	LPDWORD lpNumberOfBytesRecvd,
	LPDWORD lpFlags,
	struct sockaddr FAR * lpFrom,
	LPINT lpFromlen,
	LPWSAOVERLAPPED lpOverlapped,
	LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionROUTINE) {

	int			Err, Status;
	WsSocket	*pSock;
	WSATHREADID	WsaThreadId;

	PerfCommBegin(WINSOCK_DurRecvFrom);

	if (! (Err = RefSocketHandle(s, &pSock))) {

		if (lpFrom) {
			if (lpFromlen)
				Err = CheckSockaddr(lpFrom, *lpFromlen);
			else
				Err = WSAEFAULT;
		}

		if (! Err ) {

			WsaThreadId.ThreadHandle = (HANDLE)GetCurrentThreadId();

			Status = pSock->pProvider->ProcTable.lpWSPRecvFrom(
				pSock->hWSPSock, lpBuffers, dwBufferCount, 
				lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, 
				lpOverlapped, lpCompletionROUTINE, &WsaThreadId, &Err);

			if (Status && ! Err)
				Err = WSASYSCALLFAILURE;
		}
		DerefSocket(pSock);
	}

	if (Err) {
		Status = SOCKET_ERROR;
		SetLastError(Err);
		PerfCommEndError(WINSOCK_DurRecvFrom, Err);
	} else {
		Status = 0;
		PerfCommEnd(WINSOCK_DurRecvFrom);
	}

	return Status;

}	// WSARecvFrom()


int WSAAPI recvfrom(
	SOCKET s,
	char * buf,
	int len,
	int flags,
	struct sockaddr FAR* from,
	int FAR* fromlen) {

	WSABUF	WsaBuf;
	DWORD	cRcvd;
	DWORD	dwFlags;
	int		Status;

	WsaBuf.len = len;
	WsaBuf.buf = buf;
	dwFlags = flags;

	Status = WSARecvFrom(s, &WsaBuf, 1, &cRcvd, &dwFlags, from, fromlen, 
		NULL, NULL);

	if (!Status)
		Status = cRcvd;

	return Status;

}	// recvfrom()


int WSAAPI WSASend(
	SOCKET		s,
	LPWSABUF	lpBuffers,
	DWORD		dwBufferCount,
	LPDWORD		lpNumberOfBytesSent,
	DWORD		dwFlags,
	LPWSAOVERLAPPED	lpOverlapped,
	LPWSAOVERLAPPED_COMPLETION_ROUTINE	lpCompletionROUTINE) {

	int			Err, Status;
	WsSocket	*pSock;
	WSATHREADID	WsaThreadId;

	PerfCommBegin(WINSOCK_DurSend);

	if (! (Err = RefSocketHandle(s, &pSock))) {

		WsaThreadId.ThreadHandle = (HANDLE)GetCurrentThreadId();

		Status = pSock->pProvider->ProcTable.lpWSPSend(pSock->hWSPSock, 
			lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, 
			lpOverlapped, lpCompletionROUTINE, &WsaThreadId, &Err);

		if (Status && ! Err)
			Err = WSASYSCALLFAILURE;

		DerefSocket(pSock);
	}

	if (Err) {
		Status = SOCKET_ERROR;
		SetLastError(Err);
		PerfCommEndError(WINSOCK_DurSend, Err);
	} else {
		Status = 0;
		PerfCommEnd(WINSOCK_DurSend);
	}

	return Status;

}	// WSASend()


int WSAAPI send(
	SOCKET	s,
	const char FAR *	buf,
	int		len,
	int		flags) {

	WSABUF	WsaBuf;
	DWORD	cSent;
	int		Status;

	WsaBuf.len = len;
	WsaBuf.buf = (char *)buf;

	Status = WSASend(s, &WsaBuf, 1, &cSent, flags, NULL, NULL);

	if (!Status)
		Status = cSent;

	return Status;

}	// send()


int WSAAPI WSASendTo(
	SOCKET			s,
	LPWSABUF		lpBuffers,
	DWORD			dwBufferCount,
	LPDWORD			lpNumberOfBytesSent,
	DWORD			dwFlags,
	const struct sockaddr FAR *	lpTo,
	INT				iToLen,
	LPWSAOVERLAPPED	lpOverlapped,
	LPWSAOVERLAPPED_COMPLETION_ROUTINE	lpCompletionROUTINE) {

	int			Err, Status;
	WsSocket	*pSock;
	WSATHREADID	WsaThreadId;

	PerfCommBegin(WINSOCK_DurSendTo);

	if (! (Err = RefSocketHandle(s, &pSock))) {

		WsaThreadId.ThreadHandle = (HANDLE)GetCurrentThreadId();

		Status = pSock->pProvider->ProcTable.lpWSPSendTo(pSock->hWSPSock, 
			lpBuffers, dwBufferCount, lpNumberOfBytesSent, dwFlags, lpTo,
			iToLen, lpOverlapped, lpCompletionROUTINE, &WsaThreadId, &Err);

		if (Status && ! Err)
			Err = WSASYSCALLFAILURE;

		DerefSocket(pSock);
	}

	if (Err) {
		Status = SOCKET_ERROR;
		SetLastError(Err);
		PerfCommEndError(WINSOCK_DurSendTo, Err);
	} else {
		Status = 0;
		PerfCommEnd(WINSOCK_DurSendTo);
	}

	return Status;

}	// WSASendTo()


int WSAAPI sendto(
	SOCKET	s,
	const char FAR *	buf,
	int		len,
	int		flags,
	const struct sockaddr FAR*	to,
	int		tolen) {

	WSABUF	WsaBuf;
	DWORD	cSent;
	int		Status;

	WsaBuf.len = len;
	WsaBuf.buf = (char *)buf;

	Status = WSASendTo(s, &WsaBuf, 1, &cSent, flags, to, tolen, NULL, NULL);

	if (!Status)
		Status = cSent;

	return Status;

}	// sendto()

