📄 slpd_incoming.c
字号:
/***************************************************************************//* *//* Project: OpenSLP - OpenSource implementation of Service Location *//* Protocol Version 2 *//* *//* File: slpd_incoming.c *//* *//* Abstract: Handles "incoming" network conversations requests made by *//* other agents to slpd. (slpd_outgoing.c handles reqests *//* made by slpd to other agents) *//* *//*-------------------------------------------------------------------------*//* *//* 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. *//* *//***************************************************************************//*=========================================================================*//* slpd includes *//*=========================================================================*/#include "slpd_incoming.h"#include "slpd_socket.h"#include "slpd_process.h"#include "slpd_property.h"#include "slpd_log.h"/*=========================================================================*//* common code includes *//*=========================================================================*/#include "slp_xmalloc.h"#include "slp_message.h"/*=========================================================================*/SLPList G_IncomingSocketList = {0,0,0};/*=========================================================================*//*-------------------------------------------------------------------------*/void IncomingDatagramRead(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{ int bytesread; int bytestowrite; int byteswritten; int peeraddrlen = sizeof(struct sockaddr_in); bytesread = recvfrom(sock->fd, sock->recvbuf->start, SLP_MAX_DATAGRAM_SIZE, 0, (struct sockaddr *) &(sock->peeraddr), &peeraddrlen); if (bytesread > 0) { sock->recvbuf->end = sock->recvbuf->start + bytesread; switch (SLPDProcessMessage(&sock->peeraddr, sock->recvbuf, &(sock->sendbuf))) { case SLP_ERROR_PARSE_ERROR: case SLP_ERROR_VER_NOT_SUPPORTED: case SLP_ERROR_MESSAGE_NOT_SUPPORTED: break; default: /* check to see if we should send anything */ bytestowrite = sock->sendbuf->end - sock->sendbuf->start; if (bytestowrite > 0) { byteswritten = sendto(sock->fd, sock->sendbuf->start, bytestowrite, 0, (struct sockaddr *)&(sock->peeraddr), sizeof(struct sockaddr_in)); if (byteswritten != bytestowrite) { SLPDLog("NETWORK_ERROR - %d replying %s\n", errno, inet_ntoa(sock->peeraddr.sin_addr)); } } } }}/*-------------------------------------------------------------------------*/void IncomingStreamWrite(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{ int byteswritten, flags = 0;#if defined(MSG_DONTWAIT) flags = MSG_DONTWAIT;#endif if (sock->state == STREAM_WRITE_FIRST) { /* make sure that the start and curpos pointers are the same */ sock->sendbuf->curpos = sock->sendbuf->start; sock->state = STREAM_WRITE; } if (sock->sendbuf->end - sock->sendbuf->start != 0) { byteswritten = send(sock->fd, sock->sendbuf->curpos, sock->sendbuf->end - sock->sendbuf->start, flags); if (byteswritten > 0) { /* reset lifetime to max because of activity */ sock->age = 0; sock->sendbuf->curpos += byteswritten; if (sock->sendbuf->curpos == sock->sendbuf->end) { /* message is completely sent */ sock->state = STREAM_READ_FIRST; } } else {#ifdef _WIN32 if (WSAEWOULDBLOCK == WSAGetLastError())#else if (errno == EWOULDBLOCK)#endif { /* Error occured or connection was closed */ sock->state = SOCKET_CLOSE; } } }}/*-------------------------------------------------------------------------*/void IncomingStreamRead(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{ int bytesread, recvlen = 0; char peek[16]; int peeraddrlen = sizeof(struct sockaddr_in); if (sock->state == STREAM_READ_FIRST) { /*---------------------------------------------------*/ /* take a peek at the packet to get size information */ /*---------------------------------------------------*/ bytesread = recvfrom(sock->fd, peek, 16, MSG_PEEK, (struct sockaddr *)&(sock->peeraddr), &peeraddrlen); if (bytesread > 0 && bytesread >= (*peek == 2 ? 5 : 4)) { if (*peek == 2) recvlen = AsUINT24(peek + 2); else if (*peek == 1) /* SLPv1 packet */ recvlen = AsUINT16(peek + 2); /* one byte is minimum */ if (recvlen <= 0) recvlen = 1; /* allocate the recvbuf big enough for the whole message */ sock->recvbuf = SLPBufferRealloc(sock->recvbuf,recvlen); if (sock->recvbuf) { sock->state = STREAM_READ; } else { SLPDLog("INTERNAL_ERROR - out of memory!\n"); sock->state = SOCKET_CLOSE; } } else { sock->state = SOCKET_CLOSE; return; } } if (sock->state == STREAM_READ) { /*------------------------------*/ /* recv the rest of the message */ /*------------------------------*/ bytesread = recv(sock->fd, sock->recvbuf->curpos, sock->recvbuf->end - sock->recvbuf->curpos, 0); if (bytesread > 0) { /* reset age to max because of activity */ sock->age = 0; sock->recvbuf->curpos += bytesread; if (sock->recvbuf->curpos == sock->recvbuf->end) { switch (SLPDProcessMessage(&sock->peeraddr, sock->recvbuf, &(sock->sendbuf))) { case SLP_ERROR_PARSE_ERROR: case SLP_ERROR_VER_NOT_SUPPORTED: case SLP_ERROR_MESSAGE_NOT_SUPPORTED: sock->state = SOCKET_CLOSE; break; default: sock->state = STREAM_WRITE_FIRST; IncomingStreamWrite(socklist, sock); } } } else { /* error in recv() or eof */ sock->state = SOCKET_CLOSE; } }}/*-------------------------------------------------------------------------*/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); } } }}/*=========================================================================*/void SLPDIncomingHandler(int* fdcount,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -