2024-11-25 19:46:18 +09:00
package hodu
import "encoding/json"
import "net/http"
2024-11-26 09:41:15 +09:00
import "strconv"
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-25 19:46:18 +09:00
* /
2024-11-26 09:41:15 +09:00
type json_errmsg struct {
2024-11-25 22:55:03 +09:00
Text string ` json:"error-text" `
}
2024-11-25 19:46:18 +09:00
2024-11-28 01:29:02 +09:00
type json_in_peer_addrs struct {
PeerAddrs [ ] string ` json:"peer-addrs" `
2024-11-26 09:41:15 +09:00
}
2024-11-28 01:29:02 +09:00
type json_out_server struct {
Id uint32 ` json:"id" `
ServerAddr string ` json:"server-addr" `
PeerAddrs [ ] json_out_server_peer ` json:"peer-addrs" `
}
type json_out_server_peer struct {
Id uint32 ` json:"id" `
ClientPeerAddr string ` json:"peer-addr" `
ServerPeerListenAddr string ` json:"server-peer-listen-addr" `
}
// ------------------------------------
2024-11-25 19:46:18 +09:00
type client_ctl_servers struct {
c * Client
}
type client_ctl_servers_id struct {
c * Client
}
2024-11-26 09:41:15 +09:00
type client_ctl_servers_id_peers struct {
c * Client
}
2024-11-25 19:46:18 +09:00
type client_ctl_clients struct {
c * Client
}
type client_ctl_clients_id struct {
c * Client
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
func ( ctl * client_ctl_servers ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
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
c = ctl . c
switch req . Method {
case http . MethodGet :
2024-11-25 22:55:03 +09:00
var je * json . Encoder
var cts * ClientConn
2024-11-28 01:29:02 +09:00
var js [ ] json_out_server
2024-11-25 22:55:03 +09:00
status_code = http . StatusOK ; w . WriteHeader ( status_code )
je = json . NewEncoder ( w )
2024-11-28 01:29:02 +09:00
2024-11-25 22:55:03 +09:00
c . cts_mtx . Lock ( )
for _ , cts = range c . cts_map_by_id {
2024-11-28 01:29:02 +09:00
var r * ClientRoute
var jsp [ ] json_out_server_peer
cts . route_mtx . Lock ( )
for _ , r = range cts . route_map {
jsp = append ( jsp , json_out_server_peer {
Id : r . id ,
ClientPeerAddr : r . peer_addr . String ( ) ,
ServerPeerListenAddr : r . server_peer_listen_addr . String ( ) ,
} )
}
js = append ( js , json_out_server { Id : cts . id , ServerAddr : cts . saddr . String ( ) , PeerAddrs : jsp } )
cts . route_mtx . Unlock ( )
2024-11-25 22:55:03 +09:00
}
c . cts_mtx . Unlock ( )
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-25 22:55:03 +09:00
// add a new server connection
2024-11-25 19:46:18 +09:00
var s ClientCtlParamServer
var cc ClientConfig
2024-11-25 22:55:03 +09:00
var cts * ClientConn
2024-11-25 19:46:18 +09:00
err = json . NewDecoder ( req . Body ) . Decode ( & s )
if err != nil {
2024-11-25 22:55:03 +09:00
status_code = http . StatusBadRequest
w . WriteHeader ( status_code )
goto done
2024-11-25 19:46:18 +09:00
}
cc . ServerAddr = s . ServerAddr
cc . PeerAddrs = s . PeerAddrs
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 {
var je * json . Encoder
status_code = http . StatusInternalServerError ; w . WriteHeader ( status_code )
je = json . NewEncoder ( w )
2024-11-26 09:41:15 +09:00
if err = je . Encode ( json_errmsg { Text : err . Error ( ) } ) ; err != nil { goto oops }
2024-11-25 22:55:03 +09:00
} else {
var je * json . Encoder
status_code = http . StatusCreated ; w . WriteHeader ( status_code )
je = json . NewEncoder ( w )
if err = je . Encode ( cts . cfg ) ; err != nil { goto oops }
}
2024-11-25 19:46:18 +09:00
case http . MethodDelete :
2024-11-25 22:55:03 +09:00
// delete all server conneections
2024-11-25 19:46:18 +09:00
var cts * ClientConn
c . cts_mtx . Lock ( )
for _ , cts = range c . cts_map { cts . ReqStop ( ) }
c . cts_mtx . Unlock ( )
2024-11-25 22:55:03 +09:00
w . WriteHeader ( http . StatusNoContent )
default :
status_code = http . StatusBadRequest ; w . WriteHeader ( status_code )
2024-11-25 19:46:18 +09:00
}
2024-11-25 22:55:03 +09:00
done :
// TODO: need to handle x-forwarded-for and other stuff? this is not a real web service, though
c . log . Write ( "" , LOG_DEBUG , "[%s] %s %s %d" , req . RemoteAddr , req . Method , req . URL . String ( ) , status_code ) // TODO: time taken
2024-11-25 19:46:18 +09:00
return
2024-11-25 22:55:03 +09:00
oops :
c . log . Write ( "" , LOG_ERROR , "[%s] %s %s - %s" , req . RemoteAddr , req . Method , req . URL . String ( ) , err . Error ( ) )
2024-11-25 19:46:18 +09:00
return
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
2024-11-25 22:55:03 +09:00
// servers/{id}
2024-11-25 19:46:18 +09:00
func ( ctl * client_ctl_servers_id ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
2024-11-25 22:55:03 +09:00
//req.PathValue("id")
switch req . Method {
case http . MethodGet :
case http . MethodPost :
case http . MethodPut : // update
goto bad_request
case http . MethodDelete :
}
return
bad_request :
w . WriteHeader ( http . StatusBadRequest )
return
2024-11-25 19:46:18 +09:00
}
2024-11-26 09:41:15 +09:00
func ( ctl * client_ctl_servers_id_peers ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
var c * Client
var status_code int
var err error
var id string
c = ctl . c
id = req . PathValue ( "id" )
switch req . Method {
case http . MethodGet :
case http . MethodPost :
2024-11-28 01:29:02 +09:00
var pa json_in_peer_addrs
2024-11-26 09:41:15 +09:00
var cts * ClientConn
var nid uint64
2024-11-28 01:29:02 +09:00
err = json . NewDecoder ( req . Body ) . Decode ( & pa )
2024-11-26 09:41:15 +09:00
if err != nil {
status_code = http . StatusBadRequest ; w . WriteHeader ( status_code )
goto done
}
nid , err = strconv . ParseUint ( id , 10 , 32 )
if err != nil {
status_code = http . StatusBadRequest ; w . WriteHeader ( status_code )
goto done
}
cts = c . FindClientConnById ( uint32 ( nid ) )
if cts == nil {
status_code = http . StatusNotFound ; w . WriteHeader ( status_code )
} else {
2024-11-28 01:29:02 +09:00
err = cts . AddClientRoutes ( pa . PeerAddrs )
if err != nil {
var je * json . Encoder
status_code = http . StatusInternalServerError ; w . WriteHeader ( status_code )
je = json . NewEncoder ( w )
if err = je . Encode ( json_errmsg { Text : err . Error ( ) } ) ; err != nil { goto oops }
} else {
status_code = http . StatusCreated ; w . WriteHeader ( status_code )
}
2024-11-26 09:41:15 +09:00
}
default :
status_code = http . StatusBadRequest ; w . WriteHeader ( status_code )
}
done :
// TODO: need to handle x-forwarded-for and other stuff? this is not a real web service, though
c . log . Write ( "" , LOG_DEBUG , "[%s] %s %s %d" , req . RemoteAddr , req . Method , req . URL . String ( ) , status_code ) // TODO: time taken
return
oops :
c . log . Write ( "" , LOG_ERROR , "[%s] %s %s - %s" , req . RemoteAddr , req . Method , req . URL . String ( ) , err . Error ( ) )
return
2024-11-28 01:29:02 +09:00
2024-11-26 09:41:15 +09:00
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
func ( ctl * client_ctl_clients ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
}
2024-11-25 22:55:03 +09:00
// ------------------------------------
2024-11-25 19:46:18 +09:00
func ( ctl * client_ctl_clients_id ) ServeHTTP ( w http . ResponseWriter , req * http . Request ) {
}