Skip to content

Commit d2d1636

Browse files
committed
split into smaller repos
0 parents  commit d2d1636

File tree

7 files changed

+336
-0
lines changed

7 files changed

+336
-0
lines changed

.github/workflows/qa.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
on: push
2+
name: qa
3+
jobs:
4+
code-testing:
5+
runs-on: ubuntu-latest
6+
steps:
7+
- name: Install Go
8+
uses: actions/setup-go@master
9+
with:
10+
go-version: 1.13.x
11+
12+
- name: Fetch Code
13+
uses: actions/checkout@master
14+
15+
- name: Fetch Dependencies
16+
run: go get -v -t -d ./...
17+
18+
- name: Run
19+
run: go test ./...
20+
21+
code-coverage:
22+
runs-on: ubuntu-latest
23+
steps:
24+
- name: Install Go
25+
uses: actions/setup-go@master
26+
with:
27+
go-version: 1.13.x
28+
29+
- name: Fetch Code
30+
uses: actions/checkout@master
31+
32+
- name: Fetch Dependencies
33+
run: go get -v -t -d ./...
34+
35+
- name: Run
36+
run: go test -cover ./...
37+
38+
code-benchmark:
39+
runs-on: ubuntu-latest
40+
steps:
41+
- name: Install Go
42+
uses: actions/setup-go@master
43+
with:
44+
go-version: 1.13.x
45+
46+
- name: Fetch Code
47+
uses: actions/checkout@master
48+
49+
- name: Fetch Dependencies
50+
run: go get -v -t -d ./...
51+
52+
- name: Run
53+
run: go test -bench=. ./...

.helper-files/Vagrantfile

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
Vagrant.configure("2") do |config|
2+
3+
config.vm.define "windows" do |win|
4+
win.vm.box = "gusztavvargadr/windows-10"
5+
end
6+
7+
config.vm.define "raspbian" do |raspbian|
8+
raspbian.vm.box = "gvfoster/raspbian"
9+
end
10+
11+
config.vm.define "centos" do |centos|
12+
centos.vm.box = "centos/7 "
13+
end
14+
15+
config.vm.define "ubuntu" do |ubuntu|
16+
ubuntu.vm.box = "ubuntu/trusty64"
17+
end
18+
19+
config.vm.define "mac" do |mac|
20+
mac.vm.box = "AndrewDryga/vagrant-box-osx"
21+
end
22+
23+
# Tuning
24+
#
25+
# config.vm.provider "virtualbox" do |vb|
26+
# # Display the VirtualBox GUI when booting the machine
27+
# vb.gui = true
28+
#
29+
# # Customize the amount of memory on the VM:
30+
# vb.memory = "1024"
31+
# end
32+
#
33+
34+
end

go.mod

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module github.com/codemodify/systemkit-appserver-websockets
2+
3+
go 1.13
4+
5+
require (
6+
github.com/codemodify/systemkit-appserver v1.7.8
7+
github.com/codemodify/systemkit-appserver-http v0.0.0-20200405082336-855e3625f712
8+
github.com/codemodify/systemkit-helpers-channels v1.7.9
9+
github.com/gorilla/mux v1.7.4
10+
github.com/gorilla/websocket v1.4.2
11+
)

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
github.com/codemodify/systemkit-appserver v1.7.8 h1:IlBtuKVPWEWx9qiIGu1TTBr/bDxr/HUDIE7g32eHymI=
2+
github.com/codemodify/systemkit-appserver v1.7.8/go.mod h1:VJBVIgxMncYBJYSC9GAK5heqEPxA/vFQRT4yeAND87k=
3+
github.com/codemodify/systemkit-appserver-http v0.0.0-20200405082336-855e3625f712 h1:tM7xWAkc1bOHjMWaOXdBE80agBKXY90IcYaswPwyMok=
4+
github.com/codemodify/systemkit-appserver-http v0.0.0-20200405082336-855e3625f712/go.mod h1:niwj7DHxNr8aKK0UVu38T3LBnWCqK6n0b35Kjc2Ujss=
5+
github.com/codemodify/systemkit-helpers-channels v1.7.9 h1:35Jcy2k42jyNK+YN4YlpcAAu3Q66KVy3CWNCpniqG4c=
6+
github.com/codemodify/systemkit-helpers-channels v1.7.9/go.mod h1:8IcL2xCcLK+ZxnB+eo68nNzByBktWAUR+R8cBe8tuyc=
7+
github.com/codemodify/systemkit-helpers-reflection v1.7.9 h1:vPsYvbOiEZHT+rpoXlRx14IvzsKEAkYy7Aw2QEjF/G0=
8+
github.com/codemodify/systemkit-helpers-reflection v1.7.9/go.mod h1:HunZSrygIcl5IBmnWAYoDoqvFRVu7GIUvC0/scCfPzY=
9+
github.com/codemodify/systemkit-logging v1.7.9 h1:cGJu0WSQ8IpBHT/VaiDBvulGtQxY6DE1OpQAeVb9Sr4=
10+
github.com/codemodify/systemkit-logging v1.7.9/go.mod h1:29Zc9P/MnY2bgenJU9aoDszUef+Xf40b3ajtusTBC1Q=
11+
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
12+
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
13+
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
14+
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
15+
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
16+
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=

