/*=========================================================================*/ void SLPDKnownDARegister(SLPDPeerInfo* peerinfo, SLPMessage msg, SLPBuffer buf) /* Echo a message to a known DA */ /* */ /* peerinfo (IN) the peer that the registration came from */ /* */ /* msg (IN) the translated message to echo */ /* */ /* buf (IN) the message buffer to echo */ /* */ /* Returns: Zero on success, non-zero on error */ /*=========================================================================*/ { SLPDAEntry* daentry; SLPDSocket* sock; SLPBuffer dup; daentry = (SLPDAEntry*)G_KnownDAList.head; while (daentry) { sock = (SLPDSocket*)G_OutgoingSocketList.head; while (sock) { if (sock->peerinfo.peeraddr.sin_addr.s_addr == daentry->daaddr.s_addr) { break; } sock = (SLPDSocket*)sock->listitem.next; } if (sock == 0) { /* Create a new socket to the known DA */ sock = SLPDSocketCreateConnected(&(daentry->daaddr)); if (sock) { sock->daentry = daentry; SLPListLinkTail(&G_OutgoingSocketList,(SLPListItem*)sock); } } /* Load the socket with the message to send */ dup = SLPBufferDup(buf); if (dup) { if (sock->state == STREAM_CONNECT_IDLE) { sock->state = STREAM_WRITE_FIRST; } SLPListLinkTail(&(sock->sendlist),(SLPListItem*)dup); } daentry = (SLPDAEntry*)daentry->listitem.next; } }
/*=========================================================================*/ SLPDSocket* SLPDOutgoingConnect(struct in_addr* addr) /* Get a pointer to a connected socket that is associated with the */ /* outgoing socket list. If a connected socket already exists on the */ /* outgoing list, a pointer to it is returned, otherwise a new connection */ /* is made and added to the outgoing list */ /* */ /* addr (IN) the address of the peer a connection is desired for */ /* */ /* returns: pointer to socket or null on error */ /*=========================================================================*/ { SLPDSocket* sock = (SLPDSocket*)G_OutgoingSocketList.head; while ( sock ) { if ( sock->state == STREAM_CONNECT_IDLE || sock->state > SOCKET_PENDING_IO ) { if ( sock->peeraddr.sin_addr.s_addr == addr->s_addr ) { break; } } sock = (SLPDSocket*)sock->listitem.next; } if ( sock == 0 ) { sock = SLPDSocketCreateConnected(addr); SLPListLinkTail(&(G_OutgoingSocketList),(SLPListItem*)sock); } return sock; }
/*=========================================================================*/ char* _xstrdup(const char* file, int line, const char* str) /*=========================================================================*/ { xallocation_t* x; size_t strlength = strlen(str); if(G_xmalloc_freemem && G_xmalloc_allocmem + strlength > G_xmalloc_freemem) { if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"\n*** Simulating out of memory error ***\n\n"); } return NULL; } x = malloc(sizeof(xallocation_t)); if(x == NULL) { if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"\n*** Real out of memory error ***\n\n"); } return NULL; } x->buf = strdup(str); if(x->buf == NULL) { if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"\n*** Real out of memory error ***\n\n"); } return NULL; } x->size = strlength; snprintf(x->where,SLPXMALLOC_MAX_WHERE_LEN,"%s:%i",file,line); G_xmalloc_allocmem += strlength; if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"Called xstrdup() %s:%i ",file,line); _xmalloc_log(x); } SLPListLinkTail(&G_xmalloc_list, (SLPListItem*)x); return (char*)x->buf; }
/*=========================================================================*/ void* _xmalloc(const char* file, int line, size_t size) /*=========================================================================*/ { xallocation_t* x; if(G_xmalloc_freemem && G_xmalloc_allocmem + size > G_xmalloc_freemem) { if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"\n*** Simulating out of memory error ***\n\n"); } return NULL; } x = malloc(sizeof(xallocation_t)); if(x == NULL) { if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"\n*** Real out of memory error ***\n\n"); } return NULL; } x->buf = malloc(size); if(x->buf == NULL) { if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"\n*** Real out of memory error ***\n\n"); } return NULL; } SLPListLinkTail(&G_xmalloc_list, (SLPListItem*)x); x->size = size; snprintf(x->where,SLPXMALLOC_MAX_WHERE_LEN,"%s:%i",file,line); G_xmalloc_allocmem += size; if(G_xmalloc_fh) { fprintf(G_xmalloc_fh,"Called xmalloc() %s:%i ",file,line); _xmalloc_log(x); } return x->buf; }
/** Connect for outbound traffic to a specified remote address. * * @param[in] is_TCP - if non-0, this is a tcp connection to the remote device * @param[in] addr - The address to be connected to. * * @remarks Get a pointer to a connected socket that is associated with * the outgoing socket list. If a connected socket already exists on the * outgoing list, a pointer to it is returned, otherwise a new connection * is made and added to the outgoing list * * @return A pointer to socket, or null on error. */ SLPDSocket * SLPDOutgoingConnect(int is_TCP, struct sockaddr_storage * addr) { SLPDSocket * sock = 0; if(is_TCP) { sock = (SLPDSocket *) G_OutgoingSocketList.head; while (sock) { if (sock->state == STREAM_CONNECT_IDLE || sock->state > STREAM_CONNECT_CLOSE) { if (SLPNetCompareAddrs(&(sock->peeraddr), addr) == 0) break; } sock = (SLPDSocket *) sock->listitem.next; } if (sock == 0) { sock = SLPDSocketCreateConnected(addr); if (sock) SLPListLinkTail(&(G_OutgoingSocketList), (SLPListItem *) sock); } } else { sock = SLPDSocketCreateDatagram(addr, DATAGRAM_UNICAST); if (sock) { SLPListLinkTail(&(G_OutgoingSocketList), (SLPListItem *) sock); sock->reconns = 0; sock->age = 0; } } return sock; }
/*-------------------------------------------------------------------------*/ SLPBoolean KnownDADiscoveryCallback(SLPError errorcode, SLPMessage msg, void* cookie) /*-------------------------------------------------------------------------*/ { SLPSrvURL* srvurl; SLPDAEntry* entry; struct hostent* he; int* count = (int*)cookie; if (errorcode == 0) { if(msg && msg->header.functionid == SLP_FUNCT_DAADVERT) { if(msg->body.srvrply.errorcode == 0) { /* NULL terminate scopelist */ *((char*)msg->body.daadvert.scopelist + msg->body.daadvert.scopelistlen) = 0; if(SLPParseSrvURL(msg->body.daadvert.url, &srvurl) == 0) { he = gethostbyname(srvurl->s_pcHost); if(he) { entry = SLPDAEntryCreate((struct in_addr*)(he->h_addr_list[0]), msg->body.daadvert.bootstamp, msg->body.daadvert.scopelist, msg->body.daadvert.scopelistlen); SLPListLinkTail(&G_KnownDAList,(SLPListItem*)entry); *count = *count + 1; } SLPFree(srvurl); } } } } return 1; }
/*-------------------------------------------------------------------------*/ SLPBoolean ColateSLPSrvURLCallback(SLPHandle hSLP, const char* pcSrvURL, unsigned short sLifetime, SLPError errCode, void *pvCookie) /*-------------------------------------------------------------------------*/ { SLPSrvUrlColatedItem* collateditem; PSLPHandleInfo handle; handle = (PSLPHandleInfo) hSLP; handle->callbackcount ++; #ifdef ENABLE_ASYNC_API /* Do not colate for async calls */ if(handle->isAsync) { return handle->params.findsrvs.callback(hSLP, pcSrvURL, sLifetime, errCode, pvCookie); } #endif if(errCode == SLP_LAST_CALL || handle->callbackcount > SLPPropertyAsInteger(SLPGetProperty("net.slp.maxResults"))) { /* We are done so call the caller's callback for each */ /* service URL colated item and clean up the colation list */ handle->params.findsrvs.callback((SLPHandle)handle, NULL, 0, SLP_LAST_CALL, handle->params.findsrvs.cookie); goto CLEANUP; } else if(errCode != SLP_OK) { return SLP_TRUE; } /* Add the service URL to the colation list */ collateditem = (SLPSrvUrlColatedItem*) handle->collatedsrvurls.head; while(collateditem) { if(strcmp(collateditem->srvurl,pcSrvURL) == 0) { break; } collateditem = (SLPSrvUrlColatedItem*)collateditem->listitem.next; } /* create a new item if none was found */ if(collateditem == NULL) { collateditem = (SLPSrvUrlColatedItem*) xmalloc(sizeof(SLPSrvUrlColatedItem) + \ strlen(pcSrvURL) + 1); if(collateditem) { memset(collateditem,0,sizeof(SLPSrvUrlColatedItem)); collateditem->srvurl = (char*)(collateditem + 1); strcpy(collateditem->srvurl,pcSrvURL); collateditem->lifetime = sLifetime; /* Add the new item to the collated list */ SLPListLinkTail(&(handle->collatedsrvurls), (SLPListItem*)collateditem); /* Call the caller's callback */ if(handle->params.findsrvs.callback((SLPHandle)handle, pcSrvURL, sLifetime, SLP_OK, handle->params.findsrvs.cookie) == SLP_FALSE) { goto CLEANUP; } } } return SLP_TRUE; CLEANUP: /* free the collation list */ while(handle->collatedsrvurls.count) { collateditem = (SLPSrvUrlColatedItem*)SLPListUnlink(&(handle->collatedsrvurls), handle->collatedsrvurls.head); xfree(collateditem); } handle->callbackcount = 0; return SLP_FALSE; }
/** Collates response data to user callback for SLPFindSrv requests. * * @param[in] hSLP - The SLP handle object associated with the request. * @param[in] pcSrvURL - The service URL for this pass. * @param[in] sLifetime - The lifetime value for @p pcSrvURL. * @param[in] errorcode - The error code received on this pass. * * @return An SLP boolean value; SLP_TRUE indicates we are finished; * SLP_FALSE indicates we should continue. * * @todo Trace the logic of CollateToSLPSrvURLCallback to ensure * that it works. * * @internal */ static SLPBoolean CollateToSLPSrvURLCallback(SLPHandle hSLP, const char * pcSrvURL, unsigned short sLifetime, SLPError errorcode) { int maxResults; SLPHandleInfo * handle = hSLP; SLPSrvUrlCollatedItem * collateditem; #ifdef ENABLE_ASYNC_API /* Do not collate for async calls. */ if (handle->isAsync) return handle->params.findsrvs.callback(hSLP, pcSrvURL, sLifetime, errorcode, handle->params.findsrvs.cookie); #endif /* Configure behaviour for desired max results */ maxResults = SLPPropertyAsInteger("net.slp.maxResults"); if (maxResults == -1) maxResults = INT_MAX; if (errorcode == SLP_LAST_CALL || handle->callbackcount > maxResults) { /* We are done so call the caller's callback for each * service URL collated item and clean up the collation list. */ handle->params.findsrvs.callback(handle, 0, 0, SLP_LAST_CALL, handle->params.findsrvs.cookie); goto CLEANUP; } else if (errorcode != SLP_OK) return SLP_TRUE; /* We're adding another result - increment result count. */ handle->callbackcount++; /* Add the service URL to the colation list. */ collateditem = (SLPSrvUrlCollatedItem *)handle->collatedsrvurls.head; while (collateditem) { if (strcmp(collateditem->srvurl, pcSrvURL) == 0) break; collateditem = (SLPSrvUrlCollatedItem *)collateditem->listitem.next; } /* Create a new item if none was found. */ if (collateditem == 0) { collateditem = xmalloc(sizeof(SLPSrvUrlCollatedItem) + strlen(pcSrvURL) + 1); if (collateditem) { memset(collateditem, 0, sizeof(SLPSrvUrlCollatedItem)); collateditem->srvurl = (char *)(collateditem + 1); strcpy(collateditem->srvurl, pcSrvURL); collateditem->lifetime = sLifetime; /* Add the new item to the collated list. */ SLPListLinkTail(&handle->collatedsrvurls, (SLPListItem *)collateditem); /* Call the caller's callback. */ if (handle->params.findsrvs.callback(handle, pcSrvURL, sLifetime, SLP_OK, handle->params.findsrvs.cookie) == SLP_FALSE) goto CLEANUP; } } return SLP_TRUE; CLEANUP: /* Free the collation list. */ while (handle->collatedsrvurls.count) { collateditem = (SLPSrvUrlCollatedItem *)SLPListUnlink( &handle->collatedsrvurls, handle->collatedsrvurls.head); xfree(collateditem); } handle->callbackcount = 0; return SLP_FALSE; }
/*=========================================================================*/ int SLPDIncomingInit() /* Initialize incoming socket list to have appropriate sockets for all */ /* network interfaces */ /* */ /* Returns Zero on success non-zero on error */ /*=========================================================================*/ { char* begin = NULL; char* beginSave = NULL; char* end = NULL; int finished; struct in_addr myaddr; struct in_addr mcastaddr; struct in_addr bcastaddr; struct in_addr loaddr; SLPDSocket* sock; /*------------------------------------------------------------*/ /* First, remove all of the sockets that might be in the list */ /*------------------------------------------------------------*/ while (G_IncomingSocketList.count) { SLPDSocketFree((SLPDSocket*)SLPListUnlink(&G_IncomingSocketList,G_IncomingSocketList.head)); } /*--------------------------------------------------*/ /* set up address to use for loopback and broadcast */ /*--------------------------------------------------*/ loaddr.s_addr = htonl(LOOPBACK_ADDRESS); bcastaddr.s_addr = htonl(SLP_BCAST_ADDRESS); mcastaddr.s_addr = htonl(SLP_MCAST_ADDRESS); /*--------------------------------------------------------------------*/ /* Create SOCKET_LISTEN socket for LOOPBACK for the library to talk to*/ /*--------------------------------------------------------------------*/ sock = SLPDSocketCreateListen(&loaddr); if (sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPDLog("Listening on loopback...\n"); } else { SLPDLog("NETWORK_ERROR - Could not listen on loopback\n"); SLPDLog("INTERNAL_ERROR - No SLPLIB support will be available\n"); } /*---------------------------------------------------------------------*/ /* Create sockets for all of the interfaces in the interfaces property */ /*---------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/ /* Copy G_SlpdProperty.interfaces to a temporary buffer to parse the */ /* string in a safety way */ /*---------------------------------------------------------------------*/ if (G_SlpdProperty.interfaces != NULL) { begin = xstrdup((char *) G_SlpdProperty.interfaces); beginSave = begin; /* save pointer for free() operation later */ end = begin; finished = 0; } else { finished = 1; /* if no interface is defined, */ /* don't even enter the parsing loop */ } for (; (finished == 0); begin = ++end) { while (*end && *end != ',') end ++; if (*end == 0) finished = 1; *end = 0; /* Terminate string. */ if (end <= begin) continue; /* Skip empty entries */ /* begin now points to a null terminated ip address string */ myaddr.s_addr = inet_addr(begin); /*------------------------------------------------*/ /* Create TCP_LISTEN that will handle unicast TCP */ /*------------------------------------------------*/ sock = SLPDSocketCreateListen(&myaddr); if (sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPDLog("Listening on %s ...\n",inet_ntoa(myaddr)); } /*----------------------------------------------------------------*/ /* Create socket that will handle multicast UDP. */ /*----------------------------------------------------------------*/ sock = SLPDSocketCreateBoundDatagram(&myaddr, &mcastaddr, DATAGRAM_MULTICAST); if (sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPDLog("Multicast socket on %s ready\n",inet_ntoa(myaddr)); } else { SLPDLog("Couldn't bind to multicast for interface %s (%s)\n", inet_ntoa(myaddr), strerror(errno)); } #if defined(ENABLE_SLPv1) if (G_SlpdProperty.isDA) { /*------------------------------------------------------------*/ /* Create socket that will handle multicast UDP for SLPv1 DA */ /* Discovery. */ /*------------------------------------------------------------*/ mcastaddr.s_addr = htonl(SLPv1_DA_MCAST_ADDRESS); sock = SLPDSocketCreateBoundDatagram(&myaddr, &mcastaddr, DATAGRAM_MULTICAST); if (sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPDLog("SLPv1 DA Discovery Multicast socket on %s ready\n", inet_ntoa(myaddr)); } } #endif /*--------------------------------------------*/ /* Create socket that will handle unicast UDP */ /*--------------------------------------------*/ sock = SLPDSocketCreateBoundDatagram(&myaddr, &myaddr, DATAGRAM_UNICAST); if (sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPDLog("Unicast socket on %s ready\n",inet_ntoa(myaddr)); } } if (beginSave) xfree(beginSave); /*--------------------------------------------------------*/ /* Create socket that will handle broadcast UDP */ /*--------------------------------------------------------*/ sock = SLPDSocketCreateBoundDatagram(&myaddr, &bcastaddr, DATAGRAM_BROADCAST); if (sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPDLog("Broadcast socket for %s ready\n", inet_ntoa(bcastaddr)); } if (G_IncomingSocketList.count == 0) { SLPDLog("No usable interfaces\n"); return 1; } return 0; }
/*=========================================================================*/ int SLPDIncomingInit() /* Initialize incoming socket list to have appropriate sockets for all */ /* network interfaces */ /* */ /* Returns Zero on success non-zero on error */ /*=========================================================================*/ { char* begin; char* end; int finished; struct in_addr myaddr; struct in_addr mcastaddr; struct in_addr bcastaddr; struct in_addr loaddr; SLPDSocket* sock; /*------------------------------------------------------------*/ /* First, remove all of the sockets that might be in the list */ /*------------------------------------------------------------*/ while(G_IncomingSocketList.count) { SLPDSocketFree((SLPDSocket*)SLPListUnlink(&G_IncomingSocketList,G_IncomingSocketList.head)); } /*-----------------------------------------------*/ /* set up address to use for multicast/broadcast */ /*-----------------------------------------------*/ mcastaddr.s_addr = htonl(SLP_MCAST_ADDRESS); loaddr.s_addr = htonl(LOOPBACK_ADDRESS); bcastaddr.s_addr = htonl(SLP_BCAST_ADDRESS); /*-----------------------------------------------------------------*/ /* Create SOCKET_LISTEN socket for LOOPBACK for the library to talk to*/ /*-----------------------------------------------------------------*/ sock = SLPDSocketCreateListen(&loaddr); if(sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPLog("Listening on loopback...\n"); } else { SLPLog("ERROR: Could not listen on loopback\n"); SLPLog("ERROR: No SLPLIB support will be available\n"); } /*---------------------------------------------------------------------*/ /* Create sockets for all of the interfaces in the interfaces property */ /*---------------------------------------------------------------------*/ begin = (char*)G_SlpdProperty.interfaces; end = begin; finished = 0; while( finished == 0) { while(*end && *end != ',') end ++; if(*end == 0) finished = 1; while(*end <=0x2f) { *end = 0; end--; } /* begin now points to a null terminated ip address string */ myaddr.s_addr = inet_addr(begin); /*------------------------------------------------*/ /* Create TCP_LISTEN that will handle unicast TCP */ /*------------------------------------------------*/ sock = SLPDSocketCreateListen(&myaddr); if(sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPLog("Listening on %s ...\n",inet_ntoa(myaddr)); } /*--------------------------------------------------------*/ /* Create socket that will handle multicast UDP */ /*--------------------------------------------------------*/ sock = SLPDSocketCreateBoundDatagram(&myaddr, &mcastaddr, DATAGRAM_MULTICAST); if(sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPLog("Multicast socket on %s ready\n",inet_ntoa(myaddr)); } /*--------------------------------------------*/ /* Create socket that will handle unicast UDP */ /*--------------------------------------------*/ sock = SLPDSocketCreateBoundDatagram(&myaddr, &myaddr, DATAGRAM_UNICAST); if(sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPLog("Unicast socket on %s ready\n",inet_ntoa(myaddr)); } begin = end + 1; } /*--------------------------------------------------------*/ /* Create socket that will handle broadcast UDP */ /*--------------------------------------------------------*/ sock = SLPDSocketCreateBoundDatagram(&myaddr, &bcastaddr, DATAGRAM_BROADCAST); if(sock) { SLPListLinkTail(&G_IncomingSocketList,(SLPListItem*)sock); SLPLog("Broadcast socket for %s ready\n", inet_ntoa(bcastaddr)); } return 0; }