used random names to identify the agents for execution of commands, moved agentCreate step from the agent itself to the websocket server. THis means a more simple agent is possible, because it only needs to do a single request to the websocket. Cleanup needed now
This commit is contained in:
		
							parent
							
								
									54604ff488
								
							
						
					
					
						commit
						c0764ac41d
					
				| 
						 | 
				
			
			@ -61,8 +61,8 @@ func registerAgent(agentName, agentId, agentIp, agentType string) error {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func connectToWebSocket(agentName, agentIp string) error {
 | 
			
		||||
	wsURL := fmt.Sprintf("ws://%s/data?agentName=%s&IPv4Address=%s", webSocketAddr, url.QueryEscape(agentName), url.QueryEscape(agentIp))
 | 
			
		||||
func connectToWebSocket(agentName, agentId, agentIp, agentType string) error {
 | 
			
		||||
	wsURL := fmt.Sprintf("ws://%s/data?agentName=%s&agentId=%s&IPv4Address=%s&agentType=%s", webSocketAddr, url.QueryEscape(agentName), url.QueryEscape(agentId), url.QueryEscape(agentIp), url.QueryEscape(agentType))
 | 
			
		||||
	var err error
 | 
			
		||||
	for {
 | 
			
		||||
		conn, _, err = websocket.DefaultDialer.Dial(wsURL, nil)
 | 
			
		||||
| 
						 | 
				
			
			@ -76,13 +76,13 @@ func connectToWebSocket(agentName, agentIp string) error {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func reconnectToWebSocket(agentName, agentIp string) error {
 | 
			
		||||
func reconnectToWebSocket(agentName, agentId, agentIp, agentType string) error {
 | 
			
		||||
	backoff := 2 * time.Second
 | 
			
		||||
	maxBackoff := 1 * time.Minute
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		log.Println("Attempting to reconnect to WebSocket...")
 | 
			
		||||
		err := connectToWebSocket(agentName, agentIp)
 | 
			
		||||
		err := connectToWebSocket(agentName, agentId, agentIp, agentType)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			log.Println("Reconnection succesful.")
 | 
			
		||||
			return nil
 | 
			
		||||
| 
						 | 
				
			
			@ -98,14 +98,14 @@ func reconnectToWebSocket(agentName, agentIp string) error {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func listenForCommands(agentName, agentIp string) {
 | 
			
		||||
func listenForCommands(agentName, agentId, agentIp, agentType string) {
 | 
			
		||||
	defer conn.Close()
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		_, rawMessage, err := conn.ReadMessage()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("Connection lost: %v", err)
 | 
			
		||||
			if reconnectErr := reconnectToWebSocket(agentName, agentIp); reconnectErr != nil {
 | 
			
		||||
			if reconnectErr := reconnectToWebSocket(agentName, agentId, agentIp, agentType); reconnectErr != nil {
 | 
			
		||||
				log.Printf("Critical error during reconnection: %v", reconnectErr)
 | 
			
		||||
				}
 | 
			
		||||
			continue
 | 
			
		||||
| 
						 | 
				
			
			@ -161,13 +161,15 @@ func main() {
 | 
			
		|||
	agentIp := "127.0.0.1"
 | 
			
		||||
	agentType := "BaseAgent"
 | 
			
		||||
 | 
			
		||||
	if err := registerAgent(agentName, agentId, agentIp, agentType); err != nil {
 | 
			
		||||
		log.Fatalf("Agent registration failed: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	log.Printf("AgentId: %s", agentId)
 | 
			
		||||
 | 
			
		||||
	if err := connectToWebSocket(agentName, agentIp); err != nil {
 | 
			
		||||
	// if err := registerAgent(agentName, agentId, agentIp, agentType); err != nil {
 | 
			
		||||
	// 	log.Fatalf("Agent registration failed: %v", err)
 | 
			
		||||
	// }
 | 
			
		||||
 | 
			
		||||
	if err := connectToWebSocket(agentName, agentId, agentIp, agentType); err != nil {
 | 
			
		||||
		log.Fatalf("Websocket connection failed: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	listenForCommands(agentName, agentIp)
 | 
			
		||||
	listenForCommands(agentName, agentId, agentIp, agentType)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										7
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -3,9 +3,14 @@ module gontrol
 | 
			
		|||
go 1.23.4
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/PuerkitoBio/goquery v1.10.1
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.8.1
 | 
			
		||||
	github.com/gorilla/websocket v1.5.3
 | 
			
		||||
	github.com/kelseyhightower/envconfig v1.4.0
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require filippo.io/edwards25519 v1.1.0 // indirect
 | 
			
		||||
require (
 | 
			
		||||
	filippo.io/edwards25519 v1.1.0 // indirect
 | 
			
		||||
	github.com/andybalholm/cascadia v1.3.3 // indirect
 | 
			
		||||
	golang.org/x/net v0.33.0 // indirect
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										70
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										70
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -1,8 +1,78 @@
 | 
			
		|||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
 | 
			
		||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
 | 
			
		||||
github.com/PuerkitoBio/goquery v1.10.1 h1:Y8JGYUkXWTGRB6Ars3+j3kN0xg1YqqlwvdTV8WTFQcU=
 | 
			
		||||
github.com/PuerkitoBio/goquery v1.10.1/go.mod h1:IYiHrOMps66ag56LEH7QYDDupKXyo5A8qrjIx3ZtujY=
 | 
			
		||||
github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
 | 
			
		||||
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
 | 
			
		||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 | 
			
		||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 | 
			
		||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 | 
			
		||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
 | 
			
		||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
 | 
			
		||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
			
		||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
 | 
			
		||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
 | 
			
		||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 | 
			
		||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
 | 
			
		||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
			
		||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
			
		||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
			
		||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
			
		||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
			
		||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 | 
			
		||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 | 
			
		||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 | 
			
		||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 | 
			
		||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
 | 
			
		||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 | 
			
		||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
 | 
			
		||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 | 
			
		||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
			
		||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
			
		||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
			
		||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 | 
			
		||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 | 
			
		||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
 | 
			
		||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
 | 
			
		||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
 | 
			
		||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
			
		||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 | 
			
		||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 | 
			
		||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 | 
			
		||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
			
		||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
			
		||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
			
		||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 | 
			
		||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 | 
			
		||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										6
									
								
								main.go
								
								
								
								
							
							
						
						
									
										6
									
								
								main.go
								
								
								
								
							| 
						 | 
				
			
			@ -129,6 +129,11 @@ func getAgentNames(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getAgentIds(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	api.GetAgentIds(db, w, r)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -146,6 +151,7 @@ func main() {
 | 
			
		|||
	webMux.HandleFunc("/", getHomepage)
 | 
			
		||||
	webMux.HandleFunc("/agents", agentsHandler)
 | 
			
		||||
	webMux.HandleFunc("/agentNames", getAgentNames)
 | 
			
		||||
	webMux.HandleFunc("/agentIds", getAgentIds)
 | 
			
		||||
	webMux.HandleFunc("/agents/{agentId}", agentsHandler)
 | 
			
		||||
 | 
			
		||||
	initDB (cfg.Database.Username, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,8 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"log"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +55,7 @@ func CreateAgent(db *sql.DB, w http.ResponseWriter, r * http.Request) (http.Resp
 | 
			
		|||
	query := "INSERT INTO agents (agentId, agentName, agentType, IPv4Address, initialContact, lastContact) VALUES (?, ?, ?, ?, NOW(), NOW())"
 | 
			
		||||
	_, err = db.Exec(query, agentId, agentName, agentType, IPv4Address)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Database err is: %s", err)
 | 
			
		||||
		http.Error(w, "Failed to create agent", http.StatusInternalServerError)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -140,3 +143,27 @@ func GetAgentNames(db *sql.DB, w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(agentNames)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func GetAgentIds(db *sql.DB, w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	query := "SELECT agentId from agents"
 | 
			
		||||
	rows, err := db.Query(query)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, "Failed to fetch agent names", http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	var agentIds []string
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		var id int
 | 
			
		||||
		if err := rows.Scan(&id); err != nil {
 | 
			
		||||
			http.Error(w, "Error reading agent names", http.StatusInternalServerError)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		agentIds = append(agentIds, strconv.Itoa(id))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	w.Header().Set("Content-Type", "application/json")
 | 
			
		||||
	json.NewEncoder(w).Encode(agentIds)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,16 +1,26 @@
 | 
			
		|||
package websocketserver
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"gontrol/src/randomname"
 | 
			
		||||
	"gontrol/src/server/api"
 | 
			
		||||
	"io"
 | 
			
		||||
	"log"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/PuerkitoBio/goquery"
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var responseChannels sync.Map // Key: agentName, Value: chan string
 | 
			
		||||
var db 	 *sql.DB
 | 
			
		||||
 | 
			
		||||
type webSocketHandler struct {
 | 
			
		||||
	upgrader websocket.Upgrader
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +42,111 @@ var getAgentNames http.HandlerFunc = func(w http.ResponseWriter, r *http.Request
 | 
			
		|||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func registerAgent(agentName, agentId, agentIp, agentType string) error {
 | 
			
		||||
 | 
			
		||||
	registerURL := "http://localhost:3333/agents"
 | 
			
		||||
 | 
			
		||||
	form := url.Values{}
 | 
			
		||||
	form.Add("agentId", agentId)
 | 
			
		||||
	form.Add("agentName", agentName)
 | 
			
		||||
	form.Add("agentType", agentType)
 | 
			
		||||
	form.Add("IPv4Address", agentIp)
 | 
			
		||||
 | 
			
		||||
	resp, err := http.PostForm(registerURL, form)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Error registering agent: %v", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode == http.StatusCreated {
 | 
			
		||||
		log.Printf("Agent %s successfully registered.", agentName)
 | 
			
		||||
		return nil
 | 
			
		||||
	} else if resp.StatusCode == http.StatusOK {
 | 
			
		||||
		log.Printf("Agent %s already registered.", agentName)
 | 
			
		||||
		return nil
 | 
			
		||||
	} else {
 | 
			
		||||
		log.Printf("Failed to register agent, status: %v", resp.Status)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// log.Printf("Agent %s successfully registered.", agentName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getAgentDetails(agentId string) (*api.Agent, error) {
 | 
			
		||||
	agentURL := "http://localhost:3333/agents/" + agentId
 | 
			
		||||
	// var ids []string
 | 
			
		||||
	resp, err := http.Get(agentURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to make GET request: %w", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	doc, err := goquery.NewDocumentFromReader(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to parse HTML: %w", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	agent := &api.Agent{}
 | 
			
		||||
	doc.Find("#agent-detail p").Each(func(i int, s *goquery.Selection) {
 | 
			
		||||
		text := s.Text()
 | 
			
		||||
		if strings.HasPrefix(text, "ID:") {
 | 
			
		||||
			agent.AgentID, err = strconv.Atoi(strings.TrimSpace(strings.TrimPrefix(text, "ID:")))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Printf("Converting string to integer failed in getAgentDetails(): %w", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if strings.HasPrefix(text, "Name:") {
 | 
			
		||||
			agent.AgentName = strings.TrimSpace(strings.TrimPrefix(text, "Name:"))
 | 
			
		||||
		} else if strings.HasPrefix(text, "Type:") {
 | 
			
		||||
			agent.AgentType = strings.TrimSpace(strings.TrimPrefix(text, "Type:"))
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	return agent, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func containsId(ids []string, agentId string) bool {
 | 
			
		||||
	for _, id := range ids {
 | 
			
		||||
		if id == agentId {
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getAgentIds() ([]string, error) {
 | 
			
		||||
 | 
			
		||||
	idURL := "http://localhost:3333/agentIds"
 | 
			
		||||
	// var ids []string
 | 
			
		||||
	resp, err := http.Get(idURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to make GET request: %w", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode != http.StatusOK {
 | 
			
		||||
		log.Printf("Unexpected status code: %d", resp.StatusCode)
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	body, err := io.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to read response body: %w", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var agentIds []string
 | 
			
		||||
	if err := json.Unmarshal(body, &agentIds); err != nil {
 | 
			
		||||
		log.Printf("Failed to parse JSON response: %w", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return agentIds, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
 | 
			
		||||
	c, err := wsh.upgrader.Upgrade(w, r, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -39,15 +154,32 @@ func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	agentName := r.URL.Query().Get("agentName")
 | 
			
		||||
	agentIP := r.URL.Query().Get("IPv4Address")
 | 
			
		||||
	agentId := r.URL.Query().Get("agentId")
 | 
			
		||||
	agentType := r.URL.Query().Get("agentType")
 | 
			
		||||
	agentName := ""
 | 
			
		||||
 | 
			
		||||
	agentIds, err := getAgentIds()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Error %v\n", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !containsId(agentIds, agentId) {
 | 
			
		||||
		agentName = randomname.GenerateRandomName()
 | 
			
		||||
		registerAgent(agentName, agentId, agentIP, agentType)
 | 
			
		||||
	} else {
 | 
			
		||||
		agentDetails, _ :=  getAgentDetails(agentId)
 | 
			
		||||
		agentName = agentDetails.AgentName
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if agentName == "" || agentIP == "" {
 | 
			
		||||
		log.Printf("Missing agentName or IPv4Address in query parameters")
 | 
			
		||||
		c.Close()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Printf("Agent connected: %s (%s)", agentName, agentIP)
 | 
			
		||||
	log.Printf("Agent %s connected: %s (%s)", agentId, agentName, agentIP)
 | 
			
		||||
 | 
			
		||||
	agentSocketsMutex.Lock()
 | 
			
		||||
	agentSockets[agentName] = c
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,7 @@
 | 
			
		|||
            })
 | 
			
		||||
            .catch(error => console.error('Error fetching agent names:', error));
 | 
			
		||||
 | 
			
		||||
        const socket = new WebSocket("ws://localhost:5555/data");
 | 
			
		||||
        const socket = new WebSocket("ws://localhost:5555/executeCommand");
 | 
			
		||||
        socket.onmessage = (event) => {
 | 
			
		||||
            const message = JSON.parse(event.data);
 | 
			
		||||
            if (message.type === 'response') {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue