Automatically pausing/continuing a service when OS suspends - notifications

I made a Windows Service process that can be started/stopped/paused/continued.
The service is created with CreateService() and the service starts a service controller with RegisterServiceCtrlHandlerExA().
Even though the service can subscribe to power setting notifications using RegisterPowerSettingNotification() I find that these only represent events like battery/mains for laptops, and such. Not for suspend/sleep of the OS.
How can I tell the SCM to automatically pause my service before the OS suspends/sleeps? And continue my service after it wakes up again?

This requires calling the PowerRegisterSuspendResumeNotification() function.
For this, you need to #include <powrprof.h> and link against powrprof.lib.
The callback itself looks like:
static ULONG DeviceNotifyCallbackRoutine
(
PVOID Context,
ULONG Type, // PBT_APMSUSPEND, PBT_APMRESUMESUSPEND, or PBT_APMRESUMEAUTOMATIC
PVOID Setting // Unused
)
{
LOGI("DeviceNotifyCallbackRoutine");
if (Type == PBT_APMSUSPEND)
{
turboledz_pause_all_devices();
LOGI("Devices paused.");
}
if (Type == PBT_APMRESUMEAUTOMATIC)
{
turboledz_paused = 0;
LOGI("Device unpaused.");
}
return 0;
}
static DEVICE_NOTIFY_SUBSCRIBE_PARAMETERS notifycb =
{
DeviceNotifyCallbackRoutine,
NULL,
};
And then register it with:
HPOWERNOTIFY registration;
const DWORD registered = PowerRegisterSuspendResumeNotification
(
DEVICE_NOTIFY_CALLBACK,
&notifycb,
&registration
);
if (registered != ERROR_SUCCESS)
{
const DWORD err = GetLastError();
LOGI("PowerRegisterSuspendResumeNotification failed with error 0x%lx", err);
}

Related

boost::asio: how can I make some clients listen to server and other client read/write to server at the same time

