OBEX is probably the most commonly used technique to transfer files over devices that support Bluetooth. On the contrary , with being the most common , it is not very well documented how this thing actually works.
My objective is to design an OBEX client server on my laptop which should send files to my android device with popup like this.
I have chosen C++ as the language to program the server from scratch on Windows. The UUID for this action which I am using is this.
00001105-0000-1000-8000-00805F9B34FB
and I have initialised the OBEX client like this.
GUID OBEX_GUID;
UuidFromString((unsigned char*)"00001105-0000-1000-8000-00805F9B34FB",(UUID*)&OBEX_GUID);
SOCKET soc,acpt;
SOCKADDR_BTH BluetoothAddress;
BluetoothAddress.addressFamily = AF_BTH;
BluetoothAddress.port = BT_PORT_ANY;
str2ba((char*)"BC:41:01:11:BC:2F",&BluetoothAddress.btAddr);
BluetoothAddress.serviceClassId = OBEX_GUID;
//OBEXObjectPushServiceClass_UUID;
soc = socket(AF_BTH , SOCK_STREAM , BTHPROTO_RFCOMM);
if(soc>0){
printf("Socket initialisation successn");
}
stat = connect(soc,(sockaddr*)&BluetoothAddress,sizeof(BluetoothAddress));
printf("%snn",(stat==0) ? "CONNECTED to the remote device!" : "Remote device is unavailable." );
This connect process is successful yet , and without any error it starts communication with my Android device addressed BC:41:01:11:BC:2F. The status of the socket connect() function returns zero (success as well).
Now, as per OBEX 1.4 pdf , I need to start the session after the connection is estabilished successfully. So in the Page 38 of the PDF , the starting session of connection is well described and I tried to imitate the syntax of the connecting package like this
char connect_req[] = {
0x80 , 0x00 , 0x11 , 0x10 , 0x00 , 0x20 , 0x00 , 0xc0 , 0x00 , 0x00 , 0x00 , 0x01 , 0xc3 , 0x00 , 0x00 , 0xf4 , 0x83
// CNCT | 2B Length | Vers | Flag | Max Pack 8K | Count | 4 byte file count | Len Header | Total length of hex
};
Upon sending this connect package to my Android, it returns successfully with the value of 0xA0. Which means that a session has finally been started.
After the session is started , I need to send a dummy file which requires to be requested as a PUT method which is defined in the page 40 of the PDF. tried to do the same imitation and ended up with a package like this.
unsigned char putfile_req[] = {
0x82 , 0x00 , 0x21 , 0x01 , 0x00 , 0x17 , 0x00,0x41 , 0x00,0x42 , 0x00,0x43 , 0x00,0x44 , 0x00,0x45 , 0x00,0x2c , 0x00,0x74 , 0x00,0x78 , 0x00,0x74 , 0xC3 , 0x00 , 0x00 , 0x00 , 0x01 , 0x49 , 0x00 , 0x01 , 0x74
// PUT | 2b Len | HI Name | NameLen | A B C D E . T X T | Len | 1 Byte | end | 1 Byte |
};
Upon sending this PUT request with the filename of, ABCDE.TXT (1 Byte), the response from my android somehow returns unsuccessful with the value of Zero (0)
The problem is, till the connect session state every request and response worked perfectly fine but whenever I am sending a PUT request with a file name, it is received by the Android but for some unknown reasons the Android can not proces it and returns zero.
I have heard some people saying that Android does not support OBEX but had that been the actual factor , the success (A0) status would not have returned while sending the connect package in the beginning.
Here is the full code if matters…
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <inttypes.h>
#include <winsock2.h>
#include <windows.h>
#include <ws2bth.h>
#include <bthsdpdef.h>
#include <bluetoothapis.h>
#include <ws2bth.h>
GUID OBEX_GUID;
int str2ba(const char *straddr, BTH_ADDR *btaddr)
{
int i;
unsigned int aaddr[6];
BTH_ADDR tmpaddr = 0;
if (sscanf(straddr, "%02x:%02x:%02x:%02x:%02x:%02x",
&aaddr[0], &aaddr[1], &aaddr[2],
&aaddr[3], &aaddr[4], &aaddr[5]) != 6)
return 1;
*btaddr = 0;
for (i = 0; i < 6; i++) {
tmpaddr = (BTH_ADDR) (aaddr[i] & 0xff);
*btaddr = ((*btaddr) << 8) + tmpaddr;
}
return 0;
}
int main(){
unsigned char response[10000]={0};
UuidFromString((unsigned char*)"00001105-0000-1000-8000-00805F9B34FB",(UUID*)&OBEX_GUID);
WSADATA ws;
WSAStartup(MAKEWORD(2,2),&ws);
int stat;
SOCKET soc,acpt;
SOCKADDR_BTH BluetoothAddress;
BluetoothAddress.addressFamily = AF_BTH;
BluetoothAddress.port = BT_PORT_ANY;
str2ba((char*)"BC:41:01:11:BC:2F",&BluetoothAddress.btAddr);
BluetoothAddress.serviceClassId = OBEX_GUID;
OBEXObjectPushServiceClass_UUID;
soc = socket(AF_BTH , SOCK_STREAM , BTHPROTO_RFCOMM);
if(soc>0){
printf("Socket initialisation successn");
}
stat = connect(soc,(sockaddr*)&BluetoothAddress,sizeof(BluetoothAddress));
printf("%snn",(stat==0) ? "CONNECTED to the remote device!" : "Remote device is unavailable." );
char connect_req[] = {
0x80 , 0x00 , 0x11 , 0x10 , 0x00 , 0x20 , 0x00 , 0xc0 , 0x00 , 0x00 , 0x00 , 0x01 , 0xc3 , 0x00 , 0x00 , 0xf4 , 0x83
// CNCT | 2B Length | Vers | Flag | Max Pack 8K | Count | 4 byte file count | Len Header | Total length of hex
};
unsigned char putfile_req[] = {
0x82 , 0x00 , 0x21 , 0x01 , 0x00 , 0x17 , 0x00,0x41 , 0x00,0x42 , 0x00,0x43 , 0x00,0x44 , 0x00,0x45 , 0x00,0x2c , 0x00,0x74 , 0x00,0x78 , 0x00,0x74 , 0xC3 , 0x00 , 0x00 , 0x00 , 0x01 , 0x49 , 0x00 , 0x01 , 0x74
// PUT | 2b Len | HI Name | NameLen | A B C D E . T X T | Len | 1 Byte | end | 1 Byte |
};
printf("PUT packet Length: %dnn",sizeof(putfile_req)/sizeof(unsigned char));
send(soc,(const char*)connect_req,sizeof(connect_req)/sizeof(connect_req[0]),0);
int Recvd = recv(soc,(char*)response,sizeof(response),0);
printf("OBEX CONNECT status: %Xn",response[0]);
if(response[0]==0xA0){
printf(" SUCCESSn");
}
memset(response,0,sizeof(response));
send(soc,(char*)putfile_req,sizeof(putfile_req)/sizeof(putfile_req[0]),0);
Recvd = recv(soc,(char*)response,sizeof(response),0);
printf("PUT Request status: %Xn",response[0]);
if(response[0]==0x00){
printf("Something went wrong!n");
}
}
And the output looks like,
Even though the connect session is successful with the return value of 0xA0, the socket closes with an error code of zero as the response of PUT request. Hence the popup dialogue at my Android side is not supposed to appear.
Now ,all I want is to send a file from the Winsock2 OBEX client written from scratch , to my Android where there should appear a popup in my Android device asking for the user to accept or decline the incoming file or request. upon acceptance , the file transfer should begin.
So this somehow seems to be my fault , which I can not diagnose. That is why I am here to ask for some kind helps from those who are well experienced in this field.
Thanks and Regards.