< Winsock 2 & Bluetooth APIs | Winsock2 Supported Protocols Main | Bluetooth Win32 Example >


 

 

Winsock 2: Other Supported Protocols 4 Part 17

 

 

What do we have in this chapter 4 part 17?

  1. Bluetooth and Socket Options

  2. SO_BTH_AUTHENTICATE

  3. SO_BTH_ENCRYPT

  4. SO_BTH_MTU

  5. SO_BTH_MTU_MAX

  6. SO_BTH_MTU_MIN

  7. Bluetooth Receiver Program Example

  8. Bluetooth Sender Program Example

 

Bluetooth and Socket Options

 

Socket options are set and queried using the setsockopt() and getsockopt() functions, respectively. All of the following options can be used with the setsockopt() function, but only the SO_BTH_MTU option is available for use with the getsockopt() function. The following settings are required for working with Bluetooth socket options:

 

  1. The s parameter must be a Bluetooth socket.
  2. The level parameter must be SOL_RFCOMM.

 

SO_BTH_AUTHENTICATE

 

For disconnected sockets, the SO_BTH_AUTHENTICATE specifies that authentication is required for a connect() or accept() operation to complete successfully. Setting this socket option actively initiates authentication during connection establishment, if the two Bluetooth devices were not previously authenticated. The user interface for passkey exchange, if necessary, is provided by the operating system outside the application context.

For outgoing connections that require authentication, the connect() operation fails with WSAEACCES if authentication is not successful. In response, the application may prompt the user to authenticate the two Bluetooth devices before connection.

For incoming connections, the connection is rejected if authentication cannot be established and returns a WSAEHOSTDOWN error. The BluetoothAuthenticateDevice function can be used to send an authentication request to a remote Bluetooth device.

For the SO_BTH_AUTHENTICATE socket option, optval is a pointer to ULONG bAuthenticate and must be TRUE; optlen is equivalent to "sizeof(ULONG)". For Windows XP with SP2, the SO_BTH_AUTHENTICATE starts authentication for connected sockets, and forces authentication upon connection for unconnected sockets. For incoming connections, the connection is rejected if authentication cannot be performed.

 

SO_BTH_ENCRYPT

 

On unconnected sockets, the SO_BTH_ENCRYPT socket option enforces encryption to establish a connection. Encryption is only available for authenticated connections. For incoming connections, a connection for which encryption cannot be established is automatically rejected and returns WSAEHOSTDOWN as the error. For outgoing connections, the connect function fails with WSAEACCES if encryption cannot be established. In response, the application may prompt the user to authenticate the two Bluetooth devices before connection. For the SO_BTH_ENCRYPT socket option, optval is a pointer to ULONG bEncrypt and must be TRUE; optlen is equivalent to sizeof(ULONG). For Windows XP with SP2, a socket that is connected and authenticated, SO_BTH_ENCRYPT starts encryption.

 

SO_BTH_MTU

 

The SO_BTH_MTU socket option is an advanced option used primarily for validation. The SO_BTH_MTU option obtains or sets default RFCOMM MTU (maximum transmission unit) for connection negotiation to a value different than the RFCOMM protocol-default value.

Because RFCOMM MTU is affected by the underlying L2CAP MTU, and protocol and application minimums and maximums, the default value for SO_BTH_MTU is only a starting point for negotiation with the remote peer, and the final negotiated MTU is likely to vary from the default. Setting the SO_BTH_MTU value may negatively affect throughput, and as such, any modification should be performed with knowledge of the underlying Bluetooth protocol.

The SO_BTH_MTU socket option can be performed on connected sockets, but has no effect if the negotiation has already completed. Setting it on the listening (server) socket has no effect.

The amount of data that an application can send or receive in a single socket call is not affected by the MTU; MTU only affects how the underlying Windows Sockets service provider segments packets for transport. Both the proposed MTU and the MTU ultimately negotiated must be between RFCOMM_MIN_MTU and RFCOMM_MAX_MTU, as defined in the Ws2bth.h header file.

For the SO_BTH_MTU socket option, optval is a pointer to ULONG mtu; optlen is equivalent to "sizeof(ULONG)".

 

SO_BTH_MTU_MAX

 

The SO_BTH_MTU_MAX socket option is an advanced option used primarily for validation. The SO_BTH_MTU_MAX socket option sets the maximum RFCOMM MTU (maximum transmission unit) for connection negotiation. Connections with an RFCOMM MTU equal to or greater than this value fail during the connect/accept process. While setting this socket option is allowed for a connected socket, it has no effect if the negotiation has completed. Setting this socket option on a listening socket propagates the value for all incoming connections. The MAX MTU value must be between RFCOMM_MIN_MTU and RFCOMM_MAX_MTU, as defined in the Ws2bth.h header file. For the SO_BTH_MTU_MAX socket option, optval is a pointer to ULONG max_mtu; optlen is equivalent to "sizeof(ULONG)".

 

