📄 libslp_network.c
字号:
SLPError result = 0; int langtaglen = 0; int prlistlen = 0; char* prlist = 0; int xid = 0; int mtu = 0; int size = 0; int xmitcount = 0; int rplycount = 0; int maxwait = 0; int totaltimeout = 0; int usebroadcast = 0; int timeouts[MAX_RETRANSMITS]; SLPIfaceInfo ifaceinfo; SLPXcastSockets xcastsocks;#ifdef DEBUG /* This function only supports multicast or broadcast of the following * messages */ if(buftype != SLP_FUNCT_SRVRQST && buftype != SLP_FUNCT_ATTRRQST && buftype != SLP_FUNCT_SRVTYPERQST && buftype != SLP_FUNCT_DASRVRQST) { return SLP_PARAMETER_BAD; }#endif /*----------------------------------------------------*/ /* Save off a few things we don't want to recalculate */ /*----------------------------------------------------*/#ifndef MI_NOT_SUPPORTED langtaglen = strlen(handle->langtag);#else langtaglen = strlen(langtag);#endif /* MI_NOT_SUPPORTED */ xid = SLPXidGenerate(); mtu = SLPPropertyAsInteger(SLPGetProperty("net.slp.MTU")); sendbuf = SLPBufferAlloc(mtu); if(sendbuf == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } #ifndef MI_NOT_SUPPORTED if(handle->McastIFList != NULL) { #ifdef DEBUG fprintf(stderr, "McastIFList = %s\n", handle->McastIFList); #endif SLPIfaceGetInfo(handle->McastIFList, &ifaceinfo); } else #endif /* MI_NOT_SUPPORTED */ if(SLPIfaceGetInfo(SLPGetProperty("net.slp.interfaces"),&ifaceinfo)) { result = SLP_NETWORK_ERROR; goto FINISHED; } usebroadcast = SLPPropertyAsBoolean(SLPGetProperty("net.slp.useBroadcast")); /*-----------------------------------*/ /* Multicast/broadcast wait timeouts */ /*-----------------------------------*/ maxwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.multicastMaximumWait")); SLPPropertyAsIntegerVector(SLPGetProperty("net.slp.multicastTimeouts"), timeouts, MAX_RETRANSMITS ); /* 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; } /*---------------------------------------------------------------------*/ /* 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. */ /*---------------------------------------------------------------------*/ prlist = (char*)xmalloc(mtu); if(prlist == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } *prlist = 0; prlistlen = 0; /*--------------------------*/ /* Main retransmission loop */ /*--------------------------*/ xmitcount = 0; while(xmitcount <= MAX_RETRANSMITS) { xmitcount++; 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; /*------------------------------------------------------------------*/ /* 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) { if(xmitcount == 0) { result = SLP_BUFFER_OVERFLOW; } goto FINISHED; } if((sendbuf = SLPBufferRealloc(sendbuf,size)) == 0) { result = SLP_MEMORY_ALLOC_FAILED; goto FINISHED; } /*-----------------------------------*/ /* Add the header to the send buffer */ /*-----------------------------------*/ /*version*/ *(sendbuf->start) = 2; /*function id*/ *(sendbuf->start + 1) = buftype; /*length*/ ToUINT24(sendbuf->start + 2, size); /*flags*/ ToUINT16(sendbuf->start + 5, SLP_FLAG_MCAST); /*ext offset*/ ToUINT24(sendbuf->start + 7,0); /*xid*/ ToUINT16(sendbuf->start + 10,xid); /*lang tag len*/ ToUINT16(sendbuf->start + 12,langtaglen); /*lang tag*/#ifndef MI_NOT_SUPPORTED memcpy(sendbuf->start + 14, handle->langtag, langtaglen);#else memcpy(sendbuf->start + 14, langtag, langtaglen);#endif /* MI_NOT_SUPPORTED */ 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 */ /*----------------------*/ if(usebroadcast) { result = SLPBroadcastSend(&ifaceinfo,sendbuf,&xcastsocks); } else { result = SLPMulticastSend(&ifaceinfo,sendbuf,&xcastsocks); } if(result != 0) { /* we could not send the message for some reason */ result = SLP_NETWORK_ERROR; goto FINISHED; } /*----------------*/ /* Main recv loop */ /*----------------*/ while(1) { #ifndef UNICAST_NOT_SUPPORTED int retval = 0; if((retval = SLPXcastRecvMessage(&xcastsocks, &recvbuf, &peeraddr, &timeout)) != 0) #else if(SLPXcastRecvMessage(&xcastsocks, &recvbuf, &peeraddr, &timeout) != 0) #endif { /* 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; }#ifndef UNICAST_NOT_SUPPORTED /* retval = SLP_RETRY_UNICAST signifies that we received a * multicast packet of size > MTU and hence we are now sending * a unicast request to this IP-address */ if ( retval == SLP_RETRY_UNICAST ) { int tcpsockfd, retval1, retval2, unicastwait = 0; unicastwait = SLPPropertyAsInteger(SLPGetProperty("net.slp.unicastMaximumWait")); timeout.tv_sec = unicastwait / 1000; timeout.tv_usec = (unicastwait % 1000) * 1000; tcpsockfd = SLPNetworkConnectStream(&peeraddr, &timeout); if ( tcpsockfd >= 0 ) { ToUINT16(sendbuf->start + 5, SLP_FLAG_UCAST); xid = SLPXidGenerate(); ToUINT16(sendbuf->start + 10,xid); retval1 = SLPNetworkSendMessage(tcpsockfd, SOCK_STREAM, sendbuf, &peeraddr, &timeout); if ( retval1 != 0 ) { /* we could not send the message for some reason */ /* we close the TCP connection and break */ if(errno == ETIMEDOUT) { result = SLP_NETWORK_TIMED_OUT; } else { result = SLP_NETWORK_ERROR; }#ifdef _WIN32 closesocket(tcpsockfd);#else close(tcpsockfd); #endif break; } retval2 = SLPNetworkRecvMessage(tcpsockfd, SOCK_STREAM, &recvbuf, &peeraddr, &timeout); if ( retval2 != 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; } #ifdef _WIN32 closesocket(tcpsockfd);#else close(tcpsockfd);#endif break; } #ifdef _WIN32 closesocket(tcpsockfd);#else close(tcpsockfd);#endif result = SLP_OK; goto SNEEK; } else { /* Unsuccessful in opening a TCP connection */ /* just break and retry everything */ break; } } else {#endif break;#ifndef UNICAST_NOT_SUPPORTED }#endif }#ifndef UNICAST_NOT_SUPPORTED SNEEK:#endif /* Sneek in and check the XID */ if(AsUINT16(recvbuf->start+10) == xid) { rplycount += 1; /* Call the callback with the result and recvbuf */#ifndef MI_NOT_SUPPORTED if (cookie == NULL) { cookie = (PSLPHandleInfo)handle;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -