diff options
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | main.go | 118 |
2 files changed, 125 insertions, 0 deletions
@@ -1,2 +1,9 @@ | |||
1 | Diffusion | 1 | Diffusion |
2 | ========= | 2 | ========= |
3 | |||
4 | Diffusion is a simple websocket broadcaster written in Go. | ||
5 | |||
6 | Everything sent on /b/{{channel}} is broadcast to every connection on /{{channel}}. | ||
7 | |||
8 | Broadcaster and client accesses can be restricted by a key for each and they will have to connect to /b/{{channel}}?{{broadcaster key}} or /{{channel}}?{{client key}}. | ||
9 | These keys are definable using command line arguments when starting the program. \ No newline at end of file | ||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | |||
3 | This file is part of Diffusion (https://github.com/Pacien/Diffusion) | ||
4 | |||
5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
6 | of this software and associated documentation files (the "Software"), to deal | ||
7 | in the Software without restriction, including without limitation the rights | ||
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
9 | copies of the Software, and to permit persons to whom the Software is | ||
10 | furnished to do so, subject to the following conditions: | ||
11 | |||
12 | The above copyright notice and this permission notice shall be included in | ||
13 | all copies or substantial portions of the Software. | ||
14 | |||
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
21 | THE SOFTWARE. | ||
22 | |||
23 | */ | ||
24 | |||
25 | // Diffusion | ||
26 | package main | ||
27 | |||
28 | import ( | ||
29 | "code.google.com/p/go.net/websocket" | ||
30 | "flag" | ||
31 | "log" | ||
32 | "net/http" | ||
33 | "strings" | ||
34 | ) | ||
35 | |||
36 | var broadcastKey = flag.String("broadcastKey", "", "Secret key for braodcasting.") | ||
37 | var clientKey = flag.String("revieveKey", "", "Secret key for recieving.") | ||
38 | |||
39 | func splitRequest(ws *websocket.Conn, base string) (channelName string, arguments []string) { | ||
40 | request := strings.Split(ws.Request().RequestURI[len(base):], "?") | ||
41 | channelName = request[0] | ||
42 | if len(request) > 1 { | ||
43 | arguments = strings.Split(request[1], "&") | ||
44 | } | ||
45 | return | ||
46 | } | ||
47 | |||
48 | func auth(submittedKey string, key *string) bool { | ||
49 | if *key == "" || submittedKey == *key { | ||
50 | return true | ||
51 | } | ||
52 | return false | ||
53 | } | ||
54 | |||
55 | var clients = make(map[string]map[int]chan []byte) | ||
56 | |||
57 | func broadcastHandler(ws *websocket.Conn) { | ||
58 | |||
59 | channelName, arguments := splitRequest(ws, "/b/") | ||
60 | |||
61 | log.Println("New broadcaster on #" + channelName) | ||
62 | |||
63 | if !auth(arguments[0], broadcastKey) { | ||
64 | return | ||
65 | } | ||
66 | |||
67 | var message = make([]byte, 512) | ||
68 | |||
69 | for { | ||
70 | ws.Read(message) | ||
71 | |||
72 | log.Println("#" + channelName + ": " + string(message)) | ||
73 | |||
74 | for _, client := range clients[channelName] { | ||
75 | client <- message | ||
76 | } | ||
77 | } | ||
78 | |||
79 | } | ||
80 | |||
81 | func clientHandler(ws *websocket.Conn) { | ||
82 | |||
83 | channelName, arguments := splitRequest(ws, "/") | ||
84 | |||
85 | log.Println("New client on #" + channelName) | ||
86 | |||
87 | if !auth(arguments[0], clientKey) { | ||
88 | return | ||
89 | } | ||
90 | |||
91 | var channel = make(chan []byte) | ||
92 | |||
93 | clientID := len(clients[channelName]) | ||
94 | if clientID < 1 { | ||
95 | clients[channelName] = make(map[int]chan []byte) | ||
96 | } | ||
97 | clients[channelName][clientID] = channel | ||
98 | defer delete(clients[channelName], clientID) | ||
99 | |||
100 | for { | ||
101 | ws.Write(<-channel) | ||
102 | } | ||
103 | |||
104 | } | ||
105 | |||
106 | func main() { | ||
107 | |||
108 | flag.Parse() | ||
109 | |||
110 | http.Handle("/b/", websocket.Handler(broadcastHandler)) | ||
111 | http.Handle("/", websocket.Handler(clientHandler)) | ||
112 | |||
113 | err := http.ListenAndServe(":8080", nil) | ||
114 | if err != nil { | ||
115 | panic("ListenAndServe: " + err.Error()) | ||
116 | } | ||
117 | |||
118 | } | ||