My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
OpenPgm5CReferencePgmRecv  
OpenPGM 5 : C Reference : Socket : pgm_recv()
Phase-Implementation
Updated Oct 7, 2011 by fnjo...@gmail.com

Function

Declaration

 #include <pgm/pgm.h>
 

int *pgm_recv* ( [OpenPgm5CReferencePgmSockT pgm_sock_t]* sock, void* buf, size_t len, int flags, size_t* bytes_read, [OpenPgm5CReferencePgmErrorT pgm_error_t]** error );

int *pgm_recvfrom* ( [OpenPgm5CReferencePgmSockT pgm_sock_t]* sock, void** buf, size_t len, int flags, size_t* bytes_read, struct [OpenPgm5CReferencePgmSockAddrT pgm_sockaddr_t]* from, [OpenPgm5CReferencePgmErrorT pgm_error_t]** error );

int *pgm_recvmsg* ( [OpenPgm5CReferencePgmSockT pgm_sock_t]* sock, [OpenPgm5CReferencePgmMsgvT pgm_msgv_t]* msgv, int flags, size_t* bytes_read, [OpenPgm5CReferencePgmErrorT pgm_error_t]** error );

Purpose

Receive an Application Protocol Domain Unit (APDU) from the transport and drive the PGM receive and send state machines.

Remarks

The PGM protocol is bi-directional, even send-only applications need to process incoming requests for retransmission (NAKs) and other packet types. The synchronous API suite provides low level access to the raw events driving the protocol in order to accelerate performance in high message rate environments.

pgm_recv() and pgm_recvfrom() fill the provided buffer location with up to len contiguous APDU bytes therefore the buffer should be large enough to store the largest APDU expected.

If from is not NULL, the source TSI is filled in.

The pgm_recv() is identical to pgm_recvfrom() with a NULL from parameter.

pgm_recvmsg() fills a pgm_msgv_t structure with a scatter/gather vector of buffers directly from the receive window. The vector size is governed by IOV_MAX, on Linux is 1024. Using the maximum size is not always recommended as time processing the received messages might cause an incoming buffer overrun.

Memory is returned to the receive window on the next call or transport destruction. If you want buffers that remain the property of the application consider the zero-copy API pgm_recvmsgv() instead.

Unrecoverable data loss will cause the function to immediately return with PGM_IO_STATUS_RESET, setting flags to MSG_ERR_QUEUE will return a populated msgv with an error skbuff detailing the error. If PGM_ABORT_ON_RESET is set with false (the default mode) processing can continue with subsequent calls to pgm_recv(), if true then the transport will continue to return PGM_IO_STATUS_RESET until destroyed.

It is valid to send and receive zero length PGM packets.

The pgm_recv() API and other versions are the entry into the core PGM state machine. Frequent calls must be made for send-only sockets in order to process incoming NAKs, send NCFs, send repair data (RDATA), in addition to sending broadcast SPMs to define the PGM tree.

Frequent calls must be made to pgm_recv() for receive-only sockets to generate and re-generate NAKs for missing data, and to send SPM-Request messages to new senders to expedite learning of their NLAs.

Parameters

Parameter Description
sock The PGM socket object.
buf Data buffer to fill.
len Length of buf in bytes.
msgv Message vector of TPDUs.
flags
MSG_DONTWAIT
Enables non-blocking operation on Unix, no action on Windows.
MSG_ERR_QUEUE
Returns an error SKB on session reset.
bytes_read Pointer to store count of bytes read into buf.
error a return location for a pgm_error_t, or NULL.

Return Value

On success, returns PGM_IO_STATUS_NORMAL, on error returns PGM_IO_STATUS_ERROR, on reset due to unrecoverable data loss, returns PGM_IO_STATUS_RESET. If the transport is marked non-blocking and no senders have been discovered then PGM_IO_STATUS_WOULD_BLOCK is returned if the operation would block. If no data is available but a pending state timer is running PGM_IO_STATUS_TIMER_PENDING is returned. If the state engine is trying to transmit repair data but is subject to the rate limiting engine then PGM_IO_STATUS_RATE_LIMITED is returned instead.

Example

Receive an APDU up to 4096 bytes in length.

 char buf[4096];
 size_t bytes_read;
 pgm_recv (transport, buf, sizeof(buf), 0, &bytes_read, NULL);

Receive an APDU with source TSI.

 char buf[4096];
 struct pgm_sockaddr_t from;
 size_t bytes_read;
 pgm_recvfrom (transport, buf, sizeof(buf), 0, &from, &bytes_read, NULL);
 printf ("%zu bytes received from %s\n", pgm_tsi_print (&from.sa_addr));

Receive a scatter/gather vector APDU message.

 pgm_msgv_t msgv;
 size_t bytes_read;
 pgm_recvmsg (transport, &msgv, 0, &bytes_read, NULL);
 printf ("received %zu bytes: ", bytes_read);
 struct iovec* msgv_iov = msgv.msgv_iov;
 while (bytes_read > 0) {
   printf ((char*)msgv_iov->iov_base);
   bytes_read -= msgv_iov->iov_len;
   msgv_iov++;
 }
 putchar('\n');

Display error details on unrecoverable error.

 char buf[4096];
 size_t bytes_read;
 pgm_error_t *err = NULL;
 if (PGM_IO_STATUS_RESET == pgm_recv (transport, buf, sizeof(buf), &bytes_read, &err)) {
   fprintf (stderr, "pgm_recv() error %s\n", (err && err->message) ? err->message : "(null)");
   pgm_error_free (err);
   return EXIT_FAILURE;
 }

Display details from error skbuff.

 pgm_msgv_t msgv;
 size_t bytes_read;
 if (PGM_IO_STATUS_RESET == pgm_recvmsg (transport, &msgv, MSG_ERR_QUEUE, &bytes_read, NULL)) {
   fprintf (stderr, "pgm socket lost %" PRIu32 " packets detected from %s\n",
              msgv.msgv_skb[0]->seq,
              pgm_print_tsi(&msgv.msgv_skb[0]->tsi));
   return EXIT_FAILURE;
 }

See Also


Sign in to add a comment
Powered by Google Project Hosting