windows-nt/Source/XPSP1/NT/com/rpc/perf/raw/common/scipx.c
2020-09-26 16:20:57 +08:00

457 lines
13 KiB
C

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1994 - 1999
//
// File: scipx.c
//
//--------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////
//
// Filename: scipx.c
//
// Description: This file contains common routines for socket I/O
// routines for use with IPC raw network performance
// tests.
// This module is written using win32 API calls.
//
// Authors: Scott Holden (Translator from NT API to win32 API)
// Mahesh Keni (Mahesh wrote this application using mostly
// NT native API calls)
//
/////////////////////////////////////////////////////////////////////////
#include "rawcom.h"
#include "scipx.h"
/************************************************************************/
NTSTATUS
SCIPX_Initialize(
IN USHORT NClients, // Number of clients
IN PCHAR ServerName, // Server IP address
IN USHORT SrvCli) // server or client
{
INTEGER RetCode = 0;
WSADATA WsaData; // got from RCP prog
RetCode = WSAStartup(0x0101, &WsaData);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Error: WSAStartup : %ld \n",WSAGetLastError());
return(STATUS_UNSUCCESSFUL);
}
return(STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine is responsible Creating a Socket instance and doing bind for
for a thread.
--*/
NTSTATUS
SCIPX_PerClientInit(
IN USHORT CIndex, // client index
IN USHORT SrvCli )
{
NTSTATUS pstatus;
INTEGER RetCode;
SOCKADDR saddr; // socket address
INTEGER saddrlen;
SOCKET isockid;
// We can combine this with SPX routines later
PSOCKADDR_NS paddr_ns = (PSOCKADDR_NS)&saddr;
int protocol = NSPROTO_IPX;
// First create a socket for this client
if ((isockid = socket(AddrFly, SOCK_DGRAM, protocol)) == INVALID_SOCKET) {
//DbgPrint("Error: Invalid Socket: %ld \n",WSAGetLastError());
return(STATUS_UNSUCCESSFUL);
}
Clients[CIndex].c_Sock.c_Sockid = isockid;
// now do the address binding part
// should get ip address from Name
ClearSocket(&saddr); // cleanup the structure
paddr_ns->sa_family = (short)AddrFly;
if (SrvCli) { //
paddr_ns->sa_socket = htons((USHORT)(SERV_IPX_PORT + CIndex));
}
else { // for client assign socket id.
paddr_ns->sa_socket = 0;
}
RetCode = bind(isockid, &saddr, sizeof(saddr));
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Error: Bind: %ld\n",WSAGetLastError());;
closesocket(isockid);
return (STATUS_UNSUCCESSFUL);
}
else {
Clients[CIndex].c_Sock.c_Sockid = isockid;
}
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine is responsible for Connecting a server address to a
socket if Connected flag is true.
--*/
NTSTATUS
SCIPX_Connect_To_Server(
IN USHORT CIndex) // client index and namedpipe instance number
{
INTEGER RetCode;
SOCKADDR_NS saddr; // socket address
saddr.sa_family = (short)AddrFly; // Address family
saddr.sa_socket = htons((USHORT)(SERV_IPX_PORT + CIndex));
RtlCopyMemory((saddr.sa_nodenum), ServerName,6);
RtlCopyMemory((saddr.sa_netnum), ServerName+6,4);
RetCode = DGSocket_Connect(CIndex, (PSOCKADDR)&saddr);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Sock: Error in Connect %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine allocates memory required for all the buffers for a client.
--*/
NTSTATUS
SCIPX_Allocate_Memory(
IN USHORT CIndex) // client index and namedpipe instance number
{
NTSTATUS astatus;
ULONG AllocSize;
// AllocSize = Clients[CIndex].c_reqbuf.SendSize;
AllocSize = MAXBUFSIZE;
(LPVOID) Clients[CIndex].c_pSendBuf = VirtualAlloc(
(LPVOID) Clients[CIndex].c_pSendBuf,
(DWORD)AllocSize,
(DWORD)MEM_COMMIT,
(DWORD)PAGE_READWRITE);
sprintf(Clients[CIndex].c_pSendBuf,"Client%d Send Data",CIndex+1);
if (Clients[CIndex].c_pSendBuf == NULL) {
astatus = GetLastError();
printf("\nVirtual Alloc error\n");
}
// AllocSize = Clients[CIndex].c_reqbuf.RecvSize;
AllocSize = MAXBUFSIZE;
(LPVOID) Clients[CIndex].c_pRecvBuf = VirtualAlloc(
(LPVOID) Clients[CIndex].c_pRecvBuf,
(DWORD)AllocSize,
(DWORD)MEM_COMMIT,
(DWORD)PAGE_READWRITE);
sprintf(Clients[CIndex].c_pRecvBuf,"Client%d Recv Data",CIndex+1);
if (Clients[CIndex].c_pRecvBuf == NULL) {
astatus = GetLastError();
printf("\nVirtual Alloc error\n");
}
return astatus;
}
/************************************************************************/
/*++
This routine deallocates memory for a client.
--*/
NTSTATUS
SCIPX_Deallocate_Memory(
IN USHORT CIndex) // client index and namedpipe instance number
{
NTSTATUS dstatus;
ULONG DeallocSize;
// Deallocate memory for Send Buffer
// DeallocSize = Clients[CIndex].c_reqbuf.SendSize;
DeallocSize = MAXBUFSIZE;
/*
dstatus = NtFreeVirtualMemory(
NtCurrentProcess(),
(PVOID *) (&(Clients[CIndex].c_pSendBuf)),
&(DeallocSize),
MEM_DECOMMIT);
*/
dstatus = VirtualFree(
(LPVOID) Clients[CIndex].c_pSendBuf,
DeallocSize,
MEM_DECOMMIT);
if (!NT_SUCCESS(dstatus)) {
//DbgPrint("Nmp SendBuf: Deallocate memory failed: err: %lx \n", dstatus);
return dstatus;
}
// DeallocSize = Clients[CIndex].c_reqbuf.RecvSize;
DeallocSize = MAXBUFSIZE;
// Deallocate memory for Receive Buffer
/*
dstatus = NtFreeVirtualMemory(
NtCurrentProcess(),
(PVOID *) (&(Clients[CIndex].c_pRecvBuf)),
&(DeallocSize),
MEM_DECOMMIT);
*/
dstatus = VirtualFree(
(LPVOID) Clients[CIndex].c_pRecvBuf,
DeallocSize,
MEM_DECOMMIT);
if (!NT_SUCCESS(dstatus)) {
//DbgPrint("Nmp RecvBuf :Deallocate memory failed: err: %lx \n", dstatus);
}
return dstatus;
}
/************************************************************************/
/*++
This routine is responsible for disconnecting a session.
--*/
NTSTATUS
SCIPX_Disconnect_From_Server(
IN USHORT CIndex) // client index and namedpipe instance number
{
INTEGER RetCode;
//Close the socket so that it can disconnect
if ( (RetCode = DGSocket_Close(CIndex)) == SOCKET_ERROR) {
//DbgPrint("Sock: Error in Close Sockid %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine does handshake with it's peer. For Server this means
receiving request message from a client. For Client it means just the
opposite.
--*/
NTSTATUS
SCIPX_DoHandshake(
IN USHORT CIndex, // client index
IN USHORT SrvCli) // if it's a server or client
{
ULONG RWreqLen;
INTEGER RetCode = 0;
SOCKADDR_NS daddr;
USHORT daddrlen = 16;
RWreqLen = sizeof(struct reqbuf);
// for server do receivefrom for a request buffer
if (SrvCli) {
RetCode = DGSocket_RecvFrom(
CIndex,
(PVOID) &(Clients[CIndex].c_reqbuf),
(PULONG) &RWreqLen,
(PSOCKADDR)&daddr,
&daddrlen);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Sock: Error in Recv %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
// Now connect this address to client's Socket
RetCode = DGSocket_Connect(CIndex, (PSOCKADDR)&daddr);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Sock: Error in Connect %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
}
else { // for Client do send of reqbuf size
// Client always does Send
RetCode = DGSocket_Send(
CIndex,
(PVOID) &(Clients[CIndex].c_reqbuf),
(PULONG) &RWreqLen);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Sock: Error in Send %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
}
// check if read/write length is ok
if (RWreqLen != sizeof(struct reqbuf)) {
//DbgPrint("Sock:Read/Write Len mismatch: read %ld \n", RWreqLen);
}
/*
MyDbgPrint("handshake: Sendl:%ld Recvl:%ld \n",
Clients[CIndex].c_reqbuf.SendSize,
Clients[CIndex].c_reqbuf.RecvSize);
*/
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine Reads data from IPC. For server it means reading data
NumSends times in SendBuffers and for a client NumRecvs times into
RecvBuffer.
--*/
NTSTATUS
SCIPX_ReadFromIPC(
IN USHORT CIndex, // client index and namedpipe instance number
IN OUT PULONG pReadDone,
IN USHORT SrvCli) // if it's a server or client
{
ULONG NumReads;
ULONG ReadLen;
PCHAR ReadBuf;
INTEGER RetCode;
// SOCKADDR_NS raddr;
// INTEGER raddrlen;
if (SrvCli) { // set proper iterations and buffer for Server
NumReads = Clients[CIndex].c_reqbuf.NumSends;
ReadBuf = Clients[CIndex].c_pSendBuf;
ReadLen = Clients[CIndex].c_reqbuf.SendSize;
}
else { // for client do proper settings
NumReads = Clients[CIndex].c_reqbuf.NumRecvs;
ReadBuf = Clients[CIndex].c_pRecvBuf;
ReadLen = Clients[CIndex].c_reqbuf.RecvSize;
}
while (NumReads--) {
RetCode = DGSocket_Recv(
CIndex,
(PVOID) ReadBuf,
(PULONG)&ReadLen);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("DGSock: Error in Recv %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
// Assign the read length
*pReadDone = ReadLen;
}
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine Writes data to IPC. For server it means writing data
NumRecvs times in RecvBuffers and for a client NumSends times into
SendBuffer.
--*/
NTSTATUS
SCIPX_WriteToIPC(
IN USHORT CIndex, // client index and namedpipe instance number
IN OUT PULONG pWriteDone,
IN USHORT SrvCli) // if it's a server or client
{
ULONG NumWrites;
ULONG WriteLen;
PCHAR WriteBuf;
INTEGER RetCode;
if (SrvCli) { // set proper iterations and buffer for Server
NumWrites = Clients[CIndex].c_reqbuf.NumRecvs;
WriteBuf = Clients[CIndex].c_pRecvBuf;
WriteLen = Clients[CIndex].c_reqbuf.RecvSize;
}
else { // for client do proper settings
NumWrites = Clients[CIndex].c_reqbuf.NumSends;
WriteBuf = Clients[CIndex].c_pSendBuf;
WriteLen = Clients[CIndex].c_reqbuf.SendSize;
}
while (NumWrites--) {
RetCode = DGSocket_Send(
CIndex,
(PVOID) WriteBuf,
(PULONG) &WriteLen);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Sock: Error in Send %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
*pWriteDone = WriteLen;
}
return (STATUS_SUCCESS);
}
/************************************************************************/
NTSTATUS
SCIPX_Cleanup(VOID)
{
USHORT Cindex = 0; // client index
NTSTATUS cstatus;
NTSTATUS exitstatus = 0;
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine does a client specific cleanup work.
--*/
NTSTATUS
SCIPX_ThreadCleanUp(
IN USHORT CIndex)
{
// For Server Close the ListenId
return STATUS_SUCCESS;
}
/************************************************************************/
/*++
For IPX do nothing.
--*/
NTSTATUS
SCIPX_Wait_For_Client(
IN USHORT CIndex) // client index
{
return (STATUS_SUCCESS);
}
/************************************************************************/
/*++
This routine is responsible for issueing Disconnect to close the
connection with a client.
--*/
NTSTATUS
SCIPX_Disconnect_Client(
IN USHORT CIndex) // client index
{
INTEGER RetCode;
SOCKADDR_NS daddr; // socket address
ClearSocket(&daddr);
RetCode = DGSocket_Connect(CIndex, (PSOCKADDR)&daddr);
if (RetCode == SOCKET_ERROR) {
//DbgPrint("Sock: in Disconnect Client: Sock_Connect %d\n", RetCode);
return (STATUS_UNSUCCESSFUL);
}
return (STATUS_SUCCESS);
}
/************************************************************************/