static void handle_characteristic_read_request()

in HAP/HAPIPAccessoryServer.c [1489:1734]


static void handle_characteristic_read_request(
        HAPIPSessionDescriptor* session,
        const HAPCharacteristic* chr_,
        const HAPService* svc,
        const HAPAccessory* acc,
        HAPIPReadContextRef* ctx,
        HAPIPByteBuffer* data_buffer) {
    HAPPrecondition(session);
    HAPPrecondition(session->server);
    HAPPrecondition(session->securitySession.type == kHAPIPSecuritySessionType_HAP);
    HAPPrecondition(session->securitySession.isOpen);
    HAPPrecondition(session->securitySession.isSecured || kHAPIPAccessoryServer_SessionSecurityDisabled);
    HAPPrecondition(!HAPSessionIsTransient(&session->securitySession._.hap));

    HAPError err;

    size_t n, sval_length;
    bool bool_val;
    int32_t int_val;
    uint8_t uint8_val;
    uint16_t uint16_val;
    uint32_t uint32_val;
    uint64_t uint64_val;
    float float_val;
    HAPTLVWriterRef tlv8_writer;
    HAPAssert(chr_);
    const HAPBaseCharacteristic* chr = chr_;
    HAPAssert(svc);
    HAPAssert(acc);
    HAPAssert(ctx);
    HAPAssert(data_buffer);
    HAPAssert(data_buffer->data);
    HAPAssert(data_buffer->position <= data_buffer->limit);
    HAPAssert(data_buffer->limit <= data_buffer->capacity);
    HAPIPReadContext* readContext = (HAPIPReadContext*) ctx;
    readContext->status = kHAPIPAccessoryServerStatusCode_Success;
    switch (chr->format) {
        case kHAPCharacteristicFormat_Data: {
            err = HAPDataCharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPDataCharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                .session = &session->securitySession._.hap,
                                                                .characteristic = (const HAPDataCharacteristic*) chr,
                                                                .service = svc,
                                                                .accessory = acc },
                    &data_buffer->data[data_buffer->position],
                    data_buffer->limit - data_buffer->position,
                    &sval_length,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                if (sval_length <= data_buffer->limit - data_buffer->position) {
                    util_base64_encode(
                            &data_buffer->data[data_buffer->position],
                            sval_length,
                            &data_buffer->data[data_buffer->position],
                            data_buffer->limit - data_buffer->position,
                            &sval_length);
                    if (sval_length < data_buffer->limit - data_buffer->position) {
                        data_buffer->data[data_buffer->position + sval_length] = 0;
                        readContext->value.stringValue.bytes = &data_buffer->data[data_buffer->position];
                        readContext->value.stringValue.numBytes = sval_length;
                        data_buffer->position += sval_length + 1;
                        HAPAssert(data_buffer->position <= data_buffer->limit);
                        HAPAssert(data_buffer->limit <= data_buffer->capacity);
                    } else {
                        readContext->status = kHAPIPAccessoryServerStatusCode_OutOfResources;
                    }
                } else {
                    readContext->status = kHAPIPAccessoryServerStatusCode_OutOfResources;
                }
            }
        } break;
        case kHAPCharacteristicFormat_Bool: {
            err = HAPBoolCharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPBoolCharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                .session = &session->securitySession._.hap,
                                                                .characteristic = (const HAPBoolCharacteristic*) chr,
                                                                .service = svc,
                                                                .accessory = acc },
                    &bool_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.unsignedIntValue = bool_val ? 1 : 0;
            }
        } break;
        case kHAPCharacteristicFormat_UInt8: {
            err = HAPUInt8CharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPUInt8CharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                 .session = &session->securitySession._.hap,
                                                                 .characteristic = (const HAPUInt8Characteristic*) chr,
                                                                 .service = svc,
                                                                 .accessory = acc },
                    &uint8_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.unsignedIntValue = uint8_val;
            }
        } break;
        case kHAPCharacteristicFormat_UInt16: {
            err = HAPUInt16CharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPUInt16CharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                  .session = &session->securitySession._.hap,
                                                                  .characteristic =
                                                                          (const HAPUInt16Characteristic*) chr,
                                                                  .service = svc,
                                                                  .accessory = acc },
                    &uint16_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.unsignedIntValue = uint16_val;
            }
        } break;
        case kHAPCharacteristicFormat_UInt32: {
            err = HAPUInt32CharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPUInt32CharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                  .session = &session->securitySession._.hap,
                                                                  .characteristic =
                                                                          (const HAPUInt32Characteristic*) chr,
                                                                  .service = svc,
                                                                  .accessory = acc },
                    &uint32_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.unsignedIntValue = uint32_val;
            }
        } break;
        case kHAPCharacteristicFormat_UInt64: {
            err = HAPUInt64CharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPUInt64CharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                  .session = &session->securitySession._.hap,
                                                                  .characteristic =
                                                                          (const HAPUInt64Characteristic*) chr,
                                                                  .service = svc,
                                                                  .accessory = acc },
                    &uint64_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.unsignedIntValue = uint64_val;
            }
        } break;
        case kHAPCharacteristicFormat_Int: {
            err = HAPIntCharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPIntCharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                               .session = &session->securitySession._.hap,
                                                               .characteristic = (const HAPIntCharacteristic*) chr,
                                                               .service = svc,
                                                               .accessory = acc },
                    &int_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.intValue = int_val;
            }
        } break;
        case kHAPCharacteristicFormat_Float: {
            err = HAPFloatCharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPFloatCharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                 .session = &session->securitySession._.hap,
                                                                 .characteristic = (const HAPFloatCharacteristic*) chr,
                                                                 .service = svc,
                                                                 .accessory = acc },
                    &float_val,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                readContext->value.floatValue = float_val;
            }
        } break;
        case kHAPCharacteristicFormat_String: {
            err = HAPStringCharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPStringCharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                  .session = &session->securitySession._.hap,
                                                                  .characteristic =
                                                                          (const HAPStringCharacteristic*) chr,
                                                                  .service = svc,
                                                                  .accessory = acc },
                    &data_buffer->data[data_buffer->position],
                    data_buffer->limit - data_buffer->position,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                sval_length = HAPStringGetNumBytes(&data_buffer->data[data_buffer->position]);
                if (sval_length < data_buffer->limit - data_buffer->position) {
                    data_buffer->data[data_buffer->position + sval_length] = 0;
                    readContext->value.stringValue.bytes = &data_buffer->data[data_buffer->position];
                    readContext->value.stringValue.numBytes = sval_length;
                    data_buffer->position += sval_length + 1;
                    HAPAssert(data_buffer->position <= data_buffer->limit);
                    HAPAssert(data_buffer->limit <= data_buffer->capacity);
                } else {
                    readContext->status = kHAPIPAccessoryServerStatusCode_OutOfResources;
                }
            }
        } break;
        case kHAPCharacteristicFormat_TLV8: {
            n = data_buffer->limit - data_buffer->position;
            HAPTLVWriterCreate(&tlv8_writer, &data_buffer->data[data_buffer->position], n);
            err = HAPTLV8CharacteristicHandleRead(
                    HAPNonnull(session->server),
                    &(const HAPTLV8CharacteristicReadRequest) { .transportType = kHAPTransportType_IP,
                                                                .session = &session->securitySession._.hap,
                                                                .characteristic = (const HAPTLV8Characteristic*) chr,
                                                                .service = svc,
                                                                .accessory = acc },
                    &tlv8_writer,
                    HAPAccessoryServerGetClientContext(HAPNonnull(session->server)));
            readContext->status = ConvertCharacteristicReadErrorToStatusCode(err);
            if (readContext->status == kHAPIPAccessoryServerStatusCode_Success) {
                if (((HAPTLVWriter*) &tlv8_writer)->numBytes <= data_buffer->limit - data_buffer->position) {
                    util_base64_encode(
                            &data_buffer->data[data_buffer->position],
                            ((HAPTLVWriter*) &tlv8_writer)->numBytes,
                            &data_buffer->data[data_buffer->position],
                            data_buffer->limit - data_buffer->position,
                            &sval_length);
                    if (sval_length < data_buffer->limit - data_buffer->position) {
                        data_buffer->data[data_buffer->position + sval_length] = 0;
                        readContext->value.stringValue.bytes = &data_buffer->data[data_buffer->position];
                        readContext->value.stringValue.numBytes = sval_length;
                        data_buffer->position += sval_length + 1;
                        HAPAssert(data_buffer->position <= data_buffer->limit);
                        HAPAssert(data_buffer->limit <= data_buffer->capacity);
                    } else {
                        readContext->status = kHAPIPAccessoryServerStatusCode_OutOfResources;
                    }
                } else {
                    readContext->status = kHAPIPAccessoryServerStatusCode_OutOfResources;
                }
            }
        } break;
    }
}