/** Associates a unicast IP address with an open SLP handle. * * Associates an IP address @p unicast_ip with a particular SLPHandle * @p hSLP. @p unicast_ip is the IP address of the SA/DA from which service * is requested. * * @param[in] hSLP - The SLPHandle with which the @p unicast_ip address is * to be associated. * * @param[in] unicast_ip - IP address of the SA/DA from which service * is requested. * * @return An SLPError code. */ SLPEXP SLPError SLPAPI SLPAssociateIP( SLPHandle hSLP, const char * unicast_ip) { #ifndef UNICAST_NOT_SUPPORTED SLPHandleInfo * handle; int result; SLP_ASSERT(hSLP != 0); SLP_ASSERT(*(unsigned int *)hSLP == SLP_HANDLE_SIG); SLP_ASSERT(unicast_ip != 0); SLP_ASSERT(*unicast_ip != 0); /* check for invalid parameters */ if (!hSLP || *(unsigned int*)hSLP != SLP_HANDLE_SIG || !unicast_ip || !*unicast_ip) return SLP_PARAMETER_BAD; handle = (SLPHandleInfo *)hSLP; handle->dounicast = SLP_TRUE; /** @todo Verify error conditions in associate ip address. */ result = SLPNetResolveHostToAddr(unicast_ip, &handle->ucaddr); if (SLPNetSetPort(&handle->ucaddr, (uint16_t)SLPPropertyAsInteger("net.slp.port")) != 0) return SLP_PARAMETER_BAD; return SLP_OK; #else (void)hSLP; (void)unicast_ip; return SLP_NOT_IMPLEMENTED; #endif /* ! UNICAST_NOT_SUPPORTED */ }
/** Gets the SNDBUF and RCVBUF sizes. * * @param[in] sndBufSize - A poniter to the integer to which global SNDBUF * value is assigned * @param[in] sndBufSize - A poniter to the integer to which global RCVBUF * value is assigned */ void SLPPropertyInternalGetSndRcvBufSize(int *sndBufSize, int *rcvBufSize) { SLP_ASSERT(sndBufSize); SLP_ASSERT(rcvBufSize); *sndBufSize = s_GlobalPropertyInternalSndBufSize; *rcvBufSize = s_GlobalPropertyInternalRcvBufSize; }
/** Associates an interface list with an SLP handle. * * Associates a list of interfaces @p McastIFList on which multicast needs * to be done with a particular SLPHandle @p hSLP. @p McastIFList is a comma * separated list of host interface IP addresses. * * @param[in] hSLP - The SLPHandle with which the interface list is to be * associated with. * * @param[in] McastIFList - A comma separated list of host interface IP * addresses on which multicast needs to be done. * * @return An SLPError code. */ SLPEXP SLPError SLPAPI SLPAssociateIFList( SLPHandle hSLP, const char * McastIFList) { #ifndef MI_NOT_SUPPORTED SLPHandleInfo * handle; SLP_ASSERT(hSLP != 0); SLP_ASSERT(*(unsigned int *)hSLP == SLP_HANDLE_SIG); SLP_ASSERT(McastIFList != 0); SLP_ASSERT(*McastIFList != 0); /* check for invalid parameters */ if (!hSLP || *(unsigned int*)hSLP != SLP_HANDLE_SIG || !McastIFList || !*McastIFList) return SLP_PARAMETER_BAD; handle = (SLPHandleInfo *)hSLP; /** @todo Copy the interface list, rather than just assign it. */ handle->McastIFList = McastIFList; return SLP_OK; #else (void)hSLP; (void)McastIFList; return SLP_NOT_IMPLEMENTED; #endif /* ! MI_NOT_SUPPORTED */ }
/** Returns local hostname. * * @param[out] hostfdn - A pointer to char pointer that is set to buffer * contining this machine's FDN. * @param[in] hostfdnLen - The length of @p hostfdn. * @param[in] numeric_only - A flag that forces the return of numeric * addresss. * @param[in] family - A hint: The family to get info for - can be * AF_INET, AF_INET6, or AF_UNSPEC for both. * * @remarks Caller must free returns @p hostfdn string with xfree. */ static int SLPNetGetThisHostname(char * hostfdn, size_t hostfdnLen, int numeric_only, int family) { char host[MAX_HOST_NAME]; struct addrinfo * ifaddr; struct addrinfo hints; int sts = 0; *hostfdn = 0; memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; hints.ai_family = family; if (gethostname(host, MAX_HOST_NAME) == 0) { sts = getaddrinfo(host, 0, &hints, &ifaddr); if (sts == 0) { /* If the hostname has a '.' then it is probably a qualified * domain name. If it is not then we better use the IP address. */ if (!numeric_only && strchr(host, '.')) strncpy(hostfdn, host, hostfdnLen); else sts = SLPNetAddrInfoToString(ifaddr, hostfdn, hostfdnLen); freeaddrinfo(ifaddr); } else SLP_ASSERT(1); /* TODO: what? assert(1) does nothing by definition! */ } return(sts); }
/** Convert an array of sockaddr_storage buffers to a comma-delimited list. * * Converts an array of sockaddr_storage buffers to a comma-delimited list of * addresses in presentation (string) format. * * @param[in] addrs - A pointer to array of sockaddr_storages to convert. * @param[in] addrcount - The number of elements in @p addrs. * @param[out] addrstr - The address in which to return a pointer to an * allocated comma-delimited list of addresses. * * @return Zero on success, non-zero (with errno set) on error. * * @remarks The caller must free @p addrstr when no longer needed. */ int SLPIfaceSockaddrsToString(struct sockaddr_storage const * addrs, int addrcount, char ** addrstr) { int i; SLP_ASSERT(addrs && addrcount && addrstr); if (!addrs || !addrcount || !addrstr) return (errno = EINVAL), -1; /* 40 is the maximum size of a string representation of * an IPv6 address (including the comma for the list) */ if ((*addrstr = xmalloc(addrcount * 40)) == 0) return (errno = ENOMEM), -1; **addrstr = 0; for (i = 0; i < addrcount; i++) { char buf[1024] = ""; SLPNetSockAddrStorageToString(&addrs[i], buf, sizeof(buf)); strcat(*addrstr, buf); if (i != addrcount - 1) strcat(*addrstr, ","); } return 0; }
/** Return a property by name. * * This is the internal property access routine. If the @p buffer and @p bufszp * parameters are used, then this routine will return a copy of the internal * value string. Otherwise it returns a pointer to the internal value string. * * @param[in] name - The name of the property to return. * @param[out] buffer - The address of storage for the requested property * value. This parameter is optional, and may be specified as NULL. * @param[in/out] bufszp - On entry, contains the size of @p buffer. On exit, * returns the number of bytes used or required. If @p buffer is too small * then this parameter returns the number of bytes required to return all * of the value. If too large, then this parameter returns the number of * bytes used in @p buffer. * * @return A pointer to the value of the property named by @p name. If the * @p buffer and @p bufszp parameters are specified, returns a pointer to * @p buffer, otherwise a pointer to the internal value buffer is returned. * * @remarks If an internal value string pointer is returned, then OpenSLP * is absolved of all responsibility regarding concurrent access to the * internal property database. * * @remarks The correct way to call this routine with a @p buffer parameter * is to size the buffer as appropriate, or size it to zero. This routine will * return the required size in *bufszp. Then call it again with a @p buffer * parameter of the returned size. If @p bufszp is returned containing any * value less than or equal to the originally specified size, then the caller * knows that the entire value was returned in @p buffer. */ char const * SLPPropertyGet(char const * name, char * buffer, size_t * bufszp) { SLPProperty * property; char const * retval = buffer; size_t bufsz = bufszp? *bufszp: 0; /* parameter sanity check */ SLP_ASSERT(name && (bufsz || !buffer)); if (!name || (buffer && !bufsz)) return 0; if (bufszp) *bufszp = 0; SLPMutexAcquire(s_PropDbLock); if ((property = Find(name)) != 0) { char const * value = property->value; if (buffer) { size_t valsz = strlen(value); *bufszp = valsz; if (valsz > bufsz) valsz = bufsz; memcpy(buffer, value, valsz - 1); buffer[valsz - 1] = 0; } else retval = value; } SLPMutexRelease(s_PropDbLock); return retval; }
/** Close an SLP handle. * * @param[in] hSLP - The handle to be closed. */ SLPEXP void SLPAPI SLPClose(SLPHandle hSLP) { SLPHandleInfo * handle = hSLP; /* Check for invalid parameters. */ SLP_ASSERT(handle != 0); SLP_ASSERT(handle->sig == SLP_HANDLE_SIG); if (!handle || handle->sig != SLP_HANDLE_SIG) return; #ifdef ENABLE_ASYNC_API if (handle->isAsync) SLPThreadWait(handle->th); #endif SLP_ASSERT(handle->inUse == 0); #ifdef ENABLE_SLPv2_SECURITY if (handle->hspi) SLPSpiClose(handle->hspi); #endif if (handle->langtag) xfree(handle->langtag); #ifndef UNICAST_NOT_SUPPORTED xfree(handle->unicastscope); if (handle->unicastsock != SLP_INVALID_SOCKET) closesocket(handle->dasock); #endif xfree(handle->sascope); if (handle->sasock != SLP_INVALID_SOCKET) closesocket(handle->sasock); xfree(handle->dascope); if (handle->dasock != SLP_INVALID_SOCKET) closesocket(handle->dasock); handle->sig = 0; xfree(handle); ExitUserAgentLibrary(); }
/** Set a new value for a property by name. * * If the value is NULL or empty, then simply erase the existing value and * return. * * @param[in] name - The name of the desired property. * @param[in] value - The new value to which @p name should be set or * NULL if the existing value should be removed. * @param[in] attrs - The attributes of this property - zero means no * attributes are assigned, other values include SLP_PA_USERSET and * SLP_PA_READONLY. * * @return Zero on success; -1 on error, with errno set. * * @remarks The @p attrs parameter contains a set of bit flags indicating * various attributes of the property. These attributes control write * permissions mostly. SLP_PA_USERSET means that an attribute may not * be changed by reading a configuration file, except in a complete * re-initialization scenario. SLP_PA_READONLY sounds like the same thing, * but it's not. The difference is that once set, properties with the * SLP_PA_READONLY attribute may NEVER be reset (again, except in a complete * re-initialization scenario), while properties with the SLP_PA_USERSET * attribute may only be reset by passing this same flag in @p attrs, * indicating that the caller is actually a user, and so has the right * to reset the property value. */ int SLPPropertySet(char const * name, char const * value, unsigned attrs) { size_t namesz, valuesz; SLPProperty * oldprop; SLPProperty * newprop = 0; /* we may be just removing the old */ bool update = true; /* reset if old property exists */ /* property names must not be null or empty */ SLP_ASSERT(name && *name); if (!name || !*name) return -1; if (value) { /* allocate property entry for this new value */ namesz = strlen(name) + 1; valuesz = strlen(value) + 1; if ((newprop = (SLPProperty*)xmalloc( sizeof(SLPProperty) - 1 + namesz + valuesz)) == 0) { errno = ENOMEM; return -1; } /* set internal pointers to trailing buffer space, copy values */ newprop->attrs = attrs; memcpy(newprop->name, name, namesz); newprop->value = newprop->name + namesz; memcpy(newprop->value, value, valuesz); } SLPMutexAcquire(s_PropDbLock); /* locate and possibly remove old property */ if ((oldprop = Find(name))!= 0) { /* update ONLY if old is clean, or new and old are user-settable . */ update = !oldprop->attrs || (oldprop->attrs == SLP_PA_USERSET && attrs == SLP_PA_USERSET); if (update) SLPListUnlink(&s_PropertyList, (SLPListItem *)oldprop); } /* link in new property, if specified and old property was removed */ if (newprop && update) SLPListLinkHead(&s_PropertyList, (SLPListItem *)newprop); SLPMutexRelease(s_PropDbLock); /* if old property was not removed, delete the new one instead */ xfree(update? oldprop: newprop); return update? 0: ((errno = EACCES), -1); }
/** Return an allocated copy of a property by name. * * @param[in] name - The name of the property to return. * * @return A pointer to an allocated buffer containing a copy of the property * named by @p name. * * @remarks The caller is responsible for releasing the memory returned by * calling xfree on it. */ char * SLPPropertyXDup(const char * name) { char * retval = 0; SLPProperty * property; /* parameter sanity check */ SLP_ASSERT(name); if (!name) return 0; SLPMutexAcquire(s_PropDbLock); if ((property = Find(name)) != 0) retval = xstrdup(property->value); SLPMutexRelease(s_PropDbLock); return retval; }
SLPError SLPAttrSerialize(SLPAttributes attr_h, const char * tags /* NULL terminated */, char ** out_buffer /* Where to write. if *out_buffer == NULL, space is alloc'd */, size_t bufferlen, /* Size of buffer. */ size_t * count, /* Bytes needed/written. */ SLPBoolean find_delta) { struct xx_TinyAttr * slp_attr = (struct xx_TinyAttr *) attr_h; /* Write the amount of space we need. */ if (count != NULL) { *count = slp_attr->attr_len + 1; /* For the null. */ } /* Check that we have somewhere to write to. */ if (bufferlen < slp_attr->attr_len + 1) { /* +1 for null. */ return SLP_BUFFER_OVERFLOW; } SLP_ASSERT(out_buffer != NULL && *out_buffer != NULL); /* Verify we have somewhere to write. */ /* Check for empty string. */ if (slp_attr->attr_len == 0) { **out_buffer = 0; /* Empty string. */ return SLP_OK; } /* Copy. */ strcpy(*out_buffer, slp_attr->attributes); return SLP_OK; }
/** Return a list of service matching a query specification. * * Issue the query for services on the language specific SLPHandle and * return the results through the @p callback. The parameters determine * the results. * * @param[in] hSLP - The language specific SLPHandle on which to search * for services. * @param[in] pcServiceType - The Service Type String, including authority * string if any, for the request, such as can be discovered using * SLPSrvTypes. This could be, for example "service:printer:lpr" or * "service:nfs". May not be the empty string or NULL. * @param[in] pcScopeList - A pointer to a char containing a comma-separated * list of scope names. Pass in NULL or the empty string ("") to find * services in all the scopes the local host is configured to query. * @param[in] pcSearchFilter - A query formulated of attribute pattern * matching expressions in the form of a LDAPv3 Search Filter, see * [RFC 2254]. If this filter is empty, i.e. "" or NULL, all services * of the requested type in the specified scopes are returned. * @param[in] callback - A callback function through which the results of * the operation are reported. * @param[in] pvCookie - Memory passed to the @p callback code from the * client. May be NULL. * * @return If an error occurs in starting the operation, one of the SLPError * codes is returned. */ SLPEXP SLPError SLPAPI SLPFindSrvs( SLPHandle hSLP, const char * pcServiceType, const char * pcScopeList, const char * pcSearchFilter, SLPSrvURLCallback callback, void * pvCookie) { bool inuse; SLPError serr = 0; SLPHandleInfo * handle = hSLP; /* Check for invalid parameters. */ SLP_ASSERT(handle != 0); SLP_ASSERT(handle->sig == SLP_HANDLE_SIG); SLP_ASSERT(pcServiceType != 0); SLP_ASSERT(*pcServiceType != 0); SLP_ASSERT(callback != 0); if (handle == 0 || handle->sig != SLP_HANDLE_SIG || pcServiceType == 0 || *pcServiceType == 0 || callback == 0) return SLP_PARAMETER_BAD; /* Check to see if the handle is in use. */ inuse = SLPSpinLockTryAcquire(&handle->inUse); SLP_ASSERT(!inuse); if (inuse) return SLP_HANDLE_IN_USE; /* Get a scope list if not supplied. */ if (pcScopeList == 0 || *pcScopeList == 0) pcScopeList = SLPPropertyGet("net.slp.useScopes", 0, 0); /* Ensure there's a scope list of some sort... */ if (pcScopeList == 0) pcScopeList = ""; /* Get a search filter if not supplied */ if (pcSearchFilter == 0) pcSearchFilter = ""; /* Set the handle up to reference parameters. */ handle->params.findsrvs.srvtypelen = strlen(pcServiceType); handle->params.findsrvs.srvtype = pcServiceType; handle->params.findsrvs.scopelistlen = strlen(pcScopeList); handle->params.findsrvs.scopelist = pcScopeList; handle->params.findsrvs.predicatelen = strlen(pcSearchFilter); handle->params.findsrvs.predicate = pcSearchFilter; handle->params.findsrvs.callback = callback; handle->params.findsrvs.cookie = pvCookie; /* Check to see if we should be async or sync. */ #ifdef ENABLE_ASYNC_API if (handle->isAsync) { /* Copy all of the referenced parameters before creating thread. */ handle->params.findsrvs.srvtype = xstrdup(handle->params.findsrvs.srvtype); handle->params.findsrvs.scopelist = xstrdup(handle->params.findsrvs.scopelist); handle->params.findsrvs.predicate = xstrdup(handle->params.findsrvs.predicate); /* Ensure strdups and thread create succeed. */ if (handle->params.findsrvs.srvtype == 0 || handle->params.findsrvs.scopelist == 0 || handle->params.findsrvs.predicate == 0 || (handle->th = SLPThreadCreate((SLPThreadStartProc) AsyncProcessSrvRqst, handle)) == 0) { serr = SLP_MEMORY_ALLOC_FAILED; xfree((void *)handle->params.findsrvs.srvtype); xfree((void *)handle->params.findsrvs.scopelist); xfree((void *)handle->params.findsrvs.predicate); SLPSpinLockRelease(&handle->inUse); } } else #endif { /* Leave all parameters referenced. */ serr = ProcessSrvRqst(handle); SLPSpinLockRelease(&handle->inUse); } return serr; }
/** Register a service URL through OpenSLP. * * Registers the URL in @p pcSrvURL having the lifetime usLifetime with * the attribute list in pcAttrs. The @p pcAttrs list is a comma separated * list of attribute assignments in the wire format (including escaping * of reserved characters). The @p usLifetime parameter must be nonzero * and less than or equal to SLP_LIFETIME_MAXIMUM. If the @p fresh flag * is SLP_TRUE, then the registration is new (the SLP protocol FRESH flag * is set) and the registration replaces any existing registrations. * The @p pcSrvType parameter is a service type name and can be included * for service URLs that are not in the service: scheme. If the URL is * in the service: scheme, the @p pcSrvType parameter is ignored. If the * @p fresh flag is SLP_FALSE, then an existing registration is updated. * Rules for new and updated registrations, and the format for @p pcAttrs * and @p pcScopeList can be found in [RFC 2608]. Registrations and * updates take place in the language locale of the @p hSLP handle. * * @par * The API library is required to perform the operation in all scopes * obtained through configuration. * * @param[in] hSLP - The language-specific SLPHandle on which to register * the advertisement. * @param[in] srvUrl - The URL to register. May not be the empty string. * May not be NULL. Must conform to SLP Service URL syntax. * SLP_INVALID_REGISTRATION will be returned if not. * @param[in] lifetime - An unsigned short giving the life time of the * service advertisement, in seconds. The value must be an unsigned * integer less than or equal to SLP_LIFETIME_MAXIMUM, and greater * than zero. If SLP_LIFETIME_MAXIMUM is used, the registration * will remain for the life of the calling process. Also, OpenSLP, * will not allow registrations to be made with SLP_LIFETIME_MAXIMUM * unless SLP_REG_FLAG_WATCH_PID is also used. Note that RFC 2614 * defines this parameter as const unsigned short. The 'const' is * superfluous. * @param[in] srvType - The service type. If @p pURL is a "service:" * URL, then this parameter is ignored. (ALWAYS ignored since the SLP * Service URL syntax required for the @p pcSrvURL encapsulates the * service type.) * @param[in] attrList - A comma separated list of attribute assignment * expressions for the attributes of the advertisement. Use empty * string ("") for no attributes. * @param[in] fresh - An SLPBoolean that is SLP_TRUE if the registration * is new or SLP_FALSE if a RE-registration. Use of non-fresh * registrations is deprecated (post RFC 2614). SLP_TRUE must be * passed in for this parameter or SLP_BAD_PARAMETER will be returned. * It also appears that this flag has been overloaded to accept certain * specific values of "true" for internal purposes... (jmc) * @param[in] callback - A callback to report the operation completion * status. * @param[in] cookie - Memory passed to the callback code from the * client. May be NULL. * * @return If an error occurs in starting the operation, one of the * SLPError codes is returned. */ SLPEXP SLPError SLPAPI SLPReg( SLPHandle hSLP, const char * srvUrl, unsigned short lifetime, const char * srvType, const char * attrList, SLPBoolean fresh, SLPRegReport callback, void * cookie) { bool inuse; SLPError serr; SLPSrvURL * parsedurl = 0; SLPHandleInfo * handle = hSLP; /** @todo Add code to accept non- "service:" scheme * URL's - normalize with srvType parameter info. */ (void)srvType; /* not used yet */ /* Check for invalid parameters. */ SLP_ASSERT(handle != 0); SLP_ASSERT(handle->sig == SLP_HANDLE_SIG); SLP_ASSERT(srvUrl != 0); SLP_ASSERT(*srvUrl != 0); SLP_ASSERT(lifetime != 0); SLP_ASSERT(attrList != 0); SLP_ASSERT(callback != 0); if (handle == 0 || handle->sig != SLP_HANDLE_SIG || srvUrl == 0 || *srvUrl == 0 || lifetime == 0 || attrList == 0 || callback == 0) return SLP_PARAMETER_BAD; /** @todo Handle non-fresh registrations in SLPReg. */ if (fresh == SLP_FALSE) return SLP_NOT_IMPLEMENTED; /* Check to see if the handle is in use. */ inuse = SLPSpinLockTryAcquire(&handle->inUse); SLP_ASSERT(!inuse); if (inuse) return SLP_HANDLE_IN_USE; /* Parse the srvurl - mainly for service type info. */ serr = SLPParseSrvURL(srvUrl, &parsedurl); if (serr) { SLPSpinLockRelease(&handle->inUse); return serr == SLP_PARSE_ERROR? SLP_INVALID_REGISTRATION: serr; } /* Set the handle up to reference parameters. */ handle->params.reg.fresh = fresh; handle->params.reg.lifetime = lifetime; handle->params.reg.urllen = strlen(srvUrl); handle->params.reg.url = srvUrl; handle->params.reg.srvtype = parsedurl->s_pcSrvType; handle->params.reg.srvtypelen = strlen(handle->params.reg.srvtype); handle->params.reg.scopelist = SLPPropertyGet("net.slp.useScopes", 0, 0); handle->params.reg.scopelistlen = strlen(handle->params.reg.scopelist); handle->params.reg.attrlistlen = strlen(attrList); handle->params.reg.attrlist = attrList; handle->params.reg.callback = callback; handle->params.reg.cookie = cookie; #ifdef ENABLE_ASYNC_API if (handle->isAsync) { /* Copy all of the referenced parameters before creating thread. */ handle->params.reg.url = xstrdup(handle->params.reg.url); handle->params.reg.srvtype = xstrdup(handle->params.reg.url); handle->params.reg.scopelist = xstrdup(handle->params.reg.scopelist); handle->params.reg.attrlist = xstrdup(handle->params.reg.attrlist); /* Ensure strdups and thread create succeed. */ if (handle->params.reg.url == 0 || handle->params.reg.srvtype == 0 || handle->params.reg.scopelist == 0 || handle->params.reg.attrlist == 0 || (handle->th = SLPThreadCreate((SLPThreadStartProc) AsyncProcessSrvReg, handle)) == 0) { serr = SLP_MEMORY_ALLOC_FAILED; xfree((void *)handle->params.reg.url); xfree((void *)handle->params.reg.srvtype); xfree((void *)handle->params.reg.scopelist); xfree((void *)handle->params.reg.attrlist); SLPSpinLockRelease(&handle->inUse); } } else #endif { /* Reference all the parameters. */ serr = ProcessSrvReg(handle); SLPSpinLockRelease(&handle->inUse); } SLPFree(parsedurl); return serr; }
/** Open an OpenSLP session handle. * * Returns a SLPHandle handle in the phSLP parameter for the language * locale passed in as the pcLang parameter. The client indicates if * operations on the handle are to be synchronous or asynchronous * through the isAsync parameter. The handle encapsulates the language * locale for SLP requests issued through the handle, and any other * resources required by the implementation. However, SLP properties * are not encapsulated by the handle; they are global. The return * value of the function is an SLPError code indicating the status of * the operation. Upon failure, the phSLP parameter is NULL. * * @par * An SLPHandle can only be used for one SLP API operation at a time. * If the original operation was started asynchronously, any attempt * to start an additional operation on the handle while the original * operation is pending results in the return of an SLP_HANDLE_IN_USE * error from the API function. The SLPClose() API function terminates * any outstanding calls on the handle. If an implementation is unable * to support a asynchronous (resp. synchronous) operation, due to * memory constraints or lack of threading support, the * SLP_NOT_IMPLEMENTED flag may be returned when the isAsync flag * is SLP_TRUE (resp. SLP_FALSE). * * @param[in] pcLang - A pointer to an array of characters containing * the [RFC 1766] Language Tag for the natural language locale of * requests and registrations issued on the handle. (Pass NULL or * the empty string to use the default locale.) * * @param[in] isAsync - An SLPBoolean indicating whether the SLPHandle * should be opened for asynchronous operation or not. * * @param[out] phSLP - A pointer to an SLPHandle, in which the open * SLPHandle is returned. If an error occurs, the value upon return * is NULL. * * @return An SLPError code; SLP_OK(0) on success, SLP_PARAMETER_BAD, * SLP_NOT_IMPLEMENTED, SLP_MEMORY_ALLOC_FAILED, * SLP_NETWORK_INIT_FAILED, SLP_INTERNAL_SYSTEM_ERROR */ SLPEXP SLPError SLPAPI SLPOpen( const char * pcLang, SLPBoolean isAsync, SLPHandle * phSLP) { SLPError serr; SLPHandleInfo * handle; /* Check for invalid parameters. */ SLP_ASSERT(phSLP != 0); if (phSLP == 0) return SLP_PARAMETER_BAD; #ifndef ENABLE_ASYNC_API if (isAsync) return SLP_NOT_IMPLEMENTED; #endif *phSLP = 0; serr = InitUserAgentLibrary(); if (serr != SLP_OK) return serr; /* Allocate and clear an SLPHandleInfo structure. */ handle = xcalloc(1, sizeof(SLPHandleInfo)); if (handle == 0) { ExitUserAgentLibrary(); return SLP_MEMORY_ALLOC_FAILED; } handle->sig = SLP_HANDLE_SIG; handle->inUse = 0; #ifdef ENABLE_ASYNC_API handle->isAsync = isAsync; #endif handle->dasock = SLP_INVALID_SOCKET; handle->sasock = SLP_INVALID_SOCKET; #ifndef UNICAST_NOT_SUPPORTED handle->unicastsock = SLP_INVALID_SOCKET; #endif /* Set the language tag. */ if (pcLang == 0 || *pcLang == 0) pcLang = SLPPropertyGet("net.slp.locale", 0, 0); handle->langtaglen = strlen(pcLang); handle->langtag = xmemdup(pcLang, handle->langtaglen + 1); if (handle->langtag == 0) { xfree(handle); ExitUserAgentLibrary(); return SLP_MEMORY_ALLOC_FAILED; } #ifdef ENABLE_SLPv2_SECURITY handle->hspi = SLPSpiOpen(LIBSLP_SPIFILE, 0); if (!handle->hspi) { xfree(handle->langtag); xfree(handle); ExitUserAgentLibrary(); return SLP_INTERNAL_SYSTEM_ERROR; } #endif *phSLP = handle; return SLP_OK; }
/** Return a list of service types available on the network. * * The SLPFindSrvType function issues an SLP service type request for * service types in the scopes indicated by the @p pcScopeList. The * results are returned through the @p callback parameter. The service * types are independent of language locale, but only for services * registered in one of scopes and for the indicated naming authority. * * @par * If the naming authority is "*", then results are returned for all * naming authorities. If the naming authority is the empty string, * i.e. "", then the default naming authority, "IANA", is used. "IANA" * is not a valid naming authority name, and it is a PARAMETER_BAD error * to include it explicitly. * * @par * The service type names are returned with the naming authority intact. * If the naming authority is the default (i.e. empty string) then it * is omitted, as is the separating ".". Service type names from URLs * of the service: scheme are returned with the "service:" prefix * intact. [RFC 2608] See [RFC 2609] for more information on the * syntax of service type names. * * @param[in] hSLP - The SLPHandle on which to search for types. * @param[in] pcNamingAuthority - The naming authority to search. Use "*" * for all naming authorities and the empty string, "", for the default * naming authority. * @param[in] pcScopeList - A pointer to a char containing comma separated * list of scope names to search for service types. May not be the empty * string, "". * @param[in] callback - A callback function through which the results of * the operation are reported. * @param[in] pvCookie - Memory passed to the @p callback code from the * client. May be NULL. * * @return If an error occurs in starting the operation, one of the * SLPError codes is returned. */ SLPError SLPAPI SLPFindSrvTypes( SLPHandle hSLP, const char * pcNamingAuthority, const char * pcScopeList, SLPSrvTypeCallback callback, void * pvCookie) { bool inuse; SLPError serr = 0; SLPHandleInfo * handle = hSLP; /* Check for invalid parameters. */ SLP_ASSERT(handle != 0); SLP_ASSERT(handle->sig == SLP_HANDLE_SIG); SLP_ASSERT(pcNamingAuthority != 0); SLP_ASSERT(strcmp(pcNamingAuthority, "IANA") != 0); SLP_ASSERT(callback != 0); if (handle == 0 || handle->sig != SLP_HANDLE_SIG || pcNamingAuthority == 0 || strcmp(pcNamingAuthority, "IANA") == 0 || callback == 0) return SLP_PARAMETER_BAD; /* Check to see if the handle is in use. */ inuse = SLPSpinLockTryAcquire(&handle->inUse); SLP_ASSERT(!inuse); if (inuse) return SLP_HANDLE_IN_USE; /* Get a scope list if none was specified. */ if (pcScopeList == 0 || *pcScopeList == 0) pcScopeList = SLPPropertyGet("net.slp.useScopes", 0, 0); /* Set the handle up to reference parameters. */ handle->params.findsrvtypes.namingauthlen = strlen(pcNamingAuthority); handle->params.findsrvtypes.namingauth = pcNamingAuthority; handle->params.findsrvtypes.scopelistlen = strlen(pcScopeList); handle->params.findsrvtypes.scopelist = pcScopeList; handle->params.findsrvtypes.callback = callback; handle->params.findsrvtypes.cookie = pvCookie; /* Check to see if we should be async or sync. */ #ifdef ENABLE_ASYNC_API if (handle->isAsync) { /* Copy all the referenced parameters. */ handle->params.findsrvtypes.namingauth = xstrdup(handle->params.findsrvtypes.namingauth); handle->params.findsrvtypes.scopelist = xstrdup(handle->params.findsrvtypes.scopelist); /* Ensure strdups and thread create succeed. */ if (handle->params.findsrvtypes.namingauth == 0 || handle->params.findsrvtypes.scopelist == 0 || (handle->th = SLPThreadCreate((SLPThreadStartProc) AsyncProcessSrvTypeRqst, handle)) == 0) { serr = SLP_MEMORY_ALLOC_FAILED; xfree((void *)handle->params.findsrvtypes.namingauth); xfree((void *)handle->params.findsrvtypes.scopelist); SLPSpinLockRelease(&handle->inUse); } return serr; } #endif /* Reference all parameters. */ serr = ProcessSrvTypeRqst(handle); SLPSpinLockRelease(&handle->inUse); return serr; }