예제 #1
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;
        }
    }
}
예제 #2
0
/*=========================================================================*/
void SLPDIncomingHandler(int* fdcount,
                         fd_set* readfds,
                         fd_set* writefds)
/* Handles all outgoing requests that are pending on the specified file    */
/* discriptors                                                             */
/*                                                                         */
/* fdcount  (IN/OUT) number of file descriptors marked in fd_sets          */
/*                                                                         */
/* readfds  (IN) file descriptors with pending read IO                     */
/*                                                                         */
/* writefds  (IN) file descriptors with pending read IO                    */
/*=========================================================================*/
{
    SLPDSocket* sock;
    sock = (SLPDSocket*) G_IncomingSocketList.head;
    while (sock && *fdcount)
    {
        if (FD_ISSET(sock->fd,readfds))
        {
            switch (sock->state)
            {
            case SOCKET_LISTEN:
                IncomingSocketListen(&G_IncomingSocketList,sock);
                break;

            case DATAGRAM_UNICAST:
            case DATAGRAM_MULTICAST:
            case DATAGRAM_BROADCAST:
                IncomingDatagramRead(&G_IncomingSocketList,sock);
                break;                      

            case STREAM_READ:
            case STREAM_READ_FIRST:
                IncomingStreamRead(&G_IncomingSocketList,sock);
                break;

            default:
                break;
            }

            *fdcount = *fdcount - 1;
        }
        else if (FD_ISSET(sock->fd,writefds))
        {
            switch (sock->state)
            {
            case STREAM_WRITE:
            case STREAM_WRITE_FIRST:
                IncomingStreamWrite(&G_IncomingSocketList,sock);
                break;

            default:
                break;
            }

            *fdcount = *fdcount - 1;
        }

        sock = (SLPDSocket*)sock->listitem.next; 
    }                               
}
예제 #3
0
/** Read inbound stream data.
 *
 * @param[in] socklist - The list of monitored sockets.
 * @param[in] sock - The socket to be read.
 *
 * @internal
 */
static void IncomingStreamRead(SLPList * socklist, SLPDSocket * sock)
{
   int bytesread;
   size_t recvlen = 0;
   char peek[16];
   socklen_t peeraddrlen = sizeof(struct sockaddr_storage);

   if (sock->state == STREAM_READ_FIRST)
   {
      /*---------------------------------------------------*/
      /* take a peek at the packet to get size information */
      /*---------------------------------------------------*/
      bytesread = recvfrom(sock->fd, (char *)peek, 16, MSG_PEEK,
            (struct sockaddr *)&sock->peeraddr, &peeraddrlen);
      if (bytesread > 0 && bytesread >= (*peek == 2? 5: 4))
      {
         recvlen = PEEK_LENGTH(peek);

         /* 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, (char *)sock->recvbuf->curpos,
            (int)(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) {
            if (!sock->sendbuf)
               /* Some of the error handling code expects a sendbuf to be available
                * to be emptied, so make sure there is at least a minimal buffer
                */
               sock->sendbuf = SLPBufferAlloc(1);
            switch (SLPDProcessMessage(&sock->peeraddr,
                  &sock->localaddr, sock->recvbuf, &sock->sendbuf, 0))
            {
               case SLP_ERROR_PARSE_ERROR:
               case SLP_ERROR_VER_NOT_SUPPORTED:
               case SLP_ERROR_MESSAGE_NOT_SUPPORTED:
                  sock->state = SOCKET_CLOSE;
                  break;

               default:
                  if (!sock->sendbuf || sock->sendbuf->end == sock->sendbuf->start)
                  {
                     /* no answer available, just close socket */
                     sock->state = SOCKET_CLOSE;
                     break;
                  }

                  /* some clients cannot cope with the OVERFLOW
                   * bit set on a TCP stream, so always clear it
                   */
                  if (sock->sendbuf->end - sock->sendbuf->start > 5)
                  {
                     if (sock->sendbuf->start[0] == 1)
                        sock->sendbuf->start[4] &= ~SLPv1_FLAG_OVERFLOW;
                     else
                        sock->sendbuf->start[5] &= ~(SLP_FLAG_OVERFLOW >> 8);
                  }
                  sock->state = STREAM_WRITE_FIRST;
                  IncomingStreamWrite(socklist, sock);
            }
         }
      }