summaryrefslogtreecommitdiffstats
path: root/hicn-light/src/io
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/io')
-rw-r--r--hicn-light/src/io/hicnConnection.c9
-rw-r--r--hicn-light/src/io/ioOperations.c6
-rw-r--r--hicn-light/src/io/ioOperations.h36
-rw-r--r--hicn-light/src/io/streamConnection.c38
-rw-r--r--hicn-light/src/io/udpConnection.c94
-rw-r--r--hicn-light/src/io/udpListener.c216
6 files changed, 150 insertions, 249 deletions
diff --git a/hicn-light/src/io/hicnConnection.c b/hicn-light/src/io/hicnConnection.c
index 6def8ed43..991c0064e 100644
--- a/hicn-light/src/io/hicnConnection.c
+++ b/hicn-light/src/io/hicnConnection.c
@@ -75,6 +75,7 @@ typedef struct hicn_state {
// Prototypes
static bool _send(IoOperations *ops, const Address *nexthop, Message *message);
+static bool _sendCommandResponse(IoOperations *ops, struct iovec *message);
static const Address *_getRemoteAddress(const IoOperations *ops);
static const AddressPair *_getAddressPair(const IoOperations *ops);
static unsigned _getConnectionId(const IoOperations *ops);
@@ -100,6 +101,7 @@ static const void *_streamConnection_Class(const IoOperations *ops) {
static IoOperations _template = {.closure = NULL,
.send = &_send,
+ .sendCommandResponse = &_sendCommandResponse,
.getRemoteAddress = &_getRemoteAddress,
.getAddressPair = &_getAddressPair,
.getConnectionId = &_getConnectionId,
@@ -253,7 +255,6 @@ static unsigned _getConnectionId(const IoOperations *ops) {
* sends a message to the peer.
*
* @param dummy is ignored. .
- * @return <#return#>
*/
static bool _send(IoOperations *ops, const Address *dummy, Message *message) {
parcAssertNotNull(ops, "Parameter ops must be non-null");
@@ -328,6 +329,12 @@ static bool _send(IoOperations *ops, const Address *dummy, Message *message) {
return true;
}
+static bool _sendCommandResponse(IoOperations *ops, struct iovec *message) {
+ //XXX this should be nerver called since we do not handle control messages
+ //with hicn connections, so nothing to do here!
+ return false;
+}
+
static list_connections_type _getConnectionType(const IoOperations *ops) {
return CONN_HICN;
}
diff --git a/hicn-light/src/io/ioOperations.c b/hicn-light/src/io/ioOperations.c
index bbc8cec91..b40b51d76 100644
--- a/hicn-light/src/io/ioOperations.c
+++ b/hicn-light/src/io/ioOperations.c
@@ -28,6 +28,12 @@ bool ioOperations_Send(IoOperations *ops, const Address *nexthop,
return ops->send(ops, nexthop, message);
}
+bool ioOperations_SendCommandResponse(IoOperations *ops,
+ struct iovec *message) {
+ return ops->sendCommandResponse(ops, message);
+}
+
+
const Address *ioOperations_GetRemoteAddress(const IoOperations *ops) {
return ops->getRemoteAddress(ops);
}
diff --git a/hicn-light/src/io/ioOperations.h b/hicn-light/src/io/ioOperations.h
index dee66030d..48319c259 100644
--- a/hicn-light/src/io/ioOperations.h
+++ b/hicn-light/src/io/ioOperations.h
@@ -15,38 +15,6 @@
/**
* Defines the interface all connections use to communicate with the forwarder.
- *
- * @code
- *
- * static IoOperations _template = {
- * .closure = NULL,
- * .send = &_etherConnection_Send,
- * .getRemoteAddress = &_etherConnection_GetRemoteAddress,
- * .getAddressPair = &_etherConnection_GetAddressPair,
- * .getConnectionId = &_etherConnection_GetConnectionId,
- * .isUp = &_etherConnection_IsUp,
- * .isLocal = &_etherConnection_IsLocal,
- * .destroy = &_etherConnection_DestroyOperations,
- * .class = &_etherConnection_Class,
- * .getConnectionType = &_etherConnection_getConnectionType
- * };
- *
- * IoOperations *
- * etherConnection_Create(Forwarder *forwarder, GenericEther *ether,
- * AddressPair *pair)
- * {
- * _EtherState *etherConnState = parcMemory_Allocate(sizeof(_EtherState));
- * // Fill in etherConnState with instance variables
- *
- * IoOperations *io_ops = parcMemory_Allocate(sizeof(IoOperations));
- * memcpy(io_ops, &_template, sizeof(IoOperations));
- * io_ops->closure = etherConnState;
- * // Add to connection table, send missives about connection state
- *
- * return op_ops;
- * }
- * @endcode
- *
*/
/**
@@ -95,6 +63,7 @@ typedef struct io_ops IoOperations;
struct io_ops {
void *closure;
bool (*send)(IoOperations *ops, const Address *nexthop, Message *message);
+ bool (*sendCommandResponse)(IoOperations *ops, struct iovec *message);
const Address *(*getRemoteAddress)(const IoOperations *ops);
const AddressPair *(*getAddressPair)(const IoOperations *ops);
bool (*isUp)(const IoOperations *ops);
@@ -201,6 +170,9 @@ void ioOperations_Release(IoOperations **opsPtr);
bool ioOperations_Send(IoOperations *ops, const Address *nexthop,
Message *message);
+bool ioOperations_SendCommandResponse(IoOperations *ops,
+ struct iovec *message);
+
/**
* A connection is made up of a local and a remote address. This function
* returns the remote address.
diff --git a/hicn-light/src/io/streamConnection.c b/hicn-light/src/io/streamConnection.c
index 948b6c01b..78c19fb18 100644
--- a/hicn-light/src/io/streamConnection.c
+++ b/hicn-light/src/io/streamConnection.c
@@ -65,6 +65,8 @@ typedef struct stream_state {
// Prototypes
static bool _streamConnection_Send(IoOperations *ops, const Address *nexthop,
Message *message);
+static bool _streamConnection_SendCommandResponse(IoOperations *ops,
+ struct iovec *msg);
static const Address *_streamConnection_GetRemoteAddress(
const IoOperations *ops);
static const AddressPair *_streamConnection_GetAddressPair(
@@ -80,31 +82,6 @@ static list_connections_type _streamConnection_GetConnectionType(
static Ticks _sendProbe(IoOperations *ops, unsigned probeType,
uint8_t *message);
-// REMINDER: when a new_command is added, the following array has to be updated
-// with the sizeof(new_command). It allows to allocate the buffer for receiving
-// the payload of the CONTROLLER REQUEST after the header has beed read. Each
-// command identifier (typedef enum command_id) corresponds to a position in the
-// following array.
-static int payloadLengthDaemon[LAST_COMMAND_VALUE] = {
- sizeof(add_listener_command),
- sizeof(add_connection_command),
- 0, // list connections: payload always 0 when get controller request
- sizeof(add_route_command),
- 0, // list routes: payload always 0 when get controller request
- sizeof(remove_connection_command),
- sizeof(remove_route_command),
- sizeof(cache_store_command),
- sizeof(cache_serve_command),
- 0, // cache clear
- sizeof(set_strategy_command),
- sizeof(set_wldr_command),
- sizeof(add_punting_command),
- 0, // list listeners: payload always 0 when get controller request
- sizeof(mapme_activator_command),
- sizeof(mapme_activator_command),
- sizeof(mapme_timing_command),
- sizeof(mapme_timing_command)};
-
/*
* This assigns a unique pointer to the void * which we use
* as a GUID for this class.
@@ -121,6 +98,7 @@ static const void *_streamConnection_Class(const IoOperations *ops) {
static IoOperations _template = {
.closure = NULL,
.send = &_streamConnection_Send,
+ .sendCommandResponse = &_streamConnection_SendCommandResponse,
.getRemoteAddress = &_streamConnection_GetRemoteAddress,
.getAddressPair = &_streamConnection_GetAddressPair,
.getConnectionId = &_streamConnection_GetConnectionId,
@@ -308,7 +286,7 @@ static unsigned _streamConnection_GetConnectionId(const IoOperations *ops) {
return stream->id;
}
-bool streamState_SendCommandResponse(IoOperations *ops,
+bool _streamConnection_SendCommandResponse(IoOperations *ops,
struct iovec *response) {
parcAssertNotNull(ops, "Parameter ops must be non-null");
parcAssertNotNull(response, "Parameter message must be non-null");
@@ -447,7 +425,7 @@ int _isACommand(PARCEventBuffer *input) {
// read first byte of the header
// first byte: must be a REQUEST_LIGHT
- if (msg[0] != 100) {
+ if (msg[0] != REQUEST_LIGHT) {
return LAST_COMMAND_VALUE;
}
@@ -468,7 +446,7 @@ PARCEventBuffer *_tryReadControlMessage(_StreamState *stream,
if (stream->nextMessageLength == 0) {
stream->nextMessageLength =
sizeof(header_control_message) +
- payloadLengthDaemon[command]; // consider the whole packet.
+ payloadLengthDaemon(command); // consider the whole packet.
}
if (bytesAvailable >= stream->nextMessageLength) {
@@ -487,13 +465,13 @@ PARCEventBuffer *_tryReadControlMessage(_StreamState *stream,
}
(*request)[0].iov_base = control; // header
(*request)[0].iov_len = sizeof(header_control_message);
- if (payloadLengthDaemon[command] > 0) {
+ if (payloadLengthDaemon(command) > 0) {
(*request)[1].iov_base =
control + sizeof(header_control_message); // payload
} else {
(*request)[1].iov_base = NULL;
}
- (*request)[1].iov_len = payloadLengthDaemon[command];
+ (*request)[1].iov_len = payloadLengthDaemon(command);
// now reset message length for next packet
stream->nextMessageLength = 0;
diff --git a/hicn-light/src/io/udpConnection.c b/hicn-light/src/io/udpConnection.c
index 6c2e35392..3faf2bfac 100644
--- a/hicn-light/src/io/udpConnection.c
+++ b/hicn-light/src/io/udpConnection.c
@@ -19,6 +19,7 @@
* NB The Send() function may overflow the output buffer
*
*/
+#include <sys/uio.h>
#include <errno.h>
#include <src/config.h>
@@ -58,6 +59,7 @@ typedef struct udp_state {
// Prototypes
static bool _send(IoOperations *ops, const Address *nexthop, Message *message);
+static bool _sendCommandResponse(IoOperations *ops, struct iovec *message);
static const Address *_getRemoteAddress(const IoOperations *ops);
static const AddressPair *_getAddressPair(const IoOperations *ops);
static unsigned _getConnectionId(const IoOperations *ops);
@@ -82,6 +84,7 @@ static const void *_streamConnection_Class(const IoOperations *ops) {
static IoOperations _template = {.closure = NULL,
.send = &_send,
+ .sendCommandResponse = &_sendCommandResponse,
.getRemoteAddress = &_getRemoteAddress,
.getAddressPair = &_getAddressPair,
.getConnectionId = &_getConnectionId,
@@ -239,38 +242,6 @@ static bool _send(IoOperations *ops, const Address *dummy, Message *message) {
// in this particular connection we don't need natting beacause we send the
// packet to the next hop using upd connection
-#if 0
- if((hicnConnState->peerAddressLength == sizeof(struct sockaddr_in)) || (hicnConnState->localAddressLength == sizeof(struct sockaddr_in)))
- return false;
-
- if(message_GetType(message) = MessagePacketType_ContentObject){
- //this is a data packet. We need to put the remote address in the destination field
- messageHandler_SetDestination_IPv6((uint8_t *) message_FixedHeader(message),
- &((struct sockaddr_in6 *) hicnConnState->peerAddress)->sin6_addr);
-
- } else if (message_GetType(message) == MessagePacketType_Interest) {
- //this si an interest packet. We need to put the local address in the source field
- messageHandler_SetSource_IPv6((uint8_t *) message_FixedHeader(message),
- &((struct sockaddr_in6 *) hicnConnState->localAddress)->sin6_addr);
-
- //only in this case we may need to set the probeDestAddress
- if(hicnConnState->refreshProbeDestAddress){
- _refreshProbeDestAddress(hicnConnState, message_FixedHeader(message));
- }
-
- } else if (message_GetType(message) == MessagePacketType_WldrNotification) {
- //here we don't need to do anything for now
- }else{
- //unkown packet
- if (logger_IsLoggable(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(hicnConnState->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "connid %u can't parse the message",
- hicnConnState->id);
- }
- return false;
- }
-#endif
-
ssize_t writeLength =
sendto(udpConnState->udpListenerSocket, message_FixedHeader(message),
(int)message_Length(message), 0, udpConnState->peerAddress,
@@ -290,44 +261,39 @@ static bool _send(IoOperations *ops, const Address *dummy, Message *message) {
return true;
}
+static bool _sendCommandResponse(IoOperations *ops, struct iovec *message){
+ parcAssertNotNull(ops, "Parameter ops must be non-null");
+ parcAssertNotNull(message, "Parameter message must be non-null");
+ _UdpState *udpConnState = (_UdpState *)ioOperations_GetClosure(ops);
+
+ // Perform connect before to establish association between this peer and
+ // the remote peer. This is required to use writev.
+ // Connection association can be changed at any time.
+ connect(udpConnState->udpListenerSocket,
+ udpConnState->peerAddress,
+ udpConnState->peerAddressLength);
+
+ ssize_t writeLength = writev(udpConnState->udpListenerSocket, message, 2);
+
+ struct sockaddr any_address = {0};
+ any_address.sa_family = AF_UNSPEC;
+ connect(udpConnState->udpListenerSocket,
+ &any_address, (socklen_t)sizeof(any_address));
+
+ if (writeLength < 0) {
+ return false;
+ }
+
+ return true;
+}
+
static list_connections_type _getConnectionType(const IoOperations *ops) {
return CONN_UDP;
}
static Ticks _sendProbe(IoOperations *ops, unsigned probeType,
uint8_t *message) {
-#if 0
- parcAssertNotNull(ops, "Parameter ops must be non-null");
- _MetisUdpState *udpConnState = (_MetisUdpState *) metisIoOperations_GetClosure(ops);
-
-
- uint8_t *pkt;
- size_t pkt_size = 8;
- pkt = (uint8_t *) malloc(sizeof(uint8_t) * pkt_size);
- for (unsigned i = 0; i < pkt_size; i++) {
- pkt[i] = 0;
- }
- pkt[0] = 1; //type
- pkt[1] = probeType; //packet type
- pkt[6] = 8; //header len (16bit, network order)
-
- ssize_t writeLen = sendto(udpConnState->udpListenerSocket, pkt, pkt_size, 0, udpConnState->peerAddress, udpConnState->peerAddressLength);
-
- if (writeLen < 0) {
- if (errno == EAGAIN || errno == EWOULDBLOCK) {
- free(pkt);
- return 0;
- } else {
- //this print is for debugging
- printf("Incorrect write length %zd, expected %zd: (%d) %s\n", writeLen, pkt_size, errno, strerror(errno));
- free(pkt);
- return 0;
- }
- }
-
- free(pkt);
- return metisForwarder_GetTicks(udpConnState->metis);
-#endif
+ //TODO
return 0;
}
diff --git a/hicn-light/src/io/udpListener.c b/hicn-light/src/io/udpListener.c
index 6c2947c66..4411bc7f6 100644
--- a/hicn-light/src/io/udpListener.c
+++ b/hicn-light/src/io/udpListener.c
@@ -282,55 +282,9 @@ static int _getSocket(const ListenerOps *ops) {
return (int)udp->udp_socket;
}
-// void
-// udpListener_SetPacketType(ListenerOps *ops, MessagePacketType type)
-//{
-// return;
-//}
-
// =====================================================================
/**
- * @function peekMesageLength
- * @abstract Peek at the next packet to learn its length by reading the fixed
- * header
- * @discussion
- * <#Discussion#>
- *
- * @param <#param1#>
- * @return <#return#>
- */
-static size_t _peekMessageLength(UdpListener *udp, int fd,
- struct sockaddr *peerIpAddress,
- socklen_t *peerIpAddressLengthPtr) {
- // to be fast I try to use just ipv6, this needs to be validated for ipv4
-
- size_t packetLength = 0;
-
- uint8_t *fixedHeader = (uint8_t *)malloc(
- sizeof(uint8_t) * messageHandler_GetIPHeaderLength(IPv6));
-
- // peek at the UDP packet and read in the fixed header.
- // Also returns the socket information for the remote peer
-
- ssize_t res = recvfrom(
- fd, fixedHeader, (int)messageHandler_GetIPHeaderLength(IPv6), MSG_PEEK,
- (struct sockaddr *)peerIpAddress, peerIpAddressLengthPtr);
-
- if (res == messageHandler_GetIPHeaderLength(IPv6)) {
- packetLength = messageHandler_GetTotalPacketLength(fixedHeader);
- } else {
- if (res < 0) {
- printf("error while readin packet\n");
- }
- }
-
- free(fixedHeader);
-
- return packetLength;
-}
-
-/**
* @function _constructAddressPair
* @abstract Creates the address pair that uniquely identifies the connection
* @discussion
@@ -441,100 +395,108 @@ static void _handleWldrNotification(UdpListener *udp, unsigned connId,
message_Release(&message);
}
-static Message *_readMessage(UdpListener *udp, int fd, size_t packetLength,
- AddressPair *pair) {
- uint8_t *msgBuffer = parcMemory_AllocateAndClear(packetLength);
-
- ssize_t readLength = read(fd, msgBuffer, (unsigned int)packetLength);
+static Message *_readMessage(UdpListener *udp, int fd,
+ AddressPair *pair, uint8_t * packet, bool * processed) {
Message *message = NULL;
- if (readLength < 0) {
- printf("read failed %d: (%d) %s\n", fd, errno, strerror(errno));
- return message;
- }
-
unsigned connid = 0;
bool foundConnection = _lookupConnectionId(udp, pair, &connid);
- if (readLength == packetLength) {
- // we need to check if it is a valid packet
- if (messageHandler_IsTCP(msgBuffer)) {
- MessagePacketType pktType;
-
- if (messageHandler_IsData(msgBuffer)) {
- pktType = MessagePacketType_ContentObject;
- if (!foundConnection) {
- parcMemory_Deallocate((void **)&msgBuffer);
- return message;
- }
- } else if (messageHandler_IsInterest(msgBuffer)) {
- pktType = MessagePacketType_Interest;
- if (!foundConnection) {
- connid = _createNewConnection(udp, fd, pair);
- }
- } else {
- printf("Got a packet that is not a data nor an interest, drop it!\n");
- parcMemory_Deallocate((void **)&msgBuffer);
+ if (messageHandler_IsTCP(packet)) {
+ *processed = true;
+ MessagePacketType pktType;
+
+ if (messageHandler_IsData(packet)) {
+ pktType = MessagePacketType_ContentObject;
+ if (!foundConnection) {
+ parcMemory_Deallocate((void **)&packet);
return message;
}
+ } else if (messageHandler_IsInterest(packet)) {
+ pktType = MessagePacketType_Interest;
+ if (!foundConnection) {
+ connid = _createNewConnection(udp, fd, pair);
+ }
+ } else {
+ printf("Got a packet that is not a data nor an interest, drop it!\n");
+ parcMemory_Deallocate((void **)&packet);
+ return message;
+ }
- message = message_CreateFromByteArray(
- connid, msgBuffer, pktType, forwarder_GetTicks(udp->forwarder),
- forwarder_GetLogger(udp->forwarder));
+ message = message_CreateFromByteArray(
+ connid, packet, pktType, forwarder_GetTicks(udp->forwarder),
+ forwarder_GetLogger(udp->forwarder));
- if (message == NULL) {
- parcMemory_Deallocate((void **)&msgBuffer);
- }
- } else if (messageHandler_IsWldrNotification(msgBuffer)) {
- _handleWldrNotification(udp, connid, msgBuffer);
- } else if (messageHandler_IsLoadBalancerProbe(msgBuffer)) {
- _handleProbeMessage(udp, msgBuffer);
+ if (message == NULL) {
+ parcMemory_Deallocate((void **)&packet);
}
+ } else if (messageHandler_IsWldrNotification(packet)) {
+ *processed = true;
+ _handleWldrNotification(udp, connid, packet);
+ } else if (messageHandler_IsLoadBalancerProbe(packet)) {
+ *processed = true;
+ _handleProbeMessage(udp, packet);
+ }
#ifdef WITH_MAPME
- else if (mapMe_isMapMe(msgBuffer)) {
- forwarder_ProcessMapMe(udp->forwarder, msgBuffer, connid);
- }
-#endif /* WITH_MAPME */
+ else if (mapMe_isMapMe(packet)) {
+ *processed = true;
+ forwarder_ProcessMapMe(udp->forwarder, packet, connid);
}
+#endif /* WITH_MAPME */
return message;
}
-static void _receivePacket(UdpListener *udp, int fd, size_t packetLength,
- struct sockaddr_storage *peerIpAddress,
- socklen_t peerIpAddressLength) {
- AddressPair *pair = _constructAddressPair(
- udp, (struct sockaddr *)peerIpAddress, peerIpAddressLength);
+static void _readCommand(UdpListener *udp, int fd,
+ AddressPair *pair,
+ uint8_t * command) {
- Message *message = _readMessage(udp, fd, packetLength, pair);
- addressPair_Release(&pair);
+ if (*command != REQUEST_LIGHT){
+ printf("the message received is not a command, drop\n");
+ return;
+ }
- if (message) {
- forwarder_Receive(udp->forwarder, message);
- } else {
+ command_id id = *(command + 1);
+
+ if ( id < 0 || id >= LAST_COMMAND_VALUE){
+ printf("the message received is not a valid command, drop\n");
return;
}
+
+ unsigned connid = 0;
+ bool foundConnection = _lookupConnectionId(udp, pair, &connid);
+ if(!foundConnection){
+ connid = _createNewConnection(udp, fd, pair);
+ }
+
+ struct iovec *request;
+ if (!(request = (struct iovec *) parcMemory_AllocateAndClear(
+ sizeof(struct iovec) * 2))) {
+ return;
+ }
+
+ request[0].iov_base = command;
+ request[0].iov_len = sizeof(header_control_message);
+ request[1].iov_base = command + sizeof(header_control_message);
+ request[1].iov_len = payloadLengthDaemon(id);
+
+ forwarder_ReceiveCommand(udp->forwarder, id, request, connid);
+ parcMemory_Deallocate((void **) &command);
+ parcMemory_Deallocate((void **) &request);
}
-static void _readFrameToDiscard(UdpListener *udp, int fd) {
- // we need to discard the frame. Read 1 byte. This will clear it off the
- // stack.
- uint8_t buffer;
- ssize_t nread = read(fd, &buffer, 1);
- if (nread == 1) {
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__,
- "Discarded frame from fd %d", fd);
- }
- } else if (nread < 0) {
- if (logger_IsLoggable(udp->logger, LoggerFacility_IO, PARCLogLevel_Error)) {
- logger_Log(udp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__,
- "Error trying to discard frame from fd %d: (%d) %s", fd, errno,
- strerror(errno));
- }
+static bool _receivePacket(UdpListener *udp, int fd,
+ AddressPair *pair,
+ uint8_t * packet) {
+ bool processed = false;
+ Message *message = _readMessage(udp, fd, pair,
+ packet, &processed);
+ if (message) {
+ forwarder_Receive(udp->forwarder, message);
}
+ return processed;
}
static void _readcb(int fd, PARCEventType what, void *udpVoid) {
@@ -553,14 +515,24 @@ static void _readcb(int fd, PARCEventType what, void *udpVoid) {
struct sockaddr_storage peerIpAddress;
socklen_t peerIpAddressLength = sizeof(peerIpAddress);
- size_t packetLength = _peekMessageLength(
- udp, fd, (struct sockaddr *)&peerIpAddress, &peerIpAddressLength);
+ //packet it deallocated by _receivePacket or _readCommand
+ uint8_t * packet = parcMemory_AllocateAndClear(1500); //max MTU
+ ssize_t readLength = recvfrom(fd, packet, 1500, 0,
+ (struct sockaddr *)&peerIpAddress, &peerIpAddressLength);
- if (packetLength > 0) {
- _receivePacket(udp, fd, packetLength, &peerIpAddress,
- peerIpAddressLength);
- } else {
- _readFrameToDiscard(udp, fd);
+ if(readLength < 0) {
+ printf("unable to read the message\n");
+ return;
}
+
+ AddressPair *pair = _constructAddressPair(
+ udp, (struct sockaddr *)&peerIpAddress, peerIpAddressLength);
+
+ bool done = _receivePacket(udp, fd, pair, packet);
+ if(!done){
+ _readCommand(udp, fd, pair, packet);
+ }
+
+ addressPair_Release(&pair);
}
}