Exemple #1
0
func decodeCaseACK(c *client.Conn, fields client.Fields, statusCode int, errorText string) (client.Packet, error) {
	if len(errorText) > 0 {
		return nil, &client.ServerError{
			MessageType: "ack",
			Origin:      c.Origin(),
			Message:     errorText,
			StatusCode:  statusCode,
		}
	}
	return nil, nil
}
Exemple #2
0
func decodeServerInvalidACK(c *client.Conn, fields client.Fields, statusCode int, errorText string) (client.Packet, error) {
	if len(errorText) == 0 {
		return nil, nil
	}
	updates, hasUpdates := fields["updates"].([]interface{})
	if !hasUpdates {
		return nil, &client.IncompleteError{
			MessageType: "ack",
			Origin:      c.Origin(),
			Field:       "updates"}
	}
	reply := ServerInvalidACK{
		Updates:    make([]client.Update, len(updates)),
		StatusCode: statusCode,
	}
	for index, field := range updates {
		var (
			update    map[string]interface{}
			channelId string
			version   float64
			ok        bool
		)
		if update, ok = field.(map[string]interface{}); !ok {
			return nil, &client.IncompleteError{MessageType: "ack", Origin: c.Origin(), Field: "update"}
		}
		if channelId, ok = update["channelID"].(string); !ok {
			return nil, &client.IncompleteError{MessageType: "ack", Origin: c.Origin(), Field: "channelID"}
		}
		if version, ok = update["version"].(float64); !ok {
			return nil, &client.IncompleteError{MessageType: "ack", Origin: c.Origin(), Field: "version"}
		}
		reply.Updates[index] = client.Update{ChannelId: channelId, Version: int64(version)}
	}
	return reply, nil
}
Exemple #3
0
func decodeUnregisterReply(c *client.Conn, fields client.Fields, statusCode int, errorText string) (client.Packet, error) {
	if len(errorText) > 0 {
		return nil, &client.ServerError{"unregister", c.Origin(), errorText, statusCode}
	}
	channelId, hasChannelId := fields["channelID"].(string)
	if !hasChannelId {
		return nil, &client.IncompleteError{"register", c.Origin(), "channelID"}
	}
	reply := ServerUnregister{
		StatusCode: statusCode,
		ChannelId:  channelId,
	}
	return reply, nil
}
Exemple #4
0
func roundTrip(conn *client.Conn, deviceId, channelId, endpoint string, version int64) (err error) {
	stopChan, errChan := make(chan bool), make(chan error)
	defer close(stopChan)
	go func() {
		err := client.Notify(endpoint, version)
		if err != nil {
			err = fmt.Errorf("Error sending update %d on channel %q: %s",
				version, channelId, err)
		}
		select {
		case <-stopChan:
		case errChan <- err:
		}
	}()
	go func() {
		var (
			pendingAccepts []client.Update
			err            error
		)
		timeout := time.After(15 * time.Second)
		for ok := true; ok; {
			var packet client.Packet
			select {
			case ok = <-stopChan:
			case <-timeout:
				ok = false
				err = client.ErrTimedOut

			case packet, ok = <-conn.Packets:
				if !ok {
					err = client.ErrChanClosed
					break
				}
				updates, _ := packet.(client.ServerUpdates)
				if len(updates) == 0 {
					continue
				}
				pendingAccepts = append(pendingAccepts, updates...)
				var (
					update    client.Update
					hasUpdate bool
				)
				for _, update = range updates {
					if update.ChannelId == channelId && update.Version >= version {
						hasUpdate = true
						break
					}
				}
				if !hasUpdate {
					continue
				}
				ok = false
				if update.Version != version {
					err = fmt.Errorf("Wrong update version: got %d; want %d",
						update.Version, version)
					break
				}
			}
		}
		if acceptErr := conn.AcceptBatch(pendingAccepts); acceptErr != nil {
			err = fmt.Errorf("Error acknowledging updates: %s", acceptErr)
		}
		select {
		case <-stopChan:
		case errChan <- err:
		}
	}()
	for i := 0; i < 2; i++ {
		if err := <-errChan; err != nil {
			return err
		}
	}
	return nil
}
Exemple #5
0
func decodeCaseACK(c *client.Conn, fields client.Fields, statusCode int, errorText string) (client.Packet, error) {
	if len(errorText) > 0 {
		return nil, &client.ServerError{"ack", c.Origin(), errorText, statusCode}
	}
	return nil, nil
}
Exemple #6
0
func decodePing(c *client.Conn, fields client.Fields, statusCode int, errorText string) (client.Packet, error) {
	if len(errorText) > 0 {
		return nil, &client.ServerError{"ping", c.Origin(), errorText, statusCode}
	}
	return ServerPing{statusCode}, nil
}