예제 #1
0
/** Read a datagram from an outbound socket.
 *
 * @param[in] socklist - The list of sockets being monitored.
 * @param[in] sock - The socket to be read from.
 */
void OutgoingDatagramRead(SLPList * socklist, SLPDSocket * sock)
{
   int bytesread;
   socklen_t peeraddrlen = sizeof(struct sockaddr_storage);

   (void)socklist;

   bytesread = recvfrom(sock->fd, (char*)sock->recvbuf->start, 
         G_SlpdProperty.MTU, 0, (struct sockaddr *)&sock->peeraddr, 
         &peeraddrlen);
   if (bytesread > 0)
   {
      sock->recvbuf->end = sock->recvbuf->start + bytesread;

      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);
      SLPDProcessMessage(&sock->peeraddr, &sock->localaddr, 
            sock->recvbuf, &sock->sendbuf, &sock->sendlist);

      /* Completely ignore the message */

   }
}
예제 #2
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));
                }
            }
        }
    }
}
예제 #3
0
/*-------------------------------------------------------------------------*/
void HandleDatagramRead(SLPDSocketList* list, SLPDSocket* sock)
/*-------------------------------------------------------------------------*/
{
    int                 bytesread;
    int                 bytestowrite;
    
    bytesread = recvfrom(sock->fd,
                         sock->recvbuf->start,
                         SLP_MAX_DATAGRAM_SIZE,
                         0,
                         &(sock->peerinfo.peeraddr),
                         &(sock->peerinfo.peeraddrlen));
    if(bytesread > 0)
    {
        sock->recvbuf->end = sock->recvbuf->start + bytesread;

        if(SLPDProcessMessage(&(sock->peerinfo),
                              sock->recvbuf,
                              sock->sendbuf) == 0)
        {
            /* check to see if we should send anything */
            bytestowrite = sock->sendbuf->end - sock->sendbuf->start;
            if(bytestowrite > 0)
            {
                sendto(sock->fd,
                       sock->sendbuf->start,
                       sock->sendbuf->end - sock->sendbuf->start,
                       0,
                       &(sock->peerinfo.peeraddr),
                       sock->peerinfo.peeraddrlen);
            }
        }
        else
        {
            SLPLog("An error occured while processing message from %s\n",
                   inet_ntoa(sock->peerinfo.peeraddr.sin_addr));
        } 
    }

}
예제 #4
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 */
    }
}
예제 #5
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);
            }
        }
    }
}
예제 #6
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;
        }
    }
}
예제 #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
/** Read an inbound datagram.
 *
 * @param[in] socklist - The list of monitored sockets.
 * @param[in] sock - The socket to be read.
 *
 * @internal
 */
static void IncomingDatagramRead(SLPList * socklist, SLPDSocket * sock)
{
   int bytesread;
   int byteswritten;
   socklen_t peeraddrlen = sizeof(struct sockaddr_storage);
   char addr_str[INET6_ADDRSTRLEN];
   sockfd_t sendsock = SLP_INVALID_SOCKET;

   (void)socklist;

   bytesread = recvfrom(sock->fd, (char*)sock->recvbuf->start,
         G_SlpdProperty.MTU, 0, (struct sockaddr *)&sock->peeraddr,
         &peeraddrlen);
   if (bytesread > 0)
   {
      sock->recvbuf->end = sock->recvbuf->start + bytesread;

      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:
            break;

         default:
#ifdef DARWIN
            /* If the socket is a multicast socket, find the designated UDP output socket for sending */
            if (sock->state == DATAGRAM_MULTICAST)
               if ((sendsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != SLP_INVALID_SOCKET)
                  SLPNetworkSetSndRcvBuf(sendsock);
#endif
            if (sendsock == SLP_INVALID_SOCKET)
               sendsock = sock->fd;

            /* check to see if we should send anything, breaking up individual packets in the buffer
               into different sendto calls (should only be an issue with the loopback DA response)*/
            if (sock->sendbuf)
            {
               sock->sendbuf->curpos = sock->sendbuf->start;
               while (sock->sendbuf->curpos < sock->sendbuf->end)
               {
                  int packetbytes = AS_UINT24(sock->sendbuf->curpos + 2);
                  byteswritten = sendto(sendsock, (char*)sock->sendbuf->curpos,
                        packetbytes, 0, (struct sockaddr *)&sock->peeraddr,
                        SLPNetAddrLen(&sock->peeraddr));

                  if (byteswritten != packetbytes)
                  {
                     /* May be an overflow reply */
                     int flags = AS_UINT16(sock->sendbuf->curpos + 5);
                     if ((byteswritten == -1) &&
#ifdef _WIN32
                           (WSAGetLastError() == WSAEMSGSIZE) &&
#else
                           (errno == EMSGSIZE) &&
#endif
                           (flags & SLP_FLAG_OVERFLOW))
                     {
                        int byteswrittenmax = sendto(sendsock, (char*)sock->sendbuf->curpos,
                                G_SlpdProperty.MTU, 0, (struct sockaddr *)&sock->peeraddr,
                                SLPNetAddrLen(&sock->peeraddr));
                        if (byteswrittenmax == G_SlpdProperty.MTU)
                           byteswritten = packetbytes;
                     }
                  }

                  if (byteswritten != packetbytes)
                     SLPDLog("NETWORK_ERROR - %d replying %s\n", errno,
                           SLPNetSockAddrStorageToString(&(sock->peeraddr),
                                 addr_str, sizeof(addr_str)));

                  sock->sendbuf->curpos += packetbytes;
               }

               /* Only close if we allocated a new socket */
               if (sendsock != sock->fd)
                  closesocket(sendsock);
            }
            break;
      }
   }
}
예제 #9
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);
            }
         }
      }