ccs/ccs.go
func (c *Conn) Receive() (*InMsg, error) {
	stanza, err := c.xmppConn.Recv()
	if err != nil {
		return nil, err
	}

	if c.debug {
		log.Printf("Incoming raw CCS stanza: %+v\n", stanza)
	}

	chat, ok := stanza.(xmpp.Chat)
	if !ok {
		return nil, nil
	}

	if chat.Type == "error" {
		// todo: once go-xmpp can parse XMPP error messages, return error with XMPP error message (issue: https://github.com/soygul/gcm/issues/14)
		return nil, errors.New("CCS returned an XMPP error (can be a stanza or JSON error or anything else)")
	}

	var m InMsg
	if err = json.Unmarshal([]byte(chat.Other[0]), &m); err != nil { // todo: handle other fields of chat (remote/type/text/other[1,2,..])
		return nil, errors.New("unknow message from CCS")
	}

	switch m.MessageType {
	case "ack":
		return &m, nil // todo: mark message as sent
	case "nack":
		return &m, nil // todo: try and resend the message (after reconnect if problem is about connection draining)
	case "receipt":
		return &m, nil // todo: mark message as delivered and remove from the queue
	case "control":
		return &m, nil // todo: handle connection draining (and any other control message type?)
	case "":
		// acknowledge the incoming ordinary messages as per spec
		ack := &OutMsg{MessageType: "ack", To: m.From, ID: m.ID}
		if _, err = c.Send(ack); err != nil {
			return nil, fmt.Errorf("failed to send ack message to CCS with error: %v", err)
		}
		return &m, nil
	default:
		// unknown message types can be ignored, as per GCM specs
	}
	return &m, nil
}
func (c *Conn) Receive() (*InMsg, error) {
	stanza, err := c.xmppConn.Recv()
	if err != nil {
		return nil, err
	}

	if c.debug {
		log.Printf("Incoming raw CCS stanza: %+v\n", stanza)
	}

	chat, ok := stanza.(xmpp.Chat)
	if !ok {
		return nil, nil
	}

	if chat.Type == "error" {
		// todo: once go-xmpp can parse XMPP error messages, return error with XMPP error message (issue: https://github.com/soygul/gcm/issues/14)
		return nil, errors.New("CCS returned an XMPP error (can be a stanza or JSON error or anything else)")
	}

	var m InMsg
	if err = json.Unmarshal([]byte(chat.Other[0]), &m); err != nil { // todo: handle other fields of chat (remote/type/text/other[1,2,..])
		return nil, errors.New("unknow message from CCS")
	}

	switch m.MessageType {
	case "ack":
		return &m, nil // todo: mark message as sent
	case "nack":
		return &m, nil // todo: try and resend the message (after reconnect if problem is about connection draining)
	case "receipt":
		return &m, nil // todo: mark message as delivered and remove from the queue
	case "control":
		return &m, nil // todo: handle connection draining (and any other control message type?)
	case "":
		// acknowledge the incoming ordinary messages as per spec
		ack := &OutMsg{MessageType: "ack", To: m.From, ID: m.ID}
		if _, err = c.Send(ack); err != nil {
			return nil, fmt.Errorf("failed to send ack message to CCS with error: %v", err)
		}
		return &m, nil
	default:
		// unknown message types can be ignored, as per GCM specs
	}
	return &m, nil
}
// Receive waits to receive the next incoming messages from the CCS connection.