I am a novice about boost::asio, I write a server, some clients can connect to it and keep listening.
class socket_server {
public:
~socket_server() { io_context.stop(); };
int server_process();
private:
boost::asio::io_context io_context;
};
int socket_server::server_process() {
try {
unlink("/var/run/socket");
server s(io_context, "/var/run/socket");
INFO("server_process, start run\n");
io_context.run();
} catch (std::exception &e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
class server {
public:
server(boost::asio::io_context &io_context, const std::string &file)
: acceptor_(io_context, stream_protocol::endpoint(file)), socket_id_(0) {
do_accept();
}
private:
void do_accept();
stream_protocol::acceptor acceptor_;
int socket_id_;
};
void server::do_accept() {
INFO("do accept\n");
acceptor_.async_accept(
[this](std::error_code ec, stream_protocol::socket socket) {
if (!ec) {
INFO("new session create\n");
std::make_shared<session>(std::move(socket), socket_id_++)->start();
}
do_accept();
});
}
class session : public std::enable_shared_from_this<session> {
public:
session(stream_protocol::socket sock, int socket_id)
: socket_(std::move(sock)), socket_id_(socket_id) {}
~session() { socket_id_--; }
void start();
private:
void do_read();
void do_write(std::array<char, 1024> data);
int get_id() { return socket_id_; }
// The socket used to communicate with the client.
stream_protocol::socket socket_;
// Buffer used to store data received from the client.
std::array<char, 1024> data_;
int socket_id_;
};
void session::start() { do_read(); }
void session::do_read() {
INFO("in do_read\n");
auto self(shared_from_this());
socket_.async_read_some(
boost::asio::buffer(data_),
[this, self](std::error_code ec, std::size_t length) {
if (!ec) {
if (request.find("listen") != std::string::npos) {
std::unique_lock<std::mutex> lock(unsol_mutex);
unsol_cond.wait(lock)
do_write(get_unsol_data());
} else {
std::unique_lock<std::mutex> lock(send_mutex);
if (send_cond.wait_for(lock, std::chrono::seconds(2)) ==
std::cv_status::timeout) {
ERROR("response time out\n");
}
do_write(get_write_data());
}
}
});
}
In do_read(), I found when a client is listening (block in unsol_cond.wait(lock)), another client can not go to do_read().
Is it due to make_shared session? Is there a better implementation suggestion?
Thanks~
You're using blocking synchronization primitives in async code. That's an anti-pattern.
Firstly, as you noticed, the blocking operations will prevent the event loop from progressing.
Secondly, holding locks across async calls is often a bug (it doesn't guard the critical execution during execution of the async operation).
For simple integration with Asio proactor model, you can often
use a strand instead.
Under the hood, it will end up using mutexes, just like now, but only
if the concurrency model requires it. That mainly depends on the
execution context used and/or how many threads are running the
services.
Use a queue with a async send-chain. I have quite a few answers on this site that show you how to do that.
I would gladly demonstrate, but the code is too incomplete, and the naming doesn't really give me an idea what things mean ("listen"/"unsol"?, nothing ever signals those conditions so... hard to guess what they do in reality)

WxSocket (Was not declared in this scope)

Hello, if i try to build this code here, ill get a error and dont know what to do.
void wxsocket_test_finalFrame::OnServerStart(wxCommandEvent& WXUNUSED(event))
{
// Create the address - defaults to localhost:0 initially
wxIPV4address addr;
addr.Service(3000);
// Create the socket. We maintain a class pointer so we can
// shut it down
m_server = new wxSocketServer(addr);
// We use Ok() here to see if the server is really listening
if (! m_server->Ok())
{
return;
}
// Set up the event handler and subscribe to connection events
m_server->SetEventHandler(*this, SERVER_ID);
m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
m_server->Notify(true);
}
void wxsocket_test_finalFrame::OnServerEvent(wxSocketEvent& WXUNUSED(event))
{
// Accept the new connection and get the socket pointer
wxSocketBase* sock = m_server->Accept(false);
// Tell the new socket how and where to process its events
sock->SetEventHandler(*this, SOCKET_ID);
sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
sock->Notify(true);
}
void wxsocket_test_finalFrame::OnSocketEvent(wxSocketEvent& event)
{
wxSocketBase *sock = event.GetSocket();
// Process the event
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT:
{
char buf[10];
// Read the data
sock->Read(buf, sizeof(buf));
// Write it back
sock->Write(buf, sizeof(buf));
// We are done with the socket, destroy it
sock->Destroy();
break;
}
case wxSOCKET_LOST:
{
sock->Destroy();
break;
}
}
}
\wxsocket_test_finalMain.cpp|99|error: 'm_server' was not declared in this scope|
OS: Windows
Compiler: gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
im a bloody newbie and cant figure out what is happening here, someone has a clue ?

How to call a service through a menu-driven application in Ballerina

I have a file main.bal which contains the prints the menu and deals with user input. gmail_service.bal file contains a hello service which has the ability to send emails.
main.bal
function main(string... args) {
int c = 0;
while ( c != 2) {
// print options menu to choose from
io:println("-------------------------------------------------------------------------");
io:println("1. Email");
io:println("2. Exit");
io:println("-------------------------------------------------------------------------");
// read user's choice
string choice = io:readln("Enter choice 1 - 2: ");
c = check <int>choice;
if (c == 1) {
//code to send email
}
if (c == 2) {
break;
}
}
}
gmail_service.bal
// A system package containing protocol access constructs
// Package objects referenced with 'http:' in code
import ballerina/http;
import ballerina/io;
import wso2/gmail;
import ballerina/config;
endpoint gmail:Client gmailEP {
clientConfig:{
auth:{
accessToken:config:getAsString("accessToken"),
clientId:config:getAsString("clientId"),
clientSecret:config:getAsString("clientSecret"),
refreshToken:config:getAsString("refreshToken")
}
}
};
documentation {
A service endpoint represents a listener.
}
endpoint http:Listener listener {
port:9090
};
documentation {
A service is a network-accessible API
Advertised on '/hello', port comes from listener endpoint
}
#http:ServiceConfig {
basePath: "/"
}
service<http:Service> hello bind listener {
#http:ResourceConfig {
methods: ["POST"],
path: "/"
}
documentation {
A resource is an invokable API method
Accessible at '/hello/sayHello
'caller' is the client invoking this resource
P{{caller}} Server Connector
P{{request}} Request
}
sayHello (endpoint caller, http:Request request) {
gmail:MessageRequest messageRequest;
messageRequest.recipient = "abc#gmail.com";
messageRequest.sender = "efg#gmail.com";
messageRequest.cc = "";
messageRequest.subject = "Email-Subject";
messageRequest.messageBody = "Email Message Body Text";
//Set the content type of the mail as TEXT_PLAIN or TEXT_HTML.
messageRequest.contentType = gmail:TEXT_PLAIN;
//Send the message.
var sendMessageResponse = gmailEP -> sendMessage("efg#gmail.com", messageRequest);
}
}
How can I invoke the gmail service when the user enters "1"?
In Ballerina, we interact with network-accessible points such as services through endpoints. For example, the your Gmail service source, you have used two endpoints: a listener endpoint and a client endpoint. The listener endpoint is used to bind your hello service to a port and the client endpoint is used to invoke a 3rd party API (the Gmail API).
Similarly, to invoke your hello service from your main() function, you need to create an HTTP client endpoint for the service. You will be interacting with your service through this endpoint. The modified source for main.bal would look something like below. Note that a payload hasn't been set to the POST request since the request body is not used anywhere in the hello service.
import ballerina/http;
import ballerina/io;
endpoint http:Client emailClient {
url: "http://localhost:9090"
};
function main(string... args) {
int c = 0;
while ( c != 2) {
// print options menu to choose from
io:println("-------------------------------------------------------------------------");
io:println("1. Email");
io:println("2. Exit");
io:println("-------------------------------------------------------------------------");
// read user's choice
string choice = io:readln("Enter choice 1 - 2: ");
c = check <int>choice;
if (c == 1) {
http:Response response = check emailClient->post("/", ());
// Do whatever you want with the response
}
if (c == 2) {
break;
}
}
}

Listening for BlueTooth state Changes with React-Native - Android

I am working with a team of React-Native JS developers who asked me to give them a native module for listening for Bluetooth state changes.
I created a ReactMethod that takes a Callback:
#ReactMethod
public void registerForBlueToothStateChanges(Callback listener){
mainActivity = (MainActivity)getCurrentActivity();
mainActivity.registerBTStateChangeListener(listener);
}
This method essentially is designed to set a Callback that will be used by my broadcast Receiver and at the same time send the current Bluetooth state back to the call back.. That all works fine, but in my Actual BroadCast Receiver i get an error: "The callback registerForBlueToothStateChanges() exists in module TripManager, but only one callback maybe registered to a function in a native Module"
Main Activity Relative Code:
#Subscribe
public void onBluetoothStateChanged(BluetoothStateChange state){
//check against current state to avoid duplicate offs
Log.v(TAG, "STATE CHANGED WOOT");
if(!state.equals(lastBluetoothState)){
lastBluetoothState = state;
Log.v(TAG, "BT STATE CHANGE***: "+state +" "+state.equals(BluetoothStateChange.ON));
if(blueToothStateListener != null) {
int i = 0;
if (state.equals(BluetoothStateChange.ON)) {
i = 1;
}
sendBTStateChange(i);
}
}
lastBluetoothState = state;
}
public void registerBTStateChangeListener(Callback listener){
blueToothStateListener = listener;
int i = 0;
if(lastBluetoothState.equals(BluetoothStateChange.ON)){
i = 1;
}
sendBTStateChange(i);
}
private void sendBTStateChange(int code){
blueToothStateListener.invoke(code);
}
Any pointers how i can get around this?

How to use Pub/sub with hiredis in C++?

I am trying to test this pub/sub function of redis with hiredis client via c++.
I can see that subscribing to certain channel seems to be easy enough to do through redisCommand Api.
However I am wondering how the reply is coming back when somebody publish to the certain server.
Thank you
https://github.com/redis/hiredis/issues/55
aluiken commented on Mar 2, 2012
void onMessage(redisAsyncContext *c, void *reply, void *privdata) {
redisReply *r = reply;
if (reply == NULL) return;
if (r->type == REDIS_REPLY_ARRAY) {
for (int j = 0; j < r->elements; j++) {
printf("%u) %s\n", j, r->element[j]->str);
}
}
}
int main (int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
struct event_base *base = event_base_new();
redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379);
if (c->err) {
printf("error: %s\n", c->errstr);
return 1;
}
redisLibeventAttach(c, base);
redisAsyncCommand(c, onMessage, NULL, "SUBSCRIBE testtopic");
event_base_dispatch(base);
return 0;
}
This is a late answer, but you can try redis-plus-plus, which is based on hiredis, and written in C++ 11.
Disclaimer: I'm the author of this library. If you have any problem with this client, feel free to let me know. If you like it, also feel free to star it :)
Sample code:
Redis redis("tcp://127.0.0.1:6379");
// Create a Subscriber.
auto sub = redis.subscriber();
// Set callback functions.
sub.on_message([](std::string channel, std::string msg) {
// Process message of MESSAGE type.
});
sub.on_pmessage([](std::string pattern, std::string channel, std::string msg) {
// Process message of PMESSAGE type.
});
sub.on_meta([](Subscriber::MsgType type, OptionalString channel, long long num) {
// Process message of META type.
});
// Subscribe to channels and patterns.
sub.subscribe("channel1");
sub.subscribe({"channel2", "channel3"});
sub.psubscribe("pattern1*");
// Consume messages in a loop.
while (true) {
try {
sub.consume();
} catch (...) {
// Handle exceptions.
}
}
Check the doc for detail.
Observer pattern is what we see in pub/sub feature of Redis.
All subscribers are observers and subject is the channel which is being modified by publishers.
When a publisher modifies a channel i.e. executes command like redis-cli> publish foo value
This change is communicated by Redis server to all observers (i.e. subscribers)
So Redis server has list of all observers for a particular channel.