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 + -
显示快捷键?