cwUI.h/cpp, cwUiTest.cpp : Separated the UI component into three parts ui, ws, srv.

This commit is contained in:
kevin.larke 2020-04-07 16:24:34 -04:00
parent 38aab880a0
commit c6ccaefcdb
3 changed files with 527 additions and 283 deletions

648
cwUi.cpp
View File

@ -33,12 +33,13 @@ namespace cw
typedef struct ui_str typedef struct ui_str
{ {
websockSrv::handle_t wssH; // websock server handle
unsigned eleAllocN; // size of eleA[] unsigned eleAllocN; // size of eleA[]
unsigned eleN; // count of ele's in use unsigned eleN; // count of ele's in use
ele_t** eleA; // eleA[ eleAllocN ] ele_t** eleA; // eleA[ eleAllocN ]
uiCallback_t cbFunc; // app. cb func uiCallback_t uiCbFunc; // app. cb func
void* cbArg; // app. cb func arg. void* uiCbArg; // app. cb func arg.
sendCallback_t sendCbFunc;
void* sendCbArg;
appIdMapRecd_t* appIdMap; // map of application parent/child/js id's appIdMapRecd_t* appIdMap; // map of application parent/child/js id's
char* buf; // buf[bufN] output message formatting buffer char* buf; // buf[bufN] output message formatting buffer
unsigned bufN; // unsigned bufN; //
@ -60,10 +61,6 @@ namespace cw
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
if( p->wssH.isValid() )
if((rc = websockSrv::destroy(p->wssH)) != kOkRC )
return rc;
for(unsigned i=0; i<p->eleN; ++i) for(unsigned i=0; i<p->eleN; ++i)
{ {
mem::release(p->eleA[i]->eleName); mem::release(p->eleA[i]->eleName);
@ -230,7 +227,16 @@ namespace cw
rc_t _websockSend( ui_t* p, unsigned wsSessId, const char* msg ) rc_t _websockSend( ui_t* p, unsigned wsSessId, const char* msg )
{ {
return websock::send( websockSrv::websockHandle( p->wssH ), kUiProtocolId, wsSessId, msg, strlen(msg) ); rc_t rc = kOkRC;
//return websock::send( websockSrv::websockHandle( p->wssH ), kUiProtocolId, wsSessId, msg, strlen(msg) );
if( p->sendCbFunc != nullptr )
{
unsigned msgByteN = msg==nullptr ? 0 : strlen(msg);
return p->sendCbFunc( p->sendCbArg, wsSessId, msg, msgByteN );
}
return rc;
} }
@ -243,7 +249,7 @@ namespace cw
// Override format_attribute_data() for char. string data so that strings are wrapped in quotes. // Override format_attribute_data() for char. string data so that strings are wrapped in quotes.
template<> template<>
unsigned format_attribute_data( char* buf, unsigned n, const char* t ) unsigned format_attribute_data( char* buf, unsigned n, const char* t )
{ {
unsigned i = 0; unsigned i = 0;
i += toText(buf+i, n-i, "\"" ); i += toText(buf+i, n-i, "\"" );
@ -475,7 +481,7 @@ namespace cw
} }
// value message format: 'value' <uuid> <value_data_type> ':' <value>
ele_t* _parse_value_msg( ui_t* p, value_t& valueRef, const char* msg ) ele_t* _parse_value_msg( ui_t* p, value_t& valueRef, const char* msg )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
@ -553,90 +559,6 @@ namespace cw
return ele; return ele;
} }
rc_t _send_app_id_msg( ui_t* p, unsigned wsSessId, ele_t* ele )
{
rc_t rc = kOkRC;
unsigned i = snprintf(p->buf,p->bufN,"{ \"op\":\"set_app_id\", \"parentUuId\":%i, \"eleName\":\"%s\", \"appId\":%i, \"uuId\":%i }", ele->parent->uuId, ele->eleName, ele->parent->appId, ele->appId );
if( i >= p->bufN )
return cwLogError(kBufTooSmallRC,"The 'app_id' msg formatting buffer is too small (%i bytes).", p->bufN);
if((rc = _websockSend( p, wsSessId, p->buf )) != kOkRC )
return cwLogError(rc,"'app_id' msg transmission failed.");
return rc;
}
ele_t* _handle_register_msg( ui_t* p, unsigned wsSessId, const char* msg )
{
printf("%s\n",msg);
return nullptr;
}
ele_t* _handle_register_msg0( ui_t* p, unsigned wsSessId, const char* msg )
{
rc_t rc = kOkRC;
unsigned parentUuId = kInvalidId;
ele_t* parentEle = nullptr;
ele_t* ele = nullptr;
const char* s0 = nextNonWhiteChar(msg + strlen("register"));
const char* eleName = nextNonWhiteChar(nextWhiteChar(s0));
// verifity the message tokens
if( s0 == nullptr || eleName == nullptr )
{
cwLogError(kSyntaxErrorRC, "'register' msg format error: '%s' is not a valid message.", cwStringNullGuard(msg) );
goto errLabel;
}
// verify the parentUuId parsing
if((rc = string_to_number<unsigned>(s0,parentUuId)) != kOkRC )
{
cwLogError(kSyntaxErrorRC, "'register' msg parentUuId format error: '%s' does not contain a valid parentUuId.", cwStringNullGuard(msg) );
goto errLabel;
}
// get the parent ele
if((parentEle = _uuIdToEle( p, parentUuId)) == nullptr )
{
cwLogError(kInvalidIdRC,"UI register msg parent element not found.");
goto errLabel;
}
// if the child element does not already exist
if(( ele = _parentUuId_EleName_ToEle( p, parentUuId, eleName, false )) == nullptr )
{
// look up the parent/eleName pair map
appIdMapRecd_t* m = _findAppIdMap( p, parentEle->appId, eleName );
// create the ele
ele = _createEle( p, parentEle, m==nullptr ? kInvalidId : m->appId, eleName );
printf("creating: parent uuid:%i js:%s \n", parentUuId,eleName);
// notify the app of the new ele's uuid and appId
if( m != nullptr )
_send_app_id_msg( p, wsSessId, ele );
}
else
{
printf("parent uuid:%i js:%s already exists.\n", parentUuId,eleName);
}
if( ele != nullptr )
_send_app_id_msg( p, wsSessId, ele );
return ele;
errLabel:
return nullptr;
}
opId_t _labelToOpId( const char* label ) opId_t _labelToOpId( const char* label )
{ {
typedef struct typedef struct
@ -646,146 +568,55 @@ namespace cw
} map_t; } map_t;
map_t mapA[] = map_t mapA[] =
{ {
{ kConnectOpId, "connect" }, { kConnectOpId, "connect" },
{ kInitOpId, "init" }, { kInitOpId, "init" },
{ kValueOpId, "value" }, { kValueOpId, "value" },
{ kRegisterOpId, "register" }, { kDisconnectOpId, "disconnect" },
{ kDisconnectOpId, "disconnect" }, { kInvalidOpId, "<invalid>" },
{ kEndAppIdUpdateOpId, "end_app_id_update" }, };
{ kInvalidOpId, "<invalid>" },
};
for(unsigned i=0; mapA[i].id != kInvalidOpId; ++i) for(unsigned i=0; mapA[i].id != kInvalidOpId; ++i)
if( textCompare(label,mapA[i].label,strlen(mapA[i].label)) == 0 ) if( textCompare(label,mapA[i].label,strlen(mapA[i].label)) == 0 )
return mapA[i].id; return mapA[i].id;
return kInvalidOpId; return kInvalidOpId;
}
void _websockCb( void* cbArg, unsigned protocolId, unsigned wsSessId, websock::msgTypeId_t msg_type, const void* msg, unsigned byteN )
{
ui_t* p = (ui_t*)cbArg;
opId_t opId = kInvalidOpId;
value_t value;
switch( msg_type )
{
case websock::kConnectTId:
opId = kConnectOpId;
break;
case websock::kDisconnectTId:
opId = kDisconnectOpId;
break;
case websock::kMessageTId:
{
ele_t* ele;
opId = _labelToOpId((const char*)msg);
switch( opId )
{
case kInitOpId:
// Pass on the 'init' msg to the app.
p->cbFunc( p->cbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, nullptr );
break;
case kValueOpId:
if((ele = _parse_value_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI Value message parse failed.");
else
{
unsigned parentEleAppId = ele->parent == nullptr ? kInvalidId : ele->parent->appId;
p->cbFunc( p->cbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, &value );
}
break;
case kRegisterOpId:
_handle_register_msg(p, wsSessId, (const char*)msg );
break;
case kEndAppIdUpdateOpId:
_print_eles( p );
cwLogInfo("App Id Update Complete.");
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
} // kMessageTId
break;
default:
cwLogError(kInvalidOpRC,"Unknown websock message type:%i.", msg_type );
return;
}
} }
} }
} }
cw::rc_t cw::ui::createUi( cw::rc_t cw::ui::create(
handle_t& h, handle_t& h,
unsigned port, sendCallback_t sendCbFunc,
uiCallback_t cbFunc, void* sendCbArg,
void* cbArg, uiCallback_t uiCbFunc,
const char* physRootDir, void* uiCbArg,
const char* dfltPageFn, unsigned fmtBufByteN )
unsigned websockTimeOutMs,
unsigned rcvBufByteN,
unsigned xmtBufByteN,
unsigned fmtBufByteN)
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
ele_t* ele; ele_t* ele;
websock::protocol_t protocolA[] = if((rc = destroy(h)) != kOkRC )
{
{ "http", kHttpProtocolId, 0, 0 },
{ "ui_protocol", kUiProtocolId, rcvBufByteN, xmtBufByteN }
};
unsigned protocolN = sizeof(protocolA)/sizeof(protocolA[0]);
if((rc = destroyUi(h)) != kOkRC )
return rc; return rc;
if( cbFunc == nullptr ) if( sendCbFunc == nullptr )
return cwLogError(kInvalidArgRC,"The UI send callback function must be a valid pointer.");
if( uiCbFunc == nullptr )
return cwLogError(kInvalidArgRC,"The UI callback function must be a valid pointer."); return cwLogError(kInvalidArgRC,"The UI callback function must be a valid pointer.");
ui_t* p = mem::allocZ<ui_t>(); ui_t* p = mem::allocZ<ui_t>();
if((rc = websockSrv::create(p->wssH, _websockCb, p, physRootDir, dfltPageFn, port, protocolA, protocolN, websockTimeOutMs )) != kOkRC )
{
cwLogError(rc,"Internal websock server creation failed.");
goto errLabel;
}
p->eleAllocN = 100; p->eleAllocN = 100;
p->eleA = mem::allocZ<ele_t*>( p->eleAllocN ); p->eleA = mem::allocZ<ele_t*>( p->eleAllocN );
p->eleN = 0; p->eleN = 0;
p->cbFunc = cbFunc; p->uiCbFunc = uiCbFunc;
p->cbArg = cbArg; p->uiCbArg = uiCbArg;
p->buf = mem::allocZ<char>(fmtBufByteN); p->sendCbFunc = sendCbFunc;
p->bufN = fmtBufByteN; p->sendCbArg = sendCbArg;
p->buf = mem::allocZ<char>(fmtBufByteN);
p->bufN = fmtBufByteN;
// create the root element // create the root element
if((ele = _createEle(p, nullptr, kRootAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId ) if((ele = _createEle(p, nullptr, kRootAppId, "uiDivId" )) == nullptr || ele->uuId != kRootUuId )
@ -806,29 +637,8 @@ cw::rc_t cw::ui::createUi(
return rc; return rc;
} }
cw::rc_t cw::ui::start( handle_t h )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
if((rc = websockSrv::start(p->wssH)) != kOkRC ) cw::rc_t cw::ui::destroy( handle_t& h )
rc = cwLogError(rc,"Internal websock server start failed.");
return rc;
}
cw::rc_t cw::ui::stop( handle_t h )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
if((rc = websockSrv::pause(p->wssH)) != kOkRC )
rc = cwLogError(rc,"Internal websock server stop failed.");
return rc;
}
cw::rc_t cw::ui::destroyUi( handle_t& h )
{ {
rc_t rc = kOkRC; rc_t rc = kOkRC;
if( !h.isValid() ) if( !h.isValid() )
@ -843,6 +653,58 @@ cw::rc_t cw::ui::destroyUi( handle_t& h )
return rc; return rc;
} }
cw::rc_t cw::ui::onConnect( handle_t h, unsigned wsSessId )
{
return kOkRC;
}
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 )
{
rc_t rc = kOkRC;
ui_t* p = _handleToPtr(h);
opId_t opId = _labelToOpId((const char*)msg);
value_t value;
ele_t* ele;
switch( opId )
{
case kInitOpId:
// Pass on the 'init' msg to the app.
p->uiCbFunc( p->uiCbArg, wsSessId, opId, kInvalidId, kInvalidId, kInvalidId, nullptr );
break;
case kValueOpId:
if((ele = _parse_value_msg(p, value, (const char*)msg )) == nullptr )
cwLogError(kOpFailRC,"UI Value message parse failed.");
else
{
unsigned parentEleAppId = ele->parent == nullptr ? kInvalidId : ele->parent->appId;
p->uiCbFunc( p->uiCbArg, wsSessId, opId, parentEleAppId, ele->uuId, ele->appId, &value );
}
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
return rc;
}
unsigned cw::ui::findElementAppId( handle_t h, unsigned parentUuId, const char* eleName ) unsigned cw::ui::findElementAppId( handle_t h, unsigned parentUuId, const char* eleName )
{ {
ui_t* p = _handleToPtr(h); ui_t* p = _handleToPtr(h);
@ -983,5 +845,321 @@ cw::rc_t cw::ui::registerAppIds( handle_t h, const appIdMap_t* map, unsigned ma
namespace cw
{
namespace ui
{
namespace ws
{
typedef struct ui_ws_str
{
websock::handle_t wsH;
ui::handle_t uiH;
void* cbArg;
uiCallback_t uiCbFunc;
websock::cbFunc_t wsCbFunc;
unsigned wsTimeOutMs;
} ui_ws_t;
ui_ws_t* _handleToPtr( handle_t h )
{ return handleToPtr<handle_t,ui_ws_t>(h); }
rc_t _destroy( ui_ws_t* p )
{
rc_t rc;
if((rc = ui::destroy(p->uiH)) != kOkRC )
return rc;
if((rc = websock::destroy(p->wsH)) != kOkRC )
return rc;
mem::release(p);
return rc;
}
void _webSockCb( void* cbArg, unsigned protocolId, unsigned sessionId, websock::msgTypeId_t msg_type, const void* msg, unsigned byteN )
{
ui_ws_t* p = static_cast<ui_ws_t*>(cbArg);
switch( msg_type )
{
case websock::kConnectTId:
ui::onConnect(p->uiH,sessionId);
break;
case websock::kDisconnectTId:
ui::onDisconnect(p->uiH,sessionId);
break;
case websock::kMessageTId:
ui::onReceive(p->uiH,sessionId,msg,byteN);
break;
default:
cwLogError(kInvalidIdRC,"An invalid websock msgTypeId (%i) was encountered",msg_type);
}
}
rc_t _webSockSend( void* cbArg, unsigned wsSessId, const void* msg, unsigned msgByteN )
{
ui_ws_t* p = static_cast<ui_ws_t*>(cbArg);
return websock::send( p->wsH, kUiProtocolId, wsSessId, msg, msgByteN );
}
}
}
}
cw::rc_t cw::ui::ws::create( handle_t& h,
unsigned port,
const char* physRootDir,
void* cbArg,
uiCallback_t uiCbFunc,
websock::cbFunc_t wsCbFunc,
const char* dfltPageFn,
unsigned websockTimeOutMs,
unsigned rcvBufByteN,
unsigned xmtBufByteN,
unsigned fmtBufByteN )
{
rc_t rc = kOkRC;
if((rc = destroy(h)) != kOkRC )
return rc;
ui_ws_t* p = mem::allocZ<ui_ws_t>();
websock::protocol_t protocolA[] =
{
{ "http", kHttpProtocolId, 0, 0 },
{ "ui_protocol", kUiProtocolId, rcvBufByteN, xmtBufByteN }
};
unsigned protocolN = sizeof(protocolA)/sizeof(protocolA[0]);
websock::cbFunc_t wsCbF = wsCbFunc==nullptr ? _webSockCb : wsCbFunc;
void* wsCbA = wsCbFunc==nullptr ? p : cbArg;
// create the websocket
if((rc = websock::create(p->wsH, wsCbF, wsCbA, physRootDir, dfltPageFn, port, protocolA, protocolN )) != kOkRC )
{
cwLogError(rc,"UI Websock create failed.");
goto errLabel;
}
// create the ui
if((rc = ui::create(p->uiH, _webSockSend, p, uiCbFunc, cbArg, fmtBufByteN )) != kOkRC )
{
cwLogError(rc,"UI object create failed.");
goto errLabel;
}
p->cbArg = cbArg;
p->uiCbFunc = uiCbFunc;
p->wsCbFunc = wsCbFunc;
p->wsTimeOutMs = websockTimeOutMs;
h.set(p);
errLabel:
if( rc != kOkRC )
_destroy(p);
return rc;
}
cw::rc_t cw::ui::ws::destroy( handle_t& h )
{
rc_t rc = kOkRC;
ui_ws_t* p = nullptr;
if( !h.isValid() )
return rc;
p = _handleToPtr(h);
if((rc = _destroy(p)) != kOkRC )
return rc;
h.clear();
return rc;
}
cw::rc_t cw::ui::ws::exec( handle_t h, unsigned timeOutMs )
{
rc_t rc = kOkRC;
ui_ws_t* p = _handleToPtr(h);
if((rc = websock::exec( p->wsH, p->wsTimeOutMs )) != kOkRC)
cwLogError(rc,"The UI websock execution failed.");
return rc;
}
cw::rc_t cw::ui::ws::onReceive( handle_t h, unsigned protocolId, unsigned sessionId, websock::msgTypeId_t msg_type, const void* msg, unsigned byteN )
{
ui_ws_t* p = _handleToPtr(h);
_webSockCb( p, protocolId, sessionId, msg_type, msg, byteN );
return kOkRC;
}
cw::websock::handle_t cw::ui::ws::websockHandle( handle_t h )
{
ui_ws_t* p = _handleToPtr(h);
return p->wsH;
}
cw::ui::handle_t cw::ui::ws::uiHandle( handle_t h )
{
ui_ws_t* p = _handleToPtr(h);
return p->uiH;
}
namespace cw
{
namespace ui
{
namespace srv
{
typedef struct ui_ws_srv_str
{
ws::handle_t wsUiH;
thread::handle_t thH;
unsigned wsTimeOutMs;
} ui_ws_srv_t;
ui_ws_srv_t* _handleToPtr(handle_t h )
{ return handleToPtr<handle_t,ui_ws_srv_t>(h); }
rc_t _destroy( ui_ws_srv_t* p )
{
rc_t rc;
if((rc = thread::destroy(p->thH)) != kOkRC )
return rc;
if((rc = ws::destroy(p->wsUiH)) != kOkRC )
return rc;
mem::release(p);
return rc;
}
bool _threadCallback( void* arg )
{
ui_ws_srv_t* p = static_cast<ui_ws_srv_t*>(arg);
rc_t rc;
if((rc = ws::exec(p->wsUiH,p->wsTimeOutMs)) != kOkRC )
{
cwLogError(rc,"Websocket UI exec failed.");
}
return true;
}
}
}
}
cw::rc_t cw::ui::srv::create( handle_t& h,
unsigned port,
const char* physRootDir,
void* cbArg,
uiCallback_t uiCbFunc,
websock::cbFunc_t wsCbFunc,
const char* dfltPageFn,
unsigned websockTimeOutMs,
unsigned rcvBufByteN,
unsigned xmtBufByteN,
unsigned fmtBufByteN )
{
rc_t rc = kOkRC;
if((rc = destroy(h)) != kOkRC )
return rc;
ui_ws_srv_t* p = mem::allocZ<ui_ws_srv_t>();
if((rc = ws::create(p->wsUiH, port, physRootDir, cbArg, uiCbFunc, wsCbFunc, dfltPageFn, websockTimeOutMs, rcvBufByteN, xmtBufByteN, fmtBufByteN )) != kOkRC )
{
cwLogError(rc,"The websock UI creationg failed.");
goto errLabel;
}
if((rc = thread::create( p->thH, _threadCallback, p )) != kOkRC )
{
cwLogError(rc,"The websock UI server thread create failed.");
goto errLabel;
}
p->wsTimeOutMs = websockTimeOutMs;
h.set(p);
errLabel:
if( rc != kOkRC )
_destroy(p);
return rc;
}
cw::rc_t cw::ui::srv::destroy( handle_t& h )
{
rc_t rc = kOkRC;
if( !h.isValid() )
return rc;
ui_ws_srv_t* p = _handleToPtr(h);
if((rc = _destroy(p)) != kOkRC )
return rc;
h.clear();
return rc;
}
cw::rc_t cw::ui::srv::start( handle_t h )
{
ui_ws_srv_t* p = _handleToPtr(h);
rc_t rc;
if((rc = thread::unpause(p->thH)) != kOkRC )
cwLogError(rc,"WebockUI server thread start failed.");
return rc;
}
cw::rc_t cw::ui::srv::stop( handle_t h )
{
ui_ws_srv_t* p = _handleToPtr(h);
rc_t rc;
if((rc = thread::pause(p->thH, thread::kPauseFl | thread::kWaitFl )) != kOkRC )
cwLogError(rc,"WebockUI server thread stop failed.");
return rc;
}
cw::thread::handle_t cw::ui::srv::threadHandle( handle_t h )
{
ui_ws_srv_t* p = _handleToPtr(h);
return p->thH;
}
cw::websock::handle_t cw::ui::srv::websockHandle( handle_t h )
{
ui_ws_srv_t* p = _handleToPtr(h);
return ws::websockHandle(p->wsUiH);
}
cw::ui::handle_t cw::ui::srv::uiHandle( handle_t h )
{
ui_ws_srv_t* p = _handleToPtr(h);
return ws::uiHandle(p->wsUiH);
}

92
cwUi.h
View File

@ -21,8 +21,6 @@ namespace cw
kConnectOpId, kConnectOpId,
kInitOpId, kInitOpId,
kValueOpId, kValueOpId,
kRegisterOpId,
kEndAppIdUpdateOpId,
kDisconnectOpId kDisconnectOpId
} opId_t; } opId_t;
@ -58,23 +56,21 @@ namespace cw
} u; } u;
} value_t; } value_t;
typedef rc_t (*uiCallback_t)( void* cbArg, unsigned websockSessionId, opId_t opId, unsigned parentAppId, unsigned uuId, unsigned appId, const value_t* value ); typedef rc_t (*uiCallback_t)( void* cbArg, unsigned wsSessId, opId_t opId, unsigned parentAppId, unsigned uuId, unsigned appId, const value_t* value );
typedef rc_t (*sendCallback_t)( void* cbArg, unsigned wsSessId, const void* msg, unsigned msgByteN );
rc_t createUi( handle_t& h, rc_t create( handle_t& h,
unsigned port, sendCallback_t sendCbFunc,
uiCallback_t cbFunc, void* sendCbArg,
void* cbArg, uiCallback_t uiCbFunc,
const char* physRootDir, void* uiCbArg,
const char* dfltPageFn = "index.html", unsigned fmtBufByteN = 4096 );
unsigned websockTimeOutMs = 50,
unsigned rcvBufByteN = 1024,
unsigned xmtBufByteN = 1024,
unsigned fmtBufByteN = 4096 );
rc_t destroyUi( handle_t& h ); rc_t destroy( handle_t& h );
rc_t start( handle_t h ); rc_t onConnect( handle_t h, unsigned wsSessId );
rc_t stop( handle_t h ); rc_t onDisconnect( handle_t h, unsigned wsSessId );
rc_t onReceive( handle_t h, unsigned wsSessId, const void* msg, unsigned byteN );
unsigned findElementAppId( handle_t h, unsigned parentUuId, const char* eleName ); unsigned findElementAppId( handle_t h, unsigned parentUuId, const char* eleName );
unsigned findElementUuId( handle_t h, unsigned parentUuId, const char* eleName ); unsigned findElementUuId( handle_t h, unsigned parentUuId, const char* eleName );
@ -107,7 +103,71 @@ namespace cw
// Register parent/child/name app id's // Register parent/child/name app id's
rc_t registerAppIds( handle_t h, const appIdMap_t* map, unsigned mapN ); rc_t registerAppIds( handle_t h, const appIdMap_t* map, unsigned mapN );
namespace ws
{
typedef handle<struct ui_ws_str> handle_t;
rc_t create( handle_t& h,
unsigned port,
const char* physRootDir,
void* cbArg,
uiCallback_t uiCbFunc,
websock::cbFunc_t wsCbFunc = nullptr,
const char* dfltPageFn = "index.html",
unsigned websockTimeOutMs = 50,
unsigned rcvBufByteN = 1024,
unsigned xmtBufByteN = 1024,
unsigned fmtBufByteN = 4096 );
rc_t destroy( handle_t& h );
// This function should be called periodically to send and receive
// queued messages to and from the websocket.
rc_t exec( handle_t h, unsigned timeOutMs );
// This function executes the internal default websock callback function.
// It is useful if the user provides a custom websock callback function
// and wants to fallback to the default websock->ui interaction.
rc_t onReceive( handle_t h, unsigned protocolId, unsigned sessionId, websock::msgTypeId_t msg_type, const void* msg, unsigned byteN );
websock::handle_t websockHandle( handle_t h );
ui::handle_t uiHandle( handle_t h );
}
namespace srv
{
typedef handle<struct ui_ws_srv_str> handle_t;
rc_t create( handle_t& h,
unsigned port,
const char* physRootDir,
void* cbArg,
uiCallback_t uiCbFunc,
websock::cbFunc_t wsCbFunc = nullptr,
const char* dfltPageFn = "index.html",
unsigned websockTimeOutMs = 50,
unsigned rcvBufByteN = 1024,
unsigned xmtBufByteN = 1024,
unsigned fmtBufByteN = 4096 );
rc_t destroy( handle_t& h );
rc_t start( handle_t h );
rc_t stop( handle_t h );
thread::handle_t threadHandle( handle_t h );
websock::handle_t websockHandle( handle_t h );
ui::handle_t uiHandle( handle_t h );
}
} }
} }

