[ Home | Syllabus | Course Notes | Assignments | Search]
Concepts to be demonstrated:
// ****
// verifyFolder - verifies then creates/opens message folder
bool CMsgFolder::verifyFolder(const char* name)
{
DWORD nBytes;
if(client_CreateDirectory(name,0)) {
cout << "Created Directory:" << name << endl;
if(!client_SetCurrentDirectory(name)) {
cerr << "Could not set message folder" << name << GetLastError();
return false;
}
// create "messages" file with magic cookie
messages = client_CreateFile("messages",GENERIC_WRITE,0,0,CREATE_NEW,0,0);
if(messages == INVALID_HANDLE_VALUE) {
cerr << "Could not create messages file" << GetLastError();
return false;
}
nextMsgNum = 0;
return true;
}
else {
if(!client_SetCurrentDirectory(name)) {
cerr << "Could not set message folder" << name << GetLastError();
return false;
}
// Now check if this folder contains a "messages" file with the magic cookie
messages = client_CreateFile(
"messages",
GENERIC_READ|GENERIC_WRITE, // read then write this file
0,0,
OPEN_EXISTING,
0,0);
if(messages == INVALID_HANDLE_VALUE) {
cerr << "Could not open messages file" << GetLastError();
return false;
}
int cookie;
if(!client_ReadFile(messages, (LPBYTE) &cookie, sizeof(cookie), &nBytes, NULL)) {
cerr << "Could not read magic cookie!" << GetLastError();
return false;
}
if(cookie != MAGIC_COOKIE) {
cerr << "no magic cookie!\n";
return false;
}
if(!client_ReadFile(messages, (LPBYTE) &nextMsgNum, sizeof(nextMsgNum), &nBytes, NULL)) {
cerr << "Could not nMessages!" << GetLastError();
return false;
}
// now read messages list
if(!msgList.ReadListMsgs(messages)) {
cerr << "Could not read message list\n";
return false;
}
return true;
}
}
//**********************************************
// Packet.cpp: implements several useful functions for
// communicating between clients and servers for version 2
// Does not support GetLastError between client and server
#include "packet.h"
#include <iostream.h>
SOCKET connect2server(const char* serverIP)
{
SOCKADDR_IN serverSockAddr;
SOCKET socket2server;
WSADATA Data;
int status;
status=WSAStartup(MAKEWORD(1, 1), &Data);
if (status != 0) {
cerr << "ERROR: WSAStartup unsuccessful" << endl;
return INVALID_SOCKET;
}
socket2server=socket(AF_INET, SOCK_STREAM, 0);
if (socket2server == INVALID_SOCKET)
{
cerr << "ERROR: socket unsuccessful" << endl;
status=WSACleanup();
if (status == SOCKET_ERROR)
cerr << "ERROR: WSACleanup unsuccessful" << endl;
return INVALID_SOCKET;
}
serverSockAddr.sin_addr.s_addr=inet_addr(serverIP);
serverSockAddr.sin_port=htons(PORT);
serverSockAddr.sin_family=AF_INET;
status=connect(socket2server,
(LPSOCKADDR) &serverSockAddr,
sizeof(serverSockAddr));
if (status == SOCKET_ERROR)
{
cerr << "ERROR: connect unsuccessful" << endl;
status=closesocket(socket2server);
if (status == SOCKET_ERROR)
cerr << "ERROR: closesocket unsuccessful"
<< endl;
status=WSACleanup();
if (status == SOCKET_ERROR)
cerr << "ERROR: WSACleanup unsuccessful"
<< endl;
return INVALID_SOCKET;
}
return socket2server;
}
//*****************************
//** client_CreateDirectory: simulates client side RPC for CreateDirectory
// does not support security parameter
// PRE: socket2server connection is open
bool client_CreateDirectory(LPCTSTR name, LPSECURITY_ATTRIBUTES dummy)
{
PCKT_CREATE_DIRECTORY_IN pcktCD;
PCKT_CREATE_DIRECTORY_OUT pcktCDout;
if (!sendControl(socket2server, CREATE_DIRECTORY))
return false;
memcpy(pcktCD.name, name, SIZE_NAME); // marshall string in to packet
if(!sendPacket(socket2server, LPBYTE(&pcktCD), sizeof(pcktCD)))
return false;
if(!getPacket(socket2server, LPBYTE(&pcktCDout), sizeof(pcktCDout)))
return false;
if(pcktCDout.status != SUCCESS)
return false;
return pcktCDout.returnValue; // marshall return value
}
//*****************************
//** client_CreatFile: simulates client side RPC for CreateFile
// does not supprt share, security, attributes, and template file parameters
// PRE: socket2server connection is open
HANDLE client_CreateFile(LPCTSTR fileName, DWORD access, DWORD share, LPSECURITY_ATTRIBUTES dummy1,
DWORD create, DWORD attributes, HANDLE templateFile)
{
PCKT_CREATE_FILE_IN pcktCF;
PCKT_CREATE_FILE_OUT pcktCFout;
if (!sendControl(socket2server, CREATE_FILE))
return INVALID_HANDLE_VALUE;
memcpy(pcktCF.fileName, fileName, SIZE_NAME);
pcktCF.accessMode = access;
pcktCF.createMode = create;
if(!sendPacket(socket2server, LPBYTE(&pcktCF), sizeof(pcktCF)))
return INVALID_HANDLE_VALUE;
if(!getPacket(socket2server, LPBYTE(&pcktCFout), sizeof(pcktCFout)))
return INVALID_HANDLE_VALUE;
if(pcktCFout.status != SUCCESS)
return INVALID_HANDLE_VALUE;
return pcktCFout.fileHandle;
}
//***********************************
//** client_WriteFile: simulates client side RPC for WriteFile
// does not support overlapped parameter
// PRE: socket2server connection is open
bool client_WriteFile(HANDLE fileHandle, LPCVOID buffer, DWORD nBytes, LPDWORD nBytesOut, LPOVERLAPPED dummy)
{
PCKT_WRITE_FILE_IN pcktWF;
PCKT_WRITE_FILE_OUT pcktWFout;
if (!sendControl(socket2server, WRITE_FILE))
return false;
pcktWF.fileHandle = fileHandle;
memcpy(pcktWF.buffer, buffer, nBytes);
pcktWF.nBytesIn = nBytes;
if(!sendPacket(socket2server, LPBYTE(&pcktWF), sizeof(pcktWF)))
return false;
if(!getPacket(socket2server, LPBYTE(&pcktWFout), sizeof(pcktWFout)))
return false;
if(pcktWFout.status != SUCCESS)
return false;
*nBytesOut = pcktWFout.nBytesOut;
return true;
}
//***** SetEndOfFile RPC section
//** sendControl - sends a network control word
// PRE: socket2server is ready for communications
// POST: sends "request" to socket2server
// on network failure - closes socket and cleans up TCP connection
bool sendControl(SOCKET socket2server, NET_CONTROL request)
{
char* Ptr = (char*) &request;
int numsnt = send(socket2server, Ptr, sizeof(request), 0);
if (numsnt != sizeof(request)) {
// TRACE("Could not send request:%d", (int) WSAGetLastError());
closesocket(socket2server);
WSACleanup();
return false;
}
return true;
}
//*************************************
//** getControl: receives a network control word
NET_CONTROL getControl(SOCKET socket2server)
{
NET_CONTROL reply;
int numrcv = recv(socket2server, (char*) &reply, sizeof(reply),0);
if(numrcv != sizeof(reply))
return FAILURE;
return reply;
}
//******************************************
//** sendPacket: sends packet to socket2server
bool sendPacket(SOCKET socket2server, LPBYTE packet, int size)
{
int numsnt = send(socket2server, (char*) packet, size, 0);
if (numsnt != size) {
//TRACE("Could not send fileHandle:%d", (int) WSAGetLastError());
closesocket(socket2server);
WSACleanup();
return false;
}
return true;
}
bool getPacket(SOCKET socket2server, LPBYTE packet, int size)
{
int numrcv = recv(socket2server, (char*) packet, size,0);
if(numrcv != size)
return false;
return true;
}
//*********************************************** // Simple Message Filer (Version3): SERVER SIDE // This implementation introduces a multi-client server solution // each client is serviced by a separate thread // Uses "file locking" to prevent simulataneous access to a message folder // Message folder naming structure is flat at the present time // there is no authentification or security provided // Basically the server implements remote versions of // the following procedure calls (a home built RPC) // CreateDirectory // SetCurrentDirectory // SetFilePointer // CreateFile // ReadFile // WriteFile // CloseHandle // This RPC DOES NOT preserve GetLastError state // // PACKET FORMATS: // Requests consist of two packets. // First packet is request type (which of the four procedure calls to do) // Second Packet is the argument list for the procedure call // Response Packet is // Status (Success/Failure of RPC) // Return arguments // The type and values of the request and reply packets are defined in "packets.h" // AUTHOR: chris wild // DATE: September 6, 1997 //************************************************* #include "packet.h" // packet formats and constants #include <iostream.h> #include <windows.h> #include <process.h> // for locking file?
// Prototype to thread call VOIDtalkToClient(VOID *
cs); int main() { // . . .
DWORD threadID; HANDLE clientThread;serverSocket = getServerSocket(); // contains the "listen" API while (true) { // accept a connection from a client clientSocket=accept(serverSocket, (LPSOCKADDR) &clientSockAddr, &addrLen); //. . .spawn a thread to handle this client.
clientThread = CreateThread(0, // no child process cannot inherit 0, // gives same stack space as parent thread (LPTHREAD_START_ROUTINE) talkToClient, (VOID *) clientSocket, // Pass in one parameter 0, // Put into ready Q &threadID); // system wide thread ID // . . .
}
}
VOID talkToClient(VOID *cs)
{
SOCKET socket2client=(SOCKET)cs;
NET_CONTROL request;
while(TRUE) // loop until killed
{
request = getControl(socket2client);
if (request == FAILURE) {
shutdown(socket2client, 2);
// 2 shutdown send and receive
closesocket(socket2client);
ExitThread(0);
}
switch (request)
{
case CREATE_DIRECTORY:
SetCurrentDirectory(ParentDir);
server_CreateDirectory(socket2client);
break;
case SET_CURRENT_DIRECTORY:
strcpy(CurrPath, server_SetCurrentDirectory(socket2client));
setFlg = 1;
break;
case CREATE_FILE:
server_CreateFile(socket2client);
break;
case READ_FILE:
server_ReadFile(socket2client);
break;
case WRITE_FILE:
server_WriteFile(socket2client);
break;
case SET_FILE_POINTER:
server_SetFilePointer(socket2client);
break;
case CLOSE_HANDLE:
server_CloseHandle(socket2client);
break;
case DELETE_FILE:
server_DeleteFile(socket2client);
break;
case SET_END_OF_FILE:
server_SetEndOfFile(socket2client);
break;
default:
;
// ignore and hope you get back into sync
}
}
}
//****************
// getServerSocket: sets up a server socket to listen on a known port
SOCKET getServerSocket()
{
WSADATA Data;
SOCKADDR_IN serverSockAddr;
SOCKET serverSocket;
int addrLen=sizeof(SOCKADDR_IN);
int status;
status=WSAStartup(MAKEWORD(1, 1), &Data); // ONLY REQUIRES VERSION 1.1 OF DLL
if (status != 0) {
cerr << "ERROR: WSAStartup unsuccessful"
<< endl;
ExitProcess(1);
}
memset(&serverSockAddr, 0, sizeof(serverSockAddr));
serverSockAddr.sin_port=htons(PORT);
serverSockAddr.sin_family=AF_INET;
serverSockAddr.sin_addr.s_addr=htonl(INADDR_ANY);
serverSocket=socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET) {
cerr << "ERROR: socket unsuccessful" << endl;
ExitProcess(1);
}
status=bind(serverSocket,
(LPSOCKADDR) &serverSockAddr,
sizeof(serverSockAddr));
if (status == SOCKET_ERROR) {
cerr << "ERROR: bind unsuccessful" << endl;
ExitProcess(1);
}
status=listen(serverSocket, 1);
if (status == SOCKET_ERROR) {
cerr << "ERROR: listen unsuccessful" << endl;
ExitProcess(1);
}
return serverSocket;
}
void server_CreateDirectory(SOCKET socket2client)
{
PCKT_CREATE_DIRECTORY_IN pcktCDin;
PCKT_CREATE_DIRECTORY_OUT pcktCDout;
if(!getPacket(socket2client, LPBYTE(&pcktCDin), sizeof(pcktCDin)))
{
cout << "Could not get CREATE_DIRECTORY packet" << endl;
pcktCDout.status = FAILURE;
sendPacket(socket2client, (LPBYTE) &pcktCDout, sizeof(pcktCDout));
closesocket(socket2client);
WSACleanup();
ExitProcess(1);
}
if(CreateDirectory(pcktCDin.name,0)) {
pcktCDout.status = SUCCESS;
pcktCDout.returnValue = true;
}
else {
pcktCDout.status = SUCCESS;
pcktCDout.returnValue = false;
}
if(!sendPacket(socket2client, LPBYTE(&pcktCDout), sizeof (pcktCDout))) {
cout << "Could not send CREATE_DIRECTORY" << endl;
closesocket(socket2client);
WSACleanup();
ExitProcess(1);
}
}
void server_CreateFile(SOCKET socket2client)
{
PCKT_CREATE_FILE_IN pcktCFin;
PCKT_CREATE_FILE_OUT pcktCFout;
HANDLE fileHandle;
if(!getPacket(socket2client, LPBYTE(&pcktCFin), sizeof(pcktCFin)))
{
cout << "Could not get CREATE_FILE packet" << endl;
pcktCFout.status = FAILURE;
sendPacket(socket2client, (LPBYTE) &pcktCFout, sizeof(pcktCFout));
closesocket(socket2client);
WSACleanup();
ExitProcess(1);
}
fileHandle = CreateFile(pcktCFin.fileName, pcktCFin.accessMode,0,0, pcktCFin.createMode,0,0);
pcktCFout.status = SUCCESS;
pcktCFout.fileHandle = fileHandle; // send handle back
if(!sendPacket(socket2client, LPBYTE(&pcktCFout), sizeof (pcktCFout))) {
cout << "Could not get CREATE_FILE" << endl;
closesocket(socket2client);
WSACleanup();
ExitProcess(1);
}
}
void server_WriteFile(SOCKET socket2client)
{
PCKT_WRITE_FILE_IN pcktWFin;
PCKT_WRITE_FILE_OUT pcktWFout;
if(!getPacket(socket2client, LPBYTE(&pcktWFin), sizeof(pcktWFin)))
{
cout << "Could not get READ_FILE packet" << endl;
pcktWFout.status = FAILURE;
sendPacket(socket2client, LPBYTE(&pcktWFout), sizeof(pcktWFout));
closesocket(socket2client);
WSACleanup();
ExitProcess(1);
}
if(WriteFile(pcktWFin.fileHandle, pcktWFin.buffer,
pcktWFin.nBytesIn,&(pcktWFout.nBytesOut),0))
pcktWFout.status = SUCCESS;
else
pcktWFout.status = FAILURE;
if(!sendPacket(socket2client, LPBYTE(&pcktWFout), sizeof (pcktWFout))) {
cout << "Could not READ_FILE" << endl;
closesocket(socket2client);
WSACleanup();
ExitProcess(1);
}
}