Added support for processEvents to Transport and Face.  Removed tempReceive.
diff --git a/ndn-cpp/c/errors.c b/ndn-cpp/c/errors.c
index a5b0510..8c87d77 100644
--- a/ndn-cpp/c/errors.c
+++ b/ndn-cpp/c/errors.c
@@ -62,6 +62,8 @@
     return      "SocketTransport socket is not open";
   case NDN_ERROR_SocketTransport_error_in_send:
     return      "SocketTransport error in send";
+  case NDN_ERROR_SocketTransport_error_in_poll:
+    return      "SocketTransport error in poll";
   case NDN_ERROR_SocketTransport_error_in_recv:
     return      "SocketTransport error in recv";
   case NDN_ERROR_SocketTransport_error_in_close:
diff --git a/ndn-cpp/c/errors.h b/ndn-cpp/c/errors.h
index 1f9de76..f6adb08 100644
--- a/ndn-cpp/c/errors.h
+++ b/ndn-cpp/c/errors.h
@@ -39,6 +39,7 @@
   NDN_ERROR_SocketTransport_cannot_connect_to_socket,
   NDN_ERROR_SocketTransport_socket_is_not_open,
   NDN_ERROR_SocketTransport_error_in_send,
+  NDN_ERROR_SocketTransport_error_in_poll,
   NDN_ERROR_SocketTransport_error_in_recv,
   NDN_ERROR_SocketTransport_error_in_close
 } ndn_Error;
diff --git a/ndn-cpp/c/transport/socket-transport.c b/ndn-cpp/c/transport/socket-transport.c
index a6fcbac..2a537db 100644
--- a/ndn-cpp/c/transport/socket-transport.c
+++ b/ndn-cpp/c/transport/socket-transport.c
@@ -13,6 +13,7 @@
 #include <netinet/in.h>
 #include <sys/socket.h>
 #include <arpa/inet.h>
+#include <poll.h>
 #include "../util/ndn_memory.h"
 
 ndn_Error ndn_SocketTransport_connect(struct ndn_SocketTransport *self, ndn_SocketType socketType, char *host, unsigned short port)
@@ -84,8 +85,36 @@
   return NDN_ERROR_success;  
 }
 
+ndn_Error ndn_SocketTransport_receiveIsReady(struct ndn_SocketTransport *self, int *receiveIsReady)
+{
+  // Default to not ready.
+  *receiveIsReady = 0;
+
+  if (self->socketDescriptor < 0)
+    // The socket is not open.  Just silently return.
+    return NDN_ERROR_success;
+  
+  struct pollfd pollInfo[1];
+  pollInfo[0].fd = self->socketDescriptor;
+  pollInfo[0].events = POLLIN;
+  
+  int pollResult = poll(pollInfo, 1, 200);
+
+  if (pollResult < 0)
+    return NDN_ERROR_SocketTransport_error_in_poll;
+  else if (pollResult == 0)
+    // Timeout, so no data ready.
+    return NDN_ERROR_success;
+  else {
+   if (pollInfo[0].revents & POLLIN)
+     *receiveIsReady = 1;
+  }
+
+  return NDN_ERROR_success;
+}
+
 ndn_Error ndn_SocketTransport_receive
-(struct ndn_SocketTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytesOut)
+  (struct ndn_SocketTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytesOut)
 {
   if (self->socketDescriptor < 0)
     return NDN_ERROR_SocketTransport_socket_is_not_open;
diff --git a/ndn-cpp/c/transport/socket-transport.h b/ndn-cpp/c/transport/socket-transport.h
index 0011e26..6c2da6e 100644
--- a/ndn-cpp/c/transport/socket-transport.h
+++ b/ndn-cpp/c/transport/socket-transport.h
@@ -22,18 +22,59 @@
   int socketDescriptor; /**< -1 if not connected */
 };
   
+/**
+ * Initialize the ndn_SocketTransport struct with default values for no connection yet.
+ * @param self A pointer to the ndn_SocketTransport struct.
+ */
 static inline void ndn_SocketTransport_init(struct ndn_SocketTransport *self)
 {
   self->socketDescriptor = -1;
 }
 
+/**
+ * Connect with TCP or UDP to the host:port.
+ * @param self A pointer to the ndn_SocketTransport struct.
+ * @param socketType SOCKET_TCP or SOCKET_UDP.
+ * @param host The host to connect to.
+ * @param port The port to connect to.
+ * @return 0 for success, else an error code.
+ */
 ndn_Error ndn_SocketTransport_connect(struct ndn_SocketTransport *self, ndn_SocketType socketType, char *host, unsigned short port);
 
+/**
+ * Send data to the socket.
+ * @param self A pointer to the ndn_SocketTransport struct.
+ * @param data A pointer to the buffer of data to send.
+ * @param dataLength The number of bytes in data.
+ * @return 0 for success, else an error code.
+ */
 ndn_Error ndn_SocketTransport_send(struct ndn_SocketTransport *self, unsigned char *data, unsigned int dataLength);
 
+/**
+ * Check if there is data ready on the socket to be received with ndn_SocketTransport_receive.
+ * @param self A pointer to the ndn_SocketTransport struct.
+ * @param receiveIsReady This will be set to 1 if data is ready, 0 if not.
+ * @return 0 for success, else an error code.
+ */
+ndn_Error ndn_SocketTransport_receiveIsReady(struct ndn_SocketTransport *self, int *receiveIsReady);
+
+/**
+ * Receive data from the socket.  NOTE: This is a blocking call.  You should first call ndn_SocketTransport_receiveIsReady
+ * to make sure there is data ready to receive.
+ * @param self A pointer to the ndn_SocketTransport struct.
+ * @param buffer A pointer to the buffer to receive the data.
+ * @param bufferLength The maximum length of buffer.
+ * @param nBytes Return the number of bytes received into buffer.
+ * @return 0 for success, else an error code.
+ */
 ndn_Error ndn_SocketTransport_receive
   (struct ndn_SocketTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytes);
 
+/**
+ * Close the socket.
+ * @param self A pointer to the ndn_SocketTransport struct.
+ * @return 0 for success, else an error code.
+ */
 ndn_Error ndn_SocketTransport_close(struct ndn_SocketTransport *self);
 
 #ifdef __cplusplus
diff --git a/ndn-cpp/c/transport/tcp-transport.h b/ndn-cpp/c/transport/tcp-transport.h
index f0b5d0c..1860002 100644
--- a/ndn-cpp/c/transport/tcp-transport.h
+++ b/ndn-cpp/c/transport/tcp-transport.h
@@ -18,27 +18,70 @@
   struct ndn_SocketTransport base;
 };
   
+/**
+ * Initialize the ndn_TcpTransport struct with default values for no connection yet.
+ * @param self A pointer to the ndn_TcpTransport struct.
+ */
 static inline void ndn_TcpTransport_init(struct ndn_TcpTransport *self)
 {
   ndn_SocketTransport_init(&self->base);
 }
 
+/**
+ * Connect with TCP to the host:port.
+ * @param self A pointer to the ndn_TcpTransport struct.
+ * @param host The host to connect to.
+ * @param port The port to connect to.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_TcpTransport_connect(struct ndn_TcpTransport *self, char *host, unsigned short port)
 {
   return ndn_SocketTransport_connect(&self->base, SOCKET_TCP, host, port);
 }
 
+/**
+ * Send data to the socket.
+ * @param self A pointer to the ndn_TcpTransport struct.
+ * @param data A pointer to the buffer of data to send.
+ * @param dataLength The number of bytes in data.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_TcpTransport_send(struct ndn_TcpTransport *self, unsigned char *data, unsigned int dataLength)
 {
   return ndn_SocketTransport_send(&self->base, data, dataLength);
 }
 
+/**
+ * Check if there is data ready on the socket to be received with ndn_TcpTransport_receive.
+ * @param self A pointer to the ndn_TcpTransport struct.
+ * @param receiveIsReady This will be set to 1 if data is ready, 0 if not.
+ * @return 0 for success, else an error code.
+ */
+static inline ndn_Error ndn_TcpTransport_receiveIsReady(struct ndn_TcpTransport *self, int *receiveIsReady)
+{
+  return ndn_SocketTransport_receiveIsReady(&self->base, receiveIsReady);
+}
+
+/**
+ * Receive data from the socket.  NOTE: This is a blocking call.  You should first call ndn_SocketTransport_receiveIsReady
+ * to make sure there is data ready to receive.
+ * @param self A pointer to the ndn_TcpTransport struct.
+ * @param buffer A pointer to the buffer to receive the data.
+ * @param bufferLength The maximum length of buffer.
+ * @param nBytes Return the number of bytes received into buffer.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_TcpTransport_receive
   (struct ndn_TcpTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytes)
 {
   return ndn_SocketTransport_receive(&self->base, buffer, bufferLength, nBytes);
 }
 
+/**
+ * Close the socket.
+ * @param self A pointer to the ndn_TcpTransport struct.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_TcpTransport_close(struct ndn_TcpTransport *self)
 {
   return ndn_SocketTransport_close(&self->base);
diff --git a/ndn-cpp/c/transport/udp-transport.h b/ndn-cpp/c/transport/udp-transport.h
index 82aee19..c9f0d55 100644
--- a/ndn-cpp/c/transport/udp-transport.h
+++ b/ndn-cpp/c/transport/udp-transport.h
@@ -18,27 +18,70 @@
   struct ndn_SocketTransport base;
 };
   
+/**
+ * Initialize the ndn_UdpTransport struct with default values for no connection yet.
+ * @param self A pointer to the ndn_UdpTransport struct.
+ */
 static inline void ndn_UdpTransport_init(struct ndn_UdpTransport *self)
 {
   ndn_SocketTransport_init(&self->base);
 }
 
+/**
+ * Connect with UDP to the host:port.
+ * @param self A pointer to the ndn_UdpTransport struct.
+ * @param host The host to connect to.
+ * @param port The port to connect to.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_UdpTransport_connect(struct ndn_UdpTransport *self, char *host, unsigned short port)
 {
   return ndn_SocketTransport_connect(&self->base, SOCKET_UDP, host, port);
 }
 
+/**
+ * Send data to the socket.
+ * @param self A pointer to the ndn_UdpTransport struct.
+ * @param data A pointer to the buffer of data to send.
+ * @param dataLength The number of bytes in data.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_UdpTransport_send(struct ndn_UdpTransport *self, unsigned char *data, unsigned int dataLength)
 {
   return ndn_SocketTransport_send(&self->base, data, dataLength);
 }
 
+/**
+ * Check if there is data ready on the socket to be received with ndn_UdpTransport_receive.
+ * @param self A pointer to the ndn_UdpTransport struct.
+ * @param receiveIsReady This will be set to 1 if data is ready, 0 if not.
+ * @return 0 for success, else an error code.
+ */
+static inline ndn_Error ndn_UdpTransport_receiveIsReady(struct ndn_UdpTransport *self, int *receiveIsReady)
+{
+  return ndn_SocketTransport_receiveIsReady(&self->base, receiveIsReady);
+}
+
+/**
+ * Receive data from the socket.  NOTE: This is a blocking call.  You should first call ndn_SocketTransport_receiveIsReady
+ * to make sure there is data ready to receive.
+ * @param self A pointer to the ndn_UdpTransport struct.
+ * @param buffer A pointer to the buffer to receive the data.
+ * @param bufferLength The maximum length of buffer.
+ * @param nBytes Return the number of bytes received into buffer.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_UdpTransport_receive
   (struct ndn_UdpTransport *self, unsigned char *buffer, unsigned int bufferLength, unsigned int *nBytes)
 {
   return ndn_SocketTransport_receive(&self->base, buffer, bufferLength, nBytes);
 }
 
+/**
+ * Close the socket.
+ * @param self A pointer to the ndn_UdpTransport struct.
+ * @return 0 for success, else an error code.
+ */
 static inline ndn_Error ndn_UdpTransport_close(struct ndn_UdpTransport *self)
 {
   return ndn_SocketTransport_close(&self->base);
diff --git a/ndn-cpp/face.cpp b/ndn-cpp/face.cpp
index c5be3d2..89462d6 100644
--- a/ndn-cpp/face.cpp
+++ b/ndn-cpp/face.cpp
@@ -24,7 +24,12 @@
   transport_->connect(*this);
   transport_->send(*encoding);
 }
-    
+
+void Face::processEvents()
+{
+  transport_->processEvents();
+}
+
 void Face::shutdown()
 {
   transport_->close();
diff --git a/ndn-cpp/face.hpp b/ndn-cpp/face.hpp
index 372c908..e377577 100644
--- a/ndn-cpp/face.hpp
+++ b/ndn-cpp/face.hpp
@@ -48,6 +48,15 @@
     expressInterest(name, closure, 0);
   }
   
+  /**
+   * Process any data to receive.  For each element received, call face.onReceivedElement.
+   * This is non-blocking and will silently time out after a brief period if there is no data to receive.
+   * You should repeatedly call this from an event loop.
+   * @throw This may throw an exception for reading data or in the callback for processing the data.  If you
+   * call this from an main event loop, you may want to catch and log/disregard all exceptions.
+   */
+  void processEvents();
+
   void shutdown();
   
   const char *getHost() const { return host_.c_str(); }
