Add memory debugging (--enable-mem-debug), find and fix several small (and not so small) memory leaks

This commit is contained in:
Ron Pedde 2007-01-17 01:06:16 +00:00
parent b23f0d226b
commit 14fe9f9c6c
53 changed files with 627 additions and 364 deletions

View File

@ -6,13 +6,14 @@ AC_INIT(config.h.in)
AM_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE(mt-daapd,0.2.1.1)
AC_USE_SYSTEM_EXTENSIONS
dnl Checks for programs.
AC_PROG_CC
dnl AC_PROG_YACC
dnl AM_PROG_LEX
AC_PROG_LIBTOOL
AC_USE_SYSTEM_EXTENSIONS
AC_CHECK_HEADERS([sys/wait.h])
AC_CHECK_HEADERS([sys/param.h])
@ -115,6 +116,10 @@ AC_ARG_ENABLE(gdbm,[ --enable-gdbm Enable gdbm support],
AC_ARG_ENABLE(ffmpeg,[ --enable-ffmpeg Enable ffmpeg transcode support],
use_ffmpeg=true;)
AC_ARG_ENABLE(mem-debug,[ --enable-mem-debug Enable memory debugging],
CPPFLAGS="${CPPFLAGS} -DDEBUG_MEM")
AM_CONDITIONAL(COND_REND_HOWL, test x$rend_howl = xtrue)
AM_CONDITIONAL(COND_REND_POSIX, test x$rend_posix = xtrue)
AM_CONDITIONAL(COND_REND_AVAHI, test x$rend_avahi = xtrue)

View File

@ -62,6 +62,7 @@ mt_daapd_SOURCES = main.c daapd.h rend.h uici.c uici.h webserver.c \
smart-parser.c smart-parser.h xml-rpc.c xml-rpc.h \
os.h ll.c ll.h conf.c conf.h compat.c compat.h util.c util.h \
os-unix.h os-unix.c os.h plugin.c plugin.h db-sql-updates.c \
memdebug.c memdebug.h \
$(PRENDSRC) $(ORENDSRC) $(HRENDSRC) $(ARENDSRC) $(OGGVORBISSRC) \
$(FLACSRC) $(MUSEPACKSRC) $(SQLITEDB) $(SQLITE3DB) $(SQLDB) $(GDBM)

View File

@ -8,6 +8,8 @@
#include <string.h>
#include <stdio.h>
#include "daapd.h"
#if !HAVE_STRCASESTR
/* case-independent string matching, similar to strstr but
* matching */
@ -264,7 +266,7 @@ char *strptime(char *buf, char *fmt, struct tm *tm) {
}
len = (int) strlen(En_US.pm_string);
if (strncmp(buf, En_US.pm_string, len) == 0) {
if (tm->tm_hour > 12)
return 0;
@ -373,7 +375,7 @@ char *strptime(char *buf, char *fmt, struct tm *tm) {
i *= 10;
i += *buf - '0';
}
if (c == 'Y')
i -= 1900;
else if (i < 69) /*c=='y', 00-68 is for 20xx, the rest is for 19xx*/
@ -467,7 +469,7 @@ char *strtok_r(char *s, const char *delim, char **last)
return NULL;
}
tok = s - 1;
/*
* Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
* Note that delim must have one NUL; we stop if we see that, too.
@ -504,7 +506,7 @@ time_t timegm(struct tm *tm) {
_putenv("TZ=UTC0");
_tzset();
ret = mktime(tm);
if(tz)
sprintf(buffer,"TZ=%s",tz);
else

View File

@ -48,10 +48,10 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "ll.h"
#include "daapd.h"
#include "os.h"
#include "util.h"
#include "webserver.h"
@ -1696,5 +1696,6 @@ char *conf_get_servername(void) {
retval[MAX_REND_LEN-3] = '.';
}
free(template);
return retval;
}

View File

@ -8,6 +8,7 @@
#define os_syslog(a,b)
#define os_closesyslog()
#include "daapd.h"
#include "conf.h"
#include "err.h"

View File

@ -50,6 +50,7 @@
# include <sys/wait.h>
#endif
#include "daapd.h"
#include "conf.h"
#include "configfile.h"
#include "db-generic.h"

View File

@ -31,7 +31,16 @@
#ifndef _DAAPD_H_
#define _DAAPD_H_
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <time.h>
#include "memdebug.h" /* redefine free/malloc/etc */
#include "compat.h"
#include "webserver.h"
@ -54,35 +63,6 @@ typedef struct tag_config {
int foreground; /**< Whether or not we are running in foreground */
int full_reload; /**< Whether the reload should be a full one */
#if 0
char *configfile; /**< path to config file */
char *web_root; /**< path to the dir containing the web files */
char *iface; /**< interface to advertise on */
int port; /**< port to listen on */
int rescan_interval; /**< How often to do a background fs rescan */
int always_scan; /**< 0 to minimize disk usage (embedded devices) */
int process_m3u; /**< Should we process m3u files? */
int scan_type; /**< Method for finding playtime. see scan-mp3.c */
int compress; /**< Should we compress? */
int latin1_tags; /**< interpret all tags as latin1 rather than utf8 */
char *adminpassword; /**< Password to web management pages */
char *readpassword; /**< iTunes password */
char *mp3dir; /**< root directory of the mp3 files */
char *servername; /**< Name advertised via rendezvous */
char *playlist; /**< Path to the playlist file */
char *runas; /**< Who to drop privs to (if run as root) */
char *dbdir; /**< Where to put the db file */
char *extensions; /**< What music file extentions to process */
char *ssc_codectypes; /**< What codectypes are converted in server */
char *ssc_prog; /**< Server side music format converter prog */
char *artfilename; /**< What filename to merge coverart with */
char *logfile; /**< What file to use as a logfile */
char *compdirs; /**< Compilations directories */
char *dbtype; /**< db backend type */
char *dbparms; /**< parameters for the db backend */
char **complist; /**< list of compilation directories */
#endif
STATS stats; /**< Stats structure (see above) */
WSHANDLE server; /**< webserver handle */
} CONFIG;

View File

@ -34,6 +34,7 @@
#include <stdlib.h>
#include <string.h>
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"
#include "redblack.h"

View File

@ -39,6 +39,7 @@
# include <stdint.h>
#endif
#include "daapd.h"
#include "db-generic.h"
#include "err.h"
#include "mp3-scanner.h"
@ -62,7 +63,7 @@ typedef struct tag_db_functions {
int(*dbs_edit_playlist)(char **, int, char*, char*);
int(*dbs_playcount_increment)(char **, int);
int(*dbs_enum_start)(char **, DBQUERYINFO *);
int(*dbs_enum_fetch_row)(char **, PACKED_MP3FILE *, DBQUERYINFO *);
int(*dbs_enum_fetch_row)(char **, PACKED_MP3FILE *, DBQUERYINFO *);
int(*dbs_enum_reset)(char **, DBQUERYINFO *);
int(*dbs_enum_end)(char **);
int(*dbs_force_rescan)(char **);
@ -466,7 +467,7 @@ int db_enum_start(char **pe, DBQUERYINFO *pinfo) {
/**
* fetch the next item int he result set started by the db enum. this
* will be in native packed row format
* will be in native packed row format
*/
int db_enum_fetch_row(char **pe, PACKED_MP3FILE *row, DBQUERYINFO *pinfo) {
return db_current->dbs_enum_fetch_row(pe, row, pinfo);

View File

@ -48,6 +48,7 @@
#include <stdint.h>
#endif
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "db-generic.h"

View File

@ -48,6 +48,7 @@
# include <unistd.h>
#endif
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "db-generic.h"

View File

@ -5,6 +5,7 @@
*/
#include <stdio.h>
#include "daapd.h"
char *db_sqlite_updates[] = {
/* version 0 -> version 1 -- initial update */
@ -47,7 +48,7 @@ char *db_sqlite_updates[] = {
" sample_count INTEGER DEFAULT 0,\n"
" force_update INTEGER DEFAULT 0\n"
");\n"
"CREATE INDEX idx_path ON songs(path);\n"
"CREATE INDEX idx_path ON songs(path);\n"
"CREATE TABLE config (\n"
" term VARCHAR(255) NOT NULL,\n"
" subterm VARCHAR(255) DEFAULT NULL,\n"
@ -141,7 +142,7 @@ char *db_sqlite_updates[] = {
"create index idx_path on songs(path);\n"
"drop table tempsongs;\n"
"update config set value=3 where term='version';\n",
/* version 3 -> version 4 */
/* add db_timestamp and path to playlist table */
"create temp table tempplaylists as select * from playlists;\n"
@ -240,13 +241,13 @@ char *db_sqlite_updates[] = {
"insert into playlistitems (playlistid, songid) select * from tempitems;\n"
"drop table tempitems;\n"
"update config set value=7 where term='version';\n",
/* version 7 -> version 8 */
"create index idx_songid on playlistitems(songid)\n"
"create index idx_playlistid on playlistitems(playlistid)\n"
"update config set value=8 where term='version';\n",
/* version 8 -> version 9 */
/* version 8 -> version 9 */
"drop index idx_path;\n"
"create temp table tempsongs as select * from songs;\n"
"drop table songs;\n"
@ -301,7 +302,7 @@ char *db_sqlite_updates[] = {
"drop table tempsongs;\n"
"update config set value=9 where term='version';\n",
/* version 9 -> version 10 */
/* version 9 -> version 10 */
"drop index idx_path;\n"
"create temp table tempsongs as select * from songs;\n"
"drop table songs;\n"
@ -354,7 +355,7 @@ char *db_sqlite_updates[] = {
"create index idx_path on songs(path,idx);\n"
"drop table tempsongs;\n"
"update config set value=10 where term='version';\n",
/* version 10 -> version 11 */
/* version 10 -> version 11 */
"drop index idx_playlistid;\n"
"create index idx_playlistid on playlistitems(playlistid,songid);\n"
"update config set value=11 where term='version';\n",

View File

@ -38,6 +38,7 @@
# include <stdint.h>
#endif
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"
#include "db-generic.h"
@ -1624,6 +1625,7 @@ void db_sql_dispose_item(MP3FILE *pmp3) {
MAYBEFREE(pmp3->description);
MAYBEFREE(pmp3->url);
MAYBEFREE(pmp3->codectype);
MAYBEFREE(pmp3->album_artist);
free(pmp3);
}

View File

@ -40,6 +40,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include "daapd.h"
#include "conf.h"
#include "configfile.h"
#include "err.h"

View File

@ -47,6 +47,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "daapd.h"
#include "err.h"
#ifndef ERR_LEAN
# include "os.h"

View File

@ -32,6 +32,7 @@
#endif
#include <stdio.h>
#include "daapd.h"
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C

View File

@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include "daapd.h"
#include "ll.h"
#include "err.h"
@ -126,11 +127,11 @@ int ll_del_item(LL *pl, char *key) {
phead = pl->itemlist.next;
while(phead) {
if((pl->flags & LL_FLAG_HONORCASE) &&
if((pl->flags & LL_FLAG_HONORCASE) &&
(strcmp(phead->key,key)==0))
break;
if((!(pl->flags & LL_FLAG_HONORCASE) &&
(strcasecmp(phead->key,key)==0)))
if((!(pl->flags & LL_FLAG_HONORCASE) &&
(strcasecmp(phead->key,key)==0)))
break;
ptail=phead;

View File

@ -2,14 +2,14 @@
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@ -17,12 +17,12 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
*
* @APPLE_LICENSE_HEADER_END@
*
* This code is completely 100% portable C. It does not depend on any external header files
* from outside the mDNS project -- all the types it expects to find are defined right here.
*
*
* The previous point is very important: This file does not depend on any external
* header files. It should complile on *any* platform that has a C compiler, without
* making *any* assumptions about availability of so-called "standard" C functions,
@ -1016,19 +1016,19 @@ Merge in license terms from Quinn's copy, in preparation for Darwin release
#include "mDNSClientAPI.h" // Defines the interface provided to the client layer above
#include "mDNSPlatformFunctions.h" // Defines the interface required of the supporting layer below
#include "daapd.h"
// Disable certain benign warnings with Microsoft compilers
#if(defined(_MSC_VER))
// Disable "conditional expression is constant" warning for debug macros.
// Otherwise, this generates warnings for the perfectly natural construct "while(1)"
// If someone knows a variant way of writing "while(1)" that doesn't generate warning messages, please let us know
#pragma warning(disable:4127)
// Disable "const object should be initialized"
// We know that static/globals are defined to be zeroed in ANSI C, and to avoid this warning would require some
// *really* ugly chunk of zeroes and curly braces to initialize zeroRR and mDNSprintf_format_default to all zeroes
#pragma warning(disable:4132)
// Disable "assignment within conditional expression".
// Other compilers understand the convention that if you place the assignment expression within an extra pair
// of parentheses, this signals to the compiler that you really intended an assignment and no warning is necessary.
@ -1047,7 +1047,7 @@ typedef enum
kDNSFlag0_QR_Mask = 0x80, // Query or response?
kDNSFlag0_QR_Query = 0x00,
kDNSFlag0_QR_Response = 0x80,
kDNSFlag0_OP_Mask = 0x78, // Operation type
kDNSFlag0_OP_StdQuery = 0x00,
kDNSFlag0_OP_Iquery = 0x08,
@ -1055,14 +1055,14 @@ typedef enum
kDNSFlag0_OP_Unused3 = 0x18,
kDNSFlag0_OP_Notify = 0x20,
kDNSFlag0_OP_Update = 0x28,
kDNSFlag0_QROP_Mask = kDNSFlag0_QR_Mask | kDNSFlag0_OP_Mask,
kDNSFlag0_AA = 0x04, // Authoritative Answer?
kDNSFlag0_TC = 0x02, // Truncated?
kDNSFlag0_RD = 0x01, // Recursion Desired?
kDNSFlag1_RA = 0x80, // Recursion Available?
kDNSFlag1_Zero = 0x40, // Reserved; must be zero
kDNSFlag1_AD = 0x20, // Authentic Data [RFC 2535]
kDNSFlag1_CD = 0x10, // Checking Disabled [RFC 2535]
@ -1176,7 +1176,7 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
#define mDNS_VACB_Remain(s) ((mDNSu32)(mDNS_VACB_Lim - s))
char *s = mDNS_VACB_Lim, *digits;
struct mDNSprintf_format F = mDNSprintf_format_default;
while (1) // decode flags
{
c = *++fmt;
@ -1187,7 +1187,7 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
else if (c == '0') F.zeroPad = 1;
else break;
}
if (c == '*') // decode field width
{
int f = va_arg(arg, int);
@ -1200,7 +1200,7 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
for (; c >= '0' && c <= '9'; c = *++fmt)
F.fieldWidth = (10 * F.fieldWidth) + (c - '0');
}
if (c == '.') // decode precision
{
if ((c = *++fmt) == '*')
@ -1209,9 +1209,9 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
F.precision = (10 * F.precision) + (c - '0');
F.havePrecision = 1;
}
if (F.leftJustify) F.zeroPad = 0;
conv:
switch (c) // perform appropriate conversion
{
@ -1246,7 +1246,7 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
for (; i < F.precision; i++) *--s = '0';
if (F.sign) { *--s = F.sign; i++; }
break;
case 'o' : if (F.lSize) n = va_arg(arg, unsigned long);
else n = va_arg(arg, unsigned int);
if (F.hSize) n = (unsigned short) n;
@ -1261,7 +1261,7 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
if (F.altForm && i && *s != '0') { *--s = '0'; i++; }
for (; i < F.precision; i++) *--s = '0';
break;
case 'a' : {
unsigned char *a = va_arg(arg, unsigned char *);
if (!a) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
@ -1295,7 +1295,7 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
}
}
break;
case 'p' : F.havePrecision = F.lSize = 1;
F.precision = 8;
case 'X' : digits = "0123456789ABCDEF";
@ -1319,9 +1319,9 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
for (; i < F.precision; i++) *--s = '0';
if (F.altForm) { *--s = (char)c; *--s = '0'; i += 2; }
break;
case 'c' : *--s = (char)va_arg(arg, int); i = 1; break;
case 's' : s = va_arg(arg, char *);
if (!s) { static char emsg[] = "<<NULL>>"; s = emsg; i = sizeof(emsg)-1; }
else switch (F.altForm)
@ -1347,13 +1347,13 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
if (F.havePrecision && i > F.precision) // Make sure we don't truncate in the middle of a UTF-8 character
{ i = F.precision; while (i>0 && (s[i] & 0xC0) == 0x80) i--; }
break;
case 'n' : s = va_arg(arg, char *);
if (F.hSize) * (short *) s = (short)nwritten;
else if (F.lSize) * (long *) s = (long)nwritten;
else * (int *) s = (int)nwritten;
continue;
default: s = mDNS_VACB;
i = mDNS_snprintf(mDNS_VACB, sizeof(mDNS_VACB), "<<UNKNOWN FORMAT CONVERSION CODE %%%c>>", c);
@ -1361,19 +1361,19 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
if (++nwritten >= buflen) goto exit;
break;
}
if (i < F.fieldWidth && !F.leftJustify) // Pad on the left
do {
*sbuffer++ = ' ';
if (++nwritten >= buflen) goto exit;
} while (i < --F.fieldWidth);
if (i > buflen - nwritten) // Make sure we don't truncate in the middle of a UTF-8 character
{ i = buflen - nwritten; while (i>0 && (s[i] & 0xC0) == 0x80) i--; }
for (j=0; j<i; j++) *sbuffer++ = *s++; // Write the converted result
nwritten += i;
if (nwritten >= buflen) goto exit;
for (; i < F.fieldWidth; i++) // Pad on the right
{
*sbuffer++ = ' ';
@ -1389,12 +1389,12 @@ mDNSexport mDNSu32 mDNS_vsnprintf(char *sbuffer, mDNSu32 buflen, const char *fmt
mDNSexport mDNSu32 mDNS_snprintf(char *sbuffer, mDNSu32 buflen, const char *fmt, ...)
{
mDNSu32 length;
va_list ptr;
va_start(ptr,fmt);
length = mDNS_vsnprintf(sbuffer, buflen, fmt, ptr);
va_end(ptr);
return(length);
}
@ -1449,7 +1449,7 @@ mDNSlocal mDNSu32 mDNSRandom(mDNSu32 max)
{
static mDNSu32 seed = 0;
mDNSu32 mask = 1;
if (!seed) seed = (mDNSu32)mDNSPlatformTimeNow();
while (mask < max) mask = (mask << 1) | 1;
do seed = seed * 21 + 1; while ((seed & mask) > max);
@ -1571,7 +1571,7 @@ mDNSexport mDNSBool SameDomainName(const domainname *const d1, const domainname
a += 1 + *a;
b += 1 + *b;
}
return(mDNStrue);
}
@ -1629,7 +1629,7 @@ mDNSexport mDNSu8 *AppendLiteralLabelString(domainname *const name, const char *
const mDNSu8 *const lim2 = ptr + 1 + MAX_DOMAIN_LABEL;
const mDNSu8 *const lim = (lim1 < lim2) ? lim1 : lim2;
mDNSu8 *lengthbyte = ptr++; // Record where the length is going to go
while (*cstr && ptr < lim) *ptr++ = (mDNSu8)*cstr++; // Copy the data
*lengthbyte = (mDNSu8)(ptr - lengthbyte - 1); // Fill in the length byte
*ptr++ = 0; // Put the null root label on the end
@ -1782,7 +1782,7 @@ mDNSexport char *ConvertDomainNameToCString_withescape(const domainname *const n
{
const mDNSu8 *src = name->c; // Domain name we're reading
const mDNSu8 *const max = name->c + MAX_DOMAIN_NAME; // Maximum that's valid
if (*src == 0) *ptr++ = '.'; // Special case: For root, just write a dot
while (*src) // While more characters in the domain name
@ -1858,7 +1858,7 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
}
else
name = (domainlabel*)""; // Set this up to be non-null, to avoid errors if we have to call LogMsg() below
src = type->c; // Put the service type into the domain name
len = *src;
if (len < 2 || len >= 0x40) { errormsg="Invalid service application protocol name"; goto fail; }
@ -1875,9 +1875,9 @@ mDNSexport mDNSu8 *ConstructServiceName(domainname *const fqdn,
(src[4] | 0x20) == 'p'))
{ errormsg="Service transport protocol name must be _udp or _tcp"; goto fail; }
for (i=0; i<=len; i++) *dst++ = *src++;
if (*src) { errormsg="Service type must have only two labels"; goto fail; }
*dst = 0;
dst = AppendDomainName(fqdn, domain);
if (!dst) { errormsg="Service domain too long"; goto fail; }
@ -1895,12 +1895,12 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn,
const mDNSu8 *src = fqdn->c;
const mDNSu8 *max = fqdn->c + MAX_DOMAIN_NAME;
mDNSu8 *dst;
dst = name->c; // Extract the service name from the domain name
len = *src;
if (len >= 0x40) { debugf("DeconstructServiceName: service name too long"); return(mDNSfalse); }
for (i=0; i<=len; i++) *dst++ = *src++;
dst = type->c; // Extract the service type from the domain name
len = *src;
if (len >= 0x40) { debugf("DeconstructServiceName: service type too long"); return(mDNSfalse); }
@ -1922,7 +1922,7 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn,
for (i=0; i<=len; i++) *dst++ = *src++;
}
*dst++ = 0; // Put the null root label on the end
return(mDNStrue);
}
@ -1931,7 +1931,7 @@ mDNSexport mDNSBool DeconstructServiceName(const domainname *const fqdn,
mDNSlocal mDNSBool LabelContainsSuffix(const domainlabel *const name, const mDNSBool RichText)
{
mDNSu16 l = name->c[0];
if (RichText)
{
if (l < 4) return mDNSfalse; // Need at least " (2)"
@ -1984,7 +1984,7 @@ mDNSlocal void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichTe
{
mDNSu32 divisor = 1, chars = 2; // Shortest possible RFC1034 name suffix is 3 characters ("-2")
if (RichText) chars = 4; // Shortest possible RichText suffix is 4 characters (" (2)")
// Truncate trailing spaces from RichText names
if (RichText) while (name->c[name->c[0]] == ' ') name->c[0]--;
@ -2000,7 +2000,7 @@ mDNSlocal void AppendLabelSuffix(domainlabel *name, mDNSu32 val, mDNSBool RichTe
if (RichText) { name->c[++name->c[0]] = ' '; name->c[++name->c[0]] = '('; }
else { name->c[++name->c[0]] = '-'; }
while (divisor)
{
name->c[++name->c[0]] = (mDNSu8)('0' + val / divisor);
@ -2017,7 +2017,7 @@ mDNSexport void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText)
if (LabelContainsSuffix(name, RichText))
val = RemoveLabelSuffix(name, RichText);
// If no existing suffix, start by renaming "Foo" as "Foo (2)" or "Foo-2" as appropriate.
// If existing suffix in the range 2-9, increment it.
// If we've had ten conflicts already, there are probably too many hosts trying to use the same name,
@ -2025,7 +2025,7 @@ mDNSexport void IncrementLabelSuffix(domainlabel *name, mDNSBool RichText)
if (val == 0) val = 2;
else if (val < 10) val++;
else val += 1 + mDNSRandom(99);
AppendLabelSuffix(name, val, RichText);
}
@ -2197,7 +2197,7 @@ mDNSlocal mDNSBool ShouldSuppressKnownAnswer(const CacheRecord *const ka, const
{
// If RR signature is different, or data is different, then don't suppress our answer
if (!IdenticalResourceRecord(&ka->resrec,&rr->resrec)) return(mDNSfalse);
// If the requester's indicated TTL is less than half the real TTL,
// we need to give our answer before the requester's copy expires.
// If the requester's indicated TTL is at least half the real TTL,
@ -2267,7 +2267,7 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
if (m->SuppressProbes - m->NextScheduledQuery >= 0)
m->SuppressProbes = m->NextScheduledQuery;
}
// We announce to flush stale data from other caches. It is a reasonable assumption that any
// old stale copies will probably have the same TTL we're using, so announcing longer than
// this serves no purpose -- any stale copies of that record will have expired by then anyway.
@ -2277,7 +2277,7 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
// (no need to send additional multicast responses when we're announcing anyway)
rr->LastMCTime = m->timenow;
rr->LastMCInterface = mDNSInterfaceMark;
// If this is a record type that's not going to probe, then delay its first announcement so that
// it will go out synchronized with the first announcement for the other records that *are* probing.
// This is a minor performance tweak that helps keep groups of related records synchronized together.
@ -2287,7 +2287,7 @@ mDNSlocal void InitializeLastAPTime(mDNS *const m, AuthRecord *const rr)
// because they will meet the criterion of being at least half-way to their scheduled announcement time.
if (rr->resrec.RecordType != kDNSRecordTypeUnique)
rr->LastAPTime += DefaultProbeIntervalForTypeUnique * DefaultProbeCountForTypeUnique + rr->ThisAPInterval / 2;
SetNextAnnounceProbeTime(m, rr);
}
@ -2315,12 +2315,12 @@ mDNSlocal void SetTargetToHostName(mDNS *const m, AuthRecord *const rr)
if (target && SameDomainName(target, &m->hostname))
debugf("SetTargetToHostName: Target of %##s is already %##s", rr->resrec.name.c, target->c);
if (target && !SameDomainName(target, &m->hostname))
{
AssignDomainName(*target, m->hostname);
SetNewRData(&rr->resrec, mDNSNULL, 0);
// If we're in the middle of probing this record, we need to start again,
// because changing its rdata may change the outcome of the tie-breaker.
// (If the record type is kDNSRecordTypeUnique (unconfirmed unique) then DefaultProbeCountForRecordType is non-zero.)
@ -2407,7 +2407,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
AuthRecord **p = &m->ResourceRecords;
AuthRecord **d = &m->DuplicateRecords;
AuthRecord **l = &m->LocalOnlyRecords;
#if TEST_LOCALONLY_FOR_EVERYTHING
rr->resrec.InterfaceID = (mDNSInterfaceID)~0;
#endif
@ -2518,7 +2518,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
rr->resrec.namehash = DomainNameHashValue(&rr->resrec.name);
rr->resrec.rdatahash = RDataHashValue(rr->resrec.rdlength, &rr->resrec.rdata->u);
rr->resrec.rdnamehash = target ? DomainNameHashValue(target) : 0;
if (rr->resrec.InterfaceID == ((mDNSInterfaceID)~0))
{
debugf("Adding %p %##s (%s) to LocalOnly list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
@ -2550,7 +2550,7 @@ mDNSlocal mStatus mDNS_Register_internal(mDNS *const m, AuthRecord *const rr)
{
// Now that's we've finished building our new record, make sure it's not identical to one we already have
for (r = m->ResourceRecords; r; r=r->next) if (RecordIsLocalDuplicate(r, rr)) break;
if (r)
{
debugf("Adding %p %##s (%s) to duplicate list", rr, rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
@ -2705,7 +2705,7 @@ mDNSlocal mStatus mDNS_Deregister_internal(mDNS *const m, AuthRecord *const rr,
if (rr->UpdateCallback)
rr->UpdateCallback(m, rr, OldRData); // ... and let the client know
}
// CAUTION: MUST NOT do anything more with rr after calling rr->Callback(), because the client's callback function
// is allowed to do anything, including starting/stopping queries, registering/deregistering records, etc.
// In this case the likely client action to the mStatus_MemFree message is to free the memory,
@ -2749,7 +2749,7 @@ mDNSlocal const mDNSu8 *FindCompressionPointer(const mDNSu8 *const base, const m
const mDNSu8 *result = end - *domname - 1;
if (*domname == 0) return(mDNSNULL); // There's no point trying to match just the root label
// This loop examines each possible starting position in packet, starting end of the packet and working backwards
while (result >= base)
{
@ -2806,7 +2806,7 @@ mDNSlocal mDNSu8 *putDomainNameAsLabels(const DNSMessage *const msg,
{
if (*np > MAX_DOMAIN_LABEL)
{ LogMsg("Malformed domain name %##s (label more than 63 bytes)", name->c); return(mDNSNULL); }
// This check correctly allows for the final trailing root label:
// e.g.
// Suppose our domain name is exactly 255 bytes long, including the final trailing root label.
@ -2900,7 +2900,7 @@ mDNSlocal mDNSu8 *PutResourceRecordTTL(DNSMessage *const msg, mDNSu8 *ptr, mDNSu
mDNSu8 *endofrdata;
mDNSu16 actualLength;
const mDNSu8 *limit = msg->data + AbsoluteMaxDNSMessageData;
// If we have a single large record to put in the packet, then we allow the packet to be up to 9K bytes,
// but in the normal case we try to keep the packets below 1500 to avoid IP fragmentation on standard Ethernet
if (msg->h.numAnswers || msg->h.numAuthorities || msg->h.numAdditionals)
@ -3053,7 +3053,7 @@ mDNSlocal const mDNSu8 *getDomainName(const DNSMessage *const msg, const mDNSu8
break;
}
}
if (nextbyte) return(nextbyte);
else return(ptr);
}
@ -3064,7 +3064,7 @@ mDNSlocal const mDNSu8 *skipResourceRecord(const DNSMessage *msg, const mDNSu8 *
ptr = skipDomainName(msg, ptr, end);
if (!ptr) { debugf("skipResourceRecord: Malformed RR name"); return(mDNSNULL); }
if (ptr + 10 > end) { debugf("skipResourceRecord: Malformed RR -- no type/class/ttl/len!"); return(mDNSNULL); }
pktrdlength = (mDNSu16)((mDNSu16)ptr[8] << 8 | ptr[9]);
ptr += 10;
@ -3103,7 +3103,7 @@ mDNSlocal const mDNSu8 *GetResourceRecord(mDNS *const m, const DNSMessage *msg,
if (!ptr) { debugf("GetResourceRecord: Malformed RR name"); return(mDNSNULL); }
if (ptr + 10 > end) { debugf("GetResourceRecord: Malformed RR -- no type/class/ttl/len!"); return(mDNSNULL); }
rr->resrec.rrtype = (mDNSu16) ((mDNSu16)ptr[0] << 8 | ptr[1]);
rr->resrec.rrclass = (mDNSu16)(((mDNSu16)ptr[2] << 8 | ptr[3]) & kDNSClass_Mask);
rr->resrec.rroriginalttl = (mDNSu32) ((mDNSu32)ptr[4] << 24 | (mDNSu32)ptr[5] << 16 | (mDNSu32)ptr[6] << 8 | ptr[7]);
@ -3240,7 +3240,7 @@ mDNSlocal mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg,
mDNSu16 numAnswers = msg->h.numAnswers;
mDNSu16 numAuthorities = msg->h.numAuthorities;
mDNSu16 numAdditionals = msg->h.numAdditionals;
// Put all the integer values in IETF byte-order (MSB first, LSB second)
mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
*ptr++ = (mDNSu8)(numQuestions >> 8);
@ -3251,10 +3251,10 @@ mDNSlocal mStatus mDNSSendDNSMessage(const mDNS *const m, DNSMessage *const msg,
*ptr++ = (mDNSu8)(numAuthorities );
*ptr++ = (mDNSu8)(numAdditionals >> 8);
*ptr++ = (mDNSu8)(numAdditionals );
// Send the packet on the wire
status = mDNSPlatformSendUDP(m, msg, end, InterfaceID, srcport, dst, dstport);
// Put all the integer values back the way they were before we return
msg->h.numQuestions = numQuestions;
msg->h.numAnswers = numAnswers;
@ -3280,7 +3280,7 @@ mDNSlocal void DiscardDeregistrations(mDNS *const m)
{
if (m->CurrentRecord) LogMsg("DiscardDeregistrations ERROR m->CurrentRecord already set");
m->CurrentRecord = m->ResourceRecords;
while (m->CurrentRecord)
{
AuthRecord *rr = m->CurrentRecord;
@ -3333,7 +3333,7 @@ mDNSlocal void SendResponses(mDNS *const m)
{
if (rr->NextUpdateCredit && m->timenow - rr->NextUpdateCredit >= 0)
{
if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
if (++rr->UpdateCredits >= kMaxUpdateCredits) rr->NextUpdateCredit = 0;
else rr->NextUpdateCredit = (m->timenow + mDNSPlatformOneSecond * 60) | 1;
}
if (TimeToAnnounceThisRecord(rr, m->timenow) && ResourceRecordIsValidAnswer(rr))
@ -3433,7 +3433,7 @@ mDNSlocal void SendResponses(mDNS *const m)
mDNSu8 *responseptr = response.data;
mDNSu8 *newptr;
InitializeDNSMessage(&response.h, zeroID, ResponseFlags);
// First Pass. Look for:
// 1. Deregistering records that need to send their goodbye packet
// 2. Updated records that need to retract their old data
@ -3491,7 +3491,7 @@ mDNSlocal void SendResponses(mDNS *const m)
else
rr->SendRNow = mDNSNULL;
}
// Second Pass. Add additional records, if there's space.
newptr = responseptr;
for (rr = m->ResourceRecords; rr; rr=rr->next)
@ -3515,7 +3515,7 @@ mDNSlocal void SendResponses(mDNS *const m)
rr->resrec.rrclass &= ~kDNSClass_UniqueRRSet; // Make sure to clear cache flush bit back to normal state
}
}
if (response.h.numAnswers > 0) // We *never* send a packet with only additionals in it
{
debugf("SendResponses: Sending %d Deregistration%s, %d Announcement%s, %d Answer%s, %d Additional%s on %p",
@ -3782,12 +3782,12 @@ mDNSlocal int RecordDupSuppressInfo(DupSuppressInfo ds[DupSuppressInfoSize], mDN
if (!ds[j].InterfaceID || ds[j].Time - ds[i].Time < 0)
i = j;
}
// Record the info about this query we saw
ds[i].Time = Time;
ds[i].InterfaceID = InterfaceID;
ds[i].Type = Type;
return(i);
}
@ -3868,7 +3868,7 @@ mDNSlocal void SendQueries(mDNS *const m)
if (maxExistingQuestionInterval < q->ThisQInterval)
maxExistingQuestionInterval = q->ThisQInterval;
}
// Scan our list of questions
// (a) to see if there are any more that are worth accelerating, and
// (b) to update the state variables for all the questions we're going to send
@ -3977,7 +3977,7 @@ mDNSlocal void SendQueries(mDNS *const m)
// Start a new known-answer list
CacheRecord **kalistptr = &KnownAnswerList;
mDNSu32 answerforecast = 0;
// Put query questions in this packet
for (q = m->Questions; q; q=q->next)
if (q->SendQNow == intf->InterfaceID)
@ -4050,7 +4050,7 @@ mDNSlocal void SendQueries(mDNS *const m)
else LogMsg("SendQueries: How did we fail to have space for the Update record %##s (%s)?",
rr->resrec.name.c, DNSTypeName(rr->resrec.rrtype));
}
if (queryptr > query.data)
{
if ((query.h.flags.b[0] & kDNSFlag0_TC) && query.h.numQuestions > 1)
@ -4389,14 +4389,14 @@ mDNSlocal CacheRecord *GetFreeCacheRR(mDNS *const m, mDNSu16 RDLength)
if (m->lock_rrcache) { LogMsg("GetFreeCacheRR ERROR! Cache already locked!"); return(mDNSNULL); }
m->lock_rrcache = 1;
// If we have no free records, ask the client layer to give us some more memory
if (!m->rrcache_free && m->MainCallback)
{
if (m->rrcache_totalused != m->rrcache_size)
LogMsg("GetFreeCacheRR: count mismatch: m->rrcache_totalused %lu != m->rrcache_size %lu",
m->rrcache_totalused, m->rrcache_size);
// We don't want to be vulnerable to a malicious attacker flooding us with an infinite
// number of bogus records so that we keep growing our cache until the machine runs out of memory.
// To guard against this, if we're actively using less than 1/32 of our cache, then we
@ -4407,7 +4407,7 @@ mDNSlocal CacheRecord *GetFreeCacheRR(mDNS *const m, mDNSu16 RDLength)
else
m->MainCallback(m, mStatus_GrowCache);
}
// If we still have no free records, recycle all the records we can.
// Enumerating the entire cache is moderately expensive, so when we do it, we reclaim all the records we can in one pass.
if (!m->rrcache_free)
@ -4439,7 +4439,7 @@ mDNSlocal CacheRecord *GetFreeCacheRR(mDNS *const m, mDNSu16 RDLength)
debugf("Clear unused records; m->rrcache_totalused was %lu; now %lu", oldtotalused, m->rrcache_totalused);
#endif
}
if (m->rrcache_free) // If there are records in the free list, take one
{
r = m->rrcache_free;
@ -4456,7 +4456,7 @@ mDNSlocal CacheRecord *GetFreeCacheRR(mDNS *const m, mDNSu16 RDLength)
}
mDNSPlatformMemZero(r, sizeof(*r));
r->resrec.rdata = (RData*)&r->rdatastorage; // By default, assume we're usually going to be using local storage
if (RDLength > InlineCacheRDSize) // If RDLength is too big, allocate extra storage
{
r->resrec.rdata = (RData*)mDNSPlatformMemAllocate(sizeofRDataHeader + RDLength);
@ -4543,7 +4543,7 @@ mDNSlocal void mDNS_Unlock(mDNS *const m)
{
// Decrement mDNS_busy
m->mDNS_busy--;
// Check for locking failures
if (m->mDNS_busy != m->mDNS_reentrancy)
LogMsg("mDNS_Unlock: Locking failure! mDNS_busy (%ld) != mDNS_reentrancy (%ld)", m->mDNS_busy, m->mDNS_reentrancy);
@ -4570,13 +4570,13 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
verbosedebugf("mDNS_Execute");
if (m->CurrentQuestion) LogMsg("mDNS_Execute: ERROR! m->CurrentQuestion already set");
// 1. If we're past the probe suppression time, we can clear it
if (m->SuppressProbes && m->timenow - m->SuppressProbes >= 0) m->SuppressProbes = 0;
// 2. If it's been more than ten seconds since the last probe failure, we can clear the counter
if (m->NumFailedProbes && m->timenow - m->ProbeFailTime >= mDNSPlatformOneSecond * 10) m->NumFailedProbes = 0;
// 3. Purge our cache of stale old records
if (m->rrcache_size && m->timenow - m->NextCacheCheck >= 0)
{
@ -4584,11 +4584,11 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
m->NextCacheCheck = m->timenow + 0x3FFFFFFF;
for (slot = 0; slot < CACHE_HASH_SLOTS; slot++) CheckCacheExpiration(m, slot);
}
// 4. See if we can answer any of our new local questions from the cache
for (i=0; m->NewQuestions && i<1000; i++) AnswerNewQuestion(m);
if (i >= 1000) debugf("mDNS_Execute: AnswerNewQuestion exceeded loop limit");
for (i=0; m->DiscardLocalOnlyRecords && i<1000; i++) DiscardLocalOnlyRecords(m);
if (i >= 1000) debugf("mDNS_Execute: DiscardLocalOnlyRecords exceeded loop limit");
@ -4609,7 +4609,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
// them to advance to announcing state, and we want those to be included in any announcements we send out.
// Finally, we send responses, including the previously mentioned records that just completed probing
m->SuppressSending = 0;
// 6. Send Query packets. This may cause some probing records to advance to announcing state
if (m->timenow - m->NextScheduledQuery >= 0 || m->timenow - m->NextScheduledProbe >= 0) SendQueries(m);
if (m->timenow - m->NextScheduledQuery >= 0)
@ -4622,7 +4622,7 @@ mDNSexport mDNSs32 mDNS_Execute(mDNS *const m)
LogMsg("mDNS_Execute: SendQueries didn't send all its probes; will try again in one second");
m->NextScheduledProbe = m->timenow + mDNSPlatformOneSecond;
}
// 7. Send Response packets, including probing records just advanced to announcing state
if (m->timenow - m->NextScheduledResponse >= 0) SendResponses(m);
if (m->timenow - m->NextScheduledResponse >= 0)
@ -4773,7 +4773,7 @@ mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const m
DNSQuestion q;
ptr = getQuestion(query, ptr, end, InterfaceID, &q); // get the question...
if (!ptr) return(mDNSNULL);
for (rr=ResponseRecords; rr; rr=rr->NextResponse) // and search our list of proposed answers
{
if (rr->NR_AnswerTo == ptr) // If we're going to generate a record answering this question
@ -4784,7 +4784,7 @@ mDNSlocal mDNSu8 *GenerateUnicastResponse(const DNSMessage *const query, const m
}
}
}
if (response->h.numQuestions == 0) { LogMsg("GenerateUnicastResponse: ERROR! Why no questions?"); return(mDNSNULL); }
}
@ -4834,7 +4834,7 @@ mDNSlocal int CompareRData(AuthRecord *our, CacheRecord *pkt)
if (pktptr >= pktend) return(+1); // Packet data ran out first; We won
if (*pktptr > *ourptr) return(-1); // Our data is numerically lower; We lost
if (*pktptr < *ourptr) return(+1); // Packet data is numerically lower; We won
debugf("CompareRData: How did we get here?");
return(-1);
}
@ -5007,7 +5007,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
QuestionNeedsMulticastResponse = QueryWasMulticast && !LegacyQuery && !(pktq.qclass & kDNSQClass_UnicastResponse);
// Clear the UnicastResponse flag -- don't want to confuse the rest of the code that follows later
pktq.qclass &= ~kDNSQClass_UnicastResponse;
// Note: We use the m->CurrentRecord mechanism here because calling ResolveSimultaneousProbe
// can result in user callbacks which may change the record list and/or question list.
// Also note: we just mark potential answer records here, without trying to build the
@ -5072,7 +5072,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
rr->MPExpectingKA = mDNStrue;
}
}
// Check if this question is the same as any of mine.
// We only do this for non-truncated queries. Right now it would be too complicated to try
// to keep track of duplicate suppression state between multiple packets, especially when we
@ -5106,7 +5106,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
if (rr->Additional2 && ResourceRecordIsValidInterfaceAnswer(rr->Additional2, InterfaceID))
AddRecordToResponseList(&nrp, rr->Additional2, rr);
// For SRV records, automatically add the Address record(s) for the target host
if (rr->resrec.rrtype == kDNSType_SRV)
for (rr2=m->ResourceRecords; rr2; rr2=rr2->next) // Scan list of resource records
@ -5172,7 +5172,7 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
{ *eap = rr->NextInKAList; rr->NextInKAList = mDNSNULL; }
else eap = &rr->NextInKAList;
}
// See if this Known-Answer is a surprise to us. If so, we shouldn't suppress our own query.
if (!ourcacherr)
{
@ -5202,14 +5202,14 @@ mDNSlocal mDNSu8 *ProcessQuery(mDNS *const m, const DNSMessage *const query, con
if (rr->NR_AnswerTo)
{
mDNSBool SendMulticastResponse = mDNSfalse;
// If it's been a while since we multicast this, then send a multicast response for conflict detection, etc.
if (m->timenow - (rr->LastMCTime + TicksTTL(rr)/4) >= 0) SendMulticastResponse = mDNStrue;
// If the client insists on a multicast response, then we'd better send one
if (rr->NR_AnswerTo == (mDNSu8*)~0) SendMulticastResponse = mDNStrue;
else if (rr->NR_AnswerTo) HaveUnicastAnswer = mDNStrue;
if (SendMulticastResponse)
{
// If we're already planning to send this on another interface, just send it on all interfaces
@ -5292,14 +5292,14 @@ exit:
rr->NR_AnswerTo = mDNSNULL;
rr->NR_AdditionalTo = mDNSNULL;
}
while (ExpectedAnswers)
{
CacheRecord *rr;
rr = ExpectedAnswers;
ExpectedAnswers = rr->NextInKAList;
rr->NextInKAList = mDNSNULL;
// For non-truncated queries, we can definitively say that we should expect
// to be seeing a response for any records still left in the ExpectedAnswers list
if (!(query->h.flags.b[0] & kDNSFlag0_TC))
@ -5337,7 +5337,7 @@ exit:
mDNSu32 remain = (mDNSu32)(RRExpireTime(rr) - m->timenow) / 4;
if (remain > 240 * (mDNSu32)mDNSPlatformOneSecond)
remain = 240 * (mDNSu32)mDNSPlatformOneSecond;
// Only show debugging message if this record was not about to expire anyway
if (RRExpireTime(rr) - m->timenow > 4 * mDNSPlatformOneSecond)
debugf("ProcessQuery: (MPQ) UAQ %lu MPQ %lu MPKA %lu mDNS_Reconfirm() for %s",
@ -5348,13 +5348,13 @@ exit:
rr->MPUnansweredQ = 0; // Clear MPQ/MPKA statistics
rr->MPUnansweredKA = 0;
rr->MPExpectingKA = mDNSfalse;
if (remain < kDefaultReconfirmTimeForNoAnswer)
remain = kDefaultReconfirmTimeForNoAnswer;
mDNS_Reconfirm_internal(m, rr, remain);
}
}
while (DupQuestions)
{
int i;
@ -5365,7 +5365,7 @@ exit:
debugf("ProcessQuery: Recorded DSI for %##s (%s) on %p/%s %d", q->qname.c, DNSTypeName(q->qtype), InterfaceID,
srcaddr->type == mDNSAddrType_IPv4 ? "v4" : "v6", i);
}
return(responseptr);
}
@ -5375,7 +5375,7 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg,
{
DNSMessage response;
const mDNSu8 *responseend = mDNSNULL;
verbosedebugf("Received Query from %#-15a:%d to %#-15a:%d on 0x%.8X with %2d Question%s %2d Answer%s %2d Authorit%s %2d Additional%s",
srcaddr, (mDNSu16)srcport.b[0]<<8 | srcport.b[1],
dstaddr, (mDNSu16)dstport.b[0]<<8 | dstport.b[1],
@ -5384,7 +5384,7 @@ mDNSlocal void mDNSCoreReceiveQuery(mDNS *const m, const DNSMessage *const msg,
msg->h.numAnswers, msg->h.numAnswers == 1 ? ", " : "s,",
msg->h.numAuthorities, msg->h.numAuthorities == 1 ? "y, " : "ies,",
msg->h.numAdditionals, msg->h.numAdditionals == 1 ? "" : "s");
responseend = ProcessQuery(m, msg, end, srcaddr, InterfaceID,
(srcport.NotAnInteger != MulticastDNSPort.NotAnInteger), mDNSAddrIsDNSMulticast(dstaddr), &response);
@ -5410,7 +5410,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
const mDNSu8 *ptr = LocateAnswers(response, end); // We ignore questions (if any) in a DNS response packet
CacheRecord *CacheFlushRecords = mDNSNULL;
CacheRecord **cfp = &CacheFlushRecords;
// All records in a DNS response packet are treated as equally valid statements of truth. If we want
// to guard against spoof responses, then the only credible protection against that is cryptographic
// security, e.g. DNSSEC., not worring about which section in the spoof packet contained the record
@ -5542,7 +5542,7 @@ mDNSlocal void mDNSCoreReceiveResponse(mDNS *const m,
verbosedebugf("Found record size %5d interface %p already in cache: %s",
pkt.r.resrec.rdlength, InterfaceID, GetRRDisplayString(m, &pkt.r));
rr->TimeRcvd = m->timenow;
if (pkt.r.resrec.RecordType & kDNSRecordTypePacketUniqueMask)
{
// If this packet record has the kDNSClass_UniqueRRSet flag set, then add it to our cache flushing list
@ -5647,20 +5647,20 @@ mDNSexport void mDNSCoreReceive(mDNS *const m, DNSMessage *const msg, const mDNS
const mDNSu8 StdQ = kDNSFlag0_QR_Query | kDNSFlag0_OP_StdQuery;
const mDNSu8 StdR = kDNSFlag0_QR_Response | kDNSFlag0_OP_StdQuery;
const mDNSu8 QR_OP = (mDNSu8)(msg->h.flags.b[0] & kDNSFlag0_QROP_Mask);
// Read the integer parts which are in IETF byte-order (MSB first, LSB second)
mDNSu8 *ptr = (mDNSu8 *)&msg->h.numQuestions;
msg->h.numQuestions = (mDNSu16)((mDNSu16)ptr[0] << 8 | ptr[1]);
msg->h.numAnswers = (mDNSu16)((mDNSu16)ptr[2] << 8 | ptr[3]);
msg->h.numAuthorities = (mDNSu16)((mDNSu16)ptr[4] << 8 | ptr[5]);
msg->h.numAdditionals = (mDNSu16)((mDNSu16)ptr[6] << 8 | ptr[7]);
if (!m) { LogMsg("mDNSCoreReceive ERROR m is NULL"); return; }
// We use zero addresses and all-ones addresses at various places in the code to indicate special values like "no address"
// If we accept and try to process a packet with zero or all-ones source address, that could really mess things up
if (!mDNSAddressIsValid(srcaddr)) { debugf("mDNSCoreReceive ignoring packet from %#a", srcaddr); return; }
mDNS_Lock(m);
if (QR_OP == StdQ) mDNSCoreReceiveQuery (m, msg, end, srcaddr, srcport, dstaddr, dstport, InterfaceID);
else if (QR_OP == StdR) mDNSCoreReceiveResponse(m, msg, end, srcaddr, dstaddr, InterfaceID, ttl);
@ -5999,7 +5999,7 @@ mDNSlocal void FoundServiceInfo(mDNS *const m, DNSQuestion *question, const Reso
{
ServiceInfoQuery *query = (ServiceInfoQuery *)question->QuestionContext;
if (!AddRecord) return;
if (answer->rrtype == kDNSType_A)
{
query->info->ip.type = mDNSAddrType_IPv4;
@ -6154,7 +6154,7 @@ mDNSexport void mDNS_SetupResourceRecord(AuthRecord *rr, RData *RDataStorage, mD
rr->resrec.RecordType = RecordType;
rr->HostTarget = mDNSfalse;
// Field Group 2: Transient state for Authoritative Records (set in mDNS_Register_internal)
// Field Group 3: Transient state for Cache Records (set in mDNS_Register_internal)
@ -6207,7 +6207,7 @@ mDNSexport mStatus mDNS_Update(mDNS *const m, AuthRecord *const rr, mDNSu32 newt
if (rr->UpdateCallback)
rr->UpdateCallback(m, rr, n); // ...and let the client free this memory, if necessary
}
if (rr->AnnounceCount < ReannounceCount)
rr->AnnounceCount = ReannounceCount;
rr->ThisAPInterval = DefaultAPIntervalForRecordType(rr->resrec.RecordType);
@ -6258,7 +6258,7 @@ mDNSlocal void mDNS_AdvertiseInterface(mDNS *const m, NetworkInterfaceInfo *set)
char buffer[256];
NetworkInterfaceInfo *primary = FindFirstAdvertisedInterface(m);
if (!primary) primary = set; // If no existing advertised interface, this new NetworkInterfaceInfo becomes our new primary
mDNS_SetupResourceRecord(&set->RR_A, mDNSNULL, set->InterfaceID, kDNSType_A, kDefaultTTLforUnique, kDNSRecordTypeUnique, HostNameCallback, set);
mDNS_SetupResourceRecord(&set->RR_PTR, mDNSNULL, set->InterfaceID, kDNSType_PTR, kDefaultTTLforUnique, kDNSRecordTypeKnownUnique, mDNSNULL, mDNSNULL);
mDNS_SetupResourceRecord(&set->RR_HINFO, mDNSNULL, set->InterfaceID, kDNSType_HINFO, kDefaultTTLforUnique, kDNSRecordTypeUnique, mDNSNULL, mDNSNULL);
@ -6422,7 +6422,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
mDNSBool FirstOfType = mDNStrue;
NetworkInterfaceInfo **p = &m->HostInterfaces;
mDNS_Lock(m);
// Assume this interface will be active
set->InterfaceActive = mDNStrue;
set->IPv4Available = (set->ip.type == mDNSAddrType_IPv4 && set->TxAndRx);
@ -6451,7 +6451,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
set->next = mDNSNULL;
*p = set;
debugf("mDNS_RegisterInterface: InterfaceID %p %#a %s", set->InterfaceID, &set->ip,
set->InterfaceActive ?
"not represented in list; marking active and retriggering queries" :
@ -6477,7 +6477,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
q->RecentAnswers = 0;
if (ActiveQuestion(q)) m->NextScheduledQuery = m->timenow;
}
// For all our non-specific authoritative resource records (and any dormant records specific to this interface)
// we now need them to re-probe if necessary, and then re-announce.
for (rr = m->ResourceRecords; rr; rr=rr->next)
@ -6505,7 +6505,7 @@ mDNSexport mStatus mDNS_RegisterInterface(mDNS *const m, NetworkInterfaceInfo *s
mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *set)
{
NetworkInterfaceInfo **p = &m->HostInterfaces;
mDNSBool revalidate = mDNSfalse;
// If this platform has the "phantom interfaces" known bug (e.g. Jaguar), we have to revalidate records every
// time an interface goes away. Otherwise, when you disconnect the Ethernet cable, the system reports that it
@ -6542,7 +6542,7 @@ mDNSexport void mDNS_DeregisterInterface(mDNS *const m, NetworkInterfaceInfo *se
set->InterfaceID);
intf->InterfaceActive = mDNStrue;
UpdateInterfaceProtocols(m, intf);
// See if another representative *of the same type* exists. If not, we mave have gone from
// dual-stack to v6-only (or v4-only) so we need to reconfirm which records are still valid.
for (intf = m->HostInterfaces; intf; intf = intf->next)
@ -6617,7 +6617,7 @@ mDNSlocal void ServiceCallback(mDNS *const m, AuthRecord *const rr, mStatus resu
mDNS_DeregisterService(m, sr); // Unlink the records from our list
return;
}
if (result == mStatus_MemFree)
{
// If the PTR record or any of the subtype PTR record are still in the process of deregistering,
@ -6662,13 +6662,13 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
sr->Conflict = mDNSfalse;
if (host && host->c[0]) sr->Host = *host;
else sr->Host.c[0] = 0;
// Initialize the AuthRecord objects to sane values
mDNS_SetupResourceRecord(&sr->RR_ADV, mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeAdvisory, ServiceCallback, sr);
mDNS_SetupResourceRecord(&sr->RR_PTR, mDNSNULL, InterfaceID, kDNSType_PTR, kDefaultTTLforShared, kDNSRecordTypeShared, ServiceCallback, sr);
mDNS_SetupResourceRecord(&sr->RR_SRV, mDNSNULL, InterfaceID, kDNSType_SRV, kDefaultTTLforUnique, kDNSRecordTypeUnique, ServiceCallback, sr);
mDNS_SetupResourceRecord(&sr->RR_TXT, mDNSNULL, InterfaceID, kDNSType_TXT, kDefaultTTLforUnique, kDNSRecordTypeUnique, ServiceCallback, sr);
// If the client is registering an oversized TXT record,
// it is the client's responsibility to alloate a ServiceRecordSet structure that is large enough for it
if (sr->RR_TXT.resrec.rdata->MaxRDLength < txtlen)
@ -6682,7 +6682,7 @@ mDNSexport mStatus mDNS_RegisterService(mDNS *const m, ServiceRecordSet *sr,
if (ConstructServiceName(&sr->RR_PTR.resrec.name, mDNSNULL, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
if (ConstructServiceName(&sr->RR_SRV.resrec.name, name, type, domain) == mDNSNULL) return(mStatus_BadParamErr);
AssignDomainName(sr->RR_TXT.resrec.name, sr->RR_SRV.resrec.name);
// 1. Set up the ADV record rdata to advertise our service type
AssignDomainName(sr->RR_ADV.resrec.rdata->u.name, sr->RR_PTR.resrec.name);
@ -6756,9 +6756,9 @@ mDNSexport mStatus mDNS_AddRecordToService(mDNS *const m, ServiceRecordSet *sr,
mDNS_SetupResourceRecord(&extra->r, rdata, sr->RR_PTR.resrec.InterfaceID, extra->r.resrec.rrtype, ttl, kDNSRecordTypeUnique, ServiceCallback, sr);
AssignDomainName(extra->r.resrec.name, sr->RR_SRV.resrec.name);
extra->r.DependentOn = &sr->RR_SRV;
debugf("mDNS_AddRecordToService adding record to %##s", extra->r.resrec.name.c);
result = mDNS_Register(m, &extra->r);
if (!result) *e = extra;
return result;
@ -6775,7 +6775,7 @@ mDNSexport mStatus mDNS_RemoveRecordFromService(mDNS *const m, ServiceRecordSet
}
debugf("mDNS_RemoveRecordFromService removing record from %##s", extra->r.resrec.name.c);
*e = (*e)->next;
return(mDNS_Deregister(m, &extra->r));
}
@ -6796,7 +6796,7 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS
}
debugf("Reregistering as %#s", newname->c);
if (sr->RR_SRV.HostTarget == mDNSfalse && sr->Host.c[0]) host = &sr->Host;
err = mDNS_RegisterService(m, sr, newname, &type, &domain,
host, sr->RR_SRV.resrec.rdata->u.srv.port, sr->RR_TXT.resrec.rdata->u.txt.c, sr->RR_TXT.resrec.rdlength,
sr->SubTypes, sr->NumSubTypes,
@ -6811,7 +6811,7 @@ mDNSexport mStatus mDNS_RenameAndReregisterService(mDNS *const m, ServiceRecordS
extras = extras->next;
err = mDNS_AddRecordToService(m, sr, e, e->r.resrec.rdata, e->r.resrec.rroriginalttl);
}
return(err);
}
@ -6837,14 +6837,14 @@ mDNSexport mStatus mDNS_DeregisterService(mDNS *const m, ServiceRecordSet *sr)
ExtraResourceRecord *e;
mDNS_Lock(m);
e = sr->Extras;
// We use mDNS_Dereg_repeat because, in the event of a collision, some or all of the
// SRV, TXT, or Extra records could have already been automatically deregistered, and that's okay
mDNS_Deregister_internal(m, &sr->RR_SRV, mDNS_Dereg_repeat);
mDNS_Deregister_internal(m, &sr->RR_TXT, mDNS_Dereg_repeat);
mDNS_Deregister_internal(m, &sr->RR_ADV, mDNS_Dereg_normal);
// We deregister all of the extra records, but we leave the sr->Extras list intact
// in case the client wants to do a RenameAndReregister and reinstate the registration
while (e)
@ -6924,9 +6924,9 @@ mDNSexport mStatus mDNS_Init(mDNS *const m, mDNS_PlatformSupport *const p,
mDNSs32 timenow;
mStatus result = mDNSPlatformTimeInit(&timenow);
if (result != mStatus_NoError) return(result);
if (!rrcachestorage) rrcachesize = 0;
m->p = p;
m->KnownBugs = 0;
m->AdvertiseLocalAddresses = AdvertiseLocalAddresses;
@ -7037,7 +7037,7 @@ mDNSexport void mDNS_Close(mDNS *const m)
LogMsg("*** ERROR *** rrcache_active %lu != m->rrcache_active %lu", rrcache_active, m->rrcache_active);
m->Questions = mDNSNULL; // We won't be answering any more questions!
for (intf = m->HostInterfaces; intf; intf = intf->next)
if (intf->Advertise)
mDNS_DeadvertiseInterface(m, intf);
@ -7065,7 +7065,7 @@ mDNSexport void mDNS_Close(mDNS *const m)
else
while (m->ResourceRecords)
SendResponses(m);
mDNS_Unlock(m);
debugf("mDNS_Close: mDNSPlatformClose");
mDNSPlatformClose(m);

View File

@ -2,14 +2,14 @@
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@ -17,7 +17,7 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
*
* @APPLE_LICENSE_HEADER_END@
*
* Formatting notes:
@ -146,6 +146,7 @@ First checkin
#include <sys/uio.h>
#include <netinet/in.h>
#include "daapd.h"
#include "err.h"
#include "mDNSUNP.h"
@ -481,7 +482,7 @@ static int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interface
static const int kOn = 1;
static const int kIntTwoFiveFive = 255;
static const unsigned char kByteTwoFiveFive = 255;
(void) interfaceIndex; // Unused
assert(intfAddr != NULL);
assert(sktPtr != NULL);
@ -576,8 +577,8 @@ static int SetupSocket(struct sockaddr *intfAddr, mDNSIPPort port, int interface
bindAddr.sin_port = port.NotAnInteger;
bindAddr.sin_addr.s_addr = INADDR_ANY; // Want to receive multicasts AND unicasts on this socket
err = bind(*sktPtr, (struct sockaddr *) &bindAddr, sizeof(bindAddr));
if (err < 0) {
err = errno;
if (err < 0) {
err = errno;
DPRINTF(E_LOG,L_REND,"bind: %s\n",strerror(errno));
}
}

View File

@ -2,14 +2,14 @@
* Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
@ -17,7 +17,7 @@
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
*
* @APPLE_LICENSE_HEADER_END@
Change History (most recent first):
@ -91,11 +91,12 @@ First checkin
#include <unistd.h>
#include <stdio.h>
#include "daapd.h"
#include "err.h"
/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
other platforms don't even have that include file. So,
if we haven't yet got a definition, let's try to find
/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
other platforms don't even have that include file. So,
if we haven't yet got a definition, let's try to find
<sys/sockio.h>.
*/
@ -103,7 +104,7 @@ First checkin
#include <sys/sockio.h>
#endif
/* sockaddr_dl is only referenced if we're using IP_RECVIF,
/* sockaddr_dl is only referenced if we're using IP_RECVIF,
so only include the header in that case.
*/
@ -122,7 +123,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sinptr;
// int index;
#if defined(AF_INET6) && defined(HAVE_IPV6)
struct sockaddr_in6 *sinptr6;
#endif
@ -132,7 +133,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
sockfd = -1;
buf = NULL;
ifihead = NULL;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
goto gotError;
@ -183,9 +184,9 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
ptr += sizeof(struct ifreq); /* for next one in buffer */
#endif
DPRINTF(E_DBG,L_REND,"intf name=%s AF=%d, flags=%08x\n", ifr->ifr_name, ifr->ifr_addr.sa_family,ifr->ifr_flags);
if (ifr->ifr_addr.sa_family != family)
continue; /* ignore if not desired address family */
@ -203,7 +204,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) {
goto gotError;
}
flags = ifrcopy.ifr_flags;
if ((flags & IFF_UP) == 0)
continue; /* ignore if interface not up */
@ -270,7 +271,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
if (ifi->ifi_addr == NULL) {
goto gotError;
}
/* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
/* We need to strip that out */
if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr))
@ -285,7 +286,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases)
}
}
goto done;
gotError:
if (ifihead != NULL) {
free_ifi_info(ifihead);
@ -323,7 +324,7 @@ free_ifi_info(struct ifi_info *ifihead)
}
/* end free_ifi_info */
ssize_t
ssize_t
recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp)
{
@ -358,10 +359,10 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
*salenptr = msg.msg_namelen; /* pass back results */
if (pktp) {
/* 0.0.0.0, i/f = -1 */
/* We set the interface to -1 so that the caller can
tell whether we returned a meaningful value or
just some default. Previously this code just
set the value to 0, but I'm concerned that 0
/* We set the interface to -1 so that the caller can
tell whether we returned a meaningful value or
just some default. Previously this code just
set the value to 0, but I'm concerned that 0
might be a valid interface value.
*/
memset(pktp, 0, sizeof(struct my_in_pktinfo));
@ -393,11 +394,11 @@ struct in_pktinfo
struct in_addr ipi_addr;
};
#endif
if (cmptr->cmsg_level == IPPROTO_IP &&
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_PKTINFO) {
struct in_pktinfo *tmp;
struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
sin->sin_family = AF_INET;
sin->sin_addr = tmp->ipi_addr;
@ -411,7 +412,7 @@ struct in_pktinfo
if (cmptr->cmsg_level == IPPROTO_IP &&
cmptr->cmsg_type == IP_RECVDSTADDR) {
struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
sin->sin_family = AF_INET;
sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
sin->sin_port = 0;
@ -435,11 +436,11 @@ struct in_pktinfo
#endif
#if defined(IPV6_PKTINFO) && defined(HAVE_IPV6)
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
cmptr->cmsg_type == IPV6_PKTINFO) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
sin6->sin6_family = AF_INET6;
sin6->sin6_len = sizeof(*sin6);
sin6->sin6_addr = ip6_info->ipi6_addr;

View File

@ -76,6 +76,8 @@
#include <sys/wait.h>
#endif
#include "daapd.h"
#include "conf.h"
#include "configfile.h"
#include "err.h"
@ -578,6 +580,7 @@ int main(int argc, char *argv[]) {
DPRINTF(E_LOG,L_MAIN|L_DB|L_SCAN,"Scanned %d songs (was %d) in "
"%d seconds\n",song_count,old_song_count,
time(NULL)-start_time);
conf_dispose_array(mp3_dir_array);
}
os_wait(MAIN_SLEEP_INTERVAL);
@ -610,6 +613,7 @@ int main(int argc, char *argv[]) {
DPRINTF(E_LOG,L_MAIN,"Done!\n");
os_deinit();
mem_dump();
return EXIT_SUCCESS;
}

203
src/memdebug.c Normal file
View File

@ -0,0 +1,203 @@
/**
* memory debugging
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include "err.h"
#include "util.h"
#ifdef DEBUG_MEM
typedef struct debugnode_t {
char *file;
int line;
int size;
void *ptr;
struct debugnode_t *next;
} DEBUGNODE;
DEBUGNODE _debug_memlist = { NULL, 0, 0, NULL, NULL };
void debug_free(char *file, int line, void *ptr);
void *debug_malloc(char *file, int line, size_t size);
void *debug_realloc(char *file, int line, void *ptr, size_t size);
void *debug_calloc(char *file, int line, size_t count, size_t size);
char *debug_strdup(char *file, int line, const char *str);
void debug_dump(void);
/**
* find a ptr in the node list, assuming the list is already
* locked.
*/
DEBUGNODE *_debug_find_ptr(void *ptr) {
DEBUGNODE *prev, *current;
prev = &_debug_memlist;
current = prev->next;
while(current) {
if(current->ptr == ptr)
return current;
prev = current;
current = current->next;
}
return NULL;
}
void *_debug_alloc_nolock(char *file, int line, int size) {
DEBUGNODE *pnew;
pnew = (DEBUGNODE *)malloc(sizeof(DEBUGNODE));
if(!pnew)
DPRINTF(E_FATAL,L_MISC,"Malloc failed in _debug_alloc\n");
pnew->file = strdup(file);
pnew->line = line;
pnew->size = size;
pnew->ptr = malloc(size);
if(!pnew->ptr)
DPRINTF(E_FATAL,L_MISC,"Malloc failed in _debug_alloc\n");
pnew->next = _debug_memlist.next;
_debug_memlist.next = pnew;
return pnew->ptr;
}
void *_debug_alloc(char *file, int line, int size) {
void *ptr;
util_mutex_lock(l_memdebug);
ptr = _debug_alloc_nolock(file, line, size);
util_mutex_unlock(l_memdebug);
return ptr;
}
void debug_dump(void) {
DEBUGNODE *current;
uint32_t size = 0;
int blocks = 0;
if(!_debug_memlist.next) {
DPRINTF(E_LOG,L_MISC,"No leaked memory!\n");
return;
}
current = _debug_memlist.next;
while(current) {
size += current->size;
blocks++;
current = current->next;
}
DPRINTF(E_WARN,L_MISC,"Leaked %d bytes in %d blocks\n",size, blocks);
current = _debug_memlist.next;
while(current) {
DPRINTF(E_WARN,L_MISC,"%d bytes: %s, line %d\n", current->size,
current->file, current->line);
util_hexdump(current->ptr,current->size);
current = current->next;
}
}
void debug_free(char *file, int line, void *ptr) {
DEBUGNODE *prev, *current;
util_mutex_lock(l_memdebug);
prev = &_debug_memlist;
current = prev->next;
while(current) {
if(current->ptr == ptr) {
/* found it */
break;
}
prev = current;
current = current->next;
}
if(!current) {
util_mutex_unlock(l_memdebug);
DPRINTF(E_FATAL,L_MISC,"Attempt to free an unallocated ptr: %s, %d\n",
file, line);
}
prev->next = current->next;
util_mutex_unlock(l_memdebug);
if(current) {
if(current->file)
free(current->file);
if(current->ptr)
free(current->ptr);
free(current);
}
return;
}
void *debug_malloc(char *file, int line, size_t size) {
void *ptr;
ptr = _debug_alloc(file,line,size);
return ptr;
}
void *debug_realloc(char *file, int line, void *ptr, size_t size) {
void *new_ptr;
DEBUGNODE *old_node;
int copy_size;
util_mutex_lock(l_memdebug);
old_node = _debug_find_ptr(ptr);
if(!old_node) {
util_mutex_unlock(l_memdebug);
DPRINTF(E_FATAL,L_MISC,"Attempt to realloc invalid ptr: %s, %d\n",
file, line);
}
new_ptr = _debug_alloc_nolock(file, line, size);
util_mutex_unlock(l_memdebug);
copy_size = old_node->size;
if(size < copy_size)
copy_size=size;
memcpy(new_ptr,old_node->ptr,copy_size);
debug_free(file, line, old_node->ptr);
return new_ptr;
}
void *debug_calloc(char *file, int line, size_t count, size_t size) {
void *ptr;
ptr = debug_malloc(file, line, count * size);
memset(ptr,0,count *size);
return ptr;
}
char *debug_strdup(char *file, int line, const char *str) {
void *ptr;
int size;
size = strlen(str);
ptr = debug_malloc(file, line, size + 1);
strcpy(ptr,str);
return ptr;
}
#endif

23
src/memdebug.h Normal file
View File

@ -0,0 +1,23 @@
/*
* $Id: $
*/
#ifdef DEBUG_MEM
# define free(ptr) debug_free(__FILE__,__LINE__,(ptr))
# define malloc(size) debug_malloc(__FILE__,__LINE__,(size))
# define realloc(ptr, size) debug_realloc(__FILE__,__LINE__,(ptr),(size))
# define calloc(count,size) debug_calloc(__FILE__,__LINE__,(count),(size))
# define strdup(str) debug_strdup(__FILE__,__LINE__,(str))
# define mem_dump() debug_dump()
extern void debug_free(char *file, int line, void *ptr);
extern void *debug_malloc(char *file, int line, size_t size);
extern void *debug_realloc(char *file, int line, void *ptr, size_t size);
extern void *debug_calloc(char *file, int line, size_t count, size_t size);
extern void *debug_strdup(char *file, int line, const char *str);
extern void debug_dump(void);
#else
# define mem_dump()
#endif

View File

@ -46,8 +46,8 @@
#endif
#include <sys/stat.h>
#include "conf.h"
#include "daapd.h"
#include "conf.h"
#include "db-generic.h"
#include "err.h"
#include "mp3-scanner.h"

View File

@ -52,9 +52,9 @@
#include "CoreFoundation/CoreFoundation.h"
#endif
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "daapd.h"
#include "os.h"
/** You say po-tay-to, I say po-tat-o */

View File

@ -8,11 +8,11 @@
#include <string.h>
#include <unistd.h>
#include "daapd.h"
#include "conf.h"
#include "db-generic.h"
#include "err.h"
#include "smart-parser.h"
#include "daapd.h"
CONFIG config;
char *scan_winamp_genre[] = { NULL };
@ -57,7 +57,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr,"could not read config file: %s\n",configfile);
exit(1);
}
if(debuglevel) {
printf("Setting debug level to %d\n",debuglevel);
err_setlevel(debuglevel);

View File

@ -45,6 +45,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "daapd.h"
#include "conf.h"
#include "configfile.h"
#include "db-generic.h"

View File

@ -33,6 +33,8 @@ static char rcsid[]="$Id$";
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include "daapd.h"
#include "redblack.h"
#define assert(expr)
@ -152,7 +154,7 @@ RB_STATIC struct RB_ENTRY(tree) *RB_ENTRY(init)(void)
if ((retval=(struct RB_ENTRY(tree) *) malloc(sizeof(struct RB_ENTRY(tree))))==NULL)
return(NULL);
#ifndef RB_CUSTOMIZE
retval->rb_cmp=cmp;
retval->rb_config=config;
@ -171,7 +173,7 @@ RB_ENTRY(destroy)(struct RB_ENTRY(tree) *rbinfo)
if (rbinfo->rb_root!=RBNULL)
RB_ENTRY(_destroy)(rbinfo->rb_root);
free(rbinfo);
}
#endif /* no_destroy */
@ -192,7 +194,7 @@ RB_ENTRY(search)(const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *rbinfo)
#endif /* no_search */
#ifndef no_find
RB_STATIC const RB_ENTRY(data_t) *
RB_STATIC const RB_ENTRY(data_t) *
RB_ENTRY(find)(const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *rbinfo)
{
struct RB_ENTRY(node) *x;
@ -211,7 +213,7 @@ RB_ENTRY(find)(const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *rbinfo)
#endif /* no_find */
#ifndef no_delete
RB_STATIC const RB_ENTRY(data_t) *
RB_STATIC const RB_ENTRY(data_t) *
RB_ENTRY(delete)(const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *rbinfo)
{
struct RB_ENTRY(node) *x;
@ -257,7 +259,7 @@ RB_ENTRY(openlist)(const struct RB_ENTRY(tree) *rbinfo)
return(RB_ENTRY(_openlist)(rbinfo->rb_root));
}
RB_STATIC const RB_ENTRY(data_t) *
RB_STATIC const RB_ENTRY(data_t) *
RB_ENTRY(readlist)(RBLIST *rblistp)
{
if (rblistp==NULL)
@ -277,7 +279,7 @@ RB_ENTRY(closelist)(RBLIST *rblistp)
#endif /* no_readlist */
#ifndef no_lookup
RB_STATIC const RB_ENTRY(data_t) *
RB_STATIC const RB_ENTRY(data_t) *
RB_ENTRY(lookup)(int mode, const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *rbinfo)
{
struct RB_ENTRY(node) *x;
@ -502,10 +504,10 @@ RB_ENTRY(_lookup)(int mode, const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *
if (found && (mode==RB_LUEQUAL || mode==RB_LUGTEQ || mode==RB_LULTEQ))
return(x);
if (!found && (mode==RB_LUEQUAL || mode==RB_LUNEXT || mode==RB_LUPREV))
return(RBNULL);
if (mode==RB_LUGTEQ || (!found && mode==RB_LUGREAT))
{
if (cmp>0)
@ -527,7 +529,7 @@ RB_ENTRY(_lookup)(int mode, const RB_ENTRY(data_t) *key, struct RB_ENTRY(tree) *
if (mode==RB_LUPREV || (found && mode==RB_LULESS))
return(RB_ENTRY(_predecessor)(x));
/* Shouldn't get here */
return(RBNULL);
}
@ -893,7 +895,7 @@ RB_ENTRY(_openlist)(const struct RB_ENTRY(node) *rootp)
return(rblistp);
}
static const RB_ENTRY(data_t) *
static const RB_ENTRY(data_t) *
RB_ENTRY(_readlist)(RBLIST *rblistp)
{
const RB_ENTRY(data_t) *key=NULL;
@ -1026,7 +1028,7 @@ RB_ENTRY(_check1)(struct RB_ENTRY(node) *x)
if (rb_check1(x->left))
return(1);
}
}
if (x->right != RBNULL)
{
@ -1038,7 +1040,7 @@ RB_ENTRY(_check1)(struct RB_ENTRY(node) *x)
if (rb_check1(x->right))
return(1);
}
}
return(0);
}
@ -1087,7 +1089,7 @@ RB_ENTRY(dumptree)(struct RB_ENTRY(node) *x, int n)
RB_ENTRY(dumptree)(x->left, n);
RB_ENTRY(dumptree)(x->right, n);
}
}
}
#endif

View File

@ -41,6 +41,7 @@
#include <avahi-common/timeval.h>
#include <avahi-common/malloc.h>
#include "daapd.h"
#include "err.h"
static AvahiClient *mdns_client = NULL;

View File

@ -32,6 +32,7 @@
#include <howl.h>
#include <pthread.h>
#include "daapd.h"
#include "err.h"
#include "os-unix.h"
#include "rend-unix.h"
@ -79,11 +80,11 @@ int rend_private_init(char *user) {
return -1;
}
if(os_drop_privs(user))
if(os_drop_privs(user))
return -1;
DPRINTF(E_DBG,L_REND,"Starting polling thread\n");
if(pthread_create(&rend_tid,NULL,rend_pipe_monitor,NULL)) {
DPRINTF(E_FATAL,L_REND,"Could not start thread. Terminating\n");
/* should kill parent, too */
@ -129,7 +130,7 @@ void *rend_pipe_monitor(void* arg) {
/*
* rend_callback
*
* This gets called from the main thread when there is a
* This gets called from the main thread when there is a
* message waiting to be processed.
*/
void rend_callback(void) {

View File

@ -19,6 +19,7 @@
#include <sys/types.h>
#include "daapd.h"
#include "dns_sd.h"
#include "err.h"
@ -28,7 +29,7 @@ static volatile int rend_stop_flag = 0;
//static volatile int rend_timeout = 100000000; /* select timeout */
static volatile int rend_timeout=2;
static volatile int rend_count=0;
static pthread_mutex_t rend_mutex=PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t rend_mutex=PTHREAD_MUTEX_INITIALIZER;
typedef struct tag_rend_entry {
DNSServiceRef client;
struct tag_rend_entry *next;
@ -37,9 +38,9 @@ static REND_ENTRY rend_clients = { NULL, NULL };
/* Forwards */
void *rend_mainthread(void *arg);
void DNSSD_API rend_reg_reply(DNSServiceRef client, const DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain, void *context);
void DNSSD_API rend_reg_reply(DNSServiceRef client, const DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain, void *context);
/* Typedefs */
typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
@ -95,7 +96,7 @@ void *rend_mainthread(void *arg) {
FD_SET(DNSServiceRefSockFD(current->client),&readfds);
}
current = current->next;
current = current->next;
}
rend_unlock();
@ -117,13 +118,13 @@ void *rend_mainthread(void *arg) {
}
rend_unlock();
if (err) {
DPRINTF(E_LOG,L_REND,"DNSServiceProcessResult returned %d\n", err);
rend_stop_flag = 1;
if (err) {
DPRINTF(E_LOG,L_REND,"DNSServiceProcessResult returned %d\n", err);
rend_stop_flag = 1;
}
} else if (result == 0) {
DPRINTF(E_SPAM,L_REND,"rendezvous: tick!\n");
// myTimerCallBack();
} else {
DPRINTF(E_INF,L_REND,"select() returned %d errno %d %s\n", result, errno, strerror(errno));
@ -135,7 +136,7 @@ void *rend_mainthread(void *arg) {
while(current) {
if(current->client)
DNSServiceRefDeallocate(current->client);
current = current->next;
current = current->next;
}
rend_unlock();
return NULL;
@ -191,7 +192,7 @@ int rend_register(char *name, char *type, int port, char *iface, char *txt) {
DNSServiceRegister(&pnew->client,0,kDNSServiceInterfaceIndexAny,name,type,"local",NULL,
port_netorder,(uint16_t)strlen(txt),txt,rend_reg_reply, NULL);
/* throw off a new thread work this */
if(!rend_count) {
if((err=pthread_create(&rend_tid,NULL,rend_mainthread,NULL))) {
@ -205,19 +206,19 @@ int rend_register(char *name, char *type, int port, char *iface, char *txt) {
return 0;
}
void DNSSD_API rend_reg_reply(DNSServiceRef client, const DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain, void *context)
void DNSSD_API rend_reg_reply(DNSServiceRef client, const DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *name,
const char *regtype, const char *domain, void *context)
{
DPRINTF(E_INF,L_REND,"Got a reply for %s.%s%s\n", name, regtype, domain);
switch (errorCode) {
case kDNSServiceErr_NoError:
DPRINTF(E_INF,L_REND,"Name now registered and active\n");
DPRINTF(E_INF,L_REND,"Name now registered and active\n");
break;
case kDNSServiceErr_NameConflict:
DPRINTF(E_FATAL,L_REND,"Rendezvous name in use, aborting...\n");
case kDNSServiceErr_NameConflict:
DPRINTF(E_FATAL,L_REND,"Rendezvous name in use, aborting...\n");
break;
default:
default:
DPRINTF(E_FATAL,L_REND,"Error %d\n", errorCode);
return;
}

View File

@ -4,14 +4,14 @@
*
* ** NOTICE **
*
* This code is written by (and is therefore copyright) Dr Kay Robbins
* (krobbins@cs.utsa.edu) and Dr. Steve Robbins (srobbins@cs.utsa.edu),
* and was released with unspecified licensing as part of their book
* This code is written by (and is therefore copyright) Dr Kay Robbins
* (krobbins@cs.utsa.edu) and Dr. Steve Robbins (srobbins@cs.utsa.edu),
* and was released with unspecified licensing as part of their book
* _UNIX_Systems_Programming_ (Prentice Hall, ISBN: 0130424110).
*
* Dr. Steve Robbins was kind enough to allow me to re-license this
* software as GPL. I would request that any bugs or problems with
* this code be brought to my attention (ron@pedde.com), and I will
* Dr. Steve Robbins was kind enough to allow me to re-license this
* software as GPL. I would request that any bugs or problems with
* this code be brought to my attention (ron@pedde.com), and I will
* submit appropriate patches upstream, should the problem be with
* the original code.
*
@ -52,6 +52,7 @@
# include <sys/wait.h>
#endif
#include "daapd.h"
#include "err.h"
#include "restart.h"
@ -169,7 +170,7 @@ ssize_t readblock(int fd, void *buf, size_t size) {
ssize_t bytesread;
size_t bytestoread;
size_t totalbytes;
for (bufp = buf, bytestoread = size, totalbytes = 0;
bytestoread > 0;
bufp += bytesread, bytestoread -= bytesread) {
@ -179,7 +180,7 @@ ssize_t readblock(int fd, void *buf, size_t size) {
if (bytesread == 0) {
errno = EINVAL;
return -1;
}
}
if ((bytesread) == -1 && (errno != EINTR))
return -1;
if (bytesread == -1)
@ -207,8 +208,8 @@ int readline(int fd, char *buf, int nbytes) {
if (buf[numread-1] == '\n') {
buf[numread] = '\0';
return numread;
}
}
}
}
errno = EINVAL;
return -1;
}
@ -231,8 +232,8 @@ int readlinetimed(int fd, char *buf, int nbytes, double seconds) {
if (buf[numread-1] == '\n') {
buf[numread] = '\0';
return numread;
}
}
}
}
errno = EINVAL;
return -1;
}
@ -277,11 +278,11 @@ int waitfdtimed(int fd, struct timeval end) {
fd_set readset;
int retval;
struct timeval timeout;
if ((fd < 0) || (fd >= FD_SETSIZE)) {
errno = EINVAL;
return -1;
}
}
FD_ZERO(&readset);
FD_SET(fd, &readset);
if (gettimeout(end, &timeout) == -1)

View File

@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#include "daapd.h"
#include "rxml.h"
/* Typedefs/Defines */
@ -125,7 +126,7 @@ int rxml_decode_string(char *string) {
* @param handler handler function for events
* @param udata opaque data structure to pass to the callback
*/
int rxml_open(RXMLHANDLE *vp, char *file,
int rxml_open(RXMLHANDLE *vp, char *file,
RXML_EVTHANDLER handler, void *udata) {
RXML *pnew;
@ -232,7 +233,7 @@ int rxml_parse(RXMLHANDLE vp) {
ph->line = 0;
textbuffer[0] = '\0';
/* walk through and read row by row */
@ -283,7 +284,7 @@ int rxml_parse(RXMLHANDLE vp) {
}
}
in_text=1;
in_text=1;
text_offset=0;
textbuffer[0] = '\0';
@ -298,7 +299,7 @@ int rxml_parse(RXMLHANDLE vp) {
ph->udata,tagbuffer);
/* send a follow-up end on a <tag/> - style tag */
if((single_tag) && (ph->handler))
if((single_tag) && (ph->handler))
ph->handler(RXML_EVT_END,ph->udata,tagbuffer);
offset++;
@ -307,7 +308,7 @@ int rxml_parse(RXMLHANDLE vp) {
default:
if((in_text) && (text_offset < (sizeof(textbuffer)-1))) {
/* get rid of EOL */
if((linebuffer[offset] != '\r') &&
if((linebuffer[offset] != '\r') &&
(linebuffer[offset] != '\n')) {
textbuffer[text_offset] = linebuffer[offset];
text_offset++;

View File

@ -34,6 +34,7 @@
#include <netinet/in.h>
#endif
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"
#include "scan-aac.h"
@ -50,9 +51,9 @@ time_t scan_aac_mac_to_unix_time(int t);
time_t scan_aac_mac_to_unix_time(int t) {
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return (t - (365L * 66L * 24L * 60L * 60L + 17L * 60L * 60L * 24L) +
(tz.tz_minuteswest * 60));
}
@ -93,12 +94,12 @@ off_t scan_aac_drilltoatom(FILE *aac_fp,char *atom_path,
return -1;
}
strncpy(atom_name, cur_p, 4);
atom_offset = scan_aac_findatom(aac_fp, file_size,
atom_offset = scan_aac_findatom(aac_fp, file_size,
atom_name, atom_length);
if (atom_offset == -1) {
return -1;
}
DPRINTF(E_SPAM,L_SCAN,"Found %s atom at off %ld.\n",
DPRINTF(E_SPAM,L_SCAN,"Found %s atom at off %ld.\n",
atom_name, ftell(aac_fp) - 8);
cur_p = strchr(cur_p, ':');
@ -145,7 +146,7 @@ long scan_aac_findatom(FILE *fin, long max_offset,
if(size <= 7) /* something not right */
return -1;
if(fread(atom,1,4,fin) != 4)
if(fread(atom,1,4,fin) != 4)
return -1;
if(strncasecmp(atom,which_atom,4) == 0) {
@ -196,7 +197,7 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
atom_offset=scan_aac_drilltoatom(fin, "moov:udta:meta:ilst", &atom_length);
if(atom_offset != -1) {
/* found the tag section - need to walk through now */
while(current_offset < (long)atom_length) {
if(fread((void*)&current_size,1,sizeof(int),fin) != sizeof(int))
break;
@ -204,13 +205,13 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
DPRINTF(E_SPAM,L_SCAN,"Current size: %d\n");
current_size=ntohl(current_size);
if(current_size <= 7) /* something not right */
break;
if(fread(current_atom,1,4,fin) != 4)
if(fread(current_atom,1,4,fin) != 4)
break;
DPRINTF(E_SPAM,L_SCAN,"Current Atom: %c%c%c%c\n",
current_atom[0],current_atom[1],current_atom[2],
current_atom[3]);
@ -222,16 +223,16 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
len=current_size-7; /* for ill-formed too-short tags */
if(len < 22)
len=22;
current_data=(char*)malloc(len); /* extra byte */
memset(current_data,0x00,len);
if(fread(current_data,1,current_size-8,fin) != current_size-8)
if(fread(current_data,1,current_size-8,fin) != current_size-8)
break;
if(!memcmp(current_atom,"\xA9" "nam",4)) { /* Song name */
pmp3->title=strdup((char*)&current_data[16]);
} else if(!memcmp(current_atom,"aART",4)) {
} else if(!memcmp(current_atom,"aART",4)) {
pmp3->album_artist=strdup((char*)&current_data[16]);
} else if(!memcmp(current_atom,"\xA9" "ART",4)) {
pmp3->artist=strdup((char*)&current_data[16]);
@ -253,7 +254,7 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
} else if(!memcmp(current_atom,"trkn",4)) {
us_data=*((unsigned short *)&current_data[18]);
us_data=ntohs(us_data);
pmp3->track=us_data;
us_data=*((unsigned short *)&current_data[20]);
@ -263,27 +264,27 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
} else if(!memcmp(current_atom,"disk",4)) {
us_data=*((unsigned short *)&current_data[18]);
us_data=ntohs(us_data);
pmp3->disc=us_data;
us_data=*((unsigned short *)&current_data[20]);
us_data=ntohs(us_data);
pmp3->total_discs=us_data;
} else if(!memcmp(current_atom,"\xA9" "day",4)) {
pmp3->year=atoi((char*)&current_data[16]);
} else if(!memcmp(current_atom,"gnre",4)) {
genre=(int)(*((char*)&current_data[17]));
genre--;
if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
genre=WINAMP_GENRE_UNKNOWN;
pmp3->genre=strdup(scan_winamp_genre[genre]);
} else if (!memcmp(current_atom, "cpil", 4)) {
pmp3->compilation = current_data[16];
}
free(current_data);
current_offset+=current_size;
}
@ -316,7 +317,7 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
/* DWB: use ms time instead of sec */
pmp3->song_length=(int)((samples * ms) / sample_size);
DPRINTF(E_DBG,L_SCAN,"Song length: %d seconds\n",
DPRINTF(E_DBG,L_SCAN,"Song length: %d seconds\n",
pmp3->song_length / 1000);
}
@ -324,7 +325,7 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
/* see if it is aac or alac */
atom_offset = scan_aac_drilltoatom(fin,
"moov:trak:mdia:minf:stbl:stsd:alac",
"moov:trak:mdia:minf:stbl:stsd:alac",
&atom_length);
if(atom_offset != -1) {
@ -336,10 +337,10 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
}
/* Get the sample rate from the 'mp4a' atom (timescale). This is also
found in the 'mdhd' atom which is a bit closer but we need to
found in the 'mdhd' atom which is a bit closer but we need to
navigate to the 'mp4a' atom anyways to get to the 'esds' atom. */
atom_offset=scan_aac_drilltoatom(fin,
"moov:trak:mdia:minf:stbl:stsd:mp4a",
atom_offset=scan_aac_drilltoatom(fin,
"moov:trak:mdia:minf:stbl:stsd:mp4a",
&atom_length);
if(atom_offset == -1) {
atom_offset=scan_aac_drilltoatom(fin,
@ -351,7 +352,7 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
fseek(fin, atom_offset + 32, SEEK_SET);
/* Timescale here seems to be 2 bytes here (the 2 bytes before it are
* "reserved") though the timescale in the 'mdhd' atom is 4. Not sure
* "reserved") though the timescale in the 'mdhd' atom is 4. Not sure
* how this is dealt with when sample rate goes higher than 64K. */
fread(buffer, sizeof(unsigned char), 2, fin);
@ -362,8 +363,8 @@ int scan_get_aacinfo(char *filename, MP3FILE *pmp3) {
/* Get the bit rate from the 'esds' atom. We are already positioned
in the parent atom so just scan ahead. */
atom_offset = scan_aac_findatom(fin,
atom_length-(ftell(fin)-atom_offset),
atom_offset = scan_aac_findatom(fin,
atom_length-(ftell(fin)-atom_offset),
"esds", &atom_length);
if (atom_offset != -1) {

View File

@ -33,6 +33,7 @@
#include <sys/types.h>
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"
@ -97,12 +98,12 @@ int scan_aif_parse_comm(FILE *infile, MP3FILE *pmp3) {
}
/* we'll brute the sample rate */
pmp3->samplerate = aif_from_be32((uint32_t*)&comm.sample_rate[2]) >> 16;
if(!pmp3->samplerate)
return TRUE;
pmp3->bitrate = pmp3->samplerate * comm.channels *
pmp3->bitrate = pmp3->samplerate * comm.channels *
((comm.sample_size + 7)/8)*8;
sec = pmp3->file_size / (pmp3->bitrate / 8);
@ -157,7 +158,7 @@ int scan_get_aifinfo(char *filename, MP3FILE *pmp3) {
done=1;
break;
}
/* fixup */
chunk.len = aif_from_be32(&chunk.len);

View File

@ -44,8 +44,8 @@
#include <sys/stat.h>
#include "restart.h"
#include "daapd.h"
#include "restart.h"
#include "err.h"
#include "mp3-scanner.h"

View File

@ -34,8 +34,8 @@
#include <string.h>
#include <time.h>
#include "conf.h"
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "mp3-scanner.h"

View File

@ -34,6 +34,7 @@
#include <netinet/in.h>
#endif
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"
#include "scan-aac.h"
@ -84,7 +85,7 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
atom_offset=scan_aac_drilltoatom(fin, "moov:udta:meta:ilst", &atom_length);
if(atom_offset != -1) {
/* found the tag section - need to walk through now */
while(current_offset < (long) atom_length) {
if(fread((void*)&current_size,1,sizeof(int),fin) != sizeof(int))
break;
@ -92,13 +93,13 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
DPRINTF(E_SPAM,L_SCAN,"Current size: %d\n");
current_size=ntohl(current_size);
if(current_size <= 7) /* something not right */
break;
if(fread(current_atom,1,4,fin) != 4)
if(fread(current_atom,1,4,fin) != 4)
break;
DPRINTF(E_SPAM,L_SCAN,"Current Atom: %c%c%c%c\n",
current_atom[0],current_atom[1],current_atom[2],
current_atom[3]);
@ -110,13 +111,13 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
len=current_size-7; /* for ill-formed too-short tags */
if(len < 22)
len=22;
current_data=(char*)malloc(len); /* extra byte */
memset(current_data,0x00,len);
if(fread(current_data,1,current_size-8,fin) != current_size-8)
if(fread(current_data,1,current_size-8,fin) != current_size-8)
break;
if(!memcmp(current_atom,"\xA9" "nam",4)) { /* Song name */
pmp3->title=strdup((char*)&current_data[16]);
} else if(!memcmp(current_atom,"\xA9" "ART",4)) {
@ -139,7 +140,7 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
} else if(!memcmp(current_atom,"trkn",4)) {
us_data=*((unsigned short *)&current_data[18]);
us_data=ntohs(us_data);
pmp3->track=us_data;
us_data=*((unsigned short *)&current_data[20]);
@ -149,27 +150,27 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
} else if(!memcmp(current_atom,"disk",4)) {
us_data=*((unsigned short *)&current_data[18]);
us_data=ntohs(us_data);
pmp3->disc=us_data;
us_data=*((unsigned short *)&current_data[20]);
us_data=ntohs(us_data);
pmp3->total_discs=us_data;
} else if(!memcmp(current_atom,"\xA9" "day",4)) {
pmp3->year=atoi((char*)&current_data[16]);
} else if(!memcmp(current_atom,"gnre",4)) {
genre=(int)(*((char*)&current_data[17]));
genre--;
if((genre < 0) || (genre > WINAMP_GENRE_UNKNOWN))
genre=WINAMP_GENRE_UNKNOWN;
pmp3->genre=strdup(scan_winamp_genre[genre]);
} else if (!memcmp(current_atom, "cpil", 4)) {
pmp3->compilation = current_data[16];
}
free(current_data);
current_offset+=current_size;
}
@ -202,17 +203,17 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
/* DWB: use ms time instead of sec */
pmp3->song_length=(int)((samples * ms) / sample_size);
DPRINTF(E_DBG,L_SCAN,"Song length: %d seconds\n",
DPRINTF(E_DBG,L_SCAN,"Song length: %d seconds\n",
pmp3->song_length / 1000);
}
pmp3->bitrate = 0;
/* Get the sample rate from the 'mp4a' atom (timescale). This is also
found in the 'mdhd' atom which is a bit closer but we need to
found in the 'mdhd' atom which is a bit closer but we need to
navigate to the 'mp4a' atom anyways to get to the 'esds' atom. */
atom_offset=scan_aac_drilltoatom(fin,
"moov:trak:mdia:minf:stbl:stsd:mp4a",
atom_offset=scan_aac_drilltoatom(fin,
"moov:trak:mdia:minf:stbl:stsd:mp4a",
&atom_length);
if(atom_offset == -1) {
atom_offset=scan_aac_drilltoatom(fin,
@ -224,7 +225,7 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
fseek(fin, atom_offset + 32, SEEK_SET);
/* Timescale here seems to be 2 bytes here (the 2 bytes before it are
* "reserved") though the timescale in the 'mdhd' atom is 4. Not sure
* "reserved") though the timescale in the 'mdhd' atom is 4. Not sure
* how this is dealt with when sample rate goes higher than 64K. */
fread(buffer, sizeof(unsigned char), 2, fin);
@ -235,8 +236,8 @@ int scan_get_mp4info(char *filename, MP3FILE *pmp3) {
/* Get the bit rate from the 'esds' atom. We are already positioned
in the parent atom so just scan ahead. */
atom_offset = scan_aac_findatom(fin,
atom_length-(ftell(fin)-atom_offset),
atom_offset = scan_aac_findatom(fin,
atom_length-(ftell(fin)-atom_offset),
"esds", &atom_length);
if (atom_offset != -1) {

View File

@ -31,6 +31,7 @@
#include <string.h>
#include <taglib/tag_c.h>
#include "daapd.h"
#include "mp3-scanner.h"
#include "err.h"

View File

@ -20,6 +20,8 @@
#include <string.h>
#include <sys/stat.h>
#include <vorbis/vorbisfile.h>
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"

View File

@ -30,6 +30,7 @@
#include <stdlib.h>
#include <string.h>
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"

View File

@ -30,6 +30,7 @@
#include <string.h>
#include <fcntl.h>
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"

View File

@ -32,6 +32,7 @@
#include <stdlib.h>
#include <string.h>
#include "daapd.h"
#include "mp3-scanner.h"
#include "restart.h"
#include "err.h"

View File

@ -467,6 +467,12 @@ int scan_xml_playlist(char *filename) {
}
rbdestroy(scan_xml_db);
MAYBEFREE(scan_xml_itunes_version);
MAYBEFREE(scan_xml_itunes_base_path);
MAYBEFREE(scan_xml_itunes_decoded_base_path);
MAYBEFREE(scan_xml_real_base_path);
return retval;
}
@ -956,6 +962,7 @@ int scan_xml_playlists_section(int action, char *info) {
}
dont_scan=0;
state=XML_PL_ST_EXPECTING_PL_TRACKLIST;
MAYBEFREE(current_name);
return XML_STATE_PLAYLISTS;
}
if(action == RXML_EVT_BEGIN)
@ -967,8 +974,7 @@ int scan_xml_playlists_section(int action, char *info) {
if(action == RXML_EVT_TEXT) {
/* got the value we were hoping for */
if(next_value == XML_PL_NEXT_VALUE_NAME) {
if(current_name)
free(current_name);
MAYBEFREE(current_name);
current_name = strdup(info);
DPRINTF(E_DBG,L_SCAN,"Found playlist: %s\n",current_name);
/* disallow specific playlists */

View File

@ -29,8 +29,8 @@
#include <string.h>
#include <unistd.h>
#include "conf.h"
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "mp3-scanner.h"
@ -47,7 +47,7 @@ extern int scan_get_mp3info(char *filename, MP3FILE *pmp3);
extern int scan_get_urlinfo(char *filename, MP3FILE *pmp3);
extern int scan_get_aifinfo(char *filename, MP3FILE *pmp3);
/*
/*
* Typedefs
*/
typedef struct scannerlist_tag {
@ -137,7 +137,7 @@ void usage(int errorcode) {
fprintf(stderr,"options:\n\n");
fprintf(stderr," -d level set debuglevel (9 is highest)\n");
fprintf(stderr," -c config read config file\n");
fprintf(stderr,"\n\n");
exit(errorcode);
}
@ -158,7 +158,7 @@ int main(int argc, char *argv[]) {
} else {
av0 = argv[0];
}
while((option = getopt(argc, argv, "d:c:")) != -1) {
switch(option) {
case 'd':
@ -167,13 +167,13 @@ int main(int argc, char *argv[]) {
case 'c':
configfile=optarg;
break;
default:
fprintf(stderr,"Error: unknown option (%c)\n\n",option);
usage(-1);
}
}
argc -= optind;
argv += optind;

View File

@ -4,8 +4,8 @@
#include <stdlib.h>
#include <string.h>
#include "conf.h"
#include "daapd.h"
#include "conf.h"
#include "err.h"
#include "os.h"
#include "plugin.h"
@ -23,7 +23,7 @@ void usage(void) {
fprintf(stderr," -f file file to transcode\n");
fprintf(stderr," -p plugin plugin to use\n");
fprintf(stderr," -t codectype\n");
fprintf(stderr,"\n\n");
exit(-1);
}

View File

@ -4,14 +4,14 @@
*
* ** NOTICE **
*
* This code is written by (and is therefore copyright) Dr Kay Robbins
* (krobbins@cs.utsa.edu) and Dr. Steve Robbins (srobbins@cs.utsa.edu),
* and was released with unspecified licensing as part of their book
* This code is written by (and is therefore copyright) Dr Kay Robbins
* (krobbins@cs.utsa.edu) and Dr. Steve Robbins (srobbins@cs.utsa.edu),
* and was released with unspecified licensing as part of their book
* _UNIX_Systems_Programming_ (Prentice Hall, ISBN: 0130424110).
*
* Dr. Steve Robbins was kind enough to allow me to re-license this
* software as GPL. I would request that any bugs or problems with
* this code be brought to my attention (ron@pedde.com), and I will
* Dr. Steve Robbins was kind enough to allow me to re-license this
* software as GPL. I would request that any bugs or problems with
* this code be brought to my attention (ron@pedde.com), and I will
* submit appropriate patches upstream, should the problem be with
* the original code.
*
@ -42,6 +42,8 @@
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include "daapd.h"
#include "uici.h"
#ifndef MAXBACKLOG
@ -69,7 +71,7 @@ static int u_ignore_sigpipe() {
act.sa_handler = SIG_IGN;
if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) == -1)
return -1;
}
}
return 0;
}
@ -83,30 +85,30 @@ static int u_ignore_sigpipe() {
* -1 on error and sets errno
*/
int u_open(u_port_t port) {
int error;
int error;
struct sockaddr_in server;
int sock;
int true = 1;
if ((u_ignore_sigpipe() == -1) ||
((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1))
return -1;
return -1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&true,
sizeof(true)) == -1) {
error = errno;
while ((close(sock) == -1) && (errno == EINTR));
while ((close(sock) == -1) && (errno == EINTR));
errno = error;
return -1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons((short)port);
if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) ||
(listen(sock, MAXBACKLOG) == -1)) {
error = errno;
while ((close(sock) == -1) && (errno == EINTR));
while ((close(sock) == -1) && (errno == EINTR));
errno = error;
return -1;
}
@ -142,10 +144,10 @@ int u_accept(int fd, struct in_addr *hostaddr) {
while (((retval =
accept(fd, (struct sockaddr *)(&netclient), &len)) == -1) &&
(errno == EINTR))
;
;
if (retval == -1)
return retval;
*hostaddr = netclient.sin_addr;
return retval;
}
@ -169,7 +171,7 @@ int u_connect(u_port_t port, char *hostn) {
struct hostent *phe;
/* fix broken name resolution for hosts beginning with a
/* fix broken name resolution for hosts beginning with a
* digit, plus get rid of hostname lookup stuff
*/
if(inet_addr(hostn) == INADDR_NONE) {
@ -201,11 +203,11 @@ int u_connect(u_port_t port, char *hostn) {
(errno == EINTR) ) {
FD_ZERO(&sockset);
FD_SET(sock, &sockset);
}
}
}
if (retval == -1) {
error = errno;
while ((close(sock) == -1) && (errno == EINTR));
while ((close(sock) == -1) && (errno == EINTR));
errno = error;
return -1;
}

View File

@ -31,7 +31,6 @@ int _util_initialized=0;
/* Forwards */
//int _util_xtoy(unsigned char *dbuffer, size_t dlen, unsigned char *sbuffer, size_t slen, char *from, char *to);
void _util_hexdump(unsigned char *block, int len);
void _util_mutex_init(void);
/**
@ -399,7 +398,7 @@ int _util_xtoy(unsigned char *dbuffer, size_t dlen, unsigned char *sbuffer, size
}
*/
void _util_hexdump(unsigned char *block, int len) {
void util_hexdump(unsigned char *block, int len) {
char charmap[256];
int index;
int row, offset;
@ -429,7 +428,7 @@ void _util_hexdump(unsigned char *block, int len) {
strcat(output,tmp);
}
fprintf(stderr,"%s\n",output);
DPRINTF(E_LOG,L_MISC,"%s\n",output);
}
}

View File

@ -19,6 +19,7 @@ typedef enum {
l_err,
l_conf,
l_plugin,
l_memdebug,
l_last
} lock_t;
@ -46,6 +47,7 @@ extern int util_utf8toutf16(unsigned char *utf16, int dlen, unsigned char *utf8,
extern int util_utf16toutf8(unsigned char *utf8, int dlen, unsigned char *utf16, int len);
extern int util_utf16_byte_len(unsigned char *utf16);
extern void util_hexdump(unsigned char *block, int len);
#endif /* _UTIL_H_ */

View File

@ -27,6 +27,7 @@
#include <windows.h>
#include <stdio.h>
#include "daapd.h"
#include "messages.h"
static HANDLE elog_handle = NULL;

View File

@ -43,7 +43,7 @@
char *av0;
#if 0
#if 0
/* need better longopt detection in configure.in */
struct option longopts[] =
{ { "help", 0, NULL, 'h' },
@ -130,7 +130,7 @@ size_t parse_hdr(unsigned char *hdr, size_t hdr_len,
sample_rate = GET_WAV_INT32(hdr + 24);
sample_bit_length = GET_WAV_INT16(hdr + 34);
data_length = GET_WAV_INT32(hdr + 20 + format_data_length + 4);
if ((format_data_length != 16) ||
(compression_code != 1) ||
(channel_count < 1) ||
@ -271,11 +271,11 @@ int main(int argc, char **argv)
while ((c = getopt(argc, argv, "hl:o:s:")) != -1) {
#endif
switch(c) {
case 'h':
case 'h':
usage(0);
/*NOTREACHED*/
break;
case 'l':
sec = strtoul(optarg, &end, 10);
if ((optarg[0] == '-') || (end == optarg) || ((end[0] != '\0') && (end[0] != '.'))) {
@ -284,7 +284,7 @@ int main(int argc, char **argv)
} else if (*end == '.') {
char tmp[7];
int i;
memset(tmp, '0', sizeof (tmp) - 1);
tmp[sizeof (tmp) - 1] = '\0';
for (i = 0; (i < (sizeof (tmp) - 1)) && (isdigit(end[i+1])); i++)
@ -306,7 +306,7 @@ int main(int argc, char **argv)
exit(-1);
}
break;
case 's':
samples = strtoul(optarg, &end, 10);
if ((optarg[0] == '-') || (end == optarg) || (end[0] != '\0')) {
@ -322,7 +322,7 @@ int main(int argc, char **argv)
exit(-1);
}
break;
case 'o':
offset = strtoul(optarg, &end, 10);
if ((*optarg == '-') || (end == optarg) || (*end != '\0')) {
@ -330,13 +330,13 @@ int main(int argc, char **argv)
exit(-1);
}
break;
default:
fprintf(stderr, "%s: Bad command line option -%c.\n", av0, optopt);
usage(-1);
}
}
argc -= optind;
argv += optind;
@ -373,7 +373,7 @@ int main(int argc, char **argv)
memmove(hdr, hdr + offset, hdr_len - offset);
hdr_len -= offset;
offset = 0;
}
}
if (offset > 0) {
offset -= hdr_len;

View File

@ -41,6 +41,7 @@
# include <sys/socket.h>
#endif
#include "daapd.h"
#include "err.h"
#include "restart.h"
#include "webserver.h"

View File

@ -29,10 +29,11 @@
#include <sys/stat.h>
#include <sys/types.h>
#include "daapd.h"
#include "configfile.h"
#include "conf.h"
#include "db-generic.h"
#include "daapd.h"
#include "err.h"
#include "mp3-scanner.h"
#include "os.h"