Exemplo n.º 1
0
void worker_schedulePacket(Packet* packet) {
    /* get our thread-private worker */
    Worker* worker = _worker_getPrivate();
    if(slave_isKilled(worker->slave)) {
        /* the simulation is over, don't bother */
        return;
    }

    in_addr_t srcIP = packet_getSourceIP(packet);
    in_addr_t dstIP = packet_getDestinationIP(packet);

    Address* srcAddress = dns_resolveIPToAddress(worker_getDNS(), (guint32) srcIP);
    Address* dstAddress = dns_resolveIPToAddress(worker_getDNS(), (guint32) dstIP);

    if(!srcAddress || !dstAddress) {
        error("unable to schedule packet because of null addresses");
        return;
    }

    /* check if network reliability forces us to 'drop' the packet */
    gdouble reliability = topology_getReliability(worker_getTopology(), srcAddress, dstAddress);
    Random* random = host_getRandom(worker_getCurrentHost());
    gdouble chance = random_nextDouble(random);

    /* don't drop control packets with length 0, otherwise congestion
     * control has problems responding to packet loss */
    if(chance <= reliability || packet_getPayloadLength(packet) == 0) {
        /* the sender's packet will make it through, find latency */
        gdouble latency = topology_getLatency(worker_getTopology(), srcAddress, dstAddress);
        SimulationTime delay = (SimulationTime) ceil(latency * SIMTIME_ONE_MILLISECOND);

        PacketArrivedEvent* event = packetarrived_new(packet);
        worker_scheduleEvent((Event*)event, delay, (GQuark)address_getID(dstAddress));

        packet_addDeliveryStatus(packet, PDS_INET_SENT);
    } else {
        packet_addDeliveryStatus(packet, PDS_INET_DROPPED);
    }
}
Exemplo n.º 2
0
gint host_connectToPeer(Host* host, gint handle, const struct sockaddr* address) {
	MAGIC_ASSERT(host);

	sa_family_t family = 0;
	in_addr_t peerIP = 0;
	in_port_t peerPort = 0;

    if(address->sa_family == AF_INET) {
        struct sockaddr_in* saddr = (struct sockaddr_in*) address;

        family = saddr->sin_family;
        peerIP = saddr->sin_addr.s_addr;
        peerPort = saddr->sin_port;

    } else if (address->sa_family == AF_UNIX) {
        struct sockaddr_un* saddr = (struct sockaddr_un*) address;

        family = saddr->sun_family;
        gchar* sockpath = saddr->sun_path;

        peerIP = htonl(INADDR_LOOPBACK);
        gpointer val = g_hash_table_lookup(host->unixPathToPortMap, sockpath);
        if(val) {
            peerPort = (in_port_t)GPOINTER_TO_UINT(val);
        }
    }

	in_addr_t loIP = htonl(INADDR_LOOPBACK);

	/* make sure we will be able to route this later */
	if(peerIP != loIP) {
		Address* myAddress = networkinterface_getAddress(host->defaultInterface);
		Address* peerAddress = dns_resolveIPToAddress(worker_getDNS(), peerIP);
		if(!peerAddress || !topology_isRoutable(worker_getTopology(), myAddress, peerAddress)) {
			/* can't route it - there is no node with this address */
			gchar* peerAddressString = address_ipToNewString(peerIP);
			warning("attempting to connect to address '%s:%u' for which no host exists", peerAddressString, ntohs(peerPort));
			g_free(peerAddressString);
			return ECONNREFUSED;
		}
	}

	Descriptor* descriptor = host_lookupDescriptor(host, handle);
	if(descriptor == NULL) {
		warning("descriptor handle '%i' not found", handle);
		return EBADF;
	}

	DescriptorStatus status = descriptor_getStatus(descriptor);
	if(status & DS_CLOSED) {
		warning("descriptor handle '%i' not a valid open descriptor", handle);
		return EBADF;
	}

	DescriptorType type = descriptor_getType(descriptor);
	if(type != DT_TCPSOCKET && type != DT_UDPSOCKET) {
		warning("wrong type for descriptor handle '%i'", handle);
		return ENOTSOCK;
	}

	Socket* socket = (Socket*) descriptor;

	if(!socket_isFamilySupported(socket, family)) {
		return EAFNOSUPPORT;
	}

	if(type == DT_TCPSOCKET) {
		gint error = tcp_getConnectError((TCP*)socket);
		if(error) {
			return error;
		}
	}

	if (address->sa_family == AF_UNIX) {
        struct sockaddr_un* saddr = (struct sockaddr_un*) address;
        socket_setUnixPath(socket, saddr->sun_path, FALSE);
    }

	if(!socket_isBound(socket)) {
		/* do an implicit bind to a random port.
		 * use default interface unless the remote peer is on loopback */
		in_addr_t defaultIP = networkinterface_getIPAddress(host->defaultInterface);

		in_addr_t bindAddress = loIP == peerIP ? loIP : defaultIP;
		in_port_t bindPort = _host_getRandomFreePort(host, bindAddress, type);
        if(!bindPort) {
            return EADDRNOTAVAIL;
        }

		_host_associateInterface(host, socket, bindAddress, bindPort);
	}

	return socket_connectToPeer(socket, peerIP, peerPort, family);
}