2 * Simple RFCOMM server implementation, modelled after
3 * http://people.csail.mit.edu/albert/bluez-intro/x502.html
5 * Creates a server socket, accepts up to one client at a time, reflects
6 * received data to the server (echo mode), terminates upon reception of
7 * CTRL-C / SIGTERM and friends.
9 * Was specifically written as a standalone application not using libble
10 * to demonstrate interoperability.
13 #include <bluetooth/bluetooth.h>
14 #include <bluetooth/rfcomm.h>
20 #include <sys/socket.h>
24 # define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
27 static bdaddr_t local_addr
= *BDADDR_ANY
;
28 static int channel
= 1;
30 static int log_level
= 1;
33 static void log_msg(int level
, const char *fmt
, ...)
38 if (level
> log_level
)
43 vfprintf(log_stream
, fmt
, arg
);
48 static int server_socket(void)
51 struct sockaddr_rc addr
;
54 log_msg(2, "socket()\n");
55 fd
= socket(AF_BLUETOOTH
, SOCK_STREAM
, BTPROTO_RFCOMM
);
61 log_msg(2, "bind()\n");
62 memset(&addr
, 0, sizeof(addr
));
63 addr
.rc_family
= AF_BLUETOOTH
;
64 addr
.rc_channel
= channel
;
65 memcpy(&addr
.rc_bdaddr
, &local_addr
, sizeof(addr
.rc_bdaddr
));
66 rc
= bind(fd
, (struct sockaddr
*)&addr
, sizeof(addr
));
73 log_msg(2, "listen()\n");
81 log_msg(1, "listening ...\n");
85 static void close_server(int fd
)
88 log_msg(2, "close() server\n");
90 log_msg(1, "server closed\n");
93 static int accept_client(int srv_fd
)
97 struct sockaddr_rc addr
;
103 log_msg(2, "accept()\n");
105 cli_fd
= accept(srv_fd
, (struct sockaddr
*)&addr
, &len
);
110 ba2str(&addr
.rc_bdaddr
, peer
);
111 log_msg(1, "accept: fd %d, client addr %s\n", cli_fd
, peer
);
115 static int process_client(int fd
, const char *msg
)
117 ssize_t rdlen
, wrlen
;
120 log_msg(2, "write()\n");
121 wrlen
= write(fd
, msg
, rdlen
);
126 log_msg(1, "sent: fd %d, data: %s\n", fd
, msg
);
127 if (wrlen
!= rdlen
) {
128 log_msg(0, "write mismatch: fd %d, rcvd %zd, sent %zd\n", fd
, rdlen
, wrlen
);
133 static int receive_client(int fd
)
142 log_msg(2, "read()\n");
143 rdlen
= read(fd
, buff
, sizeof(buff
));
149 log_msg(1, "rcvd: fd %d, data: %s\n", fd
, buff
);
150 rc
= process_client(fd
, buff
);
156 static void close_client(int fd
)
159 log_msg(2, "close() client\n");
161 log_msg(1, "close: fd %d, client gone\n", fd
);
164 static void signal_handler(int sig
)
170 static int is_readable(int fd
)
172 struct pollfd fds
[1];
175 memset(fds
, 0, sizeof(fds
));
177 fds
[0].events
= POLLIN
;
178 rc
= poll(fds
, ARRAY_SIZE(fds
), 0);
182 * Implementor's note: Silently accept "error" conditions here
183 * as well, to have the socket closed on failed read. Or else
184 * we'd need another has_error() test routine, too.
189 int main(int argc
, char *argv
[])
191 int server_fd
, client_fd
;
194 signal(SIGHUP
, signal_handler
);
195 signal(SIGINT
, signal_handler
);
196 signal(SIGTERM
, signal_handler
);
198 server_fd
= server_socket();
201 if (is_readable(server_fd
)) {
202 client_fd
= accept_client(server_fd
);
206 if (client_fd
>= 0 && is_readable(client_fd
)) {
207 rc
= receive_client(client_fd
);
209 close_client(client_fd
);
215 close_server(server_fd
);