diff --git a/ndn-cpp/transport/tcp-transport.cpp b/ndn-cpp/transport/tcp-transport.cpp
index 3742c97..4552cfe 100644
--- a/ndn-cpp/transport/tcp-transport.cpp
+++ b/ndn-cpp/transport/tcp-transport.cpp
@@ -35,20 +35,21 @@
     throw std::runtime_error(ndn_getErrorString(error));  
 }
 
-void TcpTransport::tempReceive()
+void TcpTransport::processEvents()
 {
-  try {   
-    ndn_Error error;
-    unsigned char buffer[8000];
-    unsigned int nBytes;
-    if ((error = ndn_TcpTransport_receive(&transport_, buffer, sizeof(buffer), &nBytes)))
-      throw std::runtime_error(ndn_getErrorString(error));  
+  int receiveIsReady;
+  ndn_Error error;
+  if ((error = ndn_TcpTransport_receiveIsReady(&transport_, &receiveIsReady)))
+    throw std::runtime_error(ndn_getErrorString(error));  
+  if (!receiveIsReady)
+    return;
 
-    ndn_BinaryXmlElementReader_onReceivedData(&elementReader_, buffer, nBytes);
-  } catch (...) {
-    // This function is called by the socket callback, so don't send an exception back to it.
-    // TODO: Log the exception?
-  }
+  unsigned char buffer[8000];
+  unsigned int nBytes;
+  if ((error = ndn_TcpTransport_receive(&transport_, buffer, sizeof(buffer), &nBytes)))
+    throw std::runtime_error(ndn_getErrorString(error));  
+
+  ndn_BinaryXmlElementReader_onReceivedData(&elementReader_, buffer, nBytes);
 }
 
 void TcpTransport::close()
diff --git a/ndn-cpp/transport/tcp-transport.hpp b/ndn-cpp/transport/tcp-transport.hpp
index 6cc5fc9..9167beb 100644
--- a/ndn-cpp/transport/tcp-transport.hpp
+++ b/ndn-cpp/transport/tcp-transport.hpp
@@ -21,15 +21,30 @@
   }
   
   /**
-   * 
+   * Connect to the host specified in face.
    * @param face Not a shared_ptr because we assume that it will remain valid during the life of this Transport object.
    */
   virtual void connect(Face &face);
   
+  /**
+   * Set data to the host
+   * @param data A pointer to the buffer of data to send.
+   * @param dataLength The number of bytes in data.
+   */
   virtual void send(const unsigned char *data, unsigned int dataLength);
 
-  virtual void tempReceive();
+  /**
+   * Process any data to receive.  For each element received, call face.onReceivedElement.
+   * This is non-blocking and will silently time out after a brief period if there is no data to receive.
+   * You should repeatedly call this from an event loop.
+   * @throw This may throw an exception for reading data or in the callback for processing the data.  If you
+   * call this from an main event loop, you may want to catch and log/disregard all exceptions.
+   */
+  virtual void processEvents();
 
+  /**
+   * Close the connection to the host.
+   */
   virtual void close();
   
 private:
diff --git a/ndn-cpp/transport/transport.cpp b/ndn-cpp/transport/transport.cpp
index 0b3c7f3..f15e2ea 100644
--- a/ndn-cpp/transport/transport.cpp
+++ b/ndn-cpp/transport/transport.cpp
@@ -19,7 +19,12 @@
 {
   throw logic_error("unimplemented");
 }
- 
+
+void Transport::processEvents()
+{
+  throw logic_error("unimplemented");
+}
+
 void Transport::close()
 {
 }
diff --git a/ndn-cpp/transport/transport.hpp b/ndn-cpp/transport/transport.hpp
index c465aa4..4be901f 100644
--- a/ndn-cpp/transport/transport.hpp
+++ b/ndn-cpp/transport/transport.hpp
@@ -14,11 +14,16 @@
 class Transport {
 public:
   /**
-   * 
+   * Connect to the host specified in face.
    * @param face Not a shared_ptr because we assume that it will remain valid during the life of this Transport object.
    */
   virtual void connect(Face &face);
   
+  /**
+   * Set data to the host
+   * @param data A pointer to the buffer of data to send.
+   * @param dataLength The number of bytes in data.
+   */
   virtual void send(const unsigned char *data, unsigned int dataLength);
   
   void send(const std::vector<unsigned char> &data)
@@ -27,10 +32,13 @@
   }
   
   /**
-   * Make one pass to receive any data waiting on the connection.
-   * @deprecated
+   * Process any data to receive.  For each element received, call face.onReceivedElement.
+   * This is non-blocking and will silently time out after a brief period if there is no data to receive.
+   * You should repeatedly call this from an event loop.
+   * @throw This may throw an exception for reading data or in the callback for processing the data.  If you
+   * call this from an main event loop, you may want to catch and log/disregard all exceptions.
    */
