📄 slp_network.c
字号:
/***************************************************************************//* *//* Project: OpenSLP - OpenSource implementation of Service Location *//* Protocol *//* *//* File: slp_network.c *//* *//* Abstract: Implementation for functions that are related *//* network (and ipc) communication. *//* *//*-------------------------------------------------------------------------*//* *//* Please submit patches to http://www.openslp.org *//* *//*-------------------------------------------------------------------------*//* *//* Copyright (C) 2000 Caldera Systems, Inc *//* All rights reserved. *//* *//* Redistribution and use in source and binary forms, with or without *//* modification, are permitted provided that the following conditions are *//* met: */ /* *//* Redistributions of source code must retain the above copyright *//* notice, this list of conditions and the following disclaimer. *//* *//* Redistributions in binary form must reproduce the above copyright *//* notice, this list of conditions and the following disclaimer in *//* the documentation and/or other materials provided with the *//* distribution. *//* *//* Neither the name of Caldera Systems nor the names of its *//* contributors may be used to endorse or promote products derived *//* from this software without specific prior written permission. *//* *//* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *//* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *//* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *//* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA *//* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *//* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *//* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *//* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *//* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *//* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE *//* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* *//***************************************************************************/#include "slp_network.h"/*=========================================================================*/ int SLPNetworkConnectStream(struct sockaddr_in* peeraddr, struct timeval* timeout)/* Connect a TCP stream to the specified peer *//* *//* peeraddr (IN) pointer to the peer to connect to *//* *//* timeout (IN) pointer to the maximum time to spend connecting *//* *//* returns: a connected socket or -1 *//*=========================================================================*/ {#ifdef _WIN32 char lowat;#else int lowat;#endif int result; /* TODO: Make this connect non-blocking so that it will timeout */ result = socket(AF_INET,SOCK_STREAM,0); if(result >= 0) { if(connect(result, (struct sockaddr*)peeraddr, sizeof(struct sockaddr_in)) == 0) { /* set the receive and send buffer low water mark to 18 bytes (the length of the smallest slpv2 message) */ lowat = 18; setsockopt(result,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat)); setsockopt(result,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat)); return result;; } else { close(result); result = -1; } } return result;}/*=========================================================================*/ int SLPNetworkConnectToMulticast(struct sockaddr_in* peeraddr, int ttl)/* Creates a socket and provides a peeraddr to send to *//* *//* peeraddr (OUT) pointer to receive the connected DA's address *//* *//* ttl (IN) ttl for the mcast socket *//* *//* Returns Valid socket or -1 if no DA connection can be made *//*=========================================================================*/{ int sockfd;#if defined(linux) int optarg;#else /* Solaris and Tru64 expect a unsigned char parameter */ unsigned char optarg;#endif#ifdef _WIN32 BOOL Reuse = TRUE; int TTLArg; struct sockaddr_in mysockaddr; memset(&mysockaddr, 0, sizeof(mysockaddr)); mysockaddr.sin_family = AF_INET; mysockaddr.sin_port = 0;#endif /* setup multicast socket */ sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd >= 0) { peeraddr->sin_family = AF_INET; peeraddr->sin_port = htons(SLP_RESERVED_PORT); peeraddr->sin_addr.s_addr = htonl(SLP_MCAST_ADDRESS); optarg = ttl;#ifdef _WIN32 TTLArg = ttl; if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&Reuse, sizeof(Reuse)) || bind(sockfd, (struct sockaddr *)&mysockaddr, sizeof(mysockaddr)) || setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&TTLArg, sizeof(TTLArg))) { return -1; }#else if(setsockopt(sockfd,IPPROTO_IP,IP_MULTICAST_TTL,&optarg,sizeof(optarg))) { return -1; }#endif } return sockfd;}/*=========================================================================*/ int SLPNetworkConnectToBroadcast(struct sockaddr_in* peeraddr)/* Creates a socket and provides a peeraddr to send to *//* *//* peeraddr (OUT) pointer to receive the connected DA's address */ /* *//* Returns Valid socket or -1 if no DA connection can be made *//*=========================================================================*/{ int sockfd;#ifdef _WIN32 BOOL on = 1;#else int on = 1;#endif /* setup broadcast */ sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd >= 0) { peeraddr->sin_family = AF_INET; peeraddr->sin_port = htons(SLP_RESERVED_PORT); peeraddr->sin_addr.s_addr = htonl(SLP_BCAST_ADDRESS); if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (char*)&on, sizeof(on))) { return -1; } } return sockfd;}/*=========================================================================*/ int SLPNetworkSendMessage(int sockfd, int socktype, SLPBuffer buf, struct sockaddr_in* peeraddr, struct timeval* timeout)/* Sends a message *//* *//* Returns - zero on success non-zero on failure *//* *//* errno EPIPE error during write *//* ETIME read timed out *//*=========================================================================*/ { fd_set writefds; int xferbytes; int flags = 0;#if defined(MSG_NOSIGNAL) flags = MSG_NOSIGNAL;#endif buf->curpos = buf->start; while(buf->curpos < buf->end) { FD_ZERO(&writefds); FD_SET(sockfd, &writefds); xferbytes = select(sockfd + 1, 0, &writefds, 0, timeout); if(xferbytes > 0) { if(socktype == SOCK_DGRAM) { xferbytes = sendto(sockfd, buf->curpos, buf->end - buf->curpos, flags, (struct sockaddr *)peeraddr, sizeof(struct sockaddr_in)); } else { xferbytes = send(sockfd, buf->curpos, buf->end - buf->curpos, flags); } if(xferbytes > 0) { buf->curpos = buf->curpos + xferbytes; } else { errno = EPIPE; return -1; } } else if(xferbytes == 0) { /* timed out */ errno = ETIMEDOUT; return -1; } else { errno = EPIPE; return -1; } } return 0;}/*=========================================================================*/ int SLPNetworkRecvMessage(int sockfd, int socktype, SLPBuffer* buf, struct sockaddr_in* peeraddr, struct timeval* timeout)/* Receives a message *//* *//* Returns - zero on success, non-zero on failure *//* *//* errno ENOTCONN error during read *//* ETIME read timed out *//* ENOMEM out of memory *//* EINVAL parse error *//*=========================================================================*/ { int xferbytes, recvlen; fd_set readfds; char peek[16]; int peeraddrlen = sizeof(struct sockaddr_in); /*---------------------------------------------------------------*/ /* take a peek at the packet to get version and size information */ /*---------------------------------------------------------------*/ FD_ZERO(&readfds); FD_SET(sockfd, &readfds); xferbytes = select(sockfd + 1, &readfds, 0 , 0, timeout); if(xferbytes > 0) { if(socktype == SOCK_DGRAM) { xferbytes = recvfrom(sockfd, peek, 16, MSG_PEEK, (struct sockaddr *)peeraddr, &peeraddrlen); } else { xferbytes = recv(sockfd, peek, 16, MSG_PEEK); } if(xferbytes <= 0) {#ifdef _WIN32 if(WSAGetLastError() != WSAEMSGSIZE) { errno = ENOTCONN; return -1; }#else errno = ENOTCONN; return -1;#endif } } else if(xferbytes == 0) { errno = ETIMEDOUT; return -1; } else { errno = ENOTCONN; return -1; } /*------------------------------*/ /* Read the rest of the message */ /*------------------------------*/ /* check the version */ if(xferbytes >= 5 && *peek == 2) { /* allocate the recvmsg big enough for the whole message */ recvlen = AsUINT24(peek + 2); /* one byte is minimum */ if (recvlen <= 0) recvlen = 1; *buf = SLPBufferRealloc(*buf, recvlen); if(*buf) { while((*buf)->curpos < (*buf)->end) { FD_ZERO(&readfds); FD_SET(sockfd, &readfds); xferbytes = select(sockfd + 1, &readfds, 0 , 0, timeout); if(xferbytes > 0) { xferbytes = recv(sockfd, (*buf)->curpos, (*buf)->end - (*buf)->curpos, 0); if(xferbytes > 0) { (*buf)->curpos = (*buf)->curpos + xferbytes; } else { errno = ENOTCONN; return -1; } } else if(xferbytes == 0) { errno = ETIMEDOUT; return -1; } else { errno = ENOTCONN; return -1; } } /* end of main read while. */ } else { errno = ENOMEM; return -1; } } else { errno = EINVAL; return -1; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -