2024-11-25 19:46:18 +09:00
package hodu
2025-03-26 23:44:41 +09:00
import "container/list"
2024-11-25 19:46:18 +09:00
import "encoding/json"
2024-12-13 02:25:27 +09:00
import "fmt"
2024-11-25 19:46:18 +09:00
import "net/http"
2025-01-10 01:02:11 +09:00
import "strings"
2025-03-26 23:44:41 +09:00
import "sync"
2025-01-07 13:44:37 +09:00
import "time"
2024-11-25 19:46:18 +09:00
2025-03-26 23:44:41 +09:00
import "golang.org/x/net/websocket"
2024-11-25 19:46:18 +09:00
/ *
* POST GET PUT DELETE
* / servers - create new server list all servers bulk update delete all servers
* / servers / 1 - X get server 1 details update server 1 delete server 1
* / servers / 1 / xxx -
2024-11-28 01:29:02 +09:00
*
2024-11-25 22:55:03 +09:00
* / servers / 1112123 / peers
2024-11-28 01:29:02 +09:00
* POST add a new peer to a server
* GET list all peers
* PUT create / replace
* PATCH partial update
2024-11-30 00:19:39 +09:00
* / servers / 1112123 / peers / 1231344
* GET get info
2024-11-25 19:46:18 +09:00
* /
2024-11-30 02:53:47 +09:00
type json_in_client_conn struct {
2025-02-22 10:08:57 +09:00
ServerAddrs [ ] string ` json:"server-addrs" ` // multiple addresses for round-robin connection re-attempts
ClientToken string ` json:"client-token" `
2025-03-05 00:44:00 +09:00
CloseOnConnErrorEvent bool ` json:"close-on-conn-error-event" `
2024-11-30 02:53:47 +09:00
}
type json_in_client_route struct {
2025-03-22 14:01:42 +09:00
RId RouteId ` json:"route-id" ` // 0 for auto-assignement.
2024-11-30 02:53:47 +09:00
ClientPeerAddr string ` json:"client-peer-addr" `
2024-12-14 00:19:12 +09:00
ClientPeerName string ` json:"client-peer-name" `
2024-12-12 21:09:16 +09:00
ServerPeerOption string ` json:"server-peer-option" `
2025-03-11 21:12:05 +09:00
// the following two fields in the input structure is the requested values.
// the actual values are returned in json_out_clinet_route and may be different from the requested ones
ServerPeerSvcAddr string ` json:"server-peer-svc-addr" ` // requested listening address on the server side - not actual
ServerPeerSvcNet string ` json:"server-peer-svc-net" ` // requested permitted network in prefix notation - not actual
2025-01-07 13:44:37 +09:00
Lifetime string ` json:"lifetime" `
2024-11-30 02:53:47 +09:00
}
2025-01-07 15:23:05 +09:00
type json_in_client_route_update struct {
2025-03-22 14:01:42 +09:00
Lifetime string ` json:"lifetime" `
2025-01-07 15:23:05 +09:00
}
2024-11-30 00:19:39 +09:00
type json_out_client_conn struct {
2025-03-22 14:01:42 +09:00
CId ConnId ` json:"conn-id" `
2024-12-08 16:06:18 +09:00
ReqServerAddrs [ ] string ` json:"req-server-addrs" ` // server addresses requested. may include a domain name
CurrentServerIndex int ` json:"current-server-index" `
2024-12-03 11:52:46 +09:00
ServerAddr string ` json:"server-addr" ` // actual server address
2024-12-02 02:19:50 +09:00
ClientAddr string ` json:"client-addr" `
2025-03-05 00:44:00 +09:00
ClientToken string ` json:"client-token" `
2025-03-26 23:44:41 +09:00
CreatedMilli int64 ` json:"created-milli" `
Routes [ ] json_out_client_route ` json:"routes,omitempty" `
2024-11-28 01:29:02 +09:00
}
2024-11-30 00:19:39 +09:00
type json_out_client_route struct {
2025-03-22 14:01:42 +09:00
CId ConnId ` json:"conn-id" `
RId RouteId ` json:"route-id" `
2024-11-30 00:19:39 +09:00
ClientPeerAddr string ` json:"client-peer-addr" `
2024-12-14 00:19:12 +09:00
ClientPeerName string ` json:"client-peer-name" `
2024-12-12 21:09:16 +09:00
ServerPeerOption string ` json:"server-peer-option" `
2025-03-11 21:12:05 +09:00
// These two values are actual addresses and networks listening on peer service port
// and may be different from the requested values conveyed in json_in_client_route.
ServerPeerSvcAddr string ` json:"server-peer-svc-addr" `
ServerPeerSvcNet string ` json:"server-peer-svc-net" `
2025-01-07 13:44:37 +09:00
Lifetime string ` json:"lifetime" `
2025-01-07 15:23:05 +09:00
LifetimeStart int64 ` json:"lifetime-start" `
2025-03-26 23:44:41 +09:00
CreatedMilli int64 ` json:"created-milli" `
2024-11-28 01:29:02 +09:00
}
2024-11-30 20:06:59 +09:00
type json_out_client_peer struct {
2025-03-22 14:01:42 +09:00
CId ConnId ` json:"conn-id" `
RId RouteId ` json:"route-id" `
PId PeerId ` json:"peer-id" `
2024-11-30 20:06:59 +09:00
ClientPeerAddr string ` json:"client-peer-addr" `
2024-12-01 17:20:16 +09:00
ClientLocalAddr string ` json:"client-local-addr" `
2024-11-30 20:06:59 +09:00
ServerPeerAddr string ` json:"server-peer-addr" `
2024-12-01 17:20:16 +09:00
ServerLocalAddr string ` json:"server-local-addr" `
2025-03-26 23:44:41 +09:00
CreatedMilli int64 ` json:"created-milli" `
2024-11-30 20:06:59 +09:00
}
2024-12-08 01:10:49 +09:00
2025-03-28 17:03:17 +09:00
type json_out_client_conn_id struct {
CId ConnId ` json:"conn-id" `
}
type json_out_client_route_id struct {
CId ConnId ` json:"conn-id" `
RId RouteId ` json:"route-id" `
}
type json_out_client_peer_id struct {
CId ConnId ` json:"conn-id" `
RId RouteId ` json:"route-id" `
PId PeerId ` json:"peer-id" `
}
2024-12-08 01:10:49 +09:00
type json_out_client_stats struct {
2025-01-28 00:44:02 +09:00
json_out_go_stats
2024-12-08 12:13:36 +09:00
ClientConns int64 ` json:"client-conns" `
ClientRoutes int64 ` json:"client-routes" `
ClientPeers int64 ` json:"client-peers" `
2024-12-08 01:10:49 +09:00
}
2024-11-28 01:29:02 +09:00
// ------------------------------------
2024-12-27 16:52:27 +09:00
type client_ctl struct {
2024-11-25 19:46:18 +09:00
c * Client
2024-12-27 16:52:27 +09:00
id string
2025-03-26 23:44:41 +09:00
noauth bool // override the auth configuration if true
2024-12-27 16:52:27 +09:00
}
2025-02-01 00:06:05 +09:00
type client_ctl_token struct {
client_ctl
}
2024-12-27 16:52:27 +09:00
type client_ctl_client_conns struct {
client_ctl
2024-11-25 19:46:18 +09:00
}
2024-11-30 00:19:39 +09:00
type client_ctl_client_conns_id struct {
2024-12-27 16:52:27 +09:00
client_ctl
2024-11-25 19:46:18 +09:00
}
2024-11-30 00:19:39 +09:00
type client_ctl_client_conns_id_routes struct {
2024-12-27 16:52:27 +09:00
client_ctl
2024-11-26 09:41:15 +09:00
}
2024-11-30 00:19:39 +09:00
type client_ctl_client_conns_id_routes_id struct {
2024-12-27 16:52:27 +09:00
client_ctl
2024-11-30 00:19:39 +09:00
}
2025-01-09 23:02:50 +09:00
type client_ctl_client_conns_id_routes_spsp struct {
client_ctl
}
2024-11-30 20:06:59 +09:00
type client_ctl_client_conns_id_routes_id_peers struct {
2024-12-27 16:52:27 +09:00
client_ctl
2024-11-30 20:06:59 +09:00
}
type client_ctl_client_conns_id_routes_id_peers_id struct {
2024-12-27 16:52:27 +09:00
client_ctl
2024-11-30 20:06:59 +09:00
}
2024-11-30 00:19:39 +09:00
2025-03-26 23:44:41 +09:00
type client_ctl_client_conns_id_peers struct {
client_ctl
}
type client_ctl_client_routes struct {
client_ctl
}
type client_ctl_client_peers struct {
client_ctl
}
2025-02-18 14:44:45 +09:00
type client_ctl_notices struct {
client_ctl
}
type client_ctl_notices_id struct {
2025-02-18 01:17:51 +09:00
client_ctl
}
2024-12-08 01:10:49 +09:00
type client_ctl_stats struct {
2024-12-27 16:52:27 +09:00
client_ctl
}
2025-03-26 23:44:41 +09:00
type client_ctl_ws struct {
client_ctl
}
2024-12-27 16:52:27 +09:00
// ------------------------------------
2025-03-29 13:29:02 +09:00
func ( ctl * client_ctl ) Identity ( ) string {
2024-12-27 16:52:27 +09:00
return ctl . id
2024-12-08 01:10:49 +09:00
}
2024-12-27 16:52:27 +09:00
2025-02-10 14:48:18 +09:00
func ( ctl * client_ctl ) Cors ( req * http . Request ) bool {
return ctl . c . ctl_cors
}
2025-02-01 00:06:05 +09:00
func ( ctl * client_ctl ) Authenticate ( req * http . Request ) ( int , string ) {
if ctl . c . ctl_auth == nil { return http . StatusOK , "" }
return ctl . c . ctl_auth . Authenticate ( req )
}
// ------------------------------------
func ( ctl * client_ctl_token ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
var c * Client
var status_code int
var je * json . Encoder
var err error
c = ctl . c
je = json . NewEncoder ( w )
switch req . Method {
case http . MethodGet :
var jwt * JWT [ ServerTokenClaim ]
var claim ServerTokenClaim
var tok string
var now time . Time
if c . ctl_auth == nil || ! c . ctl_auth . Enabled || c . ctl_auth . TokenRsaKey == nil {
status_code = WriteJsonRespHeader ( w , http . StatusForbidden )
err = fmt . Errorf ( "auth not enabled or token rsa key not set" )
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
}
now = time . Now ( )
claim . IssuedAt = now . Unix ( )
claim . ExpiresAt = now . Add ( c . ctl_auth . TokenTtl ) . Unix ( )
jwt = NewJWT ( c . ctl_auth . TokenRsaKey , & claim )
tok , err = jwt . SignRS512 ( )
if err != nil {
status_code = WriteJsonRespHeader ( w , http . StatusInternalServerError )
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
}
status_code = WriteJsonRespHeader ( w , http . StatusOK )
err = je . Encode ( json_out_token { AccessToken : tok } ) // TODO: refresh token
if err != nil { goto oops }
default :
status_code = WriteEmptyRespHeader ( w , http . StatusMethodNotAllowed )
}
//done:
return status_code , nil
oops :
return status_code , err
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_client_conns ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-11-25 19:46:18 +09:00
var c * Client
2024-11-25 22:55:03 +09:00
var status_code int
2024-11-25 19:46:18 +09:00
var err error
2024-11-30 00:19:39 +09:00
var je * json . Encoder
2024-11-25 19:46:18 +09:00
c = ctl . c
2024-11-30 00:19:39 +09:00
je = json . NewEncoder ( w )
2024-11-25 19:46:18 +09:00
switch req . Method {
case http . MethodGet :
2024-11-30 00:19:39 +09:00
var js [ ] json_out_client_conn
2025-03-07 13:41:44 +09:00
var ci ConnId
2024-11-28 01:29:02 +09:00
2024-11-30 00:19:39 +09:00
js = make ( [ ] json_out_client_conn , 0 )
2024-11-25 22:55:03 +09:00
c . cts_mtx . Lock ( )
2025-03-07 13:41:44 +09:00
for _ , ci = range c . cts_map . get_sorted_keys ( ) {
var cts * ClientConn
2024-11-30 00:19:39 +09:00
var jsp [ ] json_out_client_route
2025-03-07 13:41:44 +09:00
var ri RouteId
2024-11-28 01:29:02 +09:00
2025-03-07 13:41:44 +09:00
cts = c . cts_map [ ci ]
2024-11-30 00:19:39 +09:00
jsp = make ( [ ] json_out_client_route , 0 )
2024-11-28 01:29:02 +09:00
cts . route_mtx . Lock ( )
2025-03-07 13:41:44 +09:00
for _ , ri = range cts . route_map . get_sorted_keys ( ) {
var r * ClientRoute
2025-03-11 21:12:05 +09:00
var lftsta time . Time
var lftdur time . Duration
2025-03-07 13:41:44 +09:00
r = cts . route_map [ ri ]
2025-03-11 21:12:05 +09:00
lftsta , lftdur = r . GetLifetimeInfo ( )
2024-11-30 00:19:39 +09:00
jsp = append ( jsp , json_out_client_route {
2025-03-22 14:01:42 +09:00
CId : cts . Id ,
RId : r . Id ,
2025-01-18 12:58:17 +09:00
ClientPeerAddr : r . PeerAddr ,
ClientPeerName : r . PeerName ,
2025-03-28 17:03:17 +09:00
ServerPeerSvcAddr : r . ServerPeerSvcAddr . Get ( ) ,
ServerPeerSvcNet : r . ServerPeerSvcNet . Get ( ) ,
2025-01-18 12:58:17 +09:00
ServerPeerOption : r . ServerPeerOption . String ( ) ,
2025-03-11 21:12:05 +09:00
Lifetime : DurationToSecString ( lftdur ) ,
LifetimeStart : lftsta . Unix ( ) ,
2025-03-26 23:44:41 +09:00
CreatedMilli : r . Created . UnixMilli ( ) ,
2024-11-28 01:29:02 +09:00
} )
}
2025-03-07 13:41:44 +09:00
cts . route_mtx . Unlock ( )
2025-03-11 21:12:05 +09:00
2024-12-02 02:19:50 +09:00
js = append ( js , json_out_client_conn {
2025-03-22 14:01:42 +09:00
CId : cts . Id ,
2024-12-08 16:06:18 +09:00
ReqServerAddrs : cts . cfg . ServerAddrs ,
CurrentServerIndex : cts . cfg . Index ,
2025-03-13 21:24:59 +09:00
ServerAddr : cts . remote_addr . Get ( ) ,
ClientAddr : cts . local_addr . Get ( ) ,
2025-03-21 12:53:16 +09:00
ClientToken : cts . Token . Get ( ) ,
2025-03-26 23:44:41 +09:00
CreatedMilli : cts . Created . UnixMilli ( ) ,
2024-12-02 02:19:50 +09:00
Routes : jsp ,
} )
2024-11-25 22:55:03 +09:00
}
c . cts_mtx . Unlock ( )
2024-11-28 01:29:02 +09:00
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2024-11-28 01:29:02 +09:00
if err = je . Encode ( js ) ; err != nil { goto oops }
2024-11-25 19:46:18 +09:00
case http . MethodPost :
2024-11-30 15:38:06 +09:00
// add a new client connection to a server with no client-side peers
// while the client code can accept one more more client-side peer address
// with the server added, i don't intentially accept peer addresses
// as it's tricky to handle erroneous cases in creating the client routes
// after hacing connected to the server. therefore, the json_in_client_conn
// type contains a server address field only.
2025-02-22 10:08:57 +09:00
var in_cc json_in_client_conn
2025-02-10 14:48:18 +09:00
var cc ClientConnConfig
2024-11-25 22:55:03 +09:00
var cts * ClientConn
2025-02-22 10:08:57 +09:00
err = json . NewDecoder ( req . Body ) . Decode ( & in_cc )
if err != nil || len ( in_cc . ServerAddrs ) <= 0 {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-25 22:55:03 +09:00
goto done
2024-11-25 19:46:18 +09:00
}
2024-12-03 00:55:19 +09:00
2025-02-22 10:08:57 +09:00
cc . ServerAddrs = in_cc . ServerAddrs
cc . ClientToken = in_cc . ClientToken
2025-03-05 00:44:00 +09:00
cc . CloseOnConnErrorEvent = in_cc . CloseOnConnErrorEvent
2024-11-25 22:55:03 +09:00
cts , err = c . start_service ( & cc ) // TODO: this can be blocking. do we have to resolve addresses before calling this? also not good because resolution succeed or fail at each attempt. however ok as ServeHTTP itself is in a goroutine?
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusInternalServerError )
2025-01-28 23:50:28 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
2024-11-25 22:55:03 +09:00
} else {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusCreated )
2025-03-22 14:01:42 +09:00
if err = je . Encode ( json_out_client_conn_id { CId : cts . Id } ) ; err != nil { goto oops }
2024-11-25 22:55:03 +09:00
}
2024-11-25 19:46:18 +09:00
case http . MethodDelete :
2024-11-30 18:59:36 +09:00
// delete all client connections to servers. if we request to stop all
// client connections, they will remove themselves from the client.
// we do passive deletion rather than doing active deletion by calling
// c.RemoveAllClientConns()
c . ReqStopAllClientConns ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2024-11-25 22:55:03 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-25 19:46:18 +09:00
}
2024-11-25 22:55:03 +09:00
done :
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-11-25 19:46:18 +09:00
2024-11-25 22:55:03 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-11-25 19:46:18 +09:00
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
2024-11-30 00:19:39 +09:00
// client-conns/{conn_id}
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_client_conns_id ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-11-30 00:19:39 +09:00
var c * Client
var status_code int
var conn_id string
var je * json . Encoder
2024-12-03 00:55:19 +09:00
var cts * ClientConn
2025-02-22 10:08:57 +09:00
var err error
2024-11-30 00:19:39 +09:00
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
2025-02-22 10:08:57 +09:00
cts , err = c . FindClientConnByIdStr ( conn_id )
2024-11-30 00:19:39 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
2025-02-22 10:08:57 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
2025-01-28 23:50:28 +09:00
goto oops
2024-12-03 00:55:19 +09:00
}
2024-11-25 22:55:03 +09:00
switch req . Method {
case http . MethodGet :
2024-11-30 00:19:39 +09:00
var jsp [ ] json_out_client_route
var js * json_out_client_conn
2025-03-07 13:41:44 +09:00
var ri RouteId
2024-11-30 00:19:39 +09:00
jsp = make ( [ ] json_out_client_route , 0 )
cts . route_mtx . Lock ( )
2025-03-07 13:41:44 +09:00
for _ , ri = range cts . route_map . get_sorted_keys ( ) {
var r * ClientRoute
2025-03-11 21:12:05 +09:00
var lftsta time . Time
var lftdur time . Duration
2025-03-07 13:41:44 +09:00
2025-03-07 21:12:21 +09:00
r = cts . route_map [ ri ]
2025-03-11 21:12:05 +09:00
lftsta , lftdur = r . GetLifetimeInfo ( )
2024-11-30 00:19:39 +09:00
jsp = append ( jsp , json_out_client_route {
2025-03-22 14:01:42 +09:00
CId : cts . Id ,
RId : r . Id ,
2025-01-18 12:58:17 +09:00
ClientPeerAddr : r . PeerAddr ,
ClientPeerName : r . PeerName ,
2025-03-28 17:03:17 +09:00
ServerPeerSvcAddr : r . ServerPeerSvcAddr . Get ( ) ,
ServerPeerSvcNet : r . ServerPeerSvcNet . Get ( ) ,
2025-01-18 12:58:17 +09:00
ServerPeerOption : r . ServerPeerOption . String ( ) ,
2025-03-11 21:12:05 +09:00
Lifetime : DurationToSecString ( lftdur ) ,
LifetimeStart : lftsta . Unix ( ) ,
2025-03-26 23:44:41 +09:00
CreatedMilli : r . Created . UnixMilli ( ) ,
2024-11-30 00:19:39 +09:00
} )
}
2025-03-07 13:41:44 +09:00
cts . route_mtx . Unlock ( )
2025-03-13 21:24:59 +09:00
2024-12-03 11:52:46 +09:00
js = & json_out_client_conn {
2025-03-22 14:01:42 +09:00
CId : cts . Id ,
2024-12-08 16:06:18 +09:00
ReqServerAddrs : cts . cfg . ServerAddrs ,
CurrentServerIndex : cts . cfg . Index ,
2025-03-13 21:24:59 +09:00
ServerAddr : cts . remote_addr . Get ( ) ,
ClientAddr : cts . local_addr . Get ( ) ,
2025-03-21 12:53:16 +09:00
ClientToken : cts . Token . Get ( ) ,
2025-03-26 23:44:41 +09:00
CreatedMilli : cts . Created . UnixMilli ( ) ,
2024-12-03 11:52:46 +09:00
Routes : jsp ,
}
2024-11-25 22:55:03 +09:00
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2024-11-30 00:19:39 +09:00
if err = je . Encode ( js ) ; err != nil { goto oops }
2024-11-25 22:55:03 +09:00
case http . MethodDelete :
2024-12-03 00:55:19 +09:00
//c.RemoveClientConn(cts)
cts . ReqStop ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2024-11-30 03:08:20 +09:00
2024-11-30 00:19:39 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-25 22:55:03 +09:00
}
2025-01-28 23:50:28 +09:00
//done:
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-11-30 00:19:39 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-11-25 19:46:18 +09:00
}
2024-11-30 18:59:36 +09:00
// ------------------------------------
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_client_conns_id_routes ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-11-26 09:41:15 +09:00
var c * Client
var status_code int
2024-11-30 00:19:39 +09:00
var conn_id string
var je * json . Encoder
var cts * ClientConn
2025-02-22 10:08:57 +09:00
var err error
2024-11-26 09:41:15 +09:00
c = ctl . c
2024-11-30 00:19:39 +09:00
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
2025-02-22 10:08:57 +09:00
cts , err = c . FindClientConnByIdStr ( conn_id )
2024-11-30 00:19:39 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
2025-02-22 10:08:57 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
2025-01-28 23:50:28 +09:00
goto oops
2024-11-30 00:19:39 +09:00
}
2024-11-26 09:41:15 +09:00
switch req . Method {
case http . MethodGet :
2024-11-30 00:19:39 +09:00
var jsp [ ] json_out_client_route
2025-03-07 13:41:44 +09:00
var ri RouteId
2024-11-30 00:19:39 +09:00
jsp = make ( [ ] json_out_client_route , 0 )
cts . route_mtx . Lock ( )
2025-03-07 13:41:44 +09:00
for _ , ri = range cts . route_map . get_sorted_keys ( ) {
var r * ClientRoute
2025-03-11 21:12:05 +09:00
var lftsta time . Time
var lftdur time . Duration
2025-03-07 13:41:44 +09:00
r = cts . route_map [ ri ]
2025-03-11 21:12:05 +09:00
lftsta , lftdur = r . GetLifetimeInfo ( )
2024-11-30 00:19:39 +09:00
jsp = append ( jsp , json_out_client_route {
2025-03-22 14:01:42 +09:00
CId : r . cts . Id ,
RId : r . Id ,
2025-01-18 12:58:17 +09:00
ClientPeerAddr : r . PeerAddr ,
ClientPeerName : r . PeerName ,
2025-03-28 17:03:17 +09:00
ServerPeerSvcAddr : r . ServerPeerSvcAddr . Get ( ) ,
ServerPeerSvcNet : r . ServerPeerSvcNet . Get ( ) ,
2025-01-18 12:58:17 +09:00
ServerPeerOption : r . ServerPeerOption . String ( ) ,
2025-03-11 21:12:05 +09:00
Lifetime : DurationToSecString ( lftdur ) ,
LifetimeStart : lftsta . Unix ( ) ,
2025-03-26 23:44:41 +09:00
CreatedMilli : r . Created . UnixMilli ( ) ,
2024-11-30 00:19:39 +09:00
} )
}
cts . route_mtx . Unlock ( )
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2024-11-30 00:19:39 +09:00
if err = je . Encode ( jsp ) ; err != nil { goto oops }
2024-11-26 09:41:15 +09:00
case http . MethodPost :
2024-11-30 02:53:47 +09:00
var jcr json_in_client_route
var r * ClientRoute
2024-12-16 09:59:14 +09:00
var rc * ClientRouteConfig
2024-12-13 02:25:27 +09:00
var server_peer_option RouteOption
2025-01-07 13:44:37 +09:00
var lifetime time . Duration
2024-11-26 09:41:15 +09:00
2024-11-30 02:53:47 +09:00
err = json . NewDecoder ( req . Body ) . Decode ( & jcr )
2024-12-13 02:25:27 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-12-13 02:25:27 +09:00
goto oops
2024-12-12 21:09:16 +09:00
}
2024-12-14 00:19:12 +09:00
if jcr . ClientPeerAddr == "" {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-12-13 02:25:27 +09:00
err = fmt . Errorf ( "blank client-peer-addr" )
2025-01-08 17:32:40 +09:00
goto oops
2024-12-13 02:25:27 +09:00
}
2025-01-19 01:56:31 +09:00
server_peer_option = StringToRouteOption ( jcr . ServerPeerOption )
2024-12-13 02:25:27 +09:00
if server_peer_option == RouteOption ( ROUTE_OPTION_UNSPEC ) {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-07 13:44:37 +09:00
err = fmt . Errorf ( "wrong server-peer-option value - %s" , server_peer_option )
2024-12-13 02:25:27 +09:00
goto oops
2024-11-26 09:41:15 +09:00
}
2025-01-19 01:56:31 +09:00
lifetime , err = ParseDurationString ( jcr . Lifetime )
2025-01-07 15:23:05 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-07 15:23:05 +09:00
err = fmt . Errorf ( "wrong lifetime value %s - %s" , jcr . Lifetime , err . Error ( ) )
goto oops
2025-01-07 13:44:37 +09:00
}
2024-12-16 09:59:14 +09:00
rc = & ClientRouteConfig {
2025-03-22 14:01:42 +09:00
Id : jcr . RId ,
2024-12-16 09:59:14 +09:00
PeerAddr : jcr . ClientPeerAddr ,
PeerName : jcr . ClientPeerName ,
2025-03-11 21:12:05 +09:00
ServiceAddr : jcr . ServerPeerSvcAddr ,
ServiceNet : jcr . ServerPeerSvcNet ,
2025-03-29 13:29:02 +09:00
ServiceOption : server_peer_option ,
2025-01-07 13:44:37 +09:00
Lifetime : lifetime ,
2025-01-19 12:17:27 +09:00
Static : false ,
2024-12-16 09:59:14 +09:00
}
r , err = cts . AddNewClientRoute ( rc )
2024-11-30 02:53:47 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusInternalServerError )
2025-01-28 23:50:28 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
2024-11-26 09:41:15 +09:00
} else {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusCreated )
2025-03-22 14:01:42 +09:00
if err = je . Encode ( json_out_client_route_id { RId : r . Id , CId : r . cts . Id } ) ; err != nil { goto oops }
2024-11-26 09:41:15 +09:00
}
2024-11-30 02:53:47 +09:00
case http . MethodDelete :
2024-11-30 18:59:36 +09:00
//cts.RemoveAllClientRoutes()
cts . ReqStopAllClientRoutes ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2024-11-30 02:53:47 +09:00
2024-11-26 09:41:15 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-26 09:41:15 +09:00
}
2025-01-28 23:50:28 +09:00
//done:
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-11-26 09:41:15 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-11-26 09:41:15 +09:00
}
2024-11-30 00:19:39 +09:00
// ------------------------------------
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_client_conns_id_routes_id ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-11-30 00:19:39 +09:00
var c * Client
var status_code int
var conn_id string
var route_id string
var je * json . Encoder
2024-12-08 23:16:43 +09:00
var r * ClientRoute
2025-02-22 10:08:57 +09:00
var err error
2024-11-30 00:19:39 +09:00
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
route_id = req . PathValue ( "route_id" )
2025-02-22 10:08:57 +09:00
r , err = c . FindClientRouteByIdStr ( conn_id , route_id )
2024-11-30 00:19:39 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
2025-02-22 10:08:57 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
2025-01-28 23:50:28 +09:00
goto oops
2024-12-08 23:16:43 +09:00
}
2024-11-30 00:19:39 +09:00
switch req . Method {
case http . MethodGet :
2025-03-11 21:12:05 +09:00
var lftsta time . Time
var lftdur time . Duration
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2025-03-11 21:12:05 +09:00
lftsta , lftdur = r . GetLifetimeInfo ( )
2024-11-30 00:19:39 +09:00
err = je . Encode ( json_out_client_route {
2025-03-22 14:01:42 +09:00
CId : r . cts . Id ,
RId : r . Id ,
2025-01-18 12:58:17 +09:00
ClientPeerAddr : r . PeerAddr ,
ClientPeerName : r . PeerName ,
2025-03-28 17:03:17 +09:00
ServerPeerSvcAddr : r . ServerPeerSvcAddr . Get ( ) ,
ServerPeerSvcNet : r . ServerPeerSvcNet . Get ( ) ,
2025-01-18 12:58:17 +09:00
ServerPeerOption : r . ServerPeerOption . String ( ) ,
2025-03-11 21:12:05 +09:00
Lifetime : DurationToSecString ( lftdur ) ,
LifetimeStart : lftsta . Unix ( ) ,
2025-03-26 23:44:41 +09:00
CreatedMilli : r . Created . UnixMilli ( ) ,
2024-11-30 00:19:39 +09:00
} )
if err != nil { goto oops }
2025-01-07 15:23:05 +09:00
case http . MethodPut :
var jcr json_in_client_route_update
var lifetime time . Duration
err = json . NewDecoder ( req . Body ) . Decode ( & jcr )
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-07 15:23:05 +09:00
goto oops
}
2025-01-19 01:56:31 +09:00
lifetime , err = ParseDurationString ( jcr . Lifetime )
2025-01-07 15:23:05 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-07 15:23:05 +09:00
err = fmt . Errorf ( "wrong lifetime value %s - %s" , jcr . Lifetime , err . Error ( ) )
goto oops
}
2025-01-10 01:02:11 +09:00
if strings . HasPrefix ( jcr . Lifetime , "+" ) {
err = r . ExtendLifetime ( lifetime )
} else {
err = r . ResetLifetime ( lifetime )
}
2025-01-10 01:14:49 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusForbidden )
2025-01-10 01:14:49 +09:00
goto oops
}
2025-01-13 20:17:49 +09:00
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusOK )
2025-01-09 23:02:50 +09:00
case http . MethodDelete :
r . ReqStop ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2025-01-09 23:02:50 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-09 23:02:50 +09:00
}
2025-01-28 23:50:28 +09:00
//done:
2025-01-09 23:02:50 +09:00
return status_code , nil
oops :
return status_code , err
}
// ------------------------------------
func ( ctl * client_ctl_client_conns_id_routes_spsp ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
var c * Client
var status_code int
var conn_id string
var port_id string
var je * json . Encoder
var r * ClientRoute
2025-02-23 20:06:37 +09:00
var err error
2025-01-09 23:02:50 +09:00
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
port_id = req . PathValue ( "port_id" )
2025-02-23 20:06:37 +09:00
r , err = c . FindClientRouteByServerPeerSvcPortIdStr ( conn_id , port_id )
2025-02-23 00:55:15 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
2025-02-23 00:55:15 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
2025-01-28 23:50:28 +09:00
goto oops
2025-01-09 23:02:50 +09:00
}
switch req . Method {
case http . MethodGet :
2025-03-11 21:12:05 +09:00
var lftsta time . Time
var lftdur time . Duration
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2025-03-11 21:12:05 +09:00
lftsta , lftdur = r . GetLifetimeInfo ( )
2025-01-09 23:02:50 +09:00
err = je . Encode ( json_out_client_route {
2025-03-22 14:01:42 +09:00
CId : r . cts . Id ,
RId : r . Id ,
2025-01-18 12:58:17 +09:00
ClientPeerAddr : r . PeerAddr ,
ClientPeerName : r . PeerName ,
2025-03-28 17:03:17 +09:00
ServerPeerSvcAddr : r . ServerPeerSvcAddr . Get ( ) ,
ServerPeerSvcNet : r . ServerPeerSvcNet . Get ( ) ,
2025-01-18 12:58:17 +09:00
ServerPeerOption : r . ServerPeerOption . String ( ) ,
2025-03-11 21:12:05 +09:00
Lifetime : DurationToSecString ( lftdur ) ,
LifetimeStart : lftsta . Unix ( ) ,
2025-01-09 23:02:50 +09:00
} )
if err != nil { goto oops }
case http . MethodPut :
var jcr json_in_client_route_update
var lifetime time . Duration
err = json . NewDecoder ( req . Body ) . Decode ( & jcr )
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-09 23:02:50 +09:00
goto oops
}
2025-01-19 01:56:31 +09:00
lifetime , err = ParseDurationString ( jcr . Lifetime )
2025-01-09 23:02:50 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-09 23:02:50 +09:00
err = fmt . Errorf ( "wrong lifetime value %s - %s" , jcr . Lifetime , err . Error ( ) )
goto oops
2025-01-10 01:02:11 +09:00
} else if lifetime < 0 {
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2025-01-10 01:02:11 +09:00
err = fmt . Errorf ( "negative lifetime value %s" , jcr . Lifetime )
goto oops
2025-01-09 23:02:50 +09:00
}
2025-01-10 01:02:11 +09:00
if strings . HasPrefix ( jcr . Lifetime , "+" ) {
err = r . ExtendLifetime ( lifetime )
} else {
err = r . ResetLifetime ( lifetime )
}
2025-01-07 15:23:05 +09:00
if err != nil { goto oops }
2024-11-30 00:19:39 +09:00
case http . MethodDelete :
2024-12-08 23:16:43 +09:00
r . ReqStop ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2024-11-30 00:19:39 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-30 00:19:39 +09:00
}
2025-01-28 23:50:28 +09:00
//done:
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-11-30 00:19:39 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-11-30 00:19:39 +09:00
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_client_conns_id_routes_id_peers ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-11-30 20:06:59 +09:00
var c * Client
var status_code int
var conn_id string
var route_id string
var je * json . Encoder
var r * ClientRoute
2025-02-22 10:08:57 +09:00
var err error
2024-11-30 20:06:59 +09:00
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
route_id = req . PathValue ( "route_id" )
2025-02-22 10:08:57 +09:00
r , err = c . FindClientRouteByIdStr ( conn_id , route_id )
2024-11-30 20:06:59 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
2025-02-22 10:08:57 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
2025-01-28 23:50:28 +09:00
goto oops
2024-11-30 20:06:59 +09:00
}
switch req . Method {
case http . MethodGet :
var jcp [ ] json_out_client_peer
2025-03-07 13:41:44 +09:00
var pi PeerId
2024-11-30 20:06:59 +09:00
jcp = make ( [ ] json_out_client_peer , 0 )
r . ptc_mtx . Lock ( )
2025-03-07 13:41:44 +09:00
for _ , pi = range r . ptc_map . get_sorted_keys ( ) {
var p * ClientPeerConn
p = r . ptc_map [ pi ]
2024-11-30 20:06:59 +09:00
jcp = append ( jcp , json_out_client_peer {
2025-03-22 14:01:42 +09:00
CId : r . cts . Id ,
RId : r . Id ,
PId : p . conn_id ,
2024-11-30 20:06:59 +09:00
ClientPeerAddr : p . conn . RemoteAddr ( ) . String ( ) ,
2024-12-01 17:20:16 +09:00
ClientLocalAddr : p . conn . LocalAddr ( ) . String ( ) ,
ServerPeerAddr : p . pts_raddr ,
ServerLocalAddr : p . pts_laddr ,
2025-03-26 23:44:41 +09:00
CreatedMilli : p . Created . UnixMilli ( ) ,
2024-11-30 20:06:59 +09:00
} )
}
r . ptc_mtx . Unlock ( )
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2024-11-30 20:06:59 +09:00
if err = je . Encode ( jcp ) ; err != nil { goto oops }
2024-12-01 19:11:12 +09:00
case http . MethodDelete :
r . ReqStopAllClientPeerConns ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2024-11-30 20:06:59 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-30 20:06:59 +09:00
}
2024-12-27 16:52:27 +09:00
2025-01-28 23:50:28 +09:00
//done:
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-11-30 20:06:59 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-11-30 20:06:59 +09:00
}
// ------------------------------------
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_client_conns_id_routes_id_peers_id ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-11-30 20:06:59 +09:00
var c * Client
var status_code int
var conn_id string
var route_id string
2024-12-01 17:20:16 +09:00
var peer_id string
2024-11-30 20:06:59 +09:00
var je * json . Encoder
2024-12-01 17:20:16 +09:00
var p * ClientPeerConn
2025-02-22 10:08:57 +09:00
var err error
2024-11-30 20:06:59 +09:00
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
route_id = req . PathValue ( "route_id" )
2024-12-01 17:20:16 +09:00
peer_id = req . PathValue ( "peer_id" )
2025-02-22 10:08:57 +09:00
p , err = c . FindClientPeerConnByIdStr ( conn_id , route_id , peer_id )
2024-12-01 17:20:16 +09:00
if err != nil {
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
2025-02-22 10:08:57 +09:00
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
2025-01-28 23:50:28 +09:00
goto oops
2024-11-30 20:06:59 +09:00
}
switch req . Method {
case http . MethodGet :
2024-12-01 17:20:16 +09:00
var jcp * json_out_client_peer
jcp = & json_out_client_peer {
2025-03-22 14:01:42 +09:00
CId : p . route . cts . Id ,
RId : p . route . Id ,
PId : p . conn_id ,
2024-12-01 17:20:16 +09:00
ClientPeerAddr : p . conn . RemoteAddr ( ) . String ( ) ,
ClientLocalAddr : p . conn . LocalAddr ( ) . String ( ) ,
ServerPeerAddr : p . pts_raddr ,
ServerLocalAddr : p . pts_laddr ,
2025-03-26 23:44:41 +09:00
CreatedMilli : p . Created . UnixMilli ( ) ,
2024-12-01 17:20:16 +09:00
}
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2024-12-01 17:20:16 +09:00
if err = je . Encode ( jcp ) ; err != nil { goto oops }
2024-12-01 19:11:12 +09:00
case http . MethodDelete :
p . ReqStop ( )
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusNoContent )
2024-12-01 19:11:12 +09:00
2024-11-30 20:06:59 +09:00
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-11-30 20:06:59 +09:00
}
2024-12-08 17:19:20 +09:00
2025-01-28 23:50:28 +09:00
//done:
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-11-30 20:06:59 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-11-30 20:06:59 +09:00
}
2024-12-08 01:10:49 +09:00
// ------------------------------------
2025-03-26 23:44:41 +09:00
func ( ctl * client_ctl_client_conns_id_peers ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
var c * Client
var status_code int
var err error
var conn_id string
var je * json . Encoder
var cts * ClientConn
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
cts , err = c . FindClientConnByIdStr ( conn_id )
if err != nil {
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
}
switch req . Method {
case http . MethodGet :
var jsp [ ] json_out_client_peer
var e * list . Element
jsp = make ( [ ] json_out_client_peer , 0 )
cts . ptc_mtx . Lock ( )
for e = cts . ptc_list . Front ( ) ; e != nil ; e = e . Next ( ) {
var ptc * ClientPeerConn
ptc = e . Value . ( * ClientPeerConn )
jsp = append ( jsp , json_out_client_peer {
CId : ptc . route . cts . Id ,
RId : ptc . route . Id ,
PId : ptc . conn_id ,
ClientPeerAddr : ptc . conn . RemoteAddr ( ) . String ( ) ,
ClientLocalAddr : ptc . conn . LocalAddr ( ) . String ( ) ,
ServerPeerAddr : ptc . pts_raddr ,
ServerLocalAddr : ptc . pts_laddr ,
CreatedMilli : ptc . Created . UnixMilli ( ) ,
} )
}
cts . ptc_mtx . Unlock ( )
status_code = WriteJsonRespHeader ( w , http . StatusOK )
if err = je . Encode ( jsp ) ; err != nil { goto oops }
default :
status_code = WriteEmptyRespHeader ( w , http . StatusMethodNotAllowed )
}
//done:
return status_code , nil
oops :
return status_code , err
}
// ------------------------------------
func ( ctl * client_ctl_client_routes ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
var c * Client
var status_code int
var je * json . Encoder
var err error
c = ctl . c
je = json . NewEncoder ( w )
switch req . Method {
case http . MethodGet :
var js [ ] json_out_client_route
var e * list . Element
js = make ( [ ] json_out_client_route , 0 )
c . route_mtx . Lock ( )
for e = c . route_list . Front ( ) ; e != nil ; e = e . Next ( ) {
var r * ClientRoute
var lftsta time . Time
var lftdur time . Duration
r = e . Value . ( * ClientRoute )
lftsta , lftdur = r . GetLifetimeInfo ( )
js = append ( js , json_out_client_route {
CId : r . cts . Id ,
RId : r . Id ,
ClientPeerAddr : r . PeerAddr ,
ClientPeerName : r . PeerName ,
2025-03-28 17:03:17 +09:00
ServerPeerSvcAddr : r . ServerPeerSvcAddr . Get ( ) ,
ServerPeerSvcNet : r . ServerPeerSvcNet . Get ( ) ,
2025-03-26 23:44:41 +09:00
ServerPeerOption : r . ServerPeerOption . String ( ) ,
Lifetime : DurationToSecString ( lftdur ) ,
LifetimeStart : lftsta . Unix ( ) ,
CreatedMilli : r . Created . UnixMilli ( ) ,
} )
}
c . route_mtx . Unlock ( )
status_code = WriteJsonRespHeader ( w , http . StatusOK )
if err = je . Encode ( js ) ; err != nil { goto oops }
default :
status_code = WriteEmptyRespHeader ( w , http . StatusMethodNotAllowed )
}
//done:
return status_code , nil
oops :
return status_code , err
}
// ------------------------------------
func ( ctl * client_ctl_client_peers ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
var c * Client
var status_code int
var je * json . Encoder
var err error
c = ctl . c
je = json . NewEncoder ( w )
switch req . Method {
case http . MethodGet :
var js [ ] json_out_client_peer
var e * list . Element
js = make ( [ ] json_out_client_peer , 0 )
c . ptc_mtx . Lock ( )
for e = c . ptc_list . Front ( ) ; e != nil ; e = e . Next ( ) {
var ptc * ClientPeerConn
ptc = e . Value . ( * ClientPeerConn )
js = append ( js , json_out_client_peer {
CId : ptc . route . cts . Id ,
RId : ptc . route . Id ,
PId : ptc . conn_id ,
ClientPeerAddr : ptc . conn . RemoteAddr ( ) . String ( ) ,
ClientLocalAddr : ptc . conn . LocalAddr ( ) . String ( ) ,
ServerPeerAddr : ptc . pts_raddr ,
ServerLocalAddr : ptc . pts_laddr ,
CreatedMilli : ptc . Created . UnixMilli ( ) ,
} )
}
c . ptc_mtx . Unlock ( )
status_code = WriteJsonRespHeader ( w , http . StatusOK )
if err = je . Encode ( js ) ; err != nil { goto oops }
default :
status_code = WriteEmptyRespHeader ( w , http . StatusMethodNotAllowed )
}
//done:
return status_code , nil
oops :
return status_code , err
}
// ------------------------------------
2025-02-18 14:44:45 +09:00
func ( ctl * client_ctl_notices ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
var c * Client
var status_code int
var cts * ClientConn
var err error
c = ctl . c
switch req . Method {
case http . MethodPost :
var noti json_in_notice
err = json . NewDecoder ( req . Body ) . Decode ( & noti )
if err != nil {
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
goto oops
}
c . cts_mtx . Lock ( )
for _ , cts = range c . cts_map {
cts . psc . Send ( MakeConnNoticePacket ( noti . Text ) )
// let's not care about an error when broacasting a notice to all connections
}
c . cts_mtx . Unlock ( )
status_code = WriteJsonRespHeader ( w , http . StatusOK )
default :
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
}
//done:
return status_code , nil
oops :
return status_code , err
}
// ------------------------------------
func ( ctl * client_ctl_notices_id ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2025-02-18 01:17:51 +09:00
var c * Client
var status_code int
var conn_id string
var cts * ClientConn
var je * json . Encoder
var err error
c = ctl . c
je = json . NewEncoder ( w )
conn_id = req . PathValue ( "conn_id" )
cts , err = c . FindClientConnByIdStr ( conn_id )
if err != nil {
status_code = WriteJsonRespHeader ( w , http . StatusNotFound )
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
}
switch req . Method {
case http . MethodPost :
var noti json_in_notice
err = json . NewDecoder ( req . Body ) . Decode ( & noti )
if err != nil {
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
goto oops
}
// no check if noti.Text is empty as i want an empty message to be delivered too.
err = cts . psc . Send ( MakeConnNoticePacket ( noti . Text ) )
if err != nil {
2025-02-24 10:34:22 +09:00
err = fmt . Errorf ( "failed to send conn_notice text '%s' to %s - %s" , noti . Text , cts . remote_addr , err . Error ( ) )
2025-02-18 01:17:51 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusInternalServerError )
je . Encode ( JsonErrmsg { Text : err . Error ( ) } )
goto oops
}
status_code = WriteJsonRespHeader ( w , http . StatusOK )
default :
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
}
//done:
return status_code , nil
oops :
return status_code , err
}
// ------------------------------------
2024-12-27 16:52:27 +09:00
func ( ctl * client_ctl_stats ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) ( int , error ) {
2024-12-08 01:10:49 +09:00
var c * Client
var status_code int
var err error
var je * json . Encoder
c = ctl . c
je = json . NewEncoder ( w )
switch req . Method {
case http . MethodGet :
var stats json_out_client_stats
2025-01-28 00:44:02 +09:00
stats . from_runtime_stats ( )
2024-12-08 12:13:36 +09:00
stats . ClientConns = c . stats . conns . Load ( )
stats . ClientRoutes = c . stats . routes . Load ( )
stats . ClientPeers = c . stats . peers . Load ( )
2025-01-15 01:19:50 +09:00
status_code = WriteJsonRespHeader ( w , http . StatusOK )
2024-12-08 01:10:49 +09:00
if err = je . Encode ( stats ) ; err != nil { goto oops }
default :
2025-01-15 01:19:50 +09:00
status_code = WriteEmptyRespHeader ( w , http . StatusBadRequest )
2024-12-08 01:10:49 +09:00
}
//done:
2024-12-27 16:52:27 +09:00
return status_code , nil
2024-12-08 01:10:49 +09:00
oops :
2024-12-27 16:52:27 +09:00
return status_code , err
2024-12-08 01:10:49 +09:00
}
2025-03-26 23:44:41 +09:00
// ------------------------------------
func ( ctl * client_ctl_ws ) ServeWebsocket ( ws * websocket . Conn ) ( int , error ) {
var c * Client
var wg sync . WaitGroup
var sbsc * ClientEventSubscription
var status_code int
var err error
var xerr error
c = ctl . c
// handle authentication using the first message.
// end this task if authentication fails.
if ! ctl . noauth && c . ctl_auth != nil {
var req * http . Request
req = ws . Request ( )
if req . Header . Get ( "Authorization" ) == "" {
var token string
token = req . FormValue ( "token" )
if token != "" {
// websocket doesn't actual have extra headers except a few fixed
// ones. add "Authorization" header from the query paramerer and
// compose a fake header to reuse the same Authentication() function
req . Header . Set ( "Authorization" , fmt . Sprintf ( "Bearer %s" , token ) )
}
}
status_code , _ = c . ctl_auth . Authenticate ( req )
if status_code != http . StatusOK {
goto done
}
}
sbsc , err = c . bulletin . Subscribe ( "" )
if err != nil { goto done }
wg . Add ( 1 )
go func ( ) {
var c chan * ClientEvent
var err error
defer wg . Done ( )
c = sbsc . C
for c != nil {
var e * ClientEvent
var ok bool
var msg [ ] byte
e , ok = <- c
if ok {
msg , err = json . Marshal ( e )
if err != nil {
xerr = fmt . Errorf ( "failed to marshal event - %+v - %s" , e , err . Error ( ) )
c = nil
} else {
err = websocket . Message . Send ( ws , msg )
if err != nil {
xerr = fmt . Errorf ( "failed to send message - %s" , err . Error ( ) )
c = nil
}
}
} else {
// most likely sbcs.C is closed. if not readable, break the loop
c = nil
}
}
ws . Close ( ) // hack to break the recv loop. don't care about double closes
} ( )
ws_recv_loop :
for {
var msg [ ] byte
err = websocket . Message . Receive ( ws , & msg )
if err != nil { break ws_recv_loop }
if len ( msg ) > 0 {
// do nothing. discard received messages
}
}
// Ubsubscribe() to break the internal event reception
// goroutine as well as for cleanup
c . bulletin . Unsubscribe ( sbsc )
done :
ws . Close ( )
wg . Wait ( )
if err == nil && xerr != nil { err = xerr }
return http . StatusOK , err
}