public inbox for linux-bluetooth@vger.kernel.org
 help / color / mirror / Atom feed
* [Bluez-devel] [PATCH] SDP lib memory leak
@ 2007-08-31 17:28 Manuel Naranjo
  2007-08-31 18:45 ` Marcel Holtmann
  0 siblings, 1 reply; 3+ messages in thread
From: Manuel Naranjo @ 2007-08-31 17:28 UTC (permalink / raw)
  To: BlueZ development

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

Marcel and team,
Hi folks, I have made an application that makes use of the sdp lib. By 
running the app with valgrind [1] I found a memory leak.
There's an static variable called bluetooth_base_uuid that's being 
initializated once but then never freed.
I had added a method that should be called, only when the thread is 
about to end that frees that variable.
Attached you can see the patch.
Thanks,
Manuel


[1] http://valgrind.org/


[-- Attachment #2: leak.patch --]
[-- Type: text/x-patch, Size: 1074 bytes --]

diff -uprN bluez-libs-3.17/include/sdp_lib.h bluez-libs-3.17.patched/include/sdp_lib.h
--- bluez-libs-3.17/include/sdp_lib.h	2007-05-09 03:40:39.000000000 -0300
+++ bluez-libs-3.17.patched/include/sdp_lib.h	2007-08-31 14:15:49.000000000 -0300
@@ -609,6 +609,9 @@ void sdp_pattern_add_uuidseq(sdp_record_
 
 int sdp_send_req_w4_rsp(sdp_session_t *session, uint8_t *req, uint8_t *rsp, uint32_t reqsize, uint32_t *rspsize);
 
+/** This function will cleanup the bluetooth base uuid, should be called only after the thread has ended it's work **/
+void sdp_cleanup();
+
 #ifdef __cplusplus
 }
 #endif
diff -uprN bluez-libs-3.17/src/sdp.c bluez-libs-3.17.patched/src/sdp.c
--- bluez-libs-3.17/src/sdp.c	2007-08-23 06:59:37.000000000 -0300
+++ bluez-libs-3.17.patched/src/sdp.c	2007-08-31 14:15:02.000000000 -0300
@@ -2152,6 +2152,11 @@ uint128_t *sdp_create_base_uuid(void)
 	return bluetooth_base_uuid;
 }
 
+void sdp_cleanup(){
+	if (bluetooth_base_uuid)
+		free(bluetooth_base_uuid);
+}
+
 uuid_t *sdp_uuid16_create(uuid_t *u, uint16_t val)
 {
 	memset(u, 0, sizeof(uuid_t));

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

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

[-- 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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Bluez-devel] [PATCH] SDP lib memory leak
  2007-08-31 17:28 [Bluez-devel] [PATCH] SDP lib memory leak Manuel Naranjo
@ 2007-08-31 18:45 ` Marcel Holtmann
  2007-08-31 19:11   ` Manuel Naranjo
  0 siblings, 1 reply; 3+ messages in thread
From: Marcel Holtmann @ 2007-08-31 18:45 UTC (permalink / raw)
  To: BlueZ development

Hi Manuel,

> I have made an application that makes use of the sdp lib. By 
> running the app with valgrind [1] I found a memory leak.
> There's an static variable called bluetooth_base_uuid that's being 
> initializated once but then never freed.
> I had added a method that should be called, only when the thread is 
> about to end that frees that variable.
> Attached you can see the patch.

thanks for the patch, but I put a different patch in the CVS that avoids
any memory allocation at all.

Can you extract me a test program from your application, so I can double
check that it is doing the right thing on little and big endian systems
and we don't have any memory leaks at all anymore.

Regards

Marcel



-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
Bluez-devel mailing list
Bluez-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/bluez-devel

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Bluez-devel] [PATCH] SDP lib memory leak
  2007-08-31 18:45 ` Marcel Holtmann
