123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include "util/events/FakeNetwork.h"
- #include "exception/Except.h"
- #include "interface/Iface.h"
- #include "interface/addressable/AddrIface.h"
- #include "memory/Allocator.h"
- #include "util/events/EventBase.h"
- #include "util/log/Log.h"
- #include "interface/ASynchronizer.h"
- #define Map_USE_HASH
- #define Map_USE_COMPARATOR
- #define Map_NAME OfIfaces
- #define Map_KEY_TYPE struct Sockaddr*
- #define Map_VALUE_TYPE struct FakeNetwork_UDPIface_pvt*
- #include "util/Map.h"
- static inline uint32_t Map_OfIfaces_hash(struct Sockaddr** key)
- {
- return Sockaddr_hash(*key);
- }
- static inline int Map_OfIfaces_compare(struct Sockaddr** keyA, struct Sockaddr** keyB)
- {
- return Sockaddr_compare(*keyA, *keyB);
- }
- struct FakeNetwork_pvt
- {
- struct FakeNetwork pub;
- struct Allocator* alloc;
- struct Log* log;
- struct EventBase* base;
- struct ASynchronizer* async;
- struct Iface fromAsync;
- struct Iface toAsync;
- uint16_t lastPort;
- struct Map_OfIfaces map;
- Identity
- };
- struct FakeNetwork_UDPIface_pvt
- {
- struct FakeNetwork_UDPIface pub;
- struct FakeNetwork_pvt* fnp;
- Identity
- };
- static void popSockaddr(struct Message* msg, struct Sockaddr_storage* ss)
- {
- uint64_t length = 0;
- Message_pop(msg, &length, 8, NULL);
- Message_shift(msg, 8, NULL);
- Assert_true(length >= Sockaddr_OVERHEAD);
- Assert_true(length <= sizeof(struct Sockaddr_storage));
- Message_pop(msg, ss, length, NULL);
- }
- static void pushSockaddr(struct Message* msg, struct Sockaddr* sa)
- {
- Message_push(msg, sa, sa->addrLen, NULL);
- }
- static Iface_DEFUN fromAsync(struct Message* msg, struct Iface* fnpFromAsync)
- {
- struct FakeNetwork_pvt* fnp =
- Identity_containerOf(fnpFromAsync, struct FakeNetwork_pvt, fromAsync);
- struct Sockaddr_storage dest;
- struct Sockaddr* dp = &dest.addr;
- popSockaddr(msg, &dest);
- int idx = Map_OfIfaces_indexForKey(&dp, &fnp->map);
- if (idx == -1) {
- char* destAddr = Sockaddr_print(dp, msg->alloc);
- // hack, the 'dest' becomes the source.
- popSockaddr(msg, &dest);
- char* srcAddr = Sockaddr_print(dp, msg->alloc);
- Log_debug(fnp->log, "Message with unknown dest address [%s] from [%s]", destAddr, srcAddr);
- return NULL;
- }
- struct FakeNetwork_UDPIface_pvt* fnip = Identity_check(fnp->map.values[idx]);
- return Iface_next(&fnip->pub.generic.iface, msg);
- }
- static Iface_DEFUN incoming(struct Message* msg, struct Iface* iface)
- {
- struct FakeNetwork_UDPIface_pvt* fnip =
- Identity_check((struct FakeNetwork_UDPIface_pvt*) iface);
- struct FakeNetwork_pvt* fnp = Identity_check(fnip->fnp);
- // Swap so that the message contains [dest][src][content]
- struct Sockaddr_storage dest;
- popSockaddr(msg, &dest);
- pushSockaddr(msg, fnip->pub.generic.addr);
- pushSockaddr(msg, &dest.addr);
- return Iface_next(&fnp->toAsync, msg);
- }
- struct FakeNetwork_UDPIface* FakeNetwork_iface(struct FakeNetwork* net,
- struct Sockaddr* bindAddress,
- struct Allocator* allocator)
- {
- struct FakeNetwork_pvt* fnp = Identity_check((struct FakeNetwork_pvt*) net);
- struct Allocator* alloc = Allocator_child(allocator);
- struct Sockaddr* addr = Sockaddr_clone(bindAddress, alloc);
- uint8_t* addrBytes;
- int addrLen = Sockaddr_getAddress(addr, &addrBytes);
- if (Sockaddr_getPort(addr) == 0) {
- Sockaddr_setPort(addr, ++fnp->lastPort);
- // Check for wrapping.
- Assert_true(fnp->lastPort != 0);
- Assert_true(addrLen == 4);
- Bits_memcpy(addrBytes, ((uint8_t[]){127, 0, 0, 1}), 4);
- } else if (addrLen == 4 && !Bits_memcmp(addrBytes, "\0\0\0\0", 4)) {
- Assert_failure("Address 0 with port specified is not allowed");
- }
- if (Map_OfIfaces_indexForKey(&addr, &fnp->map) != -1) {
- return NULL;
- }
- struct FakeNetwork_UDPIface_pvt* fnip =
- Allocator_calloc(alloc, sizeof(struct FakeNetwork_UDPIface_pvt), 1);
- Map_OfIfaces_put(&addr, &fnip, &fnp->map);
- fnip->fnp = fnp;
- fnip->pub.generic.alloc = alloc;
- fnip->pub.generic.addr = addr;
- fnip->pub.generic.iface.send = incoming;
- Identity_set(fnip);
- return &fnip->pub;
- }
- struct FakeNetwork* FakeNetwork_new(struct EventBase* base,
- struct Allocator* allocator,
- struct Log* logger)
- {
- struct Allocator* alloc = Allocator_child(allocator);
- struct FakeNetwork_pvt* fnp = Allocator_calloc(alloc, sizeof(struct FakeNetwork_pvt), 1);
- fnp->alloc = alloc;
- fnp->log = logger;
- fnp->base = base;
- fnp->map.allocator = alloc;
- fnp->async = ASynchronizer_new(alloc, base, logger);
- fnp->fromAsync.send = fromAsync;
- Iface_plumb(&fnp->fromAsync, &fnp->async->ifB);
- Iface_plumb(&fnp->toAsync, &fnp->async->ifA);
- Identity_set(fnp);
- return &fnp->pub;
- }
|