Skip to content

Instantly share code, notes, and snippets.

@cawa87
Created February 9, 2017 16:00
Show Gist options
  • Save cawa87/45f2e1fbc01c074d1aad37e08afd3f27 to your computer and use it in GitHub Desktop.
Save cawa87/45f2e1fbc01c074d1aad37e08afd3f27 to your computer and use it in GitHub Desktop.
Websocket server
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