diff --git a/include/opendht/dht_proxy_server.h b/include/opendht/dht_proxy_server.h index 0c00493850445467849d4823d0f59fece8a778ed..272cc975d7029d52fc2337e79c7658bb06f2788d 100644 --- a/include/opendht/dht_proxy_server.h +++ b/include/opendht/dht_proxy_server.h @@ -40,7 +40,8 @@ namespace dht { enum class PushType { None = 0, Android, - iOS + iOS, + UnifiedPush }; } MSGPACK_ADD_ENUM(dht::PushType) @@ -65,6 +66,7 @@ struct OPENDHT_PUBLIC ProxyServerConfig { std::string address {}; in_port_t port {8000}; std::string pushServer {}; + std::string unifiedPushEndpoint {}; std::string persistStatePath {}; dht::crypto::Identity identity {}; std::string bundleId {}; @@ -424,6 +426,7 @@ private: mutable std::atomic<time_point> lastStatsReset_ {time_point::min()}; std::string pushServer_; + std::string unifiedPushEndpoint_; std::string bundleId_; #ifdef OPENDHT_PUSH_NOTIFICATIONS diff --git a/src/dht_proxy_server.cpp b/src/dht_proxy_server.cpp index 3fe2aae45f7f8229b4f6e1185e1234c1722e3f98..c697fe73117b1749dad012bd906c2ed385cf1830 100644 --- a/src/dht_proxy_server.cpp +++ b/src/dht_proxy_server.cpp @@ -212,6 +212,7 @@ DhtProxyServer::DhtProxyServer(const std::shared_ptr<DhtRunner>& dht, printStatsTimer_(std::make_unique<asio::steady_timer>(*ioContext_, 3s)), connListener_(std::make_shared<ConnectionListener>(std::bind(&DhtProxyServer::onConnectionClosed, this, std::placeholders::_1))), pushServer_(config.pushServer), + unifiedPushEndpoint_(config.unifiedPushEndpoint), bundleId_(config.bundleId) { if (not dht_) @@ -762,6 +763,8 @@ DhtProxyServer::getTypeFromString(const std::string& type) { return PushType::Android; else if (type == "ios") return PushType::iOS; + else if (type == "unifiedpush") + return PushType::UnifiedPush; return PushType::None; } @@ -1012,55 +1015,65 @@ DhtProxyServer::handleCancelPushListen(const asio::error_code &ec, const std::st void DhtProxyServer::sendPushNotification(const std::string& token, Json::Value&& json, PushType type, bool highPriority, const std::string& topic) { - if (pushServer_.empty()) + if (pushServer_.empty() and unifiedPushEndpoint_.empty()) return; unsigned reqid = 0; try { - auto request = std::make_shared<http::Request>(io_context(), pushHostPort_.first, pushHostPort_.second, - pushHostPort_.first.find("https://") == 0, logger_); + auto request = type == PushType::UnifiedPush + ? std::make_shared<http::Request>(io_context(), unifiedPushEndpoint_, logger_) + : std::make_shared<http::Request>(io_context(), pushHostPort_.first, pushHostPort_.second, pushHostPort_.first.find("https://") == 0, logger_); reqid = request->id(); - request->set_target("/api/push"); + request->set_target(type == PushType::UnifiedPush ? ("/" + token) : "/api/push"); request->set_method(restinio::http_method_post()); - request->set_header_field(restinio::http_field_t::host, pushServer_.c_str()); + request->set_header_field(restinio::http_field_t::host, type == PushType::UnifiedPush ? unifiedPushEndpoint_.c_str() : pushServer_.c_str()); request->set_header_field(restinio::http_field_t::user_agent, "RESTinio client"); request->set_header_field(restinio::http_field_t::accept, "*/*"); request->set_header_field(restinio::http_field_t::content_type, "application/json"); - // NOTE: see https://github.com/appleboy/gorush - Json::Value notification(Json::objectValue); - Json::Value tokens(Json::arrayValue); - tokens[0] = token; - notification["tokens"] = std::move(tokens); - notification["platform"] = type == PushType::Android ? 2 : 1; - notification["data"] = std::move(json); - notification["priority"] = highPriority ? "high" : "normal"; - if (type == PushType::Android) - notification["time_to_live"] = 3600 * 24; // 24 hours - else { - const auto expiration = std::chrono::system_clock::now() + std::chrono::hours(24); - uint32_t exp = std::chrono::duration_cast<std::chrono::seconds>(expiration.time_since_epoch()).count(); - notification["expiration"] = exp; - if (!topic.empty()) - notification["topic"] = topic; - if (highPriority) { - Json::Value alert(Json::objectValue); - alert["title"]="hello"; - notification["push_type"] = "alert"; - notification["alert"] = alert; - notification["mutable_content"] = true; - } else { - notification["push_type"] = "background"; - notification["content_available"] = true; + if (type == PushType::UnifiedPush) { + Json::Value notification(Json::objectValue); + notification["message"] = Json::writeString(jsonBuilder_, std::move(json)); + notification["topic"] = token; + notification["priority"] = highPriority ? 5 : 1; + request->set_body(Json::writeString(jsonBuilder_, std::move(json))); + } else { + // NOTE: see https://github.com/appleboy/gorush + Json::Value notification(Json::objectValue); + Json::Value tokens(Json::arrayValue); + tokens[0] = token; + notification["tokens"] = std::move(tokens); + notification["platform"] = type == PushType::Android ? 2 : 1; + notification["data"] = std::move(json); + notification["priority"] = highPriority ? "high" : "normal"; + if (type == PushType::Android) + notification["time_to_live"] = 3600 * 24; // 24 hours + else { + const auto expiration = std::chrono::system_clock::now() + std::chrono::hours(24); + uint32_t exp = std::chrono::duration_cast<std::chrono::seconds>(expiration.time_since_epoch()).count(); + notification["expiration"] = exp; + if (!topic.empty()) + notification["topic"] = topic; + if (highPriority) { + Json::Value alert(Json::objectValue); + alert["title"]="hello"; + notification["push_type"] = "alert"; + notification["alert"] = alert; + notification["mutable_content"] = true; + } else { + notification["push_type"] = "background"; + notification["content_available"] = true; + } } - } - Json::Value notifications(Json::arrayValue); - notifications[0] = notification; + Json::Value notifications(Json::arrayValue); + notifications[0] = notification; + + Json::Value content; + content["notifications"] = std::move(notifications); + request->set_body(Json::writeString(jsonBuilder_, content)); + } - Json::Value content; - content["notifications"] = std::move(notifications); - request->set_body(Json::writeString(jsonBuilder_, content)); request->add_on_state_change_callback([this, reqid] (http::Request::State state, const http::Response& response){ if (state == http::Request::State::DONE){ diff --git a/tools/dhtnode.cpp b/tools/dhtnode.cpp index 5767641ea7da68845f830b258edd91ade98a4dd3..1c8d20a4b0d8479393be637574feebc543a5a734 100644 --- a/tools/dhtnode.cpp +++ b/tools/dhtnode.cpp @@ -43,7 +43,7 @@ void print_version() { } void print_usage() { - std::cout << "Usage: dhtnode [-v [-l logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b bootstrap_host[:port]] [--proxyserver local_port] [--proxyserverssl local_port] [--bundleid bundleid]" << std::endl << std::endl; + std::cout << "Usage: dhtnode [-v [-l logfile]] [-i] [-d] [-n network_id] [-p local_port] [-b bootstrap_host[:port]] [--proxyserver local_port] [--proxyserverssl local_port] [--bundleid bundleid] [--openpush endpoint]" << std::endl << std::endl; print_info(); } @@ -552,6 +552,7 @@ main(int argc, char **argv) serverConfig.pushServer = params.pushserver; serverConfig.bundleId = params.bundle_id; serverConfig.address = params.proxy_address; + serverConfig.unifiedPushEndpoint = params.unifiedPushEndpoint; if (params.proxyserverssl and params.proxy_id.first and params.proxy_id.second){ serverConfig.identity = params.proxy_id; serverConfig.port = params.proxyserverssl; diff --git a/tools/tools_common.h b/tools/tools_common.h index 258482ab49e2b253fe16cd211bb510ba5d4a7ff7..bb783d93946a7c1344f62d07e4beb4e772d16052 100644 --- a/tools/tools_common.h +++ b/tools/tools_common.h @@ -130,6 +130,7 @@ struct dht_params { in_port_t port {0}; in_port_t proxyserver {0}; in_port_t proxyserverssl {0}; + std::string unifiedPushEndpoint {}; std::string proxyclient {}; std::string proxy_address {}; std::string pushserver {}; @@ -225,6 +226,7 @@ static const constexpr struct option long_options[] = { {"syslog", no_argument , nullptr, 'L'}, {"proxyserver", required_argument, nullptr, 'S'}, {"proxyserverssl", required_argument, nullptr, 'e'}, + {"unifiedpush", required_argument, nullptr, 'O'}, {"proxy-addr", required_argument, nullptr, 'a'}, {"proxy-certificate", required_argument, nullptr, 'w'}, {"proxy-privkey", required_argument, nullptr, 'K'}, @@ -243,7 +245,7 @@ parseArgs(int argc, char **argv) { int opt; std::string privkey; std::string proxy_privkey; - while ((opt = getopt_long(argc, argv, "hidsvDUPp:n:b:f:l:", long_options, nullptr)) != -1) { + while ((opt = getopt_long(argc, argv, "hidsvODUPp:n:b:f:l:", long_options, nullptr)) != -1) { switch (opt) { case 'p': { int port_arg = atoi(optarg); @@ -261,6 +263,9 @@ parseArgs(int argc, char **argv) { std::cout << "Invalid port: " << port_arg << std::endl; } break; + case 'O': + params.unifiedPushEndpoint = optarg; + break; case 'e': { int port_arg = atoi(optarg); if (port_arg >= 0 && port_arg < 0x10000)