/* * * BlueZ - Bluetooth protocol stack for Linux * * Copyright (C) 2001-2002 Nokia Corporation * Copyright (C) 2002-2003 Maxim Krasnyansky * Copyright (C) 2002-2004 Marcel Holtmann * Copyright (C) 2002-2003 Stephen Crane * * * 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 #endif #include #include #include #include #include #include #include #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; }