Created
February 9, 2017 16:00
-
-
Save cawa87/45f2e1fbc01c074d1aad37e08afd3f27 to your computer and use it in GitHub Desktop.
Websocket server
This file contains hidden or 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
package main | |
import ( | |
"github.com/googollee/go-socket.io" | |
"log" | |
"github.com/astaxie/goredis" | |
"net/http" | |
"regexp" | |
"os" | |
"encoding/json" | |
"fmt" | |
"gopkg.in/mgo.v2" | |
"gopkg.in/mgo.v2/bson" | |
"time" | |
"strconv" | |
"sort" | |
"github.com/speps/go-hashids" | |
) | |
type Configuration struct { | |
Redis string | |
MongoHost string | |
MongoDb string | |
MongoDbUsername string | |
MongoDbPassword string | |
} | |
type Message struct { | |
ID bson.ObjectId `json:"id" bson:"_id"` | |
Author int `json:"author" bson:"author"` | |
Message string `json:"message" bson:"message"` | |
ConversationId bson.ObjectId `json:"coversation_id" bson:"conversationId"` | |
CreatedAt time.Time `json:"created_at" bson:"createdAt"` | |
} | |
type Conversation struct { | |
ID bson.ObjectId `json:"id" bson:"_id"` | |
Members []int `json:"members" bson:"members"` | |
RoomId string `json:"roomId" bson:"roomId"` | |
} | |
func say(room string, server *socketio.Server) { | |
for i := 0; i < 5; i++ { | |
fmt.Println("say gorutine") | |
server.BroadcastTo(room, "chat message", "chat message") | |
} | |
} | |
func onConnect(so socketio.Socket) { | |
} | |
func getHistory(configuration Configuration, room string, members []int) ([]Message, Conversation) { | |
// mongo | |
log.Println("Conecting to mongo...") | |
session, err := mgo.DialWithInfo(&mgo.DialInfo{ | |
Addrs: []string{configuration.MongoHost}, | |
Username: configuration.MongoDbUsername, | |
Password: configuration.MongoDbPassword, | |
Database: configuration.MongoDb, | |
}) | |
if err != nil { | |
panic(err) | |
} | |
defer session.Close() | |
// Optional. Switch the session to a monotonic behavior. | |
session.SetMode(mgo.Monotonic, true) | |
c := session.DB(configuration.MongoDb).C("conversation") | |
var roomC = Conversation{} | |
log.Println("find by room: ", room) | |
err = c.Find(bson.M{"roomId": room}).One(&roomC) | |
if err != nil { | |
log.Println(err) | |
} | |
fmt.Println("History room: ", roomC.ID) | |
fmt.Println("History room: ", roomC.RoomId) | |
fmt.Println("History room: ", roomC.Members) | |
if roomC.ID == "" { | |
log.Println("creating") | |
// Insert Datas | |
newRoom := Conversation{} | |
newRoom.ID = bson.NewObjectId() | |
newRoom.RoomId = room | |
newRoom.Members = members | |
err = c.Insert(newRoom) | |
if err != nil { | |
panic(err) | |
} | |
log.Println(newRoom) | |
roomC = newRoom | |
} | |
c1 := session.DB(configuration.MongoDb).C("message") | |
var result []Message | |
err = c1.Find(bson.M{"conversationId": roomC.ID}).All(&result) | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println("History Results All: ", result) | |
return result, roomC | |
} | |
func addMessage(configuration Configuration, conversation Conversation, msg string) Message { | |
// mongo | |
log.Println("addMessage") | |
log.Println("addMessage:", conversation) | |
log.Println("addMessage:", msg) | |
res := Message{} | |
res.ID = bson.NewObjectId() | |
res.ConversationId = conversation.ID | |
res.CreatedAt = time.Time{} | |
json.Unmarshal([]byte(msg), &res) | |
session, err := mgo.DialWithInfo(&mgo.DialInfo{ | |
Addrs: []string{configuration.MongoHost}, | |
Username: configuration.MongoDbUsername, | |
Password: configuration.MongoDbPassword, | |
Database: configuration.MongoDb, | |
}) | |
if err != nil { | |
panic(err) | |
} | |
defer session.Close() | |
log.Println(res) | |
// Optional. Switch the session to a monotonic behavior. | |
session.SetMode(mgo.Monotonic, true) | |
c := session.DB(configuration.MongoDb).C("message") | |
log.Println("creating") | |
// Insert Datas | |
err = c.Insert(res) | |
if err != nil { | |
panic(err) | |
} | |
return res | |
} | |
func main() { | |
log.Println("Reading config") | |
file, _ := os.Open("./config.json") | |
decoder := json.NewDecoder(file) | |
configuration := Configuration{} | |
err := decoder.Decode(&configuration) | |
if err != nil { | |
fmt.Println("error:", err) | |
} | |
fmt.Println(configuration) | |
log.Println("Starting socket server...") | |
server, err := socketio.NewServer(nil) | |
if err != nil { | |
log.Fatal(err) | |
} | |
var client goredis.Client | |
// Set the default port in Redis | |
client.Addr = configuration.Redis | |
var clients = make(map[string]socketio.Socket) | |
server.On("connection", func(so socketio.Socket) { | |
log.Println("Client connected:", so) | |
// auth | |
cookie, err := so.Request().Cookie("laravel_session") | |
if err != nil { | |
//log.Fatal(err) | |
so.Emit("disconnect") | |
log.Println("Diconected by auth check") | |
return | |
} | |
val, _ := client.Get("laravel:" + cookie.Value) | |
str := string(val[:]) | |
r, _ := regexp.Compile("(?:\\\"login_web_[\\da-z]+\\\";i:)(\\d+)(?:;)") | |
userId := r.FindStringSubmatch(str) | |
if len(userId) > 0 { | |
log.Println(userId[1]) | |
clients[userId[1]] = so | |
} else { | |
log.Println(cookie.Value) | |
log.Println(val) | |
log.Println(userId) | |
return | |
} | |
room := so.Request().URL.Query().Get("key") | |
roomI, _ := strconv.Atoi(room) | |
userI, _ := strconv.Atoi(userId[1]) | |
var i1 = []int{roomI, userI} | |
sort.Ints(i1) | |
hd := hashids.NewData() | |
hd.Salt = "this is my salt" | |
h := hashids.NewWithData(hd) | |
idR, _ := h.Encode(i1) | |
//numbers, _ := h.DecodeWithError(id) | |
//roomHash :=string(roomI ^ userI) | |
so.Join(idR) | |
log.Println("Joined room:", idR) | |
history, conversation := getHistory(configuration, idR, i1) | |
so.Emit("history", history) | |
so.On("chat message", func(msg string) { | |
log.Println("FROM CLI:", msg) | |
newMessage := addMessage(configuration, conversation, msg) | |
so.BroadcastTo(idR, "chat message", newMessage) | |
/*dataForClient := "HI ACK" | |
//You can use Emit or BroadcastTo with last parameter as callback for handling ack from client | |
//Sending packet to room "room_name" and event "some:event" | |
so.BroadcastTo("room_name", "some:event", dataForClient, func(so socketio.Socket, data string) { | |
log.Println("Client ACK with data: ", data) | |
}) | |
// Or | |
so.Emit("some:event", dataForClient, func(so socketio.Socket, data string) { | |
log.Println("Client ACK with data: ", data) | |
}) | |
*/ | |
log.Println("clients", clients) | |
}) | |
so.On("disconect", func() { | |
log.Println("Client disconected") | |
}) | |
//time.Sleep(5000 * time.Millisecond) | |
//go say("roLtxVe", server) | |
}) | |
server.On("error", func(so socketio.Socket, err error) { | |
log.Println("Error:", err) | |
}) | |
server.On("chat message", func(so socketio.Socket, err error) { | |
log.Println("MESSAGE:", err) | |
}) | |
http.Handle("/socket.io/", server) | |
//http.Handle("/", http.FileServer(http.Dir("./asset"))) | |
log.Println("Serving at localhost:8001...") | |
log.Fatal(http.ListenAndServe(":8001", nil)) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment