Windows NT Systems Programming: Spring 1999

[ Home | Syllabus | Course Notes | Assignments | Search]


Check out Assignment 3


Version 2 (Client/Server)

Problem: where does the object exist:


Approach 1: Simulate Remote Procedure Calls for File WIN32 APIs

Dealing with the problems of passing parameters is called "parameter marshalling"

We will handle only the special cases of interest for version 2 at this time.

DCOM will need a more general RPC mechanism.


Packet.h

(complete source code here in two directories - client and server)

 

//**************************
// packet.h : defines packet formats between client and server
//	for Version2 (CLIENT SIDE)
// Also defines several utility functions (implemented in packet.cpp)
// These send/receive control and packet information
// and implement several WIN32 system calls as a client/server RPC
// This RPC mechanism is limited to the needs of version2
//
#ifndef PACKET_H
#define PACKET_H
#include <windows.h>
#include <winsock.h>  // also need "wsock32.lib"
#include "Message.h"

const int PORT = 44444;	// pick some arbitrary port number

typedef int NET_CONTROL;	// REQUEST and REPLIES sent between client/server

// REQUESTS/REPLIES:
//Assign each win32 function a unique ID
const NET_CONTROL CREATE_FILE = 123;
const NET_CONTROL READ_FILE = 234;
const NET_CONTROL WRITE_FILE = 345;
const NET_CONTROL CLOSE_HANDLE = 456;
const NET_CONTROL CREATE_DIRECTORY = 567;
const NET_CONTROL SET_CURRENT_DIRECTORY = 678;
const NET_CONTROL SET_FILE_POINTER = 789;
const NET_CONTROL DELETE_FILE = 890;
const NET_CONTROL SET_END_OF_FILE = 901;
const NET_CONTROL SUCCESS = 1;
const NET_CONTROL FAILURE = -1;
const int SIZE_NAME = 30;
const int SIZE_BUFFER = 512;

// . . .
//****  RPC (Remote Procedure Call) section  
// same parameter list - append "client_" before function name
HANDLE client_CreateFile(LPCTSTR fileName, DWORD access, DWORD share,
				LPSECURITY_ATTRIBUTES dummy1, 
				DWORD create, DWORD attributes, HANDLE templateFile);
typedef struct { // input parameters  // only send the ones we need for simplicity
	char fileName[SIZE_NAME];
	DWORD accessMode;
	DWORD createMode;
} PCKT_CREATE_FILE_IN;

typedef struct { // output parameters 
	NET_CONTROL status; // used to indicate any failures
	HANDLE fileHandle;
} PCKT_CREATE_FILE_OUT;

//***** WriteFile RPC section
bool client_WriteFile(HANDLE fileHandle, LPCVOID buffer, DWORD nBytes, LPDWORD nBytesOut, LPOVERLAPPED dummy);
typedef struct { // input parameters
	HANDLE fileHandle;
	BYTE buffer[SIZE_BUFFER];
	DWORD nBytesIn;
} PCKT_WRITE_FILE_IN;

typedef struct { // output parameters
	NET_CONTROL status;
	DWORD nBytesOut;
} PCKT_WRITE_FILE_OUT;
// . . .
// prototype for packet send/recieve functions 

//** sendRequest - sends a request to the server
bool sendControl(SOCKET, NET_CONTROL);
NET_CONTROL getControl(SOCKET);
bool sendPacket(SOCKET, LPBYTE packet, int size);
bool getPacket(SOCKET, LPBYTE packet, int size);

Implementation of Simulated RPCs (Client Side)

//** sendControl - sends a network control word
// PRE: socket2client is ready for communications
// POST: sends "request" to socket2client
// on network failure - closes socket and cleans up TCP connection
bool sendControl(SOCKET socket2client, NET_CONTROL request)
{
	char* Ptr = (char*) &request;
	int numsnt = send(socket2client, Ptr, sizeof(request), 0);
	if (numsnt != sizeof(request)) {
	// . . 
	}
	return true;
}
//******************************************
//** sendPacket: sends packet to socket2client
bool sendPacket(SOCKET socket2client, LPBYTE packet, int size)
{
	int numsnt = send(socket2client, (char*) packet, size, 0);
	if (numsnt != size) {
	// . . .
	}
	return true;
}


bool getPacket(SOCKET socket2client, LPBYTE packet, int size)
{
	int numrcv = recv(socket2client, (char*) packet, size,0);
	if(numrcv != size)
		return false;
	return true;
}


//***********************************
//** client_WriteFile: simulates client side RPC for WriteFile
// does not support overlapped parameter
// PRE: socket2client connection is open

bool client_WriteFile(HANDLE fileHandle, LPCVOID buffer, DWORD nBytes, LPDWORD nBytesOut, LPOVERLAPPED dummy)
{
	PCKT_WRITE_FILE_IN pcktWFin;
	PCKT_WRITE_FILE_OUT pcktWFout;

	// tell server to prepare to receive input parameters for WriteFile
	if (!sendControl(socket2client, WRITE_FILE)) 
		return false;
	// Marshall input paramters
	pcktWFin.fileHandle = fileHandle; 
	strncpy((char*)(pcktWFin.buffer), (char*)buffer, nBytes);
	pcktWFin.nBytesIn = nBytes;
	// sent input parameters to server
	if(!sendPacket(socket2client, LPBYTE(&pcktWFin), sizeof(pcktWFin))) 
		return false;
	// wait for completion and output parameters
	if(!getPacket(socket2client, LPBYTE(&pcktWFout), sizeof(pcktWFout))) 
		return false;
	if(pcktWFout.status != SUCCESS)
		return false;
	// Marshall output parameter
	*nBytesOut = pcktWFout.nBytesOut; 
	return true;
}

Implementation of Simulated RPCs (Server Implementation)

//		PACKET FORMATS:
// Requests consist of two packets.
// First packet is request type (which of the procedure calls to do)
// Second Packet is the argument list for the procedure call
// Response Packet is 
//	Status (Success/Failure of RPC)
//	Return arguments
// ....
	while(TRUE) // loop until the connection goes down
	{
		request = getControl(socket2client);
		switch (request)
		{
		case CREATE_FILE:
			server_CreateFile(socket2client);
			break;
	// . . .
// Append "server_" before function name
// input parameter tells which SOCKET to get the "real" input parameters on
void server_CreateFile(SOCKET socket2client)
{
	PCKT_CREATE_FILE_IN pcktCFin;
	PCKT_CREATE_FILE_OUT pcktCFout;
	HANDLE fileHandle;
	
	if(!getPacket(socket2client, LPBYTE(&pcktCFin), sizeof(pcktCFin))) 
	{
	// . . 
	}
	fileHandle = CreateFile(pcktCFin.fileName, pcktCFin.accessMode,0,0, pcktCFin.createMode,0,0) ;
	pcktCFout.status = SUCCESS;
	pcktCFout.fileHandle = fileHandle; 
	if(!sendPacket(socket2client, LPBYTE(&pcktCFout), sizeof (pcktCFout))) { 
	// . . .
	}
}

Changes to Object Code from Version 1

Replace File APIs with client version.

For Example:

bool CMessage::ReadMsg(HANDLE fileHandle) 
{
	DWORD nBytes;
	
	if(!client_ReadFile(fileHandle,topic,SIZE_TOPIC+1,&nBytes,0))
		return false;
	
	if(!client_ReadFile(fileHandle,text,SIZE_TEXT+1,&nBytes,0))
		return false;
	return true;
}

Copyright chris wild 1999.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: January 24, 1999.