feat(server): Функционал сервера переписан для того, чтоб впоследствии

реализовать работу с несколькими клиентами
master
Nihonium 3 weeks ago
parent 4c6087fe9d
commit 9d71f33432

@ -3,14 +3,11 @@
#include "server.h" #include "server.h"
void PrintHelpMessage() {
printf("Usage error: I know 3 arguments \n\t\"install\"\n\t\"delete\"\n\t\"app\"\n");
}
int _tmain(int argc, TCHAR *argv[]) { int _tmain(int argc, TCHAR *argv[]) {
printf("\n->Start of parent execution.\n");
if (argc == 2) { if (argc == 2) {
// TODO: implement client
if (lstrcmpi(argv[1], TEXT("-c")) == 0) { if (lstrcmpi(argv[1], TEXT("-c")) == 0) {
// StartShellClient();
return 0; return 0;
} }
else if (lstrcmpi(argv[1], TEXT("-s")) == 0) { else if (lstrcmpi(argv[1], TEXT("-s")) == 0) {
@ -18,16 +15,27 @@ int _tmain(int argc, TCHAR *argv[]) {
return 0; return 0;
} }
else { else {
PrintHelpMessage(); goto help_message;
return -1;
} }
} }
else if (argc == 3) {
// TODO: implement service
if (lstrcmpi(argv[1], TEXT("-s")) == 0 && lstrcmpi(argv[2], TEXT("-service")) == 0) {
// CreateService
return 0;
}
else {
goto help_message;
}
}
else { else {
PrintHelpMessage(); goto help_message;
return -1;
} }
return 0; return 0;
help_message:
printf("Wrong usage\nUsage: %s [-c | -s [-service]]\n", argv[0]);
return -1;
} }

@ -4,75 +4,44 @@
#define DEFAULT_PORT "50113" #define DEFAULT_PORT "50113"
#define DEFAULT_BUFLEN 512 #define DEFAULT_BUFLEN 512
// Handles for child process STDIN and STDOUT typedef struct PipeThreadInfo_t {
HANDLE g_hChildStd_IN_Rd = NULL; HANDLE Pipe;
HANDLE g_hChildStd_IN_Wr = NULL; SOCKET ClientSocket;
HANDLE g_hChildStd_OUT_Rd = NULL; } PipeThreadInfo;
HANDLE g_hChildStd_OUT_Wr = NULL;
SOCKET ClientSocket = INVALID_SOCKET; void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr);
DWORD WINAPI WriteToPipe(LPVOID lpParam);
//HANDLE g_hInputFile = NULL; DWORD WINAPI ReadFromPipe(LPVOID lpParam);
void ErrorExit(PCTSTR);
void StartShellServer() { void StartShellServer() {
printf("\n->Start of shell server execution.\n"); printf("\n->Start of shell server execution.\n");
CreatePipes(); /*
CreateSocket(); * Server variables
*/
// Create the child process.
CreateChildProcess();
// TODO: split into threads
WriteToPipe();
// Read from pipe that is the standard output for child process.
ReadFromPipe();
printf("\n->End of shell server execution.\n");
// The remaining open handles are cleaned up when this process terminates.
// To avoid resource leaks in a larger application, close handles explicitly.
}
void CreatePipes() {
SECURITY_ATTRIBUTES saAttr;
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT.
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
ErrorExit(TEXT("StdoutRd CreatePipe"));
// Ensure the read handle to the pipe for STDOUT is not inherited.
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
ErrorExit(TEXT("Stdout SetHandleInformation"));
// Create a pipe for the child process's STDIN.
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
ErrorExit(TEXT("Stdin CreatePipe"));
// Ensure the write handle to the pipe for STDIN is not inherited.
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
ErrorExit(TEXT("Stdin SetHandleInformation"));
}
// TODO: to review
void CreateSocket() {
WSADATA wsaData; WSADATA wsaData;
struct addrinfo* result = NULL, * ptr = NULL, hints; struct addrinfo* result = NULL, * ptr = NULL, hints;
SOCKET ListenSocket = INVALID_SOCKET; SOCKET ListenSocket = INVALID_SOCKET;
int iResult; int iResult;
/*
* Client variables
*/
SOCKET ClientSocket = INVALID_SOCKET;
// Pipe handles for child STDIN/STDOUT
HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
SECURITY_ATTRIBUTES saAttr;
HANDLE PipeThreads[2];
/*
* Initialize listening socket
*/
// Initialize Winsock // Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) { if (iResult != 0) {
@ -125,6 +94,39 @@ void CreateSocket() {
return 1; return 1;
} }
/*
* Initialize pipes
*/
// Set the bInheritHandle flag so pipe handles are inherited.
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
// Create a pipe for the child process's STDOUT.
if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
ErrorExit(TEXT("StdoutRd CreatePipe"));
// Ensure the read handle to the pipe for STDOUT is not inherited.
if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
ErrorExit(TEXT("Stdout SetHandleInformation"));
// Create a pipe for the child process's STDIN.
if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
ErrorExit(TEXT("Stdin CreatePipe"));
// Ensure the write handle to the pipe for STDIN is not inherited.
if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
ErrorExit(TEXT("Stdin SetHandleInformation"));
/*
* Create child process
*/
CreateChildProcess(g_hChildStd_IN_Rd, g_hChildStd_OUT_Wr);
/*
* Process client connection
*/
// Accepting a connection // Accepting a connection
ClientSocket = INVALID_SOCKET; ClientSocket = INVALID_SOCKET;
@ -136,11 +138,24 @@ void CreateSocket() {
WSACleanup(); WSACleanup();
return 1; return 1;
} }
// No longer needed
PipeThreadInfo WriteThreadInfo = { g_hChildStd_IN_Wr, ClientSocket };
PipeThreadInfo ReadThreadInfo = { g_hChildStd_OUT_Rd, ClientSocket };
PipeThreads[0] = CreateThread(NULL, 0, WriteToPipe, &WriteThreadInfo, 0, NULL);
PipeThreads[1] = CreateThread(NULL, 0, ReadFromPipe, &ReadThreadInfo, 0, NULL);
WaitForMultipleObjects(2, PipeThreads, TRUE, INFINITE);
printf("\n->Client disconnected.\n");
/*
* Finalization
*/
// TODO: properly close all handles
closesocket(ListenSocket); closesocket(ListenSocket);
} }
void CreateChildProcess() void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr)
// Create a child process that uses the previously created pipes for STDIN and STDOUT. // Create a child process that uses the previously created pipes for STDIN and STDOUT.
{ {
TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe"); TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe");
@ -195,36 +210,25 @@ void CreateChildProcess()
} }
} }
void WriteToPipe(void) DWORD WINAPI WriteToPipe(LPVOID lpParam)
// Read from a file and write its contents to the pipe for the child's STDIN.
// Stop when there is no more data.
{ {
DWORD dwRead, dwWritten; DWORD dwRead, dwWritten;
//CHAR chBuf[BUFSIZE] = "dir\r\n";
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
int i = 0; int i = 0;
SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket;
HANDLE g_hChildStd_IN_Wr = ((PipeThreadInfo*)lpParam)->Pipe;
char recvbuf[DEFAULT_BUFLEN]; char recvbuf[DEFAULT_BUFLEN];
int iResult, iSendResult; int iResult, iSendResult;
int recvbuflen = DEFAULT_BUFLEN; int recvbuflen = DEFAULT_BUFLEN;
do do
{ {
iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); iResult = recv(ClientSocket, recvbuf, recvbuflen, 0);
if (iResult > 0) { if (iResult > 0) {
printf("Bytes received: %d\n", iResult); bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL);
if (!bSuccess) break;
// Echo the buffer back to the sender
iSendResult = send(ClientSocket, recvbuf, iResult, 0);
if (iSendResult == SOCKET_ERROR) {
printf("send failed: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n", iSendResult);
} }
else if (iResult == 0) else if (iResult == 0)
printf("Connection closing...\n"); printf("Connection closing...\n");
@ -234,33 +238,21 @@ void WriteToPipe(void)
WSACleanup(); WSACleanup();
return 1; return 1;
} }
//dwRead = strlen(chBuf) + 1;
bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL);
if (!bSuccess) break;
//break;
//dwRead = strlen(chBuf) + 1;
//bSuccess = WriteFile(g_hChildStd_IN_Wr, chBuf, dwRead, &dwWritten, NULL);
//if (!bSuccess) break;
ReadFromPipe();
} while (iResult > 0); } while (iResult > 0);
// Close the pipe handle so the child process stops reading. // Closing STDIN => cmd.exe exit
if (!CloseHandle(g_hChildStd_IN_Wr)) if (!CloseHandle(g_hChildStd_IN_Wr))
ErrorExit(TEXT("StdInWr CloseHandle")); ErrorExit(TEXT("StdInWr CloseHandle"));
} }
void ReadFromPipe(void) DWORD WINAPI ReadFromPipe(LPVOID lpParam)
// Read output from the child process's pipe for STDOUT
// and write to the parent process's pipe for STDOUT.
// Stop when there is no more data.
{ {
DWORD dwRead, dwWritten; DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE]; CHAR chBuf[BUFSIZE];
BOOL bSuccess = FALSE; BOOL bSuccess = FALSE;
HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket;
HANDLE g_hChildStd_OUT_Rd = ((PipeThreadInfo*)lpParam)->Pipe;
int iSendResult; int iSendResult;
@ -280,7 +272,6 @@ void ReadFromPipe(void)
bSuccess = WriteFile(hParentStdOut, chBuf, bSuccess = WriteFile(hParentStdOut, chBuf,
dwRead, &dwWritten, NULL); dwRead, &dwWritten, NULL);
if (!bSuccess) break; if (!bSuccess) break;
break;
} }
} }

@ -14,9 +14,9 @@
// Defined functions // Defined functions
void StartShellServer(); void StartShellServer();
void CreatePipes(); //void CreatePipes();
void CreateChildProcess(void); //void CreateChildProcess(void);
void WriteToPipe(void); //DWORD WINAPI WriteToPipe(LPVOID lpParam);
void ReadFromPipe(void); //DWORD WINAPI ReadFromPipe(LPVOID lpParam);
void ErrorExit(PCTSTR); //void ErrorExit(PCTSTR);
void CreateSocket(); //void CreateSocket();
Loading…
Cancel
Save