1#include <fc/network/gntp.hpp>
6#include <fc/network/tcp_socket.hpp>
14#include <boost/lexical_cast.hpp>
15#include <boost/foreach.hpp>
16#include <boost/algorithm/string/case_conv.hpp>
22 static std::string calc_sha1_base32_of_buffer(
const std::string& buffer)
24 sha1::encoder sha1_encoder;
25 sha1_encoder.write(buffer.c_str(), buffer.size());
26 sha1 sha1_result = sha1_encoder.result();
27 string sha1_result_base32 =
to_base32((
char*)&sha1_result,
sizeof(sha1_result));
28 return sha1_result_base32.c_str();
48 gntp_notifier_impl(
const std::string& host_to_notify =
"127.0.0.1",
uint16_t port = 23053,
const std::optional<std::string>& password = std::optional<std::string>());
60 std::optional<boost::asio::ip::tcp::endpoint>
endpoint;
69 const std::optional<std::string>& password ) :
70 hostname(host_to_notify),
73 connection_failed(false),
80 std::shared_ptr<boost::asio::ip::tcp::socket> sock(
new boost::asio::ip::tcp::socket(asio::default_io_service()));
82 bool connected =
false;
88 asio::tcp::connect(*sock, *
endpoint);
93 ilog(
"Failed to connect to GNTP service using an endpoint that previously worked: ${error_report}",
97 endpoint = std::optional<boost::asio::ip::tcp::endpoint>();
101 ilog(
"Failed to connect to GNTP service using an endpoint that previously worked");
104 endpoint = std::optional<boost::asio::ip::tcp::endpoint>();
110 auto eps = asio::tcp::resolve(
hostname, boost::lexical_cast<std::string>(
port));
114 for (
uint32_t i = 0; i < eps.size(); ++i)
118 boost::system::error_code ec;
119 ilog(
"Attempting to connect to GNTP srvice");
120 asio::tcp::connect(*sock, eps[i]);
127 ilog(
"Failed to connect to GNTP service: ${error_reprot}",
133 ilog(
"Failed to connect to GNTP service");
139 FC_THROW(
"Unable to connect to any resolved endpoint for ${host}:${port}",
143 asio::ostream<boost::asio::ip::tcp::socket> write_stream(sock);
144 write_stream.write(message.c_str(), message.size());
145 write_stream.flush();
146 write_stream.close();
154 FC_THROW(
"Caught an exception while sending data to GNTP service");
159 gntp_icon::gntp_icon(
const char* buffer,
size_t length) :
160 my(new
detail::gntp_icon_impl(buffer, length))
163 gntp_icon::~gntp_icon()
167 gntp_notifier::gntp_notifier(
const std::string& host_to_notify ,
uint16_t port ,
168 const std::optional<std::string>& password ) :
169 my(new
detail::gntp_notifier_impl(host_to_notify, port, password))
173 gntp_notifier::~gntp_notifier()
177 void gntp_notifier::set_application_name(std::string appName)
179 my->application_name = appName;
181 void gntp_notifier::set_application_icon(
const gntp_icon_ptr& icon)
183 my->application_icon = icon;
185 void gntp_notifier::add_notification_type(
const gntp_notification_type& notification_type)
187 my->notification_types.push_back(notification_type);
190 void gntp_notifier::register_notifications()
193 my->connection_failed =
false;
194 my->is_registered =
false;
196 std::ostringstream message;
197 std::set<gntp_icon_ptr> icons_used;
199 message <<
"GNTP/1.0 REGISTER NONE\r\n";
200 message <<
"Application-Name: " << my->application_name <<
"\r\n";
201 if (my->application_icon)
203 message <<
"Application-Icon: x-growl-resource://" << my->application_icon->my->_sha1_hash <<
"\r\n";
204 icons_used.insert(my->application_icon);
207 message <<
"Notifications-Count: " << my->notification_types.size() <<
"\r\n";
208 for (
const gntp_notification_type& notification_type : my->notification_types)
211 message <<
"Notification-Name: " << notification_type.name <<
"\r\n";
212 if (!notification_type.display_name.empty())
213 message <<
"Notification-Display-Name: " << notification_type.display_name <<
"\r\n";
214 if (notification_type.icon)
216 message <<
"Notification-Icon: x-growl-resource://" << notification_type.icon->my->_sha1_hash <<
"\r\n";
217 icons_used.insert(notification_type.icon);
219 message <<
"Notification-Enabled: " << (notification_type.enabled ?
"True" :
"False") <<
"\r\n";
221 if (!icons_used.empty())
224 for (
const gntp_icon_ptr& icon : icons_used)
226 message <<
"Identifier: " << icon->my->_sha1_hash <<
"\r\n";
227 message <<
"Length: " << icon->my->_icon_bytes.size() <<
"\r\n";
229 message << icon->my->_icon_bytes;
234 message <<
"\r\n\r\n";
237 my->send_gntp_message(message.str());
238 my->is_registered =
true;
240 catch (
const exception&)
242 my->connection_failed =
true;
245 gntp_guid gntp_notifier::send_notification(std::string
name, std::string title, std::string text,
246 const gntp_icon_ptr& icon, std::optional<gntp_guid> coalescingId )
248 if (my->connection_failed)
250 if (!my->is_registered)
253 gntp_guid notification_id;
256 std::ostringstream message;
257 message <<
"GNTP/1.0 NOTIFY NONE";
262 std::string salted_password = *my->password + std::string(salt, 16);
265 message <<
" SHA256:" << boost::to_upper_copy(
to_hex(keyhash.data(), 32)) <<
"." << boost::to_upper_copy(
to_hex(salt,
sizeof(salt)));
268 message <<
"Application-Name: " << my->application_name <<
"\r\n";
269 message <<
"Notification-Name: " <<
name <<
"\r\n";
270 message <<
"Notification-ID: " << notification_id.str() <<
"\r\n";
271 message <<
"Notification-Coalescing-ID: " << (coalescingId ? coalescingId->str() : notification_id.str()) <<
"\r\n";
272 message <<
"Notification-Title: " << title <<
"\r\n";
273 message <<
"Notification-Text: " <<
text <<
"\r\n";
275 message <<
"Notification-Icon: x-growl-resource://" << icon->my->_sha1_hash <<
"\r\n";
280 message <<
"Identifier: " << icon->my->_sha1_hash <<
"\r\n";
281 message <<
"Length: " << icon->my->_icon_bytes.size() <<
"\r\n";
283 message << icon->my->_icon_bytes;
286 message <<
"\r\n\r\n";
287 my->send_gntp_message(message.str());
288 return notification_id;
gntp_icon_impl(const char *buffer, size_t length)
std::optional< boost::asio::ip::tcp::endpoint > endpoint
gntp_notifier_impl(const std::string &host_to_notify="127.0.0.1", uint16_t port=23053, const std::optional< std::string > &password=std::optional< std::string >())
gntp_notification_type_list notification_types
void send_gntp_message(const std::string &message)
std::optional< std::string > password
std::string application_name
gntp_icon_ptr application_icon
Used to generate a useful error report when an exception is thrown.
std::string to_detail_string(log_level ll=log_level::all) const
static sha256 hash(const char *d, uint32_t dlen)
Defines exception's used by fc.
#define FC_RETHROW_EXCEPTION(ER, LOG_LEVEL, FORMAT,...)
Appends a log_message to the exception ER and rethrows it.
fc::string to_base32(const std::vector< char > &vec)
void rand_pseudo_bytes(char *buf, int count)
fc::string to_hex(const char *d, uint32_t s)
constexpr const char sha256[]