blob: 9f87eca62b5b59a4c498d58bd9db343de422074f [file] [log] [blame]
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2001-2002 Nokia Corporation
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2002-2004 Marcel Holtmann <marcel@holtmann.org>
* Copyright (C) 2002-2003 Stephen Crane <steve.crane@rococosoft.com>
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
* CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
* COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
* SOFTWARE IS DISCLAIMED.
*
*
* $Id$
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <malloc.h>
#include <syslog.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/l2cap.h>
#include <bluetooth/sdp.h>
#include <bluetooth/sdp_lib.h>
#include "sdpd.h"
static sdp_list_t *service_db;
/*
* Ordering function called when inserting a service record.
* The service repository is a linked list in sorted order
* and the service record handle is the sort key
*/
static int record_sort(const void *r1, const void *r2)
{
const sdp_record_t *rec1 = (const sdp_record_t *)r1;
const sdp_record_t *rec2 = (const sdp_record_t *)r2;
if (!rec1 || !rec2) {
SDPERR("NULL RECORD LIST FATAL\n");
return -1;
}
return rec1->handle - rec2->handle;
}
/*
* Reset the service repository by deleting its contents
*/
void sdp_svcdb_reset()
{
sdp_list_free(service_db, (sdp_free_func_t)sdp_record_free);
}
typedef struct _indexed {
int sock;
sdp_record_t *record;
} sdp_indexed_t;
static sdp_list_t *socket_index;
/*
* collect all services registered over this socket
*/
void sdp_svcdb_collect_all(int sock)
{
sdp_list_t *p, *q;
for (p=socket_index, q=0; p; ) {
sdp_indexed_t *item = (sdp_indexed_t *)p->data;
if (item->sock == sock) {
sdp_list_t *next = p->next;
sdp_record_remove(item->record->handle);
free(item);
if (q)
q->next = next;
else
socket_index = next;
free(p);
p = next;
} else if (item->sock > sock)
return;
else {
q = p;
p = p->next;
}
}
}
void sdp_svcdb_collect(sdp_record_t *rec)
{
sdp_list_t *p, *q;
for (p=socket_index, q=0; p; q=p, p=p->next) {
sdp_indexed_t *item = (sdp_indexed_t *)p->data;
if (rec == item->record) {
free(item);
if (q)
q->next = p->next;
else
socket_index = p->next;
free(p);
return;
}
}
}
static int compare_indices(const void *i1, const void *i2)
{
const sdp_indexed_t *s1 = (const sdp_indexed_t *)i1;
const sdp_indexed_t *s2 = (const sdp_indexed_t *)i2;
return s1->sock - s2->sock;
}
void sdp_svcdb_set_collectable(sdp_record_t *record, int sock)
{
sdp_indexed_t *item = (sdp_indexed_t *)malloc(sizeof(sdp_indexed_t));
item->sock = sock;
item->record = record;
socket_index = sdp_list_insert_sorted(socket_index, item, compare_indices);
}
/*
* Add a service record to the repository
*/
void sdp_record_add(sdp_record_t *rec)
{
#ifdef SDP_DEBUG
SDPDBG("Adding rec : 0x%lx\n", (long)rec);
SDPDBG("with handle : 0x%lx\n", (long)rec->handle);
#endif
service_db = sdp_list_insert_sorted(service_db, rec, record_sort);
}
static sdp_list_t *record_locate(uint32_t handle)
{
if (service_db) {
sdp_list_t *p;
sdp_record_t r;
r.handle = handle;
p = sdp_list_find(service_db, &r, record_sort);
return p;
}
SDPDBG("Could not find svcRec for : 0x%x\n", handle);
return 0;
}
/*
* Given a service record handle, find the record associated with it.
*/
sdp_record_t *sdp_record_find(uint32_t handle)
{
sdp_list_t *p = record_locate(handle);
if (p)
return (sdp_record_t *)p->data;
SDPDBG("Couldn't find record for : 0x%x\n", handle);
return 0;
}
/*
* Given a service record handle, remove its record from the repository
*/
int sdp_record_remove(uint32_t handle)
{
sdp_list_t *p = record_locate(handle);
if (p) {
sdp_record_t *r = (sdp_record_t *)p->data;
if (r) {
service_db = sdp_list_remove(service_db, r);
return 0;
}
}
SDPERR("Remove : Couldn't find record for : 0x%x\n", handle);
return -1;
}
/*
* Return a pointer to the linked list containing the records in sorted order
*/
sdp_list_t *sdp_get_record_list()
{
return service_db;
}
uint32_t sdp_next_handle(void)
{
uint32_t handle = 0x10000;
while (sdp_record_find(handle))
handle++;
return handle;
}