Beispiel #1
0
/*
 * this function builds a UDP packet and sends to the virtual node given by the
 * ip and port parameters. this function assumes that the socket is already
 * bound to a local port, no matter if that happened explicitly or implicitly.
 */
gssize udp_sendUserData(UDP* udp, gconstpointer buffer, gsize nBytes, in_addr_t ip, in_port_t port) {
	MAGIC_ASSERT(udp);

	gsize space = socket_getOutputBufferSpace(&(udp->super));
	if(space < nBytes) {
		/* not enough space to buffer the data */
		return -1;
	}

	/* break data into segments and send each in a packet */
	gsize maxPacketLength = CONFIG_DATAGRAM_MAX_SIZE;
	gsize remaining = nBytes;
	gsize offset = 0;

	/* create as many packets as needed */
	while(remaining > 0) {
		gsize copyLength = MIN(maxPacketLength, remaining);

		/* use default destination if none was specified */
		in_addr_t destinationIP = (ip != 0) ? ip : udp->super.peerIP;
		in_port_t destinationPort = (port != 0) ? port : udp->super.peerPort;

		/* create the UDP packet */
		Packet* packet = packet_new(buffer + offset, copyLength);
		packet_setUDP(packet, PUDP_NONE, socket_getBinding(&(udp->super)),
				udp->super.boundPort, destinationIP, destinationPort);

		/* buffer it in the transport layer, to be sent out when possible */
		gboolean success = socket_addToOutputBuffer((Socket*) udp, packet);

		/* counter maintenance */
		if(success) {
			remaining -= copyLength;
			offset += copyLength;
		} else {
			warning("unable to send UDP packet");
			break;
		}
	}

	/* update the tracker output buffer stats */
	Tracker* tracker = node_getTracker(worker_getPrivate()->cached_node);
	Socket* socket = (Socket* )udp;
	Descriptor* descriptor = (Descriptor *)socket;
	gsize outLength = socket_getOutputBufferLength(socket);
	gsize outSize = socket_getOutputBufferSize(socket);
	tracker_updateSocketOutputBuffer(tracker, descriptor->handle, outLength, outSize);

	debug("buffered %"G_GSIZE_FORMAT" outbound UDP bytes from user", offset);

	return (gssize) offset;
}
Beispiel #2
0
gssize udp_receiveUserData(UDP* udp, gpointer buffer, gsize nBytes, in_addr_t* ip, in_port_t* port) {
	MAGIC_ASSERT(udp);

	Packet* packet = socket_removeFromInputBuffer((Socket*)udp);
	if(!packet) {
		return -1;
	}

	/* copy lesser of requested and available amount to application buffer */
	guint packetLength = packet_getPayloadLength(packet);
	gsize copyLength = MIN(nBytes, packetLength);
	guint bytesCopied = packet_copyPayload(packet, 0, buffer, copyLength);

	utility_assert(bytesCopied == copyLength);
	packet_addDeliveryStatus(packet, PDS_RCV_SOCKET_DELIVERED);

	/* fill in address info */
	if(ip) {
		*ip = packet_getSourceIP(packet);
	}
	if(port) {
		*port = packet_getSourcePort(packet);
	}

	/* destroy packet, throwing away any bytes not claimed by the app */
	packet_unref(packet);

	/* update the tracker output buffer stats */
	Tracker* tracker = host_getTracker(worker_getCurrentHost());
	Socket* socket = (Socket* )udp;
	Descriptor* descriptor = (Descriptor *)socket;
	gsize outLength = socket_getOutputBufferLength(socket);
	gsize outSize = socket_getOutputBufferSize(socket);
	tracker_updateSocketOutputBuffer(tracker, descriptor->handle, outLength, outSize);

	debug("user read %u inbound UDP bytes", bytesCopied);

	return (gssize)bytesCopied;
}
Beispiel #3
0
	gint result = 0;

	/* normally, the type of farg depends on the request */
	Host* node = _system_switchInShadowContext();
	Descriptor* descriptor = host_lookupDescriptor(node, fd);

	if(descriptor) {
		DescriptorType t = descriptor_getType(descriptor);
		if(t == DT_TCPSOCKET || t == DT_UDPSOCKET) {
			Socket* socket = (Socket*) descriptor;
			if(request == SIOCINQ || request == FIONREAD) {
				gsize bufferLength = socket_getInputBufferLength(socket);
				gint* lengthOut = va_arg(farg, int*);
				*lengthOut = (gint)bufferLength;
			} else if (request == SIOCOUTQ || request == TIOCOUTQ) {
				gsize bufferLength = socket_getOutputBufferLength(socket);
				gint* lengthOut = va_arg(farg, int*);
				*lengthOut = (gint)bufferLength;
			} else {
				result = ENOTTY;
			}
		} else {
			result = ENOTTY;
		}
	} else {
		result = EBADF;
	}

	_system_switchOutShadowContext(node);
	return result;
}
Beispiel #4
0
/*
 * this function builds a UDP packet and sends to the virtual node given by the
 * ip and port parameters. this function assumes that the socket is already
 * bound to a local port, no matter if that happened explicitly or implicitly.
 */
gssize udp_sendUserData(UDP* udp, gconstpointer buffer, gsize nBytes, in_addr_t ip, in_port_t port) {
	MAGIC_ASSERT(udp);

	gsize space = socket_getOutputBufferSpace(&(udp->super));
	if(space < nBytes) {
		/* not enough space to buffer the data */
		return -1;
	}

	/* break data into segments and send each in a packet */
	gsize maxPacketLength = CONFIG_DATAGRAM_MAX_SIZE;
	gsize remaining = nBytes;
	gsize offset = 0;

	/* create as many packets as needed */
	while(remaining > 0) {
		gsize copyLength = MIN(maxPacketLength, remaining);

		/* use default destination if none was specified */
		in_addr_t destinationIP = (ip != 0) ? ip : udp->super.peerIP;
		in_port_t destinationPort = (port != 0) ? port : udp->super.peerPort;

		in_addr_t sourceIP = 0;
		in_port_t sourcePort = 0;
		socket_getSocketName(&(udp->super), &sourceIP, &sourcePort);

		if(sourceIP == htonl(INADDR_ANY)) {
			/* source interface depends on destination */
			if(destinationIP == htonl(INADDR_LOOPBACK)) {
				sourceIP = htonl(INADDR_LOOPBACK);
			} else {
				sourceIP = host_getDefaultIP(worker_getCurrentHost());
			}
		}

		utility_assert(sourceIP && sourcePort && destinationIP && destinationPort);

		/* create the UDP packet */
		Packet* packet = packet_new(buffer + offset, copyLength);
		packet_setUDP(packet, PUDP_NONE, sourceIP, sourcePort, destinationIP, destinationPort);
		packet_addDeliveryStatus(packet, PDS_SND_CREATED);

		/* buffer it in the transport layer, to be sent out when possible */
		gboolean success = socket_addToOutputBuffer((Socket*) udp, packet);

		/* counter maintenance */
		if(success) {
			remaining -= copyLength;
			offset += copyLength;
		} else {
			warning("unable to send UDP packet");
			break;
		}
	}

	/* update the tracker output buffer stats */
	Tracker* tracker = host_getTracker(worker_getCurrentHost());
	Socket* socket = (Socket* )udp;
	Descriptor* descriptor = (Descriptor *)socket;
	gsize outLength = socket_getOutputBufferLength(socket);
	gsize outSize = socket_getOutputBufferSize(socket);
	tracker_updateSocketOutputBuffer(tracker, descriptor->handle, outLength, outSize);

	debug("buffered %"G_GSIZE_FORMAT" outbound UDP bytes from user", offset);

	return (gssize) offset;
}