socket fs: support non-blocking 'connect()'

Fixes #3113
This commit is contained in:
Christian Prochaska
2019-01-11 14:56:07 +01:00
committed by Norman Feske
parent 12c10dbcd1
commit e8ea28d897
3 changed files with 210 additions and 34 deletions

View File

@ -635,7 +635,24 @@ class Vfs::Lxip_connect_file : public Vfs::Lxip_file
** File interface **
********************/
bool poll(bool, Vfs::Vfs_handle::Context *) { return true; }
bool poll(bool trigger_io_response, Vfs::Vfs_handle::Context *context)
{
/*
* The connect file is considered readable when the socket is
* writeable (connected or error).
*/
using namespace Linux;
file f;
f.f_flags = 0;
if (_sock.ops->poll(&f, &_sock, nullptr) & (POLLOUT_SET)) {
if (trigger_io_response)
_parent.trigger_io_response(context);
return true;
}
return false;
}
Lxip::ssize_t write(Lxip_vfs_file_handle &handle,
char const *src, Genode::size_t len,
@ -657,12 +674,12 @@ class Vfs::Lxip_connect_file : public Vfs::Lxip_file
addr->sin_addr.s_addr = get_addr(handle.content_buffer);
addr->sin_family = AF_INET;
_write_err = _sock.ops->connect(&_sock, (sockaddr *)addr, sizeof(addr_storage), 0);
_write_err = _sock.ops->connect(&_sock, (sockaddr *)addr, sizeof(addr_storage), O_NONBLOCK);
switch (_write_err) {
case Lxip::Io_result::LINUX_EINPROGRESS:
_connecting = true;
return -1;
return len;
case Lxip::Io_result::LINUX_EALREADY:
return -1;
@ -679,6 +696,7 @@ class Vfs::Lxip_connect_file : public Vfs::Lxip_file
default:
if (_write_err != 0) return -1;
_is_connected = true;
break;
}
@ -691,6 +709,29 @@ class Vfs::Lxip_connect_file : public Vfs::Lxip_file
return len;
}
Lxip::ssize_t read(Lxip_vfs_file_handle &handle,
char *dst, Genode::size_t len,
file_size /* ignored */) override
{
int so_error = 0;
int opt_len = sizeof(so_error);
int res = sock_getsockopt(&_sock, SOL_SOCKET, SO_ERROR, (char*)&so_error, &opt_len);
if (res != 0) {
Genode::error("Vfs::Lxip_connect_file::read(): getsockopt() failed");
return -1;
}
switch (so_error) {
case 0:
return Genode::snprintf(dst, len, "connected");
case Linux::ECONNREFUSED:
return Genode::snprintf(dst, len, "connection refused");
default:
return Genode::snprintf(dst, len, "unknown error");
}
}
};