func (p *protocol) checkOfflineMessage(client *client) { var buf bytes.Buffer messageIDs, err := model.GetOfflineMessages(client.ClientID) if err != nil || messageIDs == nil { log.Printf("ERROR: GetOfflineMessages clientID %s error %s ", client.ClientID, err) return } subChannel, _ := strconv.ParseInt(client.SubChannel, 10, 64) for _, messageID := range messageIDs { msg, err := model.FindMessageByID(messageID) if err != nil || msg == nil { log.Printf("ERROR: client %s message ID %d message doesn't exist, err %s", client.ClientID, messageID, err) continue } // live := msg.CreatedAt + msg.Expires*100000000000000 // if time.Now().UnixNano() > live { // log.Printf("ERROR: client %s message ID %d message expired.", client.ClientID, messageID) // model.RemoveOfflineMessage(client.ClientID, messageID) // continue // } if subChannel != msg.ChannelID { continue } msg2 := &Message{ Id: util.Guid(msg.ID).Hex(), Body: []byte(msg.Body), Timestamp: msg.CreatedAt, } log.Printf("msg is %#v", msg2) err = p.SendMessage(client, msg2, &buf) if err != nil { log.Printf("send message to client %s error %s", client, err) } client.Lock() err = client.Flush() client.Unlock() log.Printf("send message %#v to client %s success ", msg, client) model.RemoveOfflineMessage(client.ClientID, messageID) } }
func (p *protocol) PUB(client *client, params [][]byte) ([]byte, error) { // var err error var buf bytes.Buffer if client.Role != "$_@push_sign_$_kz_worker" { return nil, util.NewFatalClientErr(nil, "E_INVALID_REQUEST", "client can't pub message") } if len(params) < 3 { return nil, util.NewFatalClientErr(nil, "E_INVALID", "PUB insufficient number of parameters") } log.Printf("receive params on sub %s", params) bodyLen, err := readLen(client.Reader, client.lenSlice) if err != nil { return nil, util.NewFatalClientErr(err, "E_BAD_BODY", "IDENTIFY failed to read body size") } if int64(bodyLen) > p.context.broker.options.MaxBodySize { return nil, util.NewFatalClientErr(nil, "E_BAD_BODY", fmt.Sprintf("IDENTIFY body too big %d > %d", bodyLen, p.context.broker.options.MaxBodySize)) } body := make([]byte, bodyLen) _, err = io.ReadFull(client.Reader, body) if err != nil { return nil, util.NewFatalClientErr(err, "E_BAD_BODY", "IDENTIFY failed to read body") } client_id := string(params[1]) channel_id := string(params[2]) message_id := string(params[3]) msgId, _ := strconv.ParseInt(message_id, 10, 64) log.Printf("msgId == %d", msgId) // TODO 另外启动一个channel 与 goroutine 用来处理这个消息 dstClient, err := p.context.broker.GetClient(client_id, channel_id) if err != nil || dstClient == nil { p.ackPublish(client, util.ACK_OFF, client_id, msgId) // model.SaveOfflineMessage(dstClient.ClientID, msgId) log.Printf("client %s is null", client_id) return nil, nil //return nil, util.NewFatalClientErr(nil, "E_INVALID", "PUB insufficient number of parameters") // return FrameTypeACKError message_id } log.Printf("get client %s by channel %s = %s ", client_id, channel_id, dstClient) msg := &Message{ Id: util.Guid(msgId).Hex(), Body: body, Timestamp: time.Now().UnixNano(), } log.Printf("msg is %#v", msg) // dstClient.SendingMessage() err = p.SendMessage(dstClient, msg, &buf) if err != nil { log.Printf("send message to client %s error %s", dstClient, err) } dstClient.Lock() err = dstClient.Flush() dstClient.Unlock() if err != nil { p.ackPublish(client, util.ACT_ERR, client_id, msgId) } else { p.ackPublish(client, util.ACK_SUCCESS, client_id, msgId) } return nil, nil }