Example #1
0
void zmq::pgm_socket_t::process_upstream (void)
{
    zmq_log (1, "On upstream packet, %s(%i)\n", __FILE__, __LINE__);
    //  We acctually do not want to read any data here we are going to 
    //  process NAK.
    pgm_msgv_t dummy_msg;

    ssize_t dummy_bytes = pgm_transport_recvmsgv (g_transport, &dummy_msg,
        1, MSG_DONTWAIT);
    
    //  No data should be returned.
    assert (dummy_bytes == -1 && errno == EAGAIN);
}
Example #2
0
//  pgm_transport_recvmsgv is called to fill the pgm_msgv array up to 
//  pgm_msgv_len. In subsequent calls data from pgm_msgv structure are 
//  returned.
ssize_t zmq::pgm_socket_t::receive (void **raw_data_)
{
 
    //  We just sent all data from pgm_transport_recvmsgv up 
    //  and have to return 0 that another engine in this thread is scheduled.
    if (nbytes_rec == nbytes_processed && nbytes_rec > 0) {

        //  Reset all the counters.
        nbytes_rec = 0;
        nbytes_processed = 0;
        pgm_msgv_processed = 0;

        return 0;
    }

    //  If we have are going first time or if we have processed all pgm_msgv_t
    //  structure previaously read from the pgm socket.
    if (nbytes_rec == nbytes_processed) {

        //  Check program flow.
        assert (pgm_msgv_processed == 0);
        assert (nbytes_processed == 0);
        assert (nbytes_rec == 0);

        //  Receive a vector of Application Protocol Domain Unit's (APDUs) 
        //  from the transport.
        nbytes_rec = pgm_transport_recvmsgv (g_transport, pgm_msgv, 
            pgm_msgv_len, MSG_DONTWAIT);
  
        //  In a case when no ODATA/RDATA fired POLLIN event (SPM...)
        //  pgm_transport_recvmsg returns -1 with errno == EAGAIN.
        if (nbytes_rec == -1 && errno == EAGAIN) {
        
            //  In case if no RDATA/ODATA caused POLLIN 0 is 
            //  returned.
            nbytes_rec = 0;
            return 0;
        }

        //  For data loss nbytes_rec == -1 errno == ECONNRESET.
        if (nbytes_rec == -1 && errno == ECONNRESET) {
            
            //  In case of dala loss -1 is returned.
            zmq_log (1, "Data loss detected, %s(%i)\n", __FILE__, __LINE__);
            nbytes_rec = 0;
            return -1;
        }

        //  Catch the rest of the errors.
        if (nbytes_rec <= 0) {
            zmq_log (1, "received %i B, errno %i, %s(%i)", (int)nbytes_rec, 
                errno, __FILE__, __LINE__);
            errno_assert (nbytes_rec > 0);
        }
   
        zmq_log (4, "received %i bytes\n", (int)nbytes_rec);
    }

    assert (nbytes_rec > 0);

    // Only one APDU per pgm_msgv_t structure is allowed. 
    assert (pgm_msgv [pgm_msgv_processed].msgv_iovlen == 1);

    //  Take pointers from pgm_msgv_t structure.
    *raw_data_ = pgm_msgv[pgm_msgv_processed].msgv_iov->iov_base;
    size_t raw_data_len = pgm_msgv[pgm_msgv_processed].msgv_iov->iov_len;

    //  Check if peer TSI did not change, this is detection of peer restart.
    const pgm_tsi_t *current_tsi = pgm_msgv [pgm_msgv_processed].msgv_tsi;

    //  If empty store new TSI.
    if (tsi_empty (&tsi)) {
        //  Store current peer TSI.
        memcpy (&tsi, current_tsi, sizeof (pgm_tsi_t));
#ifdef PGM_SOCKET_DEBUG
        uint8_t *gsi = (uint8_t*)(&tsi)->gsi.identifier;
#endif

        zmq_log (1, "First peer TSI: %i.%i.%i.%i.%i.%i.%i, %s(%i)\n",
            gsi [0], gsi [1], gsi [2], gsi [3], gsi [4], gsi [5], 
            ntohs (tsi.sport), __FILE__, __LINE__);
    }

    //  Compare stored TSI with actual.
    if (!tsi_equal (&tsi, current_tsi)) {
        //  Peer change detected.
        zmq_log (1, "Peer change detected, %s(%i)\n", __FILE__, __LINE__);
        
        //  Compare with retired TSI, in case of match ignore APDU.
        if (tsi_equal (&retired_tsi, current_tsi)) {
            zmq_log (1, "Retired TSI - ignoring APDU, %s(%i)\n", 
                __FILE__, __LINE__); 
            
            //  Move the the next pgm_msgv_t structure.
            pgm_msgv_processed++;
            nbytes_processed +=raw_data_len;
            
            return 0;

        } else {
            zmq_log (1, "New TSI, %s(%i)\n", __FILE__, __LINE__); 

            //  Store new TSI and move last valid to retired_tsi
            memcpy (&retired_tsi, &tsi, sizeof (pgm_tsi_t));
            memcpy (&tsi, current_tsi, sizeof (pgm_tsi_t));

#ifdef PGM_SOCKET_DEBUG
            uint8_t *gsi = (uint8_t*)(&retired_tsi)->gsi.identifier;
#endif
            zmq_log (1, "retired TSI: %i.%i.%i.%i.%i.%i.%i, %s(%i)\n",
                gsi [0], gsi [1], gsi [2], gsi [3], gsi [4], gsi [5], 
                ntohs (retired_tsi.sport), __FILE__, __LINE__);

#ifdef PGM_SOCKET_DEBUG
            gsi = (uint8_t*)(&tsi)->gsi.identifier;
#endif
            zmq_log (1, "        TSI: %i.%i.%i.%i.%i.%i.%i, %s(%i)\n",
                gsi [0], gsi [1], gsi [2], gsi [3], gsi [4], gsi [5], 
                ntohs (tsi.sport), __FILE__, __LINE__);

            //  Peers change is recognized as a GAP.
            return -1;
        }

    }
        
    //  Move the the next pgm_msgv_t structure.
    pgm_msgv_processed++;
    nbytes_processed +=raw_data_len;

    zmq_log (4, "sendig up %i bytes\n", (int)raw_data_len);

    return raw_data_len;
}
Example #3
0
static gpointer
receiver_thread (
	gpointer	data
	)
{
	pgm_transport_t* transport = (pgm_transport_t*)data;
	long iov_max = sysconf( SC_IOV_MAX );
	pgm_msgv_t msgv[iov_max];

#ifdef CONFIG_HAVE_EPOLL
	int efd = epoll_create (IP_MAX_MEMBERSHIPS);
	if (efd < 0) {
		g_error ("epoll_create failed errno %i: \"%s\"", errno, strerror(errno));
		g_main_loop_quit(g_loop);
		return NULL;
	}

	int retval = pgm_transport_epoll_ctl (g_transport, efd, EPOLL_CTL_ADD, EPOLLIN);
	if (retval < 0) {
		g_error ("pgm_epoll_ctl failed errno %i: \"%s\"", errno, strerror(errno));
		g_main_loop_quit(g_loop);
		return NULL;
	}
#else
	int n_fds = 2;
	struct pollfd fds[ n_fds ];
	
#endif /* !CONFIG_HAVE_EPOLL */

	do {
		gssize len = pgm_transport_recvmsgv (transport, msgv, iov_max, MSG_DONTWAIT /* non-blocking */);
		if (len >= 0)
		{
			on_msgv (msgv, len, NULL);
		}
		else if (errno == EAGAIN)	/* len == -1, an error occured */
		{
#ifdef CONFIG_HAVE_EPOLL
			struct epoll_event events[1];	/* wait for maximum 1 event */
			epoll_wait (efd, events, G_N_ELEMENTS(events), 1000 /* ms */);
#else
			memset (fds, 0, sizeof(fds));
			pgm_transport_poll_info (g_transport, fds, &n_fds, POLLIN);
			poll (fds, n_fds, 1000 /* ms */);
#endif /* !CONFIG_HAVE_EPOLL */
		}
		else if (errno == ECONNRESET)
		{
			pgm_sock_err_t* pgm_sock_err = (pgm_sock_err_t*)msgv[0].msgv_iov->iov_base;
			g_warning ("pgm socket lost %" G_GUINT32_FORMAT " packets detected from %s",
					pgm_sock_err->lost_count,
					pgm_print_tsi(&pgm_sock_err->tsi));
			continue;
		} 
		else if (errno == ENOTCONN)		/* socket(s) closed */
		{
			g_error ("pgm socket closed.");
			g_main_loop_quit(g_loop);
			break;
		}
		else
		{
			g_error ("pgm socket failed errno %i: \"%s\"", errno, strerror(errno));
			g_main_loop_quit(g_loop);
			break;
		}
	} while (!g_quit);

#ifdef CONFIG_HAVE_EPOLL
	close (efd);
#endif
	return NULL;
}