Programmatially Send files using OBEX Object Push over the Microsoft Bluetooth Stack

A while back during my senior project of my BSc computer science studies, I wrote an implementation of parts_of_HCI, L2CAP, SDP, RFCOMM and OBEX on top of freebt.net's bluetooth implementation for Windows.

That same OBEX code was modified to be used with the MS BT stack to send files over bluetooth - please see the code of WMouseXP open-source version, the fuction "sendFile" at https://github.com/ykasidit/WMouseXP/blob/master/src/WMouseXPDlg.cpp and the main OBEX layer packet code was https://github.com/ykasidit/WMouseXP/blob/master/src/OBEX.cpp - sorry for the low quality/cleanliness of code here - it was written when I was still just starting C and C++ programming back then - but it worked when tested with many Bluetooth devices/phones.

The main part is making the OBEX object:

bool CWMouseXPDlg::SendFile(char* devaddr, int port, BYTE* dataptr, DWORD datalen)
{
    //close socket to make sure it is closed, new session
    closesocket(iSocket);    
    WSACleanup();

    if(!InitSocket())
    {
        throw "Initialize MS Bluetooth stack/driver failed";        
    }

    SOCKADDR_BTH sa = { 0 };
    int sa_len = sizeof(sa);


    if( SOCKET_ERROR == WSAStringToAddress( devaddr, AF_BTH,
    NULL, (LPSOCKADDR) &sa, &sa_len ) ) 
    {
        throw "Convert BT address WSAStringToAddress failed";   
    }

    sa.port = port;

    if( sa.port == 0 ) {
        iStep1Label.SetWindowText("Invalid device OBEX port specified");
    return false;
    }   




    //open socket



    //Made new send and recv functions implements a timer, see SendViaSocketL and RevcViaSocketL

    //try catch handles when send and recv fails






    //make safe cleanup when exceptions occur



    OBEXPutCommand* opc = NULL;

    OBEXPacket* obexPktToSend = NULL; //file part packet


    bool success = false;

    try{
              
                iStep1Label.SetWindowText("Waiting for phone to accept file...");

                StartBTInteractionTimer(); //so we don't wait too long for a user to respond

                if(SOCKET_ERROR != connect( iSocket, (LPSOCKADDR) &sa, sa_len ))
                  {
                        //Send OBEX Connect             

                        StopBTInteractionTimer();   

                        m_InstallPic.Draw();

                        OBEXConnectPacket obexConnectPkt(Opcode_Connect,0x4000);                

                        BYTE recvBuff[512];                                             

                        SendViaSocketL((const char*) (obexConnectPkt.wholePacket),obexConnectPkt.packetLength);


                        bool startedPut = false;
                        USHORT theirMaxOBEXPacketSize = 0;                  


                        //See response, then Send all OBEX file packets                                         

                        int nreceived = RecvViaSocketL((char*)recvBuff,512);                        



                        if(recvBuff[0] == RspCode_Success)
                        {
                                
                            iStep1Label.SetWindowText("Connect OBEX Success");      


                        while(1)
                        {

                            if(startedPut)
                                nreceived = RecvViaSocketL((char*)recvBuff,512);


                            OBEXPacket obexRcvdPkt(recvBuff,nreceived);


                            if(!startedPut)
                            {

                                    if(obexRcvdPkt.wholePacket->code == RspCode_Success)
                                    {
                                        iStep1Label.SetWindowText("OBEX connection successful");

                                        BEUS tmo(((BYTE*)(obexRcvdPkt.wholePacket->data))+2);                   
                                        theirMaxOBEXPacketSize = tmo.getValUSHORT(); 

                                        char buf[50] = {0};
                                        sprintf(buf,"Their max OBEX packet size: %d",theirMaxOBEXPacketSize);
                                        iStep1Label.SetWindowText(buf);



                                        //file->Open("card.vcf",CFile::modeRead|CFile::typeBinary);
                                        //file->Open("img.jpg",CFile::modeRead|CFile::typeBinary);
                                        //if(opc)
                                        //  delete opc;

                                         opc = new OBEXPutCommand("WMouseXP.jar",theirMaxOBEXPacketSize,dataptr,datalen);                           

                                        //sprintf(buf,"N OBEX puts to send: %d",opc->nPacketsToSend);
                                        iStep1Label.SetWindowText("Sending File...");
                                        //devicesLB->DrawAnimatedRects()


                                                    obexPktToSend = opc->CgetNextPacket();

                                                    SendViaSocketL((const char*) (obexPktToSend->wholePacket),obexPktToSend->packetLength);

                                                    delete obexPktToSend;
                                                    obexPktToSend = NULL;

                                                    startedPut = true;

                                    }


                            }                       
                            else
                            {
                                    if(obexRcvdPkt.wholePacket->code == RspCode_Success)
                                        {
                                            //send obex disc
                                            iStep1Label.SetWindowText("File sent via Bluetooth");
                                            success = true;

                                            OBEXPacket dsc(Opcode_Disconnect,NULL,0);

                                            //AddLog("Sending OBEX Disconnect Request");
                                            SendViaSocketL((const char*) (dsc.wholePacket),dsc.packetLength);                   
                                            //AddLog("OBEX Disconnect Sent");                   
                                            iStep1Label.SetWindowText("File sent via Bluetooth");
                                            break;

                                        }
                                        else
                                    if(obexRcvdPkt.wholePacket->code == RspCode_Continue)
                                        {
                                            obexPktToSend = opc->CgetNextPacket();  

                                            SendViaSocketL((const char*) (obexPktToSend->wholePacket), obexPktToSend->packetLength);

                                            delete obexPktToSend;
                                            obexPktToSend = NULL;//avoid double deletion

                                        }
                                    else
                                        {
                                            throw "Unknown OBEX Response";
                                            //break; throw already broke...
                                        }


                            }//end else of if(!started)


                            }//end while    




                        }//end if(recvBuff[0] == RspCode_Success)           
                        else
                        {
                            throw("OBEX handshake failed.");                            

                        }   
                        

                }// end if(connect!=SOCKET_ERROR)                                          
                else
                {           StopBTInteractionTimer();
                            throw "Connection Declined or Timed-Out";
                }





    }
    catch(char* exception)
    {
        iStep1Label.SetWindowText(exception);
    }


    delete obexPktToSend;
    delete opc;


    closesocket(iSocket);      
    WSACleanup();

    return success;

}


blog comments powered by Disqus

This ClearEvo.com blog is powered by Debian GNU/Linux, running lighttpd, generated using jekyll on Ubuntu.

Subscribe for new updates