|
diff --git a/README.md b/README.md index 0bb4db0..efa5cfb 100644 --- a/ README.md+++ b/ README.md |
@@ -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 |
|
|
diff --git a/main.go b/main.go new file mode 100644 index 0000000..bea50be --- /dev/null +++ b/ main.go |
@@ -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 | } |
|