/*
 * Function:    _wilddog_url_getPath
 * Description: Get the path from the source path.
 * Input:       p_src_path: The source path.
 *              type: type of the function.
 *              str: input str, now used for child's name.
 *              pp_dstPath: The return 
 * Output:      pp_dstPath: pointer to the new path.
 * Return:      If success return 0, else return negative number.
*/
Wilddog_Return_T WD_SYSTEM _wilddog_url_getPath
    (
    Wilddog_Str_T* p_srcPath, 
    Wilddog_RefChange_T type,
    Wilddog_Str_T* str, 
    Wilddog_Str_T** pp_dstPath
    )
{
    wilddog_assert(p_srcPath, WILDDOG_ERR_NULL);
    wilddog_assert(pp_dstPath, WILDDOG_ERR_NULL);

    *pp_dstPath = NULL;

    switch(type)
    {
        case WILDDOG_REFCHG_PARENT:
            *pp_dstPath = _wilddog_url_getParentStr(p_srcPath);
            break;
        case WILDDOG_REFCHG_ROOT:
            *pp_dstPath = _wilddog_url_getRootStr(p_srcPath);
            break;
        case WILDDOG_REFCHG_CHILD:
            *pp_dstPath = _wilddog_url_getChildStr(p_srcPath, str);
            break;
        default:
            return 0;
    }
    if(*pp_dstPath)
        return WILDDOG_ERR_NOERR;
    return WILDDOG_ERR_NULL;
}
/*
 * Function:    wilddog_getKey
 * Description: Get the client's key(the node's name).
 * Input:       wilddog: Id of the client.
 * Output:      N/A
 * Return:      a pointer point to a name string(should be freed by user).
 * Others:      N/A
*/
Wilddog_Str_T *wilddog_getKey(Wilddog_T wilddog)
{
    wilddog_assert(wilddog, NULL);

    return (Wilddog_Str_T *)_wilddog_ct_ioctl(WILDDOG_APICMD_GETKEY, \
                                                (void*)wilddog,0);
}
/*
 * Function:    _wilddog_coap_countPacktSize.
 * Description: Count the conn packet size.
 *              Count method:
 *                    host : 4+ host len
 *                    path : n*(4+ subpath)
 *                    query: 4+2+query len
 * Input:       p_cp_pkt: The pointer of conn packet
 * Output:      N/A
 * Return:      The number of the conn packet size
*/
STATIC int WD_SYSTEM _wilddog_coap_countPacktSize
    (
    Protocol_Arg_CountSize_T *p_arg
    )
{
    int len = 0,n=0;
    wilddog_assert(p_arg,0);
    
    /*option*/
    if(p_arg->p_host)
        len = 4+ strlen((const char *)p_arg->p_host);
    
    if(p_arg->p_query)
        len += 6+ strlen((const char *)p_arg->p_query);
    if(p_arg->p_path)
    {
        n = _wilddog_coap_findChar('/',p_arg->p_path);
        len += 4*(n+1)+strlen((const char *)p_arg->p_path);
        }
    else
        len += 5;
    
    /* payload add */
    len += (p_arg->d_payloadLen + 4 );
    
    /* + had + token + observer*/
    len += 8 + 14 + 8;
    
    return len;
}
/*
 * Function:    wilddog_destroy
 * Description: Destory a wilddog client.
 * Input:       p_wilddog: a pointer which point to the client id.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_destroy(Wilddog_T *p_wilddog)
{
    wilddog_assert(p_wilddog, 0);

    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_DESTROYREF, \
                                               p_wilddog,0);
}
int WD_SYSTEM _wilddogurl_checkPath(Wilddog_Str_T *p_path)
{
    int len , i;
    u8 data;
    wilddog_assert(p_path, WILDDOG_ERR_NULL);

    len = strlen((const char*)p_path);

    if( (p_path[0] == '/') || ((len >= 1) && (p_path[len - 1] == '/')))
        return WILDDOG_ERR_INVALID;

    for(i = 0; i < len; i++)
    {
        data = p_path[i];
        if( data <  32  || \
            data == '.' || \
            data == '$' || \
            data == '#' || \
            data == '[' || \
            data == ']' || \
            data ==  127)
        {
            return WILDDOG_ERR_INVALID;
        }
        if(i < len - 1)
        {
            if(data == '/' && p_path[i + 1] == '/')
                return WILDDOG_ERR_INVALID;
        }
    }
    return WILDDOG_ERR_NOERR;
}
STATIC int WD_SYSTEM _wilddog_conn_onLine
    ( 
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    

    /*set online.*/
    return _wilddog_cm_ioctl(CM_CMD_ONLINE,p_arg->p_repo->p_rp_conn->p_cm_l,0);
/*
 * Function:    wilddog_getChild
 * Description: Get the client's child.
 * Input:       wilddog: Id of the client.
 * Output:      N/A
 * Return:      an id of your client's child.
 * Others:      The sdk do not check wether the child is really in the server 
 *              or not, only create it.
*/
Wilddog_T wilddog_getChild(Wilddog_T wilddog, Wilddog_Str_T * childName)
{
    Wilddog_Arg_GetRef_T args;
    
    wilddog_assert(wilddog, 0);
    
    args.p_ref = wilddog;
    args.d_cmd = WILDDOG_REFCHG_CHILD;
    args.p_str = childName;
    
    return (Wilddog_T )_wilddog_ct_ioctl(WILDDOG_APICMD_GETREF, &args, 0);
}
/*
 * Function:    wilddog_getRoot
 * Description: Get the client's Root.
 * Input:       wilddog: Id of the client.
 * Output:      N/A
 * Return:      an id of your client's root.
*/
Wilddog_T wilddog_getRoot(Wilddog_T wilddog)
{
    Wilddog_Arg_GetRef_T args;
    
    wilddog_assert(wilddog, 0);

    args.p_ref = wilddog;
    args.d_cmd = WILDDOG_REFCHG_ROOT;
    args.p_str = NULL;
    
    return (Wilddog_T )_wilddog_ct_ioctl(WILDDOG_APICMD_GETREF, &args,0);
}
/*
 * Function:    wilddog_auth
 * Description: Set the auth data to a host(such as aaa.wilddogio.com).
 * Input:       p_host: a pointer to host .
 *              p_auth: the auth data
 *              len: the auth data length
 *              onAuth: the callback function called when the server returns 
 *                      a response or send fail.
 *              args: the arg defined by user, if you do not need, can be NULL.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
 * Others:      Input url such as appId.wilddogio.com
*/
Wilddog_Return_T wilddog_auth
    (
    Wilddog_Str_T * p_host, 
    u8 *p_auth, 
    int len, 
    onAuthFunc onAuth, 
    void* args
    )
{
    Wilddog_Arg_SetAuth_T arg;

    wilddog_assert(p_host, WILDDOG_ERR_NULL);
    wilddog_assert(p_auth, WILDDOG_ERR_NULL);
    
    arg.p_host = p_host;
    arg.p_auth = p_auth;
    arg.d_len = len;
    arg.onAuth = onAuth;
    arg.arg = args;

    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_SETAUTH, &arg,0);
}
/*
 * Function:    _wilddog_conn_getCborPayload.
 * Description: node transition to cbor payload.
 * Input:   p_node: node data.
 *             p_pkg: protocol package.
 * Output:      N/A
 * Return:      N/A
*/ 
STATIC Wilddog_Return_T WD_SYSTEM _wilddog_conn_getCborPayload
    (
    Protocol_Arg_Payload_T *p_cbor_hd,
    Wilddog_Node_T *p_snode
    )
{
    Wilddog_Payload_T *p_nodeData = NULL;

    wilddog_assert(p_cbor_hd,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_snode,WILDDOG_ERR_INVALID);

    p_nodeData = _wilddog_node2Payload(p_snode);

    if( p_nodeData )
    {
        p_cbor_hd->p_payload = p_nodeData->p_dt_data;
        p_cbor_hd->d_payloadLen = p_nodeData->d_dt_len;
        wfree(p_nodeData);

        return WILDDOG_ERR_NOERR;
    }
    else
        return WILDDOG_ERR_NULL;
}
/*
 * Function:    wilddog_removeObserver
 * Description: Unsubscibe the client's data change.
 * Input:       wilddog: Id of the client.
 *              event: Event type, see the struct.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_removeObserver
    (
    Wilddog_T wilddog, 
    Wilddog_EventType_T event
    )
{
    Wilddog_Arg_Off_T args;
    
    wilddog_assert(wilddog, WILDDOG_ERR_NULL);
    
    args.p_ref = wilddog;
    args.d_event = event;
    
    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_OFF, &args,0);
}
/*
 * Function:    wilddog_getValue
 * Description: Get the data of the client from server.
 * Input:       wilddog: the id of wilddog client.
 *              callback: the callback function called when the server returns 
 *                      a response or send fail.
 *              args: the arg defined by user, if you do not need, can be NULL.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_getValue
    (
    Wilddog_T wilddog, 
    onQueryFunc callback, 
    void* arg
    )
{
    Wilddog_Arg_Query_T args;

    wilddog_assert(wilddog, WILDDOG_ERR_NULL);
    
    args.p_ref = wilddog;
    args.p_callback = (Wilddog_Func_T)callback;
    args.arg = arg;
    
    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_QUERY, &args,0);
}
/*
 * Function:    wilddog_removeValue
 * Description: Remove the data of the client from server.
 * Input:       wilddog: Id of the client.
 *              callback: the callback function called when the server returns 
 *                      a response or send fail.
 *              args: the arg defined by user, if you do not need, can be NULL.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_removeValue
    (
    Wilddog_T wilddog,
    onRemoveFunc callback, 
    void* arg
    )
{
    Wilddog_Arg_Remove_T args;
    
    wilddog_assert(wilddog, WILDDOG_ERR_NULL);

    args.p_ref = wilddog;
    args.p_callback = (Wilddog_Func_T)callback;
    args.arg = arg;
    
    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_REMOVE, &args,0);
}
/*
 * Function:    wilddog_addObserver
 * Description: Subscibe the client's data change, if data changed, server 
 *              will notify the client.
 * Input:       wilddog: Id of the client.
 *              event: Event type, see the struct.
 *              onDataChange: The callback function called when the server 
 *                          sends a data change packet.
 *              dataChangeArg: The arg defined by user, if you do not need, 
 *                          can be NULL.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_addObserver
    (
    Wilddog_T wilddog,
    Wilddog_EventType_T event, 
    onEventFunc onDataChange, 
    void* dataChangeArg
    )
{
    Wilddog_Arg_On_T args;
    wilddog_assert(wilddog, WILDDOG_ERR_NULL);
    
    args.p_ref = wilddog;
    args.d_event = event;
    args.p_onData = (Wilddog_Func_T)onDataChange;
    args.p_dataArg = dataChangeArg;
    
    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_ON, &args,0);
}
/*
 * Function:    wilddog_setValue
 * Description: Post the data of the client to server.
 * Input:       wilddog: Id of the client.
 *              p_node: a point to node(Wilddog_Node_T structure), you can
 *                      create a node tree by call node APIs.
 *              callback: the callback function called when the server returns 
 *                      a response or send fail.
 *              args: the arg defined by user, if you do not need, can be NULL.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_setValue
    (
    Wilddog_T wilddog, 
    Wilddog_Node_T *p_node, 
    onSetFunc callback, 
    void* arg
    )
{
    Wilddog_Arg_Set_T args;
    
    wilddog_assert(wilddog, WILDDOG_ERR_NULL);
    
    args.p_ref = wilddog;
    args.p_node = p_node;
    args.p_callback = (Wilddog_Func_T)callback;
    args.arg = arg;
    
    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_SET, &args,0);
}
/*
 * Function:    wilddog_push
 * Description: Push the data of the client to server.
 * Input:       wilddog: Id of the client.
 *              p_node: a point to node(Wilddog_Node_T structure), you can 
 *                      create a node tree by call node APIs.
 *              callback: the callback function called when the server returns 
 *                      a response or send fail.
 *              args: the arg defined by user, if you do not need, can be NULL.
 * Output:      N/A
 * Return:      0 means succeed, negative number means failed.
*/
Wilddog_Return_T wilddog_push
    (
    Wilddog_T wilddog,
    Wilddog_Node_T *p_node, 
    onPushFunc callback,
    void* arg
    )
{
    Wilddog_Arg_Push_T args;
    
    wilddog_assert(wilddog, WILDDOG_ERR_NULL);
    
    args.p_ref = wilddog;
    args.p_node = p_node;
    args.p_callback = (Wilddog_Func_T)callback;
    args.arg = arg;
    
    return (Wilddog_Return_T)_wilddog_ct_ioctl(WILDDOG_APICMD_PUSH, &args,0);
}
STATIC int WD_SYSTEM _wilddog_conn_push
    (
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    void* p_pkg_index = 0;
    int res = 0;
    Protocol_Arg_Creat_T pkg_arg;
    Protocol_Arg_Option_T pkg_option;
    Protocol_Arg_Payload_T pkg_cborPayload;

    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_url,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_data,WILDDOG_ERR_INVALID);

    memset(&pkg_arg,0,sizeof(Protocol_Arg_Creat_T));
    memset(&pkg_option,0,sizeof(Protocol_Arg_Option_T));    
    memset(&pkg_cborPayload,0,sizeof(Protocol_Arg_Payload_T));
    
    /* init protocol package.*/
    pkg_arg.cmd = WILDDOG_CONN_CMD_PUSH;
 
    /* get messageid */
    pkg_arg.d_index = (u16)_wilddog_cm_ioctl(CM_CMD_GET_INDEX,NULL,0);
    
    pkg_arg.d_token = _wilddog_cm_ioctl(CM_CMD_GET_TOKEN, \
                                        p_arg->p_repo->p_rp_conn->p_cm_l, \
                                        0);
    
    /*get payload len.*/
    if(_wilddog_conn_getCborPayload(&pkg_cborPayload,p_arg->p_data) < 0 )
        return WILDDOG_ERR_INVALID;
    /*get package size.*/
    pkg_arg.d_packageLen = _wilddog_conn_countPakgeSize(p_arg, \
                                                 pkg_cborPayload.d_payloadLen, \
                                                 0);
    
    /* creat coap package.*/
    p_pkg_index =(void*)_wilddog_protocol_ioctl(_PROTOCOL_CMD_CREAT,&pkg_arg,0);
    if( p_pkg_index == 0)
         return WILDDOG_ERR_NULL;
 
    /* add host.*/
    /* add path.*/
    if(_wilddog_conn_addUrl(p_arg->p_url,(void*)p_pkg_index) != WILDDOG_ERR_NOERR)
         goto _CONN_PUSH_ERR;
    /* add query - auth.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)_wilddog_cm_ioctl(CM_CMD_SHORTTOKEN,
                                             p_arg->p_repo->p_rp_conn->p_cm_l, \
                                             0);

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_QUERY,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
         goto _CONN_PUSH_ERR;
    /*add payload*/
    pkg_cborPayload.p_pkg = p_pkg_index;

    res = (int)_wilddog_protocol_ioctl(_PROTOCOL_CMD_ADD_DATA, \
                                       &pkg_cborPayload, \
                                       0);
    
    if( res < 0)
         goto _CONN_PUSH_ERR;
    
    wfree(pkg_cborPayload.p_payload);

    /* send to */ 
    res = (int)_wilddog_conn_send(pkg_arg.cmd, \
                                  (void*)p_pkg_index, \
                                  pkg_arg.d_token, \
                                  p_arg);
    
    if( res < 0)
         goto _CONN_PUSH_ERR;

    return res;
     
_CONN_PUSH_ERR:
    
    wfree(pkg_cborPayload.p_payload);
    _wilddog_protocol_ioctl(_PROTOCOL_CMD_DESTORY,(void*)p_pkg_index,0);
    return res;
STATIC int WD_SYSTEM _wilddog_conn_get
    (
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    void* p_pkg_index = NULL;
    int res = 0;
    Protocol_Arg_Creat_T pkg_arg;
    Protocol_Arg_Option_T pkg_option;

    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_url,WILDDOG_ERR_INVALID);
    
    memset(&pkg_arg,0,sizeof(Protocol_Arg_Creat_T));
    memset(&pkg_option,0,sizeof(Protocol_Arg_Option_T));

    /* init protocol package.*/
    pkg_arg.cmd = WILDDOG_CONN_CMD_GET;

    /* get messageid */
    pkg_arg.d_index = (u16)_wilddog_cm_ioctl(CM_CMD_GET_INDEX,NULL,0);
    
    pkg_arg.d_token = (u32)_wilddog_cm_ioctl(CM_CMD_GET_TOKEN, \
                                             p_arg->p_repo->p_rp_conn->p_cm_l, \
                                             0);

    /*count pakage size*/
    pkg_arg.d_packageLen = _wilddog_conn_countPakgeSize(p_arg,0,0);
    /* creat coap package.*/
    p_pkg_index = (void*)_wilddog_protocol_ioctl(_PROTOCOL_CMD_CREAT,&pkg_arg,0);
    if( p_pkg_index == 0)
        return WILDDOG_ERR_NULL;

    /* add host.*/
    /* add path.*/
    if(_wilddog_conn_addUrl(p_arg->p_url,p_pkg_index) != WILDDOG_ERR_NOERR)
        goto _CONN_GET_ERR;
    /* add query - auth.*/
    pkg_option.p_pkg = p_pkg_index;
    pkg_option.p_options = (void*)_wilddog_cm_ioctl(CM_CMD_SHORTTOKEN,
                                             p_arg->p_repo->p_rp_conn->p_cm_l, \
                                             0);

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_QUERY,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_GET_ERR;
   
    /* send to */ 
    res = _wilddog_conn_send(WILDDOG_CONN_CMD_GET,
                             p_pkg_index,
                             pkg_arg.d_token,
                             p_arg);
    if(res < 0)
        goto _CONN_GET_ERR;
   
    return res;

_CONN_GET_ERR:

    _wilddog_protocol_ioctl(_PROTOCOL_CMD_DESTORY,p_pkg_index,0);
    return res;
}
STATIC int WD_SYSTEM _wilddog_conn_auth
    (
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    void* p_pkg_index = 0;
    int res = 0;
    u8 *p_buf = NULL;
    Protocol_Arg_Creat_T pkg_arg;
    Protocol_Arg_Option_T pkg_option;
    Protocol_Arg_Payload_T authData;

    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_url,WILDDOG_ERR_INVALID);

    memset(&pkg_arg,0,sizeof(Protocol_Arg_Creat_T));
    memset(&pkg_option,0,sizeof(Protocol_Arg_Option_T));
    memset(&authData,0,sizeof(Protocol_Arg_Payload_T));
   /* init protocol package.*/
   pkg_arg.cmd = WILDDOG_CONN_CMD_AUTH;

   /* get messageid */
   pkg_arg.d_index = (u16)_wilddog_cm_ioctl(CM_CMD_GET_INDEX,NULL,0);
   pkg_arg.d_token = _wilddog_cm_ioctl(CM_CMD_GET_TOKEN, \
                                       p_arg->p_repo->p_rp_conn->p_cm_l,
                                       0);

   /* get auth data and payload size*/
   authData.d_payloadLen = p_arg->p_repo->p_rp_store->p_se_callback(
                                p_arg->p_repo->p_rp_store,\
                                WILDDOG_STORE_CMD_GETAUTH, \
                                &p_buf, \
                                0);
   
   authData.p_payload = p_buf;
   /* count pakge size.*/
   pkg_arg.d_packageLen = _wilddog_conn_countPakgeSize(p_arg, \
                                                        authData.d_payloadLen, \
                                                        0);
   /* creat coap package.*/
   p_pkg_index = (void*)_wilddog_protocol_ioctl(_PROTOCOL_CMD_CREAT,&pkg_arg,0);
   if( p_pkg_index == 0)
        return WILDDOG_ERR_NULL;

   /* add host.*/
   pkg_option.p_pkg = (void*)p_pkg_index;
   pkg_option.p_options = p_arg->p_url->p_url_host;

   res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_HOST,&pkg_option,0);
   if( res != WILDDOG_ERR_NOERR )
       goto _CONN_AUTH_ERR;
   
   /* add path.*/
   pkg_option.p_pkg = (void*)p_pkg_index;
   pkg_option.p_options = _CM_AUTHR_PATH;

   res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_PATH,&pkg_option,0);
   if( res != WILDDOG_ERR_NOERR )
       goto _CONN_AUTH_ERR;

   /*add payload.*/
   authData.p_pkg = (void*)p_pkg_index; 

   res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_DATA,&authData,0);
   if(res < 0)
        goto _CONN_AUTH_ERR;
   /* send to */ 

   res = (int)_wilddog_conn_send(pkg_arg.cmd, \
                                 (void*)p_pkg_index, \
                                 pkg_arg.d_token, \
                                 p_arg);
   if( res < 0)
        goto _CONN_AUTH_ERR;
   
   return res;
    
