Skip to content
This repository was archived by the owner on Feb 14, 2025. It is now read-only.

Commit a763dad

Browse files
committed
reworking listener, connectoin, etc
1 parent 6e58a3d commit a763dad

File tree

9 files changed

+262
-256
lines changed

9 files changed

+262
-256
lines changed

gojo/net/__init__.mojo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ A good chunk of the leg work here came from the lightbug_http project! https://g
66
from .fd import FileDescriptor
77
from .socket import Socket
88
from .tcp import TCPConnection, TCPListener, listen_tcp, dial_tcp, TCPAddr
9+
from .udp import UDPAddr
910
from .address import NetworkType, Addr
1011
from .ip import get_ip_address, get_addr_info
1112
from .dial import Dialer

gojo/net/address.mojo

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,36 @@ struct NetworkType:
1616

1717

1818
trait Addr(CollectionElement, Stringable):
19-
fn __init__(inout self):
20-
...
21-
2219
fn network(self) -> String:
2320
"""Name of the network (for example, "tcp", "udp")."""
2421
...
2522

2623

27-
fn resolve_internet_addr(network: String, address: String) raises -> TCPAddr:
24+
@value
25+
struct BaseAddr:
26+
"""Addr struct representing a TCP address.
27+
28+
Args:
29+
ip: IP address.
30+
port: Port number.
31+
zone: IPv6 addressing zone.
32+
"""
33+
34+
var ip: String
35+
var port: Int
36+
var zone: String # IPv6 addressing zone
37+
38+
fn __init__(inout self, ip: String = "", port: Int = 0, zone: String = ""):
39+
self.ip = ip
40+
self.port = port
41+
self.zone = zone
42+
43+
44+
fn resolve_internet_addr(network: String, address: String) -> (TCPAddr, Error):
2845
var host: String = ""
2946
var port: String = ""
3047
var portnum: Int = 0
48+
var err = Error()
3149
if (
3250
network == NetworkType.tcp.value
3351
or network == NetworkType.tcp4.value
@@ -37,29 +55,33 @@ fn resolve_internet_addr(network: String, address: String) raises -> TCPAddr:
3755
or network == NetworkType.udp6.value
3856
):
3957
if address != "":
40-
var host_port = split_host_port(address)
41-
host = host_port.host
42-
port = str(host_port.port)
43-
portnum = atol(port.__str__())
58+
var result = split_host_port(address)
59+
if result[1]:
60+
return TCPAddr(), result[1]
61+
62+
host = result[0].host
63+
port = str(result[0].port)
64+
portnum = result[0].port
4465
elif network == NetworkType.ip.value or network == NetworkType.ip4.value or network == NetworkType.ip6.value:
4566
if address != "":
4667
host = address
4768
elif network == NetworkType.unix.value:
48-
raise Error("Unix addresses not supported yet")
69+
return TCPAddr(), Error("Unix addresses not supported yet")
4970
else:
50-
raise Error("unsupported network type: " + network)
51-
return TCPAddr(host, portnum)
71+
return TCPAddr(), Error("unsupported network type: " + network)
72+
return TCPAddr(host, portnum), err
5273

5374

54-
alias missingPortError = Error("missing port in address")
55-
alias tooManyColonsError = Error("too many colons in address")
75+
alias MISSING_PORT_ERROR = Error("missing port in address")
76+
alias TOO_MANY_COLONS_ERROR = Error("too many colons in address")
5677

5778

79+
@value
5880
struct HostPort(Stringable):
5981
var host: String
6082
var port: Int
6183

62-
fn __init__(inout self, host: String, port: Int):
84+
fn __init__(inout self, host: String = "", port: Int = 0):
6385
self.host = host
6486
self.port = port
6587

@@ -73,43 +95,46 @@ fn join_host_port(host: String, port: String) -> String:
7395
return host + ":" + port
7496

7597

76-
fn split_host_port(hostport: String) raises -> HostPort:
98+
fn split_host_port(hostport: String) -> (HostPort, Error):
7799
var host: String = ""
78100
var port: String = ""
79101
var colon_index = hostport.rfind(":")
80102
var j: Int = 0
81103
var k: Int = 0
82104

83105
if colon_index == -1:
84-
raise missingPortError
106+
return HostPort(), MISSING_PORT_ERROR
85107
if hostport[0] == "[":
86108
var end_bracket_index = hostport.find("]")
87109
if end_bracket_index == -1:
88-
raise Error("missing ']' in address")
110+
return HostPort(), Error("missing ']' in address")
89111
if end_bracket_index + 1 == len(hostport):
90-
raise missingPortError
112+
return HostPort(), MISSING_PORT_ERROR
91113
elif end_bracket_index + 1 == colon_index:
92114
host = hostport[1:end_bracket_index]
93115
j = 1
94116
k = end_bracket_index + 1
95117
else:
96118
if hostport[end_bracket_index + 1] == ":":
97-
raise tooManyColonsError
119+
return HostPort(), TOO_MANY_COLONS_ERROR
98120
else:
99-
raise missingPortError
121+
return HostPort(), MISSING_PORT_ERROR
100122
else:
101123
host = hostport[:colon_index]
102124
if host.find(":") != -1:
103-
raise tooManyColonsError
125+
return HostPort(), TOO_MANY_COLONS_ERROR
104126
if hostport[j:].find("[") != -1:
105-
raise Error("unexpected '[' in address")
127+
return HostPort(), Error("unexpected '[' in address")
106128
if hostport[k:].find("]") != -1:
107-
raise Error("unexpected ']' in address")
129+
return HostPort(), Error("unexpected ']' in address")
108130
port = hostport[colon_index + 1 :]
109131

110132
if port == "":
111-
raise missingPortError
133+
return HostPort(), MISSING_PORT_ERROR
112134
if host == "":
113-
raise Error("missing host")
135+
return HostPort(), Error("missing host")
114136

115-
return HostPort(host, atol(port))
137+
try:
138+
return HostPort(host, atol(port)), Error()
139+
except e:
140+
return HostPort(), e

gojo/net/dial.mojo

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .tcp import resolve_internet_addr
22
from .socket import Socket
3-
from .address import split_host_port
3+
from .address import split_host_port, BaseAddr
44

55

66
@value
@@ -9,7 +9,11 @@ struct Dialer:
99

1010
@always_inline
1111
fn dial(self, network: String, address: String) raises -> TCPConnection:
12-
var tcp_addr = resolve_internet_addr(network, address)
13-
var socket = Socket(local_address=self.local_address)
12+
var tcp_addr: TCPAddr
13+
var err: Error
14+
tcp_addr, err = resolve_internet_addr(network, address)
15+
if err:
16+
raise err
17+
var socket = Socket(local_address=BaseAddr(tcp_addr.ip, tcp_addr.port, tcp_addr.zone))
1418
socket.connect(tcp_addr.ip, tcp_addr.port)
1519
return TCPConnection(socket^)

gojo/net/listen.mojo

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
# TODO: For now listener is paired with TCP until we need to support
2-
# more than one type of Connection or Listener
3-
@value
4-
struct ListenConfig(CollectionElement):
5-
var keep_alive: Duration
1+
from .address import resolve_internet_addr, BaseAddr
2+
from ..syscall import SocketOptions
63

7-
fn listen(self, network: String, address: String) raises -> TCPListener:
8-
var tcp_addr = resolve_internet_addr(network, address)
9-
var socket = Socket(local_address=tcp_addr)
10-
socket.bind(tcp_addr.ip, tcp_addr.port)
11-
socket.set_socket_option(SocketOptions.SO_REUSEADDR, 1)
12-
socket.listen()
13-
print(str("Listening on ") + str(socket.local_address))
14-
return TCPListener(socket^, self, network, address)
4+
5+
fn listen(network: String, address: String) raises -> TCPListener:
6+
var tcp_addr: TCPAddr
7+
var err: Error
8+
tcp_addr, err = resolve_internet_addr(network, address)
9+
if err:
10+
raise err
11+
var socket = Socket(local_address=BaseAddr(tcp_addr.ip, tcp_addr.port, tcp_addr.zone))
12+
socket.bind(tcp_addr.ip, tcp_addr.port)
13+
socket.set_socket_option(SocketOptions.SO_REUSEADDR, 1)
14+
socket.listen()
15+
print(str("Listening on ") + str(socket.local_address_as_tcp()))
16+
return TCPListener(socket^, network, address)
1517

1618

1719
trait Listener(Movable):
1820
# Raising here because a Result[Optional[Connection], Error] is funky.
19-
fn accept(self) raises -> Connection:
21+
fn accept[T: Conn](self) raises -> T:
2022
...
2123

2224
fn close(inout self) -> Error:

gojo/net/net.mojo

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -55,67 +55,67 @@ trait Conn(io.Writer, io.Reader, io.Closer):
5555
# ...
5656

5757

58-
struct Connection(Conn):
59-
"""Connection is a concrete generic stream-oriented network connection.
60-
It is used as the internal connection for structs like TCPConnection.
61-
62-
Args:
63-
fd: The file descriptor of the connection.
64-
"""
65-
66-
var fd: Socket
67-
68-
@always_inline
69-
fn __init__(inout self, owned socket: Socket):
70-
self.fd = socket^
71-
72-
@always_inline
73-
fn __moveinit__(inout self, owned existing: Self):
74-
self.fd = existing.fd^
75-
76-
@always_inline
77-
fn read(inout self, inout dest: List[UInt8]) -> (Int, Error):
78-
"""Reads data from the underlying file descriptor.
79-
80-
Args:
81-
dest: The buffer to read data into.
82-
83-
Returns:
84-
The number of bytes read, or an error if one occurred.
85-
"""
86-
return self.fd.read(dest)
87-
88-
@always_inline
89-
fn write(inout self, src: List[UInt8]) -> (Int, Error):
90-
"""Writes data to the underlying file descriptor.
91-
92-
Args:
93-
src: The buffer to read data into.
94-
95-
Returns:
96-
The number of bytes written, or an error if one occurred.
97-
"""
98-
return self.fd.write(src)
99-
100-
@always_inline
101-
fn close(inout self) -> Error:
102-
"""Closes the underlying file descriptor.
103-
104-
Returns:
105-
An error if one occurred, or None if the file descriptor was closed successfully.
106-
"""
107-
return self.fd.close()
108-
109-
@always_inline
110-
fn local_address[T: Addr](self) -> T:
111-
"""Returns the local network address.
112-
The Addr returned is shared by all invocations of local_address, so do not modify it.
113-
"""
114-
return self.fd.local_address
115-
116-
@always_inline
117-
fn remote_address[T: Addr](self) -> T:
118-
"""Returns the remote network address.
119-
The Addr returned is shared by all invocations of remote_address, so do not modify it.
120-
"""
121-
return self.fd.remote_address
58+
# struct Connection():
59+
# """Connection is a concrete generic stream-oriented network connection.
60+
# It is used as the internal connection for structs like TCPConnection.
61+
62+
# Args:
63+
# socket: The file descriptor of the connection.
64+
# """
65+
66+
# var socket: Socket
67+
68+
# @always_inline
69+
# fn __init__(inout self, owned socket: Socket):
70+
# self.socket = socket^
71+
72+
# @always_inline
73+
# fn __moveinit__(inout self, owned existing: Self):
74+
# self.socket = existing.socket^
75+
76+
# @always_inline
77+
# fn read(inout self, inout dest: List[UInt8]) -> (Int, Error):
78+
# """Reads data from the underlying file descriptor.
79+
80+
# Args:
81+
# dest: The buffer to read data into.
82+
83+
# Returns:
84+
# The number of bytes read, or an error if one occurred.
85+
# """
86+
# return self.socket.read(dest)
87+
88+
# @always_inline
89+
# fn write(inout self, src: List[UInt8]) -> (Int, Error):
90+
# """Writes data to the underlying file descriptor.
91+
92+
# Args:
93+
# src: The buffer to read data into.
94+
95+
# Returns:
96+
# The number of bytes written, or an error if one occurred.
97+
# """
98+
# return self.socket.write(src)
99+
100+
# @always_inline
101+
# fn close(inout self) -> Error:
102+
# """Closes the underlying file descriptor.
103+
104+
# Returns:
105+
# An error if one occurred, or None if the file descriptor was closed successfully.
106+
# """
107+
# return self.socket.close()
108+
109+
# @always_inline
110+
# fn local_address[T: Addr](self) -> T:
111+
# """Returns the local network address.
112+
# The Addr returned is shared by all invocations of local_address, so do not modify it.
113+
# """
114+
# return self.socket.local_address
115+
116+
# @always_inline
117+
# fn remote_address[T: Addr](self) -> T:
118+
# """Returns the remote network address.
119+
# The Addr returned is shared by all invocations of remote_address, so do not modify it.
120+
# """
121+
# return self.socket.remote_address

0 commit comments

Comments
 (0)