📄 libslp_network.c
字号:
socktype = SOCK_DGRAM; } else { maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.unicastMaximumWait")); SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.unicastTimeouts"), timeouts, MAX_RETRANSMITS ); size = sizeof(socktype); getsockopt(sock,SOL_SOCKET,SO_TYPE,&socktype,&size); if(socktype == SOCK_DGRAM) { xmitcount = 0; looprecv = 1; } else { xmitcount = MAX_RETRANSMITS; looprecv = 0; } } /* Special case for fake SLP_FUNCT_DASRVRQST */ if(buftype == SLP_FUNCT_DASRVRQST) { /* do something special for SRVRQST that will be discovering DAs */ maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.DADiscoveryMaximumWait")); SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.DADiscoveryTimeouts"), timeouts, MAX_RETRANSMITS ); /* SLP_FUNCT_DASRVRQST is a fake function. We really want to */ /* send a SRVRQST */ buftype = SLP_FUNCT_SRVRQST; looprecv = 1; } /*---------------------------------------------------------------------*/ /* Allocate memory for the prlist for appropriate messages. */ /* Notice that the prlist is as large as the MTU -- thus assuring that */ /* there will not be any buffer overwrites regardless of how many */ /* previous responders there are. This is because the retransmit */ /* code terminates if ever MTU is exceeded for any datagram message. */ /*---------------------------------------------------------------------*/ if(buftype == SLP_FUNCT_SRVRQST || buftype == SLP_FUNCT_ATTRRQST || buftype == SLP_FUNCT_SRVTYPERQST) { prlist = (char*)xmalloc(mtu); if(prlist == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto CLEANUP; } *prlist = 0; prlistlen = 0; } /*--------------------------*/ /* Main retransmission loop */ /*--------------------------*/ while(xmitcount <= MAX_RETRANSMITS) { xmitcount++; /*--------------------*/ /* setup recv timeout */ /*--------------------*/ if(socktype == SOCK_DGRAM) { totaltimeout += timeouts[xmitcount]; if(totaltimeout >= maxwait || timeouts[xmitcount] == 0) { /* we are all done */ break; } timeout.tv_sec = timeouts[xmitcount] / 1000; timeout.tv_usec = (timeouts[xmitcount] % 1000) * 1000; } else { timeout.tv_sec = maxwait / 1000; timeout.tv_usec = (maxwait % 1000) * 1000; } /*------------------------------------------------------------------*/ /* re-allocate buffer and make sure that the send buffer does not */ /* exceed MTU for datagram transmission */ /*------------------------------------------------------------------*/ size = 14 + langtaglen + bufsize; if(buftype == SLP_FUNCT_SRVRQST || buftype == SLP_FUNCT_ATTRRQST || buftype == SLP_FUNCT_SRVTYPERQST) { /* add in room for the prlist */ size += 2 + prlistlen; } if(size > mtu && socktype == SOCK_DGRAM) { if(xmitcount == 0) { result = SLP_BUFFER_OVERFLOW; } goto FINISHED; } if((sendbuf = SLPBufferRealloc(sendbuf,size)) == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto CLEANUP; } /*-----------------------------------*/ /* Add the header to the send buffer */ /*-----------------------------------*/ /*version*/ *(sendbuf->start) = 2; /*function id*/ *(sendbuf->start + 1) = buftype; /*length*/ ToUINT24(sendbuf->start + 2, size); /*flags*/ flags = (ISMCAST(destaddr->sin_addr) ? SLP_FLAG_MCAST : 0); if (buftype == SLP_FUNCT_SRVREG) { flags |= SLP_FLAG_FRESH; } ToUINT16(sendbuf->start + 5, flags); /*ext offset*/ /* TRICKY: the extoffset passed into us was the offset not * including the header. We need to fix up the offset so * that it is from the beginning of the SLP message */ if(extoffset != 0) { ToUINT24(sendbuf->start + 7,extoffset + langtaglen + 14); } else { ToUINT24(sendbuf->start + 7, 0); } /*xid*/ ToUINT16(sendbuf->start + 10,xid); /*lang tag len*/ ToUINT16(sendbuf->start + 12,langtaglen); /*lang tag*/ memcpy(sendbuf->start + 14, langtag, langtaglen); sendbuf->curpos = sendbuf->start + langtaglen + 14 ; /*-----------------------------------*/ /* Add the prlist to the send buffer */ /*-----------------------------------*/ if(prlist) { ToUINT16(sendbuf->curpos,prlistlen); sendbuf->curpos = sendbuf->curpos + 2; memcpy(sendbuf->curpos, prlist, prlistlen); sendbuf->curpos = sendbuf->curpos + prlistlen; } /*-----------------------------*/ /* Add the rest of the message */ /*-----------------------------*/ memcpy(sendbuf->curpos, buf, bufsize); /*----------------------*/ /* send the send buffer */ /*----------------------*/ result = SLPNetworkSendMessage(sock, socktype, sendbuf, destaddr, &timeout); if(result != 0) { /* we could not send the message for some reason */ /* we're done */ if(errno == ETIMEDOUT) { result = SLP_NETWORK_TIMED_OUT; } else { result = SLP_NETWORK_ERROR; } goto FINISHED; } /*----------------*/ /* Main recv loop */ /*----------------*/ do { if(SLPNetworkRecvMessage(sock, socktype, &recvbuf, &peeraddr, &timeout) != 0) { /* An error occured while receiving the message */ /* probably a just time out error. break for re-send. */ if(errno == ETIMEDOUT) { result = SLP_NETWORK_TIMED_OUT; } else { result = SLP_NETWORK_ERROR; } break; } else { /* Sneek in and check the XID */ if(AsUINT16(recvbuf->start+10) == xid) { rplycount += 1; /* Call the callback with the result and recvbuf */ if(callback(result,&peeraddr,recvbuf,cookie) == SLP_FALSE) { /* Caller does not want any more info */ /* We are done! */ goto CLEANUP; } /* add the peer to the previous responder list */ /* Note that prlist will be NULL if message type is not */ /* SLP_FUNCT_SRVRQST, SLP_FUNCT_ATTRRQST, or */ /* SLP_FUNCT_SRVTYPERQST) */ if(prlist && socktype == SOCK_DGRAM) { /* calculate the peeraddr string and length */ char* peeraddrstr = NULL; int peeraddrstrlen = 0; peeraddrstr = inet_ntoa(peeraddr.sin_addr); if(peeraddrstr) { peeraddrstrlen = strlen(peeraddrstr); /* Append to the prlist if we won't overflow */ if((prlistlen + peeraddrstrlen + 1) < mtu ) { /* append comma if necessary */ if(prlistlen != 0) { strcat(prlist,","); prlistlen ++; } /* append address string */ strcat(prlist,peeraddrstr); prlistlen += peeraddrstrlen; } } } } } }while(looprecv); } FINISHED: /*-----------------------------------------------*/ /* Notify the last time callback that we're done */ /*-----------------------------------------------*/ if(rplycount) { result = SLP_LAST_CALL; } if(result == SLP_NETWORK_TIMED_OUT && ISMCAST(destaddr->sin_addr)) { result = SLP_LAST_CALL; } callback(result, &peeraddr, recvbuf, cookie); if(result == SLP_LAST_CALL) { result = 0; } /*----------------*/ /* Free resources */ /*----------------*/ CLEANUP: if(prlist) xfree(prlist); SLPBufferFree(sendbuf); SLPBufferFree(recvbuf); return result;}/*=========================================================================*/ #ifndef MI_NOT_SUPPORTEDSLPError NetworkMcastRqstRply(PSLPHandleInfo handle,#elseSLPError NetworkMcastRqstRply(const char* langtag,#endif /* MI_NOT_SUPPORTED */ char* buf, char buftype, int bufsize, NetworkRplyCallback callback, void * cookie)/* Description: *//* *//* Broadcasts/multicasts SLP messages via multicast convergence algorithm *//* *//* langtag (IN) Language tag to use in SLP message header *//* *//* buf (IN) pointer to the portion of the SLP message to send. The *//* portion to that should be pointed to is everything after *//* the pr-list. NetworkXcastRqstRply() automatically *//* generates the header and the prlist. *//* *//* buftype (IN) the function-id to use in the SLPMessage header *//* *//* bufsize (IN) the size of the buffer pointed to by buf *//* *//* callback (IN) the callback to use for reporting results *//* *//* cookie (IN) the cookie to pass to the callback *//* *//* Returns - SLP_OK on success. SLP_ERROR on failure *//*=========================================================================*/ { struct timeval timeout; struct sockaddr_in peeraddr; SLPBuffer sendbuf = 0; SLPBuffer recvbuf = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -