예제 #1
0
func (this *MsgBusManager) NotifyBindedIdChanged(deviceId int64, newBindIds []int64, unbindIds []int64) {
	// new code
	body := msgs.MsgStatus{}
	body.Id = deviceId
	m := msgs.NewMsg(nil, nil)
	m.FrameHeader.SrcId = deviceId
	m.FrameHeader.Opcode = 2
	m.DataHeader.MsgId = msgs.MIDStatus
	if len(newBindIds) > 0 {
		body.Type = msgs.MSTBinded
		m.Data, _ = body.Marshal()
		GMsgBusManager.Push2Bus(0, newBindIds, m.MarshalBytes())
	}
	if len(unbindIds) > 0 {
		body.Type = msgs.MSTUnbinded
		m.Data, _ = body.Marshal()
		GMsgBusManager.Push2Bus(0, unbindIds, m.MarshalBytes())
	}

	// old code
	//m := msgs.NewAppMsg(0, deviceId, msgs.MIDBind)
	//if len(newBindIds) > 0 {
	//	GMsgBusManager.Push2Backend(0, newBindIds, m.MarshalBytes())
	//}
	//if len(unbindIds) > 0 {
	//	m.SetMsgId(msgs.MIDUnbind)
	//	GMsgBusManager.Push2Backend(0, unbindIds, m.MarshalBytes())
	//}
}
예제 #2
0
func (this *UdpSessionList) PushCommonMsg(msgId uint16, did int64, msgBody []byte) error {
	msg := msgs.NewMsg(msgBody, nil)
	msg.FrameHeader.Opcode = 2
	msg.DataHeader.MsgId = msgId
	msg.FrameHeader.DstId = did

	sid, err := GetDeviceSid(did)
	if err != nil {
		return fmt.Errorf("[udp:err] get session of device [%d] error: %v", did, err)
	}

	locker := NewDeviceSessionLocker(sid)
	err = locker.Lock()
	if err != nil {
		return fmt.Errorf("[udp:err] lock session id [%s] failed: %v", sid, err)
	}
	defer locker.Unlock()

	i, err := uuid.ParseHex(sid)
	if err != nil {
		return fmt.Errorf("[udp:err] wrong session id format: %v", err)
	}
	sess, err := this.GetSession(i)
	if err != nil {
		return fmt.Errorf("[udp:err] get session %s error: %v", sid, err)
	}
	sess.Sidx++
	msg.FrameHeader.Sequence = sess.Sidx
	msgBytes := msg.MarshalBytes()
	this.server.Send(sess.Addr, msgBytes)

	this.SaveSession(i, sess)
	return nil
}
예제 #3
0
func (this *SessionList) PushCommonMsg(msgid uint16, dstId int64, msgBody []byte) {
	glog.Infof("[ch:sending] msgid:%v | dstId:%v | len(msgBody):%v | msgBody:%v\n", msgid, dstId, len(msgBody), msgBody)
	msg := msgs.NewMsg(msgBody, nil)
	msg.FrameHeader.Opcode = 2
	msg.DataHeader.MsgId = msgid

	ids := TransId(dstId)

	for _, id := range ids {
		blockId := getBlockID(id)
		lock := this.onlinedMu[blockId]
		lock.Lock()
		if list, ok := this.onlined[blockId][id]; ok {
			for e := list.Front(); e != nil; e = e.Next() {
				s, ok := e.Value.(*Session)
				if !ok {
					break
				}

				msg.FrameHeader.DstId = id
				msgBytes := msg.MarshalBytes()
				glog.Infoln("session.go Push msgBytes:", len(msgBytes), msgBytes)

				_, err := s.Conn.Send(msgBytes)
				if err != nil && glog.V(2) {
					glog.Warningf("[ch:err] id: %d, MsgId %d, error: %v", id, msgid, err)
					err = s.Conn.Close()
					if err != nil && glog.V(2) {
						glog.Warningf("[ch:err] id: %d, MsgId: %d, error: %v", id, msgid, err)
					}
				}
				if glog.V(1) {
					glog.Infof("[ch:sended]%v->%v, MsgID:%v,ctn:%v ", s.Uid, dstId, msgid, msgBytes)
				}
			}
		}
		lock.Unlock()
	}
}
예제 #4
0
func (this *SessionList) KickOffline(uid int64) {
	ids := TransId(uid)

	body := msgs.MsgStatus{}
	body.Type = msgs.MSTKickOff
	kickMsg := msgs.NewMsg(nil, nil)
	kickMsg.FrameHeader.Opcode = 2
	kickMsg.DataHeader.MsgId = msgs.MIDStatus

	for _, id := range ids {
		blockId := getBlockID(id)
		lock := this.onlinedMu[blockId]
		body.Id = id
		kickMsg.FrameHeader.DstId = id
		kickMsg.Data, _ = body.Marshal()
		msgBody := kickMsg.MarshalBytes()
		lock.Lock()
		if list, ok := this.onlined[blockId][id]; ok {
			for e := list.Front(); e != nil; e = e.Next() {
				s, ok := e.Value.(*Session)
				if !ok {
					break
				}
				_, err := s.Conn.Send(msgBody)
				if err != nil && glog.V(2) {
					glog.Warningf("[kick|send] mid: %d, user: %d, error: %v", s.Uid, id, err)
				}
				err = s.Conn.Close()
				if err != nil && glog.V(2) {
					glog.Warningf("[kick|close] mid: %d, user: %d, error: %v", s.Uid, id, err)
				}
				glog.Infof("[kick] mid: %d, user %d modified password", s.Uid, id)
			}
		}
		lock.Unlock()
	}
}
예제 #5
0
func WsHandler(ws *websocket.Conn) {
	addr := ws.Request().RemoteAddr
	var err error
	if err = setReadTimeout(ws, 60); err != nil {
		glog.Errorf("[ws:err] %v websocket.SetReadDeadline() error(%s)\n", addr, err)
		ws.Close()
		return
	}
	reply := make([]byte, 0, 256)
	if err = websocket.Message.Receive(ws, &reply); err != nil {
		glog.Errorf("[ws:err] %v websocket.Message.Receive() error(%v)\n", addr, err)
		ws.Close()
		return
	}

	// parse login params
	id, timestamp, timeout, encryShadow, loginErr := getLoginParams(string(reply))
	if loginErr != nil {
		glog.Errorf("[ws:err] [%s] params (%s) error (%v)\n", addr, string(reply), loginErr)
		websocket.Message.Send(ws, AckWrongParams)
		ws.Close()
		return
	}
	// check login
	if err = isAuth(id, timestamp, timeout, encryShadow); err != nil {
		glog.Errorf("[ws:err] [%s] auth failed:\"%s\", error: %v", addr, string(reply), err)
		websocket.Message.Send(ws, LoginFailed.ErrorId)
		ws.Close()
		return
	}
	var bindedIds []int64
	var mid byte
	if id > 0 {
		// 用户登录,检查其id是否为16整数倍,并为其分配一个1到15内的未使用的手机子id,相加后作为手机
		// id,用于本session
		if id%int64(kUseridUnit) != 0 {
			glog.Warningf("[ws:err] invalid user id %d, low byte is not zero", id)
			err = websocket.Message.Send(ws, AckWrongLoginDevice)
			ws.Close()
			return
		}
		mobileid, err := SelectMobileId(id)
		if err != nil {
			glog.Warningf("[ws:err] select mobile id for user %d failed: %v", id, err)
			err = websocket.Message.Send(ws, AckServerError)
			ws.Close()
			return
		}
		if mobileid <= 0 {
			glog.Warningf("[ws:err] no valid mobile id for user %d, the user may have 15 clients now.", id)
			err = websocket.Message.Send(ws, AckWrongLoginDevice)
			ws.Close()
			return
		}
		newId := id + int64(mobileid%int(kUseridUnit))
		if id > newId {
			glog.Errorf("[ws:err] user id overflow, origin id: %d, newId %d with mid %d", id, newId, mobileid)
		}
		mid = byte(mobileid)
		// 先用原始的用户id获取设备列表
		bindedIds, err = GetUserDevices(id)
		id = newId // 防止错误的手机id溢出可用的范围
	} else if id < 0 {
		bindedIds, err = GetDeviceUsers(id)
	}
	if err != nil {
		glog.Errorf("[ws:err] id [%d] get devices error: %v, devices: %v", id, err, bindedIds)
		websocket.Message.Send(ws, LoginFailed.ErrorId)
		ws.Close()
		return
	}

	statIncConnTotal()
	statIncConnOnline()
	defer statDecConnOnline()

	// 成功登陆后的一次回复
	if id > 0 {
		err = websocket.Message.Send(ws, []byte{0, mid})
	} else {
		err = websocket.Message.Send(ws, []byte{0})
	}
	if err != nil {
		glog.Errorf("[ws:err]  [%s] [uid: %d] sent login-ack error (%v)\n", addr, id, err)
		ws.Close()
		return
	}

	_, err = SetUserOnline(id, gLocalAddr)
	if err != nil {
		glog.Errorf("[ws:err] SetUserOnline error [uid: %d] %v\n", id, err)
		ws.Close()
		return
	}
	if glog.V(2) {
		glog.Infof("[ws:online] success id: %d, ip: %v, comet: %s, param: %s, binded ids: %v", id, addr, gLocalAddr, reply, bindedIds)
	}

	s := NewWsSession(id, bindedIds, NewWsConn(ws))
	selement := gSessionList.AddSession(s)

	if id < 0 {
		destIds := gSessionList.CalcDestIds(s, 0)

		body := msgs.MsgStatus{}
		body.Type = msgs.MSTDeviceOnline
		body.Id = id
		m := msgs.NewMsg(nil, nil)
		m.FrameHeader.Opcode = 2
		m.FrameHeader.SrcId = id
		m.DataHeader.MsgId = msgs.MIDStatus
		m.Data, _ = body.Marshal()

		GMsgBusManager.Push2Bus(id, destIds, m.MarshalBytes())
	}

	if timeout <= 0 {
		timeout = TIME_OUT
	}
	ws.ReadTimeout = time.Duration(3*timeout) * time.Second
	for {
		if err = websocket.Message.Receive(ws, &reply); err != nil {
			glog.Errorf("[ws:err] [err:%v] causing ws closed", err)
			break
		}
		gSessionList.GetBindedIds(s, &bindedIds)
		if len(reply) == 1 && string(reply) == PING_MSG {
			if err = websocket.Message.Send(ws, PONG_MSG); err != nil {
				glog.Errorf("[ws:err] causing ws closed <%s> user_id:\"%d\" write heartbeat to client error(%s)\n", addr, id, err)
				break
			}
		} else {
			statIncUpStreamIn()
			msg := reply
			if len(msg) < kDstIdEnd {
				glog.Infof("[ws:err] causing ws closed Invalid msg lenght %d bytes, %v", len(msg), msg)
				break
			}
			// 根据手机与嵌入式协议,提取消息中的目标id
			toId := int64(binary.LittleEndian.Uint64(msg[kDstIdOffset:kDstIdEnd]))

			destIds := gSessionList.CalcDestIds(s, toId)

			if glog.V(3) {
				glog.Infof("[ws|received] %d -> %d, binded(%v), calc to: %v, data: (len: %d)%v...", id, toId, s.BindedIds, destIds, len(msg), msg)
			} else if glog.V(2) {
				glog.Infof("[ws|received] %d -> %d, binded(%v), calc to: %v, data: (len: %d)%v...", id, toId, s.BindedIds, destIds, len(msg), msg[0:kDstIdEnd])
			}
			// Send to Message Bus
			GMsgBusManager.Push2Bus(id, destIds, msg)
		}
		//end = time.Now().UnixNano()
	}
	offlineErr := err
	err = SetUserOffline(id, gLocalAddr)
	if err != nil {
		glog.Errorf("[ws:offline|error] uid %d, error: %v", id, err)
	}
	if glog.V(2) {
		glog.Infof("[ws:offline] id:%d, comet: %s, reason: %v", id, gLocalAddr, offlineErr)
	}
	if id > 0 && mid > 0 {
		id -= int64(mid)
		ReturnMobileId(id, mid)
		//		q := ReturnMobileId(id, mid)
		//		if q != 1 {
		//			glog.Errorf("[ws|return] return mid %d for user %d failed, error: %v", mid, id-int64(mid), err)
		//		} else {
		//			glog.Errorf("[ws|return] return mid %d for user %d successed, error: %v", mid, id-int64(mid), err)
		//		}
	}
	if id < 0 {
		destIds := gSessionList.CalcDestIds(s, 0)

		body := msgs.MsgStatus{}
		body.Type = msgs.MSTDeviceOffline
		body.Id = id
		m := msgs.NewMsg(nil, nil)
		m.FrameHeader.Opcode = 2
		m.FrameHeader.SrcId = id
		m.DataHeader.MsgId = msgs.MIDStatus
		m.Data, _ = body.Marshal()
		glog.Infof("deprecated [ws->udp] %v->%v ctn:%v\n", id, destIds, m)
		GMsgBusManager.Push2Bus(id, destIds, m.MarshalBytes())
	}
	gSessionList.RemoveSession(selement)
	return
}