license

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# The Free License
3+
# https://github.com/codemodify/TheFreeLicense
4+
#
5+
# ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~
6+
# @Authors : Nicolae Carabut
7+
# @URLs : https://github.com/codemodify/systemkit-appserver-websockets
8+
# @Contributors :
9+
# ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~ ~~~~
10+
#
11+
# You can do whatever you please with this.
12+
# If you manage to shoot yourself in the foot, create a support ticket.
13+
#

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
`systemkit-appserver-websockets` is a component from `systemkit-appserver`

web-sockets.go

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package servers
2+
3+
import (
4+
"log"
5+
"net"
6+
"net/http"
7+
"sync"
8+
9+
"github.com/gorilla/mux"
10+
"github.com/gorilla/websocket"
11+
12+
appServer "github.com/codemodify/systemkit-appserver"
13+
httpServer "github.com/codemodify/systemkit-appserver-http"
14+
channels "github.com/codemodify/systemkit-helpers-channels"
15+
)
16+
17+
// WebScoketsRequestHandler -
18+
type WebScoketsRequestHandler func(inChannel chan []byte, outChannel chan []byte)
19+
20+
// WebSocketsHandler -
21+
type WebSocketsHandler struct {
22+
Route string
23+
Handler WebScoketsRequestHandler
24+
}
25+
26+
// WebScoketsServer -
27+
type WebScoketsServer struct {
28+
handlers []WebSocketsHandler
29+
routeToHandler map[string]WebSocketsHandler
30+
HTTPServer appServer.IServer
31+
peers []*websocket.Conn
32+
peersSync sync.RWMutex
33+
enableCORS bool
34+
}
35+
36+
// NewWebSocketsServer -
37+
func NewWebSocketsServer(handlers []WebSocketsHandler) appServer.IServer {
38+
39+
var thisRef = &WebScoketsServer{
40+
handlers: handlers,
41+
routeToHandler: map[string]WebSocketsHandler{},
42+
HTTPServer: nil,
43+
peers: []*websocket.Conn{},
44+
peersSync: sync.RWMutex{},
45+
}
46+
47+
var lowLevelRequestHelper = func(rw http.ResponseWriter, r *http.Request) {
48+
r.Header["Origin"] = nil
49+
50+
var handler WebSocketsHandler = thisRef.routeToHandler[r.URL.Path]
51+
52+
var upgrader = websocket.Upgrader{
53+
CheckOrigin: func(r *http.Request) bool { return thisRef.enableCORS },
54+
}
55+
ws, err := upgrader.Upgrade(rw, r, nil)
56+
if err != nil {
57+
log.Print("upgrade: ", err)
58+
return
59+
}
60+
61+
thisRef.setupCommunication(ws, &handler)
62+
}
63+
64+
var HTTPHandlers = []httpServer.HTTPHandler{}
65+
66+
for _, handler := range thisRef.handlers {
67+
thisRef.routeToHandler[handler.Route] = handler
68+
69+
HTTPHandlers = append(HTTPHandlers, httpServer.HTTPHandler{
70+
Route: handler.Route,
71+
Handler: lowLevelRequestHelper,
72+
Verb: "GET",
73+
})
74+
}
75+
76+
thisRef.HTTPServer = httpServer.NewHTTPServer(HTTPHandlers)
77+
78+
return thisRef
79+
}
80+
81+
// Run - Implement `IServer`
82+
func (thisRef *WebScoketsServer) Run(ipPort string, enableCORS bool) error {
83+
thisRef.enableCORS = enableCORS
84+
return thisRef.HTTPServer.Run(ipPort, enableCORS)
85+
}
86+
87+
// PrepareRoutes - Implement `IServer`
88+
func (thisRef *WebScoketsServer) PrepareRoutes(router *mux.Router) {
89+
thisRef.HTTPServer.PrepareRoutes(router)
90+
}
91+
92+
// RunOnExistingListenerAndRouter - Implement `IServer`
93+
func (thisRef *WebScoketsServer) RunOnExistingListenerAndRouter(listener net.Listener, router *mux.Router, enableCORS bool) {
94+
thisRef.HTTPServer.RunOnExistingListenerAndRouter(listener, router, enableCORS)
95+
}
96+
97+
func (thisRef *WebScoketsServer) setupCommunication(ws *websocket.Conn, handler *WebSocketsHandler) {
98+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: setupCommunication - START")
99+
100+
thisRef.addPeer(ws)
101+
102+
var inChannel = make(chan []byte) // data from WS
103+
var outChannel = make(chan []byte) // data to WS
104+
105+
go handler.Handler(inChannel, outChannel)
106+
107+
var once sync.Once
108+
closeInChannel := func() {
109+
close(inChannel)
110+
}
111+
112+
var wg sync.WaitGroup
113+
114+
wg.Add(1)
115+
go func() {
116+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: SEND-TO-PEER - START")
117+
118+
for {
119+
data, readOk := <-outChannel
120+
if !readOk { // if CHANNEL closed - means communication ended by the handler
121+
// DEBUG: fmt.Println(fmt.Sprint("AppServer-WebScokets-DEBUG: SEND-TO-PEER - communication ended by the handler"))
122+
break
123+
}
124+
125+
// DEBUG: fmt.Println(fmt.Sprint("AppServer-WebScokets-DEBUG: SEND-TO-PEER - DATA: ", string(data)))
126+
127+
err := ws.WriteMessage(websocket.TextMessage, data)
128+
if err != nil { // if can't send - means communication ended by the peer
129+
// DEBUG: fmt.Println(fmt.Sprint("AppServer-WebScokets-DEBUG: SEND-TO-PEER - send - communication ended by the peer"))
130+
break
131+
}
132+
}
133+
134+
once.Do(closeInChannel)
135+
136+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: SEND-TO-PEER - END")
137+
wg.Done()
138+
139+
}()
140+
141+
wg.Add(1)
142+
go func() {
143+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: READ-FROM-PEER - START")
144+
145+
for {
146+
_, data, err := ws.ReadMessage()
147+
if err != nil { // if can't read - means communication ended by the peer
148+
// DEBUG: fmt.Println(fmt.Sprint("AppServer-WebScokets-DEBUG: SEND-FROM-PEER - read - communication ended by the peer"))
149+
once.Do(closeInChannel)
150+
break
151+
}
152+
153+
// DEBUG: fmt.Println(fmt.Sprint("AppServer-WebScokets-DEBUG: READ-FROM-PEER - DATA: ", string(data)))
154+
155+
if channels.IsClosed(inChannel) {
156+
break
157+
}
158+
inChannel <- []byte(data)
159+
}
160+
161+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: READ-FROM-PEER - END")
162+
wg.Done()
163+
}()
164+
165+
wg.Wait()
166+
thisRef.removePeer(ws)
167+
168+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: setupCommunication - DONE")
169+
}
170+
171+
// SendToAllPeers -
172+
func (thisRef *WebScoketsServer) SendToAllPeers(data []byte) {
173+
thisRef.peersSync.RLock()
174+
defer thisRef.peersSync.RUnlock()
175+
176+
for _, conn := range thisRef.peers {
177+
conn.WriteMessage(websocket.TextMessage, data)
178+
}
179+
}
180+
181+
func (thisRef *WebScoketsServer) addPeer(peer *websocket.Conn) {
182+
thisRef.peersSync.Lock()
183+
defer thisRef.peersSync.Unlock()
184+
185+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: addPeer")
186+
187+
thisRef.peers = append(thisRef.peers, peer)
188+
}
189+
190+
func (thisRef *WebScoketsServer) removePeer(peer *websocket.Conn) {
191+
thisRef.peersSync.Lock()
192+
defer thisRef.peersSync.Unlock()
193+
194+
// DEBUG: fmt.Println("AppServer-WebScokets-DEBUG: removePeer")
195+
196+
index := -1
197+
for i, conn := range thisRef.peers {
198+
if conn == peer {
199+
index = i
200+
break
201+
}
202+
}
203+
if index != -1 {
204+
thisRef.peers = append(thisRef.peers[:index], thisRef.peers[index+1:]...)
205+
}
206+
207+
peer.Close()
208+
}

0 commit comments

Comments
 (0)