2018-02-11 20:36:55 +01:00
/*
* This file is part of aasdk library project .
* Copyright ( C ) 2018 f1x . studio ( Michal Szwaj )
*
* aasdk is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
* aasdk is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with aasdk . If not , see < http : //www.gnu.org/licenses/>.
*/
2020-05-13 04:55:03 +02:00
# include <aasdk/Messenger/MessageInStream.hpp>
# include <aasdk/Error/Error.hpp>
2022-02-11 13:35:07 +01:00
# include <aasdk/Common/Log.hpp>
# include <iostream>
2020-04-13 05:49:52 +02:00
2018-02-11 20:36:55 +01:00
namespace aasdk
{
namespace messenger
{
MessageInStream : : MessageInStream ( boost : : asio : : io_service & ioService , transport : : ITransport : : Pointer transport , ICryptor : : Pointer cryptor )
: strand_ ( ioService )
, transport_ ( std : : move ( transport ) )
, cryptor_ ( std : : move ( cryptor ) )
{
2022-02-11 13:35:07 +01:00
currentMessageIndex_ = 0 ;
2018-02-11 20:36:55 +01:00
}
2022-02-11 13:35:07 +01:00
void MessageInStream : : startReceive ( ReceivePromise : : Pointer promise , ChannelId channelId , int promiseIndex , int messageIndex )
2018-02-11 20:36:55 +01:00
{
2022-02-11 13:35:07 +01:00
AASDK_LOG ( debug ) < < " [MessageInStream] 1. Start Receive called with channel " < < channelIdToString ( channelId ) < < " PI " < < std : : to_string ( promiseIndex ) < < " MI " < < std : : to_string ( messageIndex ) ;
2018-02-11 20:36:55 +01:00
strand_ . dispatch ( [ this , self = this - > shared_from_this ( ) , promise = std : : move ( promise ) ] ( ) mutable {
2022-02-11 13:35:07 +01:00
if ( promise_ = = nullptr ) {
2018-02-11 20:36:55 +01:00
promise_ = std : : move ( promise ) ;
auto transportPromise = transport : : ITransport : : ReceivePromise : : defer ( strand_ ) ;
transportPromise - > then (
2022-02-11 13:35:07 +01:00
[ this , self = this - > shared_from_this ( ) ] ( common : : Data data ) mutable {
this - > receiveFrameHeaderHandler ( common : : DataConstBuffer ( data ) ) ;
} ,
[ this , self = this - > shared_from_this ( ) ] ( const error : : Error & e ) mutable {
AASDK_LOG ( debug ) < < " [MessageInStream] 2. Error Here? " ;
promise_ - > reject ( e ) ;
promise_ . reset ( ) ;
} ) ;
2018-02-11 20:36:55 +01:00
transport_ - > receive ( FrameHeader : : getSizeOf ( ) , std : : move ( transportPromise ) ) ;
2022-02-11 13:35:07 +01:00
} else {
AASDK_LOG ( debug ) < < " [MessageInStream] 3. Operation in Progress. " ;
2018-02-11 20:36:55 +01:00
promise - > reject ( error : : Error ( error : : ErrorCode : : OPERATION_IN_PROGRESS ) ) ;
}
} ) ;
}
2022-02-11 13:35:07 +01:00
void MessageInStream : : setInterleavedHandler ( ReceivePromise : : Pointer promise )
{
interleavedPromise_ = std : : move ( promise ) ;
}
2018-02-11 20:36:55 +01:00
void MessageInStream : : receiveFrameHeaderHandler ( const common : : DataConstBuffer & buffer )
{
FrameHeader frameHeader ( buffer ) ;
2020-04-13 05:49:52 +02:00
2022-02-11 13:35:07 +01:00
AASDK_LOG ( debug ) < < " [MessageInStream] 5. Processing Frame Header: Ch " < < channelIdToString ( frameHeader . getChannelId ( ) ) < < " Fr " < < frameTypeToString ( frameHeader . getType ( ) ) ;
isValidFrame_ = true ;
isInterleaved_ = false ;
// New Promise or Interleaved
if ( message_ ! = nullptr & & message_ - > getChannelId ( ) ! = frameHeader . getChannelId ( ) ) {
// We have an existing message but the channels don't match...
AASDK_LOG ( debug ) < < " [MessageInStream] 6. Interleaved ChannelId MisMatch - F: " < < channelIdToString ( frameHeader . getChannelId ( ) ) < < " M: " < < channelIdToString ( message_ - > getChannelId ( ) ) ;
isInterleaved_ = true ;
// Store message in buffer;
2020-04-13 05:49:52 +02:00
messageBuffer_ [ message_ - > getChannelId ( ) ] = message_ ;
2022-02-11 13:35:07 +01:00
message_ . reset ( ) ;
2018-02-11 20:36:55 +01:00
}
2020-04-13 05:49:52 +02:00
2022-02-11 13:35:07 +01:00
// Look for Buffered Message
if ( ( message_ = = nullptr ) & & ( frameHeader . getType ( ) = = FrameType : : MIDDLE | | frameHeader . getType ( ) = = FrameType : : LAST ) ) {
AASDK_LOG ( debug ) < < " [MessageInStream] 7. Null Message but Middle or Last Frame. " ;
auto bufferedMessage = messageBuffer_ . find ( frameHeader . getChannelId ( ) ) ;
if ( bufferedMessage ! = messageBuffer_ . end ( ) ) {
AASDK_LOG ( debug ) < < " [MessageInStream] 8. Found Existing Message on Channel. " ;
2020-04-13 05:49:52 +02:00
message_ = bufferedMessage - > second ;
2022-02-11 13:35:07 +01:00
messageBuffer_ . erase ( bufferedMessage ) ;
isInterleaved_ = false ;
2020-04-13 05:49:52 +02:00
}
2020-03-21 07:01:59 +01:00
}
2022-02-11 13:35:07 +01:00
if ( message_ = = nullptr ) {
if ( frameHeader . getType ( ) = = FrameType : : FIRST | | frameHeader . getType ( ) = = FrameType : : BULK ) {
AASDK_LOG ( debug ) < < " [MessageInStream] 11. New message created with Index " < < std : : to_string ( currentMessageIndex_ ) ;
currentMessageIndex_ + + ;
} else {
// This will be an invalid message, but we still need to read from the buffer.
isValidFrame_ = false ;
}
2020-03-21 07:01:59 +01:00
message_ = std : : make_shared < Message > ( frameHeader . getChannelId ( ) , frameHeader . getEncryptionType ( ) , frameHeader . getMessageType ( ) ) ;
2018-02-11 20:36:55 +01:00
}
2020-04-13 05:49:52 +02:00
2022-02-11 13:35:07 +01:00
thisFrameType_ = frameHeader . getType ( ) ;
2018-02-11 20:36:55 +01:00
const size_t frameSize = FrameSize : : getSizeOf ( frameHeader . getType ( ) = = FrameType : : FIRST ? FrameSizeType : : EXTENDED : FrameSizeType : : SHORT ) ;
auto transportPromise = transport : : ITransport : : ReceivePromise : : defer ( strand_ ) ;
transportPromise - > then (
[ this , self = this - > shared_from_this ( ) ] ( common : : Data data ) mutable {
this - > receiveFrameSizeHandler ( common : : DataConstBuffer ( data ) ) ;
} ,
[ this , self = this - > shared_from_this ( ) ] ( const error : : Error & e ) mutable {
message_ . reset ( ) ;
promise_ - > reject ( e ) ;
promise_ . reset ( ) ;
} ) ;
transport_ - > receive ( frameSize , std : : move ( transportPromise ) ) ;
}
void MessageInStream : : receiveFrameSizeHandler ( const common : : DataConstBuffer & buffer )
{
auto transportPromise = transport : : ITransport : : ReceivePromise : : defer ( strand_ ) ;
transportPromise - > then (
[ this , self = this - > shared_from_this ( ) ] ( common : : Data data ) mutable {
this - > receiveFramePayloadHandler ( common : : DataConstBuffer ( data ) ) ;
} ,
[ this , self = this - > shared_from_this ( ) ] ( const error : : Error & e ) mutable {
message_ . reset ( ) ;
promise_ - > reject ( e ) ;
promise_ . reset ( ) ;
} ) ;
FrameSize frameSize ( buffer ) ;
2022-02-11 11:19:12 +01:00
frameSize_ = ( int ) frameSize . getFrameSize ( ) ;
transport_ - > receive ( frameSize . getFrameSize ( ) , std : : move ( transportPromise ) ) ;
2018-02-11 20:36:55 +01:00
}
void MessageInStream : : receiveFramePayloadHandler ( const common : : DataConstBuffer & buffer )
{
if ( message_ - > getEncryptionType ( ) = = EncryptionType : : ENCRYPTED )
{
try
{
2022-02-11 11:29:02 +01:00
cryptor_ - > decrypt ( message_ - > getPayload ( ) , buffer , frameSize_ ) ;
2018-02-11 20:36:55 +01:00
}
catch ( const error : : Error & e )
{
message_ . reset ( ) ;
promise_ - > reject ( e ) ;
promise_ . reset ( ) ;
return ;
}
}
else
{
message_ - > insertPayload ( buffer ) ;
}
2022-02-11 13:35:07 +01:00
bool isResolved = false ;
// If this is the LAST frame or a BULK frame...
if ( ( thisFrameType_ = = FrameType : : BULK | | thisFrameType_ = = FrameType : : LAST ) & & isValidFrame_ )
2018-02-11 20:36:55 +01:00
{
2022-02-11 13:35:07 +01:00
if ( ! isInterleaved_ ) {
AASDK_LOG ( debug ) < < " [MessageInStream] 12. Resolving Normal message. " < < std : : to_string ( currentMessageIndex_ ) ;
promise_ - > resolve ( std : : move ( message_ ) ) ;
promise_ . reset ( ) ;
isResolved = true ;
} else {
AASDK_LOG ( debug ) < < " [MessageInStream] 13. Resolving Interleaved Message. " < < std : : to_string ( currentMessageIndex_ ) ;
interleavedPromise_ - > resolve ( std : : move ( message_ ) ) ;
}
currentMessageIndex_ - - ;
message_ . reset ( ) ;
2018-02-11 20:36:55 +01:00
}
2022-02-11 13:35:07 +01:00
// If the main promise isn't resolved, then carry on retrieving frame headers.
if ( ! isResolved ) {
2018-02-11 20:36:55 +01:00
auto transportPromise = transport : : ITransport : : ReceivePromise : : defer ( strand_ ) ;
transportPromise - > then (
2022-02-11 13:35:07 +01:00
[ this , self = this - > shared_from_this ( ) ] ( common : : Data data ) mutable {
this - > receiveFrameHeaderHandler ( common : : DataConstBuffer ( data ) ) ;
} ,
[ this , self = this - > shared_from_this ( ) ] ( const error : : Error & e ) mutable {
message_ . reset ( ) ;
promise_ - > reject ( e ) ;
promise_ . reset ( ) ;
} ) ;
2018-02-11 20:36:55 +01:00
transport_ - > receive ( FrameHeader : : getSizeOf ( ) , std : : move ( transportPromise ) ) ;
}
}
}
}