SO_BTH_MTU_MIN

 

The SO_BTH_MTU_MIN socket option is an advanced option used primarily for validation. The SO_BTH_MTU_MIN socket option sets the minimum RFCOMM MTU (maximum transmission unit) for connection negotiation. Connections with an RFCOMM MTU smaller than this value fail during the connect/accept process. While setting this socket option is allowed for a connected socket, it has no effect if the negotiation has completed. Setting this socket option on a listening socket propagates the value for all incoming connections.

Only a listening socket can revise the MTU downward, therefore if the value proposed by the connecting socket is less than the value set for SO_BTH_MTU_MIN on the listening socket, the connection is refused. The minimum MTU must be between RFCOMM_MIN_MTU and RFCOMM_MAX_MTU, as defined in the Ws2bth.h header file. For the SO_BTH_MTU_MIN socket option, optval is a pointer to ULONG min_mtu; optlen is equivalent to "sizeof(ULONG)".

 

Bluetooth Receiver Program Example

 

The following sender and receiver program examples are using Microsoft Bluetooth stack. This means the program run will fail on the machine which using WIDCOMM stack.

 

Bluetooth Receiver Program Example: Creating a new empty Win32 console mode application and adding the project/solution name.

 

Add the following source code.

 

// Link to ws2_32.lib

#include <winsock2.h>

#include <ws2bth.h>

#include <BluetoothAPIs.h>

#include <stdio.h>

 

#define DEFAULT_BUFLEN 512

 

int main(int argc, char **argv)

{

            WSADATA wsd;

            SOCKET s, s2;

            SOCKADDR_BTH sab, sab2;

// NULL_GUID

            GUID nguiD = {00000000-0000-0000-0000-000000000000};

            int ilen, iResult;

 

            // This should be const void * type for non-char data

            char *sendbuf = "Test data from receiver...";

            int recvbuflen = DEFAULT_BUFLEN;

            // Change the type accordingly for non-char data

            char recvbuf[DEFAULT_BUFLEN] = "";

 

            if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)

            {

                        printf("Unable to load Winsock! Error code is %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSAStartup() is OK, Winsock lib loaded!\n");

 

            s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);

            if (s == INVALID_SOCKET)

            {

                        printf ("Socket creation failed, error %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf ("socket() looks fine!\n");

 

            memset (&sab, 0, sizeof(sab));

            sab.addressFamily  = AF_BTH;

            // We hardcoded it

            sab.port = 1;

 

            if (0 != bind(s, (SOCKADDR *) &sab, sizeof(sab)))

            {

                        printf ("bind() failed with error code %d\n", WSAGetLastError());

                        closesocket (s);

                        return;

            }

            else

                        printf ("bind() looks fine!\n");

 

            if(listen (s, 5) == 0)

                        printf("listen() is OK! Listening for connection...\n");

            else

                        printf("listen() failed with error code %d\n", WSAGetLastError());

 

            for ( ; ; )

            {

                        // Get information on the port assigned

                        ilen = sizeof(sab2);

                        s2 = accept (s, (SOCKADDR *)&sab2, &ilen);

                        if (s2 == INVALID_SOCKET)

                        {

                                    printf ("accept() failed with error code %d\n", WSAGetLastError ());

                                    break;

                        }

                        else

                                    printf ("accept(), is OK buddy!\n");

 

                        // Print the info

                        printf ("Connection came from %04x%08x to channel %d\n", GET_NAP(sab2.btAddr), GET_SAP(sab2.btAddr), sab2.port);

            }

 

    // Receive until the peer closes the connection

    do {

        iResult = recv(s2, recvbuf, recvbuflen, 0);

        if (iResult > 0)

            printf(" %d Bytes received from sender\n", iResult);

        else if ( iResult == 0 )

            printf("Connection closed by peer!\n");

        else

            printf("recv() failed with error code %d\n", WSAGetLastError());

 

    } while(iResult > 0);

 

    // Echo back the data

    iResult = send(s2, recvbuf, recvbuflen, 0 );

    if (iResult == SOCKET_ERROR)

    {

        printf("send() failed with error code %d\n", WSAGetLastError());

        closesocket(s2);

        WSACleanup();

        return 1;

    }

            else

            {

                        printf("send() is OK!\n");

                        printf("Bytes Sent: %d\n", iResult);

            }

 

            if(closesocket(s) == 0)

                        printf("closesocket() pretty fine!\n");

            if(WSACleanup () == 0)

                        printf("WSACleanup() is OK!\n");

            return 0;

}

 

Build and run the project and the following is a sample output.

 

-------------------------------------------------------

Bluetooth Receiver Program Example: The program output sample

 

Bluetooth Sender Program Example

 

Create a new empty Win32 console mode application and add the project/solution name.

 

Bluetooth Sender Program Example: Creating a new empty Win32 console mode application and adding the project/solution name.

 

Add the following source code.

 

// Link to ws2_32.lib

#include <winsock2.h>

#include <ws2bth.h>

#include <BluetoothAPIs.h>

#include <stdio.h>

 

#define DEFAULT_BUFLEN 512

 

typedef ULONGLONG bt_addr, *pbt_addr, BT_ADDR, *PBT_ADDR;

 

int main(int argc, char **argv)

{

            WSADATA wsd;

            SOCKET s;

            SOCKADDR_BTH sab;

            // Hard coded directly, got it from the receiver/server

            BT_ADDR aSddr = 0X001DD9EA24D8;

            int iResult;

            // This should be const void * type for non-char data

            char *sendbuf = "Test data from client...";

            int recvbuflen = DEFAULT_BUFLEN;

            // Change the type accordingly for non-char data

            char recvbuf[DEFAULT_BUFLEN] = "";

 

            if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)

            {

                        printf("Unable to load Winsock! Error code is %d\n", WSAGetLastError());

                        return 1;

            }

            else

                        printf("WSAStartup() is OK, Winsock lib loaded!\n");

 

            s = socket (AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);

            if (s == INVALID_SOCKET)

            {

                        printf ("Socket creation failed, error %d\n", WSAGetLastError());

                WSACleanup();

                        return 1;

            }

            else

                        printf ("socket() looks fine!\n");

 

            memset (&sab, 0, sizeof(sab));

            sab.addressFamily  = AF_BTH;

            // Set the btAddr member to a BT_ADDR variable that

            // contains the address of the target device. App

            // can accept the device address as a string but must convert

            // the address and store it in a variable of type BT_ADDR.

            sab.btAddr = aSddr;

 

            // If the service identifier is available, then set the

            // serviceClassId member of SOCKADDR_BTH to the GUID of

            // the RFCOMM-based service. In this case, the client

            // performs an SDP query and then uses the resulting server channel.

            // sab.serviceClassId = nguiD;

 

            // Or If you want to use a hard-coded channel number, set the

            // port member of SOCKADDR_BTH to the server channel number (1-31)

            sab.port = 1;

 

            // Connect to the Bluetooth socket, created previously

            if (connect (s, (SOCKADDR *)&sab, sizeof(sab)) == SOCKET_ERROR)

            {

                        printf("connect() failed with error code %d\n", WSAGetLastError ());

                        closesocket(s);

                        WSACleanup();

                        return 1;

            }

            else

                printf("connect() should be fine!\n");

 

    // Send some data

    iResult = send(s, sendbuf, (int)strlen(sendbuf), 0 );

    if (iResult == SOCKET_ERROR) {

        printf("send() failed with error code %d\n", WSAGetLastError());

        closesocket(s);

        WSACleanup();

        return 1;

    }

    else

    {

           printf("send() is OK!\n");

           printf("Bytes Sent: %d\n", iResult);

     }

 

    // shutdown the stream connection since no more data will be sent

    iResult = shutdown(s, SD_SEND);

    if (iResult == SOCKET_ERROR)

    {

        printf("shutdown() failed with error code %d\n", WSAGetLastError());

        closesocket(s);

        WSACleanup();

        return 1;

    }

    else

        printf("shutdown() is working!\n");

 

    // receive

    // Receive until the peer closes the connection

    do {

              iResult = recv(s, recvbuf, recvbuflen, 0);

 

        if (iResult > 0)

            printf(" %d Bytes received from sender\n", iResult);

        else if (iResult == 0)

            printf("Connection was closed by peer!\n");

        else

            printf("recv() failed with error code %d\n", WSAGetLastError());

 

    } while(iResult > 0);

 

            // Do all the cleanup

            if(closesocket(s) == 0)

                        printf("closesocket() pretty fine!\n");

            if(WSACleanup () == 0)

                        printf("WSACleanup() is OK!\n");

            return 0;

}

 

The receiver address has been hardcoded and there is no authentication for the sending. Build and run the project and the following screenshot shows a sample output.

 

Bluetooth Sender Program Example: An output sample

 

 

 


< Winsock 2 & Bluetooth APIs | Winsock2 Supported Protocols Main | Bluetooth Win32 Example >