예제 #1
0
/*-------------------------------------------------------------------------*/
int ParseHeader(SLPBuffer buffer, SLPHeader* header)
/*                                                                         */
/* Returns  - Zero on success, SLP_ERROR_VER_NOT_SUPPORTED, or             */
/*            SLP_ERROR_PARSE_ERROR.                                       */
/*-------------------------------------------------------------------------*/
{
    header->version     = *(buffer->curpos);
    header->functionid  = *(buffer->curpos + 1);
    header->length      = AsUINT24(buffer->curpos + 2);
    header->flags       = AsUINT16(buffer->curpos + 5);
    header->extoffset   = AsUINT24(buffer->curpos + 7);
    header->xid         = AsUINT16(buffer->curpos + 10);
    header->langtaglen  = AsUINT16(buffer->curpos + 12);
    header->langtag     = buffer->curpos + 14;

    if(header->version != 2)
    {
        return SLP_ERROR_VER_NOT_SUPPORTED;
    }

    if(header->functionid > SLP_FUNCT_SAADVERT)
    {
        /* invalid function id */
        return SLP_ERROR_PARSE_ERROR;
    }

    if(header->length != buffer->end - buffer->start ||
       header->length < 18)
    {
        /* invalid length 18 bytes is the smallest v2 message*/
        return SLP_ERROR_PARSE_ERROR;
    }

    if(header->flags & 0x1fff)
    {
        /* invalid flags */
        return SLP_ERROR_PARSE_ERROR;
    }

    buffer->curpos = buffer->curpos + header->langtaglen + 14;

    return 0;
}
예제 #2
0
/*-------------------------------------------------------------------------*/
int ParseHeader(SLPBuffer buffer, SLPHeader* header)
/*                                                                         */
/* Returns  - Zero on success, SLP_ERROR_VER_NOT_SUPPORTED, or             */
/*            SLP_ERROR_PARSE_ERROR.                                       */
/*-------------------------------------------------------------------------*/
{
    header->version     = *(buffer->curpos);
    header->functionid  = *(buffer->curpos + 1);

#if defined(ENABLE_SLPv1)
    if(header->version == 1)
    {
        return v1ParseHeader(buffer, header);
    }
#endif

    if(header->version != 2)
    {
        return SLP_ERROR_VER_NOT_SUPPORTED;
    }

    header->length      = AsUINT24(buffer->curpos + 2);
    header->flags       = AsUINT16(buffer->curpos + 5);
    header->encoding    = 0; /* not used for SLPv2 */
    header->extoffset   = AsUINT24(buffer->curpos + 7);
    header->xid         = AsUINT16(buffer->curpos + 10);
    header->langtaglen  = AsUINT16(buffer->curpos + 12);
    header->langtag     = buffer->curpos + 14;

    /* check for invalid function id */
    if(header->functionid > SLP_FUNCT_SAADVERT)
    {
        return SLP_ERROR_PARSE_ERROR;
    }

    /* check for invalid length 18 bytes is the smallest v2 message*/
    if(header->length != buffer->end - buffer->start ||
       header->length < 18)
    {
        return SLP_ERROR_PARSE_ERROR;
    }

    /* check for invalid flags */
    if(header->flags & 0x1fff)
    {
        return SLP_ERROR_PARSE_ERROR;
    }
    buffer->curpos = buffer->curpos + header->langtaglen + 14;

    /* check for invalid langtaglen */
    if((void*)(header->langtag + header->langtaglen) > (void*)buffer->end)
    {
        return SLP_ERROR_PARSE_ERROR;
    }

    /* check for invalid ext offset */
    if(buffer->start + header->extoffset > buffer->end)
    {
        return SLP_ERROR_PARSE_ERROR;
    }

    return 0;
}
예제 #3
0
/*-------------------------------------------------------------------------*/
void OutgoingStreamRead(SLPList* socklist, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    int     bytesread;
    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 )
        {
            /* allocate the recvbuf big enough for the whole message */
            sock->recvbuf = SLPBufferRealloc(sock->recvbuf,AsUINT24(peek+2));
            if ( sock->recvbuf )
            {
                sock->state = STREAM_READ;
            }
            else
            {
                SLPDLog("INTERNAL_ERROR - out of memory!\n");
                sock->state = SOCKET_CLOSE;
            }
        }
        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);
            }
        }       
    }

    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((SLPBuffer)SLPListUnlink(&(sock->sendlist),(SLPListItem*)(sock->sendbuf)));
                    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);
            }
        }
    }
}
예제 #4
0
/*-------------------------------------------------------------------------*/
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)
        {

            if (*peek == 2)
                recvlen = AsUINT24(peek + 2);
            else if (*peek == 1) /* SLPv1 packet */
                recvlen = AsUINT16(peek + 2);
            /* 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() */
            sock->state = SOCKET_CLOSE;
        }
    }
}
예제 #5
0
/*=========================================================================*/
int SLPXcastRecvMessage(const SLPXcastSockets* sockets,
                        SLPBuffer* buf,
                        struct sockaddr_in* peeraddr,
                        struct timeval* timeout)
/* Description: 
�* � �Receives datagram messages from one of the sockets in the specified �
�* � �SLPXcastsSockets structure
�* �
�* Parameters:
�* � �sockets (IN) Pointer to the SOPXcastSockets structure that describes
�* � � � � � � � � which sockets to read messages from.
�* � �buf � � (OUT) Pointer to SLPBuffer that will contain the message upon
�* � � � � � � � � �successful return.
�* � �peeraddr (OUT) Pointer to struc sockaddr_in that will contain the
�* � � � � � � � � � address of the peer that sent the received message.
�* � �timeout (IN/OUT) pointer to the struct timeval that indicates how much
�* � � � � � � � � � � time to wait for a message to arrive
�*
�* Returns:
�* � �Zero on success, non-zero with errno set on failure.
�*========================================================================*/
{
    fd_set  readfds;
    int     highfd;
    int     i;
    int     readable;
    size_t  bytesread;
    int     recvloop;
    int     peeraddrlen = sizeof(struct sockaddr_in);
    char    peek[16];
    int     result;  

    /* recv loop */
    recvloop = 1;
    while(recvloop)
    {
        /* Set the readfds */
        FD_ZERO(&readfds);
        highfd = 0;
        for (i=0; i<sockets->sock_count; i++)
        {
            FD_SET(sockets->sock[i],&readfds);
            if(sockets->sock[i] > highfd)
            {
                highfd = sockets->sock[i];
            }
        }
    
        /* Select */
        readable = select(highfd + 1,&readfds,NULL,NULL,timeout);
        if(readable > 0)
        {
            /* Read the datagram */
            for (i=0; i<sockets->sock_count; i++)
            {
                if(FD_ISSET(sockets->sock[i],&readfds))
                {
                    /* Peek at the first 16 bytes of the header */
                    bytesread = recvfrom(sockets->sock[i],
                                         peek,
                                         16,
                                         MSG_PEEK,
                                         (struct sockaddr *)peeraddr,
                                         &peeraddrlen);
                    if(bytesread == 16)
                    {
                        if(AsUINT24(peek + 2) <=  SLP_MAX_DATAGRAM_SIZE)
                        {
                            *buf = SLPBufferRealloc(*buf, AsUINT24(peek + 2));
                            bytesread = recv(sockets->sock[i],
                                             (*buf)->curpos, 
                                             (*buf)->end - (*buf)->curpos, 
                                             0);
                            if(bytesread != AsUINT24(peek + 2))
                            {
                                /* This should never happen but we'll be paranoid*/
                                (*buf)->end = (*buf)->curpos + bytesread;
                            }
                            
                            /* Message read. We're done! */
                            result = 0; 
                            recvloop = 0;
                            break;
                        }
                        else
                        {
                            /* we got a bad message, or one that is too big! */
                        }
                    }
                    else
                    {
                        /* Not even 16 bytes available */
                    }
                }
            }   
        }
        else if(readable == 0)
        {
            result = -1;
            errno = ETIMEDOUT;
            recvloop = 0;
        }
        else
        {
            result = -1;
            recvloop = 0;
        }
    }

    return result;
}
예제 #6
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;
    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(*peek == 2)
    {
        /* allocate the recvmsg big enough for the whole message */
        *buf = SLPBufferRealloc(*buf, AsUINT24(peek + 2));
        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;
}
예제 #7
0
/*-------------------------------------------------------------------------*/
void HandleStreamRead(SLPDSocketList* list, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    int     fdflags;
    int     bytesread;
    char    peek[16];
    
    if(sock->state == STREAM_FIRST_READ)
    {
        fdflags = fcntl(sock->fd, F_GETFL, 0);
        fcntl(sock->fd,F_SETFL, fdflags | O_NONBLOCK);
        
        /*---------------------------------------------------------------*/
        /* take a peek at the packet to get version and size information */
        /*---------------------------------------------------------------*/
        bytesread = recvfrom(sock->fd,
                             peek,
                             16,
                             MSG_PEEK,
                             &(sock->peerinfo.peeraddr),
                             &(sock->peerinfo.peeraddrlen));
        if(bytesread > 0)
        {
            /* check the version */
            if(*peek == 2)
            {
                /* allocate the recvbuf big enough for the whole message */
                sock->recvbuf = SLPBufferRealloc(sock->recvbuf,AsUINT24(peek+2));
                if(sock->recvbuf)
                {
                    sock->state = STREAM_READ;
                }
                else
                {
                    SLPLog("Slpd is out of memory!\n");
                    sock->state = SOCKET_CLOSE;
                }
            }
            else
            {
                SLPLog("Unsupported version %i received from %s\n",
                       *peek,
                       inet_ntoa(sock->peerinfo.peeraddr.sin_addr));

                sock->state = SOCKET_CLOSE;
            }
        }
        else
        {
            if(errno != EWOULDBLOCK)
            {
                sock->state = SOCKET_CLOSE;
                return;
            }
        }        

        
        /*------------------------------*/
        /* recv the rest of the message */
        /*------------------------------*/
        bytesread = recv(sock->fd,
                         sock->recvbuf->curpos,
                         sock->recvbuf->end - sock->recvbuf->curpos,
                         0);              

        if(bytesread > 0)
        {
            /*------------------------------*/
            /* Reset the timestamp          */
            /*------------------------------*/
            time(&(sock->timestamp));
            
            sock->recvbuf->curpos += bytesread;
            if(sock->recvbuf->curpos == sock->recvbuf->end)
            {
                if(SLPDProcessMessage(&sock->peerinfo,
                                      sock->recvbuf,
                                      sock->sendbuf) == 0)
                {
                    sock->state = STREAM_FIRST_WRITE;
                }
                else
                {
                    /* An error has occured in SLPDProcessMessage() */
                    SLPLog("An error while processing message from %s\n",
                           inet_ntoa(sock->peerinfo.peeraddr.sin_addr));
                    sock->state = SOCKET_CLOSE;
                }                                                          
            }
        }
        else
        {
            if(errno != EWOULDBLOCK)
            {
                /* error in recv() */
                sock->state = SOCKET_CLOSE;
            }
        }
    }
}
예제 #8
0
/*=========================================================================*/ 
SLPError NetworkRecvMessage(int sockfd,
                           SLPBuffer buf,
                           struct timeval* timeout,
                           struct sockaddr* peeraddr,
                           int* peeraddrlen)
