diff --git a/include/matrix/client.hpp b/include/matrix/client.hpp index 6cae8a3..6566741 100644 --- a/include/matrix/client.hpp +++ b/include/matrix/client.hpp @@ -26,6 +26,7 @@ #include "matrix/upload_info.hpp" #include "matrix/connection.hpp" #include "matrix/roomcxn.hpp" +#include "matrix/netreturn.hpp" #include //vector #include //shared_ptr #include //size_t @@ -53,43 +54,43 @@ namespace matrix{ * Note name must be safe to be placed in a json string. * Returns: true if the operation was successful. */ - bool set_display_name(const raii::string_base&); + netreturn set_display_name(const raii::string_base&); /* * Sets the url of the user's profile picture on the homeserver. * Note url must be safe to be placed in a json string. * Returns: true if the operation was successful. */ - bool set_profile_picture(const raii::string_base&); + netreturn set_profile_picture(const raii::string_base&); - bool set_presence(const raii::string_base& status); - raii::rjp_string get_presence(const raii::string_base& userid); + netreturn set_presence(const raii::string_base& status); + netreturn get_presence(const raii::string_base& userid); /* * Gets the display name of the logged in user from the homeserver. * Returns: the display name on success, an empty string on failure. */ - raii::rjp_string get_display_name(void)const; + netreturn get_display_name(void)const; /* * Gets the profile picture url of the logged in user from the homeserver. * Returns: the profile picture url on success, an empty string on failure. */ - raii::rjp_string get_profile_picture(void)const; + netreturn get_profile_picture(void)const; /* * Lookup a room id given a room alias. * Returns: the room id of the associated room on success, empty string on failure. */ - raii::rjp_string room_alias_to_id(const raii::string_base& alias)const; + netreturn room_alias_to_id(const raii::string_base& alias)const; /* * Get a list of rooms the logged in user is a member of. * Returns: a vector of room id strings. */ - std::vector list_rooms(void)const; + netreturn> list_rooms(void)const; /* * Create a new room on the logged in user's homeserver. Assign an alias to the room. * Returns: the room id of the newly created room on success, an empty string on failure. */ - raii::rjp_string create_room(const raii::string_base& name, const raii::string_base& alias)const; + netreturn create_room(const raii::string_base& name, const raii::string_base& alias)const; /* * Create a new matrix::roomcxn object for the given roomid. @@ -108,30 +109,30 @@ namespace matrix{ * Returns: file_info struct containing the url of the file on the homeserver. * Note check the file_info::fileurl field to check if the upload succeeded. */ - uploaded_file upload_file(const file_details& file)const; + netreturn upload_file(const file_details& file)const; /* * Upload a file as an image. * Returns: image_info struct containing the url of the image on the homeserver. * Note check the image_info::fileurl field to check if the upload succeeded. */ - uploaded_image upload_image(const image_details& file)const; + netreturn upload_image(const image_details& file)const; /* * Upload data as a video. * Returns: video_info struct containing the url of the image on the homeserver. * Note check the video_info::fileurl field to check if the upload succeeded. */ - uploaded_video upload_video(const video_details& file)const; + netreturn upload_video(const video_details& file)const; /* * Upload a file as an audio file. * Returns: audio_info struct containing the url of the image on the homeserver. * Note check the audio_info::fileurl field to check if the upload succeeded. */ - uploaded_audio upload_audio(const audio_details& file)const; + netreturn upload_audio(const audio_details& file)const; - bool create_thumbnail(uploaded_image& info)const; - bool create_thumbnail(uploaded_video& video)const; + netreturn create_thumbnail(uploaded_image& info)const; + netreturn create_thumbnail(uploaded_video& video)const; raii::binary download_file(const raii::string_base& url); template @@ -153,7 +154,7 @@ namespace matrix{ static size_t _download_dispatch(char* ptr, size_t size, size_t nmemb, void* userdata){ return reinterpret_cast(userdata)(ptr, size, nmemb, nullptr); } - uploaded_file _upload_file(const file_details& file, const raii::curl_llist& header)const; + netreturn _upload_file(const file_details& file, const raii::curl_llist& header)const; }; } diff --git a/include/matrix/connection.hpp b/include/matrix/connection.hpp index 7c8bca8..2de8765 100644 --- a/include/matrix/connection.hpp +++ b/include/matrix/connection.hpp @@ -91,8 +91,9 @@ namespace matrix{ raii::binary _post_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, binary_callback_fun = _binary_reply_curl_callback)const; raii::string _put_curl(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, reply_callback_fun = _reply_curl_callback)const; raii::binary _put_curl_binary(const raii::string_base& postdata, const raii::string_base& url, const raii::curl_llist& header, binary_callback_fun = _binary_reply_curl_callback)const; - raii::rjp_string _post_and_find(const raii::string_base& data, const raii::string_base& url, const raii::curl_llist& header, const raii::string_base& target)const; - raii::rjp_string _get_and_find(const raii::string_base& url, const raii::string_base& search)const; + netreturn _post_and_find(const raii::string_base& data, const raii::string_base& url, const raii::curl_llist& header, const raii::string_base& target)const; + netreturn _put_and_find(const raii::string_base& data, const raii::string_base& url, const raii::curl_llist& header, const raii::string_base& target)const; + netreturn _get_and_find(const raii::string_base& url, const raii::string_base& search)const; raii::rjp_string _curl_reply_search(const raii::string_base& reply, const raii::string_base& search)const; raii::rjp_string _curl_reply_search(const raii::rjp_ptr& root, const raii::string_base& search)const; void _set_curl_defaults(const raii::string_base& useragent)const; diff --git a/include/matrix/netreturn.hpp b/include/matrix/netreturn.hpp index 451798b..4f4bc72 100644 --- a/include/matrix/netreturn.hpp +++ b/include/matrix/netreturn.hpp @@ -37,10 +37,13 @@ namespace matrix{ netreturn_base(const raii::rjp_string& error, raii::rjp_string&& errorcode, int httpstatus); netreturn_base(raii::rjp_string&& error, const raii::rjp_string& errorcode, int httpstatus); netreturn_base(raii::rjp_string&& error, raii::rjp_string&& errorcode, int httpstatus); - operator bool(void)const; - const raii::rjp_string mxerror(void)const; - const raii::rjp_string mxerrorcode(void)const; + bool ok(void)const; + const raii::rjp_string& mxerror(void)const; + const raii::rjp_string& mxerrorcode(void)const; + raii::rjp_string& mxerror(void); + raii::rjp_string& mxerrorcode(void); int httpstatus(void)const; + bool has_httperror(void)const; }; template class netreturn : public netreturn_base @@ -51,7 +54,7 @@ namespace matrix{ Retval m_ret = {}; public: constexpr netreturn(void) = default; - template + template netreturn(Str1&& error, Str2&& errorcode, int httpcode, Val&& val = Val()): netreturn_base(std::forward(error), std::forward(errorcode), httpcode), m_ret(std::forward(val)){} diff --git a/include/matrix/session.hpp b/include/matrix/session.hpp index 39d39bd..a58dc46 100644 --- a/include/matrix/session.hpp +++ b/include/matrix/session.hpp @@ -89,7 +89,7 @@ namespace matrix{ * This will regenerate the urls and ensure access token and homeserver are valid. * Returns: true if success, false otherwise. */ - bool login(void); + netreturn login(void); /* * NOT thread safe. * Manually log in to a homeserver first using the current access token, then trying the @@ -97,13 +97,13 @@ namespace matrix{ * homeserver are valid. * Returns: true if success, false otherwise. */ - bool login(const raii::string_base& username, const raii::string_base& pass); + netreturn login(const raii::string_base& username, const raii::string_base& pass); /* * Logout of the current connection to the homeserver. Will invalidate the access token on the server side. * Returns: true if the logout was successful, false otherwise. */ - bool logout(void); + netreturn logout(void); /* * Returns: true if the session is successfully connected to the homeserver. */ @@ -132,11 +132,11 @@ namespace matrix{ */ void invalidate(void); private: - bool _do_login(const raii::string_base& username, const raii::string_base& pass); + netreturn _do_login(const raii::string_base& username, const raii::string_base& pass); void _populate_session_info(const auth_data& a); - raii::rjp_string _get_userid(void); + netreturn _get_userid(void); raii::string _request_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl)const; - std::pair _get_new_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl); + netreturn> _get_new_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl); }; } diff --git a/include/matrix/sync_response.hpp b/include/matrix/sync_response.hpp index 4e6613f..ec5ca70 100644 --- a/include/matrix/sync_response.hpp +++ b/include/matrix/sync_response.hpp @@ -120,8 +120,9 @@ namespace matrix::sync{ class response { private: - raii::rjp_ptr m_root; + raii::rjp_ptr m_root = nullptr; public: + constexpr response(void) = default; response(const raii::string_base& src); response(RJP_value* root); diff --git a/include/matrix/syncer.hpp b/include/matrix/syncer.hpp index 75bcab2..48a5c80 100644 --- a/include/matrix/syncer.hpp +++ b/include/matrix/syncer.hpp @@ -25,6 +25,7 @@ #include "matrix/session_info.hpp" #include "matrix/connection.hpp" #include "matrix/sync_response.hpp" +#include "matrix/netreturn.hpp" #include //size_t #include //shared_ptr @@ -55,7 +56,7 @@ namespace matrix{ * Sync state with the homeserver. Will wait for up to timeout ms. * Returns: the raw json response from the homeserver. */ - sync::response sync(size_t timeout); + netreturn sync(size_t timeout); }; } diff --git a/include/raii/string_base.hpp b/include/raii/string_base.hpp index 671696c..ea3d922 100644 --- a/include/raii/string_base.hpp +++ b/include/raii/string_base.hpp @@ -105,29 +105,32 @@ namespace raii{ string_intermediary(char* data, size_t len): string_base(data, len){} string_intermediary(const char* data, size_t len): - string_base(reinterpret_cast(Allocator::copy(data, len+1)), len){} + string_base(reinterpret_cast(len ? Allocator::copy(data, len+1) : nullptr), len){} string_intermediary(const char* data): - string_base(strlen(data)) + string_base(data ? strlen(data) : 0) { - m_data = reinterpret_cast(Allocator::copy(data, m_length+1)); + if(m_length) + m_data = reinterpret_cast(Allocator::copy(data, m_length+1)); } string_intermediary(size_t len): - string_base(reinterpret_cast(Allocator::allocate(len+1)), len){} + string_base(reinterpret_cast(len ? Allocator::allocate(len+1) : nullptr), len){} //normal copy and move ctors string_intermediary(const string_intermediary& b): - string_base(reinterpret_cast(Allocator::copy(b.m_data, b.m_length+1)), b.m_length){} + string_base(reinterpret_cast(b.m_length ? Allocator::copy(b.m_data, b.m_length+1) : nullptr), b.m_length){} string_intermediary(string_intermediary&& s): string_base(std::exchange(s.m_data, nullptr), s.m_length){} string_intermediary(const string_base& b): - string_base(reinterpret_cast(Allocator::copy(b.get(), b.length()+1)), b.length()){} + string_base(reinterpret_cast(b.length() ? Allocator::copy(b.get(), b.length()+1) : nullptr), b.length()){} //copy from string expression template::value && !detail::is_concrete_string::value,void>::type* = nullptr> string_intermediary(T&& t){ size_t len = t.length(); - + if(!len){ + return; + } char* tmp = reinterpret_cast(Allocator::allocate(len+1)); _assign(tmp, t.get(), 0); m_data = tmp; diff --git a/src/matrix/client.cpp b/src/matrix/client.cpp index 84677ac..5ccb00c 100644 --- a/src/matrix/client.cpp +++ b/src/matrix/client.cpp @@ -30,55 +30,55 @@ namespace matrix{ connection(ses){} //networked setter - bool client::set_display_name(const raii::string_base& newname){ + netreturn client::set_display_name(const raii::string_base& newname){ _put_curl(raii::string("{\"displayname\":\"" + newname + "\"}"), m_ses->urls.displayname(), raii::curl_llist()); - return http_status() == 200; + return netreturn(raii::string(), raii::string(), http_status()); } - bool client::set_profile_picture(const raii::string_base& media_url){ + netreturn client::set_profile_picture(const raii::string_base& media_url){ _put_curl(raii::string("{\"avatar_url\":\"" + media_url + "\"}"), m_ses->urls.profile_picture(), raii::curl_llist()); - return http_status() == 200; + return netreturn(raii::string(), raii::string(), http_status()); } - bool client::set_presence(const raii::string_base& status){ + netreturn client::set_presence(const raii::string_base& status){ _put_curl(raii::string("{\"presence\":\""_ss + status + "\"}"), m_ses->urls.presence(m_ses->homeserver, m_ses->access_token, m_ses->userid), raii::curl_llist()); - return http_status() == 200; + return netreturn(raii::string(), raii::string(), http_status()); } - raii::rjp_string client::get_presence(const raii::string_base& userid){ + netreturn client::get_presence(const raii::string_base& userid){ return _get_and_find(m_ses->urls.presence(m_ses->homeserver, m_ses->access_token, userid), "presence"_ss); } //networked getter - raii::rjp_string client::get_display_name(void)const{ + netreturn client::get_display_name(void)const{ return _get_and_find(m_ses->urls.displayname(), "displayname"_ss); } - raii::rjp_string client::get_profile_picture(void)const{ + netreturn client::get_profile_picture(void)const{ return _get_and_find(m_ses->urls.profile_picture(), "avatar_url"_ss); } - raii::rjp_string client::room_alias_to_id(const raii::string_base& alias)const{ + netreturn client::room_alias_to_id(const raii::string_base& alias)const{ auto tmp = m_curl.encode(alias, alias.length()); return _get_and_find(raii::string(m_ses->urls.alias_lookup() + tmp), "room_id"_ss); } - std::vector client::list_rooms(void)const{ - std::vector ret; + netreturn> client::list_rooms(void)const{ raii::string reply = _get_curl(m_ses->urls.room_list()); if(!reply) - return ret; + return _create_netreturn(reply, http_status()); raii::rjp_ptr root(rjp_parse(reply)); + netreturn> retval = _create_netreturn(root, http_status()); if(!root) - return ret; + return retval; RJP_search_res res = rjp_search_member(root.get(), "joined_rooms", 0); if(!res.value) - return ret; + return retval; for(RJP_value* v = rjp_get_element(res.value);v;v = rjp_next_element(v)){ - ret.emplace_back(v); + retval.value().emplace_back(v); } - return ret; + return retval; } //room membership - raii::rjp_string client::create_room(const raii::string_base& name, const raii::string_base& alias)const{ + netreturn client::create_room(const raii::string_base& name, const raii::string_base& alias)const{ raii::string postdata; if(alias) postdata = "{\"name\": \"" + raii::json_escape(name) + "\",\"room_alias_name\": \"" + raii::json_escape(alias) + "\"}"; @@ -95,33 +95,33 @@ namespace matrix{ } //upload media - uploaded_file client::upload_file(const file_details& file)const{ + netreturn client::upload_file(const file_details& file)const{ return _upload_file(file, raii::curl_llist{}); } - uploaded_image client::upload_image(const image_details& file)const{ - uploaded_image ret = {}; + netreturn client::upload_image(const image_details& file)const{ raii::curl_llist headers(raii::string("Content-Type: "_ss + file.mimetype)); - ret = _upload_file(file, headers); - ret.m_width = file.width; - ret.m_height = file.height; - ret.m_mimetype = file.mimetype; - return ret; + netreturn upfile = _upload_file(file, headers); + netreturn retval(std::move(upfile.mxerror()), std::move(upfile.mxerrorcode()), upfile.httpstatus()); + retval.value().m_width = file.width; + retval.value().m_height = file.height; + retval.value().m_mimetype = file.mimetype; + return retval; } - uploaded_audio client::upload_audio(const audio_details& file)const{ - uploaded_audio ret = {}; + netreturn client::upload_audio(const audio_details& file)const{ raii::curl_llist headers(raii::string("Content-Type: "_ss + file.mimetype)); - ret = _upload_file(file, headers); - ret.m_mimetype = file.mimetype; - return ret; + netreturn upfile = _upload_file(file, headers); + netreturn retval(std::move(upfile.mxerror()), std::move(upfile.mxerrorcode()), upfile.httpstatus()); + retval.value().m_mimetype = file.mimetype; + return retval; } - uploaded_video client::upload_video(const video_details& file)const{ - uploaded_video ret = {}; + netreturn client::upload_video(const video_details& file)const{ raii::curl_llist headers(raii::string("Content-Type: "_ss + file.mimetype)); - ret = _upload_file(file, headers); - ret.m_width = file.width; - ret.m_height = file.height; - ret.m_mimetype = file.mimetype; - return ret; + netreturn upfile = _upload_file(file, headers); + netreturn retval(std::move(upfile.mxerror()), std::move(upfile.mxerrorcode()), upfile.httpstatus()); + retval.value().m_width = file.width; + retval.value().m_height = file.height; + retval.value().m_mimetype = file.mimetype; + return retval; } static size_t _thumbnail_header_callback(char* ptr, size_t size, size_t nmemb, void* userdata){ @@ -133,7 +133,7 @@ namespace matrix{ return size*nmemb; } - bool client::create_thumbnail(uploaded_image& info)const{ + netreturn client::create_thumbnail(uploaded_image& info)const{ image_details i; raii::string reply_header; if(info.thumb_width() > info.width() || info.thumb_height() > info.height()){ @@ -146,21 +146,21 @@ namespace matrix{ i.data = _get_curl_binary(m_ses->urls.file_thumbnail(m_ses->homeserver, info.m_fileurl, info.m_thumb.m_width, info.m_thumb.m_height, "crop"_ss)); m_curl.setopt(CURLOPT_HEADERFUNCTION, NULL); m_curl.setopt(CURLOPT_HEADERDATA, NULL); - if(!i.data){ - return false; - } + if(!i.data) + return netreturn(raii::string(), raii::string(), http_status()); i.width = info.thumb_width(); i.height = info.thumb_height(); i.mimetype = std::move(reply_header); - uploaded_image thumb_data = upload_image(i); - if(!thumb_data.m_fileurl) - return false; - info.m_thumb.m_url = std::move(thumb_data.m_fileurl); - info.m_thumb.m_size = thumb_data.m_filesize; - info.m_thumb.m_mimetype = std::move(thumb_data.m_mimetype); - return true; + netreturn thumb_data = upload_image(i); + netreturn retval(std::move(thumb_data.mxerror()), std::move(thumb_data.mxerrorcode()), thumb_data.httpstatus()); + if(!thumb_data.ok() || !thumb_data.value().m_fileurl) + return retval; + info.m_thumb.m_url = std::move(thumb_data.value().m_fileurl); + info.m_thumb.m_size = thumb_data.value().m_filesize; + info.m_thumb.m_mimetype = std::move(thumb_data.value().m_mimetype); + return retval; } - bool client::create_thumbnail(uploaded_video& info)const{ + netreturn client::create_thumbnail(uploaded_video& info)const{ return create_thumbnail(static_cast(info)); } raii::binary client::download_file(const raii::string_base& url){ @@ -185,9 +185,8 @@ namespace matrix{ return to_copy; } - uploaded_file client::_upload_file(const file_details& file, const raii::curl_llist& header)const{ + netreturn client::_upload_file(const file_details& file, const raii::curl_llist& header)const{ raii::string fileurl; - uploaded_file retval = {}; internal_upload_data upload_data = {file.data.get(), file.data.size()}; m_curl.postreq(); m_curl.setopt(CURLOPT_POSTFIELDS, NULL); @@ -201,21 +200,19 @@ namespace matrix{ m_curl.setwritedata(&fileurl); bool succ = _perform_curl(); m_curl.setreaddata(NULL); - if(!succ) - return {}; - - if(!fileurl) - return {}; + if(!succ || !fileurl) + return _create_netreturn(fileurl, http_status()); raii::rjp_ptr root(rjp_parse(fileurl)); + netreturn retval = _create_netreturn(root, http_status()); if(!root) - return {}; + return retval; RJP_search_res res = rjp_search_member(root.get(), "content_uri", 0); if(!res.value) - return {}; - retval.m_fileurl = res.value; - retval.m_filename = file.name; - retval.m_filesize = file.data.size(); + return retval; + retval.value().m_fileurl = res.value; + retval.value().m_filename = file.name; + retval.value().m_filesize = file.data.size(); return retval; } } diff --git a/src/matrix/connection.cpp b/src/matrix/connection.cpp index b7e82ae..043b899 100644 --- a/src/matrix/connection.cpp +++ b/src/matrix/connection.cpp @@ -155,19 +155,36 @@ namespace matrix{ return {}; return reply; } - raii::rjp_string connection::_post_and_find(const raii::string_base& data, const raii::string_base& url, + netreturn connection::_post_and_find(const raii::string_base& data, const raii::string_base& url, const raii::curl_llist& header, const raii::string_base& target)const { raii::string reply = _post_curl(data, url, header); if(!reply) - return {}; - return _curl_reply_search(reply, target); + return _create_netreturn(reply, http_status()); + raii::rjp_ptr root(rjp_parse(reply)); + netreturn retval = _create_netreturn(root, http_status()); + retval.value() = _curl_reply_search(reply, target); + return retval; } - raii::rjp_string connection::_get_and_find(const raii::string_base& url, const raii::string_base& target)const{ + netreturn connection::_put_and_find(const raii::string_base& data, const raii::string_base& url, + const raii::curl_llist& header, const raii::string_base& target)const + { + raii::string reply = _put_curl(data, url, header); + if(!reply) + return _create_netreturn(reply, http_status()); + raii::rjp_ptr root(rjp_parse(reply)); + netreturn retval = _create_netreturn(root, http_status()); + retval.value() = _curl_reply_search(reply, target); + return retval; + } + netreturn connection::_get_and_find(const raii::string_base& url, const raii::string_base& target)const{ raii::string reply = _get_curl(url); if(!reply) - return {}; - return _curl_reply_search(reply, target); + return _create_netreturn(reply, http_status()); + raii::rjp_ptr root(rjp_parse(reply)); + netreturn retval = _create_netreturn(root, http_status()); + retval.value() = _curl_reply_search(reply, target); + return retval; } raii::rjp_string connection::_curl_reply_search(const raii::string_base& reply, const raii::string_base& target)const{ raii::rjp_ptr root(rjp_parse(reply)); @@ -194,7 +211,7 @@ namespace matrix{ m_curl.setopt(CURLOPT_FOLLOWLOCATION, 1L); m_curl.forcessl(CURL_SSLVERSION_TLSv1_2); m_curl.setopt(CURLOPT_TCP_KEEPALIVE, 1L); - m_curl.setopt(CURLOPT_FAILONERROR, 1L); + //m_curl.setopt(CURLOPT_FAILONERROR, 0L); } netreturn_base connection::_create_netreturn(const raii::string_base& mxjson, int httpstatus){ if(!mxjson) @@ -205,9 +222,7 @@ namespace matrix{ netreturn_base connection::_create_netreturn(const raii::rjp_ptr& root, int httpstatus){ if(!root) return netreturn_base("Invalid JSON"_ss, "Invalid JSON"_ss, -1); - raii::rjp_string error = rjp_search_member(root.get(), "error", 0).value; - raii::rjp_string errorcode = rjp_search_member(root.get(), "errorcode", 0).value; - return netreturn_base(std::move(error), std::move(errorcode), httpstatus); + return netreturn_base(rjp_search_member(root.get(), "error", 0).value, rjp_search_member(root.get(), "errorcode", 0).value, httpstatus); } } diff --git a/src/matrix/netreturn.cpp b/src/matrix/netreturn.cpp index 01bbdb8..7636df7 100644 --- a/src/matrix/netreturn.cpp +++ b/src/matrix/netreturn.cpp @@ -27,16 +27,25 @@ namespace matrix{ m_error(std::move(error)), m_errorcode(errorcode), m_http_error(httpstatus){} netreturn_base::netreturn_base(raii::rjp_string&& error, raii::rjp_string&& errorcode, int httpstatus): m_error(std::move(error)), m_errorcode(std::move(errorcode)), m_http_error(httpstatus){} - netreturn_base::operator bool(void)const{ - return m_http_error > 299; + bool netreturn_base::ok(void)const{ + return (!has_httperror() && !m_error); } - const raii::rjp_string netreturn_base::mxerror(void)const{ + const raii::rjp_string& netreturn_base::mxerror(void)const{ return m_error; } - const raii::rjp_string netreturn_base::mxerrorcode(void)const{ + const raii::rjp_string& netreturn_base::mxerrorcode(void)const{ + return m_errorcode; + } + raii::rjp_string& netreturn_base::mxerror(void){ + return m_error; + } + raii::rjp_string& netreturn_base::mxerrorcode(void){ return m_errorcode; } int netreturn_base::httpstatus(void)const{ return m_http_error; } + bool netreturn_base::has_httperror(void)const{ + return (m_http_error > 299 || m_http_error < 200); + } } diff --git a/src/matrix/roomcxn.cpp b/src/matrix/roomcxn.cpp index a7a3c0d..346c0dc 100644 --- a/src/matrix/roomcxn.cpp +++ b/src/matrix/roomcxn.cpp @@ -134,12 +134,7 @@ namespace matrix{ } netreturn roomcxn::redact_event(const raii::string_base& eventid, const raii::string_base& reason)const{ - raii::string ret = _put_curl(raii::string("{\"reason\":\"" + reason + "\"}"), m_urls.redact(m_ses->homeserver, m_ses->access_token, m_curl.encode(m_roomid), m_curl.encode(eventid)), raii::curl_llist()); - if(!ret) return _create_netreturn(ret, http_status()); - raii::rjp_ptr root(rjp_parse(ret.get())); - netreturn retval = _create_netreturn(root, http_status()); - retval.value() = _curl_reply_search(root, "event_id"_ss); - return retval; + return _put_and_find(raii::string("{\"reason\":\"" + reason + "\"}"), m_urls.redact(m_ses->homeserver, m_ses->access_token, m_curl.encode(m_roomid), m_curl.encode(eventid)), raii::curl_llist(), "event_id"_ss); } netreturn roomcxn::redact_event(const raii::string_base& eventid)const{ return redact_event(eventid, "No reason given"_ss); @@ -173,13 +168,7 @@ namespace matrix{ m_urls.repopulate(m_ses->homeserver, m_ses->access_token, m_ses->userid, m_roomid); } netreturn roomcxn::upgrade(int version)const{ - raii::string reply = _post_curl(raii::string("{\"new_version\":\""_ss + raii::itostr(version) + "\"}"_ss), m_urls.upgrade(), raii::curl_llist()); - if(!reply) return _create_netreturn(reply, http_status()); - raii::rjp_ptr root(rjp_parse(reply)); - netreturn retval = _create_netreturn(root, http_status()); - if(!root) return retval; - retval.value() = _curl_reply_search(root, "event_id"_ss); - return retval; + return _post_and_find(raii::string("{\"new_version\":\""_ss + raii::itostr(version) + "\"}"_ss), m_urls.upgrade(), raii::curl_llist(), "event_id"_ss); } netreturn roomcxn::_send_message(const raii::string_base& msg)const{ diff --git a/src/matrix/session.cpp b/src/matrix/session.cpp index 91fe97e..e5352a0 100644 --- a/src/matrix/session.cpp +++ b/src/matrix/session.cpp @@ -55,15 +55,15 @@ namespace matrix{ m_ses->access_token = std::move(tok); } - bool session::login(void){ + netreturn session::login(void){ return _do_login(raii::string(), raii::string()); } - bool session::login(const raii::string_base& username, const raii::string_base& pass){ + netreturn session::login(const raii::string_base& username, const raii::string_base& pass){ return _do_login(username, pass); } - bool session::logout(void){ - _post_curl(""_ss, m_ses->urls.logout(m_ses->homeserver, m_ses->access_token), raii::curl_llist()); - return http_status() == 200; + netreturn session::logout(void){ + raii::string reply = _post_curl(""_ss, m_ses->urls.logout(m_ses->homeserver, m_ses->access_token), raii::curl_llist()); + return _create_netreturn(reply, http_status()); } bool session::valid(void)const{ @@ -84,26 +84,37 @@ namespace matrix{ m_ses->urls.invalidate_accesstoken(); } - bool session::_do_login(const raii::string_base& username, const raii::string_base& pass){ + netreturn session::_do_login(const raii::string_base& username, const raii::string_base& pass){ auto reply = _get_curl(client_url_list::stat_whoami(m_ses->homeserver, m_ses->access_token)); - if(!reply){ + netreturn retval = _create_netreturn(reply, http_status()); + if(!retval.ok()){ if(!username || !pass){ - return (m_valid = false); + m_valid = false; + return retval; } - auto [token, id] = _get_new_access_token(username, pass, client_url_list::login(m_ses->homeserver)); + auto newtoken = _get_new_access_token(username, pass, client_url_list::login(m_ses->homeserver)); + auto& token = newtoken.value().first; + auto& id = newtoken.value().second; if(token && id){ m_ses->access_token = std::move(token); m_ses->userid = std::move(id); m_ses->urls.repopulate(m_ses->homeserver, m_ses->access_token, m_ses->userid); - return (m_valid = true); + m_valid = true; }else{ - return (m_valid = false); + m_valid = false; } + return netreturn(std::move(newtoken.mxerror()), std::move(newtoken.mxerrorcode()), newtoken.httpstatus()); }else{ m_ses->urls.repopulate_accesstoken(m_ses->homeserver, m_ses->access_token); - m_ses->userid = _get_userid(); + netreturn uid = _get_userid(); + if(!uid.ok()){ + invalidate(); + return netreturn(std::move(uid.mxerror()), std::move(uid.mxerrorcode()), uid.httpstatus()); + } + m_ses->userid = std::move(uid.value()); m_ses->urls.repopulate_userid(m_ses->homeserver, m_ses->access_token, m_ses->userid); - return (m_valid = true); + m_valid = true; + return retval; } } void session::_populate_session_info(const auth_data& a){ @@ -117,28 +128,21 @@ namespace matrix{ raii::string reply = _post_curl(postdata, loginurl, raii::curl_llist{}); return reply; } - raii::rjp_string session::_get_userid(void){ - auto reply = _get_curl(client_url_list::stat_whoami(m_ses->homeserver, m_ses->access_token)); - if(!reply) - return {}; - raii::rjp_ptr root(rjp_parse(reply)); - if(!root) - return {}; - RJP_search_res id = rjp_search_member(root.get(), "user_id", 0); - return raii::rjp_string{id.value}; + netreturn session::_get_userid(void){ + return _get_and_find(client_url_list::stat_whoami(m_ses->homeserver, m_ses->access_token), "user_id"_ss); } - std::pair session::_get_new_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl){ + netreturn> session::_get_new_access_token(const raii::string_base& name, const raii::string_base& pass, const raii::string_base& loginurl){ raii::string reply = _request_access_token(name, pass, loginurl); if(!reply) - return {}; + return _create_netreturn(reply, http_status()); raii::rjp_ptr root(rjp_parse(reply)); + netreturn> retval = _create_netreturn(root, http_status()); if(!root) - return {}; - std::pair retval; + return retval; RJP_search_res token = rjp_search_member(root.get(), "access_token", 0); - retval.first = raii::rjp_string{token.value}; + retval.value().first = raii::rjp_string{token.value}; token = rjp_search_member(root.get(), "user_id", 0); - retval.second = raii::rjp_string{token.value}; + retval.value().second = raii::rjp_string{token.value}; return retval; } } diff --git a/src/matrix/syncer.cpp b/src/matrix/syncer.cpp index 75d29cd..e2f645b 100644 --- a/src/matrix/syncer.cpp +++ b/src/matrix/syncer.cpp @@ -25,19 +25,21 @@ namespace matrix{ syncer::syncer(const std::shared_ptr& ses): connection(ses){} - sync::response syncer::sync(size_t timeout){ + netreturn syncer::sync(size_t timeout){ raii::string reply = _get_curl(m_ses->urls.sync(m_ses->homeserver, m_ses->access_token, m_next_batch, raii::itostr(timeout))); if(!reply) - return {nullptr}; + return netreturn(raii::string(), raii::string(), http_status(), {nullptr}); raii::rjp_ptr root(rjp_parse(reply)); + netreturn retval = _create_netreturn(root, http_status()); if(!root) - return reply; + return retval; RJP_search_res res = rjp_search_member(root.get(), "next_batch", 0); if(!res.value) - return reply; + return retval; m_next_batch = res.value; - return sync::response(root.release()); + retval.value() = sync::response(root.release()); + return retval; } } diff --git a/src/test.cpp b/src/test.cpp index b8b8e45..ae6f233 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -35,7 +35,7 @@ void sync_fn(matrix::syncer syn, std::atomic_bool& should_quit){ printf("continuing\n"); while(!should_quit){ auto sync_reply = syn.sync(30000); - for(auto room : sync_reply.room_join_events()){ + for(auto room : sync_reply.value().room_join_events()){ for(auto event : room.timeline_events()){ printf("%s\n", event.sender().get()); } @@ -74,21 +74,18 @@ int main(){ auto syn = ses.spawn_syncer(); auto client = ses.spawn_client(); auto room = client.spawn_room("!IaZlRZWhZiNMMsiZRl:rexy712.chickenkiller.com"_ss); - auto reply = std::move(room.get_events_backward(5).value()); - printf("%s\n", reply.start_token().get()); - printf("%s\n", reply.end_token().get()); - for(auto event : reply){ - printf("%s\n", event.eventid().get()); - } syn.sync(0); + auto status = room.send_message("gay"_ss); + if(!status.ok()) + fprintf(stderr, "http error: %d\n", status.httpstatus()); + if(status.mxerror()) + fprintf(stderr, "matrix error: %s\n", status.mxerror().get()); - //auto room = ses.spawn_client().spawn_room("!OwuhlJnHlsmyPwiLIH:rexy712.chickenkiller.com"_ss); - //printf("%s\n", room.get_events_backward(1).get()); - std::thread sync_thread(sync_fn, ses.spawn_syncer(), std::ref(should_quit)); + + //std::thread sync_thread(sync_fn, ses.spawn_syncer(), std::ref(should_quit)); //std::thread key_thread(keyboard_fn, ses.spawn_client().spawn_room("!cEIFONpAlHTbGBUFAE:rexy712.chickenkiller.com"_ss), std::ref(should_quit)); - //one of these threads will always hang until another input is recieved - sync_thread.join(); + //sync_thread.join(); //key_thread.join(); }