⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 obex_socket.c

📁 It s a tool designed to extract as much information as possible from Bluetooth devices without the r
💻 C
字号:
/********************************************************************* *                 * Filename:        obex_cable.c * Original author: Pontus Fuchs <pontus.fuchs@tactel.se> * *     Copyright (c) 1999, 2000 Pontus Fuchs, All Rights Reserved. *       *     This library is free software; you can redistribute it and/or *     modify it under the terms of the GNU Lesser General Public *     License as published by the Free Software Foundation; either *     version 2 of the License, or (at your option) any later version. * *     This library is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *     Lesser General Public License for more details. * *     You should have received a copy of the GNU Lesser General Public *     License along with this library; if not, write to the Free Software *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,  *     MA  02111-1307  USA *      ********************************************************************//*  $Id: obex_socket.c,v 1.6 2002/05/15 13:08:06 kds Exp $  OBEX serial port transport functions.  Adapted for Affix, Fixes:       Imre Deak <ext-imre.deak@nokia.com>  Adapted for Bluez, Fixes marked [REV]:  reverend@unrooted.net  Modified for BT name resolution and code cleanup: Davide Libenzi <davidel@xmailserver.org>*/	 #include <stdio.h>#include <sys/time.h>#include <sys/ioctl.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <termios.h>#include <netinet/in.h>#include <arpa/inet.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/rfcomm.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <glib.h>#include <openobex/obex.h>/* * [REV] * * I've moved the necessary parts of these two includes directly into here. * The BTDEBUG and BTERROR macros and the cobex_context struct. * * #include <affix/btcore.h> * #include "obex_server.h" */#if defined(_DEBUG)#define BTDEBUG(fmt, args...) //printf(fmt, ##args);#else#define BTDEBUG(fmt, args...) (void) 0#endif#define BTERROR(fmt, args...) //fprintf(stderr, fmt, ##args);extern int* __eebt_getErrLocation(const pthread_t aThread);struct cobex_context {	char *addr;	int chan;	const char *portname;	int rfd, wfd;	char inputbuf[4096]; 	struct termios oldtio, newtio;};static void cobex_cleanup(struct cobex_context *gt, gboolean force);static char *bt_sock_cachefile(char *cfname, int len);static int bt_sock_cachefile_lookup(FILE *file, const char *btname, bdaddr_t *btaddr);static int bt_sock_cache_lookup(const char *btname, bdaddr_t *btaddr);static int bt_sock_cache_add(FILE *file, const char *btname, bdaddr_t const *btaddr);static char *bt_sock_addr2str(bdaddr_t const *btaddr, char *straddr);static int bt_sock_str2addr(const char *straddr, bdaddr_t *btaddr);static int bt_sock_name2bth(const char *btname, bdaddr_t *btaddr);static char *bt_sock_cachefile(char *cfname, int len) {	char const *env = getenv("HOME");	if (env)		snprintf(cfname, len, "%s/.bt-namecache", env);	else		snprintf(cfname, len, ".bt-namecache");	return cfname;}static int bt_sock_cachefile_lookup(FILE *file, const char *btname, bdaddr_t *btaddr) {	char *name, *addr;	char buf[512];	rewind(file);	while (fgets(buf, sizeof(buf) - 1, file) != NULL) {		buf[strlen(buf) - 1] = 0;		if ((name = strtok(buf, " \t\r\n")) == NULL ||		    (addr = strtok(NULL, " \t\r\n")) == NULL ||		    bt_sock_str2addr(addr, btaddr) < 0)			continue;		if (strcasecmp(name, btname) == 0)			return 0;	}	return -1;}static int bt_sock_cache_lookup(const char *btname, bdaddr_t *btaddr) {	int err;	FILE *file;	char cfname[256];	bt_sock_cachefile(cfname, sizeof(cfname) - 1);	if ((file = fopen(cfname, "rt")) == NULL)		return -1;	err = bt_sock_cachefile_lookup(file, btname, btaddr);	fclose(file);	return err;}static int bt_sock_cache_add(FILE *file, const char *btname, bdaddr_t const *btaddr) {	bdaddr_t laddr;	char addr[128];	if (bt_sock_cachefile_lookup(file, btname, &laddr) < 0) {		fseek(file, 0, SEEK_END);		fprintf(file, "%s\t%s\n", btname,  bt_sock_addr2str(btaddr, addr));	}	return 0;}static char *bt_sock_addr2str(bdaddr_t const *btaddr, char *straddr) {	int i;	for (i = 0; i < 6; i++) {		if (i)			sprintf(straddr + 2 + (i - 1) * 3, ":%02X", btaddr->b[5 - i]);		else			sprintf(straddr, "%02X", btaddr->b[5]);	}	return straddr;}static int bt_sock_str2addr(const char *straddr, bdaddr_t *btaddr) {	int i;	unsigned int aaddr[6];	if (sscanf(straddr, "%02x:%02x:%02x:%02x:%02x:%02x",		   &aaddr[0], &aaddr[1], &aaddr[2], &aaddr[3], &aaddr[4], &aaddr[5]) != 6)		return -1;	for (i = 0; i < 6; i++)		btaddr->b[5 - i] = (unsigned char) (aaddr[i] & 0xff);	return 0;}static int bt_sock_name2bth(const char *btname, bdaddr_t *btaddr) {	int i, niinf, dd, err = -1;	inquiry_info *piinf = NULL;	FILE *file;	char cfname[256];	if (bt_sock_cache_lookup(btname, btaddr) == 0)		return 0;	bt_sock_cachefile(cfname, sizeof(cfname) - 1);	if ((file = fopen(cfname, "r+t")) == NULL &&	    (file = fopen(cfname, "w+t")) == NULL)		return -1;	fprintf(stderr, "Resolving name '%s' ...\n", btname);	if ((niinf = hci_inquiry(0, 32, -1, NULL, &piinf, 0)) < 0) {		fprintf(stderr, "hci_inquiry error\n");		fclose(file);		return -1;	}	if ((dd = hci_open_dev(0)) < 0) {		fprintf(stderr, "Unable to open HCI device\n");		free(piinf);		fclose(file);		return -1;	}	for (i = 0; i < niinf; i++) {		char devname[128];		if (hci_remote_name(dd, &piinf[i].bdaddr, sizeof(devname) - 1,				    devname, 100000) >= 0) {			if (strcasecmp(devname, btname) == 0) {				*btaddr = piinf[i].bdaddr;				err = 0;			}			bt_sock_cache_add(file, devname, &piinf[i].bdaddr);		}	}	hci_close_dev(dd);	free(piinf);	fclose(file);	return err;}int bt_sock_open(char const *qcaddr, int channel) {	int sock;	bdaddr_t btaddr;	struct sockaddr_rc laddr, raddr;	struct hci_dev_info di;	char straddr[64];	if(hci_devinfo(0, &di) < 0) {		//perror("hci_devinfo");		return -1;	}	if (bt_sock_str2addr(qcaddr, &btaddr) < 0 &&	    bt_sock_name2bth(qcaddr, &btaddr) < 0) {		fprintf(stderr, "Unable to resolve '%s'\n", qcaddr);		return -1;	}	laddr.rc_family = AF_BLUETOOTH;	laddr.rc_bdaddr = di.bdaddr;	laddr.rc_channel = 0;	raddr.rc_family = AF_BLUETOOTH;	raddr.rc_bdaddr = btaddr;	raddr.rc_channel = channel;	if ((sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {		//perror("socket");		return -1;	}	if (bind(sock, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {		//perror("bind");		close(sock);		return -1;	}	//printf("Local device %s\n", bt_sock_addr2str(&di.bdaddr, straddr));	//printf("Remote device %s (%d)\n", qcaddr, channel);	if(connect(sock, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {		*(__eebt_getErrLocation(pthread_self())) = errno;		//printf("THREAD: %d, errno: %d\n", pthread_self(), errno);		//perror("connect1");		close(sock);		return -1;	}	return sock;}#if 0static int open_connection(char const *qcaddr, int channel) {	int sock, d;	struct sockaddr_rc laddr, raddr;	struct hci_dev_info di;	if(hci_devinfo(0, &di) < 0) {		//perror("hci_devinfo");		return -1;	}	//printf("Local device %s\n", batostr(&di.bdaddr));	laddr.rc_family = AF_BLUETOOTH;	laddr.rc_bdaddr = di.bdaddr;	laddr.rc_channel = 0;	raddr.rc_family = AF_BLUETOOTH;	str2ba(qcaddr, &raddr.rc_bdaddr);	raddr.rc_channel = channel;	if ((sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0) {		//perror("socket");		return -1;	}	if (bind(sock, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {		//perror("bind");		close(sock);		return -1;	}	//printf("Remote device %s (%d)\n", qcaddr, channel);	if(connect(sock, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {		*(__eebt_getErrLocation(pthread_self())) = errno;		//perror("connect2");		close(sock);		return -1;	}	return sock;}#endif//// Open serial port.//static gint cobex_init(struct cobex_context *gt){	if( gt->rfd == -1 ) {		if (gt->addr != NULL) {			if ((gt->rfd = bt_sock_open(gt->addr, gt->chan)) < 0) {				//printf("*** 1\n");				return -1;			}			gt->wfd = gt->rfd;		} else if (gt->portname != NULL) {			if ((gt->rfd = open(gt->portname, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) < 0) {				*(__eebt_getErrLocation(pthread_self())) = errno;				//perror("Can' t open tty");				return -1;			}			gt->wfd = gt->rfd;			tcgetattr(gt->rfd, &gt->oldtio);			bzero(&gt->newtio, sizeof(struct termios));			gt->newtio.c_cflag = B115200 | CS8 | CREAD; // T.Koba for RFCOMM			gt->newtio.c_iflag = IGNPAR;			gt->newtio.c_oflag = 0;			tcflush(gt->rfd, TCIFLUSH);			tcsetattr(gt->rfd, TCSANOW, &gt->newtio);		} else {			gt->rfd = 0;			gt->wfd = 1;		}	}	return 1;}//// Close down. If force is TRUE. Try to break out of OBEX-mode.//static void cobex_cleanup(struct cobex_context *gt, gboolean force){	if (gt->portname != NULL) {		if(force) {			// Send a break to get out of OBEX-mode			if (ioctl(gt->rfd, TCSBRKP, 0) < 0) {				BTERROR("Unable to send break!");			}		}		close(gt->rfd);	} 		gt->rfd = gt->wfd = -1;}//// Open up cable OBEX//struct cobex_context *cobex_open(const gchar *port){	struct cobex_context *gt;	const char *chan;		gt = g_new0(struct cobex_context, 1);	if (gt == NULL)		return NULL;		gt->rfd = gt->wfd = -1;	gt->portname = port;	gt->addr = NULL;	gt->chan = -1;	if ((chan = strchr((const char *) port, '@')) != NULL)	{		gt->addr = strdup((const char *) port);		gt->addr[chan - (const char *) port] = 0;		gt->chan = atoi(chan + 1);	}	return gt;}struct cobex_context *cobex_setsocket(const int fd){	struct cobex_context *gt;		gt = g_new0(struct cobex_context, 1);	if (gt == NULL)		return NULL;		gt->rfd = gt->wfd = fd;	gt->portname = NULL;	return gt;}int cobex_getsocket(struct cobex_context *gt){	return gt->rfd;}	//// Close down cable OBEX.//void cobex_close(struct cobex_context *gt){	if (gt->addr)		g_free(gt->addr);	g_free(gt);}	//// Do transport connect or listen//gint cobex_connect(obex_t *handle, gpointer userdata){	struct cobex_context *gt;	gt = userdata;	if(gt->rfd >= 0) {		BTDEBUG("fd already exist. Using it");		return 1;	}	if(cobex_init(gt) < 0) {		return -1;	}	return 1;}//// Do transport disconnect//gint cobex_disconnect(obex_t *handle, gpointer userdata){	struct cobex_context *gt;	gt = userdata;	cobex_cleanup(gt, FALSE);	return 1;}////  Called when data needs to be written//gint cobex_write(obex_t *handle, gpointer userdata, guint8 *buffer, gint length){	struct cobex_context *gt;	gint actual = 0;	gint pos = 0;	gt = userdata;	/*	 * [REV]	 * For some reason the init function wasn't getting called before this call	 * to write.  Probably my own fault, something I ripped out must have in 	 * the initial cobex_connect() callback from OpenOBEX.  Fortunately for me	 * it works fine if I just call the init from the first write.  The init	 * sets the wfd field so that this call gets skipped on all writes after 	 * the first.	 */	if(gt->wfd < 0) {		if(cobex_init(gt) < 0) {			//printf("*** 0\n");			return( -1 );		}	}	while (actual < length)	{		int frag;		frag = write(gt->wfd, &buffer[pos], length - pos);		if (frag < 0) {			if (errno == EAGAIN) {				frag = 0;				BTDEBUG("Temp. no resource avail.");			} else {				*(__eebt_getErrLocation(pthread_self())) = errno;				BTERROR("Write error:%s", strerror(errno));				return frag;			}		}		actual += frag;		pos += frag;		BTDEBUG("Wrote %d fragment", frag);	} 	BTDEBUG("Wrote %d bytes (expected %d)", actual, length);	return actual;}//// Called when more data is needed.//gint cobex_handle_input(obex_t *handle, gpointer userdata, gint timeout){	gint actual;	struct cobex_context *gt;	struct timeval time;	fd_set fdset;        gint ret;	gint16 expectlen;		gt = userdata;		/* Return if no fd */	if(gt->rfd < 0)		return -1;	time.tv_sec = timeout;	time.tv_usec = 0;	FD_ZERO(&fdset);	FD_SET(gt->rfd, &fdset);	// for fragment read  T.Koba	actual = 0;	expectlen = 0;	do {		gint len;		fd_set fdset1 = fdset;		ret = select(gt->rfd+1, &fdset1, NULL, NULL, &time);			/* Check if this is a timeout (0) or error (-1) */		if (ret < 0) {			BTERROR("Error (%d)", ret);			return -1;		}		if (ret == 0)			len = 0;		else {			len = read(gt->rfd, &gt->inputbuf[actual], sizeof(gt->inputbuf)-actual);			if( len < 0 ){				if (errno == -EAGAIN) {					BTDEBUG("Temp. no resource available.");					len = 0;				} else {					BTDEBUG("read error (%d)", len);					*(__eebt_getErrLocation(pthread_self())) = errno;					return len;				}			} else if (len == 0) {				BTDEBUG("Connection terminated.");				return -1;			}		}		actual += len;		if( (expectlen == 0) && (actual >= 3) ) {						expectlen = ntohs(*(guint16 const *) (gt->inputbuf + 1));			BTDEBUG("expect %d bytes", expectlen);			if( expectlen > sizeof(gt->inputbuf) )			{				BTDEBUG("cobex_context buffer size is too small!!!");				exit(1);			}		}	} while( (actual < expectlen) || (expectlen == 0) );	BTDEBUG("Read %d bytes", actual);	OBEX_CustomDataFeed(handle, gt->inputbuf, actual);	return actual;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -