2025-11-28 00:35:46 +09:00

242 lines
6.6 KiB
C++

// This is the main function of the executable hosting the service.
// It parses the command line and passes the parameters to the service.
// From a Sapphire perspective there is not much to see here.
#include "Service.h"
#include "string.h"
#include "wtypes.h"
#include "stdlib.h"
#include "intsafe.h"
#include "new"
HRESULT ParseCommandLine(
_In_ int argc,
_In_reads_(argc) wchar_t** argv,
_Out_ MESSAGE_ENCODING* messageEncoding,
_Out_ DWORD* chunkSize,
_Out_ long* maxConnections,
_Out_ REPORTING_LEVEL* reportingLevel,
_In_ bool server)
{
*messageEncoding = DEFAULT_ENCODING;
*chunkSize = 32768;
*maxConnections = 100;
*reportingLevel = REPORT_ERROR;
bool reportingSet = false;
// Parse the optional parameters.
for (int i = 0; i < argc; i++)
{
WCHAR* arg = argv[i];
if (!_wcsicmp(arg, L"-reporting:error") || !_wcsicmp(arg, L"/reporting:error"))
{
if (reportingSet)
{
wprintf(L"Error: More than one reporting level specified.\n");
return E_FAIL;
}
*reportingLevel = REPORT_ERROR;
reportingSet = true;
}
else if (!_wcsicmp(arg, L"-reporting:info") || !_wcsicmp(arg, L"/reporting:info"))
{
if (reportingSet)
{
wprintf(L"Error: More than one reporting level specified.\n");
return E_FAIL;
}
reportingSet = true;
*reportingLevel = REPORT_INFO;
}
else if (!_wcsicmp(arg, L"-reporting:verbose") || !_wcsicmp(arg, L"/reporting:verbose"))
{
if (reportingSet)
{
wprintf(L"Error: More than one reporting level specified.\n");
return E_FAIL;
}
reportingSet = true;
*reportingLevel = REPORT_VERBOSE;
}
else if (wcsstr(arg, L"-reporting:") || wcsstr(arg, L"-reporting:"))
{
wprintf(L"Error: Illegal reporting level specified.\n");
return E_FAIL;
}
else if (!_wcsicmp(arg, L"-encoding:binary") || !_wcsicmp(arg, L"/encoding:binary"))
{
if (DEFAULT_ENCODING != *messageEncoding)
{
wprintf(L"Error: More than one encoding specified.\n");
return E_FAIL;
}
*messageEncoding = BINARY_ENCODING;
}
else if (!_wcsicmp(arg, L"-encoding:text") || !_wcsicmp(arg, L"/encoding:text"))
{
if (DEFAULT_ENCODING != *messageEncoding)
{
wprintf(L"Error: More than one encoding specified.\n");
return E_FAIL;
}
*messageEncoding = TEXT_ENCODING;
}
else if (!_wcsicmp(arg, L"-encoding:MTOM") || !_wcsicmp(arg, L"/encoding:MTOM"))
{
if (DEFAULT_ENCODING != *messageEncoding)
{
wprintf(L"Error: More than one encoding specified.\n");
return E_FAIL;
}
*messageEncoding = MTOM_ENCODING;
}
else if (!_wcsnicmp(arg, L"-encoding:", 10) || !_wcsnicmp(arg, L"/encoding:", 10))
{
wprintf(L"Error: Illegal encoding specified.\n");
return E_FAIL;
}
else if (!_wcsnicmp(arg, L"-chunk:", 7) || !_wcsnicmp(arg, L"/chunk:", 7))
{
if (!server)
{
wprintf(L"Chunk is not a legal setting on the client side.\n");
return E_FAIL;
}
*chunkSize = wcstoul(&arg[7], NULL, 10);
}
else if (!_wcsnicmp(arg, L"-connections:", 13) || !_wcsnicmp(arg, L"/connections:", 13))
{
*maxConnections = wcstol(&arg[13], NULL, 10);
}
else
{
wprintf(L"Unrecognized parameter: %s.\n", arg);
return E_FAIL;
}
}
return S_OK;
}
int __cdecl wmain(
_In_ int argc,
_In_reads_(argc) wchar_t** argv)
{
int exitCode = -1;
bool server = true;
CFileRep* fileRep = NULL;
TRANSPORT_MODE transport = TCP_TRANSPORT;
SECURITY_MODE securityMode = NO_SECURITY;
if (argc < 3)
{
wprintf(L"Usage:\n FileRepService.exe <server/client> <Service Url> [/reporting:<error/verbose>] [/encoding:<text/binary/MTOM>]");
wprintf(L" [/connections:<number of connections>] [/chunk:<size of a the payload per message>]\n");
EXIT_FUNCTION
}
if (!_wcsicmp(argv[1], L"client"))
{
server = false;
}
else if (_wcsicmp(argv[1], L"server"))
{
wprintf(L"Must specify server or client\n");
EXIT_FUNCTION
}
LPWSTR url = argv[2];
// Default settings of optional parameters.
MESSAGE_ENCODING messageEncoding = DEFAULT_ENCODING;
DWORD chunkSize = 32768;
long maxConnections = 100;
REPORTING_LEVEL reportingLevel = REPORT_ERROR;
if (argc > 3)
{
if (FAILED(ParseCommandLine(argc - 3, &argv[3], &messageEncoding, &chunkSize, &maxConnections, &reportingLevel, server)))
{
EXIT_FUNCTION
}
}
if (FAILED(ParseTransport(url, &transport, &securityMode)))
{
wprintf(L"Illegal protocol.\n");
EXIT_FUNCTION
}
if (chunkSize > MAXMESSAGESIZE - 1024) // 1024 for overhead
{
wprintf(L"The chunk size specified exceeded the allowed maximum of %d.\n", MAXMESSAGESIZE);
EXIT_FUNCTION
}
else if (0 == chunkSize)
{
wprintf(L"The chunk size must be greater than zero.\n");
EXIT_FUNCTION
}
if (maxConnections < 1)
{
wprintf(L"You must allow at least one connection.\n");
EXIT_FUNCTION
}
if (server)
{
fileRep = new(std::nothrow) CFileRepServer(reportingLevel, maxConnections, transport, securityMode, messageEncoding, chunkSize);
}
else
{
fileRep = new(std::nothrow) CFileRepClient(reportingLevel, maxConnections, transport, securityMode, messageEncoding);
}
if (fileRep == NULL)
{
wprintf(L"Unable to create client/service.\n");
EXIT_FUNCTION
}
ULONG urlSize;
if (FAILED(SizeTToULong(::wcslen(url), &urlSize)))
{
wprintf(L"Url string too long. Exiting.\n");
EXIT_FUNCTION
}
if (FAILED(fileRep->Start(url, urlSize)))
{
wprintf(L"Service startup failed. Exiting.\n");
EXIT_FUNCTION
}
wprintf(L"Startup complete. Press any key to exit.\n");
(void)getchar();
fileRep->Stop();
wprintf(L"Shutdown complete.\n");
exitCode = 0;
EXIT
if (fileRep != NULL)
{
delete fileRep;
fileRep = NULL;
}
return exitCode;
}