@ 2007-08-31 19:11   ` Manuel Naranjo
  0 siblings, 0 replies; 3+ messages in thread
From: Manuel Naranjo @ 2007-08-31 19:11 UTC (permalink / raw)
  To: BlueZ development

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

Marcel Holtmann escribió:
> Hi Manuel,
>
>   
>> I have made an application that makes use of the sdp lib. By 
>> running the app with valgrind [1] I found a memory leak.
>> There's an static variable called bluetooth_base_uuid that's being 
>> initializated once but then never freed.
>> I had added a method that should be called, only when the thread is 
>> about to end that frees that variable.
>> Attached you can see the patch.
>>     
>
> thanks for the patch, but I put a different patch in the CVS that avoids
> any memory allocation at all.
>
> Can you extract me a test program from your application, so I can double
> check that it is doing the right thing on little and big endian systems
> and we don't have any memory leaks at all anymore.
>
> Regards
>
> Marcel
>
>   
Great. I'm attaching you the source, you can find it online at: 
http://aircable.googlecode.com/svn/lcd_temp/AIRcableSPP2/
Regards,
Manuel


[-- Attachment #2: errorcodes.h --]
[-- Type: text/plain, Size: 170 bytes --]

#ifndef SPP_ERR_CODES
#define SPP_ERR_CODES

//no problems
#define OK					0
#define CONNECTION_CLOSE 	1

//errors
//TODO: Extend errors list
#define ERROR				-1


#endif

[-- Attachment #3: sppclient.h --]
[-- Type: text/plain, Size: 1903 bytes --]

/*
 *
 *  SPPclient, little spp client.
 *
 *  Copyright (C) 2007 Naranjo,manuel <manuel@aircable.net>
 *  Copyright (C) 2007 Wireless Cables Inc  <aircable.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 */

#ifndef SPPCLIENT_H_
#define SPPCLIENT_H_

#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include <poll.h>

#include <sys/ioctl.h>
#include <sys/socket.h>

#include <fcntl.h>

#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>

#include "errorcodes.h"

//Public functions
/** Register SPP service **/
int sppRegister(int channel);
/** Unregister SPP service **/
int sppUnregister();
/** Read a line from the spp socket **/
int sppReadLine(char * buf, int MAXLEN);
/** Write a line to the spp socket **/
int sppWriteLine(const char * buf);
/** Register socket for listening **/
int sppListen();
/** Wait for connections, this method will block **/
int sppWaitConnection();
/** Disconnect SPP socket **/
int sppDisconnect();

#endif /*SPPCLIENT_H_*/

[-- Attachment #4: sspclient.c --]
[-- Type: text/x-csrc, Size: 9157 bytes --]

/*
 *  SPPclient, little spp client.
 *
 *  Copyright (C) 2007 Naranjo,manuel <manuel@aircable.net>
 *  Copyright (C) 2007 Wireless Cables Inc  <aircable.net>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 */

#include "sppclient.h"

static int channelNumber;

/* RFcomm socket */
static int SPPsocket;
/* Listening socket, opened once we get connected. */
static int SPPclient;
/* Bluetooth address of our peer */
static bdaddr_t SPPpeer;

/* Bluetooth interface used to register the SDP record */
static bdaddr_t interface;

/* SPP record handle number*/
static uint32_t recHandle;

/** Constants	**/
//times
#define TIMEOUT 			120

#define SPP_DEBUG

int sppRegister(int channelN){
	sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto;
	uuid_t root_uuid, sp_uuid, l2cap, rfcomm;
	sdp_profile_desc_t profile;
	uint8_t u8 = channelN ? channelN : 1;
	sdp_record_t  *record;
	sdp_session_t *session;	
	sdp_data_t *channel;
	
	int ret;
	
	session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0);
	if (!session) {
		perror("Failed to connect to the local SDP server");
		return ERROR;
	}

	record = sdp_record_alloc();
	if (!record) {
		perror("Failed to allocate service record");
		sdp_close(session);
		return ERROR;
	}

	sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP);
	root = sdp_list_append(0, &root_uuid);
	sdp_set_browse_groups(record, root);
	sdp_list_free(root, 0);

	sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID);
	svclass_id = sdp_list_append(0, &sp_uuid);
	sdp_set_service_classes(record, svclass_id);
	sdp_list_free(svclass_id, 0);

	sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID);
	profile.version = 0x0100;
	profiles = sdp_list_append(0, &profile);
	sdp_set_profile_descs(record, profiles);
	sdp_list_free(profiles, 0);

	sdp_uuid16_create(&l2cap, L2CAP_UUID);
	proto[0] = sdp_list_append(0, &l2cap);
	apseq = sdp_list_append(0, proto[0]);

	sdp_uuid16_create(&rfcomm, RFCOMM_UUID);
	proto[1] = sdp_list_append(0, &rfcomm);
	channel = sdp_data_alloc(SDP_UINT8, &u8);
	proto[1] = sdp_list_append(proto[1], channel);
	apseq = sdp_list_append(apseq, proto[1]);

	aproto = sdp_list_append(0, apseq);
	sdp_set_access_protos(record, aproto);

	bacpy(&interface, BDADDR_ANY);

	sdp_set_info_attr(record, "Serial Port", 0, "AIRcableSPP server");

	if (sdp_device_record_register(session, &interface, record, 0) < 0) {
		perror("Service Record registration failed\n");
		ret = ERROR;
		goto end;
	}

	printf("Serial Port service registered\n");
	
	recHandle = record->handle;
	
	ret = OK;
	channelNumber = u8;

end:
	sdp_data_free(channel);
	sdp_list_free(proto[0], 0);
	sdp_list_free(proto[1], 0);
	sdp_list_free(apseq, 0);
	sdp_list_free(aproto, 0);
	sdp_close(session);
	sdp_record_free(record);

	return ret;

}

int sppUnregister(){
	if (!recHandle){
		fprintf(stderr, "Not registered, nothing to do\n");
		return ERROR;
	}
	
	uint32_t range = 0x0000ffff;
	sdp_list_t *attr;
	sdp_session_t *sess;
	sdp_record_t *rec;

	sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
	if (!sess) {
		printf("No local SDP server!\n");
		return ERROR;
	}

	attr = sdp_list_append(0, &range);
	rec = sdp_service_attr_req(sess, recHandle, SDP_ATTR_REQ_RANGE, attr);
	sdp_list_free(attr, 0);

	if (!rec) {
		printf("Service Record not found.\n");
		sdp_close(sess);
		return ERROR;
	}

	if (sdp_device_record_unregister(sess, &interface, rec)) {
		printf("Failed to unregister service record: %s\n", strerror(errno));
		sdp_close(sess);
		return ERROR;
	}

	printf("Service Record deleted.\n");	
	sdp_close(sess);	
	return OK;
}

int sppListen(){
	struct sockaddr_rc loc_addr = { 0 };
	
	if (channelNumber < 1){
		fprintf(stderr, "Channel Number can't be 0 or negative\n");
		fprintf(stderr, "You need to call sppRegister() first\n");
		return ERROR;
	}
		
	
    // allocate socket
	SPPsocket = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
    if (SPPsocket < 0) {
		perror("Can't create RFCOMM socket");
		SPPsocket = 0;
		return ERROR;
	}

    // bind socket to port 1 of the first available 
    // local bluetooth adapter
    loc_addr.rc_family = AF_BLUETOOTH;
    loc_addr.rc_bdaddr = *BDADDR_ANY;
    loc_addr.rc_channel = (uint8_t) (channelNumber);
    if (bind(SPPsocket, (struct sockaddr *)&loc_addr, sizeof(loc_addr)) < 0) {
		perror("Can't bind RFCOMM socket");
		close(SPPsocket);
		SPPsocket = 0;
		return ERROR;
	}    

    // put socket into listening mode
    listen(SPPsocket, 1);
    
    return OK;
}
    
int sppWaitConnection(){
	struct sockaddr_rc peer_addr = { 0 };
    char addr[17] = { 0 };
    int unsigned opt = sizeof(peer_addr);
    struct timeval t;
	int result; 
	int unsigned ol = sizeof(struct timeval);
    
	if (!SPPsocket){
		fprintf(stderr, "You need to call sspListen first\n");
		return ERROR;
	}
	
    // accept one connection
    SPPclient = accept(SPPsocket, (struct sockaddr *)&peer_addr, &opt);

    ba2str( &peer_addr.rc_bdaddr, addr );
    bacpy( &SPPpeer, &peer_addr.rc_bdaddr);
    printf("accepted connection from %s\n", addr);
        
    result = getsockopt(SPPclient, SOL_SOCKET, SO_RCVTIMEO, &t, &ol); 
	
	if (result < 0)
		perror("timeout");

	t.tv_sec = TIMEOUT;
	t.tv_usec = 0;
	result = setsockopt(SPPclient, SOL_SOCKET, SO_RCVTIMEO,  &t, ol);	
	if (result < 0)
		perror("timeout");

	result = getsockopt(SPPclient, SOL_SOCKET, SO_RCVTIMEO, &t, &ol); 
	if (result < 0)
		perror("timeout");
      
    return OK;
}

int sppDisconnect(){
	struct hci_conn_info_req *cr;
	int dd;
	int ret = OK;
	
	if (SPPclient < 1 || SPPsocket < 1){
		perror("Not Connected, can't disconnect\n");
		return ERROR;
	}
	// close connection
	if (SPPclient)
    	close(SPPclient);
    	
    if (SPPsocket)
    	close(SPPsocket);
	
	dd = hci_open_dev(hci_get_route(NULL));
	if (dd < 0) {
		perror("HCI device open failed");
		return ERROR;
	}

	cr = malloc(sizeof(*cr) + sizeof(struct hci_conn_info));
	if (!cr) {
		perror("Can't allocate memory to disconnect");
		return ERROR;
	}

	bacpy(&cr->bdaddr, &SPPpeer);
	cr->type = ACL_LINK;
	if (ioctl(dd, HCIGETCONNINFO, (unsigned long) cr) < 0) {
		perror("Get connection info failed");
		return ERROR;
	}

	if (hci_disconnect(dd, htobs(cr->conn_info->handle),
				HCI_OE_USER_ENDED_CONNECTION, 10000) < 0){
		perror("Disconnect failed");
		ret = ERROR;
	}

	if (cr)
		free(cr);

	if (dd)
		hci_close_dev(dd);
	
	return ret;
}


int sppReadLine(char * out, int MAXLEN){
	struct pollfd fds;
	int ret, len=0;
	char c;	

	fds.fd = SPPclient;
	fds.events = POLLIN;

	while(1) {
		ret = poll(&fds, 1, -1); //wait forever, there's no chance poll will return = 0
		if (ret < 0){
			perror("Error while reading from Rfcomm Socket (poll)");
			return ERROR;
		}
			
		ret = read(SPPclient, &c, 1);
		if ( ret < 0 ) {
			perror("Error while reading from Rfcomm Socket (read)");
			return ERROR;
		}
			
		*out++=c;
		len++;
				
		#ifdef SPP_DEBUG
			if ( len > 0 && len % 70 ==0 )
				fprintf(stdout, "\n<< ");
			else if (len == 1)
				fprintf(stdout, "<< ");
				
			if ( isprint( c ) && c!='\n' && c!='\r')
				fprintf(stdout, "%c", c);
			else if (c != '\n')
				fprintf(stdout, "\\x%02X", c);
		#endif
						
		if (c == '\n' || c == '\x03' || c == '\r')
			break;
					
		if (len==MAXLEN -1 ){
			break;
		}			
	} 

	#ifdef SPP_DEBUG
		fprintf(stdout, "\n");
	#endif

		
	*out++=0; //null ending string.
	    
	return len;
	
}

int sppWriteLine(const char * buf){
	int ret = 0, len;
	struct pollfd fds;
	char * out = NULL;
	
	if (!SPPclient){
			fprintf(stderr, "SPP socket is not opened, can't write\n");
			return ERROR;
	}
	len = strlen(buf);
	out = calloc(len+5, sizeof(char));
	
	if (!out) {
		fprintf(stderr, "Couldn't allocate buffer\n");
		return ERROR;
	}
		
		
	fds.fd = SPPclient;
	fds.events = POLLOUT;
		
	ret = poll(&fds, 1, -1); //wait forever, there's no chance poll will return = 0
	if (ret < 0){
		perror("Error while writting to RFcomm Socket (poll)");
		free(out);
		return ERROR;
	}
	
	sprintf(out, "%s\n", buf);
	ret = write(SPPclient,out,strlen(out));
			
	if (ret < 0) {
		perror("Error while writting to RFcomm Socket (write)");
		free(out);
		return ERROR;
	}
		
	#ifdef SPP_DEBUG
		fprintf(stdout, ">> %s\n", buf);
	#endif
		
	free(out);
	return ret;
}

int main(void) {
	int r = sppRegister(1);
	if (r != OK)
		return -1;
	
	sppListen();
	sppWaitConnection();
	
	char * line;
	line = calloc(1024, sizeof(char));
	
	sppReadLine(line, 1024);
	sppWriteLine(line);
	
	free(line);
	sppUnregister();
	
	sdp_cleanup();
	return 0;
}

[-- Attachment #5: Type: text/plain, Size: 315 bytes --]

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/

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

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

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2007-08-31 19:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-08-31 17:28 [Bluez-devel] [PATCH] SDP lib memory leak Manuel Naranjo
2007-08-31 18:45 ` Marcel Holtmann
2007-08-31 19:11   ` Manuel Naranjo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox