Ejemplo n.º 1
0
/*---------------------------------------------------------------------------
 *            OBEXH_BuildByteSeq()
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Builds Byte Sequence and UNICODE style OBEX headers. Used by 
 *            both client and server functions.
 *
 * Return:    TRUE  if headers could be added.
 *            FALSE if headers would exceed limits on buffer or transmit space.
 */
BOOL OBEXH_BuildByteSeq(ObexAppHandle *AppHndl, ObexHeaderType Type, const U8 *Value, U16 Len)
{
    OS_LockObex();

#if XA_ERROR_CHECK == XA_ENABLED
    if (!AppHndl || !ObIsHeaderSpaceAvail(AppHndl, (U16)(Len+3)) ||
        ((Type & 0xC0) != 0x40 && (Type & 0xC0) != 0)) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */

    ASSERT(AppHndl && AppHndl->buffer != 0);
    ASSERT(ObIsHeaderSpaceAvail(AppHndl, (U16)(Len+3)) &&
           ((Type & 0xC0) == 0x40 || (Type & 0xC0) == 0));
    
    if (Type == OBEXH_END_BODY) {
        AppHndl->appHeaderIsEndBody = TRUE;
    }

    AppHndl->buffer[AppHndl->txLength++] = Type;  
    AppHndl->buffer[AppHndl->txLength++] = (U8)((Len+3) >> 8);
    AppHndl->buffer[AppHndl->txLength++] = (U8) (Len+3);
    if (Len > 0) {
        ASSERT( Value != 0 );
        OS_MemCopy(AppHndl->buffer+AppHndl->txLength, Value, Len);
        AppHndl->txLength += Len;
    }

    OS_UnlockObex();
    return TRUE;
}
Ejemplo n.º 2
0
/*---------------------------------------------------------------------------
 *            OBEXH_FlushHeaders()
 *---------------------------------------------------------------------------
 *
 * Synopsis:  This function is used to flush any constructed headers from
 *            the header buffer. This function is used when OBEXH_Build...()
 *            functions are used and the operation is cancelled before the
 *            headers are sent or if the requested Operation fails to start.
 *
 * Return:    void
 */
void OBEXH_FlushHeaders(ObexAppHandle *AppHndl)
{
    ASSERT(AppHndl);

    OS_LockObex();
    AppHndl->txLength = 0;
    OS_UnlockObex();
}
Ejemplo n.º 3
0
/*---------------------------------------------------------------------------
 *            OBEXH_Build1Byte()
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Builds 1-byte style OBEX headers. Used by both client and 
 *            server functions.
 *
 * Return:    TRUE  if headers could be added.
 *            FALSE if headers would exceed limits on buffer or transmit space.
 */
BOOL OBEXH_Build1Byte(ObexAppHandle *AppHndl, ObexHeaderType Type, U8 Value)
{
    OS_LockObex();

#if XA_ERROR_CHECK == XA_ENABLED
    if (!AppHndl || !ObIsHeaderSpaceAvail(AppHndl, 2) || (Type & 0xC0) != 0x80) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */

    ASSERT(AppHndl && AppHndl->buffer != 0);
    ASSERT(ObIsHeaderSpaceAvail(AppHndl, 2) && (Type & 0xC0) == 0x80);
    
    AppHndl->buffer[AppHndl->txLength++] = Type;
    AppHndl->buffer[AppHndl->txLength++] = Value;

    OS_UnlockObex();
    return TRUE;
}
Ejemplo n.º 4
0
/*---------------------------------------------------------------------------
 *            OBEXH_BuildEmptyEndBody()
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Builds empty OBEX headers. Used by both client and 
 *            server functions.
 *
 * Return:    TRUE  if headers could be added.
 *            FALSE if headers would exceed limits on buffer or transmit space.
 */
BOOL OBEXH_BuildEmptyEndBody(ObexAppHandle *AppHndl)
{
    OS_LockObex();

#if XA_ERROR_CHECK == XA_ENABLED
    if (!AppHndl || !ObIsHeaderSpaceAvail(AppHndl, 1)) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */

    ASSERT(AppHndl && AppHndl->buffer != 0);
    ASSERT(ObIsHeaderSpaceAvail(AppHndl, 1));
    
    AppHndl->buffer[AppHndl->txLength++] = OBEXH_END_BODY;
    AppHndl->buffer[AppHndl->txLength++] = 0x00;
    AppHndl->buffer[AppHndl->txLength++] = 0x03;

    OS_UnlockObex();
    return TRUE;
}
Ejemplo n.º 5
0
/*---------------------------------------------------------------------------
 *            OBEXH_Build4Byte()
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Builds 4-byte style OBEX headers. Used by both client and
 *            server functions.
 *
 * Return:    TRUE  if headers could be added.
 *            FALSE if headers would exceed limits on buffer or transmit space.
 */
