Skip to content
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

net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections, already supported by the V network stack #21657

Merged
merged 5 commits into from
Aug 5, 2024

Conversation

dasidiot
Copy link
Contributor

@dasidiot dasidiot commented Jun 9, 2024

From my thread on Discord:

Hey there,

I've recently taken an interest in vlang and I've been looking through the vlib net implementations. I'm curious if you all would be open to some patches that move away from directly referencing net.TCPConn or ssl.SSLConn structures and instead work with interfaces (similar to golang). For instance, I think the introduction of a net.IDialer interface as well as a net.IConn interface could go a long way to making vlangs net stack extendable, and reduce the amount of code required.

Taking the socks5.v (https://github.com/vlang/v/blob/master/vlib/net/socks/socks5.v) implementation as an example, today there are multiple entry points - one for TCP, one for SSL, which are required because its tightly bound to the concrete structures from TCP/SSL. There are a number of problems with this if you look at the code. For instance, what if I want to customize the options passed to the SSL connection? I'm stuck either going away from vlib or adding additional arguments to the function (which complicates usage and is a headache for existing code bases). Similarly, what if I wanted to add a SOCKS5 proxy through a UNIX domain socket? This would be a third entry point in the current code style.

Now imagine we had an net.IDialer interface which took an address as a string and left it up to the implementation to determine how to make that connection. As the coder I could pass in an implementation of IDialer for TCP (net.tcp_default_dialer), SSL (ssl.default_dialer), UNIX (unix.default_dialer) or even write my own implementation of some other network stack. Now as a developer I have a lot more control. I can setup my own SSL dialer implementation that returns SSL connections with whatever settings I want to configure. I could even implement a dialer on top of an HTTP Proxy to tunnel my SOCKS through HTTP first.

If this is something the developers would be willing to consider patches for, I'd be willing to try and put some together.

The idea here is to create new interfaces around network connections and then migrate the protocol implementations to work around these interfaces. This is one of the parts of Golang that makes it so flexible. This PR demonstrates a potential interface for dialing new network connections and another potential interface for implementing protocols on top of those connections.

If the feedback here is favorable I will tackle a larger protocol (HTTP).

Note
I don't love the I____ style interface names but I'm trying to propose this in a way that is backwards compatible to existing code written against vlib. If breaking the contract is an option then we can have better names and likely simplify many of the written protocols.

@spytheman spytheman added the Unit: vlib Bugs/feature requests, that are related to the vlib. label Jun 24, 2024
@spytheman spytheman closed this Jun 24, 2024
@spytheman spytheman reopened this Jun 24, 2024
@spytheman spytheman force-pushed the dasidiot/net_interfaces_proposal branch from 0c861ac to c203a72 Compare August 4, 2024 09:38
@spytheman
Copy link
Member

(rebased over current master)

@spytheman
Copy link
Member

I don't love the I____ style interface names but I'm trying to propose this in a way that is backwards compatible to existing code written against vlib. If breaking the contract is an option then we can have better names and likely simplify many of the written protocols.

What do you think of IDialer -> Dialer and IConn -> Connection ?

@JalonSolov
Copy link
Contributor

Yeah, IDialer and IConn is Hungarian notation. I'd prefer Dialer and Connection. Or just be explicit... DialerInterface and ConnectionInterface.

Hungarian notation was them wanting to let you know the type as part of the name, but just being lazy and not wanting to type the whole thing out. :-\

@spytheman
Copy link
Member

I ran: git grep 'interface .* {' |grep -v /tests/|grep -v is_interface|grep -v _test.v: | grep -v js.v: |grep -v '.h:'| grep -v '.m:'| grep -v 'if '|grep -v 'fn '|grep Interface | nl
which returned 6 matches in the main V repo:

     1	vlib/veb/controller.v:15:interface ControllerInterface {
     2	vlib/vweb/vweb.v:441:interface DbPoolInterface {
     3	vlib/vweb/vweb.v:447:interface DbInterface {
     4	vlib/vweb/vweb.v:454:interface MiddlewareInterface {
     5	vlib/vweb/vweb.v:488:interface ControllerInterface {
     6	vlib/x/vweb/controller.v:15:interface ControllerInterface {

For comparison,
git grep 'interface .* {' |grep -v /tests/|grep -v is_interface|grep -v _test.v: | grep -v js.v: |grep -v '.h:'| grep -v '.m:'| grep -v 'if '|grep -v 'fn '|grep -v Interface | nl
returned 69 matches in the main V repo.

     1	cmd/tools/modules/testing/output.v:31:pub interface Reporter {
     2	cmd/tools/vast/test/demo.v:56:interface Myinterfacer {
     3	cmd/tools/vast/test/demo.v:122:interface Gettable[T] {
     4	cmd/tools/vwhere/test/file_two.v:17:interface Drinker {
     5	doc/docs.md:3555:interface Speaker {
     6	doc/docs.md:3586:interface Foo {
     7	doc/docs.md:3593:interface Bar {
     8	doc/docs.md:3631:interface Something {}
     9	doc/docs.md:3653:interface IFoo {
    10	doc/docs.md:3657:interface IBar {
    11	doc/docs.md:3709:interface Adoptable {}
    12	doc/docs.md:3749:pub interface Reader {
    13	doc/docs.md:3754:pub interface Writer {
    14	doc/docs.md:3763:pub interface ReaderWriter {
    15	vlib/builtin/js/builtin.v:16:pub interface IError {
    16	vlib/builtin/result.v:7:pub interface IError {
    17	vlib/context/cancel.v:13:pub interface Canceler {
    18	vlib/context/context.v:22:pub interface Any {}
    19	vlib/context/context.v:63:pub interface Context {
    20	vlib/crypto/cipher/cipher.v:9:pub interface Block {
    21	vlib/crypto/cipher/cipher.v:18:pub interface Stream {
    22	vlib/crypto/cipher/cipher.v:35:pub interface BlockMode {
    23	vlib/hash/hash.v:6:pub interface Hash {
    24	vlib/hash/hash.v:14:interface Hash32er {
    25	vlib/hash/hash.v:18:interface Hash64er {
    26	vlib/io/reader.v:23:pub interface Reader {
    27	vlib/io/reader.v:83:pub interface RandomReader {
    28	vlib/io/readerwriter.v:4:pub interface ReaderWriter {
    29	vlib/io/writer.v:5:pub interface Writer {
    30	vlib/io/writer.v:12:pub interface RandomWriter {
    31	vlib/log/logger_interface.v:4:pub interface Logger {
    32	vlib/net/http/download_progress.v:6:pub interface Downloader {
    33	vlib/net/http/server.v:21:pub interface Handler {
    34	vlib/orm/orm.v:195:pub interface Connection {
    35	vlib/os/notify/notify.v:6:pub interface FdNotifier {
    36	vlib/os/notify/notify.v:15:pub interface FdEvent {
    37	vlib/rand/rand.v:16:pub interface PRNG {
    38	vlib/toml/ast/walker/walker.v:6:pub interface Visitor {
    39	vlib/toml/ast/walker/walker.v:11:pub interface Modifier {
    40	vlib/v/ast/walker/walker.v:6:pub interface Visitor {
    41	vlib/v/comptime/comptimeinfo.v:9:pub interface IResolverType {
    42	vlib/v/embed_file/decoder.v:4:pub interface Decoder {
    43	vlib/v/gen/c/testdata/array_as_interface.vv:1:interface Source {
    44	vlib/v/gen/c/testdata/comptime_interface_field.vv:1:interface User {
    45	vlib/v/gen/native/gen.v:79:interface CodeGen {
    46	vlib/v/preludes/test_runner.c.v:13:interface TestRunner {
    47	vlib/v/slow_tests/inout/closure_with_nested_closure_var.vv:3:interface Test {
    48	vlib/v/slow_tests/inout/comptime_selector_of_interface.vv:5:interface IPeople {
    49	vlib/v/slow_tests/inout/dump_generic_interface_ref_arg.vv:1:interface In {
    50	vlib/v/slow_tests/inout/dump_generic_interface_ref_arg.vv:5:interface Out {
    51	vlib/v/slow_tests/inout/dump_generic_interface_ref_arg.vv:9:interface InOut {
    52	vlib/v/slow_tests/inout/dump_nested_generic_fn_call_ref_arg.vv:1:interface Average {
    53	vlib/v/slow_tests/inout/interface_field_initialised_struct_update_expr.vv:1:interface Foo {
    54	vlib/v/slow_tests/inout/printing_for_v_in_a.vv:1:interface Any {}
    55	vlib/v/slow_tests/repl/interface.repl:2:interface Foo {
    56	vlib/v/slow_tests/valgrind/nil_interface.v:1:interface Resource {}
    57	vlib/veb/middleware.v:10:interface MiddlewareApp {
    58	vlib/veb/middleware.v:175:interface HasBeforeRequest {
    59	vlib/veb/static_handler.v:5:pub interface StaticApp {
    60	vlib/veb/veb.v:284:interface BeforeAcceptApp {
    61	vlib/x/crypto/chacha20poly1305/chacha20poly1305.v:25:pub interface AEAD {
    62	vlib/x/json2/types.v:25:pub interface Decodable {
    63	vlib/x/json2/types.v:30:pub interface Encodable {
    64	vlib/x/sessions/README.md:319:pub interface Store[T] {
    65	vlib/x/sessions/store.v:5:pub interface Store[T] {
    66	vlib/x/vweb/middleware.v:10:interface MiddlewareApp {
    67	vlib/x/vweb/middleware.v:175:interface HasBeforeRequest {
    68	vlib/x/vweb/static_handler.v:5:pub interface StaticApp {
    69	vlib/x/vweb/vweb.v:285:interface BeforeAcceptApp {

I think that adding an Interface suffix is not necessary.

@spytheman
Copy link
Member

However, we already do have vlib/orm/orm.v:195:pub interface Connection { .
Do you think that net.Connection is distinguishable enough from orm.Connection ?

@spytheman spytheman changed the title Proposal: Interfaces for V network stack net: add net.Dialer and net.Connection interfaces, abstracting the different types of connections, already supported by the V network stack Aug 5, 2024
@JalonSolov
Copy link
Contributor

Since you have to include the net. or orm. in front to use them, it should be fine. Namespaces are a commonly accepted method of reusing a name in a non-colliding fashion.

@spytheman spytheman merged commit 576a0ab into vlang:master Aug 5, 2024
61 checks passed
@medvednikov
Copy link
Member

Since you have to include the net. or orm. in front to use them, it should be fine. Namespaces are a commonly accepted method of reusing a name in a non-colliding fashion.

Agreed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Unit: vlib Bugs/feature requests, that are related to the vlib.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants