September 2, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Object Exchange (OBEX) Protocol Primer

  • December 27, 2005
  • By Alex Gusev
  • Send Email »
  • More Articles »

Sending Data

After the device discovery process has finished, it is really easy to send some data (a file in tour case) to the selected device. The application obtains an IObexDevice pointer through the IObex::BindToDevice function and then calls SendFile, below:

int CObex::SendFile(IObexDevice *pDevice, LPTSTR pszFileName,
                    DWORD dwFlags)
{
   LPTSTR pszName;
   DWORD dwBytesWritten;
   int nCnt, nFileSize, nTotal;
   HRESULT hr;
   BYTE pBuff[BUFFSIZE];
   CString sInfo;
   CFile File;
   sInfo.Format(_T("Sending file %s"), pszFileName);
   ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
   memset(pBuff,0,sizeof(pBuff));
   pszName = wcsrchr (pszFileName, '\\');
   if (pszName == 0)
      pszName = pszFileName;
   else
      pszName++;
   if ( !File.Open(pszFileName,CFile::modeRead) )
      return 0;
   nFileSize = File.GetLength();
   IHeaderCollection *pHC = 0;
   hr = CoCreateInstance(__uuidof(HeaderCollection), NULL,
      CLSCTX_INPROC_SERVER, __uuidof(IHeaderCollection),
      (void **)&pHC);
   if (FAILED(hr))
   {
       return -2;
   }
   if (dwFlags & DEV_SERVICE_FTP)
      pHC->AddTarget (sizeof (CLSID_FileExchange_NetOrder),
      (UCHAR *)&CLSID_FileExchange_NetOrder);
   hr = pDevice->Connect (NULL, 0, pHC);
   if (FAILED(hr))
   {
      sInfo.Format(_T("Failed to connect! hr = 0x%X, err =  0x%X\n"),
         hr, GetLastError());
      ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
      pHC->Release();
      return -3;
   }
   sInfo = _T("Connected");
   ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
   IHeaderCollection *pFileHC = 0;
   hr = CoCreateInstance(__uuidof(HeaderCollection), NULL,
      CLSCTX_INPROC_SERVER, __uuidof(IHeaderCollection),
      (void **)&pFileHC);
   if (FAILED(hr))
   {
      pHC->Release();
      pDevice->Disconnect (pHC);
      return -2;
   }
   hr = pFileHC->AddName(pszName);
   if (FAILED(hr))
   {
      pHC->Release();
      pFileHC->Release();
      return -3;
   }
   IStream *stOut = 0;
   hr = pDevice->Put(pFileHC, &stOut);
   if (FAILED(hr))
   {
      pDevice->Disconnect (pHC);
      pHC->Release();
      pFileHC->Release();
      return -4;
   }
   nTotal = nFileSize;
   while (nFileSize)
   {
      nCnt = __min (BUFFSIZE, nFileSize);
      dwBytesWritten = File.Read(pBuff, nCnt);
      if (!dwBytesWritten)
      {
         sInfo.Format(_T("ReadFile error %d"), GetLastError());
         ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
            break;
      }
      nCnt = (int)dwBytesWritten;
      sInfo.Format(_T("sending %d bytes"), nCnt);
      ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
      hr = stOut->Write (pBuff, nCnt, &dwBytesWritten);
      if(FAILED(hr))
      {
         sInfo.Format(_T("send error: hr = 0x%X, err = 0x%X"),
                      hr, GetLastError());
         ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
            break;
      }
      nFileSize -= (int)dwBytesWritten;
      sInfo.Format(_T("%d%% sent"), (nTotal-nFileSize)*100/nTotal);
      ::SendMessage(m_hWnd, WM_OBEX_INFO,0,(LPARAM)&sInfo);
   }
   stOut->Commit (STGC_DEFAULT);
   stOut->Release();
   pDevice->Disconnect (pHC);
   if(pHC)
      pHC->Release();
   if(pFileHC)
      pFileHC->Release();
   return 0;
}

Besides establishing an OBEX connection, an important point in the sample above is the IHeaderCollection stuff. Upon a successful connection, you have to fill in IHeaderCollection with actual data. For this purpose, you use an IStream object. IObexDevice::Put returns IStream objects to you, which are used to send your data to the remote device.

At the receiver's side—for example, for Palm OS devices—you might want to register your application with Exchange Manager to handle arrivals of specific data types. For some details, you can take a look at the Palm SDK documentation or at one of my previous articles.

Conclusion

OBEX makes your life easier when you face the need of 'object' transmission between different devices with different operating systems. Palm OS PDAs or Symbian devices will happily receive your files sent from Windows Mobile device because they all are OBEX compliant. Thus, with a little effort, you get a very nice-to-have feature to enjoy and to play with.

Download

Download the accompanying code's zip file here.

About the Author

Alex Gusev started to play with mainframes at the end of the 1980s, using Pascal and REXX, but soon switched to C/C++ and Java on different platforms. When mobile PDAs seriously rose their heads in the IT market, Alex did it too. Now, he works at an international retail software company as a team leader of the Mobile R department, making programmers' lives in the mobile jungles a little bit simpler.





Page 3 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel