@@ -16,11 +16,8 @@ package main
1616
1717import (
1818 "context"
19- "errors"
2019 "fmt"
2120 "net"
22- "strconv"
23- "strings"
2421 "sync"
2522 "sync/atomic"
2623 "time"
@@ -152,143 +149,79 @@ type globalListener struct {
152149 deadlineMu sync.Mutex
153150}
154151
155- type NetworkAddr struct {
156- network string
157- Host string
158- Port uint
159- }
160-
161- // String returns a human-readable representation of the [NetworkAddr].
162- func (na * NetworkAddr ) Network () string {
163- return na .network
164- }
165-
166- // String returns a human-readable representation of the [NetworkAddr].
167- func (na * NetworkAddr ) String () string {
168- return na .JoinHostPort ()
169- }
170-
171- // JoinHostPort is a convenience wrapper around [net.JoinHostPort].
172- func (na * NetworkAddr ) JoinHostPort () string {
173- return net .JoinHostPort (na .Host , strconv .Itoa (int (na .Port )))
174- }
175-
176- // Key returns a representative string useful to retrieve this entity from a
177- // map. This is used to uniquely identify reusable listeners.
178- func (na * NetworkAddr ) Key () string {
179- return na .network + "/" + na .JoinHostPort ()
180- }
181-
182- // Listen creates a new listener for the [NetworkAddr].
152+ // Listen creates a new listener for a given network and address.
183153//
184154// Listeners can overlap one another, because during config changes the new
185155// config is started before the old config is destroyed. This is done by using
186156// reusable listener wrappers, which do not actually close the underlying socket
187157// until all uses of the shared listener have been closed.
188- func (na * NetworkAddr ) Listen (ctx context.Context , config net.ListenConfig ) (any , error ) {
189- switch na .network {
158+ func Listen (ctx context.Context , network string , addr string , config net.ListenConfig ) (any , error ) {
159+ lnKey := network + "/" + addr
160+
161+ switch network {
190162
191163 case "tcp" :
192164 listenersMu .Lock ()
193165 defer listenersMu .Unlock ()
194166
195- if lnGlobal , ok := listeners [na . Key () ]; ok {
167+ if lnGlobal , ok := listeners [lnKey ]; ok {
196168 lnGlobal .usage .Add (1 )
197169 return & sharedListener {
198170 usage : & lnGlobal .usage ,
199171 deadline : & lnGlobal .deadline ,
200172 deadlineMu : & lnGlobal .deadlineMu ,
201- key : na . Key () ,
173+ key : lnKey ,
202174 listener : lnGlobal .ln ,
203175 }, nil
204176 }
205177
206- ln , err := config .Listen (ctx , na . network , na . JoinHostPort () )
178+ ln , err := config .Listen (ctx , network , addr )
207179 if err != nil {
208180 return nil , err
209181 }
210182
211183 lnGlobal := & globalListener {ln : ln }
212184 lnGlobal .usage .Store (1 )
213- listeners [na . Key () ] = lnGlobal
185+ listeners [lnKey ] = lnGlobal
214186
215187 return & sharedListener {
216188 usage : & lnGlobal .usage ,
217189 deadline : & lnGlobal .deadline ,
218190 deadlineMu : & lnGlobal .deadlineMu ,
219- key : na . Key () ,
191+ key : lnKey ,
220192 listener : ln ,
221193 }, nil
222194
223195 case "udp" :
224196 listenersMu .Lock ()
225197 defer listenersMu .Unlock ()
226198
227- if lnGlobal , ok := listeners [na . Key () ]; ok {
199+ if lnGlobal , ok := listeners [lnKey ]; ok {
228200 lnGlobal .usage .Add (1 )
229201 return & sharedPacketConn {
230202 usage : & lnGlobal .usage ,
231- key : na . Key () ,
203+ key : lnKey ,
232204 PacketConn : lnGlobal .pc ,
233205 }, nil
234206 }
235207
236- pc , err := config .ListenPacket (ctx , na . network , na . JoinHostPort () )
208+ pc , err := config .ListenPacket (ctx , network , addr )
237209 if err != nil {
238210 return nil , err
239211 }
240212
241213 lnGlobal := & globalListener {pc : pc }
242214 lnGlobal .usage .Store (1 )
243- listeners [na . Key () ] = lnGlobal
215+ listeners [lnKey ] = lnGlobal
244216
245217 return & sharedPacketConn {
246218 usage : & lnGlobal .usage ,
247- key : na . Key () ,
219+ key : lnKey ,
248220 PacketConn : pc ,
249221 }, nil
250222
251223 default :
252- return nil , fmt .Errorf ("unsupported network: %s" , na .network )
253-
254- }
255- }
256-
257- // ParseNetworkAddr parses an address into a [NetworkAddr]. The input
258- // string is expected to be of the form "network/host:port" where any part is
259- // optional.
260- //
261- // Examples:
262- //
263- // tcp/127.0.0.1:8000
264- // udp/127.0.0.1:9000
265- func ParseNetworkAddr (addr string ) (NetworkAddr , error ) {
266- var host , port string
267- network , host , port , err := SplitNetworkAddr (addr )
268- if err != nil {
269- return NetworkAddr {}, err
270- }
271- if network == "" {
272- return NetworkAddr {}, errors .New ("missing network" )
273- }
274- p , err := strconv .ParseUint (port , 10 , 16 )
275- if err != nil {
276- return NetworkAddr {}, fmt .Errorf ("invalid port: %v" , err )
277- }
278- return NetworkAddr {
279- network : network ,
280- Host : host ,
281- Port : uint (p ),
282- }, nil
283- }
224+ return nil , fmt .Errorf ("unsupported network: %s" , network )
284225
285- // SplitNetworkAddr splits a into its network, host, and port components.
286- func SplitNetworkAddr (a string ) (network , host , port string , err error ) {
287- beforeSlash , afterSlash , slashFound := strings .Cut (a , "/" )
288- if slashFound {
289- network = strings .ToLower (strings .TrimSpace (beforeSlash ))
290- a = afterSlash
291226 }
292- host , port , err = net .SplitHostPort (a )
293- return
294227}
0 commit comments