_CONN_AUTH_ERR:
    
   _wilddog_protocol_ioctl(_PROTOCOL_CMD_DESTORY,(void*)p_pkg_index,0);
   return res;
   
STATIC int WD_SYSTEM _wilddog_conn_on
    (
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    void* p_pkg_index = 0;
    int res = 0;
    u8 observerValue = 0;
    Protocol_Arg_Creat_T pkg_arg;
    Protocol_Arg_Option_T pkg_option;
    Wilddog_CM_UserArg_T sendArg;

    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_url,WILDDOG_ERR_INVALID);

    memset(&pkg_arg,0,sizeof(Protocol_Arg_Creat_T));
    memset(&pkg_option,0,sizeof(Protocol_Arg_Option_T));
    memset(&sendArg,0,sizeof(Wilddog_CM_UserArg_T));    
    /* init protocol package.*/
    pkg_arg.cmd = WILDDOG_CONN_CMD_ON;

    /* get messageid */
    pkg_arg.d_index = (u16)_wilddog_cm_ioctl(CM_CMD_GET_INDEX,NULL,0);
    pkg_arg.d_token = _wilddog_cm_ioctl(CM_CMD_GET_TOKEN, \
                                        p_arg->p_repo->p_rp_conn->p_cm_l, \
                                        0);

    /*count package size.*/
    pkg_arg.d_packageLen = _wilddog_conn_countPakgeSize(p_arg,0,0);

    /* creat coap package.*/
    p_pkg_index =(void*)_wilddog_protocol_ioctl(_PROTOCOL_CMD_CREAT,&pkg_arg,0);
    if( p_pkg_index == 0)
        return WILDDOG_ERR_NULL;

    /* add host.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = p_arg->p_url->p_url_host;

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_HOST,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_ON_ERR;
    /* add query - observer.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)&observerValue;

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_OBSERVER,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_ON_ERR;
    /* add path.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = p_arg->p_url->p_url_path;
    
    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_PATH,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_ON_ERR;

    /* add token.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)_wilddog_cm_ioctl(CM_CMD_SHORTTOKEN, \
                                             p_arg->p_repo->p_rp_conn->p_cm_l, \
                                             0);

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_QUERY,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_ON_ERR;

    /* todo send to */
    sendArg.cmd = WILDDOG_CONN_CMD_ON;
    sendArg.d_token = pkg_arg.d_token;
    sendArg.p_cm_l =  p_arg->p_repo->p_rp_conn->p_cm_l;
    sendArg.p_pkg = (void*)p_pkg_index;
    sendArg.f_userCB = p_arg->p_complete;
    sendArg.f_userCB_arg = p_arg->p_completeArg;
    sendArg.p_path = p_arg->p_url->p_url_path;
    
    if( (res = _wilddog_cm_ioctl( CM_CMD_USERSEND,&sendArg,0))< 0)
        goto _CONN_ON_ERR;

    return res;

