diff --git a/src/Mayaqua/Mayaqua.c b/src/Mayaqua/Mayaqua.c index a452ac91..cd8708cb 100644 --- a/src/Mayaqua/Mayaqua.c +++ b/src/Mayaqua/Mayaqua.c @@ -1151,6 +1151,11 @@ void PrintKernelStatus() Print(" !!! MEMORY LEAKS DETECTED !!!\n\n"); if (g_memcheck == false) { + if (IsHamMode()) + { + Print(" Enable /memcheck startup option to see the leaking memory heap.\n"); + Print(" Press Enter key to exit the process.\n"); + } GetLine(NULL, 0); } } diff --git a/src/Mayaqua/Tracking.c b/src/Mayaqua/Tracking.c index 3dda6c0a..ae0bd1f6 100644 --- a/src/Mayaqua/Tracking.c +++ b/src/Mayaqua/Tracking.c @@ -157,7 +157,15 @@ void MemoryDebugMenu() TOKEN_LIST *t; char *cmd; Print("Mayaqua Kernel Memory Debug Tools\n" - "Copyright (c) SoftEther Corporation. All Rights Reserved.\n\n"); + "Copyright (c) SoftEther VPN Project. All Rights Reserved.\n\n"); + +#ifndef OS_WIN32 + Print("Unfortunately The call stack is not recorded on non-Windows systems\n"); + Print("since UnixGetCallStack() and UnixGetCallStackSymbolInfo() is not implemented.\n"); + Print("Therefore please use valgrind or other memory leak check tools\n"); + Print("to get the actual call stacks of memory leak causes.\n\n"); +#endif // OS_WIN32 + g_memcheck = false; while (true) { diff --git a/src/vpntest/vpntest.c b/src/vpntest/vpntest.c index faf24a80..7ba5ef67 100644 --- a/src/vpntest/vpntest.c +++ b/src/vpntest/vpntest.c @@ -1,7 +1,243 @@ -#include +// vpntest.c +// VPN Server / VPN Client / VPN Bridge test program -int main() +#include +#define VPN_EXE + +#include +#include +#include +#include +#include +#include +#include +#include +#include "vpntest.h" + + + +void client_test(UINT num, char **arg) { - printf("Hello, VPN Hamster !!\n"); + Print("VPN Client Test. Press Enter key to stop the VPN Client .\n"); + CtStartClient(); + GetLine(NULL, 0); + CtStopClient(); +} + +void server_test(UINT num, char **arg) +{ + Print("VPN Server Test. Press Enter key to stop the VPN Server .\n"); + + StInit(); + + StStartServer(false); + + GetLine(NULL, 0); + + StStopServer(); + + StFree(); +} + +void bridge_test(UINT num, char **arg) +{ + Print("VPN Bridge Test. Press Enter key to stop the VPN Bridge .\n"); + + StInit(); + + StStartServer(true); + + GetLine(NULL, 0); + + StStopServer(); + + StFree(); +} + +void memory_leak_test(UINT num, char **arg) +{ + char *a = Malloc(1); + + Print("Hello, I am the great dictator of this kingdom!\n"); + Print("Just now I called Malloc(1) and never free! Ha ha ha !!\n"); +} + + +// The list of test functions +// Test function definition list +typedef void (TEST_PROC)(UINT num, char **arg); + +typedef struct TEST_LIST +{ + char *command_str; + TEST_PROC *proc; + char *help; +} TEST_LIST; + +TEST_LIST test_list[] = +{ + {"c", client_test, "VPN Client in Test Mode, enter key to graceful stop."}, + {"s", server_test, "VPN Server in Test Mode, enter key to graceful stop."}, + {"b", bridge_test, "VPN Bridge in Test Mode, enter key to graceful stop."}, + {"memory_leak", memory_leak_test, "Memory leak test: Try to leak one byte by malloc()."}, +}; + +// Test function +void TestMain(char *cmd) +{ + char tmp[MAX_SIZE]; + bool first = true; + bool exit_now = false; + + Print("SoftEther VPN Project\n"); + Print("vpntest: VPN Server / VPN Client / VPN Bridge test program\n"); + Print("Usage: vpntest [/memcheck] [command]\n\n"); + Print("Enter '?' or 'help' to show the command list.\n"); + Print("Enter 'q' or 'exit' to exit the process.\n\n"); + Print(" - In Jurassic Park: \"It's a UNIX system! I know this!\"\n\n"); + +#ifdef OS_WIN32 + MsSetEnableMinidump(false); +#endif // OS_WIN32 + + while (true) + { + Print("TEST>"); + if (first && StrLen(cmd) != 0 && g_memcheck == false) + { + first = false; + StrCpy(tmp, sizeof(tmp), cmd); + exit_now = true; + Print("%s\n", cmd); + } + else + { + GetLine(tmp, sizeof(tmp)); + } + Trim(tmp); + if (StrLen(tmp) != 0) + { + UINT i, num; + bool b = false; + TOKEN_LIST *token = ParseCmdLine(tmp); + char *cmd = token->Token[0]; + if (!StrCmpi(cmd, "exit") || !StrCmpi(cmd, "quit") || !StrCmpi(cmd, "q")) + { + FreeToken(token); + break; + } + else if (StrCmpi(cmd, "?") == 0 || StrCmpi(cmd, "help") == 0) + { + UINT max_len = 0; + Print("Available commands:\n\n"); + num = sizeof(test_list) / sizeof(TEST_LIST); + for (i = 0;i < num;i++) + { + TEST_LIST *t = &test_list[i]; + max_len = MAX(max_len, StrLen(t->command_str)); + } + for (i = 0;i < num;i++) + { + TEST_LIST *t = &test_list[i]; + UINT len = StrLen(t->command_str); + char *pad = NULL; + if (len < max_len) + { + UINT padlen = max_len - len; + pad = MakeCharArray(' ', padlen); + } + Print(" '%s'%s : %s\n", t->command_str, pad == NULL ? "" : pad, t->help); + if (pad != NULL) + { + Free(pad); + } + } + Print("\n"); + } + else if (StartWith(tmp, "vpncmd")) + { + wchar_t *s = CopyStrToUni(tmp); + CommandMain(s); + Free(s); + } + else + { + num = sizeof(test_list) / sizeof(TEST_LIST); + for (i = 0;i < num;i++) + { + if (!StrCmpi(test_list[i].command_str, cmd)) + { + char **arg = Malloc(sizeof(char *) * (token->NumTokens - 1)); + UINT j; + for (j = 0;j < token->NumTokens - 1;j++) + { + arg[j] = CopyStr(token->Token[j + 1]); + } + test_list[i].proc(token->NumTokens - 1, arg); + for (j = 0;j < token->NumTokens - 1;j++) + { + Free(arg[j]); + } + Free(arg); + b = true; + Print("\n"); + break; + } + } + if (b == false) + { + Print("Invalid Command: %s\n\n", cmd); + } + } + FreeToken(token); + + if (exit_now) + { + break; + } + } + } + Print("Exiting...\n\n"); +} + +// Main function +int main(int argc, char *argv[]) +{ + bool memchk = false; + UINT i; + char cmd[MAX_SIZE]; + char *s; + + InitProcessCallOnce(); + + cmd[0] = 0; + if (argc >= 2) + { + for (i = 1;i < (UINT)argc;i++) + { + s = argv[i]; + if (s[0] == '/') + { + if (!StrCmpi(s, "/memcheck")) + { + memchk = true; + } + } + else + { + StrCpy(cmd, sizeof(cmd), &s[0]); + } + } + } + + InitMayaqua(memchk, true, argc, argv); + EnableProbe(true); + InitCedar(); + SetHamMode(); + TestMain(cmdline); + FreeCedar(); + FreeMayaqua(); + return 0; } +