diff --git a/libretroshare/src/services/p3gxsmails.cpp b/libretroshare/src/services/p3gxsmails.cpp index 6083fbc9b..0a8c8c457 100644 --- a/libretroshare/src/services/p3gxsmails.cpp +++ b/libretroshare/src/services/p3gxsmails.cpp @@ -149,6 +149,13 @@ bool p3GxsMails::sendMail( GxsMailsClient::GxsMailSubServices service, return true; } +void p3GxsMails::registerGxsMailsClient( + GxsMailsClient::GxsMailSubServices serviceType, GxsMailsClient* service) +{ + RS_STACK_MUTEX(servClientsMutex); + servClients[serviceType] = service; +} + void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type) { @@ -239,81 +246,7 @@ void p3GxsMails::handleResponse(uint32_t token, uint32_t req_type) break; } - - std::cout << "p3GxsMails::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL got from: " - << msg->meta.mAuthorId - << " recipientsHint: " - << msg->recipientsHint << " cryptoType: " - << (uint32_t)msg->cryptoType - << " payload size: " << msg->payload.size() - << std::endl; - - std::set decryptIds; - std::list ownIds; - idService.getOwnIds(ownIds); - for(auto it = ownIds.begin(); it != ownIds.end(); ++it) - if(msg->maybeRecipient(*it)) decryptIds.insert(*it); - - if(decryptIds.empty()) - { - std::cout << "p3GxsMails::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL hint match none" - << " of our own ids" << msg->recipientsHint - << std::endl; - - break; - } - - std::cout << "p3GxsMails::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL hint: " - << msg->recipientsHint - << " match with own ids: "; - for(auto it=decryptIds.begin(); it != decryptIds.end(); ++it) - std::cout << *it; - std::cout << std::endl; - - switch (msg->cryptoType) - { - case RsGxsMailBaseItem::CLEAR_TEXT: - { - uint16_t csri = 0; - uint32_t off; - getRawUInt16(&msg->payload[0], 2, &off, &csri); - std::string str(reinterpret_cast(&msg->payload[2]), msg->payload.size()-2); - std::cout << "service: " << csri - << " got CLEAR_TEXT message: " - << str << std::endl; - break; - } - case RsGxsMailBaseItem::RSA: - { - uint8_t* decrypted_data = NULL; - uint32_t decrypted_data_size = 0; - uint32_t decryption_error; - if( idService.decryptData( - &msg->payload[0], - msg->payload.size(), decrypted_data, - decrypted_data_size, decryptIds, - decryption_error ) ) - { - uint16_t csri = *reinterpret_cast(decrypted_data); - std::string str(reinterpret_cast(decrypted_data+2), decrypted_data_size-2); - std::cout << "service: " << csri - << " got RSA message: " - << str << std::endl; - } - else std::cout << "p3GxsMails::handleResponse(...) " - << "GXS_MAIL_SUBTYPE_MAIL RSA decryption" - << " failed" << std::endl; - free(decrypted_data); - break; - } - default: - std::cout << "Unknown encryption type:" - << msg->cryptoType << std::endl; - break; - } + handleEcryptedMail(msg); break; } default: @@ -421,3 +354,93 @@ bool p3GxsMails::requestGroupsData(const std::list* groupIds) return true; } +bool p3GxsMails::handleEcryptedMail(RsGxsMailItem* mail) +{ + std::set decryptIds; + std::list ownIds; + idService.getOwnIds(ownIds); + for(auto it = ownIds.begin(); it != ownIds.end(); ++it) + if(mail->maybeRecipient(*it)) decryptIds.insert(*it); + + // Hint match none of our own ids + if(decryptIds.empty()) goto hFail; + + for(auto it=decryptIds.begin(); it != decryptIds.end(); ++it) + std::cout << *it; + std::cout << std::endl; + + switch (mail->cryptoType) + { + case RsGxsMailBaseItem::CLEAR_TEXT: + { + uint16_t csri; + uint32_t off = 0; + getRawUInt16(&mail->payload[0], 2, &off, &csri); + std::cerr << "service: " << csri << " got CLEAR_TEXT mail!" + << std::endl; + if( !dispatchDecryptedMail( mail, &mail->payload[2], + mail->payload.size()-2 ) ) + goto hFail; + break; + } + case RsGxsMailBaseItem::RSA: + { + uint8_t* decrypted_data = NULL; + uint32_t decrypted_data_size = 0; + uint32_t decryption_error; + bool ok = idService.decryptData( &mail->payload[0], + mail->payload.size(), decrypted_data, + decrypted_data_size, decryptIds, + decryption_error ); + ok = ok && dispatchDecryptedMail( mail, decrypted_data, + decrypted_data_size ); + if(!ok) + { + std::cout << "p3GxsMails::handleEcryptedMail(...) " + << "RSA decryption failed" << std::endl; + free(decrypted_data); + goto hFail; + } + break; + } + default: + std::cout << "Unknown encryption type:" + << mail->cryptoType << std::endl; + goto hFail; + } + + return true; + +hFail: + delete mail; + return false; +} + +bool p3GxsMails::dispatchDecryptedMail( RsGxsMailItem* received_msg, + uint8_t* decrypted_data, + uint32_t decrypted_data_size ) +{ + uint16_t csri; + uint32_t off; + getRawUInt16(decrypted_data, decrypted_data_size, &off, &csri); + GxsMailsClient::GxsMailSubServices rsrvc; + rsrvc = static_cast(csri); + + GxsMailsClient* reecipientService = NULL; + { + RS_STACK_MUTEX(servClientsMutex); + reecipientService = servClients[rsrvc]; + } + if(reecipientService) + return reecipientService->receiveGxsMail( received_msg, + &decrypted_data[2], + decrypted_data_size-2 ); + else + { + std::cerr << "p3GxsMails::dispatchReceivedMail(...) " + << "got message for unknown service: " + << csri << std::endl; + return false; + } +} + diff --git a/libretroshare/src/services/p3gxsmails.h b/libretroshare/src/services/p3gxsmails.h index cf05f7aae..9d6f2e1d7 100644 --- a/libretroshare/src/services/p3gxsmails.h +++ b/libretroshare/src/services/p3gxsmails.h @@ -41,14 +41,16 @@ struct GxsMailsClient /** * This will be called by p3GxsMails to dispatch mails to the subservice - * @param destinationId - * @param signingKey - * @param data - * @param dataSize + * @param originalMessage message as received from GXS backend (encrypted) + * GxsMailsClient take ownership of it ( aka should take free/delete it + * when not needed anymore ) + * @param data buffer containing the decrypted data + * GxsMailsClient take ownership of it ( aka should take free/delete it + * when not needed anymore ) + * @param dataSize size of the buffer * @return true if dispatching goes fine, false otherwise */ - virtual bool receiveGxsMail( const RsGxsId& destinationId, - const RsGxsId& signingKey, + virtual bool receiveGxsMail( RsGxsMailItem* originalMessage, uint8_t* data, uint32_t dataSize ) = 0; }; @@ -60,7 +62,8 @@ struct p3GxsMails : RsGenExchange, GxsTokenQueue RS_SERVICE_TYPE_GXS_MAIL, &identities, AuthenPolicy(), RS_GXS_DEFAULT_MSG_STORE_PERIOD ), // TODO: Discuss with Cyril about this - GxsTokenQueue(this), idService(identities) {} + GxsTokenQueue(this), idService(identities), + servClientsMutex("p3GxsMails client services map mutex") {} /** * Send an email to recipient, in the process author of the email is @@ -94,11 +97,9 @@ struct p3GxsMails : RsGenExchange, GxsTokenQueue /** * Register a client service to p3GxsMails to receive mails via * GxsMailsClient::receiveGxsMail(...) callback - * This is NOT thread safe! */ void registerGxsMailsClient( GxsMailsClient::GxsMailSubServices serviceType, - GxsMailsClient* service ) - { servClients[serviceType] = service; } + GxsMailsClient* service ); /** * @see GxsTokenQueue::handleResponse(uint32_t token, uint32_t req_type) @@ -141,6 +142,8 @@ private: /// Stores pointers to client services to notify them about new mails std::map servClients; + RsMutex servClientsMutex; + /// Request groups list to GXS backend. Async method. bool requestGroupsData(const std::list* groupIds = NULL); @@ -169,5 +172,14 @@ private: /// @return true if has passed more then interval seconds time since timeStamp bool static inline olderThen(time_t timeStamp, int32_t interval) { return (timeStamp + interval) < time(NULL); } + + + /// Decrypt email content and pass it to dispatchDecryptedMail(...) + bool handleEcryptedMail(RsGxsMailItem* mail); + + /// Dispatch the message to the recipient service + bool dispatchDecryptedMail( RsGxsMailItem* received_msg, + uint8_t* decrypted_data, + uint32_t decrypted_data_size ); };