Beispiel #1
0
Packet* socket_removeFromInputBuffer(Socket* socket) {
    MAGIC_ASSERT(socket);

    /* see if we have any packets */
    Packet* packet = g_queue_pop_head(socket->inputBuffer);
    if(packet) {
        /* just removed a packet */
        guint length = packet_getPayloadLength(packet);
        socket->inputBufferLength -= length;

        /* check if we need to reduce the buffer size */
        if(socket->inputBufferSizePending > 0) {
            socket_setInputBufferSize(socket, socket->inputBufferSizePending);
        }

        /* update the tracker input buffer stats */
        Tracker* tracker = host_getTracker(worker_getCurrentHost());
        Descriptor* descriptor = (Descriptor *)socket;
        tracker_updateSocketInputBuffer(tracker, descriptor->handle, socket->inputBufferLength, socket->inputBufferSize);

        /* we are not readable if we are now empty */
        if(socket->inputBufferLength <= 0) {
            descriptor_adjustStatus((Descriptor*)socket, DS_READABLE, FALSE);
        }
    }

    return packet;
}
Beispiel #2
0
gint system_setSockOpt(gint fd, gint level, gint optname, const gpointer optval,
		socklen_t optlen) {
	if(!optval) {
		errno = EFAULT;
		return -1;
	}

	Host* node = _system_switchInShadowContext();
	Descriptor* descriptor = host_lookupDescriptor(node, fd);

	gint result = 0;

	/* TODO: implement socket options */
	if(descriptor) {
		if(level == SOL_SOCKET) {
			DescriptorType t = descriptor_getType(descriptor);
			switch (optname) {
				case SO_SNDBUF: {
					if(optlen < sizeof(gint)) {
						warning("called setsockopt with SO_SNDBUF with optlen < %i", (gint)(sizeof(gint)));
						errno = EINVAL;
						result = -1;
					} else if (t != DT_TCPSOCKET && t != DT_UDPSOCKET) {
						warning("called setsockopt with SO_SNDBUF on non-socket");
						errno = ENOPROTOOPT;
						result = -1;
					} else {
						gint v = *((gint*) optval);
						socket_setOutputBufferSize((Socket*)descriptor, (gsize)v*2);
					}
					break;
				}

				case SO_RCVBUF: {
					if(optlen < sizeof(gint)) {
						warning("called setsockopt with SO_RCVBUF with optlen < %i", (gint)(sizeof(gint)));
						errno = EINVAL;
						result = -1;
					} else if (t != DT_TCPSOCKET && t != DT_UDPSOCKET) {
						warning("called setsockopt with SO_RCVBUF on non-socket");
						errno = ENOPROTOOPT;
						result = -1;
					} else {
						gint v = *((gint*) optval);
						socket_setInputBufferSize((Socket*)descriptor, (gsize)v*2);
					}
					break;
				}

				case SO_REUSEADDR: {
					// TODO implement this!
					// XXX Tor actually uses this option!!
					debug("setsockopt SO_REUSEADDR not yet implemented");
					break;
				}

				default: {
					warning("setsockopt optname %i not implemented", optname);
					errno = ENOSYS;
					result = -1;
					break;
				}
			}
		} else {
			warning("setsockopt level %i not implemented", level);
			errno = ENOSYS;
			result = -1;
		}
	} else {
		errno = EBADF;
		result = -1;
	}

	_system_switchOutShadowContext(node);
	return result;
}