Packet* socket_removeFromOutputBuffer(Socket* socket) { MAGIC_ASSERT(socket); /* see if we have any packets */ Packet* packet = g_queue_pop_head(socket->outputBuffer); if(packet) { /* just removed a packet */ guint length = packet_getPayloadLength(packet); socket->outputBufferLength -= length; /* check if we need to reduce the buffer size */ if(socket->outputBufferSizePending > 0) { socket_setOutputBufferSize(socket, socket->outputBufferSizePending); } /* update the tracker input buffer stats */ Tracker* tracker = host_getTracker(worker_getCurrentHost()); Descriptor* descriptor = (Descriptor *)socket; tracker_updateSocketOutputBuffer(tracker, descriptor->handle, socket->outputBufferLength, socket->outputBufferSize); /* we are writable if we now have space */ if(socket_getOutputBufferSpace(socket) > 0) { descriptor_adjustStatus((Descriptor*)socket, DS_WRITABLE, TRUE); } } return packet; }
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; }