public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
From: Denis KENZIOR <denis.kenzior@trolltech.com>
To: bluez-devel@lists.sourceforge.net
Subject: [Bluez-devel] Possible Race condition in Rfcomm TTY
Date: Wed, 5 Dec 2007 16:01:03 +1000	[thread overview]
Message-ID: <200712051601.03309.denis.kenzior@trolltech.com> (raw)
In-Reply-To: <20071204232538.GA23003@wavehammer.waldi.eu.org>

[-- Attachment #1: Type: text/plain, Size: 1268 bytes --]

Marcel,

I think there is a race condition in the RFCOMM Socket -> TTY adaptation.  
Basically whenever a client device connects and starts sending data right 
away, the serial port will not receive it.

To see what I mean:

run 'rfcomm -r listen 0 15' on a server.

and run a simple test app that sends data right after connecting (one 
attached).

Once connection has been established, run 'cat /dev/rfcomm0' 

Using my Suse 10.2 desktop with kernel 2.6.18.8 and Neo with kernel 2.6.22.5 
(Nov 26 snapshot), about 95% of the time the initial data sent never shows up 
on the serial port.  If I reverse the roles, the desktop usually gets the 
initial chunk of data.  This inconsistency makes it hard to implement 
something like the DUN or Handsfree services where clients very frequently 
send data right away.

Looking at the kernel code it seems that the data is copied into the socket 
buf or into the serial buf from the rfcomm_recv_data.  It also seems that 
rfcomm_dev_add never copies what is in the socket buffer to what is in the 
serial buffer.  It would seem that rfomm_dev_add should also copy any pending 
data from a socket read buffer to the serial port read buffer whenever doing 
the conversion.  Or is there something else going on here?

-Denis


[-- Attachment #2: rfc.c --]
[-- Type: text/x-csrc, Size: 2896 bytes --]

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/sco.h>
#include <bluetooth/rfcomm.h>

static volatile int terminate = 0;

static void sig_term(int sig) {
	terminate = 1;
}

static int rfcomm_connect(bdaddr_t *src, bdaddr_t *dst, uint8_t channel)
{
	struct sockaddr_rc addr;
	int s;

	if ((s = socket(PF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.rc_family = AF_BLUETOOTH;
	bacpy(&addr.rc_bdaddr, src);
	addr.rc_channel = 0;
	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		close(s);
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.rc_family = AF_BLUETOOTH;
	bacpy(&addr.rc_bdaddr, dst);
	addr.rc_channel = channel;
	if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ){
		close(s);
		return -1;
	}
	return s;
}

static void usage(void)
{
	printf("Usage:\n"
		"\trfc <bdaddr> [channel]\n");
}

int main(int argc, char *argv[])
{
	struct sigaction sa;

	fd_set rfds;
	struct timeval timeout;
	unsigned char buf[2048], *p;
	int maxfd, sel, rlen, wlen;

	bdaddr_t local;
	bdaddr_t bdaddr;
	uint8_t channel;

	char *filename;
	mode_t filemode;
	int err, mode = 0;
	int dd, rd, sd, fd;
	uint16_t sco_handle, sco_mtu, vs;

	switch (argc) {
	case 2:
		str2ba(argv[1], &bdaddr);
		channel = 6;
		break;
	case 3:
		str2ba(argv[1], &bdaddr);
		channel = atoi(argv[2]);
		break;
	default:
		usage();
		exit(-1);
	}

	hci_devba(0, &local);
	
	memset(&sa, 0, sizeof(sa));
	sa.sa_flags = SA_NOCLDSTOP;
	sa.sa_handler = sig_term;
	sigaction(SIGTERM, &sa, NULL);
	sigaction(SIGINT,  &sa, NULL);

	sa.sa_handler = SIG_IGN;
	sigaction(SIGCHLD, &sa, NULL);
	sigaction(SIGPIPE, &sa, NULL);

	if ((rd = rfcomm_connect(&local, &bdaddr, channel)) < 0) {
		perror("Can't connect RFCOMM channel");
		return -1;
	}

	fprintf(stderr, "RFCOMM channel connected\n");

	fprintf(stderr, "Sending BRSF\n");
	write(rd, "AT+BRSF=24\r\n", 12);

	while (!terminate) {
		FD_ZERO(&rfds);
		FD_SET(rd, &rfds);
		FD_SET(fileno(stdin), &rfds);

		timeout.tv_sec = 0;
		timeout.tv_usec = 10000;

		if ((sel = select(rd + 1, &rfds, NULL, NULL, &timeout)) > 0) {
			if (FD_ISSET(rd, &rfds)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(rd, buf, sizeof(buf));
				if (rlen > 0) {
					fprintf(stderr, "%s\n", buf);
				} else {
					break;
				}				
			}
			
			if (FD_ISSET(fileno(stdin), &rfds)) {
				memset(buf, 0, sizeof(buf));
				rlen = read(fileno(stdin), buf, sizeof(buf));
				if (rlen > 0) {
					fprintf(stderr, "Sending->%s", buf);
					wlen = write(rd, buf, rlen);
				}
				else {
					break;
				}
			}
		}
	}

	close(rd);

	return 0;
}

[-- Attachment #3: Type: text/plain, Size: 309 bytes --]

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4

[-- Attachment #4: Type: text/plain, Size: 164 bytes --]

_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

  reply	other threads:[~2007-12-05  6:01 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-12-04 23:25 [Bluez-devel] [PATCH] audio - ignore permission denied errors on avctp and avdtp sockets Bastian Blank
2007-12-05  6:01 ` Denis KENZIOR [this message]
2007-12-05  7:28   ` [Bluez-devel] Possible Race condition in Rfcomm TTY Marcel Holtmann
2007-12-05  7:22 ` [Bluez-devel] [PATCH] audio - ignore permission denied errors on avctp and avdtp sockets Marcel Holtmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200712051601.03309.denis.kenzior@trolltech.com \
    --to=denis.kenzior@trolltech.com \
    --cc=bluez-devel@lists.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox