Commit a99bc9d4 authored by armin's avatar armin
Browse files

Merge branch 'fixesByQ210' into 'master'

Fixes by q210

Closes #3

See merge request !4
parents 39582ef9 2f1f9a49
...@@ -15,7 +15,7 @@ include_directories(libs/cpp-jwt/include) ...@@ -15,7 +15,7 @@ include_directories(libs/cpp-jwt/include)
include_directories(libs/cpp-base64) include_directories(libs/cpp-base64)
set(SOURCE_FILES main.cpp HandlerFactory.cpp handlers/NorFoundHandler.cpp utils.cpp utils.h handlers/ApplePushHandler.cpp handlers/ApplePushHandler.h handlers/GooglePushHandler.cpp handlers/GooglePushHandler.h models/GooglePushModel.cpp models/GooglePushModel.h models/ApplePushModel.cpp models/ApplePushModel.h set(SOURCE_FILES main.cpp HandlerFactory.cpp handlers/NorFoundHandler.cpp utils.cpp utils.h date.h handlers/ApplePushHandler.cpp handlers/ApplePushHandler.h handlers/GooglePushHandler.cpp handlers/GooglePushHandler.h models/GooglePushModel.cpp models/GooglePushModel.h models/ApplePushModel.cpp models/ApplePushModel.h
libs/cpp-jwt/include/jwt/jwt.hpp libs/cpp-base64/base64.h libs/cpp-base64/base64.cpp) libs/cpp-jwt/include/jwt/jwt.hpp libs/cpp-base64/base64.h libs/cpp-base64/base64.cpp)
add_executable(rocketChatMobilePushGateway ${SOURCE_FILES}) add_executable(rocketChatMobilePushGateway ${SOURCE_FILES})
......
FROM afelder/proxygen:2018.1 FROM afelder/proxygen:latest
LABEL maintainer="armin.felder@osalliance.com" LABEL maintainer="armin.felder@osalliance.com"
RUN apt-get update && apt-get --yes install libjsoncpp-dev libcurl4-openssl-dev cmake && apt-get clean
ADD . /pushGateway/RocketChatMobilePushGateway ADD . /pushGateway/RocketChatMobilePushGateway
RUN cd /pushGateway/RocketChatMobilePushGateway \ RUN cd /pushGateway/RocketChatMobilePushGateway \
&&cmake . \ && cmake . \
&& make \ && make \
&& rm CMake* -rf \ && rm CMake* -rf \
&& rm cmake* -rf && rm cmake* -rf
......
## lightweight, push gateway for RocketChat servers ## lightweight, push gateway for RocketChat servers
Fork of https://git.fairkom.net/chat/RocketChatMobilePushGateway
### usage ### usage
How do mobile devices get push notifications? The Android app is registering itself with Google Firebase Messaging (former GCM), by using given credentials, built into the app, How do mobile devices get push notifications? The Android app is registering itself with Google Firebase Messaging (former GCM), by using given credentials, built into the app,
...@@ -27,6 +29,7 @@ This project has dependencies, included via submodules, so you have to clone rec ...@@ -27,6 +29,7 @@ This project has dependencies, included via submodules, so you have to clone rec
1. create key (see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token_based_connection_to_apns) 1. create key (see https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/establishing_a_token_based_connection_to_apns)
2. convert the *.p8 to pem 2. convert the *.p8 to pem
- wget https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar - wget https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar
- wget https://github.com/web-token/jwt-app/raw/gh-pages/jose.phar.pubkey
- chmod +x jose.phar - chmod +x jose.phar
- ./jose.phar key:convert:pkcs1 $(./jose.phar key:load:key ./AuthKey_*.p8) > key.pem - ./jose.phar key:convert:pkcs1 $(./jose.phar key:load:key ./AuthKey_*.p8) > key.pem
3. save the pem file apple/key.pem 3. save the pem file apple/key.pem
...@@ -35,13 +38,14 @@ This project has dependencies, included via submodules, so you have to clone rec ...@@ -35,13 +38,14 @@ This project has dependencies, included via submodules, so you have to clone rec
``{ ``{
"teamId":"YOUR_APPLE_DEVELOPER_TEAM_ID", "teamId":"YOUR_APPLE_DEVELOPER_TEAM_ID",
"key": "THE_KEY_RELATED_TO_THE_p8(also part of the name AuthKey_[KEY].p8)", "key": "THE_KEY_RELATED_TO_THE_p8(also part of the name AuthKey_[KEY].p8)",
"appId": "YOUR_APP_ID" "appId": "YOUR_APP_ID (Bundle Id)"
}`` }``
### Docker ### Docker build
- pass port 11000 - run `docker build .`
- mount your credentials folder into the container with -v /certs:/yourCertsFolder - place the credentials in the servers "credentials" directory (see "manual build instructions" for details)
- mount your credentials folder into the container with -v /yourCertsFolder:/certs and run image
- yourCertsFolder/google/serverKey.txt - yourCertsFolder/google/serverKey.txt
- yourCertsFolder/apple/cred.pem (see https://github.com/joshuakuai/PusherCpp) - yourCertsFolder/apple/cred.pem (see https://github.com/joshuakuai/PusherCpp)
e.g. docker run -t gateway -v /yourCertsFolder:/certs -p 0.0.0.0:80:11000 e.g. `docker run -t gateway -v /yourCertsFolder:/certs -p 0.0.0.0:80:11000 <image id>`
\ No newline at end of file \ No newline at end of file
This diff is collapsed.
...@@ -25,14 +25,17 @@ ...@@ -25,14 +25,17 @@
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <chrono> #include <chrono>
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp> #include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/string_generator.hpp> #include <boost/uuid/string_generator.hpp>
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid_io.hpp> #include <boost/uuid/uuid_io.hpp>
#include <proxygen/lib/utils/CryptUtil.h> #include <proxygen/lib/utils/CryptUtil.h>
#include "ApplePushModel.h" #include "ApplePushModel.h"
#include "../date.h"
#include "../libs/cpp-jwt/include/jwt/jwt.hpp" #include "../libs/cpp-jwt/include/jwt/jwt.hpp"
#include "../libs/cpp-jwt/include/jwt/algorithm.hpp" #include "../libs/cpp-jwt/include/jwt/algorithm.hpp"
...@@ -128,7 +131,14 @@ bool ApplePushModel::sendMessage() { ...@@ -128,7 +131,14 @@ bool ApplePushModel::sendMessage() {
obj["ejson"] = mPayload; obj["ejson"] = mPayload;
std::string json = fast.write(obj); std::string json = fast.write(obj);
std::cout<<json<<std::endl;
using namespace date;
using namespace std::chrono;
boost::uuids::uuid uuidObj = boost::uuids::random_generator()();
std::string uuidString = boost::lexical_cast<std::string>(uuidObj);
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tApple push data\t" << json << std::endl;
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
...@@ -142,60 +152,59 @@ bool ApplePushModel::sendMessage() { ...@@ -142,60 +152,59 @@ bool ApplePushModel::sendMessage() {
jwt::jwt_object obj{jwt::params::algorithm("ES256"), jwt::jwt_object obj{jwt::params::algorithm("ES256"),
jwt::params::headers({ jwt::params::headers({
{"alg", "ES256"}, {"alg", "ES256"},
{"kid", "3VYNV8J29D"} {"kid", mKey}
}), }),
jwt::params::secret(mPem) jwt::params::secret(mPem)
}; };
auto n = std::chrono::system_clock::now(); auto n = system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(n); auto in_time_t = system_clock::to_time_t(n);
obj.add_claim("iss", mTeamId).add_claim("iat", in_time_t); obj.add_claim("iss", mTeamId).add_claim("iat", in_time_t);
std::string encoded_jwt = obj.signature(); std::string encoded_jwt = obj.signature();
boost::uuids::uuid uuidObj = boost::uuids::random_generator()(); chunk = curl_slist_append(chunk, std::string("Authorization: Bearer "+obj.signature()).c_str());
std::string uuidString = boost::lexical_cast<std::string>(uuidObj); chunk = curl_slist_append(chunk, std::string("apns-id: "+uuidString).c_str());
chunk = curl_slist_append(chunk, std::string("apns-expiration: 0").c_str());
chunk = curl_slist_append(chunk, std::string("Authorization: Bearer "+obj.signature()).c_str()); chunk = curl_slist_append(chunk, std::string("apns-priority: 10").c_str());
chunk = curl_slist_append(chunk, std::string("apns-id: "+uuidString).c_str()); chunk = curl_slist_append(chunk, std::string("apns-topic: "+mAppId).c_str());
chunk = curl_slist_append(chunk, std::string("apns-expiration: 0").c_str());
chunk = curl_slist_append(chunk, std::string("apns-priority: 10").c_str());
chunk = curl_slist_append(chunk, std::string("apns-topic: "+mAppId).c_str()); std::string url = mApiUrl+mDeviceToken;
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tApple push url\t" << url << std::endl;
std::string url = mApiUrl+mDeviceToken;
// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, trace );
std::cout<<url<<std::endl; curl_easy_setopt(curl, CURLOPT_VERBOSE, false);
curl_easy_setopt(curl, CURLOPT_URL,url.c_str());
// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, trace ); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
curl_easy_setopt(curl, CURLOPT_VERBOSE, false); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,json.size());
curl_easy_setopt(curl, CURLOPT_URL,url.c_str()); curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str()); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,json.size()); curl_easy_setopt(curl, CURLOPT_USE_SSL, true);
curl_easy_setopt(curl, CURLOPT_POST, true); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk); curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true);
curl_easy_setopt(curl, CURLOPT_USE_SSL, true); curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true); std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tApple push result\t";
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); res = curl_easy_perform(curl);
std::cout << std::endl;
res = curl_easy_perform(curl); if (res != CURLE_OK) {
std::cerr<< "[" << system_clock::now() << "]\t" << uuidString << "\tApple push conn error: " << curl_easy_strerror(res) << std::endl;
} else {
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tApple push conn status: OK " << std::endl;
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
return true;
}
if(res != CURLE_OK){ curl_easy_cleanup(curl);
std::cerr<<"curl error: "<<curl_easy_strerror(res)<<std::endl; curl_slist_free_all(chunk);
}else{
std::cout<<"result: "<<res<<std::endl;
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
return true;
}
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
} catch (std::exception &e) { } catch (std::exception &e) {
std::cout<<e.what()<<std::endl; std::cout << "[" << system_clock::now() << "] " << e.what() << std::endl;
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_slist_free_all(chunk); curl_slist_free_all(chunk);
return false; return false;
...@@ -224,13 +233,13 @@ void ApplePushModel::loadApiKey() { ...@@ -224,13 +233,13 @@ void ApplePushModel::loadApiKey() {
mTeamId = std::move(teamId); mTeamId = std::move(teamId);
mKey = std::move(key); mKey = std::move(key);
}else{ }else{
std::cout<<"Error JSON data invalid"<<std::endl; std::cout << "Error JSON data invalid" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
}else{ }else{
std::cout<<"Error loading APNS credentials, check if the settings.json, and key.pem exists"<<std::endl; std::cout << "Error loading APNS credentials, check if the settings.json, and key.pem exists" << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -26,6 +26,12 @@ ...@@ -26,6 +26,12 @@
#include <cstdlib> #include <cstdlib>
#include <regex> #include <regex>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/string_generator.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <folly/FileUtil.h> #include <folly/FileUtil.h>
#include <folly/String.h> #include <folly/String.h>
#include <folly/io/async/SSLContext.h> #include <folly/io/async/SSLContext.h>
...@@ -34,7 +40,9 @@ ...@@ -34,7 +40,9 @@
#include <proxygen/lib/http/HTTPMessage.h> #include <proxygen/lib/http/HTTPMessage.h>
#include <proxygen/lib/http/session/HTTPUpstreamSession.h> #include <proxygen/lib/http/session/HTTPUpstreamSession.h>
#include <proxygen/lib/http/codec/HTTP2Codec.h> #include <proxygen/lib/http/codec/HTTP2Codec.h>
#include "GooglePushModel.h" #include "GooglePushModel.h"
#include "../date.h"
std::string GooglePushModel::mApiKey; std::string GooglePushModel::mApiKey;
...@@ -42,11 +50,11 @@ void GooglePushModel::loadApiKey() { ...@@ -42,11 +50,11 @@ void GooglePushModel::loadApiKey() {
std::ifstream ifs("/certs/google/serverKey.txt"); std::ifstream ifs("/certs/google/serverKey.txt");
std::string content((std::istreambuf_iterator<char>(ifs)), std::string content((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>())); (std::istreambuf_iterator<char>()));
if(content.length()){ if (content.length()) {
std::regex newLine("([\\n]+)"); std::regex newLine("([\\n]+)");
GooglePushModel::mApiKey = std::regex_replace(content,newLine,""); GooglePushModel::mApiKey = std::regex_replace(content,newLine,"");
}else{ } else {
std::cout<<"Error loading Google Push Key: file: /certs/google/serverKey.txt is empty or does not exist"; std::cout << "Error loading Google Push Key: file: /certs/google/serverKey.txt is empty or does not exist";
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -56,7 +64,7 @@ GooglePushModel::GooglePushModel(const std::string &pJson) { ...@@ -56,7 +64,7 @@ GooglePushModel::GooglePushModel(const std::string &pJson) {
Json::Value obj; Json::Value obj;
Json::FastWriter fast; Json::FastWriter fast;
if(pJson.length()) { if (pJson.length()) {
reader.parse(pJson, obj); reader.parse(pJson, obj);
if (obj.isMember("token") && obj.isMember("options")) { if (obj.isMember("token") && obj.isMember("options")) {
...@@ -68,9 +76,9 @@ GooglePushModel::GooglePushModel(const std::string &pJson) { ...@@ -68,9 +76,9 @@ GooglePushModel::GooglePushModel(const std::string &pJson) {
if (apn.isMember("text")) { if (apn.isMember("text")) {
std::string temp = std::move(apn["text"].asString()); std::string temp = std::move(apn["text"].asString());
unsigned long index = 0; unsigned long index = 0;
while(true){ while (true){
index = temp.find('\n',index); index = temp.find('\n',index);
if(index == std::string::npos){ if (index == std::string::npos) {
break; break;
} }
temp.replace(index, 1, "\\r\\n"); temp.replace(index, 1, "\\r\\n");
...@@ -119,7 +127,7 @@ int GooglePushModel::trace(CURL *handle, curl_infotype type, ...@@ -119,7 +127,7 @@ int GooglePushModel::trace(CURL *handle, curl_infotype type,
switch (type) { switch (type) {
case CURLINFO_TEXT: case CURLINFO_TEXT:
std::cerr<<"== Info:"<< data<<std::endl; std::cerr << "== Info:" << data << std::endl;
default: /* in case a new one is introduced to shock us */ default: /* in case a new one is introduced to shock us */
return 0; return 0;
...@@ -143,7 +151,7 @@ int GooglePushModel::trace(CURL *handle, curl_infotype type, ...@@ -143,7 +151,7 @@ int GooglePushModel::trace(CURL *handle, curl_infotype type,
break; break;
} }
std::cerr<<text<<": "<<data<<std::endl; std::cerr << text << ": " << data << std::endl;
return 0; return 0;
} }
...@@ -171,8 +179,15 @@ bool GooglePushModel::sendMessage() { ...@@ -171,8 +179,15 @@ bool GooglePushModel::sendMessage() {
CURL *curl; CURL *curl;
CURLcode res; CURLcode res;
using namespace date;
using namespace std::chrono;
boost::uuids::uuid uuidObj = boost::uuids::random_generator()();
std::string uuidString = boost::lexical_cast<std::string>(uuidObj);
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push data\t" << data << std::endl;
curl = curl_easy_init(); curl = curl_easy_init();
if(curl){ if (curl) {
struct curl_slist *chunk = nullptr; struct curl_slist *chunk = nullptr;
...@@ -190,13 +205,14 @@ bool GooglePushModel::sendMessage() { ...@@ -190,13 +205,14 @@ bool GooglePushModel::sendMessage() {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true); curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true);
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push result\t";
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
std::cout << std::endl;
if(res != CURLE_OK){ if (res != CURLE_OK) {
std::cerr<<"curl error: "<<curl_easy_strerror(res)<<std::endl; std::cerr << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push conn error: " << curl_easy_strerror(res) << std::endl;
}else{ } else {
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push conn status: OK" << std::endl;
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_slist_free_all(chunk); curl_slist_free_all(chunk);
return true; return true;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment