-
Notifications
You must be signed in to change notification settings - Fork 829
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a simple-tcp game server to use for testing. (#1071)
- Loading branch information
1 parent
4f9f701
commit 188bd12
Showing
6 changed files
with
283 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Copyright 2019 Google LLC All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
# build | ||
FROM golang:1.11.5 as builder | ||
WORKDIR /go/src/simple-tcp | ||
|
||
COPY examples/simple-tcp/main.go . | ||
COPY . /go/src/agones.dev/agones | ||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server . | ||
|
||
# final image | ||
FROM alpine:3.9 | ||
|
||
RUN adduser -D server | ||
COPY --from=builder /go/src/simple-tcp/server /home/server/server | ||
RUN chown -R server /home/server && \ | ||
chmod o+x /home/server/server | ||
|
||
USER server | ||
ENTRYPOINT ["/home/server/server"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# Copyright 2019 Google LLC All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
# | ||
# Makefile for building a simple tcp server | ||
# | ||
|
||
# __ __ _ _ _ | ||
# \ \ / /_ _ _ __(_) __ _| |__ | | ___ ___ | ||
# \ \ / / _` | '__| |/ _` | '_ \| |/ _ \ __| | ||
# \ V / (_| | | | | (_| | |_) | | __\__ \ | ||
# \_/ \__,_|_| |_|\__,_|_.__/|_|\___|___/ | ||
# | ||
|
||
REPOSITORY = gcr.io/agones-images | ||
|
||
mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST))) | ||
project_path := $(dir $(mkfile_path)) | ||
server_tag = $(REPOSITORY)/tcp-server:0.1 | ||
root_path = $(realpath $(project_path)/../..) | ||
|
||
# _____ _ | ||
# |_ _|_ _ _ __ __ _ ___| |_ ___ | ||
# | |/ _` | '__/ _` |/ _ \ __/ __| | ||
# | | (_| | | | (_| | __/ |_\__ \ | ||
# |_|\__,_|_| \__, |\___|\__|___/ | ||
# |___/ | ||
|
||
# Build a docker image for the server, and tag it | ||
build: | ||
cd $(root_path) && docker build -f $(project_path)/Dockerfile --tag=$(server_tag) . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Simple TCP Server | ||
|
||
A very simple game server, for the purposes of testing a TCP based server on Agones. | ||
|
||
## Server | ||
Starts a server on port `7654` by default. Can be overwritten by `PORT` env var or `port` flag. | ||
|
||
When it receives a text message ending with a newline, it will send back "ACK:<text content>" as an echo. | ||
|
||
If it receives the text "EXIT", then it will `sys.Exit(0)` | ||
|
||
## Firewalls | ||
|
||
If you plan to access your server remotely, you may need to open up a hole in your | ||
firewall. | ||
|
||
For example, if you created a cluster running on Google Kubernetes Engine following | ||
the installation guide, you can create a firewall rule to allow TCP traffic to nodes | ||
tagged as game-server via ports 7000-8000. | ||
|
||
```bash | ||
gcloud compute firewall-rules create game-server-firewall-tcp \ | ||
--allow tcp:7000-8000 \ | ||
--target-tags game-server \ | ||
--description "Firewall to allow game server udp traffic" | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# Copyright 2019 Google LLC All Rights Reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
apiVersion: "agones.dev/v1" | ||
kind: GameServer | ||
metadata: | ||
generateName: "simple-tcp-" | ||
spec: | ||
ports: | ||
- name: default | ||
portPolicy: Dynamic | ||
containerPort: 7654 | ||
protocol: TCP | ||
template: | ||
spec: | ||
containers: | ||
- name: simple-tcp | ||
image: gcr.io/agones-images/tcp-server:0.1 | ||
resources: | ||
requests: | ||
memory: "32Mi" | ||
cpu: "20m" | ||
limits: | ||
memory: "32Mi" | ||
cpu: "20m" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
// Copyright 2019 Google LLC All Rights Reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Package main is a very simple echo TCP server | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"flag" | ||
"log" | ||
"net" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"agones.dev/agones/pkg/util/signals" | ||
sdk "agones.dev/agones/sdks/go" | ||
) | ||
|
||
// main starts a TCP server that receives a message at a time | ||
// (newline delineated), and echos the output. | ||
func main() { | ||
go doSignal() | ||
|
||
port := flag.String("port", "7654", "The port to listen to tcp traffic on") | ||
flag.Parse() | ||
if ep := os.Getenv("PORT"); ep != "" { | ||
port = &ep | ||
} | ||
|
||
log.Printf("Starting TCP server, listening on port %s", *port) | ||
ln, err := net.Listen("tcp", ":"+*port) | ||
if err != nil { | ||
log.Fatalf("Could not start tcp server: %v", err) | ||
} | ||
defer ln.Close() // nolint: errcheck | ||
|
||
log.Print("Creating SDK instance") | ||
s, err := sdk.NewSDK() | ||
if err != nil { | ||
log.Fatalf("Could not connect to sdk: %v", err) | ||
} | ||
|
||
log.Print("Starting Health Ping") | ||
stop := make(chan struct{}) | ||
go doHealth(s, stop) | ||
|
||
log.Print("Marking this server as ready") | ||
if err := s.Ready(); err != nil { | ||
log.Fatalf("Could not send ready message") | ||
} | ||
|
||
for { | ||
conn, err := ln.Accept() | ||
if err != nil { | ||
log.Printf("Unable to accept incoming tcp connection: %v", err) | ||
} | ||
go handleConnection(conn, stop, s) | ||
} | ||
} | ||
|
||
// doSignal shutsdown on SIGTERM/SIGKILL | ||
func doSignal() { | ||
stop := signals.NewStopChannel() | ||
<-stop | ||
log.Println("Exit signal received. Shutting down.") | ||
os.Exit(0) | ||
} | ||
|
||
// handleConnection services a single tcp connection to the server | ||
func handleConnection(conn net.Conn, stop chan struct{}, s *sdk.SDK) { | ||
log.Printf("Client %s connected", conn.RemoteAddr().String()) | ||
scanner := bufio.NewScanner(conn) | ||
for { | ||
if ok := scanner.Scan(); !ok { | ||
log.Printf("Client %s disconnected", conn.RemoteAddr().String()) | ||
return | ||
} | ||
handleCommand(conn, scanner.Text(), stop, s) | ||
} | ||
} | ||
|
||
// respond responds to a given sender. | ||
func respond(conn net.Conn, txt string) { | ||
log.Printf("Responding with %q", txt) | ||
if _, err := conn.Write([]byte(txt+"\n")); err != nil { | ||
log.Fatalf("Could not write to tcp stream: %v", err) | ||
} | ||
} | ||
|
||
func handleCommand(conn net.Conn, txt string, stop chan struct{}, s *sdk.SDK) { | ||
parts := strings.Split(strings.TrimSpace(txt), " ") | ||
|
||
log.Printf("parts: %v", parts) | ||
switch parts[0] { | ||
// shuts down the gameserver | ||
case "EXIT": | ||
respond(conn, "ACK: "+txt) | ||
exit(s) | ||
|
||
// turns off the health pings | ||
case "UNHEALTHY": | ||
close(stop) | ||
} | ||
|
||
respond(conn, "ACK: "+txt+"\n") | ||
} | ||
|
||
// exit shutdowns the server | ||
func exit(s *sdk.SDK) { | ||
log.Printf("Received EXIT command. Exiting.") | ||
// This tells Agones to shutdown this Game Server | ||
if err := s.Shutdown(); err != nil { | ||
log.Printf("Could not call shutdown: %v", err) | ||
} | ||
os.Exit(0) | ||
} | ||
|
||
// doHealth sends the regular Health Pings | ||
func doHealth(sdk *sdk.SDK, stop <-chan struct{}) { | ||
tick := time.Tick(2 * time.Second) | ||
for { | ||
if err := sdk.Health(); err != nil { | ||
log.Fatalf("Could not send health ping: %v", err) | ||
} | ||
select { | ||
case <-stop: | ||
log.Print("Stopped health pings") | ||
return | ||
case <-tick: | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters