/** 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; }
/*=========================================================================*/ void SLPDKnownDAActiveDiscovery() /* Set outgoing socket list to send an active DA discovery SrvRqst */ /* */ /* Returns: none */ /*=========================================================================*/ { size_t bufsize; SLPDAEntry* daentry; SLPDSocket* sock; char* prlist; size_t prlistlen; struct in_addr peeraddr; if(G_SlpdProperty.isDA) { /* do not perform active DA discovery if we are a DA */ return; } if(G_SlpdProperty.activeDiscoveryAttempts <= 0) { return; } G_SlpdProperty.activeDiscoveryAttempts --; /*--------------------------------------------------*/ /* Create new DATAGRAM socket with appropriate peer */ /*--------------------------------------------------*/ if(G_SlpdProperty.isBroadcastOnly == 0) { peeraddr.s_addr = htonl(SLP_MCAST_ADDRESS); sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST); } else { peeraddr.s_addr = htonl(SLP_BCAST_ADDRESS); sock = SLPDSocketCreateDatagram(&peeraddr,DATAGRAM_BROADCAST); } /*-------------------------------------------------*/ /* Generate a DA service request buffer to be sent */ /*-------------------------------------------------*/ /* determine the size of the fixed portion of the SRVRQST */ bufsize = 47; /* 14 bytes for the header */ /* 2 bytes for the prlistlen */ /* 2 bytes for the srvtype length */ /* 23 bytes for "service:directory-agent" srvtype */ /* 2 bytes for scopelistlen */ /* 2 bytes for predicatelen */ /* 2 bytes for sprstrlen */ /* figure out what our Prlist will be by going through our list of */ /* known DAs */ prlistlen = 0; prlist = malloc(SLP_MAX_DATAGRAM_SIZE); if(prlist == 0) { goto FINISHED; } *prlist = 0; daentry = (SLPDAEntry*)G_KnownDAList.head; while(daentry && prlistlen < SLP_MAX_DATAGRAM_SIZE) { strcat(prlist,inet_ntoa(daentry->daaddr)); daentry = (SLPDAEntry*)daentry->listitem.next; if(daentry) { strcat(prlist,","); } prlistlen = strlen(prlist); } /* Allocate the send buffer */ bufsize += G_SlpdProperty.localeLen + prlistlen; sock->sendbuf = SLPBufferRealloc(sock->sendbuf,bufsize); if(sock->sendbuf == 0) { return; } /*------------------------------------------------------------*/ /* Build a buffer containing the fixed portion of the SRVRQST */ /*------------------------------------------------------------*/ /*version*/ *(sock->sendbuf->start) = 2; /*function id*/ *(sock->sendbuf->start + 1) = SLP_FUNCT_SRVRQST; /*length*/ ToUINT24(sock->sendbuf->start + 2, bufsize); /*flags*/ ToUINT16(sock->sendbuf->start + 5, SLP_FLAG_MCAST); /*ext offset*/ ToUINT24(sock->sendbuf->start + 7,0); /*xid*/ ToUINT16(sock->sendbuf->start + 10, 0); /* TODO: generat a real XID */ /*lang tag len*/ ToUINT16(sock->sendbuf->start + 12, G_SlpdProperty.localeLen); /*lang tag*/ memcpy(sock->sendbuf->start + 14, G_SlpdProperty.locale, G_SlpdProperty.localeLen); sock->sendbuf->curpos = sock->sendbuf->start + G_SlpdProperty.localeLen + 14; /* Prlist */ ToUINT16(sock->sendbuf->curpos,prlistlen); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; memcpy(sock->sendbuf->curpos,prlist,prlistlen); sock->sendbuf->curpos = sock->sendbuf->curpos + prlistlen; /* service type */ ToUINT16(sock->sendbuf->curpos,23); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; memcpy(sock->sendbuf->curpos,"service:directory-agent",23); sock->sendbuf->curpos = sock->sendbuf->curpos + 23; /* scope list zero length */ ToUINT16(sock->sendbuf->curpos,0); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; /* predicate zero length */ ToUINT16(sock->sendbuf->curpos,0); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; /* spi list zero length */ ToUINT16(sock->sendbuf->curpos,0); sock->sendbuf->curpos = sock->sendbuf->curpos + 2; /*------------------------------------*/ /* Send the active DA service request */ /*------------------------------------*/ if(sock) { sendto(sock->fd, sock->sendbuf->start, sock->sendbuf->end - sock->sendbuf->start, 0, &(sock->peerinfo.peeraddr), sock->peerinfo.peeraddrlen); } FINISHED: SLPDSocketFree(sock); }