From bac3da61644515f05663789b122554dc77549286 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 17 Jan 2019 13:47:57 +0100 Subject: This is the first commit of the hicn project Change-Id: I6f2544ad9b9f8891c88cc4bcce3cf19bd3cc863f Signed-off-by: Luca Muscariello --- hicn-light/src/io/tcpListener.c | 233 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 233 insertions(+) create mode 100755 hicn-light/src/io/tcpListener.c (limited to 'hicn-light/src/io/tcpListener.c') diff --git a/hicn-light/src/io/tcpListener.c b/hicn-light/src/io/tcpListener.c new file mode 100755 index 000000000..6f0477f5b --- /dev/null +++ b/hicn-light/src/io/tcpListener.c @@ -0,0 +1,233 @@ +/* + * 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 + +typedef struct tcp_listener { + Forwarder *forwarder; + Logger *logger; + + PARCEventSocket *listener; + + Address *localAddress; + + unsigned id; + + // is the localAddress as 127.0.0.0 address? + bool isLocalAddressLocal; +} _TcpListener; + +static void _tcpListener_Destroy(_TcpListener **listenerPtr); + +static void _tcpListener_OpsDestroy(ListenerOps **listenerOpsPtr); +static unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops); +static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops); +static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops); + +static ListenerOps _tcpTemplate = { + .context = NULL, + .destroy = &_tcpListener_OpsDestroy, + .getInterfaceIndex = &_tcpListener_OpsGetInterfaceIndex, + .getListenAddress = &_tcpListener_OpsGetListenAddress, + .getEncapType = &_tcpListener_OpsGetEncapType, + .getSocket = NULL}; + +// STREAM daemon listener callback +static void _tcpListener_Listen(int, struct sockaddr *, int socklen, + void *tcpVoid); + +ListenerOps *tcpListener_CreateInet6(Forwarder *forwarder, + struct sockaddr_in6 sin6) { + _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); + parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(_TcpListener)); + + tcp->forwarder = forwarder; + tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + + tcp->listener = dispatcher_CreateListener( + forwarder_GetDispatcher(forwarder), _tcpListener_Listen, (void *)tcp, -1, + (struct sockaddr *)&sin6, sizeof(sin6)); + + if (tcp->listener == NULL) { + logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__, + "dispatcher_CreateListener failed to create listener (%d) %s", + errno, strerror(errno)); + logger_Release(&tcp->logger); + parcMemory_Deallocate((void **)&tcp); + return NULL; + } + + tcp->localAddress = addressCreateFromInet6(&sin6); + tcp->id = forwarder_GetNextConnectionId(forwarder); + tcp->isLocalAddressLocal = + parcNetwork_IsSocketLocal((struct sockaddr *)&sin6); + + ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + + memcpy(ops, &_tcpTemplate, sizeof(ListenerOps)); + ops->context = tcp; + + if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) { + char *str = addressToString(tcp->localAddress); + logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "TcpListener %p created for address %s (isLocal %d)", + (void *)tcp, str, tcp->isLocalAddressLocal); + parcMemory_Deallocate((void **)&str); + } + + return ops; +} + +ListenerOps *tcpListener_CreateInet(Forwarder *forwarder, + struct sockaddr_in sin) { + _TcpListener *tcp = parcMemory_AllocateAndClear(sizeof(_TcpListener)); + parcAssertNotNull(tcp, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(_TcpListener)); + + tcp->forwarder = forwarder; + tcp->logger = logger_Acquire(forwarder_GetLogger(forwarder)); + tcp->listener = dispatcher_CreateListener( + forwarder_GetDispatcher(forwarder), _tcpListener_Listen, (void *)tcp, -1, + (struct sockaddr *)&sin, sizeof(sin)); + + if (tcp->listener == NULL) { + logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Error, __func__, + "dispatcher_CreateListener failed to create listener (%d) %s", + errno, strerror(errno)); + + logger_Release(&tcp->logger); + parcMemory_Deallocate((void **)&tcp); + return NULL; + } + + tcp->localAddress = addressCreateFromInet(&sin); + tcp->id = forwarder_GetNextConnectionId(forwarder); + tcp->isLocalAddressLocal = parcNetwork_IsSocketLocal((struct sockaddr *)&sin); + + ListenerOps *ops = parcMemory_AllocateAndClear(sizeof(ListenerOps)); + parcAssertNotNull(ops, "parcMemory_AllocateAndClear(%zu) returned NULL", + sizeof(ListenerOps)); + + memcpy(ops, &_tcpTemplate, sizeof(ListenerOps)); + ops->context = tcp; + + if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) { + char *str = addressToString(tcp->localAddress); + logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "TcpListener %p created for address %s (isLocal %d)", + (void *)tcp, str, tcp->isLocalAddressLocal); + parcMemory_Deallocate((void **)&str); + } + + return ops; +} + +static void _tcpListener_Destroy(_TcpListener **listenerPtr) { + parcAssertNotNull(listenerPtr, "Parameter must be non-null double pointer"); + parcAssertNotNull(*listenerPtr, + "Parameter must derefernce to non-null pointer"); + _TcpListener *tcp = *listenerPtr; + + if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) { + char *str = addressToString(tcp->localAddress); + logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "TcpListener %p destroyed", (void *)tcp); + parcMemory_Deallocate((void **)&str); + } + + logger_Release(&tcp->logger); + dispatcher_DestroyListener(forwarder_GetDispatcher(tcp->forwarder), + &tcp->listener); + addressDestroy(&tcp->localAddress); + parcMemory_Deallocate((void **)&tcp); + *listenerPtr = NULL; +} + +// ================================================== + +static void _tcpListener_Listen(int fd, struct sockaddr *sa, int socklen, + void *tcpVoid) { + _TcpListener *tcp = (_TcpListener *)tcpVoid; + + Address *remote; + + switch (sa->sa_family) { + case AF_INET: + remote = addressCreateFromInet((struct sockaddr_in *)sa); + break; + + case AF_INET6: + remote = addressCreateFromInet6((struct sockaddr_in6 *)sa); + break; + + default: + parcTrapIllegalValue(sa, "Expected INET or INET6, got %d", sa->sa_family); + abort(); + } + + AddressPair *pair = addressPair_Create(tcp->localAddress, remote); + + IoOperations *ops = streamConnection_AcceptConnection( + tcp->forwarder, fd, pair, tcp->isLocalAddressLocal); + Connection *conn = connection_Create(ops); + + connectionTable_Add(forwarder_GetConnectionTable(tcp->forwarder), conn); + + if (logger_IsLoggable(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug)) { + logger_Log(tcp->logger, LoggerFacility_IO, PARCLogLevel_Debug, __func__, + "TcpListener %p listen started", (void *)tcp); + } + + addressDestroy(&remote); +} + +static void _tcpListener_OpsDestroy(ListenerOps **listenerOpsPtr) { + ListenerOps *ops = *listenerOpsPtr; + _TcpListener *tcp = (_TcpListener *)ops->context; + _tcpListener_Destroy(&tcp); + parcMemory_Deallocate((void **)&ops); + *listenerOpsPtr = NULL; +} + +static unsigned _tcpListener_OpsGetInterfaceIndex(const ListenerOps *ops) { + _TcpListener *tcp = (_TcpListener *)ops->context; + return tcp->id; +} + +static const Address *_tcpListener_OpsGetListenAddress(const ListenerOps *ops) { + _TcpListener *tcp = (_TcpListener *)ops->context; + return tcp->localAddress; +} + +static EncapType _tcpListener_OpsGetEncapType(const ListenerOps *ops) { + return ENCAP_TCP; +} -- cgit 1.2.3-korg