BOOL OBEXH_Build4Byte(ObexAppHandle *AppHndl, ObexHeaderType Type, U32 Value)
{
    OS_LockObex();

#if XA_ERROR_CHECK == XA_ENABLED
    if (!AppHndl || !ObIsHeaderSpaceAvail(AppHndl, 5) || ((Type & 0xC0) != 0xC0)) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */

    ASSERT(AppHndl && AppHndl->buffer != 0);
    ASSERT(ObIsHeaderSpaceAvail(AppHndl, 5) && (Type & 0xC0) == 0xC0);
    
    AppHndl->buffer[AppHndl->txLength++] = Type;
    StoreBE32( AppHndl->buffer+AppHndl->txLength, Value);
    AppHndl->txLength += 4;

    OS_UnlockObex();
    return TRUE;
}
Ejemplo n.º 6
0
/*---------------------------------------------------------------------------
 *            OBEXH_GetAvailableTxHeaderLen()
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Returns the amount of header space available for adding more
 *            headers. This value is constrained by the OBEX Packet size,
 *            the application provided header buffer size and any headers
 *            which are already present in the buffer.
 *
 * Return:    Available header buffer length in bytes.
 */
U16 OBEXH_GetAvailableTxHeaderLen(ObexAppHandle *AppHndl)
{
#if OBEX_SERVER_CONS_SIZE > 0 || OBEX_SESSION_SUPPORT == XA_ENABLED
    void        *ObexApp = AppHndl;
#endif /* OBEX_SERVER_CONS_SIZE > 0 || OBEX_SESSION_SUPPORT == XA_ENABLED */
    U16            avail;

    ASSERT(AppHndl);

    OS_LockObex();
    /* Just assume Connect to get a size that will always work. */
    avail = ObParserMaxHbSize(&AppHndl->parser, OB_OPCODE_CONNECT);

#if (OBEX_SERVER_CONS_SIZE > 0) || (OBEX_SESSION_SUPPORT == XA_ENABLED)
    if (IsServerParser(&AppHndl->parser)) {
#if OBEX_ROLE_SERVER == XA_ENABLED
        avail -= OSC(protoTxLen);
#endif /* OBEX_ROLE_SERVER == XA_ENABLED */
    }
#if OBEX_SESSION_SUPPORT == XA_ENABLED
    else {
        ASSERT(IsClientParser(&AppHndl->parser));
#if OBEX_ROLE_CLIENT == XA_ENABLED
        avail -= OCC(protoTxLen);
#endif /* OBEX_ROLE_CLIENT == XA_ENABLED */
    }
#endif /* OBEX_SESSION_SUPPORT == XA_ENABLED */
#endif /* (OBEX_SERVER_CONS_SIZE > 0) || (OBEX_SESSION_SUPPORT == XA_ENABLED) */

    avail = min(avail, AppHndl->length);
    avail -= AppHndl->txLength;

    OS_UnlockObex();

    return avail;
}
Ejemplo n.º 7
0
/*---------------------------------------------------------------------------
 *            OBEXH_ParseTlv
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Sniffs out a TLV from the current header
 *
 * Return:    TRUE  if parsing was successful.
 *            FALSE if an error occurred or no more TLVs are present.
 */
BOOL OBEXH_ParseTlv(ObexAppHandle *AppHndl, ObexTlv *tlv)
{
    U8          *buffer;
    U16          len;
    U8           toUse;
    BOOL success = FALSE;

    CheckUnlockedParm(FALSE, AppHndl && tlv);

    OS_LockObex();

    /* On the first OBxx_HEADER_RX indication there is no data available.
     * Use this event to initialize the parser.
     */
    if (AppHndl->parser.dataLen == 0) {
        /* ASSERT that we are in the correct internal state to parse
         * this header, and that it is a byte sequence header
         */
        ASSERT((AppHndl->parser).rxState == OBSC_RX_PUT_HEAD2);
        ASSERT(((AppHndl->parser).header & 0xC0) == 0x40);

        /* Initialize key fields */
        AppHndl->tlv.state = 0; 
        buffer = 0;
        len = 0;
        goto Done;
    }

    /* Use these locals as aliases for the AppHndl fields */
    buffer = AppHndl->tlv.headerBuff;
    len = AppHndl->tlv.headerLen;

    if (buffer == 0) {
        buffer = AppHndl->parser.rxBuff;
        len = AppHndl->parser.dataLen;
    }

    while (len)
    {
        switch (AppHndl->tlv.state) {
        case 0: /* Buff points to option type */
            AppHndl->tlv.tag = *buffer++;
            AppHndl->tlv.state = 1;
            len--;
            break;

        case 1: /* Buff points to option length */
            AppHndl->tlv.length = *buffer++;
            AppHndl->tlv.state = 2;
            AppHndl->tlv.valuePos = 0;
            len--;

            /* No break; fall through to handle option data */
        case 2:
            /* Update length of option data we currently need. */
            toUse = min(AppHndl->tlv.length - AppHndl->tlv.valuePos, len);

            /* Fill in tlv values in case they are necessary */
            tlv->tag = AppHndl->tlv.tag;
            tlv->length = AppHndl->tlv.length;

            /* Is reassembly both necessary and possible for this TLV? */
#if OBEX_TLV_BUFF_SIZE > 0
            if ((toUse < AppHndl->tlv.length) &&
                (AppHndl->tlv.length < OBEX_TLV_BUFF_SIZE)) {

                /* Append recevied data into our staging buffer */
                OS_MemCopy(AppHndl->tlv.value + AppHndl->tlv.valuePos,
                    buffer, toUse);
                AppHndl->tlv.valuePos += toUse;
                tlv->value = AppHndl->tlv.value;
                tlv->valueLen = AppHndl->tlv.length;
                len -= toUse;
                buffer += toUse;
            
                /* Indicate success ONLY if we have completed staging */
                tlv->remainLen = (tlv->length - AppHndl->tlv.valuePos);
                success = (tlv->remainLen == 0);
            } else {
#endif /* OBEX_TLV_BUFF_SIZE > 0 */
            
                /* If reassembly is impossible or unnecessary, simply copy
                 * tag information */
                tlv->value = buffer;
                tlv->valueLen = toUse;
                AppHndl->tlv.valuePos += toUse;
                len -= toUse;
                buffer += toUse;

                /* Indicate "last" if we are indicating the last chunk of bytes
                 * as counted by valuePos
                 */
                tlv->remainLen = (tlv->length - AppHndl->tlv.valuePos);
                /* Indicate success because staging isn't going to happen */
                success = TRUE;

#if OBEX_TLV_BUFF_SIZE > 0
            }
#endif  /* OBEX_TLV_BUFF_SIZE > 0 */

            if (success)
            {
                /* If we have reached the end of the tlv then reset state for
                 * next time */
                if (tlv->remainLen == 0) {
                    AppHndl->tlv.state = 0;
                }
                goto Done;
            }
            break;
        }
    }

    /* If control gets here we have exhausted the buffer */
    buffer = 0;

Done:
    /* Reset buffer/length from locals and return success */
    AppHndl->tlv.headerBuff = buffer;
    AppHndl->tlv.headerLen = len;

    OS_UnlockObex();
    return success;
}
Ejemplo n.º 8
0
/*---------------------------------------------------------------------------
 *            OBEXH_BuildAuthResponse
 *---------------------------------------------------------------------------
 *
 * Synopsis:  This function is used by applications to build an Authentication
 *            response to a received Challenge. The header is constructed from
 *            the fields in the ObexAuthResponse structure.
 *
 * Return:    TRUE if header was successfully built.
 *            FALSE if headers would exceed limits on buffer or transmit space.
 */
BOOL OBEXH_BuildAuthResponse(ObexAppHandle *AppHndl, ObexAuthResponse *Response, 
                             U8 *Nonce)
{
    U8          len;
    xMD5Context context;
//#if XA_DEBUG == XA_ENABLED
    U8 *orig;
//#endif /* XA_DEBUG == XA_ENABLED */

    OS_LockObex();
#if XA_ERROR_CHECK == XA_ENABLED
    if (!AppHndl || !Response || !Nonce) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */
    ASSERT(AppHndl && Response && Nonce);

    len = CALC_RESPONSE_LEN(Response);
//#if XA_DEBUG == XA_ENABLED
    orig = AppHndl->buffer + AppHndl->txLength;
//#endif /* XA_DEBUG == XA_ENABLED */

#if XA_ERROR_CHECK == XA_ENABLED
    if (!ObIsHeaderSpaceAvail(AppHndl, (U16)(len+3))) {
        OS_UnlockObex();
        return FALSE;
    }
#endif
    ASSERT(ObIsHeaderSpaceAvail(AppHndl, (U16)(len+3)));

    /* Build the OBEX Response Header Identifier */
    AppHndl->buffer[AppHndl->txLength++] = OBEXH_AUTH_RESP;
    AppHndl->buffer[AppHndl->txLength++] = (U8)((len+3) >> 8);
    AppHndl->buffer[AppHndl->txLength++] = (U8) (len+3);

    /* Build digest from nonce and password */
    AppHndl->buffer[AppHndl->txLength++] = 0;                /* Request Digest Code */
    AppHndl->buffer[AppHndl->txLength++] = AUTH_NONCE_LEN;   /* Digest Length (16 bytes) */
    xMD5Init(&context);
    xMD5Update(&context, Nonce, AUTH_NONCE_LEN);
    xMD5Update(&context, (U8 *)":", 1);
    xMD5Update(&context, Response->password, Response->passwordLen);
    xMD5Final(AppHndl->buffer+AppHndl->txLength, &context);
    AppHndl->txLength += AUTH_NONCE_LEN;

    /* Add UserId */
    if (Response->userIdLen) {
        AppHndl->buffer[AppHndl->txLength++] = 1;    /* UserId */
        AppHndl->buffer[AppHndl->txLength++] = Response->userIdLen; /* Realm Len */
        OS_MemCopy(AppHndl->buffer+AppHndl->txLength, Response->userId, Response->userIdLen);
        AppHndl->txLength += Response->userIdLen;
    }

    /* Add Nonce */
    AppHndl->buffer[AppHndl->txLength++] = 2;                /* Nonce */
    AppHndl->buffer[AppHndl->txLength++] = AUTH_NONCE_LEN;   /* (16 bytes) */
    OS_MemCopy(AppHndl->buffer+AppHndl->txLength, Nonce, AUTH_NONCE_LEN);
    AppHndl->txLength += AUTH_NONCE_LEN;

//#if XA_DEBUG == XA_ENABLED
    ASSERT((orig + len + 3) == (AppHndl->buffer + AppHndl->txLength));
//#endif
    OS_UnlockObex();
    return TRUE;
}
Ejemplo n.º 9
0
/*---------------------------------------------------------------------------
 *            OBEXH_BuildAuthChallenge
 *---------------------------------------------------------------------------
 *
 * Synopsis:  OBEX applications use this function to build an Authentication
 *            Challenge header. The header is constructed from the field 
 *            values in the ObexAuthChallenge structure.
 *
 * Return:    TRUE if header was successfully built.
 *            FALSE if headers would exceed limits on buffer or transmit space.
 */
BOOL OBEXH_BuildAuthChallenge(ObexAppHandle *AppHndl, ObexAuthChallenge *Challenge, 
                              U8 *NonceOut)
{
    U8  len;
//#if XA_DEBUG == XA_ENABLED
    U8 *orig;
//#endif /* XA_DEBUG == XA_ENABLED */

    OS_LockObex();
#if XA_ERROR_CHECK == XA_ENABLED
    if (!AppHndl || !Challenge ) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */
    ASSERT(AppHndl && Challenge);

    len = CALC_CHALLENGE_LEN(Challenge);
//#if XA_DEBUG == XA_ENABLED
    orig = AppHndl->buffer + AppHndl->txLength;
//#endif /* XA_DEBUG == XA_ENABLED */

#if XA_ERROR_CHECK == XA_ENABLED
    if (!ObIsHeaderSpaceAvail(AppHndl, (U16)(len+3))) {
        OS_UnlockObex();
        return FALSE;
    }
#endif /* XA_ERROR_CHECK == XA_ENABLED */
    ASSERT(ObIsHeaderSpaceAvail(AppHndl, (U16)(len+3)));

    /* Build the OBEX Challenge Header Identifier */
    AppHndl->buffer[AppHndl->txLength++] = OBEXH_AUTH_CHAL;
    AppHndl->buffer[AppHndl->txLength++] = (U8)((len+3) >> 8);
    AppHndl->buffer[AppHndl->txLength++] = (U8) (len+3);

    /* Build nonce from challenge string */
    AppHndl->buffer[AppHndl->txLength++] = 0;                /* Nonce Code */
    AppHndl->buffer[AppHndl->txLength++] = AUTH_NONCE_LEN;   /* (16 bytes) */
    MD5(AppHndl->buffer+AppHndl->txLength, Challenge->challenge, Challenge->challengeLen);
    if (NonceOut)
        OS_MemCopy(NonceOut, AppHndl->buffer+AppHndl->txLength, AUTH_NONCE_LEN);
    AppHndl->txLength += AUTH_NONCE_LEN;

    /* Add Options */
    if (Challenge->options) {
        AppHndl->buffer[AppHndl->txLength++] = 1;    /* Options Code */
        AppHndl->buffer[AppHndl->txLength++] = 1;    /* Options Len */
        AppHndl->buffer[AppHndl->txLength++] = Challenge->options;   /* Options */
    }

    /* Add Realm */
    if (Challenge->realmLen) {
        AppHndl->buffer[AppHndl->txLength++] = 2;    /* Realm Code */
        AppHndl->buffer[AppHndl->txLength++] = Challenge->realmLen; /* Realm Len */
        OS_MemCopy(AppHndl->buffer+AppHndl->txLength, Challenge->realm, Challenge->realmLen);
        AppHndl->txLength += Challenge->realmLen;
    }

//#if XA_DEBUG == XA_ENABLED
    ASSERT((orig + len + 3) == (AppHndl->buffer + AppHndl->txLength));
//#endif
    OS_UnlockObex();
    return TRUE;
}
Ejemplo n.º 10
0
/*---------------------------------------------------------------------------
 *            TcpCallback
 *---------------------------------------------------------------------------
 *
 * Synopsis:  Process events from the client and server transport.
 *
 */
static void TcpCallback(ObTcpCommonTransport *txp, U8 EventType, void *Parm1, U16 Parm2)
{
#if (OBEX_ROLE_SERVER == XA_ENABLED) || (OBEX_ALLOW_SERVER_TP_CONNECT == XA_ENABLED)
    I32         rcode;
#endif /* (OBEX_ROLE_SERVER == XA_ENABLED) || (OBEX_ALLOW_SERVER_TP_CONNECT == XA_ENABLED) */

    OS_LockObex();
    switch (EventType) {

#if (OBEX_ROLE_SERVER == XA_ENABLED) || (OBEX_ALLOW_SERVER_TP_CONNECT == XA_ENABLED)
    case TCP_EVENT_CONNECT_IND: /* TCP Server Event */
        /* Accept the incoming connection to our server if it's idle. */
        if (OBPROT_LinkTransport(txp->app, &txp->transport)) {
            ASSERT(txp->state == OCS_IDLE);
            txp->state = OCS_CONNECTING;

            /* Save the connection handle */
            txp->conn = accept(((ObTcpServerTransport *)txp)->serverReg, 0, 0);
            ASSERT(txp->conn != INVALID_SOCKET);
            
            rcode = WSAAsyncSelect(txp->conn, asyncEventHandle, WM_SELECT, FD_WRITE|FD_CLOSE);
            ASSERT(rcode != SOCKET_ERROR);
        } else {
            /* Reject the connection, the parser is busy. */
            txp->conn = accept(((ObTcpServerTransport *)txp)->serverReg, 0, 0);
            ASSERT(txp->conn != INVALID_SOCKET);

            closesocket(txp->conn);
            txp->conn = INVALID_SOCKET;
        }            
        break;
#endif /* (OBEX_ROLE_SERVER == XA_ENABLED) || (OBEX_ALLOW_SERVER_TP_CONNECT == XA_ENABLED) */

    case TCP_EVENT_CONNECTED:
        /* Save the new connection handle (Client only) */
        txp->conn = Parm2;
        txp->state = OCS_CONNECTED;
        
        /* Tell the application that the server has accepted a connection */
        OBPROT_Connected(txp->app);
        break;

    case TCP_EVENT_DATA_IND:
        /* Pass data directly to the client parser */
        OBPROT_ParseRx(txp->app, Parm1, Parm2);
        break;

    case TCP_EVENT_DISCON:
        txp->conn = INVALID_SOCKET;

        /* This can happen if TCPSTACK_ClientDisconnect() is called while
         * a connect is in progress. When disconnect is handled synchronously.
         */
        if (txp->state == OCS_IDLE)
            break;

        txp->state = OCS_IDLE;
        txp->conn = INVALID_SOCKET;

        /* This call will deliver a disconnect indication to the app. */
        OBPROT_Disconnected(txp->app, ODR_UNKNOWN);
        break;
    }
    OS_UnlockObex();
}