From 9d71f3343211d31d4e653ac9167ba02b98358775 Mon Sep 17 00:00:00 2001 From: nihonium Date: Sun, 1 Dec 2024 19:58:51 +0300 Subject: [PATCH] =?UTF-8?q?feat(server):=20=D0=A4=D1=83=D0=BD=D0=BA=D1=86?= =?UTF-8?q?=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=B0=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BF=D0=B8=D1=81=D0=B0?= =?UTF-8?q?=D0=BD=20=D0=B4=D0=BB=D1=8F=20=D1=82=D0=BE=D0=B3=D0=BE,=20?= =?UTF-8?q?=D1=87=D1=82=D0=BE=D0=B1=20=D0=B2=D0=BF=D0=BE=D1=81=D0=BB=D0=B5?= =?UTF-8?q?=D0=B4=D1=81=D1=82=D0=B2=D0=B8=D0=B8=20=D1=80=D0=B5=D0=B0=D0=BB?= =?UTF-8?q?=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D1=83=20=D1=81=20=D0=BD=D0=B5=D1=81=D0=BA=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=B8=D0=BC=D0=B8=20=D0=BA=D0=BB=D0=B8=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- main.c | 26 +++++--- server.c | 181 ++++++++++++++++++++++++++----------------------------- server.h | 12 ++-- 3 files changed, 109 insertions(+), 110 deletions(-) diff --git a/main.c b/main.c index c422661..9cddbec 100644 --- a/main.c +++ b/main.c @@ -3,14 +3,11 @@ #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[]) { - printf("\n->Start of parent execution.\n"); if (argc == 2) { + // TODO: implement client if (lstrcmpi(argv[1], TEXT("-c")) == 0) { + // StartShellClient(); return 0; } else if (lstrcmpi(argv[1], TEXT("-s")) == 0) { @@ -18,16 +15,27 @@ int _tmain(int argc, TCHAR *argv[]) { return 0; } else { - PrintHelpMessage(); - return -1; + goto help_message; } } + 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 { - PrintHelpMessage(); - return -1; + goto help_message; } return 0; +help_message: + printf("Wrong usage\nUsage: %s [-c | -s [-service]]\n", argv[0]); + return -1; } diff --git a/server.c b/server.c index 53b6759..646b573 100644 --- a/server.c +++ b/server.c @@ -4,75 +4,44 @@ #define DEFAULT_PORT "50113" #define DEFAULT_BUFLEN 512 -// Handles for child process STDIN and 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; +typedef struct PipeThreadInfo_t { + HANDLE Pipe; + SOCKET ClientSocket; +} PipeThreadInfo; -SOCKET ClientSocket = INVALID_SOCKET; - -//HANDLE g_hInputFile = NULL; +void CreateChildProcess(HANDLE g_hChildStd_IN_Rd, HANDLE g_hChildStd_OUT_Wr); +DWORD WINAPI WriteToPipe(LPVOID lpParam); +DWORD WINAPI ReadFromPipe(LPVOID lpParam); +void ErrorExit(PCTSTR); void StartShellServer() { printf("\n->Start of shell server execution.\n"); - CreatePipes(); - CreateSocket(); - - // 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() { + /* + * Server variables + */ WSADATA wsaData; struct addrinfo* result = NULL, * ptr = NULL, hints; SOCKET ListenSocket = INVALID_SOCKET; - 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 iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); if (iResult != 0) { @@ -125,6 +94,39 @@ void CreateSocket() { 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 ClientSocket = INVALID_SOCKET; @@ -136,11 +138,24 @@ void CreateSocket() { WSACleanup(); 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); } -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. { TCHAR szCmdline[] = TEXT("C:\\Windows\\System32\\cmd.exe"); @@ -195,36 +210,25 @@ void CreateChildProcess() } } -void WriteToPipe(void) - -// Read from a file and write its contents to the pipe for the child's STDIN. -// Stop when there is no more data. +DWORD WINAPI WriteToPipe(LPVOID lpParam) { DWORD dwRead, dwWritten; - //CHAR chBuf[BUFSIZE] = "dir\r\n"; BOOL bSuccess = FALSE; int i = 0; + SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket; + HANDLE g_hChildStd_IN_Wr = ((PipeThreadInfo*)lpParam)->Pipe; + char recvbuf[DEFAULT_BUFLEN]; int iResult, iSendResult; int recvbuflen = DEFAULT_BUFLEN; - do { iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); if (iResult > 0) { - printf("Bytes received: %d\n", iResult); - - // 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); + bSuccess = WriteFile(g_hChildStd_IN_Wr, recvbuf, iResult, &dwWritten, NULL); + if (!bSuccess) break; } else if (iResult == 0) printf("Connection closing...\n"); @@ -234,33 +238,21 @@ void WriteToPipe(void) WSACleanup(); 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); - // Close the pipe handle so the child process stops reading. - + // Closing STDIN => cmd.exe exit if (!CloseHandle(g_hChildStd_IN_Wr)) ErrorExit(TEXT("StdInWr CloseHandle")); } -void ReadFromPipe(void) - -// 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 WINAPI ReadFromPipe(LPVOID lpParam) { DWORD dwRead, dwWritten; CHAR chBuf[BUFSIZE]; BOOL bSuccess = FALSE; HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + SOCKET ClientSocket = ((PipeThreadInfo*)lpParam)->ClientSocket; + HANDLE g_hChildStd_OUT_Rd = ((PipeThreadInfo*)lpParam)->Pipe; int iSendResult; @@ -280,7 +272,6 @@ void ReadFromPipe(void) bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL); if (!bSuccess) break; - break; } } diff --git a/server.h b/server.h index 249948d..ae27f3e 100644 --- a/server.h +++ b/server.h @@ -14,9 +14,9 @@ // Defined functions void StartShellServer(); -void CreatePipes(); -void CreateChildProcess(void); -void WriteToPipe(void); -void ReadFromPipe(void); -void ErrorExit(PCTSTR); -void CreateSocket(); \ No newline at end of file +//void CreatePipes(); +//void CreateChildProcess(void); +//DWORD WINAPI WriteToPipe(LPVOID lpParam); +//DWORD WINAPI ReadFromPipe(LPVOID lpParam); +//void ErrorExit(PCTSTR); +//void CreateSocket(); \ No newline at end of file