View File

@ -2,6 +2,8 @@
#include "cwLog.h" #include "cwLog.h"
#include "cwCommonImpl.h" #include "cwCommonImpl.h"
#include "cwMem.h" #include "cwMem.h"
#include "cwThread.h"
#include "cwWebSock.h"
#include "cwUi.h" #include "cwUi.h"
#include "cwUiTest.h" #include "cwUiTest.h"
@ -12,8 +14,9 @@ namespace cw
{ {
typedef struct ui_test_str typedef struct ui_test_str
{ {
handle_t uiH;
const char* uiCfgFn; const char* uiCfgFn;
srv::handle_t wsUiSrvH;
} ui_test_t; } ui_test_t;
enum enum
@ -43,45 +46,48 @@ namespace cw
unsigned divUuId = kInvalidId; unsigned divUuId = kInvalidId;
appIdMap_t mapA[] = appIdMap_t mapA[] =
{ {
{ ui::kRootAppId, kPanelDivId, "panelDivId" }, { ui::kRootAppId, kPanelDivId, "panelDivId" },
{ ui::kPanelDivId, kPanelBtnId, "myBtn1Id" }, { ui::kPanelDivId, kPanelBtnId, "myBtn1Id" },
{ ui::kPanelDivId, kPanelCheckId, "myCheck1Id" }, { ui::kPanelDivId, kPanelCheckId, "myCheck1Id" },
}; };
registerAppIds(p->uiH, mapA, sizeof(mapA)/sizeof(mapA[0])); handle_t uiH = srv::uiHandle(p->wsUiSrvH);
if((rc = createDiv( p->uiH, divUuId, wsSessId, kInvalidId, "myDivId", kDivId, "divClass", "My Panel" )) != kOkRC )
registerAppIds(uiH, mapA, sizeof(mapA)/sizeof(mapA[0]));
if((rc = createDiv( uiH, divUuId, wsSessId, kInvalidId, "myDivId", kDivId, "divClass", "My Panel" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createButton( p->uiH, uuid, wsSessId, divUuId, "myBtnId", kBtnId, "btnClass", "Push Me" )) != kOkRC ) if((rc = createButton( uiH, uuid, wsSessId, divUuId, "myBtnId", kBtnId, "btnClass", "Push Me" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createCheck( p->uiH, uuid, wsSessId, divUuId, "myCheckId", kCheckId, "checkClass", "Check Me", true )) != kOkRC ) if((rc = createCheck( uiH, uuid, wsSessId, divUuId, "myCheckId", kCheckId, "checkClass", "Check Me", true )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createSelect( p->uiH, selUuId, wsSessId, divUuId, "mySelId", kSelectId, "selClass", "Select" )) != kOkRC ) if((rc = createSelect( uiH, selUuId, wsSessId, divUuId, "mySelId", kSelectId, "selClass", "Select" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createOption( p->uiH, uuid, wsSessId, selUuId, "myOpt0Id", kOption0Id, "optClass", "Option 0" )) != kOkRC ) if((rc = createOption( uiH, uuid, wsSessId, selUuId, "myOpt0Id", kOption0Id, "optClass", "Option 0" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createOption( p->uiH, uuid, wsSessId, selUuId, "myOpt1Id", kOption1Id, "optClass", "Option 1" )) != kOkRC ) if((rc = createOption( uiH, uuid, wsSessId, selUuId, "myOpt1Id", kOption1Id, "optClass", "Option 1" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createOption( p->uiH, uuid, wsSessId, selUuId, "myOpt2Id", kOption2Id, "optClass", "Option 2" )) != kOkRC ) if((rc = createOption( uiH, uuid, wsSessId, selUuId, "myOpt2Id", kOption2Id, "optClass", "Option 2" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createString( p->uiH, uuid, wsSessId, divUuId, "myStringId", kStringId, "stringClass", "String", "a string value" )) != kOkRC ) if((rc = createString( uiH, uuid, wsSessId, divUuId, "myStringId", kStringId, "stringClass", "String", "a string value" )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createNumber( p->uiH, uuid, wsSessId, divUuId, "myNumberId", kNumberId, "numberClass", "Number", 10, 0, 100, 1, 0 )) != kOkRC ) if((rc = createNumber( uiH, uuid, wsSessId, divUuId, "myNumberId", kNumberId, "numberClass", "Number", 10, 0, 100, 1, 0 )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createProgress( p->uiH, uuid, wsSessId, divUuId, "myProgressId", kProgressId, "progressClass", "Progress", 5, 0, 10 )) != kOkRC ) if((rc = createProgress( uiH, uuid, wsSessId, divUuId, "myProgressId", kProgressId, "progressClass", "Progress", 5, 0, 10 )) != kOkRC )
goto errLabel; goto errLabel;
if((rc = createFromFile( p->uiH, p->uiCfgFn, wsSessId )) != kOkRC ) if((rc = createFromFile( uiH, p->uiCfgFn, wsSessId )) != kOkRC )
goto errLabel; goto errLabel;
errLabel: errLabel:
@ -140,10 +146,6 @@ namespace cw
_uiTestCreateUi(p,wsSessId); _uiTestCreateUi(p,wsSessId);
break; break;
case kRegisterOpId:
break;
case kValueOpId: case kValueOpId:
_handleUiValueMsg( p, wsSessId, parentAppId, uuId, appId, v ); _handleUiValueMsg( p, wsSessId, parentAppId, uuId, appId, v );
break; break;
@ -167,17 +169,21 @@ cw::rc_t cw::ui::test( )
int port = 5687; int port = 5687;
unsigned rcvBufByteN = 2048; unsigned rcvBufByteN = 2048;
unsigned xmtBufByteN = 2048; unsigned xmtBufByteN = 2048;
unsigned fmtBufByteN = 4096;
unsigned websockTimeOutMs = 50; unsigned websockTimeOutMs = 50;
const unsigned sbufN = 31; const unsigned sbufN = 31;
char sbuf[ sbufN+1 ]; char sbuf[ sbufN+1 ];
ui_test_t* ui = mem::allocZ<ui_test_t>(); ui_test_t* app = mem::allocZ<ui_test_t>();
ui->uiCfgFn = "/home/kevin/src/cwtest/src/libcw/html/uiTest/ui.cfg"; app->uiCfgFn = "/home/kevin/src/cwtest/src/libcw/html/uiTest/ui.cfg";
if((rc = createUi(ui->uiH, port, _uiTestCallback, ui, physRootDir, dfltPageFn, websockTimeOutMs, rcvBufByteN, xmtBufByteN )) != kOkRC ) // create the UI server
if((rc = srv::create(app->wsUiSrvH, port, physRootDir, app, _uiTestCallback, nullptr, dfltPageFn, websockTimeOutMs, rcvBufByteN, xmtBufByteN, fmtBufByteN )) != kOkRC )
return rc; return rc;
if((rc = start(ui->uiH)) != kOkRC )
// start the UI server
if((rc = srv::start(app->wsUiSrvH)) != kOkRC )
goto errLabel; goto errLabel;
@ -198,10 +204,10 @@ cw::rc_t cw::ui::test( )
errLabel: errLabel:
rc_t rc1 = kOkRC; rc_t rc1 = kOkRC;
if( ui->uiH.isValid() ) if( app->wsUiSrvH.isValid() )
rc1 = destroyUi(ui->uiH); rc1 = srv::destroy(app->wsUiSrvH);
mem::release(ui); mem::release(app);
return rcSelect(rc,rc1); return rcSelect(rc,rc1);
} }