cwUi.cpp : Improve websocket msg buffering.

This commit is contained in:
kevin 2022-09-10 10:18:52 -04:00
parent 984cb3a11a
commit 841aa8f744

189
cwUi.cpp
View File

@ -89,6 +89,7 @@ namespace cw
char* recvBuf; char* recvBuf;
unsigned recvBufN; unsigned recvBufN;
unsigned recvBufIdx; unsigned recvBufIdx;
unsigned recvShiftN;
unsigned* sessA; // sessA[ sessN ] array of wsSessId's unsigned* sessA; // sessA[ sessN ] array of wsSessId's
unsigned sessN; unsigned sessN;
@ -1048,6 +1049,49 @@ namespace cw
return _setPropertyValue( h, propertyStr,uuId,enableFl ? 1 : 0 ); return _setPropertyValue( h, propertyStr,uuId,enableFl ? 1 : 0 );
} }
rc_t _copy_msg_to_recv_buffer( ui_t* p, const void* msg, unsigned msgByteN )
{
rc_t rc;
if( p->recvBufIdx + msgByteN > p->recvBufN )
rc = cwLogError(kBufTooSmallRC,"The UI input buffer (%i) is too small.", p->recvBufN);
else
{
memcpy(p->recvBuf + p->recvBufIdx, msg, msgByteN );
p->recvBufIdx += msgByteN;
}
return rc;
}
const char* _get_msg_from_recv_buffer( ui_t* p )
{
const char* msg = nullptr;
unsigned i;
// shift off the previous msg
if( p->recvShiftN > 0 )
{
memmove(p->recvBuf, p->recvBuf+p->recvShiftN, p->recvBufIdx - p->recvShiftN );
p->recvShiftN = 0;
}
// locate the end of the next msg.
for(i=0; p->recvBuf[i]!=0 and i<p->recvBufIdx; ++i)
{}
// if the end of the next msg was found
if( p->recvBuf[i] == 0 )
{
p->recvShiftN = i+1;
msg = p->recvBuf;
}
return msg;
}
} }
} }
@ -1089,6 +1133,7 @@ cw::rc_t cw::ui::create(
p->recvBuf = mem::allocZ<char>(fmtBufByteN); p->recvBuf = mem::allocZ<char>(fmtBufByteN);
p->recvBufN = fmtBufByteN; p->recvBufN = fmtBufByteN;
p->recvBufIdx = 0; p->recvBufIdx = 0;
p->recvShiftN = 0;
// create the root element // create the root element
if((ele = _createBaseEle(p, nullptr, kRootAppId, kInvalidId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId ) if((ele = _createBaseEle(p, nullptr, kRootAppId, kInvalidId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId )
@ -1191,12 +1236,14 @@ cw::rc_t cw::ui::onDisconnect( handle_t h, unsigned wsSessId )
cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* void_msg, unsigned msgByteN ) cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* void_msg, unsigned msgByteN )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
opId_t opId = kInvalidOpId; opId_t opId = kInvalidOpId;
value_t value; ele_t* ele = nullptr;
ele_t* ele; const char* msg = nullptr;
value_t value;
/*
const char* src_msg = (const char*)void_msg; const char* src_msg = (const char*)void_msg;
const char* msg = src_msg; const char* msg = src_msg;
@ -1233,80 +1280,90 @@ cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const void* void_msg,
// the message is being processed so the buffer will end up empty // the message is being processed so the buffer will end up empty
// (if it was being used) // (if it was being used)
p->recvBufIdx = 0; p->recvBufIdx = 0;
*/
// parse the 'opId' from the message // buffer the incoming msg
opId = _labelToOpId(msg); if((rc = _copy_msg_to_recv_buffer( p, void_msg, msgByteN )) != kOkRC )
goto errLabel;
// remove and and act on each buffered msg
switch( opId ) while( (msg = _get_msg_from_recv_buffer(p)) != NULL )
{ {
case kInitOpId:
// if the app cfg included a reference to a UI resource file then instantiate it here
_onNewRemoteUi( p, wsSessId );
// Pass on the 'init' msg to the app. // parse the 'opId' from the message
p->uiCbFunc( p->uiCbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr ); opId = _labelToOpId(msg);
break;
case kValueOpId:
if((ele = _parse_value_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI 'value' message parse failed.");
else
{
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kCorruptOpId:
if((ele = _parse_corrupt_msg(p, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI 'corrupt' message parse failed.");
else
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
break;
case kClickOpId: switch( opId )
if((ele = _parse_click_msg(p, (const char*)msg )) == nullptr ) {
cwLogError(kOpFailRC,"UI 'click' message parse failed."); case kInitOpId:
else // if the app cfg included a reference to a UI resource file then instantiate it here
{ _onNewRemoteUi( p, wsSessId );
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kSelectOpId: // Pass on the 'init' msg to the app.
if((ele = _parse_select_msg(p, value, (const char*)msg )) == nullptr ) p->uiCbFunc( p->uiCbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr );
cwLogError(kOpFailRC,"UI 'select' message parse failed."); break;
else
{
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kEchoOpId: case kValueOpId:
if((ele = _parse_echo_msg(p,(const char*)msg)) == nullptr ) if((ele = _parse_value_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI Echo message parse failed."); cwLogError(kOpFailRC,"UI 'value' message parse failed.");
else else
{ {
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId,nullptr ); p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kIdleOpId: }
p->uiCbFunc( p->uiCbArg, kInvalidId, opId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr ); break;
break;
case kInvalidOpId: case kCorruptOpId:
cwLogError(kInvalidIdRC,"The UI received a NULL op. id."); if((ele = _parse_corrupt_msg(p, (const char*)msg )) == nullptr )
break; cwLogError(kOpFailRC,"UI 'corrupt' message parse failed.");
else
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
break;
default:
cwLogError(kInvalidIdRC,"The UI received an unknown op. id.");
break;
} // switch opId case kClickOpId:
if((ele = _parse_click_msg(p, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI 'click' message parse failed.");
else
{
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kSelectOpId:
if((ele = _parse_select_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI 'select' message parse failed.");
else
{
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId, &value );
}
break;
case kEchoOpId:
if((ele = _parse_echo_msg(p,(const char*)msg)) == nullptr )
cwLogError(kOpFailRC,"UI Echo message parse failed.");
else
{
p->uiCbFunc( p->uiCbArg, wsSessId, opId, ele->logical_parent->appId, ele->uuId, ele->appId, ele->chanId,nullptr );
}
break;
case kIdleOpId:
p->uiCbFunc( p->uiCbArg, kInvalidId, opId, kInvalidId, kInvalidId, kInvalidId, kInvalidId, nullptr );
break;
case kInvalidOpId:
cwLogError(kInvalidIdRC,"The UI received a NULL op. id.");
break;
default:
cwLogError(kInvalidIdRC,"The UI received an unknown op. id.");
break;
} // switch opId
}
errLabel:
return rc; return rc;
} }