_CONN_ON_ERR:

    _wilddog_protocol_ioctl(_PROTOCOL_CMD_DESTORY,(void*)p_pkg_index,0);
    return res;
    
}
STATIC int WD_SYSTEM _wilddog_conn_off
    (
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    int res = 0;
    void* p_pkg_index = 0;
    u8 observerValue = 1;
    Protocol_Arg_Creat_T pkg_arg;
    Protocol_Arg_Option_T pkg_option;
    Wilddog_CM_OffArg_T deleNodeArg;

    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_url,WILDDOG_ERR_INVALID);

    memset(&pkg_arg,0,sizeof(Protocol_Arg_Creat_T));
    memset(&pkg_option,0,sizeof(Protocol_Arg_Option_T));

    /* init protocol package.*/
    pkg_arg.cmd = WILDDOG_CONN_CMD_OFF;
    /* get messageid */
    pkg_arg.d_index = (u16)_wilddog_cm_ioctl(CM_CMD_GET_INDEX,NULL,0);
    pkg_arg.d_token = _wilddog_cm_ioctl(CM_CMD_GET_TOKEN, \
                                        p_arg->p_repo->p_rp_conn->p_cm_l, \
                                        0);

    /*count package size.*/
    pkg_arg.d_packageLen = _wilddog_conn_countPakgeSize(p_arg,0,0);

    /* creat coap package.*/
    p_pkg_index = (void*)_wilddog_protocol_ioctl(_PROTOCOL_CMD_CREAT,&pkg_arg,0);
    if( p_pkg_index == 0)
        return WILDDOG_ERR_NULL;

    /* add host.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = p_arg->p_url->p_url_host;

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_HOST,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
       goto _CONN_OFF_ERR;
    /* add query - observer.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)&observerValue;

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_OBSERVER,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
       goto _CONN_OFF_ERR;
    /* add path.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = p_arg->p_url->p_url_path;

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_PATH,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_OFF_ERR;

    /* add query - token.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)_wilddog_cm_ioctl(CM_CMD_SHORTTOKEN, \
                                             p_arg->p_repo->p_rp_conn->p_cm_l, \
                                             0);

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_QUERY,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_OFF_ERR;

    /*delete on node */
    deleNodeArg.p_cm_l = p_arg->p_repo->p_rp_conn->p_cm_l;
    deleNodeArg.p_path = p_arg->p_url->p_url_path;

    res = _wilddog_cm_ioctl( CM_CMD_DELENODE_BYPATH,&deleNodeArg,0);
    if( res < 0 )
        goto _CONN_OFF_ERR;
    /* todo send to */ 

    res = (int)_wilddog_conn_send(pkg_arg.cmd, \
                                  (void*)p_pkg_index,pkg_arg.d_token, \
                                  p_arg);
    if( res < 0 )
        goto _CONN_OFF_ERR;

    return res;
    
_CONN_OFF_ERR:

    _wilddog_protocol_ioctl(_PROTOCOL_CMD_DESTORY,(void*)p_pkg_index,0);
    return res;
    
/*
 * Function:    wilddog_initWithUrl
 * Description: Init a wilddog client. A client is the path in the HOST tree.
 * Input:       url: A url such as coaps://<appid>.wilddogio.com/<path>
 * Output:      N/A
 * Return:      Id of the client.
*/
Wilddog_T wilddog_initWithUrl(Wilddog_Str_T *url)
{
    wilddog_assert(url, 0);
    
    return (Wilddog_T )_wilddog_ct_ioctl(WILDDOG_APICMD_CREATEREF, url,0);
}
STATIC int WD_SYSTEM _wilddog_conn_onDisRemove
    (
    Wilddog_ConnCmd_Arg_T *p_arg,
    int flags
    )
{
    void* p_pkg_index = 0;
    int res = 0;
    Protocol_Arg_Creat_T pkg_arg;
    Protocol_Arg_Option_T pkg_option;

    wilddog_assert(p_arg,WILDDOG_ERR_INVALID);    
    wilddog_assert(p_arg->p_url,WILDDOG_ERR_INVALID);

    memset(&pkg_arg,0,sizeof(Protocol_Arg_Creat_T));
    memset(&pkg_option,0,sizeof(Protocol_Arg_Option_T));    
    
    /* init protocol package.*/
    pkg_arg.cmd = WILDDOG_CONN_CMD_ONDISREMOVE;

    /* get messageid */
    pkg_arg.d_index = (u16)_wilddog_cm_ioctl(CM_CMD_GET_INDEX,NULL,0);
    pkg_arg.d_token = _wilddog_cm_ioctl(CM_CMD_GET_TOKEN, \
                                        p_arg->p_repo->p_rp_conn->p_cm_l, \
                                        0);

    /*count package size.*/
    pkg_arg.d_packageLen = _wilddog_conn_countPakgeSize(p_arg, \
                                 0, \
                                 (strlen(_CM_ONDIS)+PROTOCOL_QUERY_HEADLEN));
    /* creat coap package.*/
    p_pkg_index =(void*)_wilddog_protocol_ioctl(_PROTOCOL_CMD_CREAT,&pkg_arg,0);
    if( p_pkg_index == 0)
        return WILDDOG_ERR_NULL;

    /* add host.*/
    /* add path.*/
    res = _wilddog_conn_addUrl(p_arg->p_url,(void*)p_pkg_index);
    if( res != WILDDOG_ERR_NOERR)
        goto _CONN_DISREMOVE_ERR;
    /* add query - token.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)_wilddog_cm_ioctl(CM_CMD_SHORTTOKEN,
        p_arg->p_repo->p_rp_conn->p_cm_l,0);
    
    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_QUERY,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_DISREMOVE_ERR;
    /* add query -.dis.*/
    pkg_option.p_pkg = (void*)p_pkg_index;
    pkg_option.p_options = (void*)_CM_ONDIS;

    res = _wilddog_protocol_ioctl( _PROTOCOL_CMD_ADD_QUERY,&pkg_option,0);
    if( res != WILDDOG_ERR_NOERR )
        goto _CONN_DISREMOVE_ERR;

    /* send to */ 
    res = (int)_wilddog_conn_send(pkg_arg.cmd, \
                                  (void*)p_pkg_index, \
                                  pkg_arg.d_token, \
                                  p_arg);
    if( res < 0 )
        goto _CONN_DISREMOVE_ERR;

    return res;

_CONN_DISREMOVE_ERR:

    _wilddog_protocol_ioctl(_PROTOCOL_CMD_DESTORY,(void*)p_pkg_index,0);
    return res;
   
/*
 * Function:    _wilddog_url_parseUrl
 * Description: parse url using wilddog format.
 * Input:       url: Input url.
 * Output:      N/A
 * Return:      Pointer to the url structure.
*/
Wilddog_Url_T * WD_SYSTEM _wilddog_url_parseUrl(Wilddog_Str_T * url)
{
    struct parsed_url * p_paresd_url = NULL;
    Wilddog_Url_T * p_wd_url = NULL;
    int len  = 2;
    
    wilddog_assert(url, NULL);
    
    p_paresd_url = parse_url((char*)url);
    if(NULL == p_paresd_url)
        return NULL;
    
    p_wd_url = (Wilddog_Url_T *)wmalloc(sizeof(Wilddog_Url_T));
    if(NULL == p_wd_url)
    {
        wilddog_debug_level(WD_DEBUG_ERROR, "cannot malloc p_wd_url!\n");
        parsed_url_free(p_paresd_url);
        return NULL;
    }
    
    if(NULL != p_paresd_url->host)
    {
        p_wd_url->p_url_host = (Wilddog_Str_T *)wmalloc( \
            strlen(p_paresd_url->host) + 1);
        if(NULL == p_wd_url->p_url_host)
        {
            wilddog_debug_level(WD_DEBUG_ERROR, "cannot malloc p_url_host!\n");
            _wilddog_url_freeParsedUrl(p_wd_url);
            parsed_url_free(p_paresd_url);
            return NULL;
        }
        strncpy((char*)p_wd_url->p_url_host, (char*)p_paresd_url->host, \
            strlen((const char*)p_paresd_url->host));
    }
    else 
        return NULL;
    
    if(NULL == p_paresd_url->path)
    {
        p_wd_url->p_url_path = (Wilddog_Str_T *)wmalloc(len);
        if(NULL == p_wd_url->p_url_path)
        {
            _wilddog_url_freeParsedUrl(p_wd_url);
            parsed_url_free(p_paresd_url);
            return NULL;
        }
        p_wd_url->p_url_path[0] = '/';
    }
    else
    {
        len += strlen((const char*)p_paresd_url->path);

        if(WILDDOG_ERR_NOERR != \
           _wilddogurl_checkPath((Wilddog_Str_T*)p_paresd_url->path)
           )
        {
            _wilddog_url_freeParsedUrl(p_wd_url);
            parsed_url_free(p_paresd_url);
            return NULL;
        }
        p_wd_url->p_url_path = (Wilddog_Str_T *)wmalloc(len + 1);
        if(NULL == p_wd_url->p_url_path)
        {
            _wilddog_url_freeParsedUrl(p_wd_url);
            parsed_url_free(p_paresd_url);
            return NULL;
        }
        snprintf((char*)p_wd_url->p_url_path, len, "/%s", \
            p_paresd_url->path);
        len = strlen((const char*)p_wd_url->p_url_path);
        if(len > 1 && p_wd_url->p_url_path[len - 1] == '/')
        {
            p_wd_url->p_url_path[len - 1] = 0;
        }
    }
    
    if(NULL != p_paresd_url->query)
    {
        p_wd_url->p_url_query = (Wilddog_Str_T *)wmalloc( \
            strlen((const char*)p_paresd_url->query) + 1);
        if(NULL == p_wd_url->p_url_query)
        {
            _wilddog_url_freeParsedUrl(p_wd_url);
            parsed_url_free(p_paresd_url);
            return NULL;
        }
        strncpy((char*)p_wd_url->p_url_query, (char*)p_paresd_url->query, \
            strlen((const char*)p_paresd_url->query));
    }
    
    parsed_url_free(p_paresd_url);
    return p_wd_url;
}