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)
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)
add_executable(rocketChatMobilePushGateway ${SOURCE_FILES})
......
FROM afelder/proxygen:2018.1
FROM afelder/proxygen:latest
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
RUN cd /pushGateway/RocketChatMobilePushGateway \
&&cmake . \
&& cmake . \
&& make \
&& rm CMake* -rf \
&& rm cmake* -rf
......
## lightweight, push gateway for RocketChat servers
Fork of https://git.fairkom.net/chat/RocketChatMobilePushGateway
### 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,
......@@ -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)
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.pubkey
- chmod +x jose.phar
- ./jose.phar key:convert:pkcs1 $(./jose.phar key:load:key ./AuthKey_*.p8) > 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
``{
"teamId":"YOUR_APPLE_DEVELOPER_TEAM_ID",
"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
- pass port 11000
- mount your credentials folder into the container with -v /certs:/yourCertsFolder
### Docker build
- run `docker build .`
- 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/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
\ No newline at end of file
e.g. `docker run -t gateway -v /yourCertsFolder:/certs -p 0.0.0.0:80:11000 <image id>`
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -25,14 +25,17 @@
#include <algorithm>
#include <cassert>
#include <chrono>
#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 <proxygen/lib/utils/CryptUtil.h>
#include "ApplePushModel.h"
#include "../date.h"
#include "../libs/cpp-jwt/include/jwt/jwt.hpp"
#include "../libs/cpp-jwt/include/jwt/algorithm.hpp"
......@@ -128,7 +131,14 @@ bool ApplePushModel::sendMessage() {
obj["ejson"] = mPayload;
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;
CURLcode res;
......@@ -142,60 +152,59 @@ bool ApplePushModel::sendMessage() {
jwt::jwt_object obj{jwt::params::algorithm("ES256"),
jwt::params::headers({
{"alg", "ES256"},
{"kid", "3VYNV8J29D"}
{"kid", mKey}
}),
jwt::params::secret(mPem)
};
auto n = std::chrono::system_clock::now();
auto in_time_t = std::chrono::system_clock::to_time_t(n);
auto n = system_clock::now();
auto in_time_t = system_clock::to_time_t(n);
obj.add_claim("iss", mTeamId).add_claim("iat", in_time_t);
std::string encoded_jwt = obj.signature();
boost::uuids::uuid uuidObj = boost::uuids::random_generator()();
std::string uuidString = boost::lexical_cast<std::string>(uuidObj);
chunk = curl_slist_append(chunk, std::string("Authorization: Bearer "+obj.signature()).c_str());
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("apns-priority: 10").c_str());
chunk = curl_slist_append(chunk, std::string("apns-topic: "+mAppId).c_str());
std::string url = mApiUrl+mDeviceToken;
std::cout<<url<<std::endl;
// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, trace );
curl_easy_setopt(curl, CURLOPT_VERBOSE, false);
curl_easy_setopt(curl, CURLOPT_URL,url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,json.size());
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_USE_SSL, true);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
res = curl_easy_perform(curl);
chunk = curl_slist_append(chunk, std::string("Authorization: Bearer "+obj.signature()).c_str());
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("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;
// curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, trace );
curl_easy_setopt(curl, CURLOPT_VERBOSE, false);
curl_easy_setopt(curl, CURLOPT_URL,url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,json.size());
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_USE_SSL, true);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true);
curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tApple push result\t";
res = curl_easy_perform(curl);
std::cout << std::endl;
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){
std::cerr<<"curl error: "<<curl_easy_strerror(res)<<std::endl;
}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);
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
} catch (std::exception &e) {
std::cout<<e.what()<<std::endl;
std::cout << "[" << system_clock::now() << "] " << e.what() << std::endl;
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
return false;
......@@ -224,13 +233,13 @@ void ApplePushModel::loadApiKey() {
mTeamId = std::move(teamId);
mKey = std::move(key);
}else{
std::cout<<"Error JSON data invalid"<<std::endl;
std::cout << "Error JSON data invalid" << std::endl;
exit(EXIT_FAILURE);
}
}
}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);
}
}
......@@ -26,6 +26,12 @@
#include <cstdlib>
#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/String.h>
#include <folly/io/async/SSLContext.h>
......@@ -34,7 +40,9 @@
#include <proxygen/lib/http/HTTPMessage.h>
#include <proxygen/lib/http/session/HTTPUpstreamSession.h>
#include <proxygen/lib/http/codec/HTTP2Codec.h>
#include "GooglePushModel.h"
#include "../date.h"
std::string GooglePushModel::mApiKey;
......@@ -42,11 +50,11 @@ void GooglePushModel::loadApiKey() {
std::ifstream ifs("/certs/google/serverKey.txt");
std::string content((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
if(content.length()){
if (content.length()) {
std::regex newLine("([\\n]+)");
GooglePushModel::mApiKey = std::regex_replace(content,newLine,"");
}else{
std::cout<<"Error loading Google Push Key: file: /certs/google/serverKey.txt is empty or does not exist";
} else {
std::cout << "Error loading Google Push Key: file: /certs/google/serverKey.txt is empty or does not exist";
exit(EXIT_FAILURE);
}
}
......@@ -56,7 +64,7 @@ GooglePushModel::GooglePushModel(const std::string &pJson) {
Json::Value obj;
Json::FastWriter fast;
if(pJson.length()) {
if (pJson.length()) {
reader.parse(pJson, obj);
if (obj.isMember("token") && obj.isMember("options")) {
......@@ -68,9 +76,9 @@ GooglePushModel::GooglePushModel(const std::string &pJson) {
if (apn.isMember("text")) {
std::string temp = std::move(apn["text"].asString());
unsigned long index = 0;
while(true){
while (true){
index = temp.find('\n',index);
if(index == std::string::npos){
if (index == std::string::npos) {
break;
}
temp.replace(index, 1, "\\r\\n");
......@@ -119,7 +127,7 @@ int GooglePushModel::trace(CURL *handle, curl_infotype type,
switch (type) {
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 */
return 0;
......@@ -143,7 +151,7 @@ int GooglePushModel::trace(CURL *handle, curl_infotype type,
break;
}
std::cerr<<text<<": "<<data<<std::endl;
std::cerr << text << ": " << data << std::endl;
return 0;
}
......@@ -171,8 +179,15 @@ bool GooglePushModel::sendMessage() {
CURL *curl;
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();
if(curl){
if (curl) {
struct curl_slist *chunk = nullptr;
......@@ -190,13 +205,14 @@ bool GooglePushModel::sendMessage() {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, true);
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push result\t";
res = curl_easy_perform(curl);
std::cout << std::endl;
if(res != CURLE_OK){
std::cerr<<"curl error: "<<curl_easy_strerror(res)<<std::endl;
}else{
if (res != CURLE_OK) {
std::cerr << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push conn error: " << curl_easy_strerror(res) << std::endl;
} else {
std::cout << "[" << system_clock::now() << "]\t" << uuidString << "\tGoogle push conn status: OK" << std::endl;
curl_easy_cleanup(curl);
curl_slist_free_all(chunk);
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