[ 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 VOID talkToClient(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); } }