slpd_outgoing.c
来自「SLP协议在linux下的实现。此版本为1.2.1版。官方网站为www.open」· C语言 代码 · 共 680 行 · 第 1/2 页
C
680 行
/***************************************************************************//* *//* Project: OpenSLP - OpenSource implementation of Service Location *//* Protocol Version 2 *//* *//* File: slpd_outgoing.c *//* *//* Abstract: Handles "outgoing" network conversations requests made by *//* other agents to slpd. (slpd_incoming.c handles reqests *//* made by other agents to slpd) *//* *//*-------------------------------------------------------------------------*//* *//* 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_outgoing.h"#include "slpd_property.h"#include "slpd_process.h"#include "slpd_log.h"#include "slpd_knownda.h"/*=========================================================================*//* common code includes *//*=========================================================================*/#include "slp_message.h"/*=========================================================================*/SLPList G_OutgoingSocketList = {0,0,0};/*=========================================================================*//*-------------------------------------------------------------------------*/void OutgoingDatagramRead(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{ int bytesread; 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; SLPDProcessMessage(&(sock->peeraddr), sock->recvbuf, &(sock->sendbuf)); /* Completely ignore the message */ }}/*-------------------------------------------------------------------------*/void OutgoingStreamReconnect(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{#ifdef _WIN32 u_long fdflags;#else int fdflags;#endif /*-----------------------------------------------------------------*/ /* If socket is already being reconnected but is reconnect blocked */ /* just return. Blocking connect sockets will eventually time out */ /*-----------------------------------------------------------------*/ if(sock->state == STREAM_CONNECT_BLOCK) { return; } #ifdef DEBUG /* Log that reconnect warning */ SLPDLog("WARNING: Reconnect to agent at %s. Agent may not be making efficient \n" " use of TCP.\n", inet_ntoa(sock->peeraddr.sin_addr)); #endif /*----------------------------------------------------------------*/ /* Make sure we have not reconnected too many times */ /* We only allow SLPD_CONFIG_MAX_RECONN reconnection retries */ /* before we stop */ /*----------------------------------------------------------------*/ sock->reconns += 1; if ( sock->reconns > SLPD_CONFIG_MAX_RECONN ) { sock->state = SOCKET_CLOSE; SLPDLog("WARNING: Reconnect tries to agent at %s exceeded maximum. It\n" " is possible that the agent is malicious. Check it out!\n", inet_ntoa(sock->peeraddr.sin_addr)); return; } /*----------------------------------------------------------------*/ /* Close the existing socket to clean the stream and open an new */ /* socket */ /*----------------------------------------------------------------*/ CloseSocket(sock->fd); sock->fd = socket(PF_INET,SOCK_STREAM,0); if ( sock->fd < 0 ) { sock->state = SOCKET_CLOSE; return; } /*---------------------------------------------*/ /* Set the new socket to enable nonblocking IO */ /*---------------------------------------------*/#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 /*--------------------------*/ /* Connect a the new socket */ /*--------------------------*/ if ( connect(sock->fd, (struct sockaddr *)&(sock->peeraddr), sizeof(struct sockaddr_in)) ) {#ifdef _WIN32 if ( WSAEWOULDBLOCK == WSAGetLastError() )#else if ( errno == EINPROGRESS )#endif { /* Connect blocked */ sock->state = STREAM_CONNECT_BLOCK; return; } } /* Connection occured immediately. Set to WRITE_FIRST so whole */ /* packet will be written */ sock->state = STREAM_WRITE_FIRST;}/*-------------------------------------------------------------------------*/void OutgoingStreamRead(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{ int bytesread, recvlen; 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 >= 5 && *peek == 2 ) { recvlen = AsUINT24(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 if ( bytesread == -1 ) {#ifdef _WIN32 if ( WSAEWOULDBLOCK != WSAGetLastError() )#else if ( errno != EWOULDBLOCK )#endif { /* Error occured or connection was closed. Try to reconnect */ /* Socket will be closed if connect times out */ OutgoingStreamReconnect(socklist,sock); } } else { sock->state = SOCKET_CLOSE; } } 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 because of activity */ sock->age = 0; /* move buffer pointers */ sock->recvbuf->curpos += bytesread; /* check to see if everything was read */ if ( sock->recvbuf->curpos == sock->recvbuf->end ) { switch ( SLPDProcessMessage(&(sock->peeraddr), sock->recvbuf, &(sock->sendbuf)) ) { case SLP_ERROR_DA_BUSY_NOW: sock->state = STREAM_WRITE_WAIT; break; case SLP_ERROR_PARSE_ERROR: case SLP_ERROR_VER_NOT_SUPPORTED: sock->state = SOCKET_CLOSE; break; default: /* End of outgoing message exchange. Unlink */ /* send buf from to do list and free it */ SLPBufferFree(sock->sendbuf); sock->sendbuf = NULL; sock->state = STREAM_WRITE_FIRST; /* clear the reconnection count since we actually * transmitted a successful message exchange */ sock->reconns = 0; break; } } } else {#ifdef _WIN32 if ( WSAEWOULDBLOCK != WSAGetLastError() )#else if ( errno != EWOULDBLOCK )#endif { /* Error occured or connection was closed. Try to reconnect */ /* Socket will be closed if connect times out */ OutgoingStreamReconnect(socklist,sock); } } }}/*-------------------------------------------------------------------------*/void OutgoingStreamWrite(SLPList* socklist, SLPDSocket* sock)/*-------------------------------------------------------------------------*/{ int byteswritten; int flags = 0;#if defined(MSG_DONTWAIT) flags = MSG_DONTWAIT;#endif if ( sock->state == STREAM_WRITE_FIRST ) { /* set sendbuf to the first item in the send list if it is not set */ if(sock->sendbuf == NULL) { sock->sendbuf = (SLPBuffer)sock->sendlist.head; if ( sock->sendbuf == NULL ) { /* there is nothing in the to do list */ sock->state = STREAM_CONNECT_IDLE; return; } /* Unlink the send buffer we are sending from the send list */ SLPListUnlink(&(sock->sendlist),(SLPListItem*)(sock->sendbuf)); } /* 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 ) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?