-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor Sockets API #5778
Comments
May be related: #4317 (comment) |
@bew yeah, this assumes UNIX sockets are only used as streams. Anything else doesn't make sense. |
Additionally, I would suggest that all sockets and servers can be created using appropriate Maybe these could also be renamed to
|
I can hear the conceptual requirement that Honestly, introducing many namespaces only introduces complicity for it's own sake and doesn't solve anything. For example Last but not least, the |
Listing problems is fine, but detailing what's accessible to each level (general / TCP / UDP and UNIX sockets and servers) would be even better, especially since the underlying system implementation just mixes everything —so Socket should be capable to intermix everything, even being an IO, because of advanced usages, such as Bluetooth or RAW sockets. That would really help to map what should be accessible, what shouldn't, and so on, and decide whether such a refactor makes sense, or if it will inexorably lead to a horrible implementation (because system sockets are an horrible blob). |
Right now working on Bluetooth socket , its a hacky ride because of current implementation. |
The only solution to avoid convoluted APIs is to separate the low-level API currently provided by Implementationwise, this could be achieved by wrapping the low-level API in the higher-level classes, though that would not be particularly great. Another approach could be non-public modules that provide the required functionality. But I guess that's gonna cause some issues, just thinking about API docs. Alternatively, we could have a very basic, internal API similar to the APIs in the I'll try to sketch the basics of each type, leaving out any detailed configuration settings to get a more clear overview: (we could probably have a module abstract class Socket::IO < IO::Syscall
getter file_descriptor : Int32
def self.open(*args, **kwargs, &block : self ->) # individual implementations in subclasses
end
class Socket::TCP < Socket::IO
getter local_address : Socket::Address::IP
getter remote_address : Socket::Address::IP
def self.new(address : IPAddress, local_address : IPAddress = nil)
def self.new(host : String, port : Int32)
end
class Socket::UNIX < Socket::IO
getter remote_address : Socket::Address::UNIX?
def self.pair : {self, self}
end
class Socket::UDP
property? broadcast : Bool
getter remote_address : Socket::Address:IP?
getter local_address : Socket::Address:IP?
def self.new
def self.new(address : IPAddress)
def file_descriptor : Int32
def connect(address : IPAddress)
def connect(host : String, port : Int32)
def connected?
def disconnect
def bind(address : Socket::Address::IP)
def bound? : Bool
def close
def send(message, address : Socket::Address::IP? = nil)
def receive(message : Bytes), {Int32, Socket::Address::IP}
end And the servers: abstract class Socket::Server
getter local_address : Socket::Address
def accept(&block : Socket::IO ->)
def accept?(&block : Socket::IO ->)
def accept? : Socket::IO?
def close
end
class Socket::Server::TCP < Socket::Server
getter file_descriptor : Int32
getter local_address : Socket::Address:IP
def self.new(address : Socket::Address::IP, backlog = nil, reuse_port = false)
def self.new(host : String, port : Int32, backlog = nil, reuse_port = false)
def self.new(port : Int32, backlog = nil, reuse_port = false)
end
class Socket::Server::UNIX < Socket::Server
getter file_descriptor : Int32
getter local_address : Socket::Address:UNIX
def self.new(address : Socket::Address::UNIX, backlog = nil)
def self.new(path : String, backlog= nil)
def close(delete = true)
end |
Why not just do this? Have a big low-level |
See #4277 (issue-comment) for the initial idea.
There are quite a few errors in the API design related to sockets:
TCPServer
inherits fromTCPSocket
which is conceptually true, butTCPSocket
is aSocket
which inherits fromIO
- yet a server cannot be used as an IO. The same is true forUNIXServer
.UDPSocket
also inherits fromSocket
andIO
, yet cannot be used as anIO
either since UDP communication does not work as a stream.IPSocket
as parent ofUDPSocket
andTCPSocket
defines accessorslocal_address
andremote_address
, yetTCPServer
does not have single remote address. Neither does aUDPSocket
in listening mode.While it's not such a big issue, I would also suggest to put all these types in the
Socket
namespace. These socket types are the only non-basic types in the global name space. And large parts of the API are already in theSocket
namespace.TCPSocket
->Socket::TCP
,TCPServer
->Socket::Server::TCP
(orSocket::TCPServer
) etc. I will use namespaced types from now on but that should not influence the logical considerations.TCP
andUNIX
sockets should be anIO
because they are essentially streaming interfaces. The basicSocket
however should not be anIO
becauseSocket::UDP
cannot be used as an IO. This would call for an intermediary classSocket::IO
as parent forSocket::TCP
andSocket::UNIX
which inherits fromIO
.Socket
Socket::UDP
Socket::IO < IO
Socket::TCP
Socket::UNIX
I'm not entirely sure about
Socket
as a base type. It needs to be a module becauseIO
is a class, but I don't know if it has any useful functionality common to streaming and non-streaming sockets. It's main purpose is to give access to lower level socket functions.I'm also not sure we need
IPSocket
at all, it adds very little.The server sockets can't inherit from
Socket::TCP
andSocket::UNIX
so they're don't need to be related. It could be considered having a module which can be included by both, but I don't think there is much commonality, at least not for the public API.Socket::Server
Socket::Server::TCP
Socket::Server::UNIX
The text was updated successfully, but these errors were encountered: