/*-------------------------------------------------------------------------*/ void IncomingSocketListen(SLPList* socklist, SLPDSocket* sock) /*-------------------------------------------------------------------------*/ { SLPDSocket* connsock; const int lowat = SLPD_SMALLEST_MESSAGE; /* Only accept if we can. If we still maximum number of sockets, just*/ /* ignore the connection */ if(socklist->count < SLPD_MAX_SOCKETS) { connsock = SLPDSocketAlloc(); if(connsock) { connsock->peerinfo.peeraddrlen = sizeof(sock->peerinfo.peeraddr); connsock->fd = accept(sock->fd, &(connsock->peerinfo.peeraddr), &(connsock->peerinfo .peeraddrlen)); if(connsock->fd >= 0) { setsockopt(connsock->fd,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat)); setsockopt(connsock->fd,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat)); connsock->peerinfo.peertype = SLPD_PEER_ACCEPTED; connsock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); connsock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); connsock->state = STREAM_READ_FIRST; sock->age = 0; SLPListLinkHead(socklist,(SLPListItem*)connsock); } else { SLPDSocketFree(connsock); } } } }
/*==========================================================================*/ SLPDSocket* SLPDSocketCreateDatagram(struct in_addr* peeraddr, int type) /* myaddr - (IN) the address of the interface to join mcast on */ /* */ /* peeraddr - (IN) the address of the peer to connect to */ /* */ /* type (IN) DATAGRAM_UNICAST, DATAGRAM_MULTICAST, DATAGRAM_BROADCAST */ /* */ /* Returns: A datagram socket SLPDSocket->state will be set to */ /* DATAGRAM_UNICAST, DATAGRAM_MULTICAST, or DATAGRAM_BROADCAST */ /*==========================================================================*/ { SLPDSocket* sock; sock = SLPDSocketAlloc(); if(sock) { sock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); if(sock->recvbuf && sock->sendbuf) { sock->fd = socket(PF_INET, SOCK_DGRAM, 0); if(sock->fd >=0) { switch(type) { case DATAGRAM_BROADCAST: EnableBroadcast(sock->fd); break; case DATAGRAM_MULTICAST: SetMulticastTTL(sock->fd,G_SlpdProperty.multicastTTL); break; default: break; } sock->peeraddr.sin_family = AF_INET; sock->peeraddr.sin_addr = *peeraddr; sock->peeraddr.sin_port = htons(SLP_RESERVED_PORT); sock->state = type; } else { SLPDSocketFree(sock); sock = 0; } } else { SLPDSocketFree(sock); sock = 0; } } return sock; }
/*-------------------------------------------------------------------------*/ void IncomingSocketListen(SLPList* socklist, SLPDSocket* sock) /*-------------------------------------------------------------------------*/ { int fdflags; sockfd_t fd; SLPDSocket* connsock; struct sockaddr_in peeraddr; socklen_t peeraddrlen; #ifdef WIN32 const char lowat = SLPD_SMALLEST_MESSAGE; #else const int lowat = SLPD_SMALLEST_MESSAGE; #endif /* Only accept if we can. If we still maximum number of sockets, just*/ /* ignore the connection */ if (socklist->count < SLPD_MAX_SOCKETS) { peeraddrlen = sizeof(peeraddr); fd = accept(sock->fd, (struct sockaddr *) &peeraddr, &peeraddrlen); if (fd >= 0) { connsock = SLPDSocketAlloc(); if (connsock) { /* setup the accepted socket */ connsock->fd = fd; connsock->peeraddr = peeraddr; connsock->state = STREAM_READ_FIRST; /* Set the low water mark on the accepted socket */ setsockopt(connsock->fd,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat)); setsockopt(connsock->fd,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat)); /* set accepted socket to non blocking */ #ifdef WIN32 fdflags = 1; ioctlsocket(connsock->fd, FIONBIO, &fdflags); #else fdflags = fcntl(connsock->fd, F_GETFL, 0); fcntl(connsock->fd,F_SETFL, fdflags | O_NONBLOCK); #endif SLPListLinkHead(socklist,(SLPListItem*)connsock); } } } }
/*==========================================================================*/ SLPDSocket* SLPDSocketCreateListen(struct in_addr* peeraddr) /* */ /* peeraddr - (IN) the address of the peer to connect to */ /* */ /* type (IN) DATAGRAM_UNICAST, DATAGRAM_MULTICAST, DATAGRAM_BROADCAST */ /* */ /* Returns: A listening socket. SLPDSocket->state will be set to */ /* SOCKET_LISTEN. Returns NULL on error */ /*==========================================================================*/ { int fdflags; SLPDSocket* sock; sock = SLPDSocketAlloc(); if(sock) { sock->fd = socket(PF_INET, SOCK_STREAM, 0); if(sock->fd >= 0) { if(BindSocketToInetAddr(sock->fd, peeraddr) >= 0) { if(listen(sock->fd,5) == 0) { /* Set socket to non-blocking so subsequent calls to */ /* accept will *never* block */ #ifdef WIN32 fdflags = 1; ioctlsocket(sock->fd, FIONBIO, &fdflags); #else fdflags = fcntl(sock->fd, F_GETFL, 0); fcntl(sock->fd,F_SETFL, fdflags | O_NONBLOCK); #endif sock->state = SOCKET_LISTEN; return sock; } } } } if(sock) { SLPDSocketFree(sock); } return 0; }
/*==========================================================================*/ SLPDSocket* SLPDSocketCreateConnected(struct in_addr* addr) /* */ /* addr - (IN) the address of the peer to connect to */ /* */ /* Returns: A connected socket or a socket in the process of being connected*/ /* if the socket was connected the SLPDSocket->state will be set */ /* to writable. If the connect would block, SLPDSocket->state will*/ /* be set to connect. Return NULL on error */ /*==========================================================================*/ { #ifdef WIN32 char lowat; u_long fdflags; #else int lowat; int fdflags; #endif SLPDSocket* sock = 0; sock = SLPDSocketAlloc(); if(sock == 0) { goto FAILURE; } /* create the stream socket */ sock->fd = socket(PF_INET,SOCK_STREAM,0); if(sock->fd < 0) { goto FAILURE; } /* set the socket to non-blocking */ #ifdef WIN32 fdflags = 1; ioctlsocket(sock->fd, FIONBIO, &fdflags); #else fdflags = fcntl(sock->fd, F_GETFL, 0); fcntl(sock->fd,F_SETFL, fdflags | O_NONBLOCK); #endif /* zero then set peeraddr to connect to */ sock->peeraddr.sin_family = AF_INET; sock->peeraddr.sin_port = htons(SLP_RESERVED_PORT); sock->peeraddr.sin_addr = *addr; /* set the receive and send buffer low water mark to 18 bytes (the length of the smallest slpv2 message) */ lowat = 18; setsockopt(sock->fd,SOL_SOCKET,SO_RCVLOWAT,&lowat,sizeof(lowat)); setsockopt(sock->fd,SOL_SOCKET,SO_SNDLOWAT,&lowat,sizeof(lowat)); /* non-blocking connect */ if(connect(sock->fd, (struct sockaddr *) &(sock->peeraddr), sizeof(sock->peeraddr)) == 0) { /* Connection occured immediately */ sock->state = STREAM_CONNECT_IDLE; } else { #ifdef WIN32 if(WSAEWOULDBLOCK == WSAGetLastError()) #else if(errno == EINPROGRESS) #endif { /* Connect would have blocked */ sock->state = STREAM_CONNECT_BLOCK; } else { goto FAILURE; } } return sock; /* cleanup on failure */ FAILURE: if(sock) { CloseSocket(sock->fd); xfree(sock); sock = 0; } return sock; }
/*==========================================================================*/ SLPDSocket* SLPDSocketCreateBoundDatagram(struct in_addr* myaddr, struct in_addr* peeraddr, int type) /* myaddr - (IN) the address of the interface to join mcast on */ /* */ /* peeraddr - (IN) the address of the peer to connect to */ /* */ /* type (IN) DATAGRAM_UNICAST, DATAGRAM_MULTICAST, DATAGRAM_BROADCAST */ /* */ /* Returns: A datagram socket SLPDSocket->state will be set to */ /* DATAGRAM_UNICAST, DATAGRAM_MULTICAST, or DATAGRAM_BROADCAST */ /*==========================================================================*/ { SLPDSocket* sock; struct in_addr* bindaddr; /*------------------------------------------*/ /* Adjust for multicast binding differences */ /*------------------------------------------*/ #ifdef LINUX bindaddr = peeraddr; #else if(type == DATAGRAM_MULTICAST) bindaddr = NULL; /* must bind to INADDR_ANY for multicast */ else bindaddr = peeraddr; #endif /*------------------------*/ /* Create and bind socket */ /*------------------------*/ sock = SLPDSocketAlloc(); if(sock) { sock->recvbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->sendbuf = SLPBufferAlloc(SLP_MAX_DATAGRAM_SIZE); sock->fd = socket(PF_INET, SOCK_DGRAM, 0); if(sock->fd >=0) { if(BindSocketToInetAddr(sock->fd, bindaddr) == 0) { if(peeraddr != NULL) { sock->peeraddr.sin_addr = *peeraddr; } switch(type) { case DATAGRAM_MULTICAST: if(JoinSLPMulticastGroup(sock->fd, peeraddr, myaddr) == 0) { sock->state = DATAGRAM_MULTICAST; goto SUCCESS; } break; case DATAGRAM_BROADCAST: if(EnableBroadcast(sock->fd) == 0) { sock->state = DATAGRAM_BROADCAST; goto SUCCESS; } break; case DATAGRAM_UNICAST: default: sock->state = DATAGRAM_UNICAST; goto SUCCESS; break; } } } } if(sock) { SLPDSocketFree(sock); } sock = 0; SUCCESS: return sock; }