77#include < Poco/Net/Context.h>
88#include < Poco/Net/HTTPServerRequestImpl.h>
99#include < Poco/Net/HTTPServerResponseImpl.h>
10+ #include < Poco/JSON/JSONException.h>
1011#include < Poco/Net/NetException.h>
1112#include < Poco/Net/SSLException.h>
1213#include < Poco/Net/SecureStreamSocketImpl.h>
@@ -39,7 +40,7 @@ namespace OpenWifi {
3940 Poco::Net::HTTPServerResponse &response,
4041 uint64_t session_id, Poco::Logger &L,
4142 std::pair<std::shared_ptr<Poco::Net::SocketReactor>, std::shared_ptr<LockedDbSession>> R)
42- : Logger_(L) {
43+ : Logger_(L), IncomingFrame_( 0 ) {
4344
4445 Reactor_ = R.first ;
4546 DbSession_ = R.second ;
@@ -54,6 +55,7 @@ namespace OpenWifi {
5455 WS_->setNoDelay (false );
5556 WS_->setKeepAlive (true );
5657 WS_->setBlocking (false );
58+ IncomingFrame_.resize (0 );
5759 uuid_ = MicroServiceRandom (std::numeric_limits<std::uint64_t >::max ()-1 );
5860
5961 AP_WS_Server ()->IncrementConnectionCount ();
@@ -600,36 +602,95 @@ namespace OpenWifi {
600602 EndConnection ();
601603 }
602604
605+ void AP_WS_Connection::ProcessWSFinalPayload () {
606+ auto IncomingSize = IncomingFrame_.size ();
607+
608+ if (IncomingSize == 0 ) {
609+ poco_debug (Logger_,
610+ fmt::format (" ProcessWSFrame({}): Final Acc. Frame received but empty" ,
611+ CId_));
612+ return ;
613+ }
614+ IncomingFrame_.append (0 );
615+
616+ poco_trace (Logger_,
617+ fmt::format (" ProcessWSFrame({}): Final Acc. Frame received (len={}, Msg={}" ,
618+ CId_, IncomingSize, IncomingFrame_.begin ()));
619+
620+ Poco::JSON::Parser parser;
621+ auto ParsedMessage = parser.parse (IncomingFrame_.begin ());
622+ auto IncomingJSON = ParsedMessage.extract <Poco::JSON::Object::Ptr>();
623+
624+ if (IncomingJSON->has (uCentralProtocol::JSONRPC)) {
625+ if (IncomingJSON->has (uCentralProtocol::METHOD) &&
626+ IncomingJSON->has (uCentralProtocol::PARAMS)) {
627+ ProcessJSONRPCEvent (IncomingJSON);
628+ } else if (IncomingJSON->has (uCentralProtocol::RESULT) &&
629+ IncomingJSON->has (uCentralProtocol::ID)) {
630+ poco_trace (Logger_, fmt::format (" RPC-RESULT({}): payload: {}" , CId_,
631+ IncomingFrame_.begin ()));
632+ ProcessJSONRPCResult (IncomingJSON);
633+ } else {
634+ poco_warning (
635+ Logger_,
636+ fmt::format (" INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}" ,
637+ CId_, IncomingFrame_.begin ()));
638+ }
639+ } else if (IncomingJSON->has (uCentralProtocol::RADIUS)) {
640+ ProcessIncomingRadiusData (IncomingJSON);
641+ } else {
642+ std::ostringstream iS;
643+ IncomingJSON->stringify (iS);
644+ poco_warning (
645+ Logger_,
646+ fmt::format (" FRAME({}): illegal transaction header, missing 'jsonrpc': {}" ,
647+ CId_, iS.str ()));
648+ Errors_++;
649+ }
650+ IncomingFrame_.clear ();
651+ IncomingFrame_.resize (0 );
652+ }
653+
603654 void AP_WS_Connection::ProcessIncomingFrame () {
604- Poco::Buffer<char > IncomingFrame (0 );
655+ Poco::Buffer<char > CurrentFrame (0 );
656+ bool KillConnection = false ;
657+ int flags = 0 ;
658+ int IncomingSize = 0 ;
605659
606- bool KillConnection=false ;
607660 try {
608- int Op , flags;
609- auto IncomingSize = WS_-> receiveFrame (IncomingFrame, flags) ;
661+ IncomingSize = WS_-> receiveFrame (CurrentFrame , flags) ;
662+ int Op ;
610663
611664 Op = flags & Poco::Net::WebSocket::FRAME_OP_BITMASK;
612665
613- if (IncomingSize == 0 && flags == 0 && Op == 0 ) {
666+ if (IncomingSize < 0 && flags == 0 ) {
667+ poco_trace (Logger_,
668+ fmt::format (" EMPTY({}): Non-blocking try-again empty frame (len={}, flags={})" ,
669+ CId_, IncomingSize, flags));
670+ } else if (IncomingSize == 0 && flags == 0 ) {
614671 poco_information (Logger_,
615672 fmt::format (" DISCONNECT({}): device has disconnected. Session={}" ,
616673 CId_, State_.sessionId ));
617674 return EndConnection ();
618675 }
619676
620- IncomingFrame.append (0 );
621-
622- State_.RX += IncomingSize;
623- AP_WS_Server ()->AddRX (IncomingSize);
677+ if (IncomingSize > 0 ) {
678+ State_.RX += IncomingSize;
679+ AP_WS_Server ()->AddRX (IncomingSize);
680+ IncomingFrame_.append (CurrentFrame);
681+ }
624682 State_.MessageCount ++;
625683 State_.LastContact = Utils::Now ();
684+ poco_trace (Logger_,
685+ fmt::format (" FRAME({}): Frame rx (op={} len={}, flags={}, acc.len={})" ,
686+ CId_, Op, IncomingSize, flags, IncomingFrame_.size ()));
626687
627688 switch (Op) {
628689 case Poco::Net::WebSocket::FRAME_OP_PING: {
629- poco_trace (Logger_, fmt::format (" WS- PING({}): received. PONG sent back." , CId_));
690+ poco_trace (Logger_, fmt::format (" PING({}): received. PONG sent back." , CId_));
630691 WS_->sendFrame (" " , 0 ,
631692 (int )Poco::Net::WebSocket::FRAME_OP_PONG |
632- (int )Poco::Net::WebSocket::FRAME_FLAG_FIN);
693+ (int )Poco::Net::WebSocket::FRAME_FLAG_FIN);
633694
634695 if (KafkaManager ()->Enabled ()) {
635696 Poco::JSON::Object PingObject;
@@ -643,49 +704,32 @@ namespace OpenWifi {
643704 PingDetails.set (" locale" , State_.locale );
644705 PingObject.set (uCentralProtocol::PING, PingDetails);
645706 poco_trace (Logger_,fmt::format (" Sending PING for {}" , SerialNumber_));
646- KafkaManager ()->PostMessage (KafkaTopics::CONNECTION, SerialNumber_,PingObject);
707+ KafkaManager ()->PostMessage (KafkaTopics::CONNECTION, SerialNumber_,
708+ PingObject);
647709 }
710+ return ;
648711 } break ;
649712
650713 case Poco::Net::WebSocket::FRAME_OP_PONG: {
651714 poco_trace (Logger_, fmt::format (" PONG({}): received and ignored." , CId_));
715+ return ;
716+ } break ;
717+
718+ case Poco::Net::WebSocket::FRAME_OP_CONT: {
719+ poco_trace (Logger_, fmt::format (" CONTINUATION({}): registered." , CId_));
720+ } break ;
721+
722+ case Poco::Net::WebSocket::FRAME_OP_BINARY: {
723+ poco_trace (Logger_, fmt::format (" BINARY({}): Invalid frame type." , CId_));
724+ KillConnection=true ;
725+ return ;
652726 } break ;
653727
654728 case Poco::Net::WebSocket::FRAME_OP_TEXT: {
655729 poco_trace (Logger_,
656- fmt::format (" FRAME({}): Frame received (length={}, flags={}). Msg={}" ,
657- CId_, IncomingSize, flags, IncomingFrame.begin ()));
658-
659- Poco::JSON::Parser parser;
660- auto ParsedMessage = parser.parse (IncomingFrame.begin ());
661- auto IncomingJSON = ParsedMessage.extract <Poco::JSON::Object::Ptr>();
662-
663- if (IncomingJSON->has (uCentralProtocol::JSONRPC)) {
664- if (IncomingJSON->has (uCentralProtocol::METHOD) &&
665- IncomingJSON->has (uCentralProtocol::PARAMS)) {
666- ProcessJSONRPCEvent (IncomingJSON);
667- } else if (IncomingJSON->has (uCentralProtocol::RESULT) &&
668- IncomingJSON->has (uCentralProtocol::ID)) {
669- poco_trace (Logger_, fmt::format (" RPC-RESULT({}): payload: {}" , CId_,
670- IncomingFrame.begin ()));
671- ProcessJSONRPCResult (IncomingJSON);
672- } else {
673- poco_warning (
674- Logger_,
675- fmt::format (" INVALID-PAYLOAD({}): Payload is not JSON-RPC 2.0: {}" ,
676- CId_, IncomingFrame.begin ()));
677- }
678- } else if (IncomingJSON->has (uCentralProtocol::RADIUS)) {
679- ProcessIncomingRadiusData (IncomingJSON);
680- } else {
681- std::ostringstream iS;
682- IncomingJSON->stringify (iS);
683- poco_warning (
684- Logger_,
685- fmt::format (" FRAME({}): illegal transaction header, missing 'jsonrpc': {}" ,
686- CId_, iS.str ()));
687- Errors_++;
688- }
730+ fmt::format (" TEXT({}): Frame received (len={}, flags={}). Msg={}" ,
731+ CId_, IncomingSize, flags,
732+ CurrentFrame.begin () == nullptr ? " " : CurrentFrame.begin ()));
689733 } break ;
690734
691735 case Poco::Net::WebSocket::FRAME_OP_CLOSE: {
@@ -701,25 +745,31 @@ namespace OpenWifi {
701745 return ;
702746 }
703747 }
748+
749+ // Check for final frame and process accumulated payload
750+ if (!KillConnection && (flags & Poco::Net::WebSocket::FRAME_FLAG_FIN) != 0 ) {
751+ ProcessWSFinalPayload ();
752+ }
753+
704754 } catch (const Poco::Net::ConnectionResetException &E) {
705755 poco_warning (Logger_,
706756 fmt::format (" ConnectionResetException({}): Text:{} Payload:{} Session:{}" ,
707757 CId_, E.displayText (),
708- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
758+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
709759 State_.sessionId ));
710760 KillConnection=true ;
711761 } catch (const Poco::JSON::JSONException &E) {
712762 poco_warning (Logger_,
713763 fmt::format (" JSONException({}): Text:{} Payload:{} Session:{}" , CId_,
714764 E.displayText (),
715- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
765+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
716766 State_.sessionId ));
717767 KillConnection=true ;
718768 } catch (const Poco::Net::WebSocketException &E) {
719769 poco_warning (Logger_,
720770 fmt::format (" WebSocketException({}): Text:{} Payload:{} Session:{}" , CId_,
721771 E.displayText (),
722- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
772+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
723773 State_.sessionId ));
724774 KillConnection=true ;
725775 } catch (const Poco::Net::SSLConnectionUnexpectedlyClosedException &E) {
@@ -728,42 +778,42 @@ namespace OpenWifi {
728778 fmt::format (
729779 " SSLConnectionUnexpectedlyClosedException({}): Text:{} Payload:{} Session:{}" ,
730780 CId_, E.displayText (),
731- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
781+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
732782 State_.sessionId ));
733783 KillConnection=true ;
734784 } catch (const Poco::Net::SSLException &E) {
735785 poco_warning (Logger_,
736786 fmt::format (" SSLException({}): Text:{} Payload:{} Session:{}" , CId_,
737787 E.displayText (),
738- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
788+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
739789 State_.sessionId ));
740790 KillConnection=true ;
741791 } catch (const Poco::Net::NetException &E) {
742792 poco_warning (Logger_,
743793 fmt::format (" NetException({}): Text:{} Payload:{} Session:{}" , CId_,
744794 E.displayText (),
745- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
795+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
746796 State_.sessionId ));
747797 KillConnection=true ;
748798 } catch (const Poco::IOException &E) {
749799 poco_warning (Logger_,
750800 fmt::format (" IOException({}): Text:{} Payload:{} Session:{}" , CId_,
751801 E.displayText (),
752- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
802+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
753803 State_.sessionId ));
754804 KillConnection=true ;
755805 } catch (const Poco::Exception &E) {
756806 poco_warning (Logger_,
757807 fmt::format (" Exception({}): Text:{} Payload:{} Session:{}" , CId_,
758808 E.displayText (),
759- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
809+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
760810 State_.sessionId ));
761811 KillConnection=true ;
762812 } catch (const std::exception &E) {
763813 poco_warning (Logger_,
764814 fmt::format (" std::exception({}): Text:{} Payload:{} Session:{}" , CId_,
765815 E.what (),
766- IncomingFrame .begin () == nullptr ? " " : IncomingFrame .begin (),
816+ CurrentFrame .begin () == nullptr ? " " : CurrentFrame .begin (),
767817 State_.sessionId ));
768818 KillConnection=true ;
769819 } catch (...) {
@@ -776,7 +826,9 @@ namespace OpenWifi {
776826 if (!KillConnection && Errors_ < 10 )
777827 return ;
778828
779- poco_warning (Logger_, fmt::format (" DISCONNECTING({}): ConnectionException: {} Errors: {}" , CId_, KillConnection, Errors_ ));
829+ poco_warning (Logger_,
830+ fmt::format (" DISCONNECTING({}): ConnectionException: {} Errors: {}" ,
831+ CId_, KillConnection, Errors_ ));
780832 EndConnection ();
781833 }
782834
@@ -921,4 +973,4 @@ namespace OpenWifi {
921973 }
922974 }
923975
924- } // namespace OpenWifi
976+ } // namespace OpenWifi
0 commit comments