added the proxy service for http/https client peer on the server side. work in progress
This commit is contained in:
		
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @ -13,6 +13,7 @@ SRCS=\ | |||||||
| 	server.go \ | 	server.go \ | ||||||
| 	server-ctl.go \ | 	server-ctl.go \ | ||||||
| 	server-peer.go \ | 	server-peer.go \ | ||||||
|  | 	server-proxy.go \ | ||||||
| 	server-ws.go \ | 	server-ws.go \ | ||||||
| 	system.go | 	system.go | ||||||
|  |  | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ import "net/http" | |||||||
| import "net/url" | import "net/url" | ||||||
| import "runtime" | import "runtime" | ||||||
| import "strconv" | import "strconv" | ||||||
|  | import "unsafe" | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  *                       POST                 GET            PUT            DELETE |  *                       POST                 GET            PUT            DELETE | ||||||
| @ -31,8 +32,9 @@ type json_in_client_conn struct { | |||||||
|  |  | ||||||
| type json_in_client_route struct { | type json_in_client_route struct { | ||||||
| 	ClientPeerAddr string `json:"client-peer-addr"` | 	ClientPeerAddr string `json:"client-peer-addr"` | ||||||
| 	ServerPeerNet string `json:"server-peer-net"` // allowed network in prefix notation | 	ServerPeerOption string `json:"server-peer-option"` | ||||||
| 	ServerPeerProto ROUTE_PROTO `json:"server-peer-proto"` | 	ServerPeerServiceAddr string `json:"server-peer-service-addr"` // desired listening address on the server side | ||||||
|  | 	ServerPeerServiceNet string `json:"server-peer-service-net"` // permitted network in prefix notation | ||||||
| } | } | ||||||
|  |  | ||||||
| type json_out_client_conn_id struct { | type json_out_client_conn_id struct { | ||||||
| @ -55,9 +57,9 @@ type json_out_client_route_id struct { | |||||||
| type json_out_client_route struct { | type json_out_client_route struct { | ||||||
| 	Id RouteId `json:"id"` | 	Id RouteId `json:"id"` | ||||||
| 	ClientPeerAddr string `json:"client-peer-addr"` | 	ClientPeerAddr string `json:"client-peer-addr"` | ||||||
| 	ServerPeerListenAddr string `json:"server-peer-listen-addr"` | 	ServerPeerOption string `json:"server-peer-option"` | ||||||
| 	ServerPeerNet string `json:"server-peer-net"` | 	ServerPeerListenAddr string `json:"server-peer-service-addr"` | ||||||
| 	ServerPeerProto ROUTE_PROTO `json:"server-peer-proto"` | 	ServerPeerNet string `json:"server-peer-service-net"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type json_out_client_peer struct { | type json_out_client_peer struct { | ||||||
| @ -152,7 +154,7 @@ func (ctl *client_ctl_client_conns) ServeHTTP(w http.ResponseWriter, req *http.R | |||||||
| 						ClientPeerAddr: r.peer_addr, | 						ClientPeerAddr: r.peer_addr, | ||||||
| 						ServerPeerListenAddr: r.server_peer_listen_addr.String(), | 						ServerPeerListenAddr: r.server_peer_listen_addr.String(), | ||||||
| 						ServerPeerNet: r.server_peer_net, | 						ServerPeerNet: r.server_peer_net, | ||||||
| 						ServerPeerProto: r.server_peer_proto, | 						ServerPeerOption: r.server_peer_proto.string(), | ||||||
| 					}) | 					}) | ||||||
| 				} | 				} | ||||||
| 				js = append(js, json_out_client_conn{ | 				js = append(js, json_out_client_conn{ | ||||||
| @ -242,7 +244,7 @@ func (ctl *client_ctl_client_conns_id) ServeHTTP(w http.ResponseWriter, req *htt | |||||||
|  |  | ||||||
| 	conn_id = req.PathValue("conn_id") | 	conn_id = req.PathValue("conn_id") | ||||||
|  |  | ||||||
| 	conn_nid, err = strconv.ParseUint(conn_id, 10, 32) | 	conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | ||||||
| @ -270,7 +272,7 @@ func (ctl *client_ctl_client_conns_id) ServeHTTP(w http.ResponseWriter, req *htt | |||||||
| 					ClientPeerAddr: r.peer_addr, | 					ClientPeerAddr: r.peer_addr, | ||||||
| 					ServerPeerListenAddr: r.server_peer_listen_addr.String(), | 					ServerPeerListenAddr: r.server_peer_listen_addr.String(), | ||||||
| 					ServerPeerNet: r.server_peer_net, | 					ServerPeerNet: r.server_peer_net, | ||||||
| 					ServerPeerProto: r.server_peer_proto, | 					ServerPeerOption: r.server_peer_proto.string(), | ||||||
| 				}) | 				}) | ||||||
| 			} | 			} | ||||||
| 			js = &json_out_client_conn{ | 			js = &json_out_client_conn{ | ||||||
| @ -326,10 +328,10 @@ func (ctl *client_ctl_client_conns_id_routes) ServeHTTP(w http.ResponseWriter, r | |||||||
|  |  | ||||||
| 	conn_id = req.PathValue("conn_id") | 	conn_id = req.PathValue("conn_id") | ||||||
|  |  | ||||||
| 	conn_nid, err = strconv.ParseUint(conn_id, 10, 32) | 	conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id }); err != nil { goto oops } | ||||||
| 		goto done | 		goto done | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -353,7 +355,7 @@ func (ctl *client_ctl_client_conns_id_routes) ServeHTTP(w http.ResponseWriter, r | |||||||
| 					ClientPeerAddr: r.peer_addr, | 					ClientPeerAddr: r.peer_addr, | ||||||
| 					ServerPeerListenAddr: r.server_peer_listen_addr.String(), | 					ServerPeerListenAddr: r.server_peer_listen_addr.String(), | ||||||
| 					ServerPeerNet: r.server_peer_net, | 					ServerPeerNet: r.server_peer_net, | ||||||
| 					ServerPeerProto: r.server_peer_proto, | 					ServerPeerOption: r.server_peer_proto.string(), | ||||||
| 				}) | 				}) | ||||||
| 			} | 			} | ||||||
| 			cts.route_mtx.Unlock() | 			cts.route_mtx.Unlock() | ||||||
| @ -364,14 +366,21 @@ func (ctl *client_ctl_client_conns_id_routes) ServeHTTP(w http.ResponseWriter, r | |||||||
| 		case http.MethodPost: | 		case http.MethodPost: | ||||||
| 			var jcr json_in_client_route | 			var jcr json_in_client_route | ||||||
| 			var r *ClientRoute | 			var r *ClientRoute | ||||||
|  | 			var server_peer_proto RouteOption | ||||||
|  |  | ||||||
| 			err = json.NewDecoder(req.Body).Decode(&jcr) | 			err = json.NewDecoder(req.Body).Decode(&jcr) | ||||||
| 			if err != nil || jcr.ClientPeerAddr == "" || jcr.ServerPeerProto < 0 || jcr.ServerPeerProto > ROUTE_PROTO_TCP6 { | 			if err != nil || jcr.ClientPeerAddr == "" { | ||||||
| 				status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 				status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 				goto done | 				goto done | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			r, err = cts.AddNewClientRoute(jcr.ClientPeerAddr, jcr.ServerPeerNet, jcr.ServerPeerProto) | 			server_peer_proto = string_to_route_proto(jcr.ServerPeerOption) | ||||||
|  | 			if server_peer_proto == RouteOption(ROUTE_OPTION_UNSPEC) { | ||||||
|  | 				status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
|  | 				goto done | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			r, err = cts.AddNewClientRoute(jcr.ClientPeerAddr, jcr.ServerPeerServiceAddr, jcr.ServerPeerServiceNet, server_peer_proto) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				status_code = http.StatusInternalServerError; w.WriteHeader(status_code) | 				status_code = http.StatusInternalServerError; w.WriteHeader(status_code) | ||||||
| 				if err = je.Encode(json_errmsg{Text: err.Error()}); err != nil { goto oops } | 				if err = je.Encode(json_errmsg{Text: err.Error()}); err != nil { goto oops } | ||||||
| @ -424,13 +433,13 @@ func (ctl *client_ctl_client_conns_id_routes_id) ServeHTTP(w http.ResponseWriter | |||||||
| 	conn_id = req.PathValue("conn_id") | 	conn_id = req.PathValue("conn_id") | ||||||
| 	route_id = req.PathValue("route_id") | 	route_id = req.PathValue("route_id") | ||||||
|  |  | ||||||
| 	conn_nid, err = strconv.ParseUint(conn_id, 10, 32) | 	conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | ||||||
| 		goto done | 		goto done | ||||||
| 	} | 	} | ||||||
| 	route_nid, err = strconv.ParseUint(route_id, 10, 32) | 	route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | ||||||
| @ -459,7 +468,7 @@ func (ctl *client_ctl_client_conns_id_routes_id) ServeHTTP(w http.ResponseWriter | |||||||
| 				ClientPeerAddr: r.peer_addr, | 				ClientPeerAddr: r.peer_addr, | ||||||
| 				ServerPeerListenAddr: r.server_peer_listen_addr.String(), | 				ServerPeerListenAddr: r.server_peer_listen_addr.String(), | ||||||
| 				ServerPeerNet: r.server_peer_net, | 				ServerPeerNet: r.server_peer_net, | ||||||
| 				ServerPeerProto: r.server_peer_proto, | 				ServerPeerOption: r.server_peer_proto.string(), | ||||||
| 			}) | 			}) | ||||||
| 			if err != nil { goto oops } | 			if err != nil { goto oops } | ||||||
|  |  | ||||||
| @ -511,7 +520,7 @@ func (ctl *client_ctl_client_conns_id_routes_id_peers) ServeHTTP(w http.Response | |||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | ||||||
| 		goto done | 		goto done | ||||||
| 	} | 	} | ||||||
| 	route_nid, err = strconv.ParseUint(route_id, 10, 32) | 	route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | ||||||
| @ -595,7 +604,7 @@ func (ctl *client_ctl_client_conns_id_routes_id_peers_id) ServeHTTP(w http.Respo | |||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | ||||||
| 		goto done | 		goto done | ||||||
| 	} | 	} | ||||||
| 	route_nid, err = strconv.ParseUint(route_id, 10, 32) | 	route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package hodu | |||||||
| import "errors" | import "errors" | ||||||
| import "io" | import "io" | ||||||
| import "net" | import "net" | ||||||
|  | import "strings" | ||||||
| import "sync" | import "sync" | ||||||
|  |  | ||||||
| func NewClientPeerConn(r *ClientRoute, c *net.TCPConn, id PeerId, pts_raddr string, pts_laddr string) *ClientPeerConn { | func NewClientPeerConn(r *ClientRoute, c *net.TCPConn, id PeerId, pts_raddr string, pts_laddr string) *ClientPeerConn { | ||||||
| @ -29,7 +30,7 @@ func (cpc *ClientPeerConn) RunTask(wg *sync.WaitGroup) error { | |||||||
| 	for { | 	for { | ||||||
| 		n, err = cpc.conn.Read(buf[:]) | 		n, err = cpc.conn.Read(buf[:]) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if errors.Is(err, io.EOF) { | 			if errors.Is(err, io.EOF) || strings.Contains(err.Error(), "use of closed network connection") { // i hate checking this condition with strings.Contains() | ||||||
| 				cpc.route.cts.cli.log.Write(cpc.route.cts.sid, LOG_INFO, | 				cpc.route.cts.cli.log.Write(cpc.route.cts.sid, LOG_INFO, | ||||||
| 					"Client-side peer(%d,%d,%s,%s) closed", | 					"Client-side peer(%d,%d,%s,%s) closed", | ||||||
| 					cpc.route.id, cpc.conn_id, cpc.conn.RemoteAddr().String(), cpc.conn.LocalAddr().String()) | 					cpc.route.id, cpc.conn_id, cpc.conn.RemoteAddr().String(), cpc.conn.LocalAddr().String()) | ||||||
|  | |||||||
							
								
								
									
										71
									
								
								client.go
									
									
									
									
									
								
							
							
						
						
									
										71
									
								
								client.go
									
									
									
									
									
								
							| @ -8,6 +8,7 @@ import "log" | |||||||
| import "math/rand" | import "math/rand" | ||||||
| import "net" | import "net" | ||||||
| import "net/http" | import "net/http" | ||||||
|  | import "strings" | ||||||
| import "sync" | import "sync" | ||||||
| import "sync/atomic" | import "sync/atomic" | ||||||
| import "time" | import "time" | ||||||
| @ -101,9 +102,12 @@ type ClientRoute struct { | |||||||
| 	cts *ClientConn | 	cts *ClientConn | ||||||
| 	id RouteId | 	id RouteId | ||||||
| 	peer_addr string | 	peer_addr string | ||||||
| 	server_peer_listen_addr *net.TCPAddr | 	peer_proto RouteOption | ||||||
|  |  | ||||||
|  | 	server_peer_listen_addr *net.TCPAddr // actual service-side service address | ||||||
|  | 	server_peer_addr string // desired server-side service address | ||||||
| 	server_peer_net string | 	server_peer_net string | ||||||
| 	server_peer_proto ROUTE_PROTO | 	server_peer_proto RouteOption | ||||||
|  |  | ||||||
| 	ptc_mtx        sync.Mutex | 	ptc_mtx        sync.Mutex | ||||||
| 	ptc_map        ClientPeerConnMap | 	ptc_map        ClientPeerConnMap | ||||||
| @ -151,7 +155,7 @@ func (g *GuardedPacketStreamClient) Context() context.Context { | |||||||
| }*/ | }*/ | ||||||
|  |  | ||||||
| // -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||||||
| func NewClientRoute(cts *ClientConn, id RouteId, client_peer_addr string, server_peer_net string, server_peer_proto ROUTE_PROTO) *ClientRoute { | func NewClientRoute(cts *ClientConn, id RouteId, client_peer_addr string, server_peer_svc_addr string, server_peer_svc_net string, server_peer_proto RouteOption) *ClientRoute { | ||||||
| 	var r ClientRoute | 	var r ClientRoute | ||||||
|  |  | ||||||
| 	r.cts = cts | 	r.cts = cts | ||||||
| @ -159,7 +163,11 @@ func NewClientRoute(cts *ClientConn, id RouteId, client_peer_addr string, server | |||||||
| 	r.ptc_map = make(ClientPeerConnMap) | 	r.ptc_map = make(ClientPeerConnMap) | ||||||
| 	r.ptc_cancel_map = make(ClientPeerCancelFuncMap) | 	r.ptc_cancel_map = make(ClientPeerCancelFuncMap) | ||||||
| 	r.peer_addr = client_peer_addr // client-side peer | 	r.peer_addr = client_peer_addr // client-side peer | ||||||
| 	r.server_peer_net = server_peer_net // permitted network for server-side peer | 	// if the client_peer_addr is a domain name, it can't tell between tcp4 and tcp6 | ||||||
|  | 	r.peer_proto = string_to_route_proto(tcp_addr_str_class(client_peer_addr)) | ||||||
|  |  | ||||||
|  | 	r.server_peer_addr = server_peer_svc_addr | ||||||
|  | 	r.server_peer_net = server_peer_svc_net // permitted network for server-side peer | ||||||
| 	r.server_peer_proto = server_peer_proto | 	r.server_peer_proto = server_peer_proto | ||||||
| 	r.stop_req.Store(false) | 	r.stop_req.Store(false) | ||||||
| 	r.stop_chan = make(chan bool, 8) | 	r.stop_chan = make(chan bool, 8) | ||||||
| @ -249,7 +257,7 @@ func (r *ClientRoute) RunTask(wg *sync.WaitGroup) { | |||||||
| 	// most useful works are triggered by ReportEvent() and done by ConnectToPeer() | 	// most useful works are triggered by ReportEvent() and done by ConnectToPeer() | ||||||
| 	defer wg.Done() | 	defer wg.Done() | ||||||
|  |  | ||||||
| 	err = r.cts.psc.Send(MakeRouteStartPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_net)) | 	err = r.cts.psc.Send(MakeRouteStartPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_addr, r.server_peer_net)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		r.cts.cli.log.Write(r.cts.sid, LOG_DEBUG, | 		r.cts.cli.log.Write(r.cts.sid, LOG_DEBUG, | ||||||
| 			"Failed to send route_start for route(%d,%s,%v,%v) to %s", | 			"Failed to send route_start for route(%d,%s,%v,%v) to %s", | ||||||
| @ -273,7 +281,7 @@ done: | |||||||
| 	r.ReqStop() | 	r.ReqStop() | ||||||
| 	r.ptc_wg.Wait() // wait for all peer tasks are finished | 	r.ptc_wg.Wait() // wait for all peer tasks are finished | ||||||
|  |  | ||||||
| 	err = r.cts.psc.Send(MakeRouteStopPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_net)) | 	err = r.cts.psc.Send(MakeRouteStopPacket(r.id, r.server_peer_proto, r.peer_addr, r.server_peer_addr, r.server_peer_net)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		r.cts.cli.log.Write(r.cts.sid, LOG_DEBUG, | 		r.cts.cli.log.Write(r.cts.sid, LOG_DEBUG, | ||||||
| 			"Failed to route_stop for route(%d,%s,%v,%v) to %s - %s", | 			"Failed to route_stop for route(%d,%s,%v,%v) to %s - %s", | ||||||
| @ -297,7 +305,7 @@ func (r *ClientRoute) ReqStop() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (r *ClientRoute) ConnectToPeer(pts_id PeerId, pts_raddr string, pts_laddr string, wg *sync.WaitGroup) { | func (r *ClientRoute) ConnectToPeer(pts_id PeerId, route_proto RouteOption, pts_raddr string, pts_laddr string, wg *sync.WaitGroup) { | ||||||
| 	var err error | 	var err error | ||||||
| 	var conn net.Conn | 	var conn net.Conn | ||||||
| 	var real_conn *net.TCPConn | 	var real_conn *net.TCPConn | ||||||
| @ -310,10 +318,14 @@ func (r *ClientRoute) ConnectToPeer(pts_id PeerId, pts_raddr string, pts_laddr s | |||||||
| 	var tmout time.Duration | 	var tmout time.Duration | ||||||
| 	var ok bool | 	var ok bool | ||||||
|  |  | ||||||
|  | // TODO: handle TTY | ||||||
|  | //	if route_proto & RouteOption(ROUTE_OPTION_TTY) it must create a pseudo-tty insteaad of connecting to tcp address | ||||||
|  | // | ||||||
|  |  | ||||||
| 	defer wg.Done() | 	defer wg.Done() | ||||||
|  |  | ||||||
| 	tmout = time.Duration(r.cts.cli.ptc_tmout) | 	tmout = time.Duration(r.cts.cli.ptc_tmout) | ||||||
| 	if tmout < 0 { tmout = 10 * time.Second} | 	if tmout <= 0 { tmout = 10 * time.Second} | ||||||
| 	ctx, cancel = context.WithTimeout(r.cts.cli.ctx, tmout) | 	ctx, cancel = context.WithTimeout(r.cts.cli.ctx, tmout) | ||||||
| 	r.ptc_mtx.Lock() | 	r.ptc_mtx.Lock() | ||||||
| 	r.ptc_cancel_map[pts_id] = cancel | 	r.ptc_cancel_map[pts_id] = cancel | ||||||
| @ -458,7 +470,7 @@ func (r *ClientRoute) ReportEvent(pts_id PeerId, event_type PACKET_KIND, event_d | |||||||
| 					} | 					} | ||||||
| 				} else { | 				} else { | ||||||
| 					r.ptc_wg.Add(1) | 					r.ptc_wg.Add(1) | ||||||
| 					go r.ConnectToPeer(pts_id, pd.RemoteAddrStr, pd.LocalAddrStr, &r.ptc_wg) | 					go r.ConnectToPeer(pts_id, r.peer_proto, pd.RemoteAddrStr, pd.LocalAddrStr, &r.ptc_wg) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| @ -577,7 +589,7 @@ func NewClientConn(c *Client, cfg *ClientConfig) *ClientConn { | |||||||
| 	return &cts | 	return &cts | ||||||
| } | } | ||||||
|  |  | ||||||
| func (cts *ClientConn) AddNewClientRoute(addr string, server_peer_net string, proto ROUTE_PROTO) (*ClientRoute, error) { | func (cts *ClientConn) AddNewClientRoute(addr string, server_peer_svc_addr string, server_peer_svc_net string, option RouteOption) (*ClientRoute, error) { | ||||||
| 	var r *ClientRoute | 	var r *ClientRoute | ||||||
| 	var id RouteId | 	var id RouteId | ||||||
| 	var nattempts RouteId | 	var nattempts RouteId | ||||||
| @ -599,11 +611,7 @@ func (cts *ClientConn) AddNewClientRoute(addr string, server_peer_net string, pr | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	//if cts.route_map[route_id] != nil { | 	r = NewClientRoute(cts, id, addr, server_peer_svc_addr, server_peer_svc_net, option) | ||||||
| 	//	cts.route_mtx.Unlock() |  | ||||||
| 	//	return nil, fmt.Errorf("existent route id - %d", route_id) |  | ||||||
| 	//} |  | ||||||
| 	r = NewClientRoute(cts, id, addr, server_peer_net, proto) |  | ||||||
| 	cts.route_map[id] = r | 	cts.route_map[id] = r | ||||||
| 	cts.cli.stats.routes.Add(1) | 	cts.cli.stats.routes.Add(1) | ||||||
| 	cts.route_mtx.Unlock() | 	cts.route_mtx.Unlock() | ||||||
| @ -701,10 +709,41 @@ func (cts *ClientConn) FindClientRouteById(route_id RouteId) *ClientRoute { | |||||||
|  |  | ||||||
| func (cts *ClientConn) AddClientRoutes(peer_addrs []string) error { | func (cts *ClientConn) AddClientRoutes(peer_addrs []string) error { | ||||||
| 	var v string | 	var v string | ||||||
|  | 	var port string | ||||||
|  | 	var option RouteOption | ||||||
|  | 	var va []string | ||||||
|  | 	var svc_addr string | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	for _, v = range peer_addrs { | 	for _, v = range peer_addrs { | ||||||
| 		_, err = cts.AddNewClientRoute(v, "", ROUTE_PROTO_TCP) | 		va = strings.Split(v, ",") | ||||||
|  | 		if len(va) <= 0 || len(va) > 2 { | ||||||
|  | 			return fmt.Errorf("invalid address %s") | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		_, port, err = net.SplitHostPort(va[0]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("invalid address %s", va[0], err.Error()) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if len(va) >= 2 { | ||||||
|  | 			_, _, err = net.SplitHostPort(va[1]) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return fmt.Errorf("invalid address %s", va[1], err.Error()) | ||||||
|  | 			} | ||||||
|  | 			svc_addr = va[1] | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		option = RouteOption(ROUTE_OPTION_TCP) | ||||||
|  | 		// automatic determination of optioncol for common ports | ||||||
|  | 		switch port { | ||||||
|  | 			case "80": | ||||||
|  | 				option |= RouteOption(ROUTE_OPTION_HTTP) | ||||||
|  | 			case "443": | ||||||
|  | 				option |= RouteOption(ROUTE_OPTION_HTTPS) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		_, err = cts.AddNewClientRoute(va[0], svc_addr, "", option) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("unable to add client route for %s - %s", v, err.Error()) | 			return fmt.Errorf("unable to add client route for %s - %s", v, err.Error()) | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -47,6 +47,10 @@ type CTLServiceConfig struct { | |||||||
| 	Addrs  []string `yaml:"addresses"` | 	Addrs  []string `yaml:"addresses"` | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type PXYServiceConfig struct { | ||||||
|  | 	Addrs  []string `yaml:"addresses"` | ||||||
|  | } | ||||||
|  |  | ||||||
| type RPCServiceConfig struct { // rpc server-side configuration | type RPCServiceConfig struct { // rpc server-side configuration | ||||||
| 	Addrs     []string  `yaml:"addresses"` | 	Addrs     []string  `yaml:"addresses"` | ||||||
| } | } | ||||||
| @ -80,6 +84,11 @@ type ServerConfig struct { | |||||||
| 		TLS ServerTLSConfig         `yaml:"tls"` | 		TLS ServerTLSConfig         `yaml:"tls"` | ||||||
| 	} `yaml:"ctl"` | 	} `yaml:"ctl"` | ||||||
|  |  | ||||||
|  | 	PXY struct { | ||||||
|  | 		Service PXYServiceConfig    `yaml:"service"` | ||||||
|  | 		TLS ServerTLSConfig         `yaml:"tls"` | ||||||
|  | 	} `yaml:"pxy"` | ||||||
|  |  | ||||||
| 	RPC struct { | 	RPC struct { | ||||||
| 		Service RPCServiceConfig    `yaml:"service"` | 		Service RPCServiceConfig    `yaml:"service"` | ||||||
| 		TLS ServerTLSConfig         `yaml:"tls"` | 		TLS ServerTLSConfig         `yaml:"tls"` | ||||||
|  | |||||||
							
								
								
									
										32
									
								
								cmd/main.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								cmd/main.go
									
									
									
									
									
								
							| @ -143,10 +143,11 @@ func (sh *signal_handler) WriteLog(id string, level hodu.LogLevel, fmt string, a | |||||||
|  |  | ||||||
| // -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||||||
|  |  | ||||||
| func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) error { | func server_main(ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, cfg *ServerConfig) error { | ||||||
| 	var s *hodu.Server | 	var s *hodu.Server | ||||||
| 	var ctltlscfg *tls.Config | 	var ctltlscfg *tls.Config | ||||||
| 	var rpctlscfg *tls.Config | 	var rpctlscfg *tls.Config | ||||||
|  | 	var pxytlscfg *tls.Config | ||||||
| 	var ctl_prefix string | 	var ctl_prefix string | ||||||
| 	var logger *AppLogger | 	var logger *AppLogger | ||||||
| 	var log_mask hodu.LogMask | 	var log_mask hodu.LogMask | ||||||
| @ -158,13 +159,11 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro | |||||||
|  |  | ||||||
| 	if cfg != nil { | 	if cfg != nil { | ||||||
| 		ctltlscfg, err = make_tls_server_config(&cfg.CTL.TLS) | 		ctltlscfg, err = make_tls_server_config(&cfg.CTL.TLS) | ||||||
| 		if err != nil { | 		if err != nil { return err } | ||||||
| 			return err |  | ||||||
| 		} |  | ||||||
| 		rpctlscfg, err = make_tls_server_config(&cfg.RPC.TLS) | 		rpctlscfg, err = make_tls_server_config(&cfg.RPC.TLS) | ||||||
| 		if err != nil { | 		if err != nil { return err } | ||||||
| 			return err | 		pxytlscfg, err = make_tls_server_config(&cfg.PXY.TLS) | ||||||
| 		} | 		if err != nil { return err } | ||||||
|  |  | ||||||
| 		if len(ctl_addrs) <= 0 { | 		if len(ctl_addrs) <= 0 { | ||||||
| 			ctl_addrs = cfg.CTL.Service.Addrs | 			ctl_addrs = cfg.CTL.Service.Addrs | ||||||
| @ -174,6 +173,10 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro | |||||||
| 			rpc_addrs = cfg.RPC.Service.Addrs | 			rpc_addrs = cfg.RPC.Service.Addrs | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		if len(pxy_addrs) <= 0 { | ||||||
|  | 			pxy_addrs = cfg.PXY.Service.Addrs | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		ctl_prefix = cfg.CTL.Service.Prefix | 		ctl_prefix = cfg.CTL.Service.Prefix | ||||||
| 		log_mask = log_strings_to_mask(cfg.APP.LogMask) | 		log_mask = log_strings_to_mask(cfg.APP.LogMask) | ||||||
| 		max_rpc_conns = cfg.APP.MaxRpcConns | 		max_rpc_conns = cfg.APP.MaxRpcConns | ||||||
| @ -191,9 +194,11 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro | |||||||
| 		logger, | 		logger, | ||||||
| 		ctl_addrs, | 		ctl_addrs, | ||||||
| 		rpc_addrs, | 		rpc_addrs, | ||||||
|  | 		pxy_addrs, | ||||||
| 		ctl_prefix, | 		ctl_prefix, | ||||||
| 		ctltlscfg, | 		ctltlscfg, | ||||||
| 		rpctlscfg, | 		rpctlscfg, | ||||||
|  | 		pxytlscfg, | ||||||
| 		max_rpc_conns, | 		max_rpc_conns, | ||||||
| 		max_peers) | 		max_peers) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @ -202,6 +207,7 @@ func server_main(ctl_addrs []string, rpc_addrs []string, cfg *ServerConfig) erro | |||||||
|  |  | ||||||
| 	s.StartService(nil) | 	s.StartService(nil) | ||||||
| 	s.StartCtlService() | 	s.StartCtlService() | ||||||
|  | 	s.StartPxyService() | ||||||
| 	s.StartExtService(&signal_handler{svc:s}, nil) | 	s.StartExtService(&signal_handler{svc:s}, nil) | ||||||
| 	s.WaitForTermination() | 	s.WaitForTermination() | ||||||
|  |  | ||||||
| @ -278,13 +284,15 @@ func main() { | |||||||
| 	if len(os.Args) < 2 { goto wrong_usage } | 	if len(os.Args) < 2 { goto wrong_usage } | ||||||
|  |  | ||||||
| 	if strings.EqualFold(os.Args[1], "server") { | 	if strings.EqualFold(os.Args[1], "server") { | ||||||
| 		var rpc_addrs[] string | 		var rpc_addrs []string | ||||||
| 		var ctl_addrs[] string | 		var ctl_addrs []string | ||||||
|  | 		var pxy_addrs []string | ||||||
| 		var cfgfile string | 		var cfgfile string | ||||||
| 		var cfg *ServerConfig | 		var cfg *ServerConfig | ||||||
|  |  | ||||||
| 		ctl_addrs = make([]string, 0) | 		ctl_addrs = make([]string, 0) | ||||||
| 		rpc_addrs = make([]string, 0) | 		rpc_addrs = make([]string, 0) | ||||||
|  | 		pxy_addrs = make([]string, 0) | ||||||
|  |  | ||||||
| 		flgs = flag.NewFlagSet("", flag.ContinueOnError) | 		flgs = flag.NewFlagSet("", flag.ContinueOnError) | ||||||
| 		flgs.Func("ctl-on", "specify a listening address for control channel", func(v string) error { | 		flgs.Func("ctl-on", "specify a listening address for control channel", func(v string) error { | ||||||
| @ -295,6 +303,10 @@ func main() { | |||||||
| 			rpc_addrs = append(rpc_addrs, v) | 			rpc_addrs = append(rpc_addrs, v) | ||||||
| 			return nil | 			return nil | ||||||
| 		}) | 		}) | ||||||
|  | 		flgs.Func("pxy-on", "specify a proxy listening address", func(v string) error { | ||||||
|  | 			pxy_addrs = append(pxy_addrs, v) | ||||||
|  | 			return nil | ||||||
|  | 		}) | ||||||
| 		flgs.Func("config-file", "specify a configuration file path", func(v string) error { | 		flgs.Func("config-file", "specify a configuration file path", func(v string) error { | ||||||
| 			cfgfile = v | 			cfgfile = v | ||||||
| 			return nil | 			return nil | ||||||
| @ -317,7 +329,7 @@ func main() { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		err = server_main(ctl_addrs, rpc_addrs, cfg) | 		err = server_main(ctl_addrs, rpc_addrs, pxy_addrs, cfg) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			fmt.Fprintf(os.Stderr, "ERROR: server error - %s\n", err.Error()) | 			fmt.Fprintf(os.Stderr, "ERROR: server error - %s\n", err.Error()) | ||||||
| 			goto oops | 			goto oops | ||||||
|  | |||||||
							
								
								
									
										68
									
								
								hodu.go
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								hodu.go
									
									
									
									
									
								
							| @ -1,10 +1,13 @@ | |||||||
| package hodu | package hodu | ||||||
|  |  | ||||||
| import "net/http" | import "net/http" | ||||||
|  | import "net/netip" | ||||||
| import "os" | import "os" | ||||||
| import "runtime" | import "runtime" | ||||||
|  | import "strings" | ||||||
| import "sync" | import "sync" | ||||||
|  |  | ||||||
|  |  | ||||||
| const HODU_RPC_VERSION uint32 = 0x010000 | const HODU_RPC_VERSION uint32 = 0x010000 | ||||||
|  |  | ||||||
| type LogLevel int | type LogLevel int | ||||||
| @ -20,6 +23,9 @@ const ( | |||||||
| const LOG_ALL LogMask = LogMask(LOG_DEBUG | LOG_INFO | LOG_WARN | LOG_ERROR) | const LOG_ALL LogMask = LogMask(LOG_DEBUG | LOG_INFO | LOG_WARN | LOG_ERROR) | ||||||
| const LOG_NONE LogMask = LogMask(0) | const LOG_NONE LogMask = LogMask(0) | ||||||
|  |  | ||||||
|  | var IPV4_PREFIX_ZERO = netip.MustParsePrefix("0.0.0.0/0") | ||||||
|  | var IPV6_PREFIX_ZERO = netip.MustParsePrefix("::/0") | ||||||
|  |  | ||||||
| type Logger interface { | type Logger interface { | ||||||
| 	Write(id string, level LogLevel, fmtstr string, args ...interface{}) | 	Write(id string, level LogLevel, fmtstr string, args ...interface{}) | ||||||
| } | } | ||||||
| @ -33,20 +39,68 @@ type Service interface { | |||||||
| } | } | ||||||
|  |  | ||||||
| func tcp_addr_str_class(addr string) string { | func tcp_addr_str_class(addr string) string { | ||||||
|  | 	// the string is supposed to be addr:port | ||||||
|  |  | ||||||
| 	if len(addr) > 0 { | 	if len(addr) > 0 { | ||||||
| 		switch addr[0] { | 		var ap netip.AddrPort | ||||||
| 			case '[': | 		var err error | ||||||
| 				return "tcp6" | 		ap, err = netip.ParseAddrPort(addr) | ||||||
| 			case ':': | 		if err == nil { | ||||||
| 				return "tcp" | 			if ap.Addr().Is6() { return "tcp6" } | ||||||
| 			default: | 			if ap.Addr().Is4() { return "tcp4" } | ||||||
| 				return "tcp4" |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return "tcp" | 	return "tcp" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func word_to_route_proto(word string) RouteOption { | ||||||
|  | 	switch word { | ||||||
|  | 		case "tcp4": | ||||||
|  | 			return RouteOption(ROUTE_OPTION_TCP4) | ||||||
|  | 		case "tcp6": | ||||||
|  | 			return RouteOption(ROUTE_OPTION_TCP6) | ||||||
|  | 		case "tcp": | ||||||
|  | 			return RouteOption(ROUTE_OPTION_TCP) | ||||||
|  | 		case "tty": | ||||||
|  | 			return RouteOption(ROUTE_OPTION_TTY) | ||||||
|  | 		case "http": | ||||||
|  | 			return RouteOption(ROUTE_OPTION_HTTP) | ||||||
|  | 		case "https": | ||||||
|  | 			return RouteOption(ROUTE_OPTION_HTTPS) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return RouteOption(ROUTE_OPTION_UNSPEC) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func string_to_route_proto(desc string) RouteOption { | ||||||
|  | 	var fld string | ||||||
|  | 	var proto RouteOption | ||||||
|  | 	var p RouteOption | ||||||
|  |  | ||||||
|  | 	proto = RouteOption(0) | ||||||
|  | 	for _, fld = range strings.Fields(desc) { | ||||||
|  | 		p = word_to_route_proto(fld) | ||||||
|  | 		if p == RouteOption(ROUTE_OPTION_UNSPEC) { return p } | ||||||
|  | 		proto |= p | ||||||
|  | 	} | ||||||
|  | 	return proto | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (proto RouteOption) string() string { | ||||||
|  | 	var str string | ||||||
|  |  | ||||||
|  | 	str = "" | ||||||
|  | 	if proto & RouteOption(ROUTE_OPTION_TCP6) != 0 { str += " tcp6" } | ||||||
|  | 	if proto & RouteOption(ROUTE_OPTION_TCP4) != 0 { str += " tcp4" } | ||||||
|  | 	if proto & RouteOption(ROUTE_OPTION_TCP)  != 0 { str += " tcp" } | ||||||
|  | 	if proto & RouteOption(ROUTE_OPTION_TTY)  != 0 { str += " tty" } | ||||||
|  | 	if proto & RouteOption(ROUTE_OPTION_HTTP) != 0 { str += " http" } | ||||||
|  | 	if proto & RouteOption(ROUTE_OPTION_HTTPS) != 0 { str += " https" } | ||||||
|  | 	if str == "" { return str } | ||||||
|  | 	return str[1:] // remove the leading space | ||||||
|  | } | ||||||
|  |  | ||||||
| func dump_call_frame_and_exit(log Logger, req *http.Request, err interface{}) { | func dump_call_frame_and_exit(log Logger, req *http.Request, err interface{}) { | ||||||
| 	var buf []byte | 	var buf []byte | ||||||
| 	buf = make([]byte, 65536); buf = buf[:min(65536, runtime.Stack(buf, false))] | 	buf = make([]byte, 65536); buf = buf[:min(65536, runtime.Stack(buf, false))] | ||||||
|  | |||||||
							
								
								
									
										222
									
								
								hodu.pb.go
									
									
									
									
									
								
							
							
						
						
									
										222
									
								
								hodu.pb.go
									
									
									
									
									
								
							| @ -20,52 +20,64 @@ const ( | |||||||
| 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) | 	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ROUTE_PROTO int32 | type ROUTE_OPTION int32 | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	ROUTE_PROTO_TCP  ROUTE_PROTO = 0 | 	ROUTE_OPTION_UNSPEC ROUTE_OPTION = 0 | ||||||
| 	ROUTE_PROTO_TCP4 ROUTE_PROTO = 1 | 	ROUTE_OPTION_TCP    ROUTE_OPTION = 1 | ||||||
| 	ROUTE_PROTO_TCP6 ROUTE_PROTO = 2 | 	ROUTE_OPTION_TCP4   ROUTE_OPTION = 2 | ||||||
|  | 	ROUTE_OPTION_TCP6   ROUTE_OPTION = 4 | ||||||
|  | 	ROUTE_OPTION_TTY    ROUTE_OPTION = 8 | ||||||
|  | 	ROUTE_OPTION_HTTP   ROUTE_OPTION = 16 | ||||||
|  | 	ROUTE_OPTION_HTTPS  ROUTE_OPTION = 32 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Enum value maps for ROUTE_PROTO. | // Enum value maps for ROUTE_OPTION. | ||||||
| var ( | var ( | ||||||
| 	ROUTE_PROTO_name = map[int32]string{ | 	ROUTE_OPTION_name = map[int32]string{ | ||||||
| 		0: "TCP", | 		0:  "UNSPEC", | ||||||
| 		1: "TCP4", | 		1:  "TCP", | ||||||
| 		2: "TCP6", | 		2:  "TCP4", | ||||||
|  | 		4:  "TCP6", | ||||||
|  | 		8:  "TTY", | ||||||
|  | 		16: "HTTP", | ||||||
|  | 		32: "HTTPS", | ||||||
| 	} | 	} | ||||||
| 	ROUTE_PROTO_value = map[string]int32{ | 	ROUTE_OPTION_value = map[string]int32{ | ||||||
| 		"TCP":  0, | 		"UNSPEC": 0, | ||||||
| 		"TCP4": 1, | 		"TCP":    1, | ||||||
| 		"TCP6": 2, | 		"TCP4":   2, | ||||||
|  | 		"TCP6":   4, | ||||||
|  | 		"TTY":    8, | ||||||
|  | 		"HTTP":   16, | ||||||
|  | 		"HTTPS":  32, | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (x ROUTE_PROTO) Enum() *ROUTE_PROTO { | func (x ROUTE_OPTION) Enum() *ROUTE_OPTION { | ||||||
| 	p := new(ROUTE_PROTO) | 	p := new(ROUTE_OPTION) | ||||||
| 	*p = x | 	*p = x | ||||||
| 	return p | 	return p | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x ROUTE_PROTO) String() string { | func (x ROUTE_OPTION) String() string { | ||||||
| 	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) | 	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (ROUTE_PROTO) Descriptor() protoreflect.EnumDescriptor { | func (ROUTE_OPTION) Descriptor() protoreflect.EnumDescriptor { | ||||||
| 	return file_hodu_proto_enumTypes[0].Descriptor() | 	return file_hodu_proto_enumTypes[0].Descriptor() | ||||||
| } | } | ||||||
|  |  | ||||||
| func (ROUTE_PROTO) Type() protoreflect.EnumType { | func (ROUTE_OPTION) Type() protoreflect.EnumType { | ||||||
| 	return &file_hodu_proto_enumTypes[0] | 	return &file_hodu_proto_enumTypes[0] | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x ROUTE_PROTO) Number() protoreflect.EnumNumber { | func (x ROUTE_OPTION) Number() protoreflect.EnumNumber { | ||||||
| 	return protoreflect.EnumNumber(x) | 	return protoreflect.EnumNumber(x) | ||||||
| } | } | ||||||
|  |  | ||||||
| // Deprecated: Use ROUTE_PROTO.Descriptor instead. | // Deprecated: Use ROUTE_OPTION.Descriptor instead. | ||||||
| func (ROUTE_PROTO) EnumDescriptor() ([]byte, []int) { | func (ROUTE_OPTION) EnumDescriptor() ([]byte, []int) { | ||||||
| 	return file_hodu_proto_rawDescGZIP(), []int{0} | 	return file_hodu_proto_rawDescGZIP(), []int{0} | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -197,10 +209,23 @@ type RouteDesc struct { | |||||||
| 	sizeCache     protoimpl.SizeCache | 	sizeCache     protoimpl.SizeCache | ||||||
| 	unknownFields protoimpl.UnknownFields | 	unknownFields protoimpl.UnknownFields | ||||||
|  |  | ||||||
| 	RouteId       uint32      `protobuf:"varint,1,opt,name=RouteId,proto3" json:"RouteId,omitempty"` | 	RouteId uint32 `protobuf:"varint,1,opt,name=RouteId,proto3" json:"RouteId,omitempty"` | ||||||
| 	TargetAddrStr string      `protobuf:"bytes,2,opt,name=TargetAddrStr,proto3" json:"TargetAddrStr,omitempty"` | 	// C->S(ROUTE_START): client-side peer address | ||||||
| 	ServiceProto  ROUTE_PROTO `protobuf:"varint,3,opt,name=ServiceProto,proto3,enum=ROUTE_PROTO" json:"ServiceProto,omitempty"` | 	// S->C(ROUTE_STARTED): server-side listening address | ||||||
| 	ServiceNetStr string      `protobuf:"bytes,4,opt,name=ServiceNetStr,proto3" json:"ServiceNetStr,omitempty"` | 	TargetAddrStr string `protobuf:"bytes,2,opt,name=TargetAddrStr,proto3" json:"TargetAddrStr,omitempty"` | ||||||
|  | 	// C->S(ROUTE_START): desired listening option on the server-side(e.g. tcp, tcp4, tcp6) + | ||||||
|  | 	// | ||||||
|  | 	//	hint to the service-side peer(e.g. local) + | ||||||
|  | 	//	hint to the client-side peer(e.g. tty, http, https) | ||||||
|  | 	// | ||||||
|  | 	// S->C(ROUTE_STARTED): cloned as sent by C. | ||||||
|  | 	ServiceOption uint32 `protobuf:"varint,3,opt,name=ServiceOption,proto3" json:"ServiceOption,omitempty"` | ||||||
|  | 	// C->S(ROUTE_START): desired lisening address on the service-side | ||||||
|  | 	// S->C(ROUTE_STARTED): cloned as sent by C | ||||||
|  | 	ServiceAddrStr string `protobuf:"bytes,4,opt,name=ServiceAddrStr,proto3" json:"ServiceAddrStr,omitempty"` | ||||||
|  | 	// C->S(ROUTE_START): permitted network of server-side peers. | ||||||
|  | 	// S->C(ROUTE_STARTED): cloned as sent by C. | ||||||
|  | 	ServiceNetStr string `protobuf:"bytes,5,opt,name=ServiceNetStr,proto3" json:"ServiceNetStr,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x *RouteDesc) Reset() { | func (x *RouteDesc) Reset() { | ||||||
| @ -247,11 +272,18 @@ func (x *RouteDesc) GetTargetAddrStr() string { | |||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x *RouteDesc) GetServiceProto() ROUTE_PROTO { | func (x *RouteDesc) GetServiceOption() uint32 { | ||||||
| 	if x != nil { | 	if x != nil { | ||||||
| 		return x.ServiceProto | 		return x.ServiceOption | ||||||
| 	} | 	} | ||||||
| 	return ROUTE_PROTO_TCP | 	return 0 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (x *RouteDesc) GetServiceAddrStr() string { | ||||||
|  | 	if x != nil { | ||||||
|  | 		return x.ServiceAddrStr | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x *RouteDesc) GetServiceNetStr() string { | func (x *RouteDesc) GetServiceNetStr() string { | ||||||
| @ -499,60 +531,65 @@ var file_hodu_proto_rawDesc = []byte{ | |||||||
| 	0x53, 0x65, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, | 	0x53, 0x65, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, | ||||||
| 	0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, | 	0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, | ||||||
| 	0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x46, | 	0x0a, 0x05, 0x46, 0x6c, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x46, | ||||||
| 	0x6c, 0x61, 0x67, 0x73, 0x22, 0xa3, 0x01, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, | 	0x6c, 0x61, 0x67, 0x73, 0x22, 0xbf, 0x01, 0x0a, 0x09, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, | ||||||
| 	0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, | 	0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, | ||||||
| 	0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, | 	0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, | ||||||
| 	0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x02, 0x20, | 	0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x02, 0x20, | ||||||
| 	0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53, | 	0x01, 0x28, 0x09, 0x52, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x53, | ||||||
| 	0x74, 0x72, 0x12, 0x30, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, | 	0x74, 0x72, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, | ||||||
| 	0x74, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x52, 0x4f, 0x55, 0x54, 0x45, | 	0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, | ||||||
| 	0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x52, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, | 	0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, | ||||||
| 	0x72, 0x6f, 0x74, 0x6f, 0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, | 	0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, | ||||||
| 	0x65, 0x74, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, | 	0x52, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, | ||||||
| 	0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x53, 0x74, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x08, 0x50, | 	0x12, 0x24, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x65, 0x74, 0x53, 0x74, | ||||||
| 	0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, | 	0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, | ||||||
| 	0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, | 	0x4e, 0x65, 0x74, 0x53, 0x74, 0x72, 0x22, 0x86, 0x01, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44, | ||||||
| 	0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, | 	0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, | ||||||
| 	0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x6d, | 	0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, | ||||||
| 	0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, | 	0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50, | ||||||
| 	0x52, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x12, | 	0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x41, | ||||||
| 	0x22, 0x0a, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, | 	0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x52, 0x65, | ||||||
| 	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, | 	0x6d, 0x6f, 0x74, 0x65, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x12, 0x22, 0x0a, 0x0c, 0x4c, | ||||||
| 	0x53, 0x74, 0x72, 0x22, 0x50, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, | 	0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, | ||||||
| 	0x18, 0x0a, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, | 	0x09, 0x52, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x53, 0x74, 0x72, 0x22, | ||||||
| 	0x52, 0x07, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, | 	0x50, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x52, | ||||||
| 	0x72, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, | 	0x6f, 0x75, 0x74, 0x65, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x52, 0x6f, | ||||||
| 	0x64, 0x12, 0x12, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, | 	0x75, 0x74, 0x65, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x18, | ||||||
| 	0x04, 0x44, 0x61, 0x74, 0x61, 0x22, 0x95, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, | 	0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, | ||||||
| 	0x12, 0x20, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, | 	0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x44, 0x61, 0x74, | ||||||
| 	0x2e, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x52, 0x04, 0x4b, 0x69, | 	0x61, 0x22, 0x95, 0x01, 0x0a, 0x06, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x20, 0x0a, 0x04, | ||||||
| 	0x6e, 0x64, 0x12, 0x22, 0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, | 	0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0c, 0x2e, 0x50, 0x41, 0x43, | ||||||
| 	0x0b, 0x32, 0x0a, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, | 	0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x22, | ||||||
| 	0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03, | 	0x0a, 0x05, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, | ||||||
| 	0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x48, | 	0x52, 0x6f, 0x75, 0x74, 0x65, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x05, 0x52, 0x6f, 0x75, | ||||||
| 	0x00, 0x52, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, | 	0x74, 0x65, 0x12, 0x1f, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, | ||||||
| 	0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, | 	0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x65, 0x73, 0x63, 0x48, 0x00, 0x52, 0x04, 0x50, | ||||||
| 	0x48, 0x00, 0x52, 0x04, 0x44, 0x61, 0x74, 0x61, 0x42, 0x03, 0x0a, 0x01, 0x55, 0x2a, 0x2a, 0x0a, | 	0x65, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x04, 0x44, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, | ||||||
| 	0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x12, 0x07, 0x0a, 0x03, | 	0x0b, 0x32, 0x09, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x48, 0x00, 0x52, 0x04, | ||||||
| 	0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x34, 0x10, 0x01, 0x12, | 	0x44, 0x61, 0x74, 0x61, 0x42, 0x03, 0x0a, 0x01, 0x55, 0x2a, 0x55, 0x0a, 0x0c, 0x52, 0x4f, 0x55, | ||||||
| 	0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x36, 0x10, 0x02, 0x2a, 0xb5, 0x01, 0x0a, 0x0b, 0x50, 0x41, | 	0x54, 0x45, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x4e, 0x53, | ||||||
| 	0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, | 	0x50, 0x45, 0x43, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x08, | ||||||
| 	0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45, | 	0x0a, 0x04, 0x54, 0x43, 0x50, 0x34, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x43, 0x50, 0x36, | ||||||
| 	0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x4f, 0x55, 0x54, | 	0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x54, 0x59, 0x10, 0x08, 0x12, 0x08, 0x0a, 0x04, 0x48, | ||||||
| 	0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54, | 	0x54, 0x54, 0x50, 0x10, 0x10, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x20, | ||||||
| 	0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, | 	0x2a, 0xb5, 0x01, 0x0a, 0x0b, 0x50, 0x41, 0x43, 0x4b, 0x45, 0x54, 0x5f, 0x4b, 0x49, 0x4e, 0x44, | ||||||
| 	0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x04, 0x12, 0x10, | 	0x12, 0x0c, 0x0a, 0x08, 0x52, 0x45, 0x53, 0x45, 0x52, 0x56, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0f, | ||||||
| 	0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x05, | 	0x0a, 0x0b, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, | ||||||
| 	0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, | 	0x0e, 0x0a, 0x0a, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x02, 0x12, | ||||||
| 	0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, | 	0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x45, 0x44, | ||||||
| 	0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x45, 0x4f, 0x46, | 	0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x52, 0x4f, 0x55, 0x54, 0x45, 0x5f, 0x53, 0x54, 0x4f, 0x50, | ||||||
| 	0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x10, | 	0x50, 0x45, 0x44, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, 0x53, 0x54, | ||||||
| 	0x09, 0x32, 0x49, 0x0a, 0x04, 0x48, 0x6f, 0x64, 0x75, 0x12, 0x19, 0x0a, 0x07, 0x47, 0x65, 0x74, | 	0x41, 0x52, 0x54, 0x45, 0x44, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, 0x52, 0x5f, | ||||||
| 	0x53, 0x65, 0x65, 0x64, 0x12, 0x05, 0x2e, 0x53, 0x65, 0x65, 0x64, 0x1a, 0x05, 0x2e, 0x53, 0x65, | 	0x53, 0x54, 0x4f, 0x50, 0x50, 0x45, 0x44, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x45, 0x45, | ||||||
| 	0x65, 0x64, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x0c, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x74, | 	0x52, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x50, | ||||||
| 	0x72, 0x65, 0x61, 0x6d, 0x12, 0x07, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x1a, 0x07, 0x2e, | 	0x45, 0x45, 0x52, 0x5f, 0x45, 0x4f, 0x46, 0x10, 0x08, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x45, 0x45, | ||||||
| 	0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, | 	0x52, 0x5f, 0x44, 0x41, 0x54, 0x41, 0x10, 0x09, 0x32, 0x49, 0x0a, 0x04, 0x48, 0x6f, 0x64, 0x75, | ||||||
| 	0x2e, 0x2f, 0x68, 0x6f, 0x64, 0x75, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | 	0x12, 0x19, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x53, 0x65, 0x65, 0x64, 0x12, 0x05, 0x2e, 0x53, 0x65, | ||||||
|  | 	0x65, 0x64, 0x1a, 0x05, 0x2e, 0x53, 0x65, 0x65, 0x64, 0x22, 0x00, 0x12, 0x26, 0x0a, 0x0c, 0x50, | ||||||
|  | 	0x61, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x07, 0x2e, 0x50, 0x61, | ||||||
|  | 	0x63, 0x6b, 0x65, 0x74, 0x1a, 0x07, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x00, 0x28, | ||||||
|  | 	0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x68, 0x6f, 0x64, 0x75, 0x62, 0x06, 0x70, | ||||||
|  | 	0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| @ -570,7 +607,7 @@ func file_hodu_proto_rawDescGZIP() []byte { | |||||||
| var file_hodu_proto_enumTypes = make([]protoimpl.EnumInfo, 2) | var file_hodu_proto_enumTypes = make([]protoimpl.EnumInfo, 2) | ||||||
| var file_hodu_proto_msgTypes = make([]protoimpl.MessageInfo, 5) | var file_hodu_proto_msgTypes = make([]protoimpl.MessageInfo, 5) | ||||||
| var file_hodu_proto_goTypes = []any{ | var file_hodu_proto_goTypes = []any{ | ||||||
| 	(ROUTE_PROTO)(0),  // 0: ROUTE_PROTO | 	(ROUTE_OPTION)(0), // 0: ROUTE_OPTION | ||||||
| 	(PACKET_KIND)(0),  // 1: PACKET_KIND | 	(PACKET_KIND)(0),  // 1: PACKET_KIND | ||||||
| 	(*Seed)(nil),      // 2: Seed | 	(*Seed)(nil),      // 2: Seed | ||||||
| 	(*RouteDesc)(nil), // 3: RouteDesc | 	(*RouteDesc)(nil), // 3: RouteDesc | ||||||
| @ -579,20 +616,19 @@ var file_hodu_proto_goTypes = []any{ | |||||||
| 	(*Packet)(nil),    // 6: Packet | 	(*Packet)(nil),    // 6: Packet | ||||||
| } | } | ||||||
| var file_hodu_proto_depIdxs = []int32{ | var file_hodu_proto_depIdxs = []int32{ | ||||||
| 	0, // 0: RouteDesc.ServiceProto:type_name -> ROUTE_PROTO | 	1, // 0: Packet.Kind:type_name -> PACKET_KIND | ||||||
| 	1, // 1: Packet.Kind:type_name -> PACKET_KIND | 	3, // 1: Packet.Route:type_name -> RouteDesc | ||||||
| 	3, // 2: Packet.Route:type_name -> RouteDesc | 	4, // 2: Packet.Peer:type_name -> PeerDesc | ||||||
| 	4, // 3: Packet.Peer:type_name -> PeerDesc | 	5, // 3: Packet.Data:type_name -> PeerData | ||||||
| 	5, // 4: Packet.Data:type_name -> PeerData | 	2, // 4: Hodu.GetSeed:input_type -> Seed | ||||||
| 	2, // 5: Hodu.GetSeed:input_type -> Seed | 	6, // 5: Hodu.PacketStream:input_type -> Packet | ||||||
| 	6, // 6: Hodu.PacketStream:input_type -> Packet | 	2, // 6: Hodu.GetSeed:output_type -> Seed | ||||||
| 	2, // 7: Hodu.GetSeed:output_type -> Seed | 	6, // 7: Hodu.PacketStream:output_type -> Packet | ||||||
| 	6, // 8: Hodu.PacketStream:output_type -> Packet | 	6, // [6:8] is the sub-list for method output_type | ||||||
| 	7, // [7:9] is the sub-list for method output_type | 	4, // [4:6] is the sub-list for method input_type | ||||||
| 	5, // [5:7] is the sub-list for method input_type | 	4, // [4:4] is the sub-list for extension type_name | ||||||
| 	5, // [5:5] is the sub-list for extension type_name | 	4, // [4:4] is the sub-list for extension extendee | ||||||
| 	5, // [5:5] is the sub-list for extension extendee | 	0, // [0:4] is the sub-list for field type_name | ||||||
| 	0, // [0:5] is the sub-list for field type_name |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func init() { file_hodu_proto_init() } | func init() { file_hodu_proto_init() } | ||||||
|  | |||||||
							
								
								
									
										35
									
								
								hodu.proto
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								hodu.proto
									
									
									
									
									
								
							| @ -18,17 +18,36 @@ message Seed { | |||||||
| 	uint64 Flags = 2; | 	uint64 Flags = 2; | ||||||
| } | } | ||||||
|  |  | ||||||
| enum ROUTE_PROTO { | enum ROUTE_OPTION { | ||||||
| 	TCP    = 0; | 	UNSPEC = 0; | ||||||
| 	TCP4   = 1; | 	TCP    = 1; | ||||||
| 	TCP6   = 2; | 	TCP4   = 2; | ||||||
|  | 	TCP6   = 4; | ||||||
|  | 	TTY    = 8; | ||||||
|  | 	HTTP   = 16; | ||||||
|  | 	HTTPS  = 32; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| message RouteDesc { | message RouteDesc { | ||||||
| 	uint32      RouteId = 1; | 	uint32 RouteId = 1; | ||||||
| 	string      TargetAddrStr = 2; |  | ||||||
| 	ROUTE_PROTO ServiceProto = 3; | 	// C->S(ROUTE_START): client-side peer address | ||||||
| 	string      ServiceNetStr = 4; | 	// S->C(ROUTE_STARTED): server-side listening address | ||||||
|  | 	string TargetAddrStr = 2; | ||||||
|  |  | ||||||
|  | 	// C->S(ROUTE_START): desired listening option on the server-side(e.g. tcp, tcp4, tcp6) + | ||||||
|  | 	//                    hint to the service-side peer(e.g. local) + | ||||||
|  | 	//                    hint to the client-side peer(e.g. tty, http, https) | ||||||
|  | 	// S->C(ROUTE_STARTED): cloned as sent by C. | ||||||
|  | 	uint32 ServiceOption = 3; | ||||||
|  |  | ||||||
|  | 	// C->S(ROUTE_START): desired lisening address on the service-side | ||||||
|  | 	// S->C(ROUTE_STARTED): cloned as sent by C | ||||||
|  | 	string ServiceAddrStr = 4; | ||||||
|  |  | ||||||
|  | 	// C->S(ROUTE_START): permitted network of server-side peers. | ||||||
|  | 	// S->C(ROUTE_STARTED): cloned as sent by C. | ||||||
|  | 	string ServiceNetStr = 5; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| message PeerDesc { | message PeerDesc { | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								packet.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								packet.go
									
									
									
									
									
								
							| @ -1,31 +1,32 @@ | |||||||
| package hodu | package hodu | ||||||
|  |  | ||||||
| type ConnId  uint64 | type ConnId     uint64 | ||||||
| type RouteId uint32 // keep this in sync with the type of RouteId in hodu.proto | type RouteId    uint32 // keep this in sync with the type of RouteId in hodu.proto | ||||||
| type PeerId  uint32 // keep this in sync with the type of RouteId in hodu.proto | type PeerId     uint32 // keep this in sync with the type of RouteId in hodu.proto | ||||||
|  | type RouteOption uint32 | ||||||
|  |  | ||||||
| func MakeRouteStartPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet { | func MakeRouteStartPacket(route_id RouteId, proto RouteOption, ptc_addr string, svc_addr string, svc_net string) *Packet { | ||||||
| 	return &Packet{ | 	return &Packet{ | ||||||
| 		Kind: PACKET_KIND_ROUTE_START, | 		Kind: PACKET_KIND_ROUTE_START, | ||||||
| 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}} | 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: ptc_addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}} | ||||||
| } | } | ||||||
|  |  | ||||||
| func MakeRouteStopPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet { | func MakeRouteStopPacket(route_id RouteId, proto RouteOption, ptc_addr string, svc_addr string, svc_net string) *Packet { | ||||||
| 	return &Packet{ | 	return &Packet{ | ||||||
| 		Kind: PACKET_KIND_ROUTE_STOP, | 		Kind: PACKET_KIND_ROUTE_STOP, | ||||||
| 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}} | 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: ptc_addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}} | ||||||
| } | } | ||||||
|  |  | ||||||
| func MakeRouteStartedPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet { | func MakeRouteStartedPacket(route_id RouteId, proto RouteOption, addr string, svc_addr string, svc_net string) *Packet { | ||||||
| 	// the connection from a peer to the server has been established | 	// the connection from a peer to the server has been established | ||||||
| 	return &Packet{Kind: PACKET_KIND_ROUTE_STARTED, | 	return &Packet{Kind: PACKET_KIND_ROUTE_STARTED, | ||||||
| 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}} | 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}} | ||||||
| } | } | ||||||
|  |  | ||||||
| func MakeRouteStoppedPacket(route_id RouteId, proto ROUTE_PROTO, addr string, svcnet string) *Packet { | func MakeRouteStoppedPacket(route_id RouteId, proto RouteOption, addr string, svc_addr string, svc_net string) *Packet { | ||||||
| 	// the connection from a peer to the server has been established | 	// the connection from a peer to the server has been established | ||||||
| 	return &Packet{Kind: PACKET_KIND_ROUTE_STOPPED, | 	return &Packet{Kind: PACKET_KIND_ROUTE_STOPPED, | ||||||
| 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceProto: proto, TargetAddrStr: addr, ServiceNetStr: svcnet}}} | 		U: &Packet_Route{Route: &RouteDesc{RouteId: uint32(route_id), ServiceOption: uint32(proto), TargetAddrStr: addr, ServiceAddrStr: svc_addr, ServiceNetStr: svc_net}}} | ||||||
| } | } | ||||||
|  |  | ||||||
| func MakePeerStartedPacket(route_id RouteId, peer_id PeerId, remote_addr string, local_addr string) *Packet { | func MakePeerStartedPacket(route_id RouteId, peer_id PeerId, remote_addr string, local_addr string) *Packet { | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import "encoding/json" | |||||||
| import "net/http" | import "net/http" | ||||||
| import "runtime" | import "runtime" | ||||||
| import "strconv" | import "strconv" | ||||||
|  | import "unsafe" | ||||||
|  |  | ||||||
| type json_out_server_conn struct { | type json_out_server_conn struct { | ||||||
| 	Id ConnId `json:"id"` | 	Id ConnId `json:"id"` | ||||||
| @ -15,9 +16,9 @@ type json_out_server_conn struct { | |||||||
| type json_out_server_route struct { | type json_out_server_route struct { | ||||||
| 	Id RouteId `json:"id"` | 	Id RouteId `json:"id"` | ||||||
| 	ClientPeerAddr string `json:"client-peer-addr"` | 	ClientPeerAddr string `json:"client-peer-addr"` | ||||||
| 	ServerPeerListenAddr string `json:"server-peer-listen-addr"` | 	ServerPeerOption string `json:"server-peer-option"` | ||||||
| 	ServerPeerNet string `json:"server-peer-net"` | 	ServerPeerServiceAddr string `json:"server-peer-service-addr"` // actual listening address | ||||||
| 	ServerPeerProto ROUTE_PROTO `json:"server-peer-proto"` | 	ServerPeerServiceNet string `json:"server-peer-service-net"` | ||||||
| } | } | ||||||
|  |  | ||||||
| type json_out_server_stats struct { | type json_out_server_stats struct { | ||||||
| @ -94,9 +95,9 @@ func (ctl *server_ctl_server_conns) ServeHTTP(w http.ResponseWriter, req *http.R | |||||||
| 					jsp = append(jsp, json_out_server_route{ | 					jsp = append(jsp, json_out_server_route{ | ||||||
| 						Id: r.id, | 						Id: r.id, | ||||||
| 						ClientPeerAddr: r.ptc_addr, | 						ClientPeerAddr: r.ptc_addr, | ||||||
| 						ServerPeerListenAddr: r.svc_addr.String(), | 						ServerPeerServiceAddr: r.svc_addr.String(), | ||||||
| 						ServerPeerNet: r.svc_permitted_net.String(), | 						ServerPeerServiceNet: r.svc_permitted_net.String(), | ||||||
| 						ServerPeerProto: r.svc_proto, | 						ServerPeerOption: r.svc_option.string(), | ||||||
| 					}) | 					}) | ||||||
| 				} | 				} | ||||||
| 				js = append(js, json_out_server_conn{ | 				js = append(js, json_out_server_conn{ | ||||||
| @ -176,9 +177,9 @@ func (ctl *server_ctl_server_conns_id) ServeHTTP(w http.ResponseWriter, req *htt | |||||||
| 				jsp = append(jsp, json_out_server_route{ | 				jsp = append(jsp, json_out_server_route{ | ||||||
| 					Id: r.id, | 					Id: r.id, | ||||||
| 					ClientPeerAddr: r.ptc_addr, | 					ClientPeerAddr: r.ptc_addr, | ||||||
| 					ServerPeerListenAddr: r.svc_addr.String(), | 					ServerPeerServiceAddr: r.svc_addr.String(), | ||||||
| 					ServerPeerNet: r.svc_permitted_net.String(), | 					ServerPeerServiceNet: r.svc_permitted_net.String(), | ||||||
| 					ServerPeerProto: r.svc_proto, | 					ServerPeerOption: r.svc_option.string(), | ||||||
| 				}) | 				}) | ||||||
| 			} | 			} | ||||||
| 			js = &json_out_server_conn{ | 			js = &json_out_server_conn{ | ||||||
| @ -256,9 +257,9 @@ func (ctl *server_ctl_server_conns_id_routes) ServeHTTP(w http.ResponseWriter, r | |||||||
| 				jsp = append(jsp, json_out_server_route{ | 				jsp = append(jsp, json_out_server_route{ | ||||||
| 					Id: r.id, | 					Id: r.id, | ||||||
| 					ClientPeerAddr: r.ptc_addr, | 					ClientPeerAddr: r.ptc_addr, | ||||||
| 					ServerPeerListenAddr: r.svc_addr.String(), | 					ServerPeerServiceAddr: r.svc_addr.String(), | ||||||
| 					ServerPeerNet: r.svc_permitted_net.String(), | 					ServerPeerServiceNet: r.svc_permitted_net.String(), | ||||||
| 					ServerPeerProto: r.svc_proto, | 					ServerPeerOption: r.svc_option.string(), | ||||||
| 				}) | 				}) | ||||||
| 			} | 			} | ||||||
| 			cts.route_mtx.Unlock() | 			cts.route_mtx.Unlock() | ||||||
| @ -309,13 +310,13 @@ func (ctl *server_ctl_server_conns_id_routes_id) ServeHTTP(w http.ResponseWriter | |||||||
| 	conn_id = req.PathValue("conn_id") | 	conn_id = req.PathValue("conn_id") | ||||||
| 	route_id = req.PathValue("route_id") | 	route_id = req.PathValue("route_id") | ||||||
|  |  | ||||||
| 	conn_nid, err = strconv.ParseUint(conn_id, 10, 32) | 	conn_nid, err = strconv.ParseUint(conn_id, 10, int(unsafe.Sizeof(conn_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong connection id - " + conn_id}); err != nil { goto oops } | ||||||
| 		goto done | 		goto done | ||||||
| 	} | 	} | ||||||
| 	route_nid, err = strconv.ParseUint(route_id, 10, 32) | 	route_nid, err = strconv.ParseUint(route_id, 10, int(unsafe.Sizeof(route_nid) * 8)) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | 		status_code = http.StatusBadRequest; w.WriteHeader(status_code) | ||||||
| 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | 		if err = je.Encode(json_errmsg{Text: "wrong route id - " + route_id}); err != nil { goto oops } | ||||||
| @ -342,9 +343,9 @@ func (ctl *server_ctl_server_conns_id_routes_id) ServeHTTP(w http.ResponseWriter | |||||||
| 			err = je.Encode(json_out_server_route{ | 			err = je.Encode(json_out_server_route{ | ||||||
| 				Id: r.id, | 				Id: r.id, | ||||||
| 				ClientPeerAddr: r.ptc_addr, | 				ClientPeerAddr: r.ptc_addr, | ||||||
| 				ServerPeerListenAddr: r.svc_addr.String(), | 				ServerPeerServiceAddr: r.svc_addr.String(), | ||||||
| 				ServerPeerNet: r.svc_permitted_net.String(), | 				ServerPeerServiceNet: r.svc_permitted_net.String(), | ||||||
| 				ServerPeerProto: r.svc_proto, | 				ServerPeerOption: r.svc_option.string(), | ||||||
| 			}) | 			}) | ||||||
| 			if err != nil { goto oops } | 			if err != nil { goto oops } | ||||||
|  |  | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package hodu | |||||||
| import "errors" | import "errors" | ||||||
| import "io" | import "io" | ||||||
| import "net" | import "net" | ||||||
|  | import "strings" | ||||||
| import "sync" | import "sync" | ||||||
| import "sync/atomic" | import "sync/atomic" | ||||||
| import "time" | import "time" | ||||||
| @ -90,7 +91,7 @@ wait_for_started: | |||||||
| 	for { | 	for { | ||||||
| 		n, err = spc.conn.Read(buf[:]) | 		n, err = spc.conn.Read(buf[:]) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if errors.Is(err, io.EOF) { | 			if errors.Is(err, io.EOF) || strings.Contains(err.Error(), "use of closed network connection") { // i don't like this way to check this error. | ||||||
| 				err = pss.Send(MakePeerEofPacket(spc.route.id, spc.conn_id)) | 				err = pss.Send(MakePeerEofPacket(spc.route.id, spc.conn_id)) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					spc.route.cts.svr.log.Write(spc.route.cts.sid, LOG_ERROR, | 					spc.route.cts.svr.log.Write(spc.route.cts.sid, LOG_ERROR, | ||||||
|  | |||||||
							
								
								
									
										243
									
								
								server.go
									
									
									
									
									
								
							
							
						
						
									
										243
									
								
								server.go
									
									
									
									
									
								
							| @ -6,7 +6,7 @@ import "errors" | |||||||
| import "fmt" | import "fmt" | ||||||
| import "io" | import "io" | ||||||
| import "log" | import "log" | ||||||
| import "math/rand" | //import "math/rand" | ||||||
| import "net" | import "net" | ||||||
| import "net/http" | import "net/http" | ||||||
| import "net/netip" | import "net/netip" | ||||||
| @ -28,10 +28,10 @@ type ServerConnMap = map[ConnId]*ServerConn | |||||||
| type ServerRouteMap = map[RouteId]*ServerRoute | type ServerRouteMap = map[RouteId]*ServerRoute | ||||||
| type ServerPeerConnMap = map[PeerId]*ServerPeerConn | type ServerPeerConnMap = map[PeerId]*ServerPeerConn | ||||||
|  |  | ||||||
|  |  | ||||||
| type Server struct { | type Server struct { | ||||||
| 	ctx             context.Context | 	ctx             context.Context | ||||||
| 	ctx_cancel      context.CancelFunc | 	ctx_cancel      context.CancelFunc | ||||||
|  | 	pxytlscfg       *tls.Config | ||||||
| 	ctltlscfg       *tls.Config | 	ctltlscfg       *tls.Config | ||||||
| 	rpctlscfg       *tls.Config | 	rpctlscfg       *tls.Config | ||||||
|  |  | ||||||
| @ -42,6 +42,10 @@ type Server struct { | |||||||
| 	ext_mtx         sync.Mutex | 	ext_mtx         sync.Mutex | ||||||
| 	ext_svcs        []Service | 	ext_svcs        []Service | ||||||
|  |  | ||||||
|  | 	pxy_addr        []string | ||||||
|  | 	pxy_mux         *http.ServeMux | ||||||
|  | 	pxy             []*http.Server // proxy server | ||||||
|  |  | ||||||
| 	ctl_addr        []string | 	ctl_addr        []string | ||||||
| 	ctl_prefix      string | 	ctl_prefix      string | ||||||
| 	ctl_mux         *http.ServeMux | 	ctl_mux         *http.ServeMux | ||||||
| @ -91,10 +95,11 @@ type ServerConn struct { | |||||||
|  |  | ||||||
| type ServerRoute struct { | type ServerRoute struct { | ||||||
| 	cts        *ServerConn | 	cts        *ServerConn | ||||||
| 	l          *net.TCPListener | 	svc_l      *net.TCPListener | ||||||
| 	svc_addr   *net.TCPAddr // listening address | 	svc_addr   *net.TCPAddr // actual listening address | ||||||
|  | 	svc_requested_addr string | ||||||
| 	svc_permitted_net netip.Prefix | 	svc_permitted_net netip.Prefix | ||||||
| 	svc_proto   ROUTE_PROTO | 	svc_option  RouteOption | ||||||
|  |  | ||||||
| 	ptc_addr    string | 	ptc_addr    string | ||||||
| 	id          RouteId | 	id          RouteId | ||||||
| @ -136,7 +141,7 @@ func (g *GuardedPacketStreamServer) Context() context.Context { | |||||||
|  |  | ||||||
| // ------------------------------------ | // ------------------------------------ | ||||||
|  |  | ||||||
| func NewServerRoute(cts *ServerConn, id RouteId, proto ROUTE_PROTO, ptc_addr string, svc_permitted_net string) (*ServerRoute, error) { | func NewServerRoute(cts *ServerConn, id RouteId, option RouteOption, ptc_addr string, svc_requested_addr string, svc_permitted_net string) (*ServerRoute, error) { | ||||||
| 	var r ServerRoute | 	var r ServerRoute | ||||||
| 	var l *net.TCPListener | 	var l *net.TCPListener | ||||||
| 	var svcaddr *net.TCPAddr | 	var svcaddr *net.TCPAddr | ||||||
| @ -144,31 +149,34 @@ func NewServerRoute(cts *ServerConn, id RouteId, proto ROUTE_PROTO, ptc_addr str | |||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	if svc_permitted_net != "" { | 	if svc_permitted_net != "" { | ||||||
|  | 		// parse the permitted network before creating a listener. | ||||||
|  | 		// the listener opened doesn't have to be closed when parsing fails. | ||||||
| 		svcnet, err = netip.ParsePrefix(svc_permitted_net) | 		svcnet, err = netip.ParsePrefix(svc_permitted_net) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil , err | 			return nil , err | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	l, svcaddr, err = cts.make_route_listener(id, proto) | 	l, svcaddr, err = cts.make_route_listener(id, option, svc_requested_addr) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if svc_permitted_net == "" { | 	if svc_permitted_net == "" { | ||||||
| 		if svcaddr.IP.To4() != nil { | 		if svcaddr.IP.To4() != nil { | ||||||
| 			svcnet, _ = netip.ParsePrefix("0.0.0.0/0") | 			svcnet = IPV4_PREFIX_ZERO | ||||||
| 		} else { | 		} else { | ||||||
| 			svcnet, _ = netip.ParsePrefix("::/0") | 			svcnet = IPV6_PREFIX_ZERO | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	r.cts = cts | 	r.cts = cts | ||||||
| 	r.id = id | 	r.id = id | ||||||
| 	r.l = l | 	r.svc_l = l | ||||||
| 	r.svc_addr = svcaddr | 	r.svc_addr = svcaddr | ||||||
|  | 	r.svc_requested_addr = svc_requested_addr | ||||||
| 	r.svc_permitted_net = svcnet | 	r.svc_permitted_net = svcnet | ||||||
| 	r.svc_proto = proto | 	r.svc_option = option | ||||||
|  |  | ||||||
| 	r.ptc_addr = ptc_addr | 	r.ptc_addr = ptc_addr | ||||||
| 	r.pts_limit = PTS_LIMIT | 	r.pts_limit = PTS_LIMIT | ||||||
| @ -230,7 +238,7 @@ func (r *ServerRoute) RunTask(wg *sync.WaitGroup) { | |||||||
| 	defer wg.Done() | 	defer wg.Done() | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
| 		conn, err = r.l.AcceptTCP() | 		conn, err = r.svc_l.AcceptTCP() // this call is blocking... | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			if errors.Is(err, net.ErrClosed) { | 			if errors.Is(err, net.ErrClosed) { | ||||||
| 				r.cts.svr.log.Write(r.cts.sid, LOG_INFO, "Server-side peer listener closed on route(%d)", r.id) | 				r.cts.svr.log.Write(r.cts.sid, LOG_INFO, "Server-side peer listener closed on route(%d)", r.id) | ||||||
| @ -280,7 +288,7 @@ func (r *ServerRoute) ReqStop() { | |||||||
| 			pts.ReqStop() | 			pts.ReqStop() | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		r.l.Close() | 		r.svc_l.Close() | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -300,52 +308,53 @@ func (r *ServerRoute) ReportEvent(pts_id PeerId, event_type PACKET_KIND, event_d | |||||||
| } | } | ||||||
| // ------------------------------------ | // ------------------------------------ | ||||||
|  |  | ||||||
| func (cts *ServerConn) make_route_listener(id RouteId, proto ROUTE_PROTO) (*net.TCPListener, *net.TCPAddr, error) { | func (cts *ServerConn) make_route_listener(id RouteId, option RouteOption, svc_requested_addr string) (*net.TCPListener, *net.TCPAddr, error) { | ||||||
| 	var l *net.TCPListener | 	var l *net.TCPListener | ||||||
| 	var err error |  | ||||||
| 	var svcaddr *net.TCPAddr | 	var svcaddr *net.TCPAddr | ||||||
| 	var port int |  | ||||||
| 	var tries int = 0 |  | ||||||
| 	var nw string | 	var nw string | ||||||
| 	var ip string | 	var err error | ||||||
|  |  | ||||||
| 	switch proto { | 	if svc_requested_addr != "" { | ||||||
| 		case ROUTE_PROTO_TCP: | 		var ap netip.AddrPort | ||||||
|  |  | ||||||
|  | 		ap, err = netip.ParseAddrPort(svc_requested_addr) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, nil, fmt.Errorf("invalid service address %s - %s", svc_requested_addr, err.Error()) | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		svcaddr = &net.TCPAddr{IP: ap.Addr().AsSlice(), Port: int(ap.Port())} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if option & RouteOption(ROUTE_OPTION_TCP) != 0 { | ||||||
| 			nw = "tcp" | 			nw = "tcp" | ||||||
| 			ip = "" | 			if svcaddr == nil { | ||||||
| 		case ROUTE_PROTO_TCP4: | 				svcaddr = &net.TCPAddr{Port: 0} // port 0 for automatic assignment. | ||||||
| 			nw = "tcp4" |  | ||||||
| 			ip = "0.0.0.0" |  | ||||||
| 		case ROUTE_PROTO_TCP6: |  | ||||||
| 			nw = "tcp6" |  | ||||||
| 			ip = "[::]" |  | ||||||
| 		default: |  | ||||||
| 			return nil, nil, fmt.Errorf("invalid protocol number %d", proto) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	for { |  | ||||||
| 		port = rand.Intn(65535-32000+1) + 32000 // TODO: configurable port range |  | ||||||
|  |  | ||||||
| 		svcaddr, err = net.ResolveTCPAddr(nw, fmt.Sprintf("%s:%d", ip, port)) |  | ||||||
| 		if err == nil { |  | ||||||
| 			l, err = net.ListenTCP(nw, svcaddr) // make the binding address configurable. support multiple binding addresses??? |  | ||||||
| 			if err == nil { |  | ||||||
| 				cts.svr.log.Write(cts.sid, LOG_DEBUG, "Route(%d) listening on %d", id, port) |  | ||||||
| 				return l, svcaddr, nil |  | ||||||
| 			} | 			} | ||||||
| 		} | 	} else if option & RouteOption(ROUTE_OPTION_TCP4) != 0 { | ||||||
|  | 			nw = "tcp4" | ||||||
| 		tries++ | 			if svcaddr == nil { | ||||||
| 		if tries >= 1000 { | 				svcaddr = &net.TCPAddr{IP: net.IPv4zero, Port: 0} // port 0 for automatic assignment. | ||||||
| 			err = fmt.Errorf("unable to allocate port") | 			} | ||||||
| 			break | 	} else if option & RouteOption(ROUTE_OPTION_TCP6) != 0 { | ||||||
| 		} | 			nw = "tcp6" | ||||||
|  | 			if svcaddr == nil { | ||||||
|  | 				svcaddr = &net.TCPAddr{IP: net.IPv6zero, Port: 0} // port 0 for automatic assignment. | ||||||
|  | 			} | ||||||
|  | 	} else { | ||||||
|  | 			return nil, nil, fmt.Errorf("invalid route option value %d(%s)", option, option.string()) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil, nil, err | 	l, err = net.ListenTCP(nw, svcaddr) // make the binding address configurable. support multiple binding addresses??? | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, nil, err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	svcaddr = l.Addr().(*net.TCPAddr) | ||||||
|  | 	cts.svr.log.Write(cts.sid, LOG_DEBUG, "Route(%d) listening on %s", id, svcaddr.String()) | ||||||
|  | 	return l, svcaddr, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (cts *ServerConn) AddNewServerRoute(route_id RouteId, proto ROUTE_PROTO, ptc_addr string, svc_permitted_net string) (*ServerRoute, error) { | func (cts *ServerConn) AddNewServerRoute(route_id RouteId, proto RouteOption, ptc_addr string, svc_requested_addr string, svc_permitted_net string) (*ServerRoute, error) { | ||||||
| 	var r *ServerRoute | 	var r *ServerRoute | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| @ -358,7 +367,7 @@ func (cts *ServerConn) AddNewServerRoute(route_id RouteId, proto ROUTE_PROTO, pt | |||||||
| 		cts.route_mtx.Unlock() | 		cts.route_mtx.Unlock() | ||||||
| 		return nil, fmt.Errorf("existent route id - %d", route_id) | 		return nil, fmt.Errorf("existent route id - %d", route_id) | ||||||
| 	} | 	} | ||||||
| 	r, err = NewServerRoute(cts, route_id, proto, ptc_addr, svc_permitted_net) | 	r, err = NewServerRoute(cts, route_id, proto, ptc_addr, svc_requested_addr, svc_permitted_net) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		cts.route_mtx.Unlock() | 		cts.route_mtx.Unlock() | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @ -478,34 +487,34 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) { | |||||||
| 				if ok { | 				if ok { | ||||||
| 					var r *ServerRoute | 					var r *ServerRoute | ||||||
|  |  | ||||||
| 					r, err = cts.AddNewServerRoute(RouteId(x.Route.RouteId), x.Route.ServiceProto, x.Route.TargetAddrStr, x.Route.ServiceNetStr) | 					r, err = cts.AddNewServerRoute(RouteId(x.Route.RouteId), RouteOption(x.Route.ServiceOption), x.Route.TargetAddrStr, x.Route.ServiceAddrStr, x.Route.ServiceNetStr) | ||||||
| 					if err != nil { | 					if err != nil { | ||||||
| 						cts.svr.log.Write(cts.sid, LOG_ERROR, | 						cts.svr.log.Write(cts.sid, LOG_ERROR, | ||||||
| 							"Failed to add route(%d,%s) for %s - %s", | 							"Failed to add route(%d,%s) for %s - %s", | ||||||
| 							x.Route.RouteId, x.Route.TargetAddrStr, cts.remote_addr, err.Error()) | 							x.Route.RouteId, x.Route.TargetAddrStr, cts.remote_addr, err.Error()) | ||||||
|  |  | ||||||
| 						err = cts.pss.Send(MakeRouteStoppedPacket(RouteId(x.Route.RouteId), x.Route.ServiceProto, x.Route.TargetAddrStr, x.Route.ServiceNetStr)) | 						err = cts.pss.Send(MakeRouteStoppedPacket(RouteId(x.Route.RouteId), RouteOption(x.Route.ServiceOption), x.Route.TargetAddrStr, x.Route.ServiceAddrStr, x.Route.ServiceNetStr)) | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							cts.svr.log.Write(cts.sid, LOG_ERROR, | 							cts.svr.log.Write(cts.sid, LOG_ERROR, | ||||||
| 								"Failed to send route_stopped event(%d,%s,%v,%s) to client %s - %s", | 								"Failed to send route_stopped event(%d,%s,%v,%s) to client %s - %s", | ||||||
| 								x.Route.RouteId, x.Route.TargetAddrStr,  x.Route.ServiceProto, x.Route.ServiceNetStr, cts.remote_addr, err.Error()) | 								x.Route.RouteId, x.Route.TargetAddrStr,  x.Route.ServiceOption, x.Route.ServiceNetStr, cts.remote_addr, err.Error()) | ||||||
| 							goto done | 							goto done | ||||||
| 						} else { | 						} else { | ||||||
| 							cts.svr.log.Write(cts.sid, LOG_DEBUG, | 							cts.svr.log.Write(cts.sid, LOG_DEBUG, | ||||||
| 								"Sent route_stopped event(%d,%s,%v,%s) to client %s", | 								"Sent route_stopped event(%d,%s,%v,%s) to client %s", | ||||||
| 								x.Route.RouteId, x.Route.TargetAddrStr,  x.Route.ServiceProto, x.Route.ServiceNetStr, cts.remote_addr) | 								x.Route.RouteId, x.Route.TargetAddrStr,  x.Route.ServiceOption, x.Route.ServiceNetStr, cts.remote_addr) | ||||||
| 						} | 						} | ||||||
|  |  | ||||||
| 					} else { | 					} else { | ||||||
| 						cts.svr.log.Write(cts.sid, LOG_INFO, | 						cts.svr.log.Write(cts.sid, LOG_INFO, | ||||||
| 							"Added route(%d,%s,%s,%v,%v) for client %s to cts(%d)", | 							"Added route(%d,%s,%s,%v,%v) for client %s to cts(%d)", | ||||||
| 							r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net, cts.remote_addr, cts.id) | 							r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net, cts.remote_addr, cts.id) | ||||||
| 						err = cts.pss.Send(MakeRouteStartedPacket(r.id, r.svc_proto, r.svc_addr.String(), r.svc_permitted_net.String())) | 						err = cts.pss.Send(MakeRouteStartedPacket(r.id, r.svc_option, r.svc_addr.String(), r.svc_requested_addr, r.svc_permitted_net.String())) | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							r.ReqStop() | 							r.ReqStop() | ||||||
| 							cts.svr.log.Write(cts.sid, LOG_ERROR, | 							cts.svr.log.Write(cts.sid, LOG_ERROR, | ||||||
| 								"Failed to send route_started event(%d,%s,%s,%s%v,%v) to client %s - %s", | 								"Failed to send route_started event(%d,%s,%s,%s%v,%v) to client %s - %s", | ||||||
| 								r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net, cts.remote_addr, err.Error()) | 								r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net, cts.remote_addr, err.Error()) | ||||||
| 							goto done | 							goto done | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| @ -529,13 +538,13 @@ func (cts *ServerConn) receive_from_stream(wg *sync.WaitGroup) { | |||||||
| 					} else { | 					} else { | ||||||
| 						cts.svr.log.Write(cts.sid, LOG_ERROR, | 						cts.svr.log.Write(cts.sid, LOG_ERROR, | ||||||
| 							"Deleted route(%d,%s,%s,%v,%v) for client %s", | 							"Deleted route(%d,%s,%s,%v,%v) for client %s", | ||||||
| 							r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net.String(), cts.remote_addr) | 							r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net.String(), cts.remote_addr) | ||||||
| 						err = cts.pss.Send(MakeRouteStoppedPacket(r.id, r.svc_proto, r.ptc_addr, r.svc_permitted_net.String())) | 						err = cts.pss.Send(MakeRouteStoppedPacket(r.id, r.svc_option, r.ptc_addr, r.svc_requested_addr, r.svc_permitted_net.String())) | ||||||
| 						if err != nil { | 						if err != nil { | ||||||
| 							r.ReqStop() | 							r.ReqStop() | ||||||
| 							cts.svr.log.Write(cts.sid, LOG_ERROR, | 							cts.svr.log.Write(cts.sid, LOG_ERROR, | ||||||
| 								"Failed to send route_stopped event(%d,%s,%s,%v.%v) to client %s - %s", | 								"Failed to send route_stopped event(%d,%s,%s,%v.%v) to client %s - %s", | ||||||
| 								r.id, r.ptc_addr, r.svc_addr.String(), r.svc_proto, r.svc_permitted_net.String(), cts.remote_addr, err.Error()) | 								r.id, r.ptc_addr, r.svc_addr.String(), r.svc_option, r.svc_permitted_net.String(), cts.remote_addr, err.Error()) | ||||||
| 							goto done | 							goto done | ||||||
| 						} | 						} | ||||||
| 					} | 					} | ||||||
| @ -846,18 +855,18 @@ func unaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServ | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| type server_ctl_log_writer struct { | type server_http_log_writer struct { | ||||||
| 	svr *Server | 	svr *Server | ||||||
| } | } | ||||||
|  |  | ||||||
| func (hlw *server_ctl_log_writer) Write(p []byte) (n int, err error) { | func (hlw *server_http_log_writer) Write(p []byte) (n int, err error) { | ||||||
| 	// the standard http.Server always requires *log.Logger | 	// the standard http.Server always requires *log.Logger | ||||||
| 	// use this iowriter to create a logger to pass it to the http server. | 	// use this iowriter to create a logger to pass it to the http server. | ||||||
| 	hlw.svr.log.Write("", LOG_INFO, string(p)) | 	hlw.svr.log.Write("", LOG_INFO, string(p)) | ||||||
| 	return len(p), nil | 	return len(p), nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs []string, ctl_prefix string, ctltlscfg *tls.Config, rpctlscfg *tls.Config, rpc_max int, peer_max int) (*Server, error) { | func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs []string, pxy_addrs []string, ctl_prefix string, ctltlscfg *tls.Config, rpctlscfg *tls.Config, pxytlscfg *tls.Config, rpc_max int, peer_max int) (*Server, error) { | ||||||
| 	var s Server | 	var s Server | ||||||
| 	var l *net.TCPListener | 	var l *net.TCPListener | ||||||
| 	var rpcaddr *net.TCPAddr | 	var rpcaddr *net.TCPAddr | ||||||
| @ -893,6 +902,7 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs | |||||||
|  |  | ||||||
| 	s.ctltlscfg = ctltlscfg | 	s.ctltlscfg = ctltlscfg | ||||||
| 	s.rpctlscfg = rpctlscfg | 	s.rpctlscfg = rpctlscfg | ||||||
|  | 	s.pxytlscfg = pxytlscfg | ||||||
| 	s.ext_svcs = make([]Service, 0, 1) | 	s.ext_svcs = make([]Service, 0, 1) | ||||||
| 	s.pts_limit = peer_max | 	s.pts_limit = peer_max | ||||||
| 	s.cts_limit = rpc_max | 	s.cts_limit = rpc_max | ||||||
| @ -916,10 +926,16 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs | |||||||
| 	s.rpc_svr = grpc.NewServer(opts...) | 	s.rpc_svr = grpc.NewServer(opts...) | ||||||
| 	RegisterHoduServer(s.rpc_svr, &s) | 	RegisterHoduServer(s.rpc_svr, &s) | ||||||
|  |  | ||||||
| 	s.ctl_prefix = ctl_prefix | 	// --------------------------------------------------------- | ||||||
|  |  | ||||||
|  | 	hs_log = log.New(&server_http_log_writer{svr: &s}, "", 0); | ||||||
|  |  | ||||||
|  | 	// --------------------------------------------------------- | ||||||
|  |  | ||||||
|  | 	s.ctl_prefix = ctl_prefix | ||||||
| 	s.ctl_mux = http.NewServeMux() | 	s.ctl_mux = http.NewServeMux() | ||||||
| 	cwd, _ = os.Getwd() | 	cwd, _ = os.Getwd() // TODO: | ||||||
|  |  | ||||||
| 	s.ctl_mux.Handle(s.ctl_prefix + "/ui/", http.StripPrefix(s.ctl_prefix, http.FileServer(http.Dir(cwd)))) // TODO: proper directory. it must not use the current working directory... | 	s.ctl_mux.Handle(s.ctl_prefix + "/ui/", http.StripPrefix(s.ctl_prefix, http.FileServer(http.Dir(cwd)))) // TODO: proper directory. it must not use the current working directory... | ||||||
| 	s.ctl_mux.Handle(s.ctl_prefix + "/ws/tty", new_server_ctl_ws_tty(&s)) | 	s.ctl_mux.Handle(s.ctl_prefix + "/ws/tty", new_server_ctl_ws_tty(&s)) | ||||||
| 	s.ctl_mux.Handle(s.ctl_prefix + "/server-conns", &server_ctl_server_conns{s: &s}) | 	s.ctl_mux.Handle(s.ctl_prefix + "/server-conns", &server_ctl_server_conns{s: &s}) | ||||||
| @ -931,7 +947,6 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs | |||||||
| 	s.ctl_addr = make([]string, len(ctl_addrs)) | 	s.ctl_addr = make([]string, len(ctl_addrs)) | ||||||
| 	s.ctl = make([]*http.Server, len(ctl_addrs)) | 	s.ctl = make([]*http.Server, len(ctl_addrs)) | ||||||
| 	copy(s.ctl_addr, ctl_addrs) | 	copy(s.ctl_addr, ctl_addrs) | ||||||
| 	hs_log = log.New(&server_ctl_log_writer{svr: &s}, "", 0); |  | ||||||
|  |  | ||||||
| 	for i = 0; i < len(ctl_addrs); i++ { | 	for i = 0; i < len(ctl_addrs); i++ { | ||||||
| 		s.ctl[i] = &http.Server{ | 		s.ctl[i] = &http.Server{ | ||||||
| @ -943,6 +958,26 @@ func NewServer(ctx context.Context, logger Logger, ctl_addrs []string, rpc_addrs | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	// --------------------------------------------------------- | ||||||
|  | 	s.pxy_mux = http.NewServeMux() // TODO: make /_init configurable... | ||||||
|  | 	s.pxy_mux.Handle("/_init/{conn_id}/{route_id}/{trailer...}", &server_proxy_http_init{s: &s}) | ||||||
|  | 	s.pxy_mux.Handle("/", &server_proxy_http_main{s: &s}) | ||||||
|  |  | ||||||
|  | 	s.pxy_addr = make([]string, len(pxy_addrs)) | ||||||
|  | 	s.pxy = make([]*http.Server, len(pxy_addrs)) | ||||||
|  | 	copy(s.pxy_addr, pxy_addrs) | ||||||
|  |  | ||||||
|  | 	for i = 0; i < len(pxy_addrs); i++ { | ||||||
|  | 		s.pxy[i] = &http.Server{ | ||||||
|  | 			Addr: pxy_addrs[i], | ||||||
|  | 			Handler: s.pxy_mux, | ||||||
|  | 			TLSConfig: s.pxytlscfg, | ||||||
|  | 			ErrorLog: hs_log, | ||||||
|  | 			// TODO: more settings | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	// --------------------------------------------------------- | ||||||
|  |  | ||||||
| 	s.stats.conns.Store(0) | 	s.stats.conns.Store(0) | ||||||
| 	s.stats.routes.Store(0) | 	s.stats.routes.Store(0) | ||||||
| 	s.stats.peers.Store(0) | 	s.stats.peers.Store(0) | ||||||
| @ -1032,7 +1067,6 @@ func (s *Server) RunCtlTask(wg *sync.WaitGroup) { | |||||||
|  |  | ||||||
| 			s.log.Write("", LOG_INFO, "Control channel[%d] started on %s", i, s.ctl_addr[i]) | 			s.log.Write("", LOG_INFO, "Control channel[%d] started on %s", i, s.ctl_addr[i]) | ||||||
|  |  | ||||||
|  |  | ||||||
| 			if s.stop_req.Load() == false { | 			if s.stop_req.Load() == false { | ||||||
| 				// defeat hard-coded "tcp" in ListenAndServe() and ListenAndServeTLS() | 				// defeat hard-coded "tcp" in ListenAndServe() and ListenAndServeTLS() | ||||||
| 				//  err = cs.ListenAndServe() | 				//  err = cs.ListenAndServe() | ||||||
| @ -1064,14 +1098,61 @@ func (s *Server) RunCtlTask(wg *sync.WaitGroup) { | |||||||
| 	l_wg.Wait() | 	l_wg.Wait() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *Server) RunPxyTask(wg *sync.WaitGroup) { | ||||||
|  | 	var err error | ||||||
|  | 	var pxy *http.Server | ||||||
|  | 	var idx int | ||||||
|  | 	var l_wg sync.WaitGroup | ||||||
|  |  | ||||||
|  | 	defer wg.Done() | ||||||
|  |  | ||||||
|  | 	for idx, pxy = range s.pxy { | ||||||
|  | 		l_wg.Add(1) | ||||||
|  | 		go func(i int, cs *http.Server) { | ||||||
|  | 			var l net.Listener | ||||||
|  |  | ||||||
|  | 			s.log.Write("", LOG_INFO, "Proxy channel[%d] started on %s", i, s.pxy_addr[i]) | ||||||
|  |  | ||||||
|  | 			if s.stop_req.Load() == false { | ||||||
|  | 				l, err = net.Listen(tcp_addr_str_class(cs.Addr), cs.Addr) | ||||||
|  | 				if err == nil { | ||||||
|  | 					if s.stop_req.Load() == false { | ||||||
|  | 						if s.pxytlscfg == nil { // TODO: change this | ||||||
|  | 							err = cs.Serve(l) | ||||||
|  | 						} else { | ||||||
|  | 							err = cs.ServeTLS(l, "", "") // s.pxytlscfg must provide a certificate and a key | ||||||
|  | 						} | ||||||
|  | 					} else { | ||||||
|  | 						err = fmt.Errorf("stop requested") | ||||||
|  | 					} | ||||||
|  | 					l.Close() | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				err = fmt.Errorf("stop requested") | ||||||
|  | 			} | ||||||
|  | 			if errors.Is(err, http.ErrServerClosed) { | ||||||
|  | 				s.log.Write("", LOG_INFO, "Proxy channel[%d] ended", i) | ||||||
|  | 			} else { | ||||||
|  | 				s.log.Write("", LOG_ERROR, "Proxy channel[%d] error - %s", i, err.Error()) | ||||||
|  | 			} | ||||||
|  | 			l_wg.Done() | ||||||
|  | 		}(idx, pxy) | ||||||
|  | 	} | ||||||
|  | 	l_wg.Wait() | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s *Server) ReqStop() { | func (s *Server) ReqStop() { | ||||||
| 	if s.stop_req.CompareAndSwap(false, true) { | 	if s.stop_req.CompareAndSwap(false, true) { | ||||||
| 		var l *net.TCPListener | 		var l *net.TCPListener | ||||||
| 		var cts *ServerConn | 		var cts *ServerConn | ||||||
| 		var ctl *http.Server | 		var hs *http.Server | ||||||
|  |  | ||||||
| 		for _, ctl = range s.ctl { | 		for _, hs = range s.ctl { | ||||||
| 			ctl.Shutdown(s.ctx) // to break c.ctl.ListenAndServe() | 			hs.Shutdown(s.ctx) // to break s.ctl.Serve() | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for _, hs = range s.pxy { | ||||||
|  | 			hs.Shutdown(s.ctx) // to break s.pxy.Serve() | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		//s.rpc_svr.GracefulStop() | 		//s.rpc_svr.GracefulStop() | ||||||
| @ -1222,6 +1303,23 @@ func (s *Server) FindServerConnByAddr(addr net.Addr) *ServerConn { | |||||||
| 	return cts | 	return cts | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | func (s *Server) FindServerRouteById(id ConnId, route_id RouteId) *ServerRoute { | ||||||
|  | 	var cts *ServerConn | ||||||
|  | 	var ok bool | ||||||
|  |  | ||||||
|  | 	s.cts_mtx.Lock() | ||||||
|  | 	defer s.cts_mtx.Unlock() | ||||||
|  |  | ||||||
|  | 	cts, ok = s.cts_map[id] | ||||||
|  | 	if !ok { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return cts.FindServerRouteById(route_id) | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| func (s *Server) StartService(cfg interface{}) { | func (s *Server) StartService(cfg interface{}) { | ||||||
| 	s.wg.Add(1) | 	s.wg.Add(1) | ||||||
| 	go s.RunTask(&s.wg) | 	go s.RunTask(&s.wg) | ||||||
| @ -1240,6 +1338,11 @@ func (s *Server) StartCtlService() { | |||||||
| 	go s.RunCtlTask(&s.wg) | 	go s.RunCtlTask(&s.wg) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *Server) StartPxyService() { | ||||||
|  | 	s.wg.Add(1) | ||||||
|  | 	go s.RunPxyTask(&s.wg) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s *Server) StopServices() { | func (s *Server) StopServices() { | ||||||
| 	var ext_svc Service | 	var ext_svc Service | ||||||
| 	s.ReqStop() | 	s.ReqStop() | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user