예제 #1
0
func (server *Server) pushWebSocket(p *proto.Proto, conn *websocket.Conn) (err error) {

	err = p.WriteWebsocket(conn)
	//log.Debugln(p)
	if err == nil {
		if p.Ensure {
			// if failed : message will be send next time
			server.pushRpc.PushEnsure(p)
		}
	}
	return err
}
예제 #2
0
func (server *Server) wsSubscribe(conn *websocket.Conn, p *proto.Proto) (userid int64, topics []int32, token string, err error) {
	if err = p.ReadWebsocket(conn); err != nil {
		return
	}
	if p.OpCode != define.OP_SUB_REQ {
		err = ErrOperation
		return
	}

	sub := new(proto.SubREQ)
	err = ffjson.Unmarshal(p.Body, sub)
	if err != nil {
		return
	}
	sub.Server = server.Config.Id
	if err = server.Subscribe(sub); err != nil {
		return
	}
	userid = sub.UserId
	topics = sub.Topics
	token = sub.Token
	p.Body = nil
	p.OpCode = define.OP_SUB_RES
	err = p.WriteWebsocket(conn)
	return
}
예제 #3
0
func (server *Server) processWriteWebsocket(userid int64, conn *websocket.Conn, ch *Channel) {
	var (
		p   *proto.Proto
		err error
	)
	for {
		p = ch.GetProto()

		switch p {
		case proto.ProtoFinish:
			goto failed
		case proto.ProtoReady:
			for {
				if p, err = ch.ProtoRing.Get(); err != nil {
					break
				}

				if err = server.pushWebSocket(p, conn); err != nil {
					log.Debugf("server.pushWebSocket  failed : %v", err)
					goto failed
				}

				p.Body = nil
				ch.ProtoRing.GetAdv()
			}
		default:
			if err = server.pushWebSocket(p, conn); err != nil {
				log.Debugf("server.pushWebSocket  failed : %v", err)
				goto failed
			}
		}
	}
failed:
	conn.Close()
	ch.DiscardAllProto()
	if isDebug {
		//log.Debugf("userid: %v processWriteWebsocket goroutine exit", userid)
	}
	return
}
예제 #4
0
func (server *Server) subscribeWS(conn *websocket.Conn) {
	var (
		err    error
		userid int64
		p      *proto.Proto
		b      *Bucket
		trd    *itime.TimerData
		ch     = NewChannel(server.Config.Bucket.Channel.RingBufferSize, server.Config.Bucket.Channel.PushBufferSize)
		topics []int32
		tr     = server.round.Timer(rand.Int())
		token  string
	)

	//
	if p, err = ch.ProtoRing.Set(); err == nil {
		if userid, topics, token, err = server.wsSubscribe(conn, p); err == nil {
			b = server.Bucket(userid)
			if tch := b.Channel(userid); tch != nil {
				conn.Close()
				return
			}
			err = b.Put(userid, ch)
		} else {
			log.Errorf("wsSubscribe failed user(%d) failed : %v", userid, err)
		}
	}
	if err != nil {
		conn.Close()
		log.Errorf("handshake failed : %v", err)
		return
	}

	//
	trd = tr.Add(time.Duration(server.Config.HeartBeatTimeout), func() {
		conn.Close()
	})

	ch.SetTopics(topics)
	ch.SetToken(token)
	trd.Key = userid
	tr.Set(trd, time.Duration(server.Config.HeartBeatTimeout))

	go server.processWriteWebsocket(userid, conn, ch)
	for {
		if p, err = ch.ProtoRing.Set(); err != nil {
			break
		}
		if err = p.ReadWebsocket(conn); err != nil {
			break
		}

		if p.OpCode == define.OP_HEARTBEAT_REQ {
			// @TODO heartbeat timeout need to close connection
			tr.Set(trd, time.Duration(server.Config.HeartBeatTimeout))
			p.Body = nil
			p.OpCode = define.OP_HEARTBEAT_RES
		}
		ch.ProtoRing.SetAdv()
		ch.Ready()
	}
	conn.Close()
	ch.Close()
	b.DelSafe(userid, ch)

	disArg := &proto.UnSubREQ{userid, server.Config.Id}
	if err = server.UnSubscribe(disArg); err != nil {
		log.Errorf("UnSubscribe user(%d)  failed : %v", userid, err)
	}
	if isDebug {
		//log.Debugf("userid: %d server websocket goroutine exit", userid)
	}
	return
}