Age | Commit message (Collapse) | Author |
|
After a socket has disconnected, we shouldn't return -EAGAIN. Instead
we should allow userspace to read/recvfrom the socket until its packet
queue has been exhausted.
At that point, we now return 0, signalling EOF.
It might be even better to start returning -ENOTCONN after signalling
EOF once. I'm not sure how that should work, needs looking into.
|
|
The can_read() and can_write() states for file descriptions are now
published in /proc, allowing SystemMonitor to display it.
|
|
Asking a File if we could possibly read or write it will never mutate
the asking FileDescription&, so it should be const.
|
|
...if there are no packets in the receive queue.
|
|
Also remove an unused Socket::listen() implementation.
|
|
This reverts commit 1cca5142afbd76833deedfdb238230ac53424855.
This appears to be causing intermittent triple-faults and I don't know
why yet, so I'll just revert it to keep the tree in decent shape.
|
|
Background: DoubleBuffer is a handy buffer class in the kernel that
allows you to keep writing to it from the "outside" while the "inside"
reads from it. It's used for things like LocalSocket and PTY's.
Internally, it has a read buffer and a write buffer, but the two will
swap places when the read buffer is exhausted (by reading from it.)
Before this patch, it was internally implemented as two Vector<u8>
that we would swap between when the reader side had exhausted the data
in the read buffer. Now instead we preallocate a large KBuffer (64KB*2)
on DoubleBuffer construction and use that throughout its lifetime.
This removes all the kmalloc heap traffic caused by DoubleBuffers :^)
|
|
|
|
Make sure we don't move accepted sockets to the Completed setup state
until we've actually constructed a FileDescription for them.
This is important, since this state transition will trigger connect()
to unblock on the client side, and the client may try writing to the
socket right away.
This makes DNS lookups way more reliable since we don't just fail to
write() right after connect()ing to LookupServer sometimes. :^)
|
|
This was causing connect() to unblock immediately for local sockets,
since that's exactly what ConnectBlocker checks for.
Instead, just move to SetupState::Completed when it's accept()ed.
|
|
|
|
We had two ways to get the data inside a ByteBuffer. That was silly.
|
|
This allows userspace programs to get and set (superuser-only) the IPv4
address of a network adapter. :^)
|
|
If we can't already read when we enter recvfrom() on a LocalSocket,
we'll now block the current thread until we can.
Also added a buffer_for(FileDescription&) helper so that the client
and server can share some of the code. :^)
|
|
Made getsockopt() and setsockopt() virtual so we can handle them in the
various Socket subclasses. The subclasses map kinda nicely to "levels".
This will allow us to implement things like "traceroute", although..
I spent some time trying to do that, but then hit a wall when it turned
out that the user-mode networking in QEMU doesn't preserve TTL in the
ICMP packets passing through.
|
|
|
|
This was getting fixed up by the loop that chooses the next TX buffer
anyway, but let's do this correctly.
Fixes #522.
|
|
|
|
|
|
|
|
|
|
This is to work around our lack of a shutdown() implementation.
|
|
This approach is a bit naiive - whenever we send a packet out, we
check to see if there are any other packets we should try to send.
This works well enough for a busy connection but not very well for a
quiet one. Ideally we would check for not-acked packets on some kind
of timer, and use the length of this not-acked list as feedback to
throttle the writes coming from userspace.
|
|
This allows us to take advantage of unsolicited ARP replies, such as
those that are emitted by many systems after their network interfaces
are enabled, or after their DHCP client sets their IP.
This also makes us a bit more vulnerable to ARP flooding, but we need
some kind of eviction strategy anyway, so we can deal with that later.
|
|
An incoming socket should only be considered connected after a
program has received it from accept(). Before that point, it's only
"half" open, and it might not ever actually be served to a program.
Socket::accept is where m_connected is correctly set.
|
|
|
|
Using a SocketHandle takes a lock on the socket, which we don't want
to do.
|
|
|
|
|
|
|
|
|
|
This was a workaround to be able to build on case-insensitive file
systems where it might get confused about <string.h> vs <String.h>.
Let's just not support building that way, so String.h can have an
objectively nicer name. :^)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This replaces the previous placeholder routing layer with a real one!
It's still very primitive, doesn't deal with things like timeouts very
well, and will probably need several more iterations to support more
normal networking things.
I haven't confirmed that this works with anything other than the QEMU
user networking layer, but I suspect that's what nearly everybody is
using at this point, so that's the important target to keep working.
|
|
This is configured in NetworkTask_main now, so there's no need to do it
here as well.
|
|
|
|
By setting up the devices in init() and looping over the registered
network adapters in NetworkTask_main, we can remove the remaining
hard-coded adapter references from the network code.
This also assigns IPs according to the default range supplied by QEMU
in its slirp networking mode.
|
|
|
|
|
|
|
|
|
|
|
|
|