/*=========================================================================*/ SLPDDatabaseEntry *SLPDDatabaseEntryAlloc() /* Allocates and initializes a database entry. */ /* */ /* Returns - zero on success or non-zero on error. */ /*=========================================================================*/ { SLPDDatabaseEntry *entry; /* Allocate the entry. */ entry = (SLPDDatabaseEntry *)malloc(sizeof(SLPDDatabaseEntry)); if(entry == NULL) { return NULL; } memset(entry,0,sizeof(SLPDDatabaseEntry)); /* Initialize the entry. */ #ifdef USE_PREDICATES if(SLPAttrAlloc("en", NULL, SLP_FALSE, &entry->attr)) { SLPDDatabaseEntryFree(entry); entry = 0; } #endif return entry; }
/*=========================================================================*/ int SLPDDatabaseReInit(const char* regfile) /* Re-initialize the database with changed registrations from a regfile. */ /* */ /* regfile (IN) the regfile to register. */ /* */ /* Returns - zero on success or non-zero on error. */ /*=========================================================================*/ { /* Delete all static registrations */ SLPDDatabaseEntry* del; SLPDDatabaseEntry* entry = (SLPDDatabaseEntry*)G_DatabaseList.head; /* delete all the static entries */ while(entry) { if(entry->regtype & SLPDDATABASE_REG_STATIC) { del = entry; entry = (SLPDDatabaseEntry*) entry->listitem.next; SLPDDatabaseEntryFree((SLPDDatabaseEntry*)SLPListUnlink(&G_DatabaseList, (SLPListItem*)del)); } else { entry = (SLPDDatabaseEntry*) entry->listitem.next; } } /* reload all the static entries by calling the init function */ return SLPDDatabaseInit(regfile); }
/*=========================================================================*/ void SLPDDatabaseDeinit() /* De-initialize the database. Free all resources taken by registrations */ /*=========================================================================*/ { while(G_DatabaseList.count) { SLPDDatabaseEntryFree((SLPDDatabaseEntry*)SLPListUnlink(&G_DatabaseList, G_DatabaseList.head)); } }
/*=========================================================================*/ void SLPDDatabaseAge(int seconds, int ageall) /* Agea the database entries and clears new and deleted entry lists */ /* */ /* seconds (IN) the number of seconds to age each entry by */ /* */ /* ageall (IN) age even entries with SLP_LIFETIME_MAX */ /* */ /* Returns - None */ /*=========================================================================*/ { SLPDDatabaseEntry* entry; SLPDDatabaseEntry* del = 0; /* Age the database */ entry = (SLPDDatabaseEntry*)G_DatabaseList.head; while(entry) { /*-----------------------------------------------------------*/ /* OK, if an entry is local and has a lifetime of */ /* SLP_LIFETIME_MAXIMUM then it must never ever ever be aged */ /*-----------------------------------------------------------*/ if(!(entry->regtype & SLPDDATABASE_REG_LOCAL && entry->lifetime == SLP_LIFETIME_MAXIMUM)) { /*---------------------------------------------------------*/ /* don't age services with lifetime > SLP_LIFETIME_MAXIMUM */ /* unless explicitly told to */ /*---------------------------------------------------------*/ if(ageall || entry->lifetime < SLP_LIFETIME_MAXIMUM) { entry->lifetime = entry->lifetime - seconds; if(entry->lifetime <= 0) { del = entry; } } } entry = (SLPDDatabaseEntry*)entry->listitem.next; if(del) { SLPDDatabaseEntryFree((SLPDDatabaseEntry*)SLPListUnlink(&G_DatabaseList,(SLPListItem*)del)); del = 0; } } }
/*=========================================================================*/ int SLPDDatabaseDeReg(SLPSrvDeReg* srvdereg) /* Remove a service registration from the database */ /* */ /* regfile - (IN) filename of the registration file to read into the */ /* database. Pass in NULL for no file. */ /* */ /* Returns - Zero on success. Non-zero if syntax error in registration */ /* file. */ /*=========================================================================*/ { SLPDDatabaseEntry* entry = (SLPDDatabaseEntry*)G_DatabaseList.head; while(entry) { if(SLPCompareString(entry->urllen, entry->url, srvdereg->urlentry.urllen, srvdereg->urlentry.url) == 0) { if(SLPIntersectStringList(entry->scopelistlen, entry->scopelist, srvdereg->scopelistlen, srvdereg->scopelist) > 0) { /* Log deregistration registration */ SLPDLogTraceReg("Deregistered",entry); SLPDDatabaseEntryFree((SLPDDatabaseEntry*)SLPListUnlink(&G_DatabaseList,(SLPListItem*)entry)); break; } } entry = (SLPDDatabaseEntry*) entry->listitem.next; } return 0; }
/*=========================================================================*/ SLPDDatabaseEntry* SLPDRegFileReadEntry(FILE* fd, SLPDDatabaseEntry** entry) /* A really big and nasty function that reads an entry SLPDDatabase entry */ /* from a file. Don't look at this too hard or you'll be sick */ /* */ /* fd (IN) file to read from */ /* */ /* entry (OUT) Address of a pointer that will be set to the location of */ /* a dynamically allocated SLPDDatabase entry. The entry */ /* must be freed */ /* */ /* Returns *entry or null on error. */ /*=========================================================================*/ { char* slider1; char* slider2; char line[4096]; /* give the out param a value */ *entry = 0; /*----------------------------------------------------------*/ /* read the next non-white non-comment line from the stream */ /*----------------------------------------------------------*/ do { slider1 = RegFileReadLine(fd,line,4096); if(slider1 == 0) { /* read through the whole file and found no entries */ return 0; } }while(*slider1 == 0x0d || *slider1 == 0x0a); /*---------------------------*/ /* Allocate a database entry */ /*---------------------------*/ *entry = SLPDDatabaseEntryAlloc(); if(entry == 0) { SLPFatal("Out of memory!\n"); return 0; } /* entries read from the .reg file are always local */ (*entry)->islocal = 1; /*---------------------*/ /* Parse the url-props */ /*---------------------*/ slider2 = strchr(slider1,','); if(slider2) { /* srvurl */ *slider2 = 0; /* squash comma to null terminate srvurl */ (*entry)->url = strdup(TrimWhitespace(slider1)); if((*entry)->url == 0) { SLPLog("Out of memory reading srvurl from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->urllen = strlen((*entry)->url); /* derive srvtype from srvurl */ (*entry)->srvtype = strstr(slider1,"://"); if((*entry)->srvtype == 0) { SLPLog("Looks like a bad url on regfile line ->%s",line); goto SLPD_ERROR; } *(*entry)->srvtype = 0; (*entry)->srvtype=strdup(TrimWhitespace(slider1)); (*entry)->srvtypelen = strlen((*entry)->srvtype); slider1 = slider2 + 1; /*lang*/ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate lang */ (*entry)->langtag = strdup(TrimWhitespace(slider1)); if((*entry)->langtag == 0) { SLPLog("Out of memory reading langtag from regfile line ->%s",line); goto SLPD_ERROR; }(*entry)->langtaglen = strlen((*entry)->langtag); slider1 = slider2 + 1; } else { SLPLog("Expected language tag near regfile line ->%s\n",line); goto SLPD_ERROR; } /* ltime */ slider2 = strchr(slider1,','); if(slider2) { *slider2 = 0; /* squash comma to null terminate ltime */ (*entry)->lifetime = atoi(slider1); slider1 = slider2 + 1; } else { (*entry)->lifetime = atoi(slider1); slider1 = slider2; } if((*entry)->lifetime < 1 || (*entry)->lifetime > 0xffff) { SLPLog("Invalid lifetime near regfile line ->%s\n",line); goto SLPD_ERROR; } /* get the srvtype if one was not derived by the srvurl*/ if((*entry)->srvtype == 0) { (*entry)->srvtype = strdup(TrimWhitespace(slider1)); if((*entry)->srvtype == 0) { SLPLog("Out of memory reading srvtype from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->srvtypelen = strlen((*entry)->srvtype); if((*entry)->srvtypelen == 0) { SLPLog("Expected to derive service-type near regfile line -> %s\n",line); goto SLPD_ERROR; } } } else { SLPLog("Expected to find srv-url near regfile line -> %s\n",line); goto SLPD_ERROR; } /*-------------------------------------------------*/ /* Read all the attributes including the scopelist */ /*-------------------------------------------------*/ *line=0; while(1) { if(RegFileReadLine(fd,line,4096) == 0) { break; } if(*line == 0x0d || *line == 0x0a) { break; } /* Check to see if it is the scopes line */ /* FIXME We can collapse the scope stuff into the value getting and * just make it a special case (do strcmp on the tag as opposed to the * line) of attribute getting. */ if(strncasecmp(line,"scopes",6) == 0) { /* found scopes line */ slider1 = line; slider2 = strchr(slider1,'='); if(slider2) { slider2++; if(*slider2) { /* just in case some idiot puts multiple scopes lines */ if((*entry)->scopelist) { SLPLog("scopes already defined previous to regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->scopelist=strdup(TrimWhitespace(slider2)); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding scopes from regfile line ->%s",line); goto SLPD_ERROR; } (*entry)->scopelistlen = strlen((*entry)->scopelist); } } } else { #ifdef USE_PREDICATES char *tag; /* Will point to the start of the tag. */ char *val; /* Will point to the start of the value. */ char *end; char *tag_end; tag = line; /*** Elide ws. ***/ while(isspace(*tag)) { tag++; } tag_end = tag; /*** Find tag end. ***/ while(*tag_end && (!isspace(*tag_end)) && (*tag_end != '=')) { tag_end++; } while(*tag_end && *tag_end != '=') { tag_end++; } *tag_end = 0; /*** Find value start. ***/ val = tag_end + 1; /*** Elide ws. ***/ while(isspace(*val)) { val++; } /*** Elide trailing ws. ***/ end = val; /** Find tag end. **/ while(*end != 0) { end++; } /*** Back up over trailing whitespace. ***/ end--; while(isspace(*end)) { *end = 0; /* Overwrite ws. */ end--; } SLPAttrSet_guess((*entry)->attr, tag, val, SLP_ADD); #else /* line contains an attribute (slow but it works)*/ /* TODO Fix this so we do not have to realloc memory each time! */ TrimWhitespace(line); (*entry)->attrlistlen += strlen(line) + 2; if((*entry)->attrlist == 0) { (*entry)->attrlist = malloc((*entry)->attrlistlen + 1); *(*entry)->attrlist = 0; } else { (*entry)->attrlist = realloc((*entry)->attrlist, (*entry)->attrlistlen + 2); strcat((*entry)->attrlist,","); } if((*entry)->attrlist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPD_ERROR; } strcat((*entry)->attrlist,"("); strcat((*entry)->attrlist,line); strcat((*entry)->attrlist,")"); #endif } } /* Set the scope set in properties if not is set */ if((*entry)->scopelist == 0) { (*entry)->scopelist=strdup(G_SlpdProperty.useScopes); if((*entry)->scopelist == 0) { SLPLog("Out of memory adding DEFAULT scope\n"); goto SLPD_ERROR; } (*entry)->scopelistlen = G_SlpdProperty.useScopesLen; } return *entry; SLPD_ERROR: if(*entry) { SLPDDatabaseEntryFree(*entry); *entry = 0; } return 0; }
/*=========================================================================*/ int SLPDDatabaseReg(SLPSrvReg* srvreg, unsigned int regtype) /* Add a service registration to the database */ /* */ /* srvreg - (IN) pointer to the SLPSrvReg to be added to the database */ /* */ /* regtype - (IN) registration types or'ed together: */ /* SLPDDATABASE_REG_FRESH */ /* SLPDDATABASE_REG_LOCAL */ /* SLPDDATABASE_REG_STATIC */ /* */ /* Returns - Zero on success. > 0 if something is wrong with srvreg */ /* < 0 if out of memory */ /* */ /* NOTE: All registrations are treated as fresh regardless of the */ /* setting of the fresh parameter */ /*=========================================================================*/ { int result = -1; SLPDDatabaseEntry* entry = (SLPDDatabaseEntry*)G_DatabaseList.head; /* Check to see if there is already an identical entry */ while(entry) { if(SLPCompareString(entry->urllen, entry->url, srvreg->urlentry.urllen, srvreg->urlentry.url) == 0) { if(SLPIntersectStringList(entry->scopelistlen, entry->scopelist, srvreg->scopelistlen, srvreg->scopelist) > 0) { SLPListUnlink(&G_DatabaseList,(SLPListItem*)entry); break; } } entry = (SLPDDatabaseEntry*) entry->listitem.next; } /* if no identical entry are found, create a new one */ if(entry == 0) { entry = SLPDDatabaseEntryAlloc(); if(entry == 0) { /* Out of memory */ goto FAILURE; } } /*----------------------------------------------------------------*/ /* copy info from the message from the wire to the database entry */ /*----------------------------------------------------------------*/ /* scope */ if(entry->scopelistlen >= srvreg->scopelistlen) { memcpy(entry->scopelist,srvreg->scopelist,srvreg->scopelistlen); } else { if(entry->scopelist) free(entry->scopelist); entry->scopelist = (char*)memdup(srvreg->scopelist,srvreg->scopelistlen); if(entry->scopelist == 0) goto FAILURE; } entry->scopelistlen = srvreg->scopelistlen; /* URL */ if(entry->urllen >= srvreg->urlentry.urllen) { memcpy(entry->url,srvreg->urlentry.url,srvreg->urlentry.urllen); } else { if(entry->url) free(entry->url); entry->url = (char*)memdup(srvreg->urlentry.url,srvreg->urlentry.urllen); if(entry->url == 0) goto FAILURE; } entry->urllen = srvreg->urlentry.urllen; /* lifetime */ entry->lifetime = srvreg->urlentry.lifetime; /* is local */ entry->regtype = regtype; /* SrvType */ if(entry->srvtypelen >= srvreg->srvtypelen) { memcpy(entry->srvtype,srvreg->srvtype,srvreg->srvtypelen); } else { if(entry->srvtype) free(entry->srvtype); entry->srvtype = (char*)memdup(srvreg->srvtype,srvreg->srvtypelen); if(entry->srvtype == 0) goto FAILURE; } entry->srvtypelen = srvreg->srvtypelen; /* Attributes */ if(srvreg->attrlistlen) { #ifdef USE_PREDICATES /* Tricky: perform an in place null termination of the attrlist */ /* Remember this squishes the authblock count */ ((char*)srvreg->attrlist)[srvreg->attrlistlen] = 0; if(SLPAttrFreshen(entry->attr, srvreg->attrlist) != SLP_OK) { result = 1; goto FAILURE; } /* Serialize all attributes into entry->attrlist */ if(entry->attrlist) { free(entry->attrlist); entry->attrlist = 0; entry->attrlistlen = 0; } if(SLPAttrSerialize(entry->attr, "", &entry->attrlist, entry->attrlistlen, &entry->attrlistlen, SLP_FALSE)) { goto FAILURE; } #else if(entry->attrlistlen >= srvreg->attrlistlen) { memcpy(entry->attrlist,srvreg->attrlist,srvreg->attrlistlen); } else { if(entry->attrlist) free(entry->attrlist); entry->attrlist = memdup(srvreg->attrlist,srvreg->attrlistlen); if(entry->attrlist == 0) goto FAILURE; } entry->attrlistlen = srvreg->attrlistlen; #endif } /* link the new (or modified) entry into the list */ SLPListLinkHead(&G_DatabaseList,(SLPListItem*)entry); /* traceReg if necessary */ SLPDLogTraceReg("Registered", entry); return 0; FAILURE: if(entry) { SLPDDatabaseEntryFree(entry); } return result; }