/* Receives a message                                                      */
/*                                                                         */
/* Returns  -    SLP_OK, SLP_NETWORK_TIMEOUT, SLP_NETWORK_ERROR, or        */
/*               SLP_PARSE_ERROR.                                          */
/*=========================================================================*/ 
{
    SLPError    result      = SLP_OK;
    int         xferbytes;
    fd_set      readfds;
    char        peek[16];
    
    /*---------------------------------------------------------------*/
    /* 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)
    {
        xferbytes = recvfrom(sockfd,
                             peek,
                             16,
                             MSG_PEEK,
                             peeraddr,
                             peeraddrlen);
        if(xferbytes <= 0)
        {
            result = SLP_NETWORK_ERROR;
        } 
    }
    else if(xferbytes == 0)
    {
        result = SLP_NETWORK_TIMED_OUT;
    }
    else
    {
        result = SLP_NETWORK_ERROR;
    }

    /*---------------------------------------*/
    /* return now if peek was not successful */
    /*---------------------------------------*/
    if(result) return result;

    
    /*------------------------------*/
    /* Read the rest of the message */
    /*------------------------------*/
    /* check the version */
    if(*peek == 2)
    {
        /* allocate the recvmsg big enough for the whole message */
        if(SLPBufferRealloc(buf, AsUINT24(peek + 2)))
        {
            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
                    {
                        result =  SLP_NETWORK_ERROR;
                        break;
                    }
                }
                else if(xferbytes == 0)
                {
                    result = SLP_NETWORK_TIMED_OUT;
                    break;
                }
                else
                {
                    result =  SLP_NETWORK_ERROR;
                    break;
                }
            } /* end of main read while. */  
        }
        else
        {
            result = SLP_MEMORY_ALLOC_FAILED;
        }
    }
    else
    {
        result = SLP_PARSE_ERROR;
    }

    return result;
}