cwUi.h/cpp : Handle partial messages arriving from the websocket by buffering and reconstructing the message.

This commit is contained in:
kevin 2022-05-14 10:16:09 -04:00
parent f4852f7b90
commit 95b0d4f213
2 changed files with 73 additions and 9 deletions

View File

@ -86,6 +86,9 @@ namespace cw
appIdMapRecd_t* appIdMap; // map of application parent/child/js id's
char* buf; // buf[bufN] output message formatting buffer
unsigned bufN; //
char* recvBuf;
unsigned recvBufN;
unsigned recvBufIdx;
unsigned* sessA; // sessA[ sessN ] array of wsSessId's
unsigned sessN;
@ -153,6 +156,7 @@ namespace cw
mem::release(p->sessA);
mem::release(p->eleA);
mem::release(p->buf);
mem::release(p->recvBuf);
mem::release(p);
@ -1082,6 +1086,9 @@ cw::rc_t cw::ui::create(
p->sendCbArg = sendCbArg;
p->buf = mem::allocZ<char>(fmtBufByteN);
p->bufN = fmtBufByteN;
p->recvBuf = mem::allocZ<char>(fmtBufByteN);
p->recvBufN = fmtBufByteN;
p->recvBufIdx = 0;
// create the root element
if((ele = _createBaseEle(p, nullptr, kRootAppId, kInvalidId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId )
@ -1182,14 +1189,55 @@ cw::rc_t cw::ui::onDisconnect( handle_t h, unsigned wsSessId )
return kOkRC;
}
cw::rc_t cw::ui::onReceive( handle_t h, unsigned wsSessId, const 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;
ui_t* p = _handleToPtr(h);
opId_t opId = _labelToOpId((const char*)msg);
opId_t opId = kInvalidOpId;
value_t value;
ele_t* ele;
const char* src_msg = (const char*)void_msg;
const char* msg = src_msg;
// if the incoming message is valid
if( msgByteN > 0 and src_msg != nullptr )
{
// if there is a partial msg in the recv buffer (recvBufIdx!=0)
// or the incoming message is a partial mesg - then buffer the message
// (Note: incoming messages that are not zero terminated are partial.")
if( p->recvBufIdx != 0 || src_msg[msgByteN-1] != 0 )
{
// verify the buffer is large enough to hold the msg
if(p->recvBufIdx + msgByteN > p->recvBufN )
{
rc = cwLogError(kOpFailRC,"The UI input buffer (%i) is too small.", p->recvBufN);
p->recvBufIdx = 0;
}
else
{
// update it with the incoming text
strncpy( p->recvBuf + p->recvBufIdx, src_msg, msgByteN );
p->recvBufIdx += msgByteN;
msg = p->recvBuf;
}
}
// if the incoming message is not zero terminated then it was a partial
// message it was buffered and there is nothing else to do.
if( src_msg[msgByteN-1] != 0)
return rc;
}
// the message is being processed so the buffer will end up empty
// (if it was being used)
p->recvBufIdx = 0;
// parse the 'opId' from the message
opId = _labelToOpId(msg);
switch( opId )
{
case kInitOpId:
@ -1877,6 +1925,7 @@ cw::rc_t cw::ui::ws::parseArgs( const object_t& o, args_t& args, const char* ob
rc_t rc = kOkRC;
const object_t* op = &o;
char* uiCfgFn = nullptr;
char* physRootDir = nullptr;
memset(&args,0,sizeof(args));
@ -1894,10 +1943,17 @@ cw::rc_t cw::ui::ws::parseArgs( const object_t& o, args_t& args, const char* ob
rc = cwLogError(rc,"'ui' cfg. parse failed.");
}
// expand the physical root directory
if((physRootDir = filesys::expandPath( args.physRootDir)) == nullptr )
{
rc = cwLogError(kInvalidArgRC,"The physical root directory of the UI cfg. is invalid.");
goto errLabel;
}
// if a default UI resource script was given then convert it into an object
if( uiCfgFn != nullptr )
{
char* fn = filesys::makeFn( args.physRootDir, uiCfgFn, nullptr, nullptr );
char* fn = filesys::makeFn( physRootDir, uiCfgFn, nullptr, nullptr );
if((rc = objectFromFile(fn,args.uiRsrc)) != kOkRC )
rc = cwLogError(rc,"An error occurred while parsing the UI resource script in '%s'.", cwStringNullGuard(uiCfgFn));
@ -1905,6 +1961,9 @@ cw::rc_t cw::ui::ws::parseArgs( const object_t& o, args_t& args, const char* ob
mem::release(fn);
}
errLabel:
mem::release(physRootDir);
return rc;
}
@ -2029,7 +2088,7 @@ cw::rc_t cw::ui::ws::exec( handle_t h )
cwLogError(rc,"The UI websock execution failed.");
// make the idle callback
ui::onReceive( p->uiH, kInvalidId, "idle", strlen("idle") );
ui::onReceive( p->uiH, kInvalidId, "idle", strlen("idle")+1 );
return rc;
}

7
cwUi.h
View File

@ -41,7 +41,12 @@ namespace cw
// A UI was disconnected
rc_t onDisconnect( handle_t h, unsigned wsSessId );
// Receive a msg from a remote UI
// Receive a msg from a remote UI.
//
// Note that individual messages are delinated with zero termination.
// Therefore a message which is not zero terminated is considered
// a partial message and will be buffered until the suffix of the message
// arrives.
rc_t onReceive( handle_t h, unsigned wsSessId, const void* msg, unsigned byteN );
// Locate an element whose parent uuid is 'parentUuId' with a child named 'eleName'.