0

For some reason, I am unable to start my listener in my windows services main thread, the code compiles without warnings and I get no linking errors, the cpprestsdk DLL is loaded correctly by the process (verified it with procmon) however, the listener is not "listening" :-). The service is running as NT AUTHORITY\SYSTEM. Are there any restrictions when it comes to running this in a win32 service (x64 architecture):

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
    //
    //  Periodically check if the service has been requested to stop
    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
    {
        /*
        * Perform main service function here
        */

        webserver();
    }

    return ERROR_SUCCESS;
}

Here is the webserver() implementation:

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <map>
#include <set>
#include <string>

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
using namespace std;

void handle_GET(http_request message)
{
    message.reply(status_codes::OK, "<html><body><h1>Hello World !</h1></body></html>", u8"text/html");
    return;
}

void webserver()
{
    http_listener listener(L"http://127.0.0.1/api");
    listener.support(methods::GET, handle_GET);
    listener.open().wait();
}

This function works if I simply compile it as a normal executable and run it from main()...

Any ideas why I am getting this weird behaviour ?

PS: The service starts and stops correctly even though the listener is not working. I am using this skeleton Windows Service Template (Windows Service Template)

I am using Microsoft Visual Studio 2017 to compile everything.

EDIT: by disabling the firewall and running netstat with admin rights, it appears that the service is listening on port 80 on the 127.0.0.1 address, however I still do not get an HTTP response and the listening port seems to flap on and off when running "netstat -an | findstr 80":

Screenshot

1 Answers1

0

Ok, I ended up doing this which seems to "fix" the issue:

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <map>
#include <set>
#include <string>
#include <Windows.h>

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
using namespace std;

void handle_GET(http_request message)
{
    message.reply(status_codes::OK, "<html><body><h1>Hello World !</h1></body></html>", u8"text/html");
    return;
}

void webserver()
{
    http_listener listener(L"http://127.0.0.1/api");
    listener.support(methods::GET, handle_GET);
    listener.open().wait();
    ::Sleep(1000000000000000000);
}

But I think it's nasty and I suspect that it's just flapping on and off based on the sleep time...

#include "api.h"
#include <thread>
#include "ServiceWorkerThread.h"

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
    //
    //  Periodically check if the service has been requested to stop
    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
    {
        /*
        * Perform main service function here
        */
        webserver();
    }

    return ERROR_SUCCESS;
}

Any advice on how to do this cleaner ?

SOLUTION: I ended up changing the code like so:

#include <iostream>
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
#include <map>
#include <set>
#include <string>
#include <Windows.h>
#include "ServiceWorkerThread.h"

using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
using namespace std;

void handle_GET(http_request message)
{
    message.reply(status_codes::OK, "<html><body><h1>Hello World !</h1></body></html>", u8"text/html");
    return;
}

long webserver()
{
    http_listener listener(L"http://127.0.0.1/api");
    listener.support(methods::GET, handle_GET);
    listener.open().wait();
    //
//  Periodically check if the service has been requested to stop
    while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
    {
        /*
        * Perform main service function here
        */
    }

    return ERROR_SUCCESS;
}

#include "api.h"
#include <thread>
#include "ServiceWorkerThread.h"

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
    long ret = webserver();
    return ret;
}

In addition to making an exception in the Windows firewall...

  • Feel free to [accept your own answer](https://stackoverflow.blog/2009/01/06/accept-your-own-answers/). – Rita Han May 27 '20 at 09:20