-  virtual void tempReceive() = 0;
+  virtual void processEvents() = 0;
 
   /**
    * Close the connection.  This base class implementation does nothing, but your derived class can override.
diff --git a/ndn-cpp/transport/udp-transport.cpp b/ndn-cpp/transport/udp-transport.cpp
index fcef683..6d6f304 100644
--- a/ndn-cpp/transport/udp-transport.cpp
+++ b/ndn-cpp/transport/udp-transport.cpp
@@ -35,20 +35,21 @@
     throw std::runtime_error(ndn_getErrorString(error));  
 }
 
-void UdpTransport::tempReceive()
+void UdpTransport::processEvents()
 {
-  try {   
-    ndn_Error error;
-    unsigned char buffer[8000];
-    unsigned int nBytes;
-    if ((error = ndn_UdpTransport_receive(&transport_, buffer, sizeof(buffer), &nBytes)))
-      throw std::runtime_error(ndn_getErrorString(error));  
+  int receiveIsReady;
+  ndn_Error error;
+  if ((error = ndn_UdpTransport_receiveIsReady(&transport_, &receiveIsReady)))
+    throw std::runtime_error(ndn_getErrorString(error));  
+  if (!receiveIsReady)
+    return;
 
-    ndn_BinaryXmlElementReader_onReceivedData(&elementReader_, buffer, nBytes);
-  } catch (...) {
-    // This function is called by the socket callback, so don't send an exception back to it.
-    // TODO: Log the exception?
-  }
+  unsigned char buffer[8000];
+  unsigned int nBytes;
+  if ((error = ndn_UdpTransport_receive(&transport_, buffer, sizeof(buffer), &nBytes)))
+    throw std::runtime_error(ndn_getErrorString(error));  
+
+  ndn_BinaryXmlElementReader_onReceivedData(&elementReader_, buffer, nBytes);
 }
 
 void UdpTransport::close()
diff --git a/ndn-cpp/transport/udp-transport.hpp b/ndn-cpp/transport/udp-transport.hpp
index 0aaa2f4..a54839f 100644
--- a/ndn-cpp/transport/udp-transport.hpp
+++ b/ndn-cpp/transport/udp-transport.hpp
@@ -21,15 +21,30 @@
   }
   
   /**
-   * 
+   * Connect to the host specified in face.
    * @param face Not a shared_ptr because we assume that it will remain valid during the life of this Transport object.
    */
   virtual void connect(Face &face);
   
+  /**
+   * Set data to the host
+   * @param data A pointer to the buffer of data to send.
+   * @param dataLength The number of bytes in data.
+   */
   virtual void send(const unsigned char *data, unsigned int dataLength);
 
-  virtual void tempReceive();
+  /**
+   * Process any data to receive.  For each element received, call face.onReceivedElement.
+   * This is non-blocking and will silently time out after a brief period if there is no data to receive.
+   * You should repeatedly call this from an event loop.
+   * @throw This may throw an exception for reading data or in the callback for processing the data.  If you
+   * call this from an main event loop, you may want to catch and log/disregard all exceptions.
+   */
+  virtual void processEvents();
   
+  /**
+   * Close the connection to the host.
+   */
   virtual void close();
 
 private:
diff --git a/tests/test-get-async.cpp b/tests/test-get-async.cpp
index 1acf65f..4b66e7d 100644
--- a/tests/test-get-async.cpp
+++ b/tests/test-get-async.cpp
@@ -47,9 +47,9 @@
     Face face("E.hub.ndn.ucla.edu", 9695, shared_ptr<UdpTransport>(new UdpTransport()));
     face.expressInterest(Name("/ndn/ucla.edu/apps/ndn-js-test/hello.txt/level2/%FD%05%0B%16%7D%95%0E"), &closure);
     
-    // Pump the receive process.  This should really be done by a socket listener.
+    // The main event loop.
     while (!closure.gotContent_)
-      face.getTransport()->tempReceive();    
+      face.processEvents();    
   } catch (std::exception &e) {
     cout << "exception: " << e.what() << endl;
   }