From eb323e056e747d71867cf965434811c1de925de2 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Sat, 23 Mar 2019 14:13:53 +0100 Subject: [HICN-141] Definition of a C API for hicn-light Change-Id: Id861f0abe58b1e3c9ba8cc76701da0f9c6801748 Signed-off-by: Luca Muscariello Signed-off-by: Angelo Mantellini --- hicn-light/src/hicn/io/hicnListener.c | 727 ++++++++++++++++++++++++++++++++++ 1 file changed, 727 insertions(+) create mode 100644 hicn-light/src/hicn/io/hicnListener.c (limited to 'hicn-light/src/hicn/io/hicnListener.c') diff --git a/hicn-light/src/hicn/io/hicnListener.c b/hicn-light/src/hicn/io/hicnListener.c new file mode 100644 index 000000000..3f6cab94e --- /dev/null +++ b/hicn-light/src/hicn/io/hicnListener.c @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#ifdef WITH_MAPME +#include +#include +#include +#include +#endif /* WITH_MAPME */ +#include +#include +#include +#include +#include +#include +#include + +#define IPv6 6 +#define IPv4 4 +#define MTU_SIZE 1500 // bytes +#define MAX_HICN_RETRY 5 + +struct hicn_listener { + Forwarder *forwarder; + Logger *logger; + + PARCEvent *hicn_event; + int hicn_fd; // this is the file descriptor got from hicn library + + Address + *localAddress; // this is the local address or 0::0 in case of the + // main listener this is the address used inside + // forwarder to identify the listener. Notice that this + // address is the same as the fisical interfaces on + // which we create the TUN. it is NOT the TUN address + // which is given by libhicn after the bind operation + // However the user alway uses this address since is + // the only one available at configuration time + + unsigned inetFamily; + + int connection_id; // this is used only if the listener is used to receive + // data packets we assume that 1 connection is associated + // to one listener in this case so we set the + // connection_id we the connection is create. if this id + // is not set and a data packet is received, the packet is + // dropped + + unsigned conn_id; +}; + +static void _destroy(ListenerOps **listenerOpsPtr); +static unsigned _getInterfaceIndex(const ListenerOps *ops); +static const Address *_getListenAddress(const ListenerOps *ops); +static EncapType _getEncapType(const ListenerOps *ops); +static int _getSocket(const ListenerOps *ops); + +static ListenerOps _hicnTemplate = {.context = NULL, + .destroy = &_destroy, + .getInterfaceIndex = &_getInterfaceIndex, + .getListenAddress = &_getListenAddress, + .getEncapType = &_getEncapType, + .getSocket = &_getSocket}; + +static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid); + +static bool _isEmptyAddressIPv6(Address *address) { + struct sockaddr_in6 *addr6 = + parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6)); + parcAssertNotNull(addr6, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(addr6)); + + addressGetInet6(address, addr6); + + bool res = true; + for (int i = 0; i < 16; ++i) { + if (addr6->sin6_addr.s6_addr[i] != 0) { + res = false; + } + } + + parcMemory_Deallocate((void **)&addr6); + + return res; +} + +static bool _isEmptyAddressIPv4(Address *address) { + bool res = false; + + if (strcmp("inet4://0.0.0.0:1234", addressToString(address)) == 0) res = true; + return res; +} + +ListenerOps *hicnListener_CreateInet(Forwarder *forwarder, char *symbolic, + Address *address) { + HicnListener *hicn = parcMemory_AllocateAndClear(sizeof(HicnListener)); + parcAssertNotNull(hicn, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(HicnListener)); + + hicn->forwarder = forwarder; + hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + + hicn->conn_id = forwarder_GetNextConnectionId(forwarder); + hicn->localAddress = addressCopy(address); + + hicn->inetFamily = IPv4; + + hicn->connection_id = -1; + + hicn_socket_helper_t *hicnSocketHelper = + forwarder_GetHicnSocketHelper(forwarder); + + if (_isEmptyAddressIPv4(address)) { + hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, NULL); + } else { + struct sockaddr_in *tmpAddr = + parcMemory_AllocateAndClear(sizeof(struct sockaddr_in)); + parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(tmpAddr)); + addressGetInet(address, tmpAddr); + char *local_addr = parcMemory_AllocateAndClear(INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(tmpAddr->sin_addr), local_addr, INET_ADDRSTRLEN); + parcMemory_Deallocate((void **)&tmpAddr); + + hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, local_addr); + + parcMemory_Deallocate((void **)&local_addr); + } + + if (hicn->hicn_fd < 0) { + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Debug)) { + logger_Log( + hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "HicnListener %s: error while creating an hicn listener in lib_hicn", + symbolic); + } + logger_Release(&hicn->logger); + addressDestroy(&hicn->localAddress); + parcMemory_Deallocate((void **)&hicn); + return NULL; + } + + // Set non-blocking flag + int flags = fcntl(hicn->hicn_fd, F_GETFL, NULL); + parcAssertTrue(flags != -1, + "fcntl failed to obtain file descriptor flags (%d)", errno); + int failure = fcntl(hicn->hicn_fd, F_SETFL, flags | O_NONBLOCK); + parcAssertFalse(failure, "fcntl failed to set file descriptor flags (%d)", + errno); + + hicn->hicn_event = dispatcher_CreateNetworkEvent( + forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb, + (void *)hicn, hicn->hicn_fd); + dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), + hicn->hicn_event); + + ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + + memcpy(ops, &_hicnTemplate, sizeof(ListenerOps)); + ops->context = hicn; + + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "HicnListener %s created", symbolic); + } + + return ops; + return NULL; +} + +ListenerOps *hicnListener_CreateInet6(Forwarder *forwarder, char *symbolic, + Address *address) { + HicnListener *hicn = parcMemory_AllocateAndClear(sizeof(HicnListener)); + parcAssertNotNull(hicn, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(HicnListener)); + + hicn->forwarder = forwarder; + hicn->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + + hicn->conn_id = forwarder_GetNextConnectionId(forwarder); + hicn->localAddress = addressCopy(address); + + hicn->inetFamily = IPv6; + + hicn->connection_id = -1; + + // the call to libhicn is the same both for the main and the normal listeners + // in both cases we need to set only the identifier. In the case of normal + // listener (listener for data packet) we let the library select the right ip + // address we just need to set the right type of packet + + hicn_socket_helper_t *hicnSocketHelper = + forwarder_GetHicnSocketHelper(forwarder); + + if (_isEmptyAddressIPv6(address)) { + // create main listener + hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, NULL); + } else { + // create listener for the connetion + struct sockaddr_in6 *tmpAddr = + parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6)); + + parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(tmpAddr)); + addressGetInet6(address, tmpAddr); + + char *local_addr = parcMemory_AllocateAndClear(INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &(tmpAddr->sin6_addr), local_addr, INET6_ADDRSTRLEN); + + parcMemory_Deallocate((void **)&tmpAddr); + + hicn->hicn_fd = hicn_socket(hicnSocketHelper, symbolic, local_addr); + + parcMemory_Deallocate((void **)&local_addr); + } + + if (hicn->hicn_fd < 0) { + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Debug)) { + logger_Log( + hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "HicnListener %s: error while creating an hicn listener in lib_hicn", + symbolic); + } + logger_Release(&hicn->logger); + addressDestroy(&hicn->localAddress); + parcMemory_Deallocate((void **)&hicn); + return NULL; + } + + // Set non-blocking flag + int flags = fcntl(hicn->hicn_fd, F_GETFL, NULL); + parcAssertTrue(flags != -1, + "fcntl failed to obtain file descriptor flags (%d)", errno); + int failure = fcntl(hicn->hicn_fd, F_SETFL, flags | O_NONBLOCK); + parcAssertFalse(failure, "fcntl failed to set file descriptor flags (%d)", + errno); + + hicn->hicn_event = dispatcher_CreateNetworkEvent( + forwarder_GetDispatcher(forwarder), true, _hicnListener_readcb, + (void *)hicn, hicn->hicn_fd); + dispatcher_StartNetworkEvent(forwarder_GetDispatcher(forwarder), + hicn->hicn_event); + + ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + + memcpy(ops, &_hicnTemplate, sizeof(ListenerOps)); + ops->context = hicn; + + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "HicnListener %s created", symbolic); + } + + return ops; +} + +bool _hicnListener_BindInet6(ListenerOps *ops, const Address *remoteAddress) { + HicnListener *hicn = (HicnListener *)ops->context; + hicn_socket_helper_t *hicnSocketHelper = + forwarder_GetHicnSocketHelper(hicn->forwarder); + + struct sockaddr_in6 *tmpAddr = + parcMemory_AllocateAndClear(sizeof(struct sockaddr_in6)); + parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(tmpAddr)); + addressGetInet6(remoteAddress, tmpAddr); + char *remote_addr = parcMemory_AllocateAndClear(INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &(tmpAddr->sin6_addr), remote_addr, INET6_ADDRSTRLEN); + parcMemory_Deallocate((void **)&tmpAddr); + + int res = hicn_bind(hicnSocketHelper, hicn->hicn_fd, remote_addr); + + bool result = false; + if (res < 0) { + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Debug)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "hicn_bild failed %d %s", res, hicn_socket_strerror(res)); + } + } else { + result = true; + } + + parcMemory_Deallocate((void **)&remote_addr); + + return result; +} + +bool _hicnListener_BindInet(ListenerOps *ops, const Address *remoteAddress) { + HicnListener *hicn = (HicnListener *)ops->context; + hicn_socket_helper_t *hicnSocketHelper = + forwarder_GetHicnSocketHelper(hicn->forwarder); + + struct sockaddr_in *tmpAddr = + parcMemory_AllocateAndClear(sizeof(struct sockaddr_in)); + parcAssertNotNull(tmpAddr, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(tmpAddr)); + addressGetInet(remoteAddress, tmpAddr); + char *remote_addr = parcMemory_AllocateAndClear(INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(tmpAddr->sin_addr), remote_addr, INET_ADDRSTRLEN); + parcMemory_Deallocate((void **)&tmpAddr); + + int res = hicn_bind(hicnSocketHelper, hicn->hicn_fd, remote_addr); + bool result = false; + + if (res < 0) { + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Debug)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "hicn_bild failed %d %s", res, hicn_socket_strerror(res)); + } + } else { + result = true; + } + + parcMemory_Deallocate((void **)&remote_addr); + + return result; +} + +bool hicnListener_Bind(ListenerOps *ops, const Address *remoteAddress) { + if (addressGetType(remoteAddress) == ADDR_INET) { + return _hicnListener_BindInet(ops, remoteAddress); + } else if (addressGetType(remoteAddress) == ADDR_INET6) { + return _hicnListener_BindInet6(ops, remoteAddress); + } else { + printf("Bind failed: Invalid address\n"); + return false; + } +} + +bool hicnListener_Punting(ListenerOps *ops, const char *prefix) { + HicnListener *hicn = (HicnListener *)ops->context; + hicn_socket_helper_t *hicnSocketHelper = + forwarder_GetHicnSocketHelper(hicn->forwarder); + + int res = hicn_listen(hicnSocketHelper, hicn->hicn_fd, prefix); + int retry = 0; + + while (res < 0 && retry < MAX_HICN_RETRY) { + sleep(1); + res = hicn_listen(hicnSocketHelper, hicn->hicn_fd, prefix); + retry++; + } + + if (res < 0) { + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Debug)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "hicn_listen failed %d %s", res, hicn_socket_strerror(res)); + } + return false; + } + + return true; +} + +bool hicnListener_SetConnectionId(ListenerOps *ops, unsigned connId) { + HicnListener *hicn = (HicnListener *)ops->context; + if (hicn) { + hicn->connection_id = connId; + return true; + } + return false; +} + +static void _hicnListener_Destroy(HicnListener **listenerPtr) { + parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*listenerPtr, + "Parameter must derefernce to non-null pointer"); + + HicnListener *hicn = *listenerPtr; + + // close(hicn->hicn_fd); //XXX close the fd in the hicnlib (detroy listener?) + dispatcher_DestroyNetworkEvent(forwarder_GetDispatcher(hicn->forwarder), + &hicn->hicn_event); + logger_Release(&hicn->logger); + addressDestroy(&hicn->localAddress); + parcMemory_Deallocate((void **)&hicn); + *listenerPtr = NULL; +} + +static void _destroy(ListenerOps **listenerOpsPtr) { + ListenerOps *ops = *listenerOpsPtr; + HicnListener *hicn = (HicnListener *)ops->context; + _hicnListener_Destroy(&hicn); + parcMemory_Deallocate((void **)&ops); + *listenerOpsPtr = NULL; +} + +static unsigned _getInterfaceIndex(const ListenerOps *ops) { + HicnListener *hicn = (HicnListener *)ops->context; + return hicn->conn_id; +} + +static const Address *_getListenAddress(const ListenerOps *ops) { + HicnListener *hicn = (HicnListener *)ops->context; + return hicn->localAddress; +} + +static EncapType _getEncapType(const ListenerOps *ops) { return ENCAP_HICN; } + +static int _getSocket(const ListenerOps *ops) { + HicnListener *hicn = (HicnListener *)ops->context; + return hicn->hicn_fd; +} + +// =============================== + +static void _readFrameToDiscard(HicnListener *hicn, int fd) { + // we need to discard the frame. Read 1 byte. This will clear it off the + // stack. + uint8_t buffer; + int nread = read(fd, &buffer, 1); + + if (nread > 0) { + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Debug)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "Discarded frame from fd %d", fd); + } + } else if (nread < 0) { + printf("Error trying to discard frame from fd %d: (%d) %s", fd, errno, + strerror(errno)); + if (logger_IsLoggable(hicn->logger, LoggerFacility_IO, + PARCLogLevel_Error)) { + logger_Log(hicn->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__, + "Error trying to discard frame from fd %d: (%d) %s", fd, errno, + strerror(errno)); + } + } +} + +static unsigned _createNewConnection(HicnListener *hicn, int fd, + const AddressPair *pair) { + bool isLocal = false; + + // udpConnection_Create takes ownership of the pair + IoOperations *ops = hicnConnection_Create(hicn->forwarder, fd, pair, isLocal); + Connection *conn = connection_Create(ops); + + connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), conn); + unsigned connid = ioOperations_GetConnectionId(ops); + + return connid; +} + +const Connection *_findConnectionFromPacket(HicnListener *hicn, + Address *packetSourceAddress) { + const Connection *conn = NULL; + if (hicn->connection_id != -1) { + conn = connectionTable_FindById( + forwarder_GetConnectionTable(hicn->forwarder), hicn->connection_id); + } else { + if (packetSourceAddress != NULL) { + // in this first check we try to retrieve the standard connection + // generated by the hicn-light + AddressPair *pair = + addressPair_Create(hicn->localAddress, packetSourceAddress); + conn = connectionTable_FindByAddressPair( + forwarder_GetConnectionTable(hicn->forwarder), pair); + addressPair_Release(&pair); + } + } + + return conn; +} + +static Address *_createAddressFromPacket(uint8_t *msgBuffer) { + Address *packetAddr = NULL; + if (messageHandler_GetIPPacketType(msgBuffer) == IPv6_TYPE) { + struct sockaddr_in6 addr_in6; + addr_in6.sin6_family = AF_INET6; + addr_in6.sin6_port = htons(1234); + addr_in6.sin6_flowinfo = 0; + addr_in6.sin6_scope_id = 0; + memcpy(&addr_in6.sin6_addr, + (struct in6_addr *)messageHandler_GetSource(msgBuffer), 16); + packetAddr = addressCreateFromInet6(&addr_in6); + } else if (messageHandler_GetIPPacketType(msgBuffer) == IPv4_TYPE) { + struct sockaddr_in addr_in; + addr_in.sin_family = AF_INET; + addr_in.sin_port = htons(1234); + memcpy(&addr_in.sin_addr, + (struct in_addr *)messageHandler_GetSource(msgBuffer), 4); + packetAddr = addressCreateFromInet(&addr_in); + } + return packetAddr; +} + +static void _handleProbeMessage(HicnListener *hicn, uint8_t *msgBuffer) { + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + if (packetAddr != NULL) { + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + if (conn != NULL) { + // we drop all the probes for a connection that does not exists + connection_HandleProbe((Connection *)conn, msgBuffer, + forwarder_GetTicks(hicn->forwarder)); + } + } + + addressDestroy(&packetAddr); + parcMemory_Deallocate((void **)&msgBuffer); +} + +static void _handleWldrNotification(HicnListener *hicn, uint8_t *msgBuffer) { + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + if (packetAddr == NULL) { + parcMemory_Deallocate((void **)&msgBuffer); + return; + } + + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + if (conn == NULL) { + addressDestroy(&packetAddr); + return; + } + + addressDestroy(&packetAddr); + + Message *message = message_CreateFromByteArray( + connection_GetConnectionId(conn), msgBuffer, + MessagePacketType_WldrNotification, forwarder_GetTicks(hicn->forwarder), + forwarder_GetLogger(hicn->forwarder)); + + connection_HandleWldrNotification((Connection *)conn, message); + + message_Release(&message); +} + +#ifdef WITH_MAPME +static void _handleMapMe(HicnListener *hicn, int fd, uint8_t *msgBuffer) { + Address *packetAddr = _createAddressFromPacket(msgBuffer); + + if (packetAddr == NULL) { + parcMemory_Deallocate((void **)&msgBuffer); + return; + } + + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + unsigned conn_id; + if (conn == NULL) { + /* Unlike the interest path, we don't create virtual connections bound + * on the listener, whose only interest is to send data, but full + * tunnels to be able to route interests + * + * packetAddr is the remote address, we need to ask the lib for our + * local address + * hicn->localAddress is None as the interest is received by the main + * listener. + */ + printf("MapMe, connection did not exist, creating\n"); + + /* Populate remote_address through packetAddr */ + struct sockaddr_in6 sockaddr; // XXX IPv6 only + addressGetInet6(packetAddr, &sockaddr); + ip_address_t remote_address = {.family = AF_INET6, + .prefix_len = IPV6_ADDR_LEN_BITS}; + memcpy(&remote_address.buffer, &sockaddr.sin6_addr, + ip_address_len(&remote_address)); + + /* Get local address through libhicn */ + ip_address_t local_address; + int rc = hicn_get_local_address(&remote_address, &local_address); + if (rc < 0) { + printf("Error getting local address. Discarded mapme packet.\n"); + return; + } + + struct sockaddr_in6 addr_in6; + addr_in6.sin6_family = AF_INET6; + addr_in6.sin6_port = htons(1234); + addr_in6.sin6_flowinfo = 0; + addr_in6.sin6_scope_id = 0; + memcpy(&addr_in6.sin6_addr, (struct in6_addr *)&(local_address.buffer), 16); + + Address *localAddr = addressCreateFromInet6(&addr_in6); + IoOperations *ops = + hicnTunnel_Create(hicn->forwarder, localAddr, packetAddr); + + if (!ops) { + printf("Error creating tunnel. Discarded mapme packet.\n"); + return; + } + + conn = connection_Create(ops); + + connectionTable_Add(forwarder_GetConnectionTable(hicn->forwarder), + (Connection *)conn); + } + conn_id = connection_GetConnectionId(conn); + + addressDestroy(&packetAddr); + + forwarder_ProcessMapMe(hicn->forwarder, msgBuffer, conn_id); +} +#endif /* WITH_MAPME */ + +static Message *_readMessage(HicnListener *hicn, int fd, uint8_t *msgBuffer) { + Message *message = NULL; + + ssize_t readLength = read(fd, msgBuffer, MTU_SIZE); + + if (readLength < 0) { + printf("read failed %d: (%d) %s\n", fd, errno, strerror(errno)); + return message; + } + + size_t packetLength = messageHandler_GetTotalPacketLength(msgBuffer); + + if (readLength != packetLength) { + parcMemory_Deallocate((void **)&msgBuffer); + return message; + } + + if (messageHandler_IsTCP(msgBuffer)) { + MessagePacketType pktType; + unsigned connid = 0; + if (messageHandler_IsData(msgBuffer)) { + pktType = MessagePacketType_ContentObject; + if (hicn->connection_id == -1) { + parcMemory_Deallocate((void **)&msgBuffer); + return message; + } else { + connid = hicn->connection_id; + } + } else if (messageHandler_IsInterest(msgBuffer)) { + // notice that the connections for the interest (the one that we create at + // run time) uses as a local address 0::0, so the main tun + pktType = MessagePacketType_Interest; + Address *packetAddr = _createAddressFromPacket(msgBuffer); + const Connection *conn = _findConnectionFromPacket(hicn, packetAddr); + + if (conn == NULL) { + AddressPair *pair = addressPair_Create(hicn->localAddress, packetAddr); + connid = _createNewConnection(hicn, fd, pair); + addressPair_Release(&pair); + } else { + connid = connection_GetConnectionId(conn); + } + addressDestroy(&packetAddr); + } else { + printf("Got a packet that is not a data nor an interest, drop it!\n"); + parcMemory_Deallocate((void **)&msgBuffer); + return message; + } + + message = message_CreateFromByteArray(connid, msgBuffer, pktType, + forwarder_GetTicks(hicn->forwarder), + forwarder_GetLogger(hicn->forwarder)); + if (message == NULL) { + parcMemory_Deallocate((void **)&msgBuffer); + } + } else if (messageHandler_IsWldrNotification(msgBuffer)) { + _handleWldrNotification(hicn, msgBuffer); + } else if (messageHandler_IsLoadBalancerProbe(msgBuffer)) { + _handleProbeMessage(hicn, msgBuffer); + } +#ifdef WITH_MAPME + else if (mapMe_isMapMe(msgBuffer)) { + /* This function triggers the handling of the MAP-Me message, and we + * will return NULL so as to terminate the processing of this + * msgBuffer. */ + _handleMapMe(hicn, fd, msgBuffer); + } +#endif /* WITH_MAPME */ + + return message; +} + +static void _receivePacket(HicnListener *hicn, int fd) { + Message *msg = NULL; + uint8_t *msgBuffer = parcMemory_AllocateAndClear(MTU_SIZE); + msg = _readMessage(hicn, fd, msgBuffer); + + if (msg) { + forwarder_Receive(hicn->forwarder, msg); + } +} + +static void _hicnListener_readcb(int fd, PARCEventType what, void *hicnVoid) { + HicnListener *hicn = (HicnListener *)hicnVoid; + + if (hicn->inetFamily == IPv4 || hicn->inetFamily == IPv6) { + if (what & PARCEventType_Read) { + _receivePacket(hicn, fd); + } + } else { + _readFrameToDiscard(hicn, fd); + } +} -- cgit 1.2.3-korg