#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>

int main(int argc, char **argv)
{
    struct sockaddr_rc loc_addr = { 0 }, rem_addr = { 0 };
    char buf[1024] = { 0 };
    int s, client, bytes_read, status;
    unsigned int opt = sizeof(rem_addr);
    fd_set readfds, writefds;
    int maxfd, sock_flags;
    struct timeval timeout;

    // allocate socket
    s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

    // bind socket to port 1 of the first available bluetooth adapter
    loc_addr.rc_family = AF_BLUETOOTH;
    loc_addr.rc_bdaddr = *BDADDR_ANY;
    loc_addr.rc_channel = 1;
    bind(s, (struct sockaddr *)&loc_addr, sizeof(loc_addr));

    // put server socket into listening mode
    listen(s, 1);

    // put server socket into nonblocking mode
    sock_flags = fcntl( s, F_GETFL, 0 );
    fcntl( s, F_SETFL, sock_flags | O_NONBLOCK );

    // accept one connection
    while(1) { 
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_SET(s, &readfds);
        maxfd = s;

        printf("waiting for connection\n");
        status = select(maxfd + 1, &readfds, &writefds, 0, &timeout);
        if( status > 0 && FD_ISSET( s, &readfds ) ) {
            // incoming connection
            client = accept( s, (struct sockaddr*)&rem_addr, &opt );
            if( client >= 0 ) break;
        }
    }
    // close the server socket, leaving only the client socket open
    close(s);

    ba2str( &rem_addr.rc_bdaddr, buf );
    fprintf(stderr, "accepted connection from %s\n", buf);
    memset(buf, 0, sizeof(buf));

    // put client socket into nonblocking mode
    sock_flags = fcntl( client, F_GETFL, 0 );
    fcntl( client, F_SETFL, sock_flags | O_NONBLOCK );

    // read data from the client
    while(1) {
        timeout.tv_sec = 1;
        timeout.tv_usec = 0;
        FD_ZERO(&readfds);
        FD_ZERO(&writefds);
        FD_SET(client, &readfds);
        FD_SET(client, &writefds);
        maxfd = client;

        status = select(maxfd + 1, &readfds, &writefds, 0, &timeout);
        if( status > 0 && FD_ISSET( client, &readfds ) ) {
            // incoming data
            bytes_read = recv(client, buf, sizeof(buf), 0);
            if( 0 == bytes_read ) break;
            printf("received [%s]\n", buf);
        }
        if( status > 0 && FD_ISSET( client, &writefds ) ) {
            // can send data
            printf("socket is writable\n");
            send( client, "hello!", 6, 0 );
        }

        printf("doing other stuff\n");
    }

    // close connection
    close(client);
    return 0;
}
