@@ -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