Move to clang-format-6.0

This commit moves the codebase to the lastest clang-format file from
upstream, as well as clang-format-6.0.

Change-Id: Ice8313468097c0c42317fbb9e10ddf036e8cff4c
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
diff --git a/include/ast_jpeg_decoder.hpp b/include/ast_jpeg_decoder.hpp
index e6e0f08..e8bdddb 100644
--- a/include/ast_jpeg_decoder.hpp
+++ b/include/ast_jpeg_decoder.hpp
@@ -1,345 +1,390 @@
 #pragma once
 
 #include <aspeed/JTABLES.H>
-#include <ast_video_types.hpp>
+
 #include <array>
+#include <ast_video_types.hpp>
 #include <cassert>
 #include <cstdint>
 #include <cstring>
 #include <iostream>
 #include <vector>
 
-namespace ast_video {
+namespace ast_video
+{
 
-struct ColorCache {
-  ColorCache()
-      : color{0x008080, 0xFF8080, 0x808080, 0xC08080}, index{0, 1, 2, 3} {}
+struct ColorCache
+{
+    ColorCache() :
+        color{0x008080, 0xFF8080, 0x808080, 0xC08080}, index{0, 1, 2, 3}
+    {
+    }
 
-  unsigned long color[4];
-  unsigned char index[4];
-  unsigned char bitMapBits{};
+    unsigned long color[4];
+    unsigned char index[4];
+    unsigned char bitMapBits{};
 };
 
-struct RGB {
-  unsigned char b;
-  unsigned char g;
-  unsigned char r;
-  unsigned char reserved;
+struct RGB
+{
+    unsigned char b;
+    unsigned char g;
+    unsigned char r;
+    unsigned char reserved;
 };
 
-enum class JpgBlock {
-  JPEG_NO_SKIP_CODE = 0x00,
-  JPEG_SKIP_CODE = 0x08,
+enum class JpgBlock
+{
+    JPEG_NO_SKIP_CODE = 0x00,
+    JPEG_SKIP_CODE = 0x08,
 
-  JPEG_PASS2_CODE = 0x02,
-  JPEG_SKIP_PASS2_CODE = 0x0A,
+    JPEG_PASS2_CODE = 0x02,
+    JPEG_SKIP_PASS2_CODE = 0x0A,
 
-  LOW_JPEG_NO_SKIP_CODE = 0x04,
-  LOW_JPEG_SKIP_CODE = 0x0C,
+    LOW_JPEG_NO_SKIP_CODE = 0x04,
+    LOW_JPEG_SKIP_CODE = 0x0C,
 
-  VQ_NO_SKIP_1_COLOR_CODE = 0x05,
-  VQ_SKIP_1_COLOR_CODE = 0x0D,
+    VQ_NO_SKIP_1_COLOR_CODE = 0x05,
+    VQ_SKIP_1_COLOR_CODE = 0x0D,
 
-  VQ_NO_SKIP_2_COLOR_CODE = 0x06,
-  VQ_SKIP_2_COLOR_CODE = 0x0E,
+    VQ_NO_SKIP_2_COLOR_CODE = 0x06,
+    VQ_SKIP_2_COLOR_CODE = 0x0E,
 
-  VQ_NO_SKIP_4_COLOR_CODE = 0x07,
-  VQ_SKIP_4_COLOR_CODE = 0x0F,
+    VQ_NO_SKIP_4_COLOR_CODE = 0x07,
+    VQ_SKIP_4_COLOR_CODE = 0x0F,
 
-  FRAME_END_CODE = 0x09,
+    FRAME_END_CODE = 0x09,
 
 };
 
-class AstJpegDecoder {
- public:
-  AstJpegDecoder() {
-    // TODO(ed) figure out how to init this in the constructor
-    yuvBuffer.resize(1920 * 1200);
-    outBuffer.resize(1920 * 1200);
-    for (auto &r : outBuffer) {
-      r.r = 0x00;
-      r.g = 0x00;
-      r.b = 0x00;
-      r.reserved = 0xAA;
+class AstJpegDecoder
+{
+  public:
+    AstJpegDecoder()
+    {
+        // TODO(ed) figure out how to init this in the constructor
+        yuvBuffer.resize(1920 * 1200);
+        outBuffer.resize(1920 * 1200);
+        for (auto &r : outBuffer)
+        {
+            r.r = 0x00;
+            r.g = 0x00;
+            r.b = 0x00;
+            r.reserved = 0xAA;
+        }
+
+        int qfactor = 16;
+
+        scalefactor = qfactor;
+        scalefactoruv = qfactor;
+        advancescalefactor = 16;
+        advancescalefactoruv = 16;
+        initJpgTable();
     }
 
-    int qfactor = 16;
+    void loadQuantTable(std::array<long, 64> &quant_table)
+    {
+        float scalefactorF[8] = {1.0f,         1.387039845f, 1.306562965f,
+                                 1.175875602f, 1.0f,         0.785694958f,
+                                 0.541196100f, 0.275899379f};
+        uint8_t j, row, col;
+        std::array<uint8_t, 64> tempQT{};
 
-    scalefactor = qfactor;
-    scalefactoruv = qfactor;
-    advancescalefactor = 16;
-    advancescalefactoruv = 16;
-    initJpgTable();
-  }
+        // Load quantization coefficients from JPG file, scale them for DCT and
+        // reorder
+        // from zig-zag order
+        switch (ySelector)
+        {
+            case 0:
+                stdLuminanceQt = tbl000Y;
+                break;
+            case 1:
+                stdLuminanceQt = tbl014Y;
+                break;
+            case 2:
+                stdLuminanceQt = tbl029Y;
+                break;
+            case 3:
+                stdLuminanceQt = tbl043Y;
+                break;
+            case 4:
+                stdLuminanceQt = tbl057Y;
+                break;
+            case 5:
+                stdLuminanceQt = tbl071Y;
+                break;
+            case 6:
+                stdLuminanceQt = tbl086Y;
+                break;
+            case 7:
+                stdLuminanceQt = tbl100Y;
+                break;
+        }
+        setQuantTable(stdLuminanceQt, static_cast<uint8_t>(scalefactor),
+                      tempQT);
 
-  void loadQuantTable(std::array<long, 64> &quant_table) {
-    float scalefactorF[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
-                             1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
-    uint8_t j, row, col;
-    std::array<uint8_t, 64> tempQT{};
-
-    // Load quantization coefficients from JPG file, scale them for DCT and
-    // reorder
-    // from zig-zag order
-    switch (ySelector) {
-      case 0:
-        stdLuminanceQt = tbl000Y;
-        break;
-      case 1:
-        stdLuminanceQt = tbl014Y;
-        break;
-      case 2:
-        stdLuminanceQt = tbl029Y;
-        break;
-      case 3:
-        stdLuminanceQt = tbl043Y;
-        break;
-      case 4:
-        stdLuminanceQt = tbl057Y;
-        break;
-      case 5:
-        stdLuminanceQt = tbl071Y;
-        break;
-      case 6:
-        stdLuminanceQt = tbl086Y;
-        break;
-      case 7:
-        stdLuminanceQt = tbl100Y;
-        break;
+        for (j = 0; j <= 63; j++)
+        {
+            quant_table[j] = tempQT[zigzag[j]];
+        }
+        j = 0;
+        for (row = 0; row <= 7; row++)
+        {
+            for (col = 0; col <= 7; col++)
+            {
+                quant_table[j] = static_cast<long>(
+                    (quant_table[j] * scalefactorF[row] * scalefactorF[col]) *
+                    65536);
+                j++;
+            }
+        }
+        bytePos += 64;
     }
-    setQuantTable(stdLuminanceQt, static_cast<uint8_t>(scalefactor), tempQT);
 
-    for (j = 0; j <= 63; j++) {
-      quant_table[j] = tempQT[zigzag[j]];
-    }
-    j = 0;
-    for (row = 0; row <= 7; row++) {
-      for (col = 0; col <= 7; col++) {
-        quant_table[j] = static_cast<long>(
-            (quant_table[j] * scalefactorF[row] * scalefactorF[col]) * 65536);
-        j++;
-      }
-    }
-    bytePos += 64;
-  }
+    void loadQuantTableCb(std::array<long, 64> &quant_table)
+    {
+        float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
+                                1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
+        uint8_t j, row, col;
+        std::array<uint8_t, 64> tempQT{};
 
-  void loadQuantTableCb(std::array<long, 64> &quant_table) {
-    float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
-                            1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
-    uint8_t j, row, col;
-    std::array<uint8_t, 64> tempQT{};
+        // Load quantization coefficients from JPG file, scale them for DCT and
+        // reorder from zig-zag order
+        if (mapping == 0)
+        {
+            switch (uvSelector)
+            {
+                case 0:
+                    stdChrominanceQt = tbl000Y;
+                    break;
+                case 1:
+                    stdChrominanceQt = tbl014Y;
+                    break;
+                case 2:
+                    stdChrominanceQt = tbl029Y;
+                    break;
+                case 3:
+                    stdChrominanceQt = tbl043Y;
+                    break;
+                case 4:
+                    stdChrominanceQt = tbl057Y;
+                    break;
+                case 5:
+                    stdChrominanceQt = tbl071Y;
+                    break;
+                case 6:
+                    stdChrominanceQt = tbl086Y;
+                    break;
+                case 7:
+                    stdChrominanceQt = tbl100Y;
+                    break;
+            }
+        }
+        else
+        {
+            switch (uvSelector)
+            {
+                case 0:
+                    stdChrominanceQt = tbl000Uv;
+                    break;
+                case 1:
+                    stdChrominanceQt = tbl014Uv;
+                    break;
+                case 2:
+                    stdChrominanceQt = tbl029Uv;
+                    break;
+                case 3:
+                    stdChrominanceQt = tbl043Uv;
+                    break;
+                case 4:
+                    stdChrominanceQt = tbl057Uv;
+                    break;
+                case 5:
+                    stdChrominanceQt = tbl071Uv;
+                    break;
+                case 6:
+                    stdChrominanceQt = tbl086Uv;
+                    break;
+                case 7:
+                    stdChrominanceQt = tbl100Uv;
+                    break;
+            }
+        }
+        setQuantTable(stdChrominanceQt, static_cast<uint8_t>(scalefactoruv),
+                      tempQT);
 
-    // Load quantization coefficients from JPG file, scale them for DCT and
-    // reorder from zig-zag order
-    if (mapping == 0) {
-      switch (uvSelector) {
-        case 0:
-          stdChrominanceQt = tbl000Y;
-          break;
-        case 1:
-          stdChrominanceQt = tbl014Y;
-          break;
-        case 2:
-          stdChrominanceQt = tbl029Y;
-          break;
-        case 3:
-          stdChrominanceQt = tbl043Y;
-          break;
-        case 4:
-          stdChrominanceQt = tbl057Y;
-          break;
-        case 5:
-          stdChrominanceQt = tbl071Y;
-          break;
-        case 6:
-          stdChrominanceQt = tbl086Y;
-          break;
-        case 7:
-          stdChrominanceQt = tbl100Y;
-          break;
-      }
-    } else {
-      switch (uvSelector) {
-        case 0:
-          stdChrominanceQt = tbl000Uv;
-          break;
-        case 1:
-          stdChrominanceQt = tbl014Uv;
-          break;
-        case 2:
-          stdChrominanceQt = tbl029Uv;
-          break;
-        case 3:
-          stdChrominanceQt = tbl043Uv;
-          break;
-        case 4:
-          stdChrominanceQt = tbl057Uv;
-          break;
-        case 5:
-          stdChrominanceQt = tbl071Uv;
-          break;
-        case 6:
-          stdChrominanceQt = tbl086Uv;
-          break;
-        case 7:
-          stdChrominanceQt = tbl100Uv;
-          break;
-      }
+        for (j = 0; j <= 63; j++)
+        {
+            quant_table[j] = tempQT[zigzag[j]];
+        }
+        j = 0;
+        for (row = 0; row <= 7; row++)
+        {
+            for (col = 0; col <= 7; col++)
+            {
+                quant_table[j] = static_cast<long>(
+                    (quant_table[j] * scalefactor[row] * scalefactor[col]) *
+                    65536);
+                j++;
+            }
+        }
+        bytePos += 64;
     }
-    setQuantTable(stdChrominanceQt, static_cast<uint8_t>(scalefactoruv),
-                  tempQT);
+    //  Note: Added for Dual_JPEG
+    void loadAdvanceQuantTable(std::array<long, 64> &quant_table)
+    {
+        float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
+                                1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
+        uint8_t j, row, col;
+        std::array<uint8_t, 64> tempQT{};
 
-    for (j = 0; j <= 63; j++) {
-      quant_table[j] = tempQT[zigzag[j]];
-    }
-    j = 0;
-    for (row = 0; row <= 7; row++) {
-      for (col = 0; col <= 7; col++) {
-        quant_table[j] = static_cast<long>(
-            (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536);
-        j++;
-      }
-    }
-    bytePos += 64;
-  }
-  //  Note: Added for Dual_JPEG
-  void loadAdvanceQuantTable(std::array<long, 64> &quant_table) {
-    float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
-                            1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
-    uint8_t j, row, col;
-    std::array<uint8_t, 64> tempQT{};
+        // Load quantization coefficients from JPG file, scale them for DCT and
+        // reorder
+        // from zig-zag order
+        switch (advanceSelector)
+        {
+            case 0:
+                stdLuminanceQt = tbl000Y;
+                break;
+            case 1:
+                stdLuminanceQt = tbl014Y;
+                break;
+            case 2:
+                stdLuminanceQt = tbl029Y;
+                break;
+            case 3:
+                stdLuminanceQt = tbl043Y;
+                break;
+            case 4:
+                stdLuminanceQt = tbl057Y;
+                break;
+            case 5:
+                stdLuminanceQt = tbl071Y;
+                break;
+            case 6:
+                stdLuminanceQt = tbl086Y;
+                break;
+            case 7:
+                stdLuminanceQt = tbl100Y;
+                break;
+        }
+        //  Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG
+        setQuantTable(stdLuminanceQt, static_cast<uint8_t>(advancescalefactor),
+                      tempQT);
 
-    // Load quantization coefficients from JPG file, scale them for DCT and
-    // reorder
-    // from zig-zag order
-    switch (advanceSelector) {
-      case 0:
-        stdLuminanceQt = tbl000Y;
-        break;
-      case 1:
-        stdLuminanceQt = tbl014Y;
-        break;
-      case 2:
-        stdLuminanceQt = tbl029Y;
-        break;
-      case 3:
-        stdLuminanceQt = tbl043Y;
-        break;
-      case 4:
-        stdLuminanceQt = tbl057Y;
-        break;
-      case 5:
-        stdLuminanceQt = tbl071Y;
-        break;
-      case 6:
-        stdLuminanceQt = tbl086Y;
-        break;
-      case 7:
-        stdLuminanceQt = tbl100Y;
-        break;
+        for (j = 0; j <= 63; j++)
+        {
+            quant_table[j] = tempQT[zigzag[j]];
+        }
+        j = 0;
+        for (row = 0; row <= 7; row++)
+        {
+            for (col = 0; col <= 7; col++)
+            {
+                quant_table[j] = static_cast<long>(
+                    (quant_table[j] * scalefactor[row] * scalefactor[col]) *
+                    65536);
+                j++;
+            }
+        }
+        bytePos += 64;
     }
-    //  Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG
-    setQuantTable(stdLuminanceQt, static_cast<uint8_t>(advancescalefactor),
-                  tempQT);
 
-    for (j = 0; j <= 63; j++) {
-      quant_table[j] = tempQT[zigzag[j]];
-    }
-    j = 0;
-    for (row = 0; row <= 7; row++) {
-      for (col = 0; col <= 7; col++) {
-        quant_table[j] = static_cast<long>(
-            (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536);
-        j++;
-      }
-    }
-    bytePos += 64;
-  }
+    //  Note: Added for Dual-JPEG
+    void loadAdvanceQuantTableCb(std::array<long, 64> &quant_table)
+    {
+        float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
+                                1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
+        uint8_t j, row, col;
+        std::array<uint8_t, 64> tempQT{};
 
-  //  Note: Added for Dual-JPEG
-  void loadAdvanceQuantTableCb(std::array<long, 64> &quant_table) {
-    float scalefactor[8] = {1.0f, 1.387039845f, 1.306562965f, 1.175875602f,
-                            1.0f, 0.785694958f, 0.541196100f, 0.275899379f};
-    uint8_t j, row, col;
-    std::array<uint8_t, 64> tempQT{};
+        // Load quantization coefficients from JPG file, scale them for DCT and
+        // reorder
+        // from zig-zag order
+        if (mapping == 1)
+        {
+            switch (advanceSelector)
+            {
+                case 0:
+                    stdChrominanceQt = tbl000Y;
+                    break;
+                case 1:
+                    stdChrominanceQt = tbl014Y;
+                    break;
+                case 2:
+                    stdChrominanceQt = tbl029Y;
+                    break;
+                case 3:
+                    stdChrominanceQt = tbl043Y;
+                    break;
+                case 4:
+                    stdChrominanceQt = tbl057Y;
+                    break;
+                case 5:
+                    stdChrominanceQt = tbl071Y;
+                    break;
+                case 6:
+                    stdChrominanceQt = tbl086Y;
+                    break;
+                case 7:
+                    stdChrominanceQt = tbl100Y;
+                    break;
+            }
+        }
+        else
+        {
+            switch (advanceSelector)
+            {
+                case 0:
+                    stdChrominanceQt = tbl000Uv;
+                    break;
+                case 1:
+                    stdChrominanceQt = tbl014Uv;
+                    break;
+                case 2:
+                    stdChrominanceQt = tbl029Uv;
+                    break;
+                case 3:
+                    stdChrominanceQt = tbl043Uv;
+                    break;
+                case 4:
+                    stdChrominanceQt = tbl057Uv;
+                    break;
+                case 5:
+                    stdChrominanceQt = tbl071Uv;
+                    break;
+                case 6:
+                    stdChrominanceQt = tbl086Uv;
+                    break;
+                case 7:
+                    stdChrominanceQt = tbl100Uv;
+                    break;
+            }
+        }
+        //  Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG
+        setQuantTable(stdChrominanceQt,
+                      static_cast<uint8_t>(advancescalefactoruv), tempQT);
 
-    // Load quantization coefficients from JPG file, scale them for DCT and
-    // reorder
-    // from zig-zag order
-    if (mapping == 1) {
-      switch (advanceSelector) {
-        case 0:
-          stdChrominanceQt = tbl000Y;
-          break;
-        case 1:
-          stdChrominanceQt = tbl014Y;
-          break;
-        case 2:
-          stdChrominanceQt = tbl029Y;
-          break;
-        case 3:
-          stdChrominanceQt = tbl043Y;
-          break;
-        case 4:
-          stdChrominanceQt = tbl057Y;
-          break;
-        case 5:
-          stdChrominanceQt = tbl071Y;
-          break;
-        case 6:
-          stdChrominanceQt = tbl086Y;
-          break;
-        case 7:
-          stdChrominanceQt = tbl100Y;
-          break;
-      }
-    } else {
-      switch (advanceSelector) {
-        case 0:
-          stdChrominanceQt = tbl000Uv;
-          break;
-        case 1:
-          stdChrominanceQt = tbl014Uv;
-          break;
-        case 2:
-          stdChrominanceQt = tbl029Uv;
-          break;
-        case 3:
-          stdChrominanceQt = tbl043Uv;
-          break;
-        case 4:
-          stdChrominanceQt = tbl057Uv;
-          break;
-        case 5:
-          stdChrominanceQt = tbl071Uv;
-          break;
-        case 6:
-          stdChrominanceQt = tbl086Uv;
-          break;
-        case 7:
-          stdChrominanceQt = tbl100Uv;
-          break;
-      }
+        for (j = 0; j <= 63; j++)
+        {
+            quant_table[j] = tempQT[zigzag[j]];
+        }
+        j = 0;
+        for (row = 0; row <= 7; row++)
+        {
+            for (col = 0; col <= 7; col++)
+            {
+                quant_table[j] = static_cast<long>(
+                    (quant_table[j] * scalefactor[row] * scalefactor[col]) *
+                    65536);
+                j++;
+            }
+        }
+        bytePos += 64;
     }
-    //  Note: pass ADVANCE SCALE FACTOR to sub-function in Dual-JPEG
-    setQuantTable(stdChrominanceQt, static_cast<uint8_t>(advancescalefactoruv),
-                  tempQT);
 
-    for (j = 0; j <= 63; j++) {
-      quant_table[j] = tempQT[zigzag[j]];
-    }
-    j = 0;
-    for (row = 0; row <= 7; row++) {
-      for (col = 0; col <= 7; col++) {
-        quant_table[j] = static_cast<long>(
-            (quant_table[j] * scalefactor[row] * scalefactor[col]) * 65536);
-        j++;
-      }
-    }
-    bytePos += 64;
-  }
-
-  void idctTransform(short *coef, uint8_t *data, uint8_t nBlock) {
+    void idctTransform(short *coef, uint8_t *data, uint8_t nBlock)
+    {
 #define FIX_1_082392200 ((int)277) /* FIX(1.082392200) */
 #define FIX_1_414213562 ((int)362) /* FIX(1.414213562) */
 #define FIX_1_847759065 ((int)473) /* FIX(1.847759065) */
@@ -347,108 +392,111 @@
 
 #define MULTIPLY(var, cons) ((int)((var) * (cons)) >> 8)
 
-    int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
-    int tmp10, tmp11, tmp12, tmp13;
-    int z5, z10, z11, z12, z13;
-    int workspace[64]; /* buffers data between passes */
+        int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
+        int tmp10, tmp11, tmp12, tmp13;
+        int z5, z10, z11, z12, z13;
+        int workspace[64]; /* buffers data between passes */
 
-    short *inptr = coef;
-    long *quantptr;
-    int *wsptr = workspace;
-    unsigned char *outptr;
-    unsigned char *rLimit = rlimitTable + 128;
-    int ctr, dcval, dctsize = 8;
+        short *inptr = coef;
+        long *quantptr;
+        int *wsptr = workspace;
+        unsigned char *outptr;
+        unsigned char *rLimit = rlimitTable + 128;
+        int ctr, dcval, dctsize = 8;
 
-    quantptr = &qt[nBlock][0];
+        quantptr = &qt[nBlock][0];
 
-    // Pass 1: process columns from input (inptr), store into work array(wsptr)
+        // Pass 1: process columns from input (inptr), store into work
+        // array(wsptr)
 
-    for (ctr = 8; ctr > 0; ctr--) {
-      /* Due to quantization, we will usually find that many of the input
-       * coefficients are zero, especially the AC terms.  We can exploit this
-       * by short-circuiting the IDCT calculation for any column in which all
-       * the AC terms are zero.  In that case each output is equal to the
-       * DC coefficient (with scale factor as needed).
-       * With typical images and quantization tables, half or more of the
-       * column DCT calculations can be simplified this way.
-       */
+        for (ctr = 8; ctr > 0; ctr--)
+        {
+            /* Due to quantization, we will usually find that many of the input
+             * coefficients are zero, especially the AC terms.  We can exploit
+             * this by short-circuiting the IDCT calculation for any column in
+             * which all the AC terms are zero.  In that case each output is
+             * equal to the DC coefficient (with scale factor as needed). With
+             * typical images and quantization tables, half or more of the
+             * column DCT calculations can be simplified this way.
+             */
 
-      if ((inptr[dctsize * 1] | inptr[dctsize * 2] | inptr[dctsize * 3] |
-           inptr[dctsize * 4] | inptr[dctsize * 5] | inptr[dctsize * 6] |
-           inptr[dctsize * 7]) == 0) {
-        /* AC terms all zero */
-        dcval = static_cast<int>((inptr[dctsize * 0] * quantptr[dctsize * 0]) >>
-                                 16);
+            if ((inptr[dctsize * 1] | inptr[dctsize * 2] | inptr[dctsize * 3] |
+                 inptr[dctsize * 4] | inptr[dctsize * 5] | inptr[dctsize * 6] |
+                 inptr[dctsize * 7]) == 0)
+            {
+                /* AC terms all zero */
+                dcval = static_cast<int>(
+                    (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16);
 
-        wsptr[dctsize * 0] = dcval;
-        wsptr[dctsize * 1] = dcval;
-        wsptr[dctsize * 2] = dcval;
-        wsptr[dctsize * 3] = dcval;
-        wsptr[dctsize * 4] = dcval;
-        wsptr[dctsize * 5] = dcval;
-        wsptr[dctsize * 6] = dcval;
-        wsptr[dctsize * 7] = dcval;
+                wsptr[dctsize * 0] = dcval;
+                wsptr[dctsize * 1] = dcval;
+                wsptr[dctsize * 2] = dcval;
+                wsptr[dctsize * 3] = dcval;
+                wsptr[dctsize * 4] = dcval;
+                wsptr[dctsize * 5] = dcval;
+                wsptr[dctsize * 6] = dcval;
+                wsptr[dctsize * 7] = dcval;
 
-        inptr++; /* advance pointers to next column */
-        quantptr++;
-        wsptr++;
-        continue;
-      }
+                inptr++; /* advance pointers to next column */
+                quantptr++;
+                wsptr++;
+                continue;
+            }
 
-      /* Even part */
+            /* Even part */
 
-      tmp0 = (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16;
-      tmp1 = (inptr[dctsize * 2] * quantptr[dctsize * 2]) >> 16;
-      tmp2 = (inptr[dctsize * 4] * quantptr[dctsize * 4]) >> 16;
-      tmp3 = (inptr[dctsize * 6] * quantptr[dctsize * 6]) >> 16;
+            tmp0 = (inptr[dctsize * 0] * quantptr[dctsize * 0]) >> 16;
+            tmp1 = (inptr[dctsize * 2] * quantptr[dctsize * 2]) >> 16;
+            tmp2 = (inptr[dctsize * 4] * quantptr[dctsize * 4]) >> 16;
+            tmp3 = (inptr[dctsize * 6] * quantptr[dctsize * 6]) >> 16;
 
-      tmp10 = tmp0 + tmp2; /* phase 3 */
-      tmp11 = tmp0 - tmp2;
+            tmp10 = tmp0 + tmp2; /* phase 3 */
+            tmp11 = tmp0 - tmp2;
 
-      tmp13 = tmp1 + tmp3;                                    /* phases 5-3 */
-      tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
+            tmp13 = tmp1 + tmp3; /* phases 5-3 */
+            tmp12 = MULTIPLY(tmp1 - tmp3, FIX_1_414213562) - tmp13; /* 2*c4 */
 
-      tmp0 = tmp10 + tmp13; /* phase 2 */
-      tmp3 = tmp10 - tmp13;
-      tmp1 = tmp11 + tmp12;
-      tmp2 = tmp11 - tmp12;
+            tmp0 = tmp10 + tmp13; /* phase 2 */
+            tmp3 = tmp10 - tmp13;
+            tmp1 = tmp11 + tmp12;
+            tmp2 = tmp11 - tmp12;
 
-      /* Odd part */
+            /* Odd part */
 
-      tmp4 = (inptr[dctsize * 1] * quantptr[dctsize * 1]) >> 16;
-      tmp5 = (inptr[dctsize * 3] * quantptr[dctsize * 3]) >> 16;
-      tmp6 = (inptr[dctsize * 5] * quantptr[dctsize * 5]) >> 16;
-      tmp7 = (inptr[dctsize * 7] * quantptr[dctsize * 7]) >> 16;
+            tmp4 = (inptr[dctsize * 1] * quantptr[dctsize * 1]) >> 16;
+            tmp5 = (inptr[dctsize * 3] * quantptr[dctsize * 3]) >> 16;
+            tmp6 = (inptr[dctsize * 5] * quantptr[dctsize * 5]) >> 16;
+            tmp7 = (inptr[dctsize * 7] * quantptr[dctsize * 7]) >> 16;
 
-      z13 = tmp6 + tmp5; /* phase 6 */
-      z10 = tmp6 - tmp5;
-      z11 = tmp4 + tmp7;
-      z12 = tmp4 - tmp7;
+            z13 = tmp6 + tmp5; /* phase 6 */
+            z10 = tmp6 - tmp5;
+            z11 = tmp4 + tmp7;
+            z12 = tmp4 - tmp7;
 
-      tmp7 = z11 + z13;                             /* phase 5 */
-      tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+            tmp7 = z11 + z13;                             /* phase 5 */
+            tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
 
-      z5 = MULTIPLY(z10 + z12, FIX_1_847759065);    /* 2*c2 */
-      tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5;  /* 2*(c2-c6) */
-      tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
+            z5 = MULTIPLY(z10 + z12, FIX_1_847759065);    /* 2*c2 */
+            tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5;  /* 2*(c2-c6) */
+            tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
 
-      tmp6 = tmp12 - tmp7; /* phase 2 */
-      tmp5 = tmp11 - tmp6;
-      tmp4 = tmp10 + tmp5;
+            tmp6 = tmp12 - tmp7; /* phase 2 */
+            tmp5 = tmp11 - tmp6;
+            tmp4 = tmp10 + tmp5;
 
-      wsptr[dctsize * 0] = (tmp0 + tmp7);
-      wsptr[dctsize * 7] = (tmp0 - tmp7);
-      wsptr[dctsize * 1] = (tmp1 + tmp6);
-      wsptr[dctsize * 6] = (tmp1 - tmp6);
-      wsptr[dctsize * 2] = (tmp2 + tmp5);
-      wsptr[dctsize * 5] = (tmp2 - tmp5);
-      wsptr[dctsize * 4] = (tmp3 + tmp4);
-      wsptr[dctsize * 3] = (tmp3 - tmp4);
+            wsptr[dctsize * 0] = (tmp0 + tmp7);
+            wsptr[dctsize * 7] = (tmp0 - tmp7);
+            wsptr[dctsize * 1] = (tmp1 + tmp6);
+            wsptr[dctsize * 6] = (tmp1 - tmp6);
+            wsptr[dctsize * 2] = (tmp2 + tmp5);
+            wsptr[dctsize * 5] = (tmp2 - tmp5);
+            wsptr[dctsize * 4] = (tmp3 + tmp4);
+            wsptr[dctsize * 3] = (tmp3 - tmp4);
 
-      inptr++; /* advance pointers to next column */
-      quantptr++;
-      wsptr++;
-    }
+            inptr++; /* advance pointers to next column */
+            quantptr++;
+            wsptr++;
+        }
 
 /* Pass 2: process rows from work array, store into output array. */
 /* Note that we must descale the results by a factor of 8 == 2**3, */
@@ -458,897 +506,1042 @@
 #define PASS1_BITS 0
 #define IDESCALE(x, n) ((int)((x) >> (n)))
 
-    wsptr = workspace;
-    for (ctr = 0; ctr < dctsize; ctr++) {
-      outptr = data + ctr * 8;
+        wsptr = workspace;
+        for (ctr = 0; ctr < dctsize; ctr++)
+        {
+            outptr = data + ctr * 8;
 
-      /* Rows of zeroes can be exploited in the same way as we did with columns.
-       * However, the column calculation has created many nonzero AC terms, so
-       * the simplification applies less often (typically 5% to 10% of the
-       * time). On machines with very fast multiplication, it's possible that
-       * the test takes more time than it's worth.  In that case this section
-       * may be commented out.
-       */
-      /* Even part */
+            /* Rows of zeroes can be exploited in the same way as we did with
+             * columns. However, the column calculation has created many nonzero
+             * AC terms, so the simplification applies less often (typically 5%
+             * to 10% of the time). On machines with very fast multiplication,
+             * it's possible that the test takes more time than it's worth.  In
+             * that case this section may be commented out.
+             */
+            /* Even part */
 
-      tmp10 = (wsptr[0] + wsptr[4]);
-      tmp11 = (wsptr[0] - wsptr[4]);
+            tmp10 = (wsptr[0] + wsptr[4]);
+            tmp11 = (wsptr[0] - wsptr[4]);
 
-      tmp13 = (wsptr[2] + wsptr[6]);
-      tmp12 = MULTIPLY((int)wsptr[2] - (int)wsptr[6], FIX_1_414213562) - tmp13;
+            tmp13 = (wsptr[2] + wsptr[6]);
+            tmp12 = MULTIPLY((int)wsptr[2] - (int)wsptr[6], FIX_1_414213562) -
+                    tmp13;
 
-      tmp0 = tmp10 + tmp13;
-      tmp3 = tmp10 - tmp13;
-      tmp1 = tmp11 + tmp12;
-      tmp2 = tmp11 - tmp12;
+            tmp0 = tmp10 + tmp13;
+            tmp3 = tmp10 - tmp13;
+            tmp1 = tmp11 + tmp12;
+            tmp2 = tmp11 - tmp12;
 
-      /* Odd part */
+            /* Odd part */
 
-      z13 = wsptr[5] + wsptr[3];
-      z10 = wsptr[5] - wsptr[3];
-      z11 = wsptr[1] + wsptr[7];
-      z12 = wsptr[1] - wsptr[7];
+            z13 = wsptr[5] + wsptr[3];
+            z10 = wsptr[5] - wsptr[3];
+            z11 = wsptr[1] + wsptr[7];
+            z12 = wsptr[1] - wsptr[7];
 
-      tmp7 = z11 + z13;                             /* phase 5 */
-      tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
+            tmp7 = z11 + z13;                             /* phase 5 */
+            tmp11 = MULTIPLY(z11 - z13, FIX_1_414213562); /* 2*c4 */
 
-      z5 = MULTIPLY(z10 + z12, FIX_1_847759065);    /* 2*c2 */
-      tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5;  /* 2*(c2-c6) */
-      tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
+            z5 = MULTIPLY(z10 + z12, FIX_1_847759065);    /* 2*c2 */
+            tmp10 = MULTIPLY(z12, FIX_1_082392200) - z5;  /* 2*(c2-c6) */
+            tmp12 = MULTIPLY(z10, -FIX_2_613125930) + z5; /* -2*(c2+c6) */
 
-      tmp6 = tmp12 - tmp7; /* phase 2 */
-      tmp5 = tmp11 - tmp6;
-      tmp4 = tmp10 + tmp5;
+            tmp6 = tmp12 - tmp7; /* phase 2 */
+            tmp5 = tmp11 - tmp6;
+            tmp4 = tmp10 + tmp5;
 
-      /* Final output stage: scale down by a factor of 8 and range-limit */
+            /* Final output stage: scale down by a factor of 8 and range-limit
+             */
 
-      outptr[0] = rLimit[IDESCALE((tmp0 + tmp7), (PASS1_BITS + 3)) & 1023L];
-      outptr[7] = rLimit[IDESCALE((tmp0 - tmp7), (PASS1_BITS + 3)) & 1023L];
-      outptr[1] = rLimit[IDESCALE((tmp1 + tmp6), (PASS1_BITS + 3)) & 1023L];
-      outptr[6] = rLimit[IDESCALE((tmp1 - tmp6), (PASS1_BITS + 3)) & 1023L];
-      outptr[2] = rLimit[IDESCALE((tmp2 + tmp5), (PASS1_BITS + 3)) & 1023L];
-      outptr[5] = rLimit[IDESCALE((tmp2 - tmp5), (PASS1_BITS + 3)) & 1023L];
-      outptr[4] = rLimit[IDESCALE((tmp3 + tmp4), (PASS1_BITS + 3)) & 1023L];
-      outptr[3] = rLimit[IDESCALE((tmp3 - tmp4), (PASS1_BITS + 3)) & 1023L];
+            outptr[0] =
+                rLimit[IDESCALE((tmp0 + tmp7), (PASS1_BITS + 3)) & 1023L];
+            outptr[7] =
+                rLimit[IDESCALE((tmp0 - tmp7), (PASS1_BITS + 3)) & 1023L];
+            outptr[1] =
+                rLimit[IDESCALE((tmp1 + tmp6), (PASS1_BITS + 3)) & 1023L];
+            outptr[6] =
+                rLimit[IDESCALE((tmp1 - tmp6), (PASS1_BITS + 3)) & 1023L];
+            outptr[2] =
+                rLimit[IDESCALE((tmp2 + tmp5), (PASS1_BITS + 3)) & 1023L];
+            outptr[5] =
+                rLimit[IDESCALE((tmp2 - tmp5), (PASS1_BITS + 3)) & 1023L];
+            outptr[4] =
+                rLimit[IDESCALE((tmp3 + tmp4), (PASS1_BITS + 3)) & 1023L];
+            outptr[3] =
+                rLimit[IDESCALE((tmp3 - tmp4), (PASS1_BITS + 3)) & 1023L];
 
-      wsptr += dctsize; /* advance pointer to next row */
+            wsptr += dctsize; /* advance pointer to next row */
+        }
     }
-  }
-  void yuvToRgb(
-      int txb, int tyb,
-      unsigned char
-          *pYCbCr,       // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
-      struct RGB *pYUV,  // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
-      unsigned char
-          *pBgr  // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
-  ) {
-    int i, j, pos, m, n;
-    unsigned char cb, cr, *py, *pcb, *pcr, *py420[4];
-    int y;
-    struct RGB *pByte;
-    int nBlocksInMcu = 6;
-    unsigned int pixelX, pixelY;
+    void yuvToRgb(
+        int txb, int tyb,
+        unsigned char
+            *pYCbCr,      // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
+        struct RGB *pYUV, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
+        unsigned char
+            *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
+    )
+    {
+        int i, j, pos, m, n;
+        unsigned char cb, cr, *py, *pcb, *pcr, *py420[4];
+        int y;
+        struct RGB *pByte;
+        int nBlocksInMcu = 6;
+        unsigned int pixelX, pixelY;
 
-    pByte = reinterpret_cast<struct RGB *>(pBgr);
-    if (yuvmode == YuvMode::YUV444) {
-      py = pYCbCr;
-      pcb = pYCbCr + 64;
-      pcr = pcb + 64;
+        pByte = reinterpret_cast<struct RGB *>(pBgr);
+        if (yuvmode == YuvMode::YUV444)
+        {
+            py = pYCbCr;
+            pcb = pYCbCr + 64;
+            pcr = pcb + 64;
 
-      pixelX = txb * 8;
-      pixelY = tyb * 8;
-      pos = (pixelY * width) + pixelX;
+            pixelX = txb * 8;
+            pixelY = tyb * 8;
+            pos = (pixelY * width) + pixelX;
 
-      for (j = 0; j < 8; j++) {
-        for (i = 0; i < 8; i++) {
-          m = ((j << 3) + i);
-          y = py[m];
-          cb = pcb[m];
-          cr = pcr[m];
-          n = pos + i;
-          // For 2Pass. Save the YUV value
-          pYUV[n].b = cb;
-          pYUV[n].g = y;
-          pYUV[n].r = cr;
-          pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
-          pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
-          pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+            for (j = 0; j < 8; j++)
+            {
+                for (i = 0; i < 8; i++)
+                {
+                    m = ((j << 3) + i);
+                    y = py[m];
+                    cb = pcb[m];
+                    cr = pcr[m];
+                    n = pos + i;
+                    // For 2Pass. Save the YUV value
+                    pYUV[n].b = cb;
+                    pYUV[n].g = y;
+                    pYUV[n].r = cr;
+                    pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
+                    pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
+                    pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+                }
+                pos += width;
+            }
         }
-        pos += width;
-      }
-    } else {
-      for (i = 0; i < nBlocksInMcu - 2; i++) {
-        py420[i] = pYCbCr + i * 64;
-      }
-      pcb = pYCbCr + (nBlocksInMcu - 2) * 64;
-      pcr = pcb + 64;
+        else
+        {
+            for (i = 0; i < nBlocksInMcu - 2; i++)
+            {
+                py420[i] = pYCbCr + i * 64;
+            }
+            pcb = pYCbCr + (nBlocksInMcu - 2) * 64;
+            pcr = pcb + 64;
 
-      pixelX = txb * 16;
-      pixelY = tyb * 16;
-      pos = (pixelY * width) + pixelX;
+            pixelX = txb * 16;
+            pixelY = tyb * 16;
+            pos = (pixelY * width) + pixelX;
 
-      for (j = 0; j < 16; j++) {
-        for (i = 0; i < 16; i++) {
-          //	block number is ((j/8) * 2 + i/8)={0, 1, 2, 3}
-          y = *(py420[(j >> 3) * 2 + (i >> 3)]++);
-          m = ((j >> 1) << 3) + (i >> 1);
-          cb = pcb[m];
-          cr = pcr[m];
-          n = pos + i;
-          pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
-          pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
-          pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+            for (j = 0; j < 16; j++)
+            {
+                for (i = 0; i < 16; i++)
+                {
+                    //	block number is ((j/8) * 2 + i/8)={0, 1, 2, 3}
+                    y = *(py420[(j >> 3) * 2 + (i >> 3)]++);
+                    m = ((j >> 1) << 3) + (i >> 1);
+                    cb = pcb[m];
+                    cr = pcr[m];
+                    n = pos + i;
+                    pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
+                    pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
+                    pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+                }
+                pos += width;
+            }
         }
-        pos += width;
-      }
     }
-  }
-  void yuvToBuffer(
-      int txb, int tyb,
-      unsigned char
-          *pYCbCr,  // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
-      struct RGB
-          *pYUV,  // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
-      unsigned char
-          *pBgr  // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
-  ) {
-    int i, j, pos, m, n;
-    unsigned char cb, cr, *py, *pcb, *pcr, *py420[4];
-    int y;
-    struct RGB *pByte;
-    int nBlocksInMcu = 6;
-    unsigned int pixelX, pixelY;
+    void yuvToBuffer(
+        int txb, int tyb,
+        unsigned char
+            *pYCbCr, // in, Y: 256 or 64 bytes; Cb: 64 bytes; Cr: 64 bytes
+        struct RGB
+            *pYUV, // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
+        unsigned char
+            *pBgr // out, BGR format, 16*16*3 = 768 bytes; or 8*8*3=192 bytes
+    )
+    {
+        int i, j, pos, m, n;
+        unsigned char cb, cr, *py, *pcb, *pcr, *py420[4];
+        int y;
+        struct RGB *pByte;
+        int nBlocksInMcu = 6;
+        unsigned int pixelX, pixelY;
 
-    pByte = reinterpret_cast<struct RGB *>(pBgr);
-    if (yuvmode == YuvMode::YUV444) {
-      py = pYCbCr;
-      pcb = pYCbCr + 64;
-      pcr = pcb + 64;
+        pByte = reinterpret_cast<struct RGB *>(pBgr);
+        if (yuvmode == YuvMode::YUV444)
+        {
+            py = pYCbCr;
+            pcb = pYCbCr + 64;
+            pcr = pcb + 64;
 
-      pixelX = txb * 8;
-      pixelY = tyb * 8;
-      pos = (pixelY * width) + pixelX;
+            pixelX = txb * 8;
+            pixelY = tyb * 8;
+            pos = (pixelY * width) + pixelX;
 
-      for (j = 0; j < 8; j++) {
-        for (i = 0; i < 8; i++) {
-          m = ((j << 3) + i);
-          n = pos + i;
-          y = pYUV[n].g + (py[m] - 128);
-          cb = pYUV[n].b + (pcb[m] - 128);
-          cr = pYUV[n].r + (pcr[m] - 128);
-          pYUV[n].b = cb;
-          pYUV[n].g = y;
-          pYUV[n].r = cr;
-          pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
-          pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
-          pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+            for (j = 0; j < 8; j++)
+            {
+                for (i = 0; i < 8; i++)
+                {
+                    m = ((j << 3) + i);
+                    n = pos + i;
+                    y = pYUV[n].g + (py[m] - 128);
+                    cb = pYUV[n].b + (pcb[m] - 128);
+                    cr = pYUV[n].r + (pcr[m] - 128);
+                    pYUV[n].b = cb;
+                    pYUV[n].g = y;
+                    pYUV[n].r = cr;
+                    pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
+                    pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
+                    pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+                }
+                pos += width;
+            }
         }
-        pos += width;
-      }
-    } else {
-      for (i = 0; i < nBlocksInMcu - 2; i++) {
-        py420[i] = pYCbCr + i * 64;
-      }
-      pcb = pYCbCr + (nBlocksInMcu - 2) * 64;
-      pcr = pcb + 64;
+        else
+        {
+            for (i = 0; i < nBlocksInMcu - 2; i++)
+            {
+                py420[i] = pYCbCr + i * 64;
+            }
+            pcb = pYCbCr + (nBlocksInMcu - 2) * 64;
+            pcr = pcb + 64;
 
-      pixelX = txb * 16;
-      pixelY = tyb * 16;
-      pos = (pixelY * width) + pixelX;
+            pixelX = txb * 16;
+            pixelY = tyb * 16;
+            pos = (pixelY * width) + pixelX;
 
-      for (j = 0; j < 16; j++) {
-        for (i = 0; i < 16; i++) {
-          //	block number is ((j/8) * 2 + i/8)={0, 1, 2, 3}
-          y = *(py420[(j >> 3) * 2 + (i >> 3)]++);
-          m = ((j >> 1) << 3) + (i >> 1);
-          cb = pcb[m];
-          cr = pcr[m];
-          n = pos + i;
-          pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
-          pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
-          pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+            for (j = 0; j < 16; j++)
+            {
+                for (i = 0; i < 16; i++)
+                {
+                    //	block number is ((j/8) * 2 + i/8)={0, 1, 2, 3}
+                    y = *(py420[(j >> 3) * 2 + (i >> 3)]++);
+                    m = ((j >> 1) << 3) + (i >> 1);
+                    cb = pcb[m];
+                    cr = pcr[m];
+                    n = pos + i;
+                    pByte[n].b = rlimitTable[mY[y] + mCbToB[cb]];
+                    pByte[n].g = rlimitTable[mY[y] + mCbToG[cb] + mCrToG[cr]];
+                    pByte[n].r = rlimitTable[mY[y] + mCrToR[cr]];
+                }
+                pos += width;
+            }
         }
-        pos += width;
-      }
     }
-  }
-  void decompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection) {
-    unsigned char *ptr;
-    unsigned char byTileYuv[768] = {};
+    void decompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection)
+    {
+        unsigned char *ptr;
+        unsigned char byTileYuv[768] = {};
 
-    memset(dctCoeff, 0, 384 * 2);
-    ptr = byTileYuv;
-    processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0);
-    idctTransform(dctCoeff, ptr, QT_TableSelection);
-    ptr += 64;
+        memset(dctCoeff, 0, 384 * 2);
+        ptr = byTileYuv;
+        processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0);
+        idctTransform(dctCoeff, ptr, QT_TableSelection);
+        ptr += 64;
 
-    if (yuvmode == YuvMode::YUV420) {
-      processHuffmanDataUnit(ydcNr, yacNr, &dcy, 64);
-      idctTransform(dctCoeff + 64, ptr, QT_TableSelection);
-      ptr += 64;
+        if (yuvmode == YuvMode::YUV420)
+        {
+            processHuffmanDataUnit(ydcNr, yacNr, &dcy, 64);
+            idctTransform(dctCoeff + 64, ptr, QT_TableSelection);
+            ptr += 64;
 
-      processHuffmanDataUnit(ydcNr, yacNr, &dcy, 128);
-      idctTransform(dctCoeff + 128, ptr, QT_TableSelection);
-      ptr += 64;
+            processHuffmanDataUnit(ydcNr, yacNr, &dcy, 128);
+            idctTransform(dctCoeff + 128, ptr, QT_TableSelection);
+            ptr += 64;
 
-      processHuffmanDataUnit(ydcNr, yacNr, &dcy, 192);
-      idctTransform(dctCoeff + 192, ptr, QT_TableSelection);
-      ptr += 64;
+            processHuffmanDataUnit(ydcNr, yacNr, &dcy, 192);
+            idctTransform(dctCoeff + 192, ptr, QT_TableSelection);
+            ptr += 64;
 
-      processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 256);
-      idctTransform(dctCoeff + 256, ptr, QT_TableSelection + 1);
-      ptr += 64;
+            processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 256);
+            idctTransform(dctCoeff + 256, ptr, QT_TableSelection + 1);
+            ptr += 64;
 
-      processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 320);
-      idctTransform(dctCoeff + 320, ptr, QT_TableSelection + 1);
-    } else {
-      processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64);
-      idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1);
-      ptr += 64;
+            processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 320);
+            idctTransform(dctCoeff + 320, ptr, QT_TableSelection + 1);
+        }
+        else
+        {
+            processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64);
+            idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1);
+            ptr += 64;
 
-      processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128);
-      idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1);
+            processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128);
+            idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1);
+        }
+
+        //    yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
+        //  yuvBuffer for YUV record
+        yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(),
+                 reinterpret_cast<unsigned char *>(outBuf));
     }
 
-    //    yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
-    //  yuvBuffer for YUV record
-    yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(),
-             reinterpret_cast<unsigned char *>(outBuf));
-  }
+    void decompress2Pass(int txb, int tyb, char *outBuf,
+                         uint8_t QT_TableSelection)
+    {
+        unsigned char *ptr;
+        unsigned char byTileYuv[768];
+        memset(dctCoeff, 0, 384 * 2);
 
-  void decompress2Pass(int txb, int tyb, char *outBuf,
-                       uint8_t QT_TableSelection) {
-    unsigned char *ptr;
-    unsigned char byTileYuv[768];
-    memset(dctCoeff, 0, 384 * 2);
+        ptr = byTileYuv;
+        processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0);
+        idctTransform(dctCoeff, ptr, QT_TableSelection);
+        ptr += 64;
 
-    ptr = byTileYuv;
-    processHuffmanDataUnit(ydcNr, yacNr, &dcy, 0);
-    idctTransform(dctCoeff, ptr, QT_TableSelection);
-    ptr += 64;
+        processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64);
+        idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1);
+        ptr += 64;
 
-    processHuffmanDataUnit(cbDcNr, cbAcNr, &dcCb, 64);
-    idctTransform(dctCoeff + 64, ptr, QT_TableSelection + 1);
-    ptr += 64;
+        processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128);
+        idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1);
 
-    processHuffmanDataUnit(crDcNr, crAcNr, &dcCr, 128);
-    idctTransform(dctCoeff + 128, ptr, QT_TableSelection + 1);
-
-    yuvToBuffer(txb, tyb, byTileYuv, yuvBuffer.data(),
-                reinterpret_cast<unsigned char *>(outBuf));
-    //    yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
-  }
-
-  void vqDecompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection,
-                    struct ColorCache *VQ) {
-    unsigned char *ptr, i;
-    unsigned char byTileYuv[192];
-    int data;
-
-    ptr = byTileYuv;
-    if (VQ->bitMapBits == 0) {
-      for (i = 0; i < 64; i++) {
-        ptr[0] = (VQ->color[VQ->index[0]] & 0xFF0000) >> 16;
-        ptr[64] = (VQ->color[VQ->index[0]] & 0x00FF00) >> 8;
-        ptr[128] = VQ->color[VQ->index[0]] & 0x0000FF;
-        ptr += 1;
-      }
-    } else {
-      for (i = 0; i < 64; i++) {
-        data = static_cast<int>(lookKbits(VQ->bitMapBits));
-        ptr[0] = (VQ->color[VQ->index[data]] & 0xFF0000) >> 16;
-        ptr[64] = (VQ->color[VQ->index[data]] & 0x00FF00) >> 8;
-        ptr[128] = VQ->color[VQ->index[data]] & 0x0000FF;
-        ptr += 1;
-        skipKbits(VQ->bitMapBits);
-      }
+        yuvToBuffer(txb, tyb, byTileYuv, yuvBuffer.data(),
+                    reinterpret_cast<unsigned char *>(outBuf));
+        //    yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
     }
-    //    yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
-    yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(),
-             reinterpret_cast<unsigned char *>(outBuf));
-  }
 
-  void moveBlockIndex() {
-    if (yuvmode == YuvMode::YUV444) {
-      txb++;
-      if (txb >= static_cast<int>(width / 8)) {
-        tyb++;
-        if (tyb >= static_cast<int>(height / 8)) {
-          tyb = 0;
+    void vqDecompress(int txb, int tyb, char *outBuf, uint8_t QT_TableSelection,
+                      struct ColorCache *VQ)
+    {
+        unsigned char *ptr, i;
+        unsigned char byTileYuv[192];
+        int data;
+
+        ptr = byTileYuv;
+        if (VQ->bitMapBits == 0)
+        {
+            for (i = 0; i < 64; i++)
+            {
+                ptr[0] = (VQ->color[VQ->index[0]] & 0xFF0000) >> 16;
+                ptr[64] = (VQ->color[VQ->index[0]] & 0x00FF00) >> 8;
+                ptr[128] = VQ->color[VQ->index[0]] & 0x0000FF;
+                ptr += 1;
+            }
         }
-        txb = 0;
-      }
-    } else {
-      txb++;
-      if (txb >= static_cast<int>(width / 16)) {
-        tyb++;
-        if (tyb >= static_cast<int>(height / 16)) {
-          tyb = 0;
+        else
+        {
+            for (i = 0; i < 64; i++)
+            {
+                data = static_cast<int>(lookKbits(VQ->bitMapBits));
+                ptr[0] = (VQ->color[VQ->index[data]] & 0xFF0000) >> 16;
+                ptr[64] = (VQ->color[VQ->index[data]] & 0x00FF00) >> 8;
+                ptr[128] = VQ->color[VQ->index[data]] & 0x0000FF;
+                ptr += 1;
+                skipKbits(VQ->bitMapBits);
+            }
         }
-        txb = 0;
-      }
+        //    yuvToRgb (txb, tyb, byTileYuv, (unsigned char *)outBuf);
+        yuvToRgb(txb, tyb, byTileYuv, yuvBuffer.data(),
+                 reinterpret_cast<unsigned char *>(outBuf));
     }
-  }
 
-  void initColorTable() {
-    int i, x;
-    int nScale = 1L << 16;  // equal to power(2,16)
-    int nHalf = nScale >> 1;
+    void moveBlockIndex()
+    {
+        if (yuvmode == YuvMode::YUV444)
+        {
+            txb++;
+            if (txb >= static_cast<int>(width / 8))
+            {
+                tyb++;
+                if (tyb >= static_cast<int>(height / 8))
+                {
+                    tyb = 0;
+                }
+                txb = 0;
+            }
+        }
+        else
+        {
+            txb++;
+            if (txb >= static_cast<int>(width / 16))
+            {
+                tyb++;
+                if (tyb >= static_cast<int>(height / 16))
+                {
+                    tyb = 0;
+                }
+                txb = 0;
+            }
+        }
+    }
+
+    void initColorTable()
+    {
+        int i, x;
+        int nScale = 1L << 16; // equal to power(2,16)
+        int nHalf = nScale >> 1;
 
 #define FIX(x) ((int)((x)*nScale + 0.5))
 
-    /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
-    /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
-    /* Cr=>r value is nearest int to 1.597656 * x */
-    /* Cb=>b value is nearest int to 2.015625 * x */
-    /* Cr=>g value is scaled-up -0.8125 * x */
-    /* Cb=>g value is scaled-up -0.390625 * x */
-    for (i = 0, x = -128; i < 256; i++, x++) {
-      mCrToR[i] = (FIX(1.597656) * x + nHalf) >> 16;
-      mCbToB[i] = (FIX(2.015625) * x + nHalf) >> 16;
-      mCrToG[i] = (-FIX(0.8125) * x + nHalf) >> 16;
-      mCbToG[i] = (-FIX(0.390625) * x + nHalf) >> 16;
-    }
-    for (i = 0, x = -16; i < 256; i++, x++) {
-      mY[i] = (FIX(1.164) * x + nHalf) >> 16;
-    }
-    // For color Text Enchance Y Re-map. Recommend to disable in default
-    /*
-            for (i = 0; i < (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate);
-       i++) {
-                    temp = (double)i /
-       VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate;
-                    temp1 = 1.0 / VideoEngineInfo->INFData.Gamma1Parameter;
-                    mY[i] =
-       (BYTE)(VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate * pow (temp,
-       temp1));
-                    if (mY[i] > 255) mY[i] = 255;
-            }
-            for (i = (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i < 256;
-       i++) {
-                    mY[i] =
-       (BYTE)((VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) + (256 -
-       VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) * ( pow((double)((i -
-       VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) / (256 -
-       (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate))), (1.0 /
-       VideoEngineInfo->INFData.Gamma2Parameter)) ));
-                    if (mY[i] > 255) mY[i] = 255;
-            }
-    */
-  }
-  void loadHuffmanTable(HuffmanTable *HT, const unsigned char *nrcode,
-                        const unsigned char *value,
-                        const unsigned short int *Huff_code) {
-    unsigned char k, j, i;
-    unsigned int code, codeIndex;
-
-    for (j = 1; j <= 16; j++) {
-      HT->length[j] = nrcode[j];
-    }
-    for (i = 0, k = 1; k <= 16; k++) {
-      for (j = 0; j < HT->length[k]; j++) {
-        HT->v[wordHiLo(k, j)] = value[i];
-        i++;
-      }
-    }
-
-    code = 0;
-    for (k = 1; k <= 16; k++) {
-      HT->minorCode[k] = static_cast<unsigned short int>(code);
-      for (j = 1; j <= HT->length[k]; j++) {
-        code++;
-      }
-      HT->majorCode[k] = static_cast<unsigned short int>(code - 1);
-      code *= 2;
-      if (HT->length[k] == 0) {
-        HT->minorCode[k] = 0xFFFF;
-        HT->majorCode[k] = 0;
-      }
-    }
-
-    HT->len[0] = 2;
-    i = 2;
-
-    for (codeIndex = 1; codeIndex < 65535; codeIndex++) {
-      if (codeIndex < Huff_code[i]) {
-        HT->len[codeIndex] = static_cast<unsigned char>(Huff_code[i + 1]);
-      } else {
-        i = i + 2;
-        HT->len[codeIndex] = static_cast<unsigned char>(Huff_code[i + 1]);
-      }
-    }
-  }
-  void initJpgTable() {
-    initColorTable();
-    prepareRangeLimitTable();
-    loadHuffmanTable(&htdc[0], stdDcLuminanceNrcodes, stdDcLuminanceValues,
-                     dcLuminanceHuffmancode);
-    loadHuffmanTable(&htac[0], stdAcLuminanceNrcodes, stdAcLuminanceValues,
-                     acLuminanceHuffmancode);
-    loadHuffmanTable(&htdc[1], stdDcChrominanceNrcodes, stdDcChrominanceValues,
-                     dcChrominanceHuffmancode);
-    loadHuffmanTable(&htac[1], stdAcChrominanceNrcodes, stdAcChrominanceValues,
-                     acChrominanceHuffmancode);
-  }
-
-  void prepareRangeLimitTable()
-  /* Allocate and fill in the sample_range_limit table */
-  {
-    int j;
-    rlimitTable = reinterpret_cast<unsigned char *>(malloc(5 * 256L + 128));
-    /* First segment of "simple" table: limit[x] = 0 for x < 0 */
-    memset((void *)rlimitTable, 0, 256);
-    rlimitTable += 256; /* allow negative subscripts of simple table */
-    /* Main part of "simple" table: limit[x] = x */
-    for (j = 0; j < 256; j++) {
-      rlimitTable[j] = j;
-    }
-    /* End of simple table, rest of first half of post-IDCT table */
-    for (j = 256; j < 640; j++) {
-      rlimitTable[j] = 255;
-    }
-
-    /* Second half of post-IDCT table */
-    memset((void *)(rlimitTable + 640), 0, 384);
-    for (j = 0; j < 128; j++) {
-      rlimitTable[j + 1024] = j;
-    }
-  }
-
-  inline unsigned short int wordHiLo(uint8_t byte_high, uint8_t byte_low) {
-    return (byte_high << 8) + byte_low;
-  }
-
-  // river
-  void processHuffmanDataUnit(uint8_t DC_nr, uint8_t AC_nr,
-                              signed short int *previous_DC,
-                              unsigned short int position) {
-    uint8_t nr = 0;
-    uint8_t k;
-    unsigned short int tmpHcode;
-    uint8_t sizeVal, count0;
-    unsigned short int *minCode;
-    uint8_t *huffValues;
-    uint8_t byteTemp;
-
-    minCode = htdc[DC_nr].minorCode;
-    //   maj_code=htdc[DC_nr].majorCode;
-    huffValues = htdc[DC_nr].v;
-
-    // DC
-    k = htdc[DC_nr].len[static_cast<unsigned short int>(codebuf >> 16)];
-    // river
-    //	 tmp_Hcode=lookKbits(k);
-    tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k));
-    skipKbits(k);
-    sizeVal =
-        huffValues[wordHiLo(k, static_cast<uint8_t>(tmpHcode - minCode[k]))];
-    if (sizeVal == 0) {
-      dctCoeff[position + 0] = *previous_DC;
-    } else {
-      dctCoeff[position + 0] = *previous_DC + getKbits(sizeVal);
-      *previous_DC = dctCoeff[position + 0];
-    }
-
-    // Second, AC coefficient decoding
-    minCode = htac[AC_nr].minorCode;
-    //   maj_code=htac[AC_nr].majorCode;
-    huffValues = htac[AC_nr].v;
-
-    nr = 1;  // AC coefficient
-    do {
-      k = htac[AC_nr].len[static_cast<unsigned short int>(codebuf >> 16)];
-      tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k));
-      skipKbits(k);
-
-      byteTemp =
-          huffValues[wordHiLo(k, static_cast<uint8_t>(tmpHcode - minCode[k]))];
-      sizeVal = byteTemp & 0xF;
-      count0 = byteTemp >> 4;
-      if (sizeVal == 0) {
-        if (count0 != 0xF) {
-          break;
+        /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
+        /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
+        /* Cr=>r value is nearest int to 1.597656 * x */
+        /* Cb=>b value is nearest int to 2.015625 * x */
+        /* Cr=>g value is scaled-up -0.8125 * x */
+        /* Cb=>g value is scaled-up -0.390625 * x */
+        for (i = 0, x = -128; i < 256; i++, x++)
+        {
+            mCrToR[i] = (FIX(1.597656) * x + nHalf) >> 16;
+            mCbToB[i] = (FIX(2.015625) * x + nHalf) >> 16;
+            mCrToG[i] = (-FIX(0.8125) * x + nHalf) >> 16;
+            mCbToG[i] = (-FIX(0.390625) * x + nHalf) >> 16;
         }
-        nr += 16;
-      } else {
-        nr += count0;  // skip count_0 zeroes
-        dctCoeff[position + dezigzag[nr++]] = getKbits(sizeVal);
-      }
-    } while (nr < 64);
-  }
-
-  unsigned short int lookKbits(uint8_t k) {
-    unsigned short int revcode;
-
-    revcode = static_cast<unsigned short int>(codebuf >> (32 - k));
-
-    return (revcode);
-  }
-
-  void skipKbits(uint8_t k) {
-    unsigned long readbuf;
-
-    if ((newbits - k) <= 0) {
-      readbuf = buffer[bufferIndex];
-      bufferIndex++;
-      codebuf =
-          (codebuf << k) | ((newbuf | (readbuf >> (newbits))) >> (32 - k));
-      newbuf = readbuf << (k - newbits);
-      newbits = 32 + newbits - k;
-    } else {
-      codebuf = (codebuf << k) | (newbuf >> (32 - k));
-      newbuf = newbuf << k;
-      newbits -= k;
+        for (i = 0, x = -16; i < 256; i++, x++)
+        {
+            mY[i] = (FIX(1.164) * x + nHalf) >> 16;
+        }
+        // For color Text Enchance Y Re-map. Recommend to disable in default
+        /*
+                for (i = 0; i <
+           (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i++) { temp =
+           (double)i / VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate; temp1
+           = 1.0 / VideoEngineInfo->INFData.Gamma1Parameter; mY[i] =
+           (BYTE)(VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate * pow (temp,
+           temp1));
+                        if (mY[i] > 255) mY[i] = 255;
+                }
+                for (i = (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate); i <
+           256; i++) { mY[i] =
+           (BYTE)((VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) + (256 -
+           VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) * ( pow((double)((i
+           - VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate) / (256 -
+           (VideoEngineInfo->INFData.Gamma1_Gamma2_Seperate))), (1.0 /
+           VideoEngineInfo->INFData.Gamma2Parameter)) ));
+                        if (mY[i] > 255) mY[i] = 255;
+                }
+        */
     }
-  }
+    void loadHuffmanTable(HuffmanTable *HT, const unsigned char *nrcode,
+                          const unsigned char *value,
+                          const unsigned short int *Huff_code)
+    {
+        unsigned char k, j, i;
+        unsigned int code, codeIndex;
 
-  signed short int getKbits(uint8_t k) {
-    signed short int signedWordvalue;
+        for (j = 1; j <= 16; j++)
+        {
+            HT->length[j] = nrcode[j];
+        }
+        for (i = 0, k = 1; k <= 16; k++)
+        {
+            for (j = 0; j < HT->length[k]; j++)
+            {
+                HT->v[wordHiLo(k, j)] = value[i];
+                i++;
+            }
+        }
+
+        code = 0;
+        for (k = 1; k <= 16; k++)
+        {
+            HT->minorCode[k] = static_cast<unsigned short int>(code);
+            for (j = 1; j <= HT->length[k]; j++)
+            {
+                code++;
+            }
+            HT->majorCode[k] = static_cast<unsigned short int>(code - 1);
+            code *= 2;
+            if (HT->length[k] == 0)
+            {
+                HT->minorCode[k] = 0xFFFF;
+                HT->majorCode[k] = 0;
+            }
+        }
+
+        HT->len[0] = 2;
+        i = 2;
+
+        for (codeIndex = 1; codeIndex < 65535; codeIndex++)
+        {
+            if (codeIndex < Huff_code[i])
+            {
+                HT->len[codeIndex] =
+                    static_cast<unsigned char>(Huff_code[i + 1]);
+            }
+            else
+            {
+                i = i + 2;
+                HT->len[codeIndex] =
+                    static_cast<unsigned char>(Huff_code[i + 1]);
+            }
+        }
+    }
+    void initJpgTable()
+    {
+        initColorTable();
+        prepareRangeLimitTable();
+        loadHuffmanTable(&htdc[0], stdDcLuminanceNrcodes, stdDcLuminanceValues,
+                         dcLuminanceHuffmancode);
+        loadHuffmanTable(&htac[0], stdAcLuminanceNrcodes, stdAcLuminanceValues,
+                         acLuminanceHuffmancode);
+        loadHuffmanTable(&htdc[1], stdDcChrominanceNrcodes,
+                         stdDcChrominanceValues, dcChrominanceHuffmancode);
+        loadHuffmanTable(&htac[1], stdAcChrominanceNrcodes,
+                         stdAcChrominanceValues, acChrominanceHuffmancode);
+    }
+
+    void prepareRangeLimitTable()
+    /* Allocate and fill in the sample_range_limit table */
+    {
+        int j;
+        rlimitTable = reinterpret_cast<unsigned char *>(malloc(5 * 256L + 128));
+        /* First segment of "simple" table: limit[x] = 0 for x < 0 */
+        memset((void *)rlimitTable, 0, 256);
+        rlimitTable += 256; /* allow negative subscripts of simple table */
+        /* Main part of "simple" table: limit[x] = x */
+        for (j = 0; j < 256; j++)
+        {
+            rlimitTable[j] = j;
+        }
+        /* End of simple table, rest of first half of post-IDCT table */
+        for (j = 256; j < 640; j++)
+        {
+            rlimitTable[j] = 255;
+        }
+
+        /* Second half of post-IDCT table */
+        memset((void *)(rlimitTable + 640), 0, 384);
+        for (j = 0; j < 128; j++)
+        {
+            rlimitTable[j + 1024] = j;
+        }
+    }
+
+    inline unsigned short int wordHiLo(uint8_t byte_high, uint8_t byte_low)
+    {
+        return (byte_high << 8) + byte_low;
+    }
 
     // river
-    // signed_wordvalue=lookKbits(k);
-    signedWordvalue = static_cast<unsigned short int>(codebuf >> (32 - k));
-    if (((1L << (k - 1)) & signedWordvalue) == 0) {
-      // neg_pow2 was previously defined as the below.  It seemed silly to keep
-      // a table of values around for something
-      // THat's relatively easy to compute, so it was replaced with the
-      // appropriate math
-      // signed_wordvalue = signed_wordvalue - (0xFFFF >> (16 - k));
-      std::array<signed short int, 17> negPow2 = {
-          0,    -1,   -3,    -7,    -15,   -31,   -63,    -127,
-          -255, -511, -1023, -2047, -4095, -8191, -16383, -32767};
+    void processHuffmanDataUnit(uint8_t DC_nr, uint8_t AC_nr,
+                                signed short int *previous_DC,
+                                unsigned short int position)
+    {
+        uint8_t nr = 0;
+        uint8_t k;
+        unsigned short int tmpHcode;
+        uint8_t sizeVal, count0;
+        unsigned short int *minCode;
+        uint8_t *huffValues;
+        uint8_t byteTemp;
 
-      signedWordvalue = signedWordvalue + negPow2[k];
-    }
-    skipKbits(k);
-    return signedWordvalue;
-  }
-  int initJpgDecoding() {
-    bytePos = 0;
-    loadQuantTable(qt[0]);
-    loadQuantTableCb(qt[1]);
-    //  Note: Added for Dual-JPEG
-    loadAdvanceQuantTable(qt[2]);
-    loadAdvanceQuantTableCb(qt[3]);
-    return 1;
-  }
+        minCode = htdc[DC_nr].minorCode;
+        //   maj_code=htdc[DC_nr].majorCode;
+        huffValues = htdc[DC_nr].v;
 
-  void setQuantTable(const uint8_t *basic_table, uint8_t scale_factor,
-                     std::array<uint8_t, 64> &newtable)
-  // Set quantization table and zigzag reorder it
-  {
-    uint8_t i;
-    long temp;
-    for (i = 0; i < 64; i++) {
-      temp = (static_cast<long>(basic_table[i] * 16) / scale_factor);
-      /* limit the values to the valid range */
-      if (temp <= 0L) {
-        temp = 1L;
-      }
-      if (temp > 255L) {
-        temp = 255L; /* limit to baseline range if requested */
-      }
-      newtable[zigzag[i]] = static_cast<uint8_t>(temp);
-    }
-  }
-
-  void updatereadbuf(uint32_t *codebuf, uint32_t *newbuf, int walks,
-                     int *newbits, std::vector<uint32_t> &buffer) {
-    unsigned long readbuf;
-
-    if ((*newbits - walks) <= 0) {
-      readbuf = buffer[bufferIndex];
-      bufferIndex++;
-      *codebuf = (*codebuf << walks) |
-                 ((*newbuf | (readbuf >> (*newbits))) >> (32 - walks));
-      *newbuf = readbuf << (walks - *newbits);
-      *newbits = 32 + *newbits - walks;
-    } else {
-      *codebuf = (*codebuf << walks) | (*newbuf >> (32 - walks));
-      *newbuf = *newbuf << walks;
-      *newbits -= walks;
-    }
-  }
-
-  uint32_t decode(std::vector<uint32_t> &bufferVector, unsigned long width,
-                  unsigned long height, YuvMode yuvmode_in, int ySelector,
-                  int uvSelector) {
-    ColorCache decodeColor;
-    if (width != userWidth || height != userHeight || yuvmode_in != yuvmode ||
-        ySelector != ySelector || uvSelector != uvSelector) {
-      yuvmode = yuvmode_in;
-      ySelector = ySelector;    // 0-7
-      uvSelector = uvSelector;  // 0-7
-      userHeight = height;
-      userWidth = width;
-      width = width;
-      height = height;
-
-      // TODO(ed) Magic number section.  Document appropriately
-      advanceSelector = 0;  // 0-7
-      mapping = 0;          // 0 or 1
-
-      if (yuvmode == YuvMode::YUV420) {
-        if ((width % 16) != 0u) {
-          width = width + 16 - (width % 16);
+        // DC
+        k = htdc[DC_nr].len[static_cast<unsigned short int>(codebuf >> 16)];
+        // river
+        //	 tmp_Hcode=lookKbits(k);
+        tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k));
+        skipKbits(k);
+        sizeVal = huffValues[wordHiLo(
+            k, static_cast<uint8_t>(tmpHcode - minCode[k]))];
+        if (sizeVal == 0)
+        {
+            dctCoeff[position + 0] = *previous_DC;
         }
-        if ((height % 16) != 0u) {
-          height = height + 16 - (height % 16);
+        else
+        {
+            dctCoeff[position + 0] = *previous_DC + getKbits(sizeVal);
+            *previous_DC = dctCoeff[position + 0];
         }
-      } else {
-        if ((width % 8) != 0u) {
-          width = width + 8 - (width % 8);
-        }
-        if ((height % 8) != 0u) {
-          height = height + 8 - (height % 8);
-        }
-      }
 
-      initJpgDecoding();
+        // Second, AC coefficient decoding
+        minCode = htac[AC_nr].minorCode;
+        //   maj_code=htac[AC_nr].majorCode;
+        huffValues = htac[AC_nr].v;
+
+        nr = 1; // AC coefficient
+        do
+        {
+            k = htac[AC_nr].len[static_cast<unsigned short int>(codebuf >> 16)];
+            tmpHcode = static_cast<unsigned short int>(codebuf >> (32 - k));
+            skipKbits(k);
+
+            byteTemp = huffValues[wordHiLo(
+                k, static_cast<uint8_t>(tmpHcode - minCode[k]))];
+            sizeVal = byteTemp & 0xF;
+            count0 = byteTemp >> 4;
+            if (sizeVal == 0)
+            {
+                if (count0 != 0xF)
+                {
+                    break;
+                }
+                nr += 16;
+            }
+            else
+            {
+                nr += count0; // skip count_0 zeroes
+                dctCoeff[position + dezigzag[nr++]] = getKbits(sizeVal);
+            }
+        } while (nr < 64);
     }
-    // TODO(ed) cleanup cruft
-    buffer = bufferVector.data();
 
-    codebuf = bufferVector[0];
-    newbuf = bufferVector[1];
-    bufferIndex = 2;
+    unsigned short int lookKbits(uint8_t k)
+    {
+        unsigned short int revcode;
 
-    txb = tyb = 0;
-    newbits = 32;
-    dcy = dcCb = dcCr = 0;
+        revcode = static_cast<unsigned short int>(codebuf >> (32 - k));
 
-    static const uint32_t vqHeaderMask = 0x01;
-    static const uint32_t vqNoUpdateHeader = 0x00;
-    static const uint32_t vqUpdateHeader = 0x01;
-    static const int vqNoUpdateLength = 0x03;
-    static const int vqUpdateLength = 0x1B;
-    static const uint32_t vqIndexMask = 0x03;
-    static const uint32_t vqColorMask = 0xFFFFFF;
+        return (revcode);
+    }
 
-    static const int blockAsT2100StartLength = 0x04;
-    static const int blockAsT2100SkipLength = 20;  // S:1 H:3 X:8 Y:8
+    void skipKbits(uint8_t k)
+    {
+        unsigned long readbuf;
 
-    do {
-      auto blockHeader = static_cast<JpgBlock>((codebuf >> 28) & 0xFF);
-      switch (blockHeader) {
-        case JpgBlock::JPEG_NO_SKIP_CODE:
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
-                        bufferVector);
-          decompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0);
-          break;
-        case JpgBlock::FRAME_END_CODE:
-          return 0;
-          break;
-        case JpgBlock::JPEG_SKIP_CODE:
+        if ((newbits - k) <= 0)
+        {
+            readbuf = buffer[bufferIndex];
+            bufferIndex++;
+            codebuf = (codebuf << k) |
+                      ((newbuf | (readbuf >> (newbits))) >> (32 - k));
+            newbuf = readbuf << (k - newbits);
+            newbits = 32 + newbits - k;
+        }
+        else
+        {
+            codebuf = (codebuf << k) | (newbuf >> (32 - k));
+            newbuf = newbuf << k;
+            newbits -= k;
+        }
+    }
 
-          txb = (codebuf & 0x0FF00000) >> 20;
-          tyb = (codebuf & 0x0FF000) >> 12;
+    signed short int getKbits(uint8_t k)
+    {
+        signed short int signedWordvalue;
 
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
-                        bufferVector);
-          decompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0);
-          break;
-        case JpgBlock::VQ_NO_SKIP_1_COLOR_CODE:
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
-                        bufferVector);
-          decodeColor.bitMapBits = 0;
+        // river
+        // signed_wordvalue=lookKbits(k);
+        signedWordvalue = static_cast<unsigned short int>(codebuf >> (32 - k));
+        if (((1L << (k - 1)) & signedWordvalue) == 0)
+        {
+            // neg_pow2 was previously defined as the below.  It seemed silly to
+            // keep a table of values around for something THat's relatively
+            // easy to compute, so it was replaced with the appropriate math
+            // signed_wordvalue = signed_wordvalue - (0xFFFF >> (16 - k));
+            std::array<signed short int, 17> negPow2 = {
+                0,    -1,   -3,    -7,    -15,   -31,   -63,    -127,
+                -255, -511, -1023, -2047, -4095, -8191, -16383, -32767};
 
-          for (int i = 0; i < 1; i++) {
-            decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
-            if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
-              updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
-                            bufferVector);
-            } else {
-              decodeColor.color[decodeColor.index[i]] =
-                  ((codebuf >> 5) & vqColorMask);
-              updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
-                            bufferVector);
+            signedWordvalue = signedWordvalue + negPow2[k];
+        }
+        skipKbits(k);
+        return signedWordvalue;
+    }
+    int initJpgDecoding()
+    {
+        bytePos = 0;
+        loadQuantTable(qt[0]);
+        loadQuantTableCb(qt[1]);
+        //  Note: Added for Dual-JPEG
+        loadAdvanceQuantTable(qt[2]);
+        loadAdvanceQuantTableCb(qt[3]);
+        return 1;
+    }
+
+    void setQuantTable(const uint8_t *basic_table, uint8_t scale_factor,
+                       std::array<uint8_t, 64> &newtable)
+    // Set quantization table and zigzag reorder it
+    {
+        uint8_t i;
+        long temp;
+        for (i = 0; i < 64; i++)
+        {
+            temp = (static_cast<long>(basic_table[i] * 16) / scale_factor);
+            /* limit the values to the valid range */
+            if (temp <= 0L)
+            {
+                temp = 1L;
             }
-          }
-          vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
-                       &decodeColor);
-          break;
-        case JpgBlock::VQ_SKIP_1_COLOR_CODE:
-          txb = (codebuf & 0x0FF00000) >> 20;
-          tyb = (codebuf & 0x0FF000) >> 12;
-
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
-                        bufferVector);
-          decodeColor.bitMapBits = 0;
-
-          for (int i = 0; i < 1; i++) {
-            decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
-            if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
-              updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
-                            bufferVector);
-            } else {
-              decodeColor.color[decodeColor.index[i]] =
-                  ((codebuf >> 5) & vqColorMask);
-              updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
-                            bufferVector);
+            if (temp > 255L)
+            {
+                temp = 255L; /* limit to baseline range if requested */
             }
-          }
-          vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
-                       &decodeColor);
-          break;
+            newtable[zigzag[i]] = static_cast<uint8_t>(temp);
+        }
+    }
 
-        case JpgBlock::VQ_NO_SKIP_2_COLOR_CODE:
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
-                        bufferVector);
-          decodeColor.bitMapBits = 1;
+    void updatereadbuf(uint32_t *codebuf, uint32_t *newbuf, int walks,
+                       int *newbits, std::vector<uint32_t> &buffer)
+    {
+        unsigned long readbuf;
 
-          for (int i = 0; i < 2; i++) {
-            decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
-            if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
-              updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
-                            bufferVector);
-            } else {
-              decodeColor.color[decodeColor.index[i]] =
-                  ((codebuf >> 5) & vqColorMask);
-              updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
-                            bufferVector);
+        if ((*newbits - walks) <= 0)
+        {
+            readbuf = buffer[bufferIndex];
+            bufferIndex++;
+            *codebuf = (*codebuf << walks) |
+                       ((*newbuf | (readbuf >> (*newbits))) >> (32 - walks));
+            *newbuf = readbuf << (walks - *newbits);
+            *newbits = 32 + *newbits - walks;
+        }
+        else
+        {
+            *codebuf = (*codebuf << walks) | (*newbuf >> (32 - walks));
+            *newbuf = *newbuf << walks;
+            *newbits -= walks;
+        }
+    }
+
+    uint32_t decode(std::vector<uint32_t> &bufferVector, unsigned long width,
+                    unsigned long height, YuvMode yuvmode_in, int ySelector,
+                    int uvSelector)
+    {
+        ColorCache decodeColor;
+        if (width != userWidth || height != userHeight ||
+            yuvmode_in != yuvmode || ySelector != ySelector ||
+            uvSelector != uvSelector)
+        {
+            yuvmode = yuvmode_in;
+            ySelector = ySelector;   // 0-7
+            uvSelector = uvSelector; // 0-7
+            userHeight = height;
+            userWidth = width;
+            width = width;
+            height = height;
+
+            // TODO(ed) Magic number section.  Document appropriately
+            advanceSelector = 0; // 0-7
+            mapping = 0;         // 0 or 1
+
+            if (yuvmode == YuvMode::YUV420)
+            {
+                if ((width % 16) != 0u)
+                {
+                    width = width + 16 - (width % 16);
+                }
+                if ((height % 16) != 0u)
+                {
+                    height = height + 16 - (height % 16);
+                }
             }
-          }
-          vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
-                       &decodeColor);
-          break;
-        case JpgBlock::VQ_SKIP_2_COLOR_CODE:
-          txb = (codebuf & 0x0FF00000) >> 20;
-          tyb = (codebuf & 0x0FF000) >> 12;
-
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
-                        bufferVector);
-          decodeColor.bitMapBits = 1;
-
-          for (int i = 0; i < 2; i++) {
-            decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
-            if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
-              updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
-                            bufferVector);
-            } else {
-              decodeColor.color[decodeColor.index[i]] =
-                  ((codebuf >> 5) & vqColorMask);
-              updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
-                            bufferVector);
+            else
+            {
+                if ((width % 8) != 0u)
+                {
+                    width = width + 8 - (width % 8);
+                }
+                if ((height % 8) != 0u)
+                {
+                    height = height + 8 - (height % 8);
+                }
             }
-          }
-          vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
-                       &decodeColor);
 
-          break;
-        case JpgBlock::VQ_NO_SKIP_4_COLOR_CODE:
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength, &newbits,
-                        bufferVector);
-          decodeColor.bitMapBits = 2;
+            initJpgDecoding();
+        }
+        // TODO(ed) cleanup cruft
+        buffer = bufferVector.data();
 
-          for (unsigned char &i : decodeColor.index) {
-            i = ((codebuf >> 29) & vqIndexMask);
-            if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
-              updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
-                            bufferVector);
-            } else {
-              decodeColor.color[i] = ((codebuf >> 5) & vqColorMask);
-              updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
-                            bufferVector);
+        codebuf = bufferVector[0];
+        newbuf = bufferVector[1];
+        bufferIndex = 2;
+
+        txb = tyb = 0;
+        newbits = 32;
+        dcy = dcCb = dcCr = 0;
+
+        static const uint32_t vqHeaderMask = 0x01;
+        static const uint32_t vqNoUpdateHeader = 0x00;
+        static const uint32_t vqUpdateHeader = 0x01;
+        static const int vqNoUpdateLength = 0x03;
+        static const int vqUpdateLength = 0x1B;
+        static const uint32_t vqIndexMask = 0x03;
+        static const uint32_t vqColorMask = 0xFFFFFF;
+
+        static const int blockAsT2100StartLength = 0x04;
+        static const int blockAsT2100SkipLength = 20; // S:1 H:3 X:8 Y:8
+
+        do
+        {
+            auto blockHeader = static_cast<JpgBlock>((codebuf >> 28) & 0xFF);
+            switch (blockHeader)
+            {
+                case JpgBlock::JPEG_NO_SKIP_CODE:
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength,
+                                  &newbits, bufferVector);
+                    decompress(txb, tyb,
+                               reinterpret_cast<char *>(outBuffer.data()), 0);
+                    break;
+                case JpgBlock::FRAME_END_CODE:
+                    return 0;
+                    break;
+                case JpgBlock::JPEG_SKIP_CODE:
+
+                    txb = (codebuf & 0x0FF00000) >> 20;
+                    tyb = (codebuf & 0x0FF000) >> 12;
+
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength,
+                                  &newbits, bufferVector);
+                    decompress(txb, tyb,
+                               reinterpret_cast<char *>(outBuffer.data()), 0);
+                    break;
+                case JpgBlock::VQ_NO_SKIP_1_COLOR_CODE:
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength,
+                                  &newbits, bufferVector);
+                    decodeColor.bitMapBits = 0;
+
+                    for (int i = 0; i < 1; i++)
+                    {
+                        decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
+                        if (((codebuf >> 31) & vqHeaderMask) ==
+                            vqNoUpdateHeader)
+                        {
+                            updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                        else
+                        {
+                            decodeColor.color[decodeColor.index[i]] =
+                                ((codebuf >> 5) & vqColorMask);
+                            updatereadbuf(&codebuf, &newbuf, vqUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                    }
+                    vqDecompress(txb, tyb,
+                                 reinterpret_cast<char *>(outBuffer.data()), 0,
+                                 &decodeColor);
+                    break;
+                case JpgBlock::VQ_SKIP_1_COLOR_CODE:
+                    txb = (codebuf & 0x0FF00000) >> 20;
+                    tyb = (codebuf & 0x0FF000) >> 12;
+
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength,
+                                  &newbits, bufferVector);
+                    decodeColor.bitMapBits = 0;
+
+                    for (int i = 0; i < 1; i++)
+                    {
+                        decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
+                        if (((codebuf >> 31) & vqHeaderMask) ==
+                            vqNoUpdateHeader)
+                        {
+                            updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                        else
+                        {
+                            decodeColor.color[decodeColor.index[i]] =
+                                ((codebuf >> 5) & vqColorMask);
+                            updatereadbuf(&codebuf, &newbuf, vqUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                    }
+                    vqDecompress(txb, tyb,
+                                 reinterpret_cast<char *>(outBuffer.data()), 0,
+                                 &decodeColor);
+                    break;
+
+                case JpgBlock::VQ_NO_SKIP_2_COLOR_CODE:
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength,
+                                  &newbits, bufferVector);
+                    decodeColor.bitMapBits = 1;
+
+                    for (int i = 0; i < 2; i++)
+                    {
+                        decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
+                        if (((codebuf >> 31) & vqHeaderMask) ==
+                            vqNoUpdateHeader)
+                        {
+                            updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                        else
+                        {
+                            decodeColor.color[decodeColor.index[i]] =
+                                ((codebuf >> 5) & vqColorMask);
+                            updatereadbuf(&codebuf, &newbuf, vqUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                    }
+                    vqDecompress(txb, tyb,
+                                 reinterpret_cast<char *>(outBuffer.data()), 0,
+                                 &decodeColor);
+                    break;
+                case JpgBlock::VQ_SKIP_2_COLOR_CODE:
+                    txb = (codebuf & 0x0FF00000) >> 20;
+                    tyb = (codebuf & 0x0FF000) >> 12;
+
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength,
+                                  &newbits, bufferVector);
+                    decodeColor.bitMapBits = 1;
+
+                    for (int i = 0; i < 2; i++)
+                    {
+                        decodeColor.index[i] = ((codebuf >> 29) & vqIndexMask);
+                        if (((codebuf >> 31) & vqHeaderMask) ==
+                            vqNoUpdateHeader)
+                        {
+                            updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                        else
+                        {
+                            decodeColor.color[decodeColor.index[i]] =
+                                ((codebuf >> 5) & vqColorMask);
+                            updatereadbuf(&codebuf, &newbuf, vqUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                    }
+                    vqDecompress(txb, tyb,
+                                 reinterpret_cast<char *>(outBuffer.data()), 0,
+                                 &decodeColor);
+
+                    break;
+                case JpgBlock::VQ_NO_SKIP_4_COLOR_CODE:
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100StartLength,
+                                  &newbits, bufferVector);
+                    decodeColor.bitMapBits = 2;
+
+                    for (unsigned char &i : decodeColor.index)
+                    {
+                        i = ((codebuf >> 29) & vqIndexMask);
+                        if (((codebuf >> 31) & vqHeaderMask) ==
+                            vqNoUpdateHeader)
+                        {
+                            updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                        else
+                        {
+                            decodeColor.color[i] =
+                                ((codebuf >> 5) & vqColorMask);
+                            updatereadbuf(&codebuf, &newbuf, vqUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                    }
+                    vqDecompress(txb, tyb,
+                                 reinterpret_cast<char *>(outBuffer.data()), 0,
+                                 &decodeColor);
+
+                    break;
+
+                case JpgBlock::VQ_SKIP_4_COLOR_CODE:
+                    txb = (codebuf & 0x0FF00000) >> 20;
+                    tyb = (codebuf & 0x0FF000) >> 12;
+
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength,
+                                  &newbits, bufferVector);
+                    decodeColor.bitMapBits = 2;
+
+                    for (unsigned char &i : decodeColor.index)
+                    {
+                        i = ((codebuf >> 29) & vqIndexMask);
+                        if (((codebuf >> 31) & vqHeaderMask) ==
+                            vqNoUpdateHeader)
+                        {
+                            updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                        else
+                        {
+                            decodeColor.color[i] =
+                                ((codebuf >> 5) & vqColorMask);
+                            updatereadbuf(&codebuf, &newbuf, vqUpdateLength,
+                                          &newbits, bufferVector);
+                        }
+                    }
+                    vqDecompress(txb, tyb,
+                                 reinterpret_cast<char *>(outBuffer.data()), 0,
+                                 &decodeColor);
+
+                    break;
+                case JpgBlock::JPEG_SKIP_PASS2_CODE:
+                    txb = (codebuf & 0x0FF00000) >> 20;
+                    tyb = (codebuf & 0x0FF000) >> 12;
+
+                    updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength,
+                                  &newbits, bufferVector);
+                    decompress2Pass(txb, tyb,
+                                    reinterpret_cast<char *>(outBuffer.data()),
+                                    2);
+
+                    break;
+                default:
+                    // TODO(ed) propogate errors upstream
+                    return -1;
+                    break;
             }
-          }
-          vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
-                       &decodeColor);
+            moveBlockIndex();
 
-          break;
+        } while (bufferIndex <= bufferVector.size());
 
-        case JpgBlock::VQ_SKIP_4_COLOR_CODE:
-          txb = (codebuf & 0x0FF00000) >> 20;
-          tyb = (codebuf & 0x0FF000) >> 12;
-
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
-                        bufferVector);
-          decodeColor.bitMapBits = 2;
-
-          for (unsigned char &i : decodeColor.index) {
-            i = ((codebuf >> 29) & vqIndexMask);
-            if (((codebuf >> 31) & vqHeaderMask) == vqNoUpdateHeader) {
-              updatereadbuf(&codebuf, &newbuf, vqNoUpdateLength, &newbits,
-                            bufferVector);
-            } else {
-              decodeColor.color[i] = ((codebuf >> 5) & vqColorMask);
-              updatereadbuf(&codebuf, &newbuf, vqUpdateLength, &newbits,
-                            bufferVector);
-            }
-          }
-          vqDecompress(txb, tyb, reinterpret_cast<char *>(outBuffer.data()), 0,
-                       &decodeColor);
-
-          break;
-        case JpgBlock::JPEG_SKIP_PASS2_CODE:
-          txb = (codebuf & 0x0FF00000) >> 20;
-          tyb = (codebuf & 0x0FF000) >> 12;
-
-          updatereadbuf(&codebuf, &newbuf, blockAsT2100SkipLength, &newbits,
-                        bufferVector);
-          decompress2Pass(txb, tyb, reinterpret_cast<char *>(outBuffer.data()),
-                          2);
-
-          break;
-        default:
-          // TODO(ed) propogate errors upstream
-          return -1;
-          break;
-      }
-      moveBlockIndex();
-
-    } while (bufferIndex <= bufferVector.size());
-
-    return -1;
-  }
+        return -1;
+    }
 
 #ifdef cimg_version
-  void dump_to_bitmap_file() {
-    cimg_library::CImg<unsigned char> image(width, height, 1, 3);
-    for (int y = 0; y < width; y++) {
-      for (int x = 0; x < height; x++) {
-        auto pixel = outBuffer[x + (y * width)];
-        image(x, y, 0) = pixel.r;
-        image(x, y, 1) = pixel.g;
-        image(x, y, 2) = pixel.b;
-      }
+    void dump_to_bitmap_file()
+    {
+        cimg_library::CImg<unsigned char> image(width, height, 1, 3);
+        for (int y = 0; y < width; y++)
+        {
+            for (int x = 0; x < height; x++)
+            {
+                auto pixel = outBuffer[x + (y * width)];
+                image(x, y, 0) = pixel.r;
+                image(x, y, 1) = pixel.g;
+                image(x, y, 2) = pixel.b;
+            }
+        }
+        image.save("/tmp/file2.bmp");
     }
-    image.save("/tmp/file2.bmp");
-  }
 #endif
 
- private:
-  YuvMode yuvmode{};
-  // width and height are the modes your display used
-  unsigned long width{};
-  unsigned long height{};
-  unsigned long userWidth{};
-  unsigned long userHeight{};
-  unsigned char ySelector{};
-  int scalefactor;
-  int scalefactoruv;
-  int advancescalefactor;
-  int advancescalefactoruv;
-  int mapping{};
-  unsigned char uvSelector{};
-  unsigned char advanceSelector{};
-  int bytePos{};  // current byte position
+  private:
+    YuvMode yuvmode{};
+    // width and height are the modes your display used
+    unsigned long width{};
+    unsigned long height{};
+    unsigned long userWidth{};
+    unsigned long userHeight{};
+    unsigned char ySelector{};
+    int scalefactor;
+    int scalefactoruv;
+    int advancescalefactor;
+    int advancescalefactoruv;
+    int mapping{};
+    unsigned char uvSelector{};
+    unsigned char advanceSelector{};
+    int bytePos{}; // current byte position
 
-  // quantization tables, no more than 4 quantization tables
-  std::array<std::array<long, 64>, 4> qt{};
+    // quantization tables, no more than 4 quantization tables
+    std::array<std::array<long, 64>, 4> qt{};
 
-  // DC huffman tables , no more than 4 (0..3)
-  std::array<HuffmanTable, 4> htdc{};
-  // AC huffman tables (0..3)
-  std::array<HuffmanTable, 4> htac{};
-  std::array<int, 256> mCrToR{};
-  std::array<int, 256> mCbToB{};
-  std::array<int, 256> mCrToG{};
-  std::array<int, 256> mCbToG{};
-  std::array<int, 256> mY{};
-  unsigned long bufferIndex{};
-  uint32_t codebuf{}, newbuf{}, readbuf{};
-  const unsigned char *stdLuminanceQt{};
-  const uint8_t *stdChrominanceQt{};
+    // DC huffman tables , no more than 4 (0..3)
+    std::array<HuffmanTable, 4> htdc{};
+    // AC huffman tables (0..3)
+    std::array<HuffmanTable, 4> htac{};
+    std::array<int, 256> mCrToR{};
+    std::array<int, 256> mCbToB{};
+    std::array<int, 256> mCrToG{};
+    std::array<int, 256> mCbToG{};
+    std::array<int, 256> mY{};
+    unsigned long bufferIndex{};
+    uint32_t codebuf{}, newbuf{}, readbuf{};
+    const unsigned char *stdLuminanceQt{};
+    const uint8_t *stdChrominanceQt{};
 
-  signed short int dcy{}, dcCb{}, dcCr{};  // Coeficientii DC pentru Y,Cb,Cr
-  signed short int dctCoeff[384]{};
-  // std::vector<signed short int> dctCoeff;  // Current DCT_coefficients
-  // quantization table number for Y, Cb, Cr
-  uint8_t yqNr = 0, cbQNr = 1, crQNr = 1;
-  // DC Huffman table number for Y,Cb, Cr
-  uint8_t ydcNr = 0, cbDcNr = 1, crDcNr = 1;
-  // AC Huffman table number for Y,Cb, Cr
-  uint8_t yacNr = 0, cbAcNr = 1, crAcNr = 1;
-  int txb = 0;
-  int tyb = 0;
-  int newbits{};
-  uint8_t *rlimitTable{};
-  std::vector<RGB> yuvBuffer;
-  // TODO(ed) this shouldn't exist.  It is cruft that needs cleaning up
-  uint32_t *buffer{};
+    signed short int dcy{}, dcCb{}, dcCr{}; // Coeficientii DC pentru Y,Cb,Cr
+    signed short int dctCoeff[384]{};
+    // std::vector<signed short int> dctCoeff;  // Current DCT_coefficients
+    // quantization table number for Y, Cb, Cr
+    uint8_t yqNr = 0, cbQNr = 1, crQNr = 1;
+    // DC Huffman table number for Y,Cb, Cr
+    uint8_t ydcNr = 0, cbDcNr = 1, crDcNr = 1;
+    // AC Huffman table number for Y,Cb, Cr
+    uint8_t yacNr = 0, cbAcNr = 1, crAcNr = 1;
+    int txb = 0;
+    int tyb = 0;
+    int newbits{};
+    uint8_t *rlimitTable{};
+    std::vector<RGB> yuvBuffer;
+    // TODO(ed) this shouldn't exist.  It is cruft that needs cleaning up
+    uint32_t *buffer{};
 
- public:
-  std::vector<RGB> outBuffer;
+  public:
+    std::vector<RGB> outBuffer;
 };
-}  // namespace ast_video
\ No newline at end of file
+} // namespace ast_video
\ No newline at end of file
diff --git a/include/ast_video_puller.hpp b/include/ast_video_puller.hpp
index c2ccea2..520fc68 100644
--- a/include/ast_video_puller.hpp
+++ b/include/ast_video_puller.hpp
@@ -1,186 +1,212 @@
 #pragma once
 
 #include <ast_video_types.hpp>
+#include <boost/asio.hpp>
 #include <cassert>
 #include <iostream>
 #include <mutex>
 #include <vector>
-#include <boost/asio.hpp>
 
-namespace ast_video {
+namespace ast_video
+{
 
 //
 // Cursor struct is used in User Mode
 //
-struct AstCurAttributionTag {
-  unsigned int posX;
-  unsigned int posY;
-  unsigned int curWidth;
-  unsigned int curHeight;
-  unsigned int curType;  // 0:mono 1:color 2:disappear cursor
-  unsigned int curChangeFlag;
+struct AstCurAttributionTag
+{
+    unsigned int posX;
+    unsigned int posY;
+    unsigned int curWidth;
+    unsigned int curHeight;
+    unsigned int curType; // 0:mono 1:color 2:disappear cursor
+    unsigned int curChangeFlag;
 };
 
 //
 // For storing Cursor Information
 //
-struct AstCursorTag {
-  AstCurAttributionTag attr;
-  // unsigned char     icon[MAX_CUR_OFFSETX*MAX_CUR_OFFSETY*2];
-  unsigned char *icon;  //[64*64*2];
+struct AstCursorTag
+{
+    AstCurAttributionTag attr;
+    // unsigned char     icon[MAX_CUR_OFFSETX*MAX_CUR_OFFSETY*2];
+    unsigned char *icon; //[64*64*2];
 };
 
 //
 // For select image format, i.e. 422 JPG420, 444 JPG444, lumin/chrom table, 0
 // ~ 11, low to high
 //
-struct FeaturesTag {
-  short jpgFmt;  // 422:JPG420, 444:JPG444
-  short luminTbl;
-  short chromTbl;
-  short toleranceNoise;
-  int w;
-  int h;
-  unsigned char *buf;
+struct FeaturesTag
+{
+    short jpgFmt; // 422:JPG420, 444:JPG444
+    short luminTbl;
+    short chromTbl;
+    short toleranceNoise;
+    int w;
+    int h;
+    unsigned char *buf;
 };
 
 //
 // For configure video engine control registers
 //
-struct ImageInfo {
-  short doImageRefresh;  // Action 0:motion 1:fullframe 2:quick cursor
-  char qcValid;          // quick cursor enable/disable
-  unsigned int len;
-  int crypttype;
-  char cryptkey[16];
-  union {
-    FeaturesTag features;
-    AstCursorTag cursorInfo;
-  } parameter;
+struct ImageInfo
+{
+    short doImageRefresh; // Action 0:motion 1:fullframe 2:quick cursor
+    char qcValid;         // quick cursor enable/disable
+    unsigned int len;
+    int crypttype;
+    char cryptkey[16];
+    union
+    {
+        FeaturesTag features;
+        AstCursorTag cursorInfo;
+    } parameter;
 };
 
-class SimpleVideoPuller {
- public:
-  SimpleVideoPuller() : imageInfo(){};
+class SimpleVideoPuller
+{
+  public:
+    SimpleVideoPuller() : imageInfo(){};
 
-  void initialize() {
-    std::cout << "Opening /dev/video\n";
-    videoFd = open("/dev/video", O_RDWR);
-    if (videoFd == 0) {
-      std::cout << "Failed to open /dev/video\n";
-      throw std::runtime_error("Failed to open /dev/video");
-    }
-    std::cout << "Opened successfully\n";
-  }
-
-  RawVideoBuffer readVideo() {
-    assert(videoFd != 0);
-    RawVideoBuffer raw;
-
-    imageInfo.doImageRefresh = 1;  // full frame refresh
-    imageInfo.qcValid = 0;         // quick cursor disabled
-    imageInfo.parameter.features.buf =
-        reinterpret_cast<unsigned char *>(raw.buffer.data());
-    imageInfo.crypttype = -1;
-    std::cout << "Writing\n";
-
-    int status;
-    /*
-    status = write(videoFd, reinterpret_cast<char*>(&imageInfo),
-                        sizeof(imageInfo));
-    if (status != sizeof(imageInfo)) {
-      std::cout << "Write failed.  Return: " << status << "\n";
-      perror("perror output:");
+    void initialize()
+    {
+        std::cout << "Opening /dev/video\n";
+        videoFd = open("/dev/video", O_RDWR);
+        if (videoFd == 0)
+        {
+            std::cout << "Failed to open /dev/video\n";
+            throw std::runtime_error("Failed to open /dev/video");
+        }
+        std::cout << "Opened successfully\n";
     }
 
-    std::cout << "Write done\n";
-    */
-    std::cout << "Reading\n";
-    status =
-        read(videoFd, reinterpret_cast<char *>(&imageInfo), sizeof(imageInfo));
-    std::cout << "Done reading\n";
+    RawVideoBuffer readVideo()
+    {
+        assert(videoFd != 0);
+        RawVideoBuffer raw;
 
-    if (status != 0) {
-      std::cerr << "Read failed with status " << status << "\n";
+        imageInfo.doImageRefresh = 1; // full frame refresh
+        imageInfo.qcValid = 0;        // quick cursor disabled
+        imageInfo.parameter.features.buf =
+            reinterpret_cast<unsigned char *>(raw.buffer.data());
+        imageInfo.crypttype = -1;
+        std::cout << "Writing\n";
+
+        int status;
+        /*
+        status = write(videoFd, reinterpret_cast<char*>(&imageInfo),
+                            sizeof(imageInfo));
+        if (status != sizeof(imageInfo)) {
+          std::cout << "Write failed.  Return: " << status << "\n";
+          perror("perror output:");
+        }
+
+        std::cout << "Write done\n";
+        */
+        std::cout << "Reading\n";
+        status = read(videoFd, reinterpret_cast<char *>(&imageInfo),
+                      sizeof(imageInfo));
+        std::cout << "Done reading\n";
+
+        if (status != 0)
+        {
+            std::cerr << "Read failed with status " << status << "\n";
+        }
+
+        raw.buffer.resize(imageInfo.len);
+
+        raw.height = imageInfo.parameter.features.h;
+        raw.width = imageInfo.parameter.features.w;
+        if (imageInfo.parameter.features.jpgFmt == 422)
+        {
+            raw.mode = YuvMode::YUV420;
+        }
+        else
+        {
+            raw.mode = YuvMode::YUV444;
+        }
+        return raw;
     }
 
-    raw.buffer.resize(imageInfo.len);
-
-    raw.height = imageInfo.parameter.features.h;
-    raw.width = imageInfo.parameter.features.w;
-    if (imageInfo.parameter.features.jpgFmt == 422) {
-      raw.mode = YuvMode::YUV420;
-    } else {
-      raw.mode = YuvMode::YUV444;
-    }
-    return raw;
-  }
-
- private:
-  int videoFd{};
-  ImageInfo imageInfo;
+  private:
+    int videoFd{};
+    ImageInfo imageInfo;
 };
 
 #if defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
-class AsyncVideoPuller {
- public:
-  using video_callback = std::function<void(RawVideoBuffer &)>;
+class AsyncVideoPuller
+{
+  public:
+    using video_callback = std::function<void(RawVideoBuffer &)>;
 
-  explicit AsyncVideoPuller(boost::asio::io_service &ioService)
-      : imageInfo(), devVideo(ioService, open("/dev/video", O_RDWR)) {
-    videobuf = std::make_shared<RawVideoBuffer>();
+    explicit AsyncVideoPuller(boost::asio::io_service &ioService) :
+        imageInfo(), devVideo(ioService, open("/dev/video", O_RDWR))
+    {
+        videobuf = std::make_shared<RawVideoBuffer>();
 
-    imageInfo.doImageRefresh = 1;  // full frame refresh
-    imageInfo.qcValid = 0;         // quick cursor disabled
-    imageInfo.parameter.features.buf =
-        reinterpret_cast<unsigned char *>(videobuf->buffer.data());
-    imageInfo.crypttype = -1;
-  };
+        imageInfo.doImageRefresh = 1; // full frame refresh
+        imageInfo.qcValid = 0;        // quick cursor disabled
+        imageInfo.parameter.features.buf =
+            reinterpret_cast<unsigned char *>(videobuf->buffer.data());
+        imageInfo.crypttype = -1;
+    };
 
-  void registerCallback(video_callback &callback) {
-    std::lock_guard<std::mutex> lock(callbackMutex);
-    callbacks.push_back(callback);
-    startRead();
-  }
-
-  void startRead() {
-    auto mutableBuffer = boost::asio::buffer(&imageInfo, sizeof(imageInfo));
-    boost::asio::async_read(devVideo, mutableBuffer,
-                            [this](const boost::system::error_code &ec,
-                                   std::size_t bytes_transferred) {
-                              if (ec) {
-                                std::cerr << "Read failed with status " << ec
-                                          << "\n";
-                              } else {
-                                this->readDone();
-                              }
-                            });
-  }
-
-  void readDone() {
-    std::cout << "Done reading\n";
-    videobuf->buffer.resize(imageInfo.len);
-
-    videobuf->height = imageInfo.parameter.features.h;
-    videobuf->width = imageInfo.parameter.features.w;
-    if (imageInfo.parameter.features.jpgFmt == 422) {
-      videobuf->mode = YuvMode::YUV420;
-    } else {
-      videobuf->mode = YuvMode::YUV444;
+    void registerCallback(video_callback &callback)
+    {
+        std::lock_guard<std::mutex> lock(callbackMutex);
+        callbacks.push_back(callback);
+        startRead();
     }
-    std::lock_guard<std::mutex> lock(callbackMutex);
-    for (auto &callback : callbacks) {
-      // TODO(ed) call callbacks async and double buffer frames
-      callback(*videobuf);
-    }
-  }
 
- private:
-  std::shared_ptr<RawVideoBuffer> videobuf;
-  boost::asio::posix::stream_descriptor devVideo;
-  ImageInfo imageInfo;
-  std::mutex callbackMutex;
-  std::vector<video_callback> callbacks;
+    void startRead()
+    {
+        auto mutableBuffer = boost::asio::buffer(&imageInfo, sizeof(imageInfo));
+        boost::asio::async_read(devVideo, mutableBuffer,
+                                [this](const boost::system::error_code &ec,
+                                       std::size_t bytes_transferred) {
+                                    if (ec)
+                                    {
+                                        std::cerr << "Read failed with status "
+                                                  << ec << "\n";
+                                    }
+                                    else
+                                    {
+                                        this->readDone();
+                                    }
+                                });
+    }
+
+    void readDone()
+    {
+        std::cout << "Done reading\n";
+        videobuf->buffer.resize(imageInfo.len);
+
+        videobuf->height = imageInfo.parameter.features.h;
+        videobuf->width = imageInfo.parameter.features.w;
+        if (imageInfo.parameter.features.jpgFmt == 422)
+        {
+            videobuf->mode = YuvMode::YUV420;
+        }
+        else
+        {
+            videobuf->mode = YuvMode::YUV444;
+        }
+        std::lock_guard<std::mutex> lock(callbackMutex);
+        for (auto &callback : callbacks)
+        {
+            // TODO(ed) call callbacks async and double buffer frames
+            callback(*videobuf);
+        }
+    }
+
+  private:
+    std::shared_ptr<RawVideoBuffer> videobuf;
+    boost::asio::posix::stream_descriptor devVideo;
+    ImageInfo imageInfo;
+    std::mutex callbackMutex;
+    std::vector<video_callback> callbacks;
 };
-#endif  // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
-}  // namespace ast_video
+#endif // defined(BOOST_ASIO_HAS_POSIX_STREAM_DESCRIPTOR)
+} // namespace ast_video
diff --git a/include/ast_video_types.hpp b/include/ast_video_types.hpp
index f980146..aeef1d8 100644
--- a/include/ast_video_types.hpp
+++ b/include/ast_video_types.hpp
@@ -2,18 +2,24 @@
 
 #include <cstdint>
 #include <vector>
-namespace ast_video {
-enum class YuvMode { YUV444 = 0, YUV420 = 1 };
-
-class RawVideoBuffer {
- public:
-  RawVideoBuffer() : buffer(1024 * 1024 * 10, 0){};
-  unsigned long height{};
-  unsigned long width{};
-  int ySelector{};
-  int uvSelector{};
-  YuvMode mode;
-  // TODO(ed) determine a more appropriate buffer size
-  std::vector<uint32_t> buffer;
+namespace ast_video
+{
+enum class YuvMode
+{
+    YUV444 = 0,
+    YUV420 = 1
 };
-}  // namespace ast_video
\ No newline at end of file
+
+class RawVideoBuffer
+{
+  public:
+    RawVideoBuffer() : buffer(1024 * 1024 * 10, 0){};
+    unsigned long height{};
+    unsigned long width{};
+    int ySelector{};
+    int uvSelector{};
+    YuvMode mode;
+    // TODO(ed) determine a more appropriate buffer size
+    std::vector<uint32_t> buffer;
+};
+} // namespace ast_video
\ No newline at end of file
diff --git a/include/dbus_monitor.hpp b/include/dbus_monitor.hpp
index e8b1a32..5dcd5ca 100644
--- a/include/dbus_monitor.hpp
+++ b/include/dbus_monitor.hpp
@@ -1,26 +1,33 @@
 #pragma once
-#include <dbus_singleton.hpp>
-#include <sdbusplus/bus/match.hpp>
 #include <crow/app.h>
 #include <crow/websocket.h>
+
 #include <boost/container/flat_map.hpp>
 #include <boost/container/flat_set.hpp>
+#include <dbus_singleton.hpp>
+#include <sdbusplus/bus/match.hpp>
 
-namespace nlohmann {
+namespace nlohmann
+{
 template <typename... Args>
-struct adl_serializer<sdbusplus::message::variant<Args...>> {
-  static void to_json(json& j, const sdbusplus::message::variant<Args...>& v) {
-    mapbox::util::apply_visitor([&](auto&& val) { j = val; }, v);
-  }
+struct adl_serializer<sdbusplus::message::variant<Args...>>
+{
+    static void to_json(json& j, const sdbusplus::message::variant<Args...>& v)
+    {
+        mapbox::util::apply_visitor([&](auto&& val) { j = val; }, v);
+    }
 };
-}  // namespace nlohmann
+} // namespace nlohmann
 
-namespace crow {
-namespace dbus_monitor {
+namespace crow
+{
+namespace dbus_monitor
+{
 
-struct DbusWebsocketSession {
-  std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
-  boost::container::flat_set<std::string> interfaces;
+struct DbusWebsocketSession
+{
+    std::vector<std::unique_ptr<sdbusplus::bus::match::match>> matches;
+    boost::container::flat_set<std::string> interfaces;
 };
 
 static boost::container::flat_map<crow::websocket::Connection*,
@@ -28,165 +35,198 @@
     sessions;
 
 inline int onPropertyUpdate(sd_bus_message* m, void* userdata,
-                            sd_bus_error* ret_error) {
-  if (ret_error == nullptr || sd_bus_error_is_set(ret_error)) {
-    BMCWEB_LOG_ERROR << "Got sdbus error on match";
-    return 0;
-  }
-  crow::websocket::Connection* connection =
-      static_cast<crow::websocket::Connection*>(userdata);
-  auto thisSession = sessions.find(connection);
-  if (thisSession == sessions.end()) {
-    BMCWEB_LOG_ERROR << "Couldn't find dbus connection " << connection;
-    return 0;
-  }
-  sdbusplus::message::message message(m);
-  using VariantType =
-      sdbusplus::message::variant<std::string, bool, int64_t, uint64_t, double>;
-  nlohmann::json j{{"event", message.get_member()},
-                   {"path", message.get_path()}};
-  if (strcmp(message.get_member(), "PropertiesChanged") == 0) {
-    std::string interface_name;
-    boost::container::flat_map<std::string, VariantType> values;
-    message.read(interface_name, values);
-    j["properties"] = values;
-    j["interface"] = std::move(interface_name);
-
-  } else if (strcmp(message.get_member(), "InterfacesAdded") == 0) {
-    std::string object_name;
-    boost::container::flat_map<
-        std::string, boost::container::flat_map<std::string, VariantType>>
-        values;
-    message.read(object_name, values);
-    for (const std::pair<std::string,
-                         boost::container::flat_map<std::string, VariantType>>&
-             paths : values) {
-      auto it = thisSession->second.interfaces.find(paths.first);
-      if (it != thisSession->second.interfaces.end()) {
-        j["interfaces"][paths.first] = paths.second;
-      }
+                            sd_bus_error* ret_error)
+{
+    if (ret_error == nullptr || sd_bus_error_is_set(ret_error))
+    {
+        BMCWEB_LOG_ERROR << "Got sdbus error on match";
+        return 0;
     }
-  } else {
-    BMCWEB_LOG_CRITICAL << "message " << message.get_member()
-                        << " was unexpected";
-    return 0;
-  }
+    crow::websocket::Connection* connection =
+        static_cast<crow::websocket::Connection*>(userdata);
+    auto thisSession = sessions.find(connection);
+    if (thisSession == sessions.end())
+    {
+        BMCWEB_LOG_ERROR << "Couldn't find dbus connection " << connection;
+        return 0;
+    }
+    sdbusplus::message::message message(m);
+    using VariantType = sdbusplus::message::variant<std::string, bool, int64_t,
+                                                    uint64_t, double>;
+    nlohmann::json j{{"event", message.get_member()},
+                     {"path", message.get_path()}};
+    if (strcmp(message.get_member(), "PropertiesChanged") == 0)
+    {
+        std::string interface_name;
+        boost::container::flat_map<std::string, VariantType> values;
+        message.read(interface_name, values);
+        j["properties"] = values;
+        j["interface"] = std::move(interface_name);
+    }
+    else if (strcmp(message.get_member(), "InterfacesAdded") == 0)
+    {
+        std::string object_name;
+        boost::container::flat_map<
+            std::string, boost::container::flat_map<std::string, VariantType>>
+            values;
+        message.read(object_name, values);
+        for (const std::pair<
+                 std::string,
+                 boost::container::flat_map<std::string, VariantType>>& paths :
+             values)
+        {
+            auto it = thisSession->second.interfaces.find(paths.first);
+            if (it != thisSession->second.interfaces.end())
+            {
+                j["interfaces"][paths.first] = paths.second;
+            }
+        }
+    }
+    else
+    {
+        BMCWEB_LOG_CRITICAL << "message " << message.get_member()
+                            << " was unexpected";
+        return 0;
+    }
 
-  connection->sendText(j.dump());
-  return 0;
+    connection->sendText(j.dump());
+    return 0;
 };
 
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...>& app) {
-  BMCWEB_ROUTE(app, "/subscribe")
-      .websocket()
-      .onopen([&](crow::websocket::Connection& conn) {
-        BMCWEB_LOG_DEBUG << "Connection " << &conn << " opened";
-        sessions[&conn] = DbusWebsocketSession();
-      })
-      .onclose([&](crow::websocket::Connection& conn,
-                   const std::string& reason) { sessions.erase(&conn); })
-      .onmessage([&](crow::websocket::Connection& conn, const std::string& data,
-                     bool is_binary) {
-        DbusWebsocketSession& thisSession = sessions[&conn];
-        BMCWEB_LOG_DEBUG << "Connection " << &conn << " recevied " << data;
-        nlohmann::json j = nlohmann::json::parse(data, nullptr, false);
-        if (j.is_discarded()) {
-          BMCWEB_LOG_ERROR << "Unable to parse json data for monitor";
-          conn.close("Unable to parse json request");
-          return;
-        }
-        nlohmann::json::iterator interfaces = j.find("interfaces");
-        if (interfaces != j.end()) {
-          thisSession.interfaces.reserve(interfaces->size());
-          for (auto& interface : *interfaces) {
-            const std::string* str = interface.get_ptr<const std::string*>();
-            if (str != nullptr) {
-              thisSession.interfaces.insert(*str);
-            }
-          }
-        }
-
-        nlohmann::json::iterator paths = j.find("paths");
-        if (paths != j.end()) {
-          int interfaceCount = thisSession.interfaces.size();
-          if (interfaceCount == 0) {
-            interfaceCount = 1;
-          }
-          // Reserve our matches upfront.  For each path there is 1 for
-          // interfacesAdded, and InterfaceCount number for PropertiesChanged
-          thisSession.matches.reserve(thisSession.matches.size() +
-                                      paths->size() * (1 + interfaceCount));
-        }
-        std::string object_manager_match_string;
-        std::string properties_match_string;
-        std::string object_manager_interfaces_match_string;
-        // These regexes derived on the rules here:
-        // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
-        std::regex validPath("^/([A-Za-z0-9_]+/?)*$");
-        std::regex validInterface(
-            "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$");
-
-        for (const auto& thisPath : *paths) {
-          const std::string* thisPathString =
-              thisPath.get_ptr<const std::string*>();
-          if (thisPathString == nullptr) {
-            BMCWEB_LOG_ERROR << "subscribe path isn't a string?";
-            conn.close();
-            return;
-          }
-          if (!std::regex_match(*thisPathString, validPath)) {
-            BMCWEB_LOG_ERROR << "Invalid path name " << *thisPathString;
-            conn.close();
-            return;
-          }
-          properties_match_string =
-              ("type='signal',"
-               "interface='org.freedesktop.DBus.Properties',"
-               "path_namespace='" +
-               *thisPathString +
-               "',"
-               "member='PropertiesChanged'");
-          // If interfaces weren't specified, add a single match for all
-          // interfaces
-          if (thisSession.interfaces.size() == 0) {
-            BMCWEB_LOG_DEBUG << "Creating match " << properties_match_string;
-
-            thisSession.matches.emplace_back(
-                std::make_unique<sdbusplus::bus::match::match>(
-                    *crow::connections::systemBus, properties_match_string,
-                    onPropertyUpdate, &conn));
-          } else {
-            // If interfaces were specified, add a match for each interface
-            for (const std::string& interface : thisSession.interfaces) {
-              if (!std::regex_match(interface, validInterface)) {
-                BMCWEB_LOG_ERROR << "Invalid interface name " << interface;
-                conn.close();
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app)
+{
+    BMCWEB_ROUTE(app, "/subscribe")
+        .websocket()
+        .onopen([&](crow::websocket::Connection& conn) {
+            BMCWEB_LOG_DEBUG << "Connection " << &conn << " opened";
+            sessions[&conn] = DbusWebsocketSession();
+        })
+        .onclose([&](crow::websocket::Connection& conn,
+                     const std::string& reason) { sessions.erase(&conn); })
+        .onmessage([&](crow::websocket::Connection& conn,
+                       const std::string& data, bool is_binary) {
+            DbusWebsocketSession& thisSession = sessions[&conn];
+            BMCWEB_LOG_DEBUG << "Connection " << &conn << " recevied " << data;
+            nlohmann::json j = nlohmann::json::parse(data, nullptr, false);
+            if (j.is_discarded())
+            {
+                BMCWEB_LOG_ERROR << "Unable to parse json data for monitor";
+                conn.close("Unable to parse json request");
                 return;
-              }
-              std::string ifaceMatchString =
-                  properties_match_string + ",arg0='" + interface + "'";
-              BMCWEB_LOG_DEBUG << "Creating match " << ifaceMatchString;
-              thisSession.matches.emplace_back(
-                  std::make_unique<sdbusplus::bus::match::match>(
-                      *crow::connections::systemBus, ifaceMatchString,
-                      onPropertyUpdate, &conn));
             }
-          }
-          object_manager_match_string =
-              ("type='signal',"
-               "interface='org.freedesktop.DBus.ObjectManager',"
-               "path_namespace='" +
-               *thisPathString +
-               "',"
-               "member='InterfacesAdded'");
-          BMCWEB_LOG_DEBUG << "Creating match " << object_manager_match_string;
-          thisSession.matches.emplace_back(
-              std::make_unique<sdbusplus::bus::match::match>(
-                  *crow::connections::systemBus, object_manager_match_string,
-                  onPropertyUpdate, &conn));
-        }
-      });
+            nlohmann::json::iterator interfaces = j.find("interfaces");
+            if (interfaces != j.end())
+            {
+                thisSession.interfaces.reserve(interfaces->size());
+                for (auto& interface : *interfaces)
+                {
+                    const std::string* str =
+                        interface.get_ptr<const std::string*>();
+                    if (str != nullptr)
+                    {
+                        thisSession.interfaces.insert(*str);
+                    }
+                }
+            }
+
+            nlohmann::json::iterator paths = j.find("paths");
+            if (paths != j.end())
+            {
+                int interfaceCount = thisSession.interfaces.size();
+                if (interfaceCount == 0)
+                {
+                    interfaceCount = 1;
+                }
+                // Reserve our matches upfront.  For each path there is 1 for
+                // interfacesAdded, and InterfaceCount number for
+                // PropertiesChanged
+                thisSession.matches.reserve(thisSession.matches.size() +
+                                            paths->size() *
+                                                (1 + interfaceCount));
+            }
+            std::string object_manager_match_string;
+            std::string properties_match_string;
+            std::string object_manager_interfaces_match_string;
+            // These regexes derived on the rules here:
+            // https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-names
+            std::regex validPath("^/([A-Za-z0-9_]+/?)*$");
+            std::regex validInterface(
+                "^[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)+$");
+
+            for (const auto& thisPath : *paths)
+            {
+                const std::string* thisPathString =
+                    thisPath.get_ptr<const std::string*>();
+                if (thisPathString == nullptr)
+                {
+                    BMCWEB_LOG_ERROR << "subscribe path isn't a string?";
+                    conn.close();
+                    return;
+                }
+                if (!std::regex_match(*thisPathString, validPath))
+                {
+                    BMCWEB_LOG_ERROR << "Invalid path name " << *thisPathString;
+                    conn.close();
+                    return;
+                }
+                properties_match_string =
+                    ("type='signal',"
+                     "interface='org.freedesktop.DBus.Properties',"
+                     "path_namespace='" +
+                     *thisPathString +
+                     "',"
+                     "member='PropertiesChanged'");
+                // If interfaces weren't specified, add a single match for all
+                // interfaces
+                if (thisSession.interfaces.size() == 0)
+                {
+                    BMCWEB_LOG_DEBUG << "Creating match "
+                                     << properties_match_string;
+
+                    thisSession.matches.emplace_back(
+                        std::make_unique<sdbusplus::bus::match::match>(
+                            *crow::connections::systemBus,
+                            properties_match_string, onPropertyUpdate, &conn));
+                }
+                else
+                {
+                    // If interfaces were specified, add a match for each
+                    // interface
+                    for (const std::string& interface : thisSession.interfaces)
+                    {
+                        if (!std::regex_match(interface, validInterface))
+                        {
+                            BMCWEB_LOG_ERROR << "Invalid interface name "
+                                             << interface;
+                            conn.close();
+                            return;
+                        }
+                        std::string ifaceMatchString = properties_match_string +
+                                                       ",arg0='" + interface +
+                                                       "'";
+                        BMCWEB_LOG_DEBUG << "Creating match "
+                                         << ifaceMatchString;
+                        thisSession.matches.emplace_back(
+                            std::make_unique<sdbusplus::bus::match::match>(
+                                *crow::connections::systemBus, ifaceMatchString,
+                                onPropertyUpdate, &conn));
+                    }
+                }
+                object_manager_match_string =
+                    ("type='signal',"
+                     "interface='org.freedesktop.DBus.ObjectManager',"
+                     "path_namespace='" +
+                     *thisPathString +
+                     "',"
+                     "member='InterfacesAdded'");
+                BMCWEB_LOG_DEBUG << "Creating match "
+                                 << object_manager_match_string;
+                thisSession.matches.emplace_back(
+                    std::make_unique<sdbusplus::bus::match::match>(
+                        *crow::connections::systemBus,
+                        object_manager_match_string, onPropertyUpdate, &conn));
+            }
+        });
 }
-}  // namespace dbus_monitor
-}  // namespace crow
+} // namespace dbus_monitor
+} // namespace crow
diff --git a/include/dbus_singleton.hpp b/include/dbus_singleton.hpp
index a4a16bb..2438152 100644
--- a/include/dbus_singleton.hpp
+++ b/include/dbus_singleton.hpp
@@ -1,21 +1,28 @@
 #pragma once
-#include <sdbusplus/asio/connection.hpp>
 #include <iostream>
+#include <sdbusplus/asio/connection.hpp>
 
-namespace mapbox {
+namespace mapbox
+{
 template <typename T, typename... Types>
-const T* getPtr(const mapbox::util::variant<Types...>& v) {
-  if (v.template is<std::remove_const_t<T>>()) {
-    return &v.template get_unchecked<std::remove_const_t<T>>();
-  } else {
-    return nullptr;
-  }
+const T* getPtr(const mapbox::util::variant<Types...>& v)
+{
+    if (v.template is<std::remove_const_t<T>>())
+    {
+        return &v.template get_unchecked<std::remove_const_t<T>>();
+    }
+    else
+    {
+        return nullptr;
+    }
 }
-}  // namespace mapbox
+} // namespace mapbox
 
-namespace crow {
-namespace connections {
+namespace crow
+{
+namespace connections
+{
 static std::shared_ptr<sdbusplus::asio::connection> systemBus;
 
-}  // namespace connections
-}  // namespace crow
+} // namespace connections
+} // namespace crow
diff --git a/include/gzip_helper.hpp b/include/gzip_helper.hpp
index e14fc1b..be13809 100644
--- a/include/gzip_helper.hpp
+++ b/include/gzip_helper.hpp
@@ -1,56 +1,65 @@
 #pragma once
 
 #include <zlib.h>
+
 #include <cstring>
 #include <string>
 
 inline bool gzipInflate(const std::string& compressedBytes,
-                        std::string& uncompressedBytes) {
-  if (compressedBytes.empty()) {
-    uncompressedBytes = compressedBytes;
-    return true;
-  }
-
-  uncompressedBytes.clear();
-
-  unsigned half_length = compressedBytes.size() / 2;
-
-  z_stream strm{};
-
-  // The following line is nolint because we're declaring away constness.
-  // It's not clear why the input buffers on zlib aren't const, so this is a
-  // bit of a cheat for the moment
-  strm.next_in = (Bytef*)compressedBytes.data();  // NOLINT
-  strm.avail_in = compressedBytes.size();
-  strm.total_out = 0;
-  strm.zalloc = Z_NULL;
-  strm.zfree = Z_NULL;
-
-  bool done = false;
-
-  if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK) {
-    return false;
-  }
-
-  while (!done) {
-    // If our output buffer is too small
-    if (strm.total_out >= uncompressedBytes.size()) {
-      uncompressedBytes.resize(uncompressedBytes.size() + half_length);
+                        std::string& uncompressedBytes)
+{
+    if (compressedBytes.empty())
+    {
+        uncompressedBytes = compressedBytes;
+        return true;
     }
 
-    strm.next_out =
-        (Bytef*)(uncompressedBytes.data() + strm.total_out);  // NOLINT
-    strm.avail_out =
-        ((uLong)uncompressedBytes.size() - strm.total_out);  // NOLINT
+    uncompressedBytes.clear();
 
-    // Inflate another chunk.
-    int err = inflate(&strm, Z_SYNC_FLUSH);
-    if (err == Z_STREAM_END) {
-      done = true;
-    } else if (err != Z_OK) {
-      break;
+    unsigned half_length = compressedBytes.size() / 2;
+
+    z_stream strm{};
+
+    // The following line is nolint because we're declaring away constness.
+    // It's not clear why the input buffers on zlib aren't const, so this is a
+    // bit of a cheat for the moment
+    strm.next_in = (Bytef*)compressedBytes.data(); // NOLINT
+    strm.avail_in = compressedBytes.size();
+    strm.total_out = 0;
+    strm.zalloc = Z_NULL;
+    strm.zfree = Z_NULL;
+
+    bool done = false;
+
+    if (inflateInit2(&strm, (16 + MAX_WBITS)) != Z_OK)
+    {
+        return false;
     }
-  }
 
-  return inflateEnd(&strm) == Z_OK;
+    while (!done)
+    {
+        // If our output buffer is too small
+        if (strm.total_out >= uncompressedBytes.size())
+        {
+            uncompressedBytes.resize(uncompressedBytes.size() + half_length);
+        }
+
+        strm.next_out =
+            (Bytef*)(uncompressedBytes.data() + strm.total_out); // NOLINT
+        strm.avail_out =
+            ((uLong)uncompressedBytes.size() - strm.total_out); // NOLINT
+
+        // Inflate another chunk.
+        int err = inflate(&strm, Z_SYNC_FLUSH);
+        if (err == Z_STREAM_END)
+        {
+            done = true;
+        }
+        else if (err != Z_OK)
+        {
+            break;
+        }
+    }
+
+    return inflateEnd(&strm) == Z_OK;
 }
\ No newline at end of file
diff --git a/include/http_utility.hpp b/include/http_utility.hpp
index f2d3172..e13dfc0 100644
--- a/include/http_utility.hpp
+++ b/include/http_utility.hpp
@@ -1,21 +1,27 @@
 #pragma once
 #include <boost/algorithm/string.hpp>
 
-namespace http_helpers {
-inline bool requestPrefersHtml(const crow::Request& req) {
-  boost::string_view header = req.getHeaderValue("accept");
-  std::vector<std::string> encodings;
-  // chrome currently sends 6 accepts headers, firefox sends 4.
-  encodings.reserve(6);
-  boost::split(encodings, header, boost::is_any_of(", "),
-               boost::token_compress_on);
-  for (const std::string& encoding : encodings) {
-    if (encoding == "text/html") {
-      return true;
-    } else if (encoding == "application/json") {
-      return false;
+namespace http_helpers
+{
+inline bool requestPrefersHtml(const crow::Request& req)
+{
+    boost::string_view header = req.getHeaderValue("accept");
+    std::vector<std::string> encodings;
+    // chrome currently sends 6 accepts headers, firefox sends 4.
+    encodings.reserve(6);
+    boost::split(encodings, header, boost::is_any_of(", "),
+                 boost::token_compress_on);
+    for (const std::string& encoding : encodings)
+    {
+        if (encoding == "text/html")
+        {
+            return true;
+        }
+        else if (encoding == "application/json")
+        {
+            return false;
+        }
     }
-  }
-  return false;
+    return false;
 }
-}  // namespace http_helpers
\ No newline at end of file
+} // namespace http_helpers
\ No newline at end of file
diff --git a/include/image_upload.hpp b/include/image_upload.hpp
index df5c1ae..2b84db8 100644
--- a/include/image_upload.hpp
+++ b/include/image_upload.hpp
@@ -1,103 +1,113 @@
 #pragma once
 
-#include <dbus_singleton.hpp>
-#include <cstdio>
-#include <fstream>
-#include <memory>
 #include <crow/app.h>
+
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_generators.hpp>
 #include <boost/uuid/uuid_io.hpp>
+#include <cstdio>
+#include <dbus_singleton.hpp>
+#include <fstream>
+#include <memory>
 
-namespace crow {
-namespace image_upload {
+namespace crow
+{
+namespace image_upload
+{
 
 std::unique_ptr<sdbusplus::bus::match::match> fwUpdateMatcher;
 
 inline void uploadImageHandler(const crow::Request& req, crow::Response& res,
-                               const std::string& filename) {
-  // Only allow one FW update at a time
-  if (fwUpdateMatcher != nullptr) {
-    res.addHeader("Retry-After", "30");
-    res.result(boost::beast::http::status::service_unavailable);
-    res.end();
-    return;
-  }
-  // Make this const static so it survives outside this method
-  static boost::asio::deadline_timer timeout(*req.ioService,
-                                             boost::posix_time::seconds(5));
-
-  timeout.expires_from_now(boost::posix_time::seconds(5));
-
-  timeout.async_wait([&res](const boost::system::error_code& ec) {
-    fwUpdateMatcher = nullptr;
-    if (ec == asio::error::operation_aborted) {
-      // expected, we were canceled before the timer completed.
-      return;
-    }
-    BMCWEB_LOG_ERROR << "Timed out waiting for log event";
-
-    if (ec) {
-      BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
-      return;
-    }
-
-    res.result(boost::beast::http::status::internal_server_error);
-    res.end();
-  });
-
-  std::function<void(sdbusplus::message::message&)> callback =
-      [&res](sdbusplus::message::message& m) {
-        BMCWEB_LOG_DEBUG << "Match fired";
-        boost::system::error_code ec;
-        timeout.cancel(ec);
-        if (ec) {
-          BMCWEB_LOG_ERROR << "error canceling timer " << ec;
-        }
-        std::string versionInfo;
-        m.read(versionInfo);  // Read in the object path that was just created
-
-        std::size_t index = versionInfo.rfind('/');
-        if (index != std::string::npos) {
-          versionInfo.erase(0, index);
-        }
-        res.jsonValue = {{"data", std::move(versionInfo)},
-                         {"message", "200 OK"},
-                         {"status", "ok"}};
-        BMCWEB_LOG_DEBUG << "ending response";
+                               const std::string& filename)
+{
+    // Only allow one FW update at a time
+    if (fwUpdateMatcher != nullptr)
+    {
+        res.addHeader("Retry-After", "30");
+        res.result(boost::beast::http::status::service_unavailable);
         res.end();
+        return;
+    }
+    // Make this const static so it survives outside this method
+    static boost::asio::deadline_timer timeout(*req.ioService,
+                                               boost::posix_time::seconds(5));
+
+    timeout.expires_from_now(boost::posix_time::seconds(5));
+
+    timeout.async_wait([&res](const boost::system::error_code& ec) {
         fwUpdateMatcher = nullptr;
-      };
-  fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
-      *crow::connections::systemBus,
-      "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
-      "member='InterfacesAdded',path='/xyz/openbmc_project/logging'",
-      callback);
+        if (ec == asio::error::operation_aborted)
+        {
+            // expected, we were canceled before the timer completed.
+            return;
+        }
+        BMCWEB_LOG_ERROR << "Timed out waiting for log event";
 
-  std::string filepath(
-      "/tmp/images/" +
-      boost::uuids::to_string(boost::uuids::random_generator()()));
-  BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
-  std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
-                                  std::ofstream::trunc);
-  out << req.body;
-  out.close();
+        if (ec)
+        {
+            BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
+            return;
+        }
+
+        res.result(boost::beast::http::status::internal_server_error);
+        res.end();
+    });
+
+    std::function<void(sdbusplus::message::message&)> callback =
+        [&res](sdbusplus::message::message& m) {
+            BMCWEB_LOG_DEBUG << "Match fired";
+            boost::system::error_code ec;
+            timeout.cancel(ec);
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << "error canceling timer " << ec;
+            }
+            std::string versionInfo;
+            m.read(
+                versionInfo); // Read in the object path that was just created
+
+            std::size_t index = versionInfo.rfind('/');
+            if (index != std::string::npos)
+            {
+                versionInfo.erase(0, index);
+            }
+            res.jsonValue = {{"data", std::move(versionInfo)},
+                             {"message", "200 OK"},
+                             {"status", "ok"}};
+            BMCWEB_LOG_DEBUG << "ending response";
+            res.end();
+            fwUpdateMatcher = nullptr;
+        };
+    fwUpdateMatcher = std::make_unique<sdbusplus::bus::match::match>(
+        *crow::connections::systemBus,
+        "interface='org.freedesktop.DBus.ObjectManager',type='signal',"
+        "member='InterfacesAdded',path='/xyz/openbmc_project/logging'",
+        callback);
+
+    std::string filepath(
+        "/tmp/images/" +
+        boost::uuids::to_string(boost::uuids::random_generator()()));
+    BMCWEB_LOG_DEBUG << "Writing file to " << filepath;
+    std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary |
+                                    std::ofstream::trunc);
+    out << req.body;
+    out.close();
 }
 
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...>& app) {
-  BMCWEB_ROUTE(app, "/upload/image/<str>")
-      .methods("POST"_method,
-               "PUT"_method)([](const crow::Request& req, crow::Response& res,
-                                const std::string& filename) {
-        uploadImageHandler(req, res, filename);
-      });
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app)
+{
+    BMCWEB_ROUTE(app, "/upload/image/<str>")
+        .methods("POST"_method,
+                 "PUT"_method)([](const crow::Request& req, crow::Response& res,
+                                  const std::string& filename) {
+            uploadImageHandler(req, res, filename);
+        });
 
-  BMCWEB_ROUTE(app, "/upload/image")
-      .methods("POST"_method,
-               "PUT"_method)([](const crow::Request& req, crow::Response& res) {
-        uploadImageHandler(req, res, "");
-      });
+    BMCWEB_ROUTE(app, "/upload/image")
+        .methods("POST"_method, "PUT"_method)(
+            [](const crow::Request& req, crow::Response& res) {
+                uploadImageHandler(req, res, "");
+            });
 }
-}  // namespace image_upload
-}  // namespace crow
+} // namespace image_upload
+} // namespace crow
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp
index 3e6443d..4f6c233 100644
--- a/include/openbmc_dbus_rest.hpp
+++ b/include/openbmc_dbus_rest.hpp
@@ -1,64 +1,78 @@
 #include <crow/app.h>
-
 #include <tinyxml2.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/container/flat_set.hpp>
 #include <dbus_singleton.hpp>
 #include <experimental/filesystem>
 #include <fstream>
-#include <boost/algorithm/string.hpp>
-#include <boost/container/flat_set.hpp>
 
-namespace crow {
-namespace openbmc_mapper {
+namespace crow
+{
+namespace openbmc_mapper
+{
 
 void introspectObjects(crow::Response &res, std::string process_name,
                        std::string path,
-                       std::shared_ptr<nlohmann::json> transaction) {
-  crow::connections::systemBus->async_method_call(
-      [
-        &res, transaction, processName{std::move(process_name)},
-        objectPath{std::move(path)}
-      ](const boost::system::error_code ec, const std::string &introspect_xml) {
-        if (ec) {
-          BMCWEB_LOG_ERROR << "Introspect call failed with error: "
-                           << ec.message() << " on process: " << processName
-                           << " path: " << objectPath << "\n";
-
-        } else {
-          transaction->push_back({{"path", objectPath}});
-
-          tinyxml2::XMLDocument doc;
-
-          doc.Parse(introspect_xml.c_str());
-          tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
-          if (pRoot == nullptr) {
-            BMCWEB_LOG_ERROR << "XML document failed to parse " << processName
-                             << " " << objectPath << "\n";
-
-          } else {
-            tinyxml2::XMLElement *node = pRoot->FirstChildElement("node");
-            while (node != nullptr) {
-              std::string childPath = node->Attribute("name");
-              std::string newpath;
-              if (objectPath != "/") {
-                newpath += objectPath;
-              }
-              newpath += "/" + childPath;
-              // introspect the subobjects as well
-              introspectObjects(res, processName, newpath, transaction);
-
-              node = node->NextSiblingElement("node");
+                       std::shared_ptr<nlohmann::json> transaction)
+{
+    crow::connections::systemBus->async_method_call(
+        [&res, transaction, processName{std::move(process_name)},
+         objectPath{std::move(path)}](const boost::system::error_code ec,
+                                      const std::string &introspect_xml) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR
+                    << "Introspect call failed with error: " << ec.message()
+                    << " on process: " << processName << " path: " << objectPath
+                    << "\n";
             }
-          }
-        }
-        // if we're the last outstanding caller, finish the request
-        if (transaction.use_count() == 1) {
-          res.jsonValue = {{"status", "ok"},
-                           {"bus_name", processName},
-                           {"objects", std::move(*transaction)}};
-          res.end();
-        }
-      },
-      process_name, path, "org.freedesktop.DBus.Introspectable", "Introspect");
+            else
+            {
+                transaction->push_back({{"path", objectPath}});
+
+                tinyxml2::XMLDocument doc;
+
+                doc.Parse(introspect_xml.c_str());
+                tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
+                if (pRoot == nullptr)
+                {
+                    BMCWEB_LOG_ERROR << "XML document failed to parse "
+                                     << processName << " " << objectPath
+                                     << "\n";
+                }
+                else
+                {
+                    tinyxml2::XMLElement *node =
+                        pRoot->FirstChildElement("node");
+                    while (node != nullptr)
+                    {
+                        std::string childPath = node->Attribute("name");
+                        std::string newpath;
+                        if (objectPath != "/")
+                        {
+                            newpath += objectPath;
+                        }
+                        newpath += "/" + childPath;
+                        // introspect the subobjects as well
+                        introspectObjects(res, processName, newpath,
+                                          transaction);
+
+                        node = node->NextSiblingElement("node");
+                    }
+                }
+            }
+            // if we're the last outstanding caller, finish the request
+            if (transaction.use_count() == 1)
+            {
+                res.jsonValue = {{"status", "ok"},
+                                 {"bus_name", processName},
+                                 {"objects", std::move(*transaction)}};
+                res.end();
+            }
+        },
+        process_name, path, "org.freedesktop.DBus.Introspectable",
+        "Introspect");
 }
 
 // A smattering of common types to unpack.  TODO(ed) this should really iterate
@@ -74,46 +88,60 @@
         std::string,
         boost::container::flat_map<std::string, DbusRestVariantType>>>>;
 
-void getManagedObjectsForEnumerate(
-    const std::string &object_name, const std::string &connection_name,
-    crow::Response &res, std::shared_ptr<nlohmann::json> transaction) {
-  crow::connections::systemBus->async_method_call(
-      [&res, transaction](const boost::system::error_code ec,
-                          const ManagedObjectType &objects) {
-        if (ec) {
-          BMCWEB_LOG_ERROR << ec;
-        } else {
-          nlohmann::json &dataJson = *transaction;
-
-          for (auto &objectPath : objects) {
-            BMCWEB_LOG_DEBUG
-                << "Reading object "
-                << static_cast<const std::string &>(objectPath.first);
-            nlohmann::json &objectJson =
-                dataJson[static_cast<const std::string &>(objectPath.first)];
-            if (objectJson.is_null()) {
-              objectJson = nlohmann::json::object();
+void getManagedObjectsForEnumerate(const std::string &object_name,
+                                   const std::string &connection_name,
+                                   crow::Response &res,
+                                   std::shared_ptr<nlohmann::json> transaction)
+{
+    crow::connections::systemBus->async_method_call(
+        [&res, transaction](const boost::system::error_code ec,
+                            const ManagedObjectType &objects) {
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR << ec;
             }
-            for (const auto &interface : objectPath.second) {
-              for (const auto &property : interface.second) {
-                nlohmann::json &propertyJson = objectJson[property.first];
-                mapbox::util::apply_visitor(
-                    [&propertyJson](auto &&val) { propertyJson = val; },
-                    property.second);
-              }
-            }
-          }
-        }
+            else
+            {
+                nlohmann::json &dataJson = *transaction;
 
-        if (transaction.use_count() == 1) {
-          res.jsonValue = {{"message", "200 OK"},
-                           {"status", "ok"},
-                           {"data", std::move(*transaction)}};
-          res.end();
-        }
-      },
-      connection_name, object_name, "org.freedesktop.DBus.ObjectManager",
-      "GetManagedObjects");
+                for (auto &objectPath : objects)
+                {
+                    BMCWEB_LOG_DEBUG
+                        << "Reading object "
+                        << static_cast<const std::string &>(objectPath.first);
+                    nlohmann::json &objectJson =
+                        dataJson[static_cast<const std::string &>(
+                            objectPath.first)];
+                    if (objectJson.is_null())
+                    {
+                        objectJson = nlohmann::json::object();
+                    }
+                    for (const auto &interface : objectPath.second)
+                    {
+                        for (const auto &property : interface.second)
+                        {
+                            nlohmann::json &propertyJson =
+                                objectJson[property.first];
+                            mapbox::util::apply_visitor(
+                                [&propertyJson](auto &&val) {
+                                    propertyJson = val;
+                                },
+                                property.second);
+                        }
+                    }
+                }
+            }
+
+            if (transaction.use_count() == 1)
+            {
+                res.jsonValue = {{"message", "200 OK"},
+                                 {"status", "ok"},
+                                 {"data", std::move(*transaction)}};
+                res.end();
+            }
+        },
+        connection_name, object_name, "org.freedesktop.DBus.ObjectManager",
+        "GetManagedObjects");
 }
 
 using GetSubTreeType = std::vector<
@@ -121,1025 +149,1320 @@
               std::vector<std::pair<std::string, std::vector<std::string>>>>>;
 
 // Structure for storing data on an in progress action
-struct InProgressActionData {
-  InProgressActionData(crow::Response &res) : res(res){};
-  ~InProgressActionData() {
-    if (res.result() == boost::beast::http::status::internal_server_error) {
-      // Reset the json object to clear out any data that made it in before the
-      // error happened
-      // todo(ed) handle error condition with proper code
-      res.jsonValue = nlohmann::json::object();
+struct InProgressActionData
+{
+    InProgressActionData(crow::Response &res) : res(res){};
+    ~InProgressActionData()
+    {
+        if (res.result() == boost::beast::http::status::internal_server_error)
+        {
+            // Reset the json object to clear out any data that made it in
+            // before the error happened todo(ed) handle error condition with
+            // proper code
+            res.jsonValue = nlohmann::json::object();
+        }
+        res.end();
     }
-    res.end();
-  }
 
-  void setErrorStatus() {
-    res.result(boost::beast::http::status::internal_server_error);
-  }
-  crow::Response &res;
-  std::string path;
-  std::string methodName;
-  nlohmann::json arguments;
+    void setErrorStatus()
+    {
+        res.result(boost::beast::http::status::internal_server_error);
+    }
+    crow::Response &res;
+    std::string path;
+    std::string methodName;
+    nlohmann::json arguments;
 };
 
-std::vector<std::string> dbusArgSplit(const std::string &string) {
-  std::vector<std::string> ret;
-  if (string.empty()) {
-    return ret;
-  }
-  ret.push_back("");
-  int containerDepth = 0;
-
-  for (std::string::const_iterator character = string.begin();
-       character != string.end(); character++) {
-    ret.back() += *character;
-    switch (*character) {
-      case ('a'):
-        break;
-      case ('('):
-      case ('{'):
-        containerDepth++;
-        break;
-      case ('}'):
-      case (')'):
-        containerDepth--;
-        if (containerDepth == 0) {
-          if (character + 1 != string.end()) {
-            ret.push_back("");
-          }
-        }
-        break;
-      default:
-        if (containerDepth == 0) {
-          if (character + 1 != string.end()) {
-            ret.push_back("");
-          }
-        }
-        break;
+std::vector<std::string> dbusArgSplit(const std::string &string)
+{
+    std::vector<std::string> ret;
+    if (string.empty())
+    {
+        return ret;
     }
-  }
+    ret.push_back("");
+    int containerDepth = 0;
+
+    for (std::string::const_iterator character = string.begin();
+         character != string.end(); character++)
+    {
+        ret.back() += *character;
+        switch (*character)
+        {
+            case ('a'):
+                break;
+            case ('('):
+            case ('{'):
+                containerDepth++;
+                break;
+            case ('}'):
+            case (')'):
+                containerDepth--;
+                if (containerDepth == 0)
+                {
+                    if (character + 1 != string.end())
+                    {
+                        ret.push_back("");
+                    }
+                }
+                break;
+            default:
+                if (containerDepth == 0)
+                {
+                    if (character + 1 != string.end())
+                    {
+                        ret.push_back("");
+                    }
+                }
+                break;
+        }
+    }
 }
 
 int convertJsonToDbus(sd_bus_message *m, const std::string &arg_type,
-                      const nlohmann::json &input_json) {
-  int r = 0;
-  BMCWEB_LOG_DEBUG << "Converting " << input_json.dump()
-                   << " to type: " << arg_type;
-  const std::vector<std::string> argTypes = dbusArgSplit(arg_type);
+                      const nlohmann::json &input_json)
+{
+    int r = 0;
+    BMCWEB_LOG_DEBUG << "Converting " << input_json.dump()
+                     << " to type: " << arg_type;
+    const std::vector<std::string> argTypes = dbusArgSplit(arg_type);
 
-  // Assume a single object for now.
-  const nlohmann::json *j = &input_json;
-  nlohmann::json::const_iterator jIt = input_json.begin();
+    // Assume a single object for now.
+    const nlohmann::json *j = &input_json;
+    nlohmann::json::const_iterator jIt = input_json.begin();
 
-  for (const std::string &arg_code : argTypes) {
-    // If we are decoding multiple objects, grab the pointer to the iterator,
-    // and increment it for the next loop
-    if (argTypes.size() > 1) {
-      if (jIt == input_json.end()) {
-        return -2;
-      }
-      j = &*jIt;
-      jIt++;
-    }
-    const int64_t *int_value = j->get_ptr<const int64_t *>();
-    const uint64_t *uint_value = j->get_ptr<const uint64_t *>();
-    const std::string *string_value = j->get_ptr<const std::string *>();
-    const double *double_value = j->get_ptr<const double *>();
-    const bool *b = j->get_ptr<const bool *>();
-    int64_t v = 0;
-    double d = 0.0;
+    for (const std::string &arg_code : argTypes)
+    {
+        // If we are decoding multiple objects, grab the pointer to the
+        // iterator, and increment it for the next loop
+        if (argTypes.size() > 1)
+        {
+            if (jIt == input_json.end())
+            {
+                return -2;
+            }
+            j = &*jIt;
+            jIt++;
+        }
+        const int64_t *int_value = j->get_ptr<const int64_t *>();
+        const uint64_t *uint_value = j->get_ptr<const uint64_t *>();
+        const std::string *string_value = j->get_ptr<const std::string *>();
+        const double *double_value = j->get_ptr<const double *>();
+        const bool *b = j->get_ptr<const bool *>();
+        int64_t v = 0;
+        double d = 0.0;
 
-    // Do some basic type conversions that make sense.  uint can be converted to
-    // int.  int and uint can be converted to double
-    if (uint_value != nullptr && int_value == nullptr) {
-      v = static_cast<int64_t>(*uint_value);
-      int_value = &v;
-    }
-    if (uint_value != nullptr && double_value == nullptr) {
-      d = static_cast<double>(*uint_value);
-      double_value = &d;
-    }
-    if (int_value != nullptr && double_value == nullptr) {
-      d = static_cast<double>(*int_value);
-      double_value = &d;
-    }
-
-    if (arg_code == "s") {
-      if (string_value == nullptr) {
-        return -1;
-      }
-      r = sd_bus_message_append_basic(m, arg_code[0],
-                                      (void *)string_value->c_str());
-      if (r < 0) {
-        return r;
-      }
-    } else if (arg_code == "i") {
-      if (int_value == nullptr) {
-        return -1;
-      }
-      int32_t i = static_cast<int32_t>(*int_value);
-      r = sd_bus_message_append_basic(m, arg_code[0], &i);
-      if (r < 0) {
-        return r;
-      }
-    } else if (arg_code == "b") {
-      // lots of ways bool could be represented here.  Try them all
-      int bool_int = false;
-      if (int_value != nullptr) {
-        bool_int = *int_value > 0 ? 1 : 0;
-      } else if (b != nullptr) {
-        bool_int = b ? 1 : 0;
-      } else if (string_value != nullptr) {
-        bool_int = boost::istarts_with(*string_value, "t") ? 1 : 0;
-      } else {
-        return -1;
-      }
-      r = sd_bus_message_append_basic(m, arg_code[0], &bool_int);
-      if (r < 0) {
-        return r;
-      }
-    } else if (arg_code == "n") {
-      if (int_value == nullptr) {
-        return -1;
-      }
-      int16_t n = static_cast<int16_t>(*int_value);
-      r = sd_bus_message_append_basic(m, arg_code[0], &n);
-      if (r < 0) {
-        return r;
-      }
-    } else if (arg_code == "x") {
-      if (int_value == nullptr) {
-        return -1;
-      }
-      r = sd_bus_message_append_basic(m, arg_code[0], int_value);
-      if (r < 0) {
-        return r;
-      }
-    } else if (arg_code == "y") {
-      if (uint_value == nullptr) {
-        return -1;
-      }
-      uint8_t y = static_cast<uint8_t>(*uint_value);
-      r = sd_bus_message_append_basic(m, arg_code[0], &y);
-    } else if (arg_code == "q") {
-      if (uint_value == nullptr) {
-        return -1;
-      }
-      uint16_t q = static_cast<uint16_t>(*uint_value);
-      r = sd_bus_message_append_basic(m, arg_code[0], &q);
-    } else if (arg_code == "u") {
-      if (uint_value == nullptr) {
-        return -1;
-      }
-      uint32_t u = static_cast<uint32_t>(*uint_value);
-      r = sd_bus_message_append_basic(m, arg_code[0], &u);
-    } else if (arg_code == "t") {
-      if (uint_value == nullptr) {
-        return -1;
-      }
-      r = sd_bus_message_append_basic(m, arg_code[0], uint_value);
-    } else if (arg_code == "d") {
-      sd_bus_message_append_basic(m, arg_code[0], double_value);
-    } else if (boost::starts_with(arg_code, "a")) {
-      std::string contained_type = arg_code.substr(1);
-      r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY,
-                                        contained_type.c_str());
-      if (r < 0) {
-        return r;
-      }
-
-      for (nlohmann::json::const_iterator it = j->begin(); it != j->end();
-           ++it) {
-        r = convertJsonToDbus(m, contained_type, *it);
-        if (r < 0) {
-          return r;
+        // Do some basic type conversions that make sense.  uint can be
+        // converted to int.  int and uint can be converted to double
+        if (uint_value != nullptr && int_value == nullptr)
+        {
+            v = static_cast<int64_t>(*uint_value);
+            int_value = &v;
+        }
+        if (uint_value != nullptr && double_value == nullptr)
+        {
+            d = static_cast<double>(*uint_value);
+            double_value = &d;
+        }
+        if (int_value != nullptr && double_value == nullptr)
+        {
+            d = static_cast<double>(*int_value);
+            double_value = &d;
         }
 
-        it++;
-      }
-      sd_bus_message_close_container(m);
-    } else if (boost::starts_with(arg_code, "v")) {
-      std::string contained_type = arg_code.substr(1);
-      BMCWEB_LOG_DEBUG << "variant type: " << arg_code
-                       << " appending variant of type: " << contained_type;
-      r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT,
-                                        contained_type.c_str());
-      if (r < 0) {
-        return r;
-      }
-
-      r = convertJsonToDbus(m, contained_type, input_json);
-      if (r < 0) {
-        return r;
-      }
-
-      r = sd_bus_message_close_container(m);
-      if (r < 0) {
-        return r;
-      }
-    } else if (boost::starts_with(arg_code, "(") &&
-               boost::ends_with(arg_code, ")")) {
-      std::string contained_type = arg_code.substr(1, arg_code.size() - 1);
-      r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT,
-                                        contained_type.c_str());
-      nlohmann::json::const_iterator it = j->begin();
-      for (const std::string &arg_code : dbusArgSplit(arg_type)) {
-        if (it == j->end()) {
-          return -1;
+        if (arg_code == "s")
+        {
+            if (string_value == nullptr)
+            {
+                return -1;
+            }
+            r = sd_bus_message_append_basic(m, arg_code[0],
+                                            (void *)string_value->c_str());
+            if (r < 0)
+            {
+                return r;
+            }
         }
-        r = convertJsonToDbus(m, arg_code, *it);
-        if (r < 0) {
-          return r;
+        else if (arg_code == "i")
+        {
+            if (int_value == nullptr)
+            {
+                return -1;
+            }
+            int32_t i = static_cast<int32_t>(*int_value);
+            r = sd_bus_message_append_basic(m, arg_code[0], &i);
+            if (r < 0)
+            {
+                return r;
+            }
         }
-        it++;
-      }
-      r = sd_bus_message_close_container(m);
-    } else if (boost::starts_with(arg_code, "{") &&
-               boost::ends_with(arg_code, "}")) {
-      std::string contained_type = arg_code.substr(1, arg_code.size() - 1);
-      r = sd_bus_message_open_container(m, SD_BUS_TYPE_DICT_ENTRY,
-                                        contained_type.c_str());
-      std::vector<std::string> codes = dbusArgSplit(contained_type);
-      if (codes.size() != 2) {
-        return -1;
-      }
-      const std::string &key_type = codes[0];
-      const std::string &value_type = codes[1];
-      for (auto it : j->items()) {
-        r = convertJsonToDbus(m, key_type, it.key());
-        if (r < 0) {
-          return r;
+        else if (arg_code == "b")
+        {
+            // lots of ways bool could be represented here.  Try them all
+            int bool_int = false;
+            if (int_value != nullptr)
+            {
+                bool_int = *int_value > 0 ? 1 : 0;
+            }
+            else if (b != nullptr)
+            {
+                bool_int = b ? 1 : 0;
+            }
+            else if (string_value != nullptr)
+            {
+                bool_int = boost::istarts_with(*string_value, "t") ? 1 : 0;
+            }
+            else
+            {
+                return -1;
+            }
+            r = sd_bus_message_append_basic(m, arg_code[0], &bool_int);
+            if (r < 0)
+            {
+                return r;
+            }
+        }
+        else if (arg_code == "n")
+        {
+            if (int_value == nullptr)
+            {
+                return -1;
+            }
+            int16_t n = static_cast<int16_t>(*int_value);
+            r = sd_bus_message_append_basic(m, arg_code[0], &n);
+            if (r < 0)
+            {
+                return r;
+            }
+        }
+        else if (arg_code == "x")
+        {
+            if (int_value == nullptr)
+            {
+                return -1;
+            }
+            r = sd_bus_message_append_basic(m, arg_code[0], int_value);
+            if (r < 0)
+            {
+                return r;
+            }
+        }
+        else if (arg_code == "y")
+        {
+            if (uint_value == nullptr)
+            {
+                return -1;
+            }
+            uint8_t y = static_cast<uint8_t>(*uint_value);
+            r = sd_bus_message_append_basic(m, arg_code[0], &y);
+        }
+        else if (arg_code == "q")
+        {
+            if (uint_value == nullptr)
+            {
+                return -1;
+            }
+            uint16_t q = static_cast<uint16_t>(*uint_value);
+            r = sd_bus_message_append_basic(m, arg_code[0], &q);
+        }
+        else if (arg_code == "u")
+        {
+            if (uint_value == nullptr)
+            {
+                return -1;
+            }
+            uint32_t u = static_cast<uint32_t>(*uint_value);
+            r = sd_bus_message_append_basic(m, arg_code[0], &u);
+        }
+        else if (arg_code == "t")
+        {
+            if (uint_value == nullptr)
+            {
+                return -1;
+            }
+            r = sd_bus_message_append_basic(m, arg_code[0], uint_value);
+        }
+        else if (arg_code == "d")
+        {
+            sd_bus_message_append_basic(m, arg_code[0], double_value);
+        }
+        else if (boost::starts_with(arg_code, "a"))
+        {
+            std::string contained_type = arg_code.substr(1);
+            r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY,
+                                              contained_type.c_str());
+            if (r < 0)
+            {
+                return r;
+            }
+
+            for (nlohmann::json::const_iterator it = j->begin(); it != j->end();
+                 ++it)
+            {
+                r = convertJsonToDbus(m, contained_type, *it);
+                if (r < 0)
+                {
+                    return r;
+                }
+
+                it++;
+            }
+            sd_bus_message_close_container(m);
+        }
+        else if (boost::starts_with(arg_code, "v"))
+        {
+            std::string contained_type = arg_code.substr(1);
+            BMCWEB_LOG_DEBUG
+                << "variant type: " << arg_code
+                << " appending variant of type: " << contained_type;
+            r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT,
+                                              contained_type.c_str());
+            if (r < 0)
+            {
+                return r;
+            }
+
+            r = convertJsonToDbus(m, contained_type, input_json);
+            if (r < 0)
+            {
+                return r;
+            }
+
+            r = sd_bus_message_close_container(m);
+            if (r < 0)
+            {
+                return r;
+            }
+        }
+        else if (boost::starts_with(arg_code, "(") &&
+                 boost::ends_with(arg_code, ")"))
+        {
+            std::string contained_type =
+                arg_code.substr(1, arg_code.size() - 1);
+            r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT,
+                                              contained_type.c_str());
+            nlohmann::json::const_iterator it = j->begin();
+            for (const std::string &arg_code : dbusArgSplit(arg_type))
+            {
+                if (it == j->end())
+                {
+                    return -1;
+                }
+                r = convertJsonToDbus(m, arg_code, *it);
+                if (r < 0)
+                {
+                    return r;
+                }
+                it++;
+            }
+            r = sd_bus_message_close_container(m);
+        }
+        else if (boost::starts_with(arg_code, "{") &&
+                 boost::ends_with(arg_code, "}"))
+        {
+            std::string contained_type =
+                arg_code.substr(1, arg_code.size() - 1);
+            r = sd_bus_message_open_container(m, SD_BUS_TYPE_DICT_ENTRY,
+                                              contained_type.c_str());
+            std::vector<std::string> codes = dbusArgSplit(contained_type);
+            if (codes.size() != 2)
+            {
+                return -1;
+            }
+            const std::string &key_type = codes[0];
+            const std::string &value_type = codes[1];
+            for (auto it : j->items())
+            {
+                r = convertJsonToDbus(m, key_type, it.key());
+                if (r < 0)
+                {
+                    return r;
+                }
+
+                r = convertJsonToDbus(m, value_type, it.value());
+                if (r < 0)
+                {
+                    return r;
+                }
+            }
+            r = sd_bus_message_close_container(m);
+        }
+        else
+        {
+            return -2;
+        }
+        if (r < 0)
+        {
+            return r;
         }
 
-        r = convertJsonToDbus(m, value_type, it.value());
-        if (r < 0) {
-          return r;
+        if (argTypes.size() > 1)
+        {
+            jIt++;
         }
-      }
-      r = sd_bus_message_close_container(m);
-    } else {
-      return -2;
     }
-    if (r < 0) {
-      return r;
-    }
-
-    if (argTypes.size() > 1) {
-      jIt++;
-    }
-  }
 }
 
 void findActionOnInterface(std::shared_ptr<InProgressActionData> transaction,
-                           const std::string &connectionName) {
-  BMCWEB_LOG_DEBUG << "findActionOnInterface for connection " << connectionName;
-  crow::connections::systemBus->async_method_call(
-      [
-        transaction, connectionName{std::string(connectionName)}
-      ](const boost::system::error_code ec, const std::string &introspect_xml) {
-        BMCWEB_LOG_DEBUG << "got xml:\n " << introspect_xml;
-        if (ec) {
-          BMCWEB_LOG_ERROR << "Introspect call failed with error: "
-                           << ec.message() << " on process: " << connectionName
-                           << "\n";
-        } else {
-          tinyxml2::XMLDocument doc;
-
-          doc.Parse(introspect_xml.c_str());
-          tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
-          if (pRoot == nullptr) {
-            BMCWEB_LOG_ERROR << "XML document failed to parse "
-                             << connectionName << "\n";
-
-          } else {
-            tinyxml2::XMLElement *interface_node =
-                pRoot->FirstChildElement("interface");
-            while (interface_node != nullptr) {
-              std::string this_interface_name =
-                  interface_node->Attribute("name");
-              tinyxml2::XMLElement *method_node =
-                  interface_node->FirstChildElement("method");
-              while (method_node != nullptr) {
-                std::string this_methodName = method_node->Attribute("name");
-                BMCWEB_LOG_DEBUG << "Found method: " << this_methodName;
-                if (this_methodName == transaction->methodName) {
-                  sdbusplus::message::message m =
-                      crow::connections::systemBus->new_method_call(
-                          connectionName.c_str(), transaction->path.c_str(),
-                          this_interface_name.c_str(),
-                          transaction->methodName.c_str());
-
-                  tinyxml2::XMLElement *argument_node =
-                      method_node->FirstChildElement("arg");
-
-                  nlohmann::json::const_iterator arg_it =
-                      transaction->arguments.begin();
-
-                  while (argument_node != nullptr) {
-                    std::string arg_direction =
-                        argument_node->Attribute("direction");
-                    if (arg_direction == "in") {
-                      std::string arg_type = argument_node->Attribute("type");
-                      if (arg_it == transaction->arguments.end()) {
-                        transaction->setErrorStatus();
-                        return;
-                      }
-                      if (convertJsonToDbus(m.get(), arg_type, *arg_it) < 0) {
-                        transaction->setErrorStatus();
-                        return;
-                      }
-
-                      arg_it++;
-                    }
-                    argument_node = method_node->NextSiblingElement("arg");
-                  }
-                  crow::connections::systemBus->async_send(
-                      m, [transaction](boost::system::error_code ec,
-                                       sdbusplus::message::message &m) {
-                        if (ec) {
-                          transaction->setErrorStatus();
-                          return;
-                        }
-                        transaction->res.jsonValue = {{"status", "ok"},
-                                                      {"message", "200 OK"},
-                                                      {"data", nullptr}};
-                      });
-                  break;
-                }
-                method_node = method_node->NextSiblingElement("method");
-              }
-              interface_node = interface_node->NextSiblingElement("interface");
+                           const std::string &connectionName)
+{
+    BMCWEB_LOG_DEBUG << "findActionOnInterface for connection "
+                     << connectionName;
+    crow::connections::systemBus->async_method_call(
+        [transaction, connectionName{std::string(connectionName)}](
+            const boost::system::error_code ec,
+            const std::string &introspect_xml) {
+            BMCWEB_LOG_DEBUG << "got xml:\n " << introspect_xml;
+            if (ec)
+            {
+                BMCWEB_LOG_ERROR
+                    << "Introspect call failed with error: " << ec.message()
+                    << " on process: " << connectionName << "\n";
             }
-          }
-        }
-      },
-      connectionName, transaction->path, "org.freedesktop.DBus.Introspectable",
-      "Introspect");
+            else
+            {
+                tinyxml2::XMLDocument doc;
+
+                doc.Parse(introspect_xml.c_str());
+                tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
+                if (pRoot == nullptr)
+                {
+                    BMCWEB_LOG_ERROR << "XML document failed to parse "
+                                     << connectionName << "\n";
+                }
+                else
+                {
+                    tinyxml2::XMLElement *interface_node =
+                        pRoot->FirstChildElement("interface");
+                    while (interface_node != nullptr)
+                    {
+                        std::string this_interface_name =
+                            interface_node->Attribute("name");
+                        tinyxml2::XMLElement *method_node =
+                            interface_node->FirstChildElement("method");
+                        while (method_node != nullptr)
+                        {
+                            std::string this_methodName =
+                                method_node->Attribute("name");
+                            BMCWEB_LOG_DEBUG << "Found method: "
+                                             << this_methodName;
+                            if (this_methodName == transaction->methodName)
+                            {
+                                sdbusplus::message::message m =
+                                    crow::connections::systemBus
+                                        ->new_method_call(
+                                            connectionName.c_str(),
+                                            transaction->path.c_str(),
+                                            this_interface_name.c_str(),
+                                            transaction->methodName.c_str());
+
+                                tinyxml2::XMLElement *argument_node =
+                                    method_node->FirstChildElement("arg");
+
+                                nlohmann::json::const_iterator arg_it =
+                                    transaction->arguments.begin();
+
+                                while (argument_node != nullptr)
+                                {
+                                    std::string arg_direction =
+                                        argument_node->Attribute("direction");
+                                    if (arg_direction == "in")
+                                    {
+                                        std::string arg_type =
+                                            argument_node->Attribute("type");
+                                        if (arg_it ==
+                                            transaction->arguments.end())
+                                        {
+                                            transaction->setErrorStatus();
+                                            return;
+                                        }
+                                        if (convertJsonToDbus(m.get(), arg_type,
+                                                              *arg_it) < 0)
+                                        {
+                                            transaction->setErrorStatus();
+                                            return;
+                                        }
+
+                                        arg_it++;
+                                    }
+                                    argument_node =
+                                        method_node->NextSiblingElement("arg");
+                                }
+                                crow::connections::systemBus->async_send(
+                                    m, [transaction](
+                                           boost::system::error_code ec,
+                                           sdbusplus::message::message &m) {
+                                        if (ec)
+                                        {
+                                            transaction->setErrorStatus();
+                                            return;
+                                        }
+                                        transaction->res.jsonValue = {
+                                            {"status", "ok"},
+                                            {"message", "200 OK"},
+                                            {"data", nullptr}};
+                                    });
+                                break;
+                            }
+                            method_node =
+                                method_node->NextSiblingElement("method");
+                        }
+                        interface_node =
+                            interface_node->NextSiblingElement("interface");
+                    }
+                }
+            }
+        },
+        connectionName, transaction->path,
+        "org.freedesktop.DBus.Introspectable", "Introspect");
 }
 
 void handle_action(const crow::Request &req, crow::Response &res,
-                   const std::string &objectPath,
-                   const std::string &methodName) {
-  nlohmann::json requestDbusData =
-      nlohmann::json::parse(req.body, nullptr, false);
+                   const std::string &objectPath, const std::string &methodName)
+{
+    nlohmann::json requestDbusData =
+        nlohmann::json::parse(req.body, nullptr, false);
 
-  if (requestDbusData.is_discarded()) {
-    res.result(boost::beast::http::status::bad_request);
-    res.end();
-    return;
-  }
-  if (!requestDbusData.is_array()) {
-    res.result(boost::beast::http::status::bad_request);
-    res.end();
-    return;
-  }
-  auto transaction = std::make_shared<InProgressActionData>(res);
-
-  transaction->path = objectPath;
-  transaction->methodName = methodName;
-  transaction->arguments = std::move(requestDbusData);
-  crow::connections::systemBus->async_method_call(
-      [transaction](
-          const boost::system::error_code ec,
-          const std::vector<std::pair<std::string, std::vector<std::string>>>
-              &interface_names) {
-        if (ec || interface_names.size() <= 0) {
-          transaction->setErrorStatus();
-          return;
-        }
-
-        BMCWEB_LOG_DEBUG << "GetObject returned objects "
-                         << interface_names.size();
-
-        for (const std::pair<std::string, std::vector<std::string>> &object :
-             interface_names) {
-          findActionOnInterface(transaction, object.first);
-        }
-      },
-      "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper",
-      "xyz.openbmc_project.ObjectMapper", "GetObject", objectPath,
-      std::array<std::string, 0>());
-}
-
-void handle_list(crow::Response &res, const std::string &objectPath) {
-  crow::connections::systemBus->async_method_call(
-      [&res](const boost::system::error_code ec,
-             std::vector<std::string> &objectPaths) {
-        if (ec) {
-          res.result(boost::beast::http::status::internal_server_error);
-        } else {
-          res.jsonValue = {{"status", "ok"},
-                           {"message", "200 OK"},
-                           {"data", std::move(objectPaths)}};
-        }
+    if (requestDbusData.is_discarded())
+    {
+        res.result(boost::beast::http::status::bad_request);
         res.end();
-      },
-      "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper",
-      "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", objectPath,
-      static_cast<int32_t>(99), std::array<std::string, 0>());
+        return;
+    }
+    if (!requestDbusData.is_array())
+    {
+        res.result(boost::beast::http::status::bad_request);
+        res.end();
+        return;
+    }
+    auto transaction = std::make_shared<InProgressActionData>(res);
+
+    transaction->path = objectPath;
+    transaction->methodName = methodName;
+    transaction->arguments = std::move(requestDbusData);
+    crow::connections::systemBus->async_method_call(
+        [transaction](
+            const boost::system::error_code ec,
+            const std::vector<std::pair<std::string, std::vector<std::string>>>
+                &interface_names) {
+            if (ec || interface_names.size() <= 0)
+            {
+                transaction->setErrorStatus();
+                return;
+            }
+
+            BMCWEB_LOG_DEBUG << "GetObject returned objects "
+                             << interface_names.size();
+
+            for (const std::pair<std::string, std::vector<std::string>>
+                     &object : interface_names)
+            {
+                findActionOnInterface(transaction, object.first);
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetObject", objectPath,
+        std::array<std::string, 0>());
 }
 
-void handle_enumerate(crow::Response &res, const std::string &objectPath) {
-  crow::connections::systemBus->async_method_call(
-      [&res, objectPath{std::string(objectPath)} ](
-          const boost::system::error_code ec,
-          const GetSubTreeType &object_names) {
-        if (ec) {
-          res.jsonValue = {{"message", "200 OK"},
-                           {"status", "ok"},
-                           {"data", nlohmann::json::object()}};
+void handle_list(crow::Response &res, const std::string &objectPath)
+{
+    crow::connections::systemBus->async_method_call(
+        [&res](const boost::system::error_code ec,
+               std::vector<std::string> &objectPaths) {
+            if (ec)
+            {
+                res.result(boost::beast::http::status::internal_server_error);
+            }
+            else
+            {
+                res.jsonValue = {{"status", "ok"},
+                                 {"message", "200 OK"},
+                                 {"data", std::move(objectPaths)}};
+            }
+            res.end();
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", objectPath,
+        static_cast<int32_t>(99), std::array<std::string, 0>());
+}
 
-          res.end();
-          return;
-        }
+void handle_enumerate(crow::Response &res, const std::string &objectPath)
+{
+    crow::connections::systemBus->async_method_call(
+        [&res, objectPath{std::string(objectPath)}](
+            const boost::system::error_code ec,
+            const GetSubTreeType &object_names) {
+            if (ec)
+            {
+                res.jsonValue = {{"message", "200 OK"},
+                                 {"status", "ok"},
+                                 {"data", nlohmann::json::object()}};
 
-        boost::container::flat_set<std::string> connections;
+                res.end();
+                return;
+            }
 
-        for (const auto &object : object_names) {
-          for (const auto &Connection : object.second) {
-            connections.insert(Connection.first);
-          }
-        }
+            boost::container::flat_set<std::string> connections;
 
-        if (connections.size() <= 0) {
-          res.result(boost::beast::http::status::not_found);
-          res.end();
-          return;
-        }
-        auto transaction =
-            std::make_shared<nlohmann::json>(nlohmann::json::object());
-        for (const std::string &Connection : connections) {
-          getManagedObjectsForEnumerate(objectPath, Connection, res,
-                                        transaction);
-        }
-      },
-      "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper",
-      "xyz.openbmc_project.ObjectMapper", "GetSubTree", objectPath, (int32_t)0,
-      std::array<std::string, 0>());
+            for (const auto &object : object_names)
+            {
+                for (const auto &Connection : object.second)
+                {
+                    connections.insert(Connection.first);
+                }
+            }
+
+            if (connections.size() <= 0)
+            {
+                res.result(boost::beast::http::status::not_found);
+                res.end();
+                return;
+            }
+            auto transaction =
+                std::make_shared<nlohmann::json>(nlohmann::json::object());
+            for (const std::string &Connection : connections)
+            {
+                getManagedObjectsForEnumerate(objectPath, Connection, res,
+                                              transaction);
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetSubTree", objectPath,
+        (int32_t)0, std::array<std::string, 0>());
 }
 
 void handle_get(crow::Response &res, std::string &objectPath,
-                std::string &destProperty) {
-  BMCWEB_LOG_DEBUG << "handle_get: " << objectPath << " prop:" << destProperty;
-  std::shared_ptr<std::string> property_name =
-      std::make_shared<std::string>(std::move(destProperty));
+                std::string &destProperty)
+{
+    BMCWEB_LOG_DEBUG << "handle_get: " << objectPath
+                     << " prop:" << destProperty;
+    std::shared_ptr<std::string> property_name =
+        std::make_shared<std::string>(std::move(destProperty));
 
-  std::shared_ptr<std::string> path =
-      std::make_shared<std::string>(std::move(objectPath));
+    std::shared_ptr<std::string> path =
+        std::make_shared<std::string>(std::move(objectPath));
 
-  using GetObjectType =
-      std::vector<std::pair<std::string, std::vector<std::string>>>;
-  crow::connections::systemBus->async_method_call(
-      [&res, path, property_name](const boost::system::error_code ec,
-                                  const GetObjectType &object_names) {
-        if (ec || object_names.size() <= 0) {
-          res.result(boost::beast::http::status::not_found);
-          res.end();
-          return;
-        }
-        std::shared_ptr<nlohmann::json> response =
-            std::make_shared<nlohmann::json>(nlohmann::json::object());
-        // The mapper should never give us an empty interface names list, but
-        // check anyway
-        for (const std::pair<std::string, std::vector<std::string>> connection :
-             object_names) {
-          const std::vector<std::string> &interfaceNames = connection.second;
+    using GetObjectType =
+        std::vector<std::pair<std::string, std::vector<std::string>>>;
+    crow::connections::systemBus->async_method_call(
+        [&res, path, property_name](const boost::system::error_code ec,
+                                    const GetObjectType &object_names) {
+            if (ec || object_names.size() <= 0)
+            {
+                res.result(boost::beast::http::status::not_found);
+                res.end();
+                return;
+            }
+            std::shared_ptr<nlohmann::json> response =
+                std::make_shared<nlohmann::json>(nlohmann::json::object());
+            // The mapper should never give us an empty interface names list,
+            // but check anyway
+            for (const std::pair<std::string, std::vector<std::string>>
+                     connection : object_names)
+            {
+                const std::vector<std::string> &interfaceNames =
+                    connection.second;
 
-          if (interfaceNames.size() <= 0) {
-            res.result(boost::beast::http::status::not_found);
-            res.end();
-            return;
-          }
-
-          for (const std::string &interface : interfaceNames) {
-            crow::connections::systemBus->async_method_call(
-                [&res, response, property_name](
-                    const boost::system::error_code ec,
-                    const std::vector<std::pair<
-                        std::string, DbusRestVariantType>> &properties) {
-                  if (ec) {
-                    BMCWEB_LOG_ERROR << "Bad dbus request error: " << ec;
-                  } else {
-                    for (const std::pair<std::string, DbusRestVariantType>
-                             &property : properties) {
-                      // if property name is empty, or matches our search query,
-                      // add it to the response json
-
-                      if (property_name->empty()) {
-                        mapbox::util::apply_visitor(
-                            [&response, &property](auto &&val) {
-                              (*response)[property.first] = val;
-                            },
-                            property.second);
-                      } else if (property.first == *property_name) {
-                        mapbox::util::apply_visitor(
-                            [&response](auto &&val) { (*response) = val; },
-                            property.second);
-                      }
-                    }
-                  }
-                  if (response.use_count() == 1) {
-                    res.jsonValue = {{"status", "ok"},
-                                     {"message", "200 OK"},
-                                     {"data", *response}};
-
+                if (interfaceNames.size() <= 0)
+                {
+                    res.result(boost::beast::http::status::not_found);
                     res.end();
-                  }
-                },
-                connection.first, *path, "org.freedesktop.DBus.Properties",
-                "GetAll", interface);
-          }
-        }
-      },
-      "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper",
-      "xyz.openbmc_project.ObjectMapper", "GetObject", *path,
-      std::array<std::string, 0>());
+                    return;
+                }
+
+                for (const std::string &interface : interfaceNames)
+                {
+                    crow::connections::systemBus->async_method_call(
+                        [&res, response, property_name](
+                            const boost::system::error_code ec,
+                            const std::vector<
+                                std::pair<std::string, DbusRestVariantType>>
+                                &properties) {
+                            if (ec)
+                            {
+                                BMCWEB_LOG_ERROR << "Bad dbus request error: "
+                                                 << ec;
+                            }
+                            else
+                            {
+                                for (const std::pair<std::string,
+                                                     DbusRestVariantType>
+                                         &property : properties)
+                                {
+                                    // if property name is empty, or matches our
+                                    // search query, add it to the response json
+
+                                    if (property_name->empty())
+                                    {
+                                        mapbox::util::apply_visitor(
+                                            [&response, &property](auto &&val) {
+                                                (*response)[property.first] =
+                                                    val;
+                                            },
+                                            property.second);
+                                    }
+                                    else if (property.first == *property_name)
+                                    {
+                                        mapbox::util::apply_visitor(
+                                            [&response](auto &&val) {
+                                                (*response) = val;
+                                            },
+                                            property.second);
+                                    }
+                                }
+                            }
+                            if (response.use_count() == 1)
+                            {
+                                res.jsonValue = {{"status", "ok"},
+                                                 {"message", "200 OK"},
+                                                 {"data", *response}};
+
+                                res.end();
+                            }
+                        },
+                        connection.first, *path,
+                        "org.freedesktop.DBus.Properties", "GetAll", interface);
+                }
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetObject", *path,
+        std::array<std::string, 0>());
 }
 
-struct AsyncPutRequest {
-  AsyncPutRequest(crow::Response &res) : res(res) {
-    res.jsonValue = {
-        {"status", "ok"}, {"message", "200 OK"}, {"data", nullptr}};
-  }
-  ~AsyncPutRequest() {
-    if (res.result() == boost::beast::http::status::internal_server_error) {
-      // Reset the json object to clear out any data that made it in before the
-      // error happened
-      // todo(ed) handle error condition with proper code
-      res.jsonValue = nlohmann::json::object();
+struct AsyncPutRequest
+{
+    AsyncPutRequest(crow::Response &res) : res(res)
+    {
+        res.jsonValue = {
+            {"status", "ok"}, {"message", "200 OK"}, {"data", nullptr}};
+    }
+    ~AsyncPutRequest()
+    {
+        if (res.result() == boost::beast::http::status::internal_server_error)
+        {
+            // Reset the json object to clear out any data that made it in
+            // before the error happened todo(ed) handle error condition with
+            // proper code
+            res.jsonValue = nlohmann::json::object();
+        }
+
+        if (res.jsonValue.empty())
+        {
+            res.result(boost::beast::http::status::forbidden);
+            res.jsonValue = {
+                {"status", "error"},
+                {"message", "403 Forbidden"},
+                {"data",
+                 {{"message", "The specified property cannot be created: " +
+                                  propertyName}}}};
+        }
+
+        res.end();
     }
 
-    if (res.jsonValue.empty()) {
-      res.result(boost::beast::http::status::forbidden);
-      res.jsonValue = {
-          {"status", "error"},
-          {"message", "403 Forbidden"},
-          {"data",
-           {{"message",
-             "The specified property cannot be created: " + propertyName}}}};
+    void setErrorStatus()
+    {
+        res.result(boost::beast::http::status::internal_server_error);
     }
 
-    res.end();
-  }
-
-  void setErrorStatus() {
-    res.result(boost::beast::http::status::internal_server_error);
-  }
-
-  crow::Response &res;
-  std::string objectPath;
-  std::string propertyName;
-  nlohmann::json propertyValue;
+    crow::Response &res;
+    std::string objectPath;
+    std::string propertyName;
+    nlohmann::json propertyValue;
 };
 
 void handlePut(const crow::Request &req, crow::Response &res,
-               const std::string &objectPath, const std::string &destProperty) {
-  nlohmann::json requestDbusData =
-      nlohmann::json::parse(req.body, nullptr, false);
+               const std::string &objectPath, const std::string &destProperty)
+{
+    nlohmann::json requestDbusData =
+        nlohmann::json::parse(req.body, nullptr, false);
 
-  if (requestDbusData.is_discarded()) {
-    res.result(boost::beast::http::status::bad_request);
-    res.end();
-    return;
-  }
-
-  nlohmann::json::const_iterator propertyIt = requestDbusData.find("data");
-  if (propertyIt == requestDbusData.end()) {
-    res.result(boost::beast::http::status::bad_request);
-    res.end();
-    return;
-  }
-  const nlohmann::json &propertySetValue = *propertyIt;
-  auto transaction = std::make_shared<AsyncPutRequest>(res);
-  transaction->objectPath = objectPath;
-  transaction->propertyName = destProperty;
-  transaction->propertyValue = propertySetValue;
-
-  using GetObjectType =
-      std::vector<std::pair<std::string, std::vector<std::string>>>;
-
-  crow::connections::systemBus->async_method_call(
-      [transaction](const boost::system::error_code ec,
-                    const GetObjectType &object_names) {
-        if (!ec && object_names.size() <= 0) {
-          transaction->res.result(boost::beast::http::status::not_found);
-          return;
-        }
-
-        for (const std::pair<std::string, std::vector<std::string>> connection :
-             object_names) {
-          const std::string &connectionName = connection.first;
-
-          crow::connections::systemBus->async_method_call(
-              [ connectionName{std::string(connectionName)}, transaction ](
-                  const boost::system::error_code ec,
-                  const std::string &introspectXml) {
-                if (ec) {
-                  BMCWEB_LOG_ERROR
-                      << "Introspect call failed with error: " << ec.message()
-                      << " on process: " << connectionName;
-                  transaction->setErrorStatus();
-                  return;
-                }
-                tinyxml2::XMLDocument doc;
-
-                doc.Parse(introspectXml.c_str());
-                tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
-                if (pRoot == nullptr) {
-                  BMCWEB_LOG_ERROR << "XML document failed to parse: "
-                                   << introspectXml;
-                  transaction->setErrorStatus();
-                  return;
-                }
-                tinyxml2::XMLElement *ifaceNode =
-                    pRoot->FirstChildElement("interface");
-                while (ifaceNode != nullptr) {
-                  const char *interfaceName = ifaceNode->Attribute("name");
-                  BMCWEB_LOG_DEBUG << "found interface " << interfaceName;
-                  tinyxml2::XMLElement *propNode =
-                      ifaceNode->FirstChildElement("property");
-                  while (propNode != nullptr) {
-                    const char *propertyName = propNode->Attribute("name");
-                    BMCWEB_LOG_DEBUG << "Found property " << propertyName;
-                    if (propertyName == transaction->propertyName) {
-                      const char *argType = propNode->Attribute("type");
-                      if (argType != nullptr) {
-                        sdbusplus::message::message m =
-                            crow::connections::systemBus->new_method_call(
-                                connectionName.c_str(),
-                                transaction->objectPath.c_str(),
-                                "org.freedesktop.DBus.Properties", "Set");
-                        m.append(interfaceName, transaction->propertyName);
-                        int r = sd_bus_message_open_container(
-                            m.get(), SD_BUS_TYPE_VARIANT, argType);
-                        if (r < 0) {
-                          transaction->setErrorStatus();
-                          return;
-                        }
-                        r = convertJsonToDbus(m.get(), argType,
-                                              transaction->propertyValue);
-                        if (r < 0) {
-                          transaction->setErrorStatus();
-                          return;
-                        }
-                        r = sd_bus_message_close_container(m.get());
-                        if (r < 0) {
-                          transaction->setErrorStatus();
-                          return;
-                        }
-
-                        crow::connections::systemBus->async_send(
-                            m, [transaction](boost::system::error_code ec,
-                                             sdbusplus::message::message &m) {
-                              BMCWEB_LOG_DEBUG << "sent";
-                              if (ec) {
-                                transaction->res.jsonValue["status"] = "error";
-                                transaction->res.jsonValue["message"] =
-                                    ec.message();
-                              }
-                            });
-                      }
-                    }
-                    propNode = propNode->NextSiblingElement("property");
-                  }
-                  ifaceNode = ifaceNode->NextSiblingElement("interface");
-                }
-              },
-              connectionName, transaction->objectPath,
-              "org.freedesktop.DBus.Introspectable", "Introspect");
-        }
-      },
-      "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper",
-      "xyz.openbmc_project.ObjectMapper", "GetObject", transaction->objectPath,
-      std::array<std::string, 0>());
-}
-
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...> &app) {
-  BMCWEB_ROUTE(app, "/bus/")
-      .methods("GET"_method)([](const crow::Request &req, crow::Response &res) {
-        res.jsonValue = {{"busses", {{{"name", "system"}}}}, {"status", "ok"}};
-      });
-
-  BMCWEB_ROUTE(app, "/bus/system/")
-      .methods("GET"_method)([](const crow::Request &req, crow::Response &res) {
-
-        auto myCallback = [&res](const boost::system::error_code ec,
-                                 std::vector<std::string> &names) {
-          if (ec) {
-            BMCWEB_LOG_ERROR << "Dbus call failed with code " << ec;
-            res.result(boost::beast::http::status::internal_server_error);
-          } else {
-            std::sort(names.begin(), names.end());
-            nlohmann::json j{{"status", "ok"}};
-            auto &objectsSub = j["objects"];
-            for (auto &name : names) {
-              objectsSub.push_back({{"name", name}});
-            }
-            res.jsonValue = std::move(j);
-          }
-          res.end();
-        };
-        crow::connections::systemBus->async_method_call(
-            std::move(myCallback), "org.freedesktop.DBus", "/",
-            "org.freedesktop.DBus", "ListNames");
-      });
-
-  BMCWEB_ROUTE(app, "/list/")
-      .methods("GET"_method)([](const crow::Request &req, crow::Response &res) {
-        handle_list(res, "/");
-      });
-
-  BMCWEB_ROUTE(app, "/xyz/<path>")
-      .methods("GET"_method, "PUT"_method,
-               "POST"_method)([](const crow::Request &req, crow::Response &res,
-                                 const std::string &path) {
-        std::string objectPath = "/xyz/" + path;
-
-        // Trim any trailing "/" at the end
-        if (boost::ends_with(objectPath, "/")) {
-          objectPath.pop_back();
-        }
-
-        // If accessing a single attribute, fill in and update objectPath,
-        // otherwise leave destProperty blank
-        std::string destProperty = "";
-        const char *attrSeperator = "/attr/";
-        size_t attrPosition = path.find(attrSeperator);
-        if (attrPosition != path.npos) {
-          objectPath = "/xyz/" + path.substr(0, attrPosition);
-          destProperty =
-              path.substr(attrPosition + strlen(attrSeperator), path.length());
-        }
-
-        if (req.method() == "POST"_method) {
-          constexpr const char *action_seperator = "/action/";
-          size_t action_position = path.find(action_seperator);
-          if (action_position != path.npos) {
-            objectPath = "/xyz/" + path.substr(0, action_position);
-            std::string post_property = path.substr(
-                (action_position + strlen(action_seperator)), path.length());
-            handle_action(req, res, objectPath, post_property);
-            return;
-          }
-        } else if (req.method() == "GET"_method) {
-          if (boost::ends_with(objectPath, "/enumerate")) {
-            objectPath.erase(objectPath.end() - 10, objectPath.end());
-            handle_enumerate(res, objectPath);
-          } else if (boost::ends_with(objectPath, "/list")) {
-            objectPath.erase(objectPath.end() - 5, objectPath.end());
-            handle_list(res, objectPath);
-          } else {
-            handle_get(res, objectPath, destProperty);
-          }
-          return;
-        } else if (req.method() == "PUT"_method) {
-          handlePut(req, res, objectPath, destProperty);
-          return;
-        }
-
-        res.result(boost::beast::http::status::method_not_allowed);
-        res.end();
-      });
-
-  BMCWEB_ROUTE(app, "/bus/system/<str>/")
-      .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
-                                const std::string &Connection) {
-        std::shared_ptr<nlohmann::json> transaction;
-        introspectObjects(res, Connection, "/", transaction);
-      });
-
-  BMCWEB_ROUTE(app, "/download/dump/<str>/")
-      .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
-                                const std::string &dumpId) {
-        std::regex validFilename("^[\\w\\- ]+(\\.?[\\w\\- ]+)$");
-        if (!std::regex_match(dumpId, validFilename)) {
-          res.result(boost::beast::http::status::not_found);
-          res.end();
-          return;
-        }
-        std::experimental::filesystem::path loc(
-            "/var/lib/phosphor-debug-collector/dumps");
-
-        loc += dumpId;
-
-        if (!std::experimental::filesystem::exists(loc) ||
-            !std::experimental::filesystem::is_directory(loc)) {
-          res.result(boost::beast::http::status::not_found);
-          res.end();
-          return;
-        }
-        std::experimental::filesystem::directory_iterator files(loc);
-        for (auto &file : files) {
-          std::ifstream readFile(file.path());
-          if (readFile.good()) {
-            continue;
-          }
-          res.addHeader("Content-Type", "application/octet-stream");
-          res.body() = {std::istreambuf_iterator<char>(readFile),
-                        std::istreambuf_iterator<char>()};
-          res.end();
-        }
-        res.result(boost::beast::http::status::not_found);
+    if (requestDbusData.is_discarded())
+    {
+        res.result(boost::beast::http::status::bad_request);
         res.end();
         return;
-      });
+    }
 
-  BMCWEB_ROUTE(app, "/bus/system/<str>/<path>")
-      .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
-                                const std::string &processName,
-                                const std::string &requestedPath) {
-        std::vector<std::string> strs;
-        boost::split(strs, requestedPath, boost::is_any_of("/"));
-        std::string objectPath;
-        std::string interfaceName;
-        std::string methodName;
-        auto it = strs.begin();
-        if (it == strs.end()) {
-          objectPath = "/";
-        }
-        while (it != strs.end()) {
-          // Check if segment contains ".".  If it does, it must be an
-          // interface
-          if (it->find(".") != std::string::npos) {
-            break;
-            // THis check is neccesary as the trailing slash gets parsed as
-            // part of our <path> specifier above, which causes the normal
-            // trailing backslash redirector to fail.
-          } else if (!it->empty()) {
-            objectPath += "/" + *it;
-          }
-          it++;
-        }
-        if (it != strs.end()) {
-          interfaceName = *it;
-          it++;
+    nlohmann::json::const_iterator propertyIt = requestDbusData.find("data");
+    if (propertyIt == requestDbusData.end())
+    {
+        res.result(boost::beast::http::status::bad_request);
+        res.end();
+        return;
+    }
+    const nlohmann::json &propertySetValue = *propertyIt;
+    auto transaction = std::make_shared<AsyncPutRequest>(res);
+    transaction->objectPath = objectPath;
+    transaction->propertyName = destProperty;
+    transaction->propertyValue = propertySetValue;
 
-          // after interface, we might have a method name
-          if (it != strs.end()) {
-            methodName = *it;
-            it++;
-          }
-        }
-        if (it != strs.end()) {
-          // if there is more levels past the method name, something went
-          // wrong, return not found
-          res.result(boost::beast::http::status::not_found);
-          res.end();
-          return;
-        }
-        if (interfaceName.empty()) {
-          crow::connections::systemBus->async_method_call(
-              [&, processName, objectPath](const boost::system::error_code ec,
-                                           const std::string &introspect_xml) {
-                if (ec) {
-                  BMCWEB_LOG_ERROR
-                      << "Introspect call failed with error: " << ec.message()
-                      << " on process: " << processName
-                      << " path: " << objectPath << "\n";
+    using GetObjectType =
+        std::vector<std::pair<std::string, std::vector<std::string>>>;
 
-                } else {
-                  tinyxml2::XMLDocument doc;
+    crow::connections::systemBus->async_method_call(
+        [transaction](const boost::system::error_code ec,
+                      const GetObjectType &object_names) {
+            if (!ec && object_names.size() <= 0)
+            {
+                transaction->res.result(boost::beast::http::status::not_found);
+                return;
+            }
 
-                  doc.Parse(introspect_xml.c_str());
-                  tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
-                  if (pRoot == nullptr) {
-                    BMCWEB_LOG_ERROR << "XML document failed to parse "
-                                     << processName << " " << objectPath
-                                     << "\n";
-                    res.jsonValue = {{"status", "XML parse error"}};
-                    res.result(
-                        boost::beast::http::status::internal_server_error);
-                  } else {
-                    nlohmann::json interfacesArray = nlohmann::json::array();
-                    tinyxml2::XMLElement *interface =
-                        pRoot->FirstChildElement("interface");
+            for (const std::pair<std::string, std::vector<std::string>>
+                     connection : object_names)
+            {
+                const std::string &connectionName = connection.first;
 
-                    while (interface != nullptr) {
-                      std::string ifaceName = interface->Attribute("name");
-                      interfacesArray.push_back({{"name", ifaceName}});
-
-                      interface = interface->NextSiblingElement("interface");
-                    }
-                    res.jsonValue = {{"status", "ok"},
-                                     {"bus_name", processName},
-                                     {"interfaces", interfacesArray},
-                                     {"objectPath", objectPath}};
-                  }
-                }
-                res.end();
-              },
-              processName, objectPath, "org.freedesktop.DBus.Introspectable",
-              "Introspect");
-        } else {
-          crow::connections::systemBus->async_method_call(
-              [
-                    &, processName, objectPath,
-                    interface_name{std::move(interfaceName)}
-              ](const boost::system::error_code ec,
-                const std::string &introspect_xml) {
-                if (ec) {
-                  BMCWEB_LOG_ERROR
-                      << "Introspect call failed with error: " << ec.message()
-                      << " on process: " << processName
-                      << " path: " << objectPath << "\n";
-
-                } else {
-                  tinyxml2::XMLDocument doc;
-
-                  doc.Parse(introspect_xml.c_str());
-                  tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node");
-                  if (pRoot == nullptr) {
-                    BMCWEB_LOG_ERROR << "XML document failed to parse "
-                                     << processName << " " << objectPath
-                                     << "\n";
-                    res.result(
-                        boost::beast::http::status::internal_server_error);
-
-                  } else {
-                    tinyxml2::XMLElement *node =
-                        pRoot->FirstChildElement("node");
-
-                    // if we know we're the only call, build the json directly
-                    nlohmann::json methodsArray = nlohmann::json::array();
-                    nlohmann::json signalsArray = nlohmann::json::array();
-                    tinyxml2::XMLElement *interface =
-                        pRoot->FirstChildElement("interface");
-
-                    while (interface != nullptr) {
-                      std::string ifaceName = interface->Attribute("name");
-
-                      if (ifaceName == interfaceName) {
-                        tinyxml2::XMLElement *methods =
-                            interface->FirstChildElement("method");
-                        while (methods != nullptr) {
-                          nlohmann::json argsArray = nlohmann::json::array();
-                          tinyxml2::XMLElement *arg =
-                              methods->FirstChildElement("arg");
-                          while (arg != nullptr) {
-                            argsArray.push_back(
-                                {{"name", arg->Attribute("name")},
-                                 {"type", arg->Attribute("type")},
-                                 {"direction", arg->Attribute("direction")}});
-                            arg = arg->NextSiblingElement("arg");
-                          }
-                          methodsArray.push_back(
-                              {{"name", methods->Attribute("name")},
-                               {"uri", "/bus/system/" + processName +
-                                           objectPath + "/" + interfaceName +
-                                           "/" + methods->Attribute("name")},
-                               {"args", argsArray}});
-                          methods = methods->NextSiblingElement("method");
+                crow::connections::systemBus->async_method_call(
+                    [connectionName{std::string(connectionName)},
+                     transaction](const boost::system::error_code ec,
+                                  const std::string &introspectXml) {
+                        if (ec)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "Introspect call failed with error: "
+                                << ec.message()
+                                << " on process: " << connectionName;
+                            transaction->setErrorStatus();
+                            return;
                         }
-                        tinyxml2::XMLElement *signals =
-                            interface->FirstChildElement("signal");
-                        while (signals != nullptr) {
-                          nlohmann::json argsArray = nlohmann::json::array();
+                        tinyxml2::XMLDocument doc;
 
-                          tinyxml2::XMLElement *arg =
-                              signals->FirstChildElement("arg");
-                          while (arg != nullptr) {
-                            std::string name = arg->Attribute("name");
-                            std::string type = arg->Attribute("type");
-                            argsArray.push_back({
-                                {"name", name},
-                                {"type", type},
-                            });
-                            arg = arg->NextSiblingElement("arg");
-                          }
-                          signalsArray.push_back(
-                              {{"name", signals->Attribute("name")},
-                               {"args", argsArray}});
-                          signals = signals->NextSiblingElement("signal");
+                        doc.Parse(introspectXml.c_str());
+                        tinyxml2::XMLNode *pRoot =
+                            doc.FirstChildElement("node");
+                        if (pRoot == nullptr)
+                        {
+                            BMCWEB_LOG_ERROR << "XML document failed to parse: "
+                                             << introspectXml;
+                            transaction->setErrorStatus();
+                            return;
                         }
+                        tinyxml2::XMLElement *ifaceNode =
+                            pRoot->FirstChildElement("interface");
+                        while (ifaceNode != nullptr)
+                        {
+                            const char *interfaceName =
+                                ifaceNode->Attribute("name");
+                            BMCWEB_LOG_DEBUG << "found interface "
+                                             << interfaceName;
+                            tinyxml2::XMLElement *propNode =
+                                ifaceNode->FirstChildElement("property");
+                            while (propNode != nullptr)
+                            {
+                                const char *propertyName =
+                                    propNode->Attribute("name");
+                                BMCWEB_LOG_DEBUG << "Found property "
+                                                 << propertyName;
+                                if (propertyName == transaction->propertyName)
+                                {
+                                    const char *argType =
+                                        propNode->Attribute("type");
+                                    if (argType != nullptr)
+                                    {
+                                        sdbusplus::message::message m =
+                                            crow::connections::systemBus
+                                                ->new_method_call(
+                                                    connectionName.c_str(),
+                                                    transaction->objectPath
+                                                        .c_str(),
+                                                    "org.freedesktop.DBus."
+                                                    "Properties",
+                                                    "Set");
+                                        m.append(interfaceName,
+                                                 transaction->propertyName);
+                                        int r = sd_bus_message_open_container(
+                                            m.get(), SD_BUS_TYPE_VARIANT,
+                                            argType);
+                                        if (r < 0)
+                                        {
+                                            transaction->setErrorStatus();
+                                            return;
+                                        }
+                                        r = convertJsonToDbus(
+                                            m.get(), argType,
+                                            transaction->propertyValue);
+                                        if (r < 0)
+                                        {
+                                            transaction->setErrorStatus();
+                                            return;
+                                        }
+                                        r = sd_bus_message_close_container(
+                                            m.get());
+                                        if (r < 0)
+                                        {
+                                            transaction->setErrorStatus();
+                                            return;
+                                        }
 
-                        res.jsonValue = {
-                            {"status", "ok"},
-                            {"bus_name", processName},
-                            {"interface", interfaceName},
-                            {"methods", methodsArray},
-                            {"objectPath", objectPath},
-                            {"properties", nlohmann::json::object()},
-                            {"signals", signalsArray}};
-
-                        break;
-                      }
-
-                      interface = interface->NextSiblingElement("interface");
-                    }
-                    if (interface == nullptr) {
-                      // if we got to the end of the list and never found a
-                      // match, throw 404
-                      res.result(boost::beast::http::status::not_found);
-                    }
-                  }
-                }
-                res.end();
-              },
-              processName, objectPath, "org.freedesktop.DBus.Introspectable",
-              "Introspect");
-        }
-      });
+                                        crow::connections::systemBus
+                                            ->async_send(
+                                                m,
+                                                [transaction](
+                                                    boost::system::error_code
+                                                        ec,
+                                                    sdbusplus::message::message
+                                                        &m) {
+                                                    BMCWEB_LOG_DEBUG << "sent";
+                                                    if (ec)
+                                                    {
+                                                        transaction->res
+                                                            .jsonValue
+                                                                ["status"] =
+                                                            "error";
+                                                        transaction->res
+                                                            .jsonValue
+                                                                ["message"] =
+                                                            ec.message();
+                                                    }
+                                                });
+                                    }
+                                }
+                                propNode =
+                                    propNode->NextSiblingElement("property");
+                            }
+                            ifaceNode =
+                                ifaceNode->NextSiblingElement("interface");
+                        }
+                    },
+                    connectionName, transaction->objectPath,
+                    "org.freedesktop.DBus.Introspectable", "Introspect");
+            }
+        },
+        "xyz.openbmc_project.ObjectMapper",
+        "/xyz/openbmc_project/object_mapper",
+        "xyz.openbmc_project.ObjectMapper", "GetObject",
+        transaction->objectPath, std::array<std::string, 0>());
 }
-}  // namespace openbmc_mapper
-}  // namespace crow
+
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...> &app)
+{
+    BMCWEB_ROUTE(app, "/bus/")
+        .methods("GET"_method)(
+            [](const crow::Request &req, crow::Response &res) {
+                res.jsonValue = {{"busses", {{{"name", "system"}}}},
+                                 {"status", "ok"}};
+            });
+
+    BMCWEB_ROUTE(app, "/bus/system/")
+        .methods("GET"_method)(
+            [](const crow::Request &req, crow::Response &res) {
+                auto myCallback = [&res](const boost::system::error_code ec,
+                                         std::vector<std::string> &names) {
+                    if (ec)
+                    {
+                        BMCWEB_LOG_ERROR << "Dbus call failed with code " << ec;
+                        res.result(
+                            boost::beast::http::status::internal_server_error);
+                    }
+                    else
+                    {
+                        std::sort(names.begin(), names.end());
+                        nlohmann::json j{{"status", "ok"}};
+                        auto &objectsSub = j["objects"];
+                        for (auto &name : names)
+                        {
+                            objectsSub.push_back({{"name", name}});
+                        }
+                        res.jsonValue = std::move(j);
+                    }
+                    res.end();
+                };
+                crow::connections::systemBus->async_method_call(
+                    std::move(myCallback), "org.freedesktop.DBus", "/",
+                    "org.freedesktop.DBus", "ListNames");
+            });
+
+    BMCWEB_ROUTE(app, "/list/")
+        .methods("GET"_method)(
+            [](const crow::Request &req, crow::Response &res) {
+                handle_list(res, "/");
+            });
+
+    BMCWEB_ROUTE(app, "/xyz/<path>")
+        .methods("GET"_method, "PUT"_method,
+                 "POST"_method)([](const crow::Request &req,
+                                   crow::Response &res,
+                                   const std::string &path) {
+            std::string objectPath = "/xyz/" + path;
+
+            // Trim any trailing "/" at the end
+            if (boost::ends_with(objectPath, "/"))
+            {
+                objectPath.pop_back();
+            }
+
+            // If accessing a single attribute, fill in and update objectPath,
+            // otherwise leave destProperty blank
+            std::string destProperty = "";
+            const char *attrSeperator = "/attr/";
+            size_t attrPosition = path.find(attrSeperator);
+            if (attrPosition != path.npos)
+            {
+                objectPath = "/xyz/" + path.substr(0, attrPosition);
+                destProperty = path.substr(attrPosition + strlen(attrSeperator),
+                                           path.length());
+            }
+
+            if (req.method() == "POST"_method)
+            {
+                constexpr const char *action_seperator = "/action/";
+                size_t action_position = path.find(action_seperator);
+                if (action_position != path.npos)
+                {
+                    objectPath = "/xyz/" + path.substr(0, action_position);
+                    std::string post_property = path.substr(
+                        (action_position + strlen(action_seperator)),
+                        path.length());
+                    handle_action(req, res, objectPath, post_property);
+                    return;
+                }
+            }
+            else if (req.method() == "GET"_method)
+            {
+                if (boost::ends_with(objectPath, "/enumerate"))
+                {
+                    objectPath.erase(objectPath.end() - 10, objectPath.end());
+                    handle_enumerate(res, objectPath);
+                }
+                else if (boost::ends_with(objectPath, "/list"))
+                {
+                    objectPath.erase(objectPath.end() - 5, objectPath.end());
+                    handle_list(res, objectPath);
+                }
+                else
+                {
+                    handle_get(res, objectPath, destProperty);
+                }
+                return;
+            }
+            else if (req.method() == "PUT"_method)
+            {
+                handlePut(req, res, objectPath, destProperty);
+                return;
+            }
+
+            res.result(boost::beast::http::status::method_not_allowed);
+            res.end();
+        });
+
+    BMCWEB_ROUTE(app, "/bus/system/<str>/")
+        .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
+                                  const std::string &Connection) {
+            std::shared_ptr<nlohmann::json> transaction;
+            introspectObjects(res, Connection, "/", transaction);
+        });
+
+    BMCWEB_ROUTE(app, "/download/dump/<str>/")
+        .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
+                                  const std::string &dumpId) {
+            std::regex validFilename("^[\\w\\- ]+(\\.?[\\w\\- ]+)$");
+            if (!std::regex_match(dumpId, validFilename))
+            {
+                res.result(boost::beast::http::status::not_found);
+                res.end();
+                return;
+            }
+            std::experimental::filesystem::path loc(
+                "/var/lib/phosphor-debug-collector/dumps");
+
+            loc += dumpId;
+
+            if (!std::experimental::filesystem::exists(loc) ||
+                !std::experimental::filesystem::is_directory(loc))
+            {
+                res.result(boost::beast::http::status::not_found);
+                res.end();
+                return;
+            }
+            std::experimental::filesystem::directory_iterator files(loc);
+            for (auto &file : files)
+            {
+                std::ifstream readFile(file.path());
+                if (readFile.good())
+                {
+                    continue;
+                }
+                res.addHeader("Content-Type", "application/octet-stream");
+                res.body() = {std::istreambuf_iterator<char>(readFile),
+                              std::istreambuf_iterator<char>()};
+                res.end();
+            }
+            res.result(boost::beast::http::status::not_found);
+            res.end();
+            return;
+        });
+
+    BMCWEB_ROUTE(app, "/bus/system/<str>/<path>")
+        .methods("GET"_method)([](const crow::Request &req, crow::Response &res,
+                                  const std::string &processName,
+                                  const std::string &requestedPath) {
+            std::vector<std::string> strs;
+            boost::split(strs, requestedPath, boost::is_any_of("/"));
+            std::string objectPath;
+            std::string interfaceName;
+            std::string methodName;
+            auto it = strs.begin();
+            if (it == strs.end())
+            {
+                objectPath = "/";
+            }
+            while (it != strs.end())
+            {
+                // Check if segment contains ".".  If it does, it must be an
+                // interface
+                if (it->find(".") != std::string::npos)
+                {
+                    break;
+                    // THis check is neccesary as the trailing slash gets parsed
+                    // as part of our <path> specifier above, which causes the
+                    // normal trailing backslash redirector to fail.
+                }
+                else if (!it->empty())
+                {
+                    objectPath += "/" + *it;
+                }
+                it++;
+            }
+            if (it != strs.end())
+            {
+                interfaceName = *it;
+                it++;
+
+                // after interface, we might have a method name
+                if (it != strs.end())
+                {
+                    methodName = *it;
+                    it++;
+                }
+            }
+            if (it != strs.end())
+            {
+                // if there is more levels past the method name, something went
+                // wrong, return not found
+                res.result(boost::beast::http::status::not_found);
+                res.end();
+                return;
+            }
+            if (interfaceName.empty())
+            {
+                crow::connections::systemBus->async_method_call(
+                    [&, processName,
+                     objectPath](const boost::system::error_code ec,
+                                 const std::string &introspect_xml) {
+                        if (ec)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "Introspect call failed with error: "
+                                << ec.message()
+                                << " on process: " << processName
+                                << " path: " << objectPath << "\n";
+                        }
+                        else
+                        {
+                            tinyxml2::XMLDocument doc;
+
+                            doc.Parse(introspect_xml.c_str());
+                            tinyxml2::XMLNode *pRoot =
+                                doc.FirstChildElement("node");
+                            if (pRoot == nullptr)
+                            {
+                                BMCWEB_LOG_ERROR
+                                    << "XML document failed to parse "
+                                    << processName << " " << objectPath << "\n";
+                                res.jsonValue = {{"status", "XML parse error"}};
+                                res.result(boost::beast::http::status::
+                                               internal_server_error);
+                            }
+                            else
+                            {
+                                nlohmann::json interfacesArray =
+                                    nlohmann::json::array();
+                                tinyxml2::XMLElement *interface =
+                                    pRoot->FirstChildElement("interface");
+
+                                while (interface != nullptr)
+                                {
+                                    std::string ifaceName =
+                                        interface->Attribute("name");
+                                    interfacesArray.push_back(
+                                        {{"name", ifaceName}});
+
+                                    interface = interface->NextSiblingElement(
+                                        "interface");
+                                }
+                                res.jsonValue = {
+                                    {"status", "ok"},
+                                    {"bus_name", processName},
+                                    {"interfaces", interfacesArray},
+                                    {"objectPath", objectPath}};
+                            }
+                        }
+                        res.end();
+                    },
+                    processName, objectPath,
+                    "org.freedesktop.DBus.Introspectable", "Introspect");
+            }
+            else
+            {
+                crow::connections::systemBus->async_method_call(
+                    [&, processName, objectPath,
+                     interface_name{std::move(interfaceName)}](
+                        const boost::system::error_code ec,
+                        const std::string &introspect_xml) {
+                        if (ec)
+                        {
+                            BMCWEB_LOG_ERROR
+                                << "Introspect call failed with error: "
+                                << ec.message()
+                                << " on process: " << processName
+                                << " path: " << objectPath << "\n";
+                        }
+                        else
+                        {
+                            tinyxml2::XMLDocument doc;
+
+                            doc.Parse(introspect_xml.c_str());
+                            tinyxml2::XMLNode *pRoot =
+                                doc.FirstChildElement("node");
+                            if (pRoot == nullptr)
+                            {
+                                BMCWEB_LOG_ERROR
+                                    << "XML document failed to parse "
+                                    << processName << " " << objectPath << "\n";
+                                res.result(boost::beast::http::status::
+                                               internal_server_error);
+                            }
+                            else
+                            {
+                                tinyxml2::XMLElement *node =
+                                    pRoot->FirstChildElement("node");
+
+                                // if we know we're the only call, build the
+                                // json directly
+                                nlohmann::json methodsArray =
+                                    nlohmann::json::array();
+                                nlohmann::json signalsArray =
+                                    nlohmann::json::array();
+                                tinyxml2::XMLElement *interface =
+                                    pRoot->FirstChildElement("interface");
+
+                                while (interface != nullptr)
+                                {
+                                    std::string ifaceName =
+                                        interface->Attribute("name");
+
+                                    if (ifaceName == interfaceName)
+                                    {
+                                        tinyxml2::XMLElement *methods =
+                                            interface->FirstChildElement(
+                                                "method");
+                                        while (methods != nullptr)
+                                        {
+                                            nlohmann::json argsArray =
+                                                nlohmann::json::array();
+                                            tinyxml2::XMLElement *arg =
+                                                methods->FirstChildElement(
+                                                    "arg");
+                                            while (arg != nullptr)
+                                            {
+                                                argsArray.push_back(
+                                                    {{"name",
+                                                      arg->Attribute("name")},
+                                                     {"type",
+                                                      arg->Attribute("type")},
+                                                     {"direction",
+                                                      arg->Attribute(
+                                                          "direction")}});
+                                                arg = arg->NextSiblingElement(
+                                                    "arg");
+                                            }
+                                            methodsArray.push_back(
+                                                {{"name",
+                                                  methods->Attribute("name")},
+                                                 {"uri",
+                                                  "/bus/system/" + processName +
+                                                      objectPath + "/" +
+                                                      interfaceName + "/" +
+                                                      methods->Attribute(
+                                                          "name")},
+                                                 {"args", argsArray}});
+                                            methods =
+                                                methods->NextSiblingElement(
+                                                    "method");
+                                        }
+                                        tinyxml2::XMLElement *signals =
+                                            interface->FirstChildElement(
+                                                "signal");
+                                        while (signals != nullptr)
+                                        {
+                                            nlohmann::json argsArray =
+                                                nlohmann::json::array();
+
+                                            tinyxml2::XMLElement *arg =
+                                                signals->FirstChildElement(
+                                                    "arg");
+                                            while (arg != nullptr)
+                                            {
+                                                std::string name =
+                                                    arg->Attribute("name");
+                                                std::string type =
+                                                    arg->Attribute("type");
+                                                argsArray.push_back({
+                                                    {"name", name},
+                                                    {"type", type},
+                                                });
+                                                arg = arg->NextSiblingElement(
+                                                    "arg");
+                                            }
+                                            signalsArray.push_back(
+                                                {{"name",
+                                                  signals->Attribute("name")},
+                                                 {"args", argsArray}});
+                                            signals =
+                                                signals->NextSiblingElement(
+                                                    "signal");
+                                        }
+
+                                        res.jsonValue = {
+                                            {"status", "ok"},
+                                            {"bus_name", processName},
+                                            {"interface", interfaceName},
+                                            {"methods", methodsArray},
+                                            {"objectPath", objectPath},
+                                            {"properties",
+                                             nlohmann::json::object()},
+                                            {"signals", signalsArray}};
+
+                                        break;
+                                    }
+
+                                    interface = interface->NextSiblingElement(
+                                        "interface");
+                                }
+                                if (interface == nullptr)
+                                {
+                                    // if we got to the end of the list and
+                                    // never found a match, throw 404
+                                    res.result(
+                                        boost::beast::http::status::not_found);
+                                }
+                            }
+                        }
+                        res.end();
+                    },
+                    processName, objectPath,
+                    "org.freedesktop.DBus.Introspectable", "Introspect");
+            }
+        });
+}
+} // namespace openbmc_mapper
+} // namespace crow
diff --git a/include/pam_authenticate.hpp b/include/pam_authenticate.hpp
index 65e4740..f51f9aa 100644
--- a/include/pam_authenticate.hpp
+++ b/include/pam_authenticate.hpp
@@ -1,72 +1,84 @@
 #pragma once
 
 #include <security/pam_appl.h>
+
+#include <boost/utility/string_view.hpp>
 #include <cstring>
 #include <memory>
-#include <boost/utility/string_view.hpp>
 
 // function used to get user input
 inline int pamFunctionConversation(int numMsg, const struct pam_message** msg,
-                                   struct pam_response** resp,
-                                   void* appdataPtr) {
-  if (appdataPtr == nullptr) {
-    return PAM_AUTH_ERR;
-  }
-  auto* pass = reinterpret_cast<char*>(
-      malloc(std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1));
-  std::strcpy(pass, reinterpret_cast<char*>(appdataPtr));
+                                   struct pam_response** resp, void* appdataPtr)
+{
+    if (appdataPtr == nullptr)
+    {
+        return PAM_AUTH_ERR;
+    }
+    auto* pass = reinterpret_cast<char*>(
+        malloc(std::strlen(reinterpret_cast<char*>(appdataPtr)) + 1));
+    std::strcpy(pass, reinterpret_cast<char*>(appdataPtr));
 
-  *resp = reinterpret_cast<pam_response*>(
-      calloc(numMsg, sizeof(struct pam_response)));
+    *resp = reinterpret_cast<pam_response*>(
+        calloc(numMsg, sizeof(struct pam_response)));
 
-  for (int i = 0; i < numMsg; ++i) {
-    /* Ignore all PAM messages except prompting for hidden input */
-    if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF) {
-      continue;
+    for (int i = 0; i < numMsg; ++i)
+    {
+        /* Ignore all PAM messages except prompting for hidden input */
+        if (msg[i]->msg_style != PAM_PROMPT_ECHO_OFF)
+        {
+            continue;
+        }
+
+        /* Assume PAM is only prompting for the password as hidden input */
+        resp[i]->resp = pass;
     }
 
-    /* Assume PAM is only prompting for the password as hidden input */
-    resp[i]->resp = pass;
-  }
-
-  return PAM_SUCCESS;
+    return PAM_SUCCESS;
 }
 
 inline bool pamAuthenticateUser(const boost::string_view username,
-                                const boost::string_view password) {
-  std::string userStr(username);
-  std::string passStr(password);
-  const struct pam_conv localConversation = {
-      pamFunctionConversation, const_cast<char*>(passStr.c_str())};
-  pam_handle_t* localAuthHandle = NULL;  // this gets set by pam_start
+                                const boost::string_view password)
+{
+    std::string userStr(username);
+    std::string passStr(password);
+    const struct pam_conv localConversation = {
+        pamFunctionConversation, const_cast<char*>(passStr.c_str())};
+    pam_handle_t* localAuthHandle = NULL; // this gets set by pam_start
 
-  if (pam_start("webserver", userStr.c_str(), &localConversation,
-                &localAuthHandle) != PAM_SUCCESS) {
-    return false;
-  }
-  int retval =
-      pam_authenticate(localAuthHandle, PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
-
-  if (retval != PAM_SUCCESS) {
-    if (retval == PAM_AUTH_ERR) {
-      // printf("Authentication failure.\n");
-    } else {
-      // printf("pam_authenticate returned %d\n", retval);
+    if (pam_start("webserver", userStr.c_str(), &localConversation,
+                  &localAuthHandle) != PAM_SUCCESS)
+    {
+        return false;
     }
-    pam_end(localAuthHandle, PAM_SUCCESS);
-    return false;
-  }
+    int retval = pam_authenticate(localAuthHandle,
+                                  PAM_SILENT | PAM_DISALLOW_NULL_AUTHTOK);
 
-  /* check that the account is healthy */
-  if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
-      PAM_SUCCESS) {
-    pam_end(localAuthHandle, PAM_SUCCESS);
-    return false;
-  }
+    if (retval != PAM_SUCCESS)
+    {
+        if (retval == PAM_AUTH_ERR)
+        {
+            // printf("Authentication failure.\n");
+        }
+        else
+        {
+            // printf("pam_authenticate returned %d\n", retval);
+        }
+        pam_end(localAuthHandle, PAM_SUCCESS);
+        return false;
+    }
 
-  if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS) {
-    return false;
-  }
+    /* check that the account is healthy */
+    if (pam_acct_mgmt(localAuthHandle, PAM_DISALLOW_NULL_AUTHTOK) !=
+        PAM_SUCCESS)
+    {
+        pam_end(localAuthHandle, PAM_SUCCESS);
+        return false;
+    }
 
-  return true;
+    if (pam_end(localAuthHandle, PAM_SUCCESS) != PAM_SUCCESS)
+    {
+        return false;
+    }
+
+    return true;
 }
diff --git a/include/persistent_data_middleware.hpp b/include/persistent_data_middleware.hpp
index 706f6f4..b384f02 100644
--- a/include/persistent_data_middleware.hpp
+++ b/include/persistent_data_middleware.hpp
@@ -1,121 +1,165 @@
 #pragma once
 
-#include <nlohmann/json.hpp>
-#include <pam_authenticate.hpp>
-#include <sessions.hpp>
-#include <webassets.hpp>
-#include <random>
 #include <crow/app.h>
 #include <crow/http_request.h>
 #include <crow/http_response.h>
+
 #include <boost/container/flat_map.hpp>
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_generators.hpp>
 #include <boost/uuid/uuid_io.hpp>
+#include <nlohmann/json.hpp>
+#include <pam_authenticate.hpp>
+#include <random>
+#include <sessions.hpp>
+#include <webassets.hpp>
 
-namespace crow {
+namespace crow
+{
 
-namespace persistent_data {
+namespace persistent_data
+{
 
-class Middleware {
-  // todo(ed) should read this from a fixed location somewhere, not CWD
-  static constexpr const char* filename = "bmcweb_persistent_data.json";
-  int jsonRevision = 1;
+class Middleware
+{
+    // todo(ed) should read this from a fixed location somewhere, not CWD
+    static constexpr const char* filename = "bmcweb_persistent_data.json";
+    int jsonRevision = 1;
 
- public:
-  struct Context {};
+  public:
+    struct Context
+    {
+    };
 
-  Middleware() { readData(); }
-
-  ~Middleware() {
-    if (persistent_data::SessionStore::getInstance().needsWrite()) {
-      writeData();
+    Middleware()
+    {
+        readData();
     }
-  }
 
-  void beforeHandle(crow::Request& req, Response& res, Context& ctx) {}
-
-  void afterHandle(Request& req, Response& res, Context& ctx) {}
-
-  // TODO(ed) this should really use protobuf, or some other serialization
-  // library, but adding another dependency is somewhat outside the scope of
-  // this application for the moment
-  void readData() {
-    std::ifstream persistentFile(filename);
-    int fileRevision = 0;
-    if (persistentFile.is_open()) {
-      // call with exceptions disabled
-      auto data = nlohmann::json::parse(persistentFile, nullptr, false);
-      if (data.is_discarded()) {
-        BMCWEB_LOG_ERROR << "Error parsing persistent data in json file.";
-      } else {
-        for (const auto& item : data.items()) {
-          if (item.key() == "revision") {
-            fileRevision = 0;
-
-            const uint64_t* uintPtr = item.value().get_ptr<const uint64_t*>();
-            if (uintPtr == nullptr) {
-              BMCWEB_LOG_ERROR << "Failed to read revision flag";
-            } else {
-              fileRevision = *uintPtr;
-            }
-          } else if (item.key() == "system_uuid") {
-            const std::string* jSystemUuid =
-                item.value().get_ptr<const std::string*>();
-            if (jSystemUuid != nullptr) {
-              systemUuid = *jSystemUuid;
-            }
-          } else if (item.key() == "sessions") {
-            for (const auto& elem : item.value()) {
-              std::shared_ptr<UserSession> newSession =
-                  UserSession::fromJson(elem);
-
-              if (newSession == nullptr) {
-                BMCWEB_LOG_ERROR
-                    << "Problem reading session from persistent store";
-                continue;
-              }
-
-              BMCWEB_LOG_DEBUG << "Restored session: " << newSession->csrfToken
-                               << " " << newSession->uniqueId << " "
-                               << newSession->sessionToken;
-              SessionStore::getInstance().authTokens.emplace(
-                  newSession->sessionToken, newSession);
-            }
-          } else {
-            // Do nothing in the case of extra fields.  We may have cases where
-            // fields are added in the future, and we want to at least attempt
-            // to gracefully support downgrades in that case, even if we don't
-            // officially support it
-          }
+    ~Middleware()
+    {
+        if (persistent_data::SessionStore::getInstance().needsWrite())
+        {
+            writeData();
         }
-      }
     }
-    bool needWrite = false;
 
-    if (systemUuid.empty()) {
-      systemUuid = boost::uuids::to_string(boost::uuids::random_generator()());
-      needWrite = true;
+    void beforeHandle(crow::Request& req, Response& res, Context& ctx)
+    {
     }
-    if (fileRevision < jsonRevision) {
-      needWrite = true;
-    }
-    // write revision changes or system uuid changes immediately
-    if (needWrite) {
-      writeData();
-    }
-  }
 
-  void writeData() {
-    std::ofstream persistentFile(filename);
-    nlohmann::json data{{"sessions", SessionStore::getInstance().authTokens},
-                        {"system_uuid", systemUuid},
-                        {"revision", jsonRevision}};
-    persistentFile << data;
-  }
+    void afterHandle(Request& req, Response& res, Context& ctx)
+    {
+    }
 
-  std::string systemUuid{""};
+    // TODO(ed) this should really use protobuf, or some other serialization
+    // library, but adding another dependency is somewhat outside the scope of
+    // this application for the moment
+    void readData()
+    {
+        std::ifstream persistentFile(filename);
+        int fileRevision = 0;
+        if (persistentFile.is_open())
+        {
+            // call with exceptions disabled
+            auto data = nlohmann::json::parse(persistentFile, nullptr, false);
+            if (data.is_discarded())
+            {
+                BMCWEB_LOG_ERROR
+                    << "Error parsing persistent data in json file.";
+            }
+            else
+            {
+                for (const auto& item : data.items())
+                {
+                    if (item.key() == "revision")
+                    {
+                        fileRevision = 0;
+
+                        const uint64_t* uintPtr =
+                            item.value().get_ptr<const uint64_t*>();
+                        if (uintPtr == nullptr)
+                        {
+                            BMCWEB_LOG_ERROR << "Failed to read revision flag";
+                        }
+                        else
+                        {
+                            fileRevision = *uintPtr;
+                        }
+                    }
+                    else if (item.key() == "system_uuid")
+                    {
+                        const std::string* jSystemUuid =
+                            item.value().get_ptr<const std::string*>();
+                        if (jSystemUuid != nullptr)
+                        {
+                            systemUuid = *jSystemUuid;
+                        }
+                    }
+                    else if (item.key() == "sessions")
+                    {
+                        for (const auto& elem : item.value())
+                        {
+                            std::shared_ptr<UserSession> newSession =
+                                UserSession::fromJson(elem);
+
+                            if (newSession == nullptr)
+                            {
+                                BMCWEB_LOG_ERROR << "Problem reading session "
+                                                    "from persistent store";
+                                continue;
+                            }
+
+                            BMCWEB_LOG_DEBUG
+                                << "Restored session: " << newSession->csrfToken
+                                << " " << newSession->uniqueId << " "
+                                << newSession->sessionToken;
+                            SessionStore::getInstance().authTokens.emplace(
+                                newSession->sessionToken, newSession);
+                        }
+                    }
+                    else
+                    {
+                        // Do nothing in the case of extra fields.  We may have
+                        // cases where fields are added in the future, and we
+                        // want to at least attempt to gracefully support
+                        // downgrades in that case, even if we don't officially
+                        // support it
+                    }
+                }
+            }
+        }
+        bool needWrite = false;
+
+        if (systemUuid.empty())
+        {
+            systemUuid =
+                boost::uuids::to_string(boost::uuids::random_generator()());
+            needWrite = true;
+        }
+        if (fileRevision < jsonRevision)
+        {
+            needWrite = true;
+        }
+        // write revision changes or system uuid changes immediately
+        if (needWrite)
+        {
+            writeData();
+        }
+    }
+
+    void writeData()
+    {
+        std::ofstream persistentFile(filename);
+        nlohmann::json data{
+            {"sessions", SessionStore::getInstance().authTokens},
+            {"system_uuid", systemUuid},
+            {"revision", jsonRevision}};
+        persistentFile << data;
+    }
+
+    std::string systemUuid{""};
 };
 
-}  // namespace persistent_data
-}  // namespace crow
+} // namespace persistent_data
+} // namespace crow
diff --git a/include/redfish_v1.hpp b/include/redfish_v1.hpp
index b81aa54..13e1838 100644
--- a/include/redfish_v1.hpp
+++ b/include/redfish_v1.hpp
@@ -1,15 +1,18 @@
 #pragma once
 
+#include <crow/app.h>
+
+#include <boost/algorithm/string.hpp>
 #include <dbus_singleton.hpp>
-#include <persistent_data_middleware.hpp>
-#include <token_authorization_middleware.hpp>
 #include <fstream>
+#include <persistent_data_middleware.hpp>
 #include <streambuf>
 #include <string>
-#include <crow/app.h>
-#include <boost/algorithm/string.hpp>
-namespace crow {
-namespace redfish {
+#include <token_authorization_middleware.hpp>
+namespace crow
+{
+namespace redfish
+{
 
 using ManagedObjectType = std::vector<std::pair<
     sdbusplus::message::object_path,
@@ -17,108 +20,130 @@
         std::string, boost::container::flat_map<
                          std::string, sdbusplus::message::variant<bool>>>>>;
 
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...>& app) {
-  BMCWEB_ROUTE(app, "/redfish/")
-      .methods("GET"_method)([](const crow::Request& req, crow::Response& res) {
-        res.jsonValue = {{"v1", "/redfish/v1/"}};
-        res.end();
-      });
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app)
+{
+    BMCWEB_ROUTE(app, "/redfish/")
+        .methods("GET"_method)(
+            [](const crow::Request& req, crow::Response& res) {
+                res.jsonValue = {{"v1", "/redfish/v1/"}};
+                res.end();
+            });
 
-  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/")
-      .methods(
-          "GET"_method)([&](const crow::Request& req, crow::Response& res) {
-        crow::connections::systemBus->async_method_call(
-            [&](const boost::system::error_code ec,
-                const ManagedObjectType& users) {
-              if (ec) {
-                res.result(boost::beast::http::status::internal_server_error);
-              } else {
-                res.jsonValue = {
-                    {"@odata.context",
-                     "/redfish/v1/"
-                     "$metadata#ManagerAccountCollection."
-                     "ManagerAccountCollection"},
-                    {"@odata.id", "/redfish/v1/AccountService/Accounts"},
-                    {"@odata.type",
-                     "#ManagerAccountCollection.ManagerAccountCollection"},
-                    {"Name", "Accounts Collection"},
-                    {"Description", "BMC User Accounts"},
-                    {"Members@odata.count", users.size()}};
-                nlohmann::json memberArray = nlohmann::json::array();
-                int userIndex = 0;
-                for (auto& user : users) {
-                  const std::string& path =
-                      static_cast<const std::string&>(user.first);
-                  std::size_t lastIndex = path.rfind("/");
-                  if (lastIndex == std::string::npos) {
-                    lastIndex = 0;
-                  } else {
-                    lastIndex += 1;
-                  }
-                  memberArray.push_back(
-                      {{"@odata.id", "/redfish/v1/AccountService/Accounts/" +
-                                         path.substr(lastIndex)}});
-                }
-                res.jsonValue["Members"] = memberArray;
-              }
-              res.end();
-            },
-            "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
-            "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
-      });
+    BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/")
+        .methods(
+            "GET"_method)([&](const crow::Request& req, crow::Response& res) {
+            crow::connections::systemBus->async_method_call(
+                [&](const boost::system::error_code ec,
+                    const ManagedObjectType& users) {
+                    if (ec)
+                    {
+                        res.result(
+                            boost::beast::http::status::internal_server_error);
+                    }
+                    else
+                    {
+                        res.jsonValue = {
+                            {"@odata.context",
+                             "/redfish/v1/"
+                             "$metadata#ManagerAccountCollection."
+                             "ManagerAccountCollection"},
+                            {"@odata.id",
+                             "/redfish/v1/AccountService/Accounts"},
+                            {"@odata.type", "#ManagerAccountCollection."
+                                            "ManagerAccountCollection"},
+                            {"Name", "Accounts Collection"},
+                            {"Description", "BMC User Accounts"},
+                            {"Members@odata.count", users.size()}};
+                        nlohmann::json memberArray = nlohmann::json::array();
+                        int userIndex = 0;
+                        for (auto& user : users)
+                        {
+                            const std::string& path =
+                                static_cast<const std::string&>(user.first);
+                            std::size_t lastIndex = path.rfind("/");
+                            if (lastIndex == std::string::npos)
+                            {
+                                lastIndex = 0;
+                            }
+                            else
+                            {
+                                lastIndex += 1;
+                            }
+                            memberArray.push_back(
+                                {{"@odata.id",
+                                  "/redfish/v1/AccountService/Accounts/" +
+                                      path.substr(lastIndex)}});
+                        }
+                        res.jsonValue["Members"] = memberArray;
+                    }
+                    res.end();
+                },
+                "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
+                "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+        });
 
-  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
-      .methods("GET"_method)([](const crow::Request& req, crow::Response& res,
-                                const std::string& account_name) {
-
-        crow::connections::systemBus->async_method_call(
-            [&, accountName{std::move(account_name)} ](
-                const boost::system::error_code ec,
-                const ManagedObjectType& users) {
-              if (ec) {
-                res.result(boost::beast::http::status::internal_server_error);
-              } else {
-                for (auto& user : users) {
-                  const std::string& path =
-                      static_cast<const std::string&>(user.first);
-                  std::size_t lastIndex = path.rfind("/");
-                  if (lastIndex == std::string::npos) {
-                    lastIndex = 0;
-                  } else {
-                    lastIndex += 1;
-                  }
-                  if (path.substr(lastIndex) == accountName) {
-                    res.jsonValue = {
-                        {"@odata.context",
-                         "/redfish/v1/$metadata#ManagerAccount.ManagerAccount"},
-                        {"@odata.id", "/redfish/v1/AccountService/Accounts/1"},
-                        {"@odata.type",
-                         "#ManagerAccount.v1_0_3.ManagerAccount"},
-                        {"Id", "1"},
-                        {"Name", "User Account"},
-                        {"Description", "User Account"},
-                        {"Enabled", false},
-                        {"Password", nullptr},
-                        {"UserName", accountName},
-                        {"RoleId", "Administrator"},
-                        {"Links",
-                         {{"Role",
-                           {{"@odata.id",
-                             "/redfish/v1/AccountService/Roles/"
-                             "Administrator"}}}}}};
-                    break;
-                  }
-                }
-                if (res.jsonValue.is_null()) {
-                  res.result(boost::beast::http::status::not_found);
-                }
-              }
-              res.end();
-            },
-            "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
-            "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
-      });
+    BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/<str>/")
+        .methods("GET"_method)([](const crow::Request& req, crow::Response& res,
+                                  const std::string& account_name) {
+            crow::connections::systemBus->async_method_call(
+                [&, accountName{std::move(account_name)}](
+                    const boost::system::error_code ec,
+                    const ManagedObjectType& users) {
+                    if (ec)
+                    {
+                        res.result(
+                            boost::beast::http::status::internal_server_error);
+                    }
+                    else
+                    {
+                        for (auto& user : users)
+                        {
+                            const std::string& path =
+                                static_cast<const std::string&>(user.first);
+                            std::size_t lastIndex = path.rfind("/");
+                            if (lastIndex == std::string::npos)
+                            {
+                                lastIndex = 0;
+                            }
+                            else
+                            {
+                                lastIndex += 1;
+                            }
+                            if (path.substr(lastIndex) == accountName)
+                            {
+                                res.jsonValue = {
+                                    {"@odata.context",
+                                     "/redfish/v1/"
+                                     "$metadata#ManagerAccount.ManagerAccount"},
+                                    {"@odata.id",
+                                     "/redfish/v1/AccountService/Accounts/1"},
+                                    {"@odata.type",
+                                     "#ManagerAccount.v1_0_3.ManagerAccount"},
+                                    {"Id", "1"},
+                                    {"Name", "User Account"},
+                                    {"Description", "User Account"},
+                                    {"Enabled", false},
+                                    {"Password", nullptr},
+                                    {"UserName", accountName},
+                                    {"RoleId", "Administrator"},
+                                    {"Links",
+                                     {{"Role",
+                                       {{"@odata.id",
+                                         "/redfish/v1/AccountService/Roles/"
+                                         "Administrator"}}}}}};
+                                break;
+                            }
+                        }
+                        if (res.jsonValue.is_null())
+                        {
+                            res.result(boost::beast::http::status::not_found);
+                        }
+                    }
+                    res.end();
+                },
+                "xyz.openbmc_project.User.Manager", "/xyz/openbmc_project/user",
+                "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
+        });
 }
-}  // namespace redfish
-}  // namespace crow
+} // namespace redfish
+} // namespace crow
diff --git a/include/security_headers_middleware.hpp b/include/security_headers_middleware.hpp
index 750f87b..561fd81 100644
--- a/include/security_headers_middleware.hpp
+++ b/include/security_headers_middleware.hpp
@@ -3,7 +3,8 @@
 #include <crow/http_request.h>
 #include <crow/http_response.h>
 
-namespace crow {
+namespace crow
+{
 static const char* strictTransportSecurityKey = "Strict-Transport-Security";
 static const char* strictTransportSecurityValue =
     "max-age=31536000; includeSubdomains; preload";
@@ -26,40 +27,46 @@
 static const char* cacheControlKey = "Cache-Control";
 static const char* cacheControlValue = "no-Store,no-Cache";
 
-struct SecurityHeadersMiddleware {
-  struct Context {};
+struct SecurityHeadersMiddleware
+{
+    struct Context
+    {
+    };
 
-  void beforeHandle(crow::Request& req, Response& res, Context& ctx) {
+    void beforeHandle(crow::Request& req, Response& res, Context& ctx)
+    {
 #ifdef BMCWEB_INSECURE_DISABLE_XSS_PREVENTION
-    if ("OPTIONS"_method == req.method()) {
-      res.end();
+        if ("OPTIONS"_method == req.method())
+        {
+            res.end();
+        }
+#endif
     }
-#endif
-  }
 
-  void afterHandle(Request& req, Response& res, Context& ctx) {
-    /*
-     TODO(ed) these should really check content types.  for example,
-     X-UA-Compatible header doesn't make sense when retrieving a JSON or
-     javascript file.  It doesn't hurt anything, it's just ugly.
-     */
-    res.addHeader(strictTransportSecurityKey, strictTransportSecurityValue);
-    res.addHeader(uaCompatabilityKey, uaCompatabilityValue);
-    res.addHeader(xframeKey, xframeValue);
-    res.addHeader(xssKey, xssValue);
-    res.addHeader(contentSecurityKey, contentSecurityValue);
-    res.addHeader(pragmaKey, pragmaValue);
-    res.addHeader(cacheControlKey, cacheControlValue);
+    void afterHandle(Request& req, Response& res, Context& ctx)
+    {
+        /*
+         TODO(ed) these should really check content types.  for example,
+         X-UA-Compatible header doesn't make sense when retrieving a JSON or
+         javascript file.  It doesn't hurt anything, it's just ugly.
+         */
+        res.addHeader(strictTransportSecurityKey, strictTransportSecurityValue);
+        res.addHeader(uaCompatabilityKey, uaCompatabilityValue);
+        res.addHeader(xframeKey, xframeValue);
+        res.addHeader(xssKey, xssValue);
+        res.addHeader(contentSecurityKey, contentSecurityValue);
+        res.addHeader(pragmaKey, pragmaValue);
+        res.addHeader(cacheControlKey, cacheControlValue);
 
 #ifdef BMCWEB_INSECURE_DISABLE_XSS_PREVENTION
 
-    res.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
-    res.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH");
-    res.addHeader("Access-Control-Allow-Credentials", "true");
-    res.addHeader("Access-Control-Allow-Headers",
-                  "Origin, Content-Type, Accept, Cookie, X-XSRF-TOKEN");
+        res.addHeader("Access-Control-Allow-Origin", "http://localhost:8080");
+        res.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH");
+        res.addHeader("Access-Control-Allow-Credentials", "true");
+        res.addHeader("Access-Control-Allow-Headers",
+                      "Origin, Content-Type, Accept, Cookie, X-XSRF-TOKEN");
 
 #endif
-  }
+    }
 };
-}  // namespace crow
+} // namespace crow
diff --git a/include/sessions.hpp b/include/sessions.hpp
index f549fde..510f566 100644
--- a/include/sessions.hpp
+++ b/include/sessions.hpp
@@ -1,232 +1,284 @@
 #pragma once
 
-#include <nlohmann/json.hpp>
-#include <pam_authenticate.hpp>
-#include <webassets.hpp>
-#include <random>
 #include <crow/app.h>
 #include <crow/http_request.h>
 #include <crow/http_response.h>
+
 #include <boost/container/flat_map.hpp>
 #include <boost/uuid/uuid.hpp>
 #include <boost/uuid/uuid_generators.hpp>
 #include <boost/uuid/uuid_io.hpp>
+#include <nlohmann/json.hpp>
+#include <pam_authenticate.hpp>
+#include <random>
+#include <webassets.hpp>
 
-namespace crow {
+namespace crow
+{
 
-namespace persistent_data {
+namespace persistent_data
+{
 
-enum class PersistenceType {
-  TIMEOUT,        // User session times out after a predetermined amount of time
-  SINGLE_REQUEST  // User times out once this request is completed.
+enum class PersistenceType
+{
+    TIMEOUT, // User session times out after a predetermined amount of time
+    SINGLE_REQUEST // User times out once this request is completed.
 };
 
-struct UserSession {
-  std::string uniqueId;
-  std::string sessionToken;
-  std::string username;
-  std::string csrfToken;
-  std::chrono::time_point<std::chrono::steady_clock> lastUpdated;
-  PersistenceType persistence;
+struct UserSession
+{
+    std::string uniqueId;
+    std::string sessionToken;
+    std::string username;
+    std::string csrfToken;
+    std::chrono::time_point<std::chrono::steady_clock> lastUpdated;
+    PersistenceType persistence;
 
-  /**
-   * @brief Fills object with data from UserSession's JSON representation
-   *
-   * This replaces nlohmann's from_json to ensure no-throw approach
-   *
-   * @param[in] j   JSON object from which data should be loaded
-   *
-   * @return a shared pointer if data has been loaded properly, nullptr
-   * otherwise
-   */
-  static std::shared_ptr<UserSession> fromJson(const nlohmann::json& j) {
-    std::shared_ptr<UserSession> userSession = std::make_shared<UserSession>();
-    for (const auto& element : j.items()) {
-      const std::string* thisValue =
-          element.value().get_ptr<const std::string*>();
-      if (thisValue == nullptr) {
-        BMCWEB_LOG_ERROR << "Error reading persistent store.  Property "
-                         << element.key() << " was not of type string";
-        return nullptr;
-      }
-      if (element.key() == "unique_id") {
-        userSession->uniqueId = *thisValue;
-      } else if (element.key() == "session_token") {
-        userSession->sessionToken = *thisValue;
-      } else if (element.key() == "csrf_token") {
-        userSession->csrfToken = *thisValue;
-      } else if (element.key() == "username") {
-        userSession->username = *thisValue;
-      } else {
-        BMCWEB_LOG_ERROR << "Got unexpected property reading persistent file: "
-                         << element.key();
-        return nullptr;
-      }
+    /**
+     * @brief Fills object with data from UserSession's JSON representation
+     *
+     * This replaces nlohmann's from_json to ensure no-throw approach
+     *
+     * @param[in] j   JSON object from which data should be loaded
+     *
+     * @return a shared pointer if data has been loaded properly, nullptr
+     * otherwise
+     */
+    static std::shared_ptr<UserSession> fromJson(const nlohmann::json& j)
+    {
+        std::shared_ptr<UserSession> userSession =
+            std::make_shared<UserSession>();
+        for (const auto& element : j.items())
+        {
+            const std::string* thisValue =
+                element.value().get_ptr<const std::string*>();
+            if (thisValue == nullptr)
+            {
+                BMCWEB_LOG_ERROR << "Error reading persistent store.  Property "
+                                 << element.key() << " was not of type string";
+                return nullptr;
+            }
+            if (element.key() == "unique_id")
+            {
+                userSession->uniqueId = *thisValue;
+            }
+            else if (element.key() == "session_token")
+            {
+                userSession->sessionToken = *thisValue;
+            }
+            else if (element.key() == "csrf_token")
+            {
+                userSession->csrfToken = *thisValue;
+            }
+            else if (element.key() == "username")
+            {
+                userSession->username = *thisValue;
+            }
+            else
+            {
+                BMCWEB_LOG_ERROR
+                    << "Got unexpected property reading persistent file: "
+                    << element.key();
+                return nullptr;
+            }
+        }
+
+        // For now, sessions that were persisted through a reboot get their idle
+        // timer reset.  This could probably be overcome with a better
+        // understanding of wall clock time and steady timer time, possibly
+        // persisting values with wall clock time instead of steady timer, but
+        // the tradeoffs of all the corner cases involved are non-trivial, so
+        // this is done temporarily
+        userSession->lastUpdated = std::chrono::steady_clock::now();
+        userSession->persistence = PersistenceType::TIMEOUT;
+
+        return userSession;
     }
-
-    // For now, sessions that were persisted through a reboot get their idle
-    // timer reset.  This could probably be overcome with a better understanding
-    // of wall clock time and steady timer time, possibly persisting values with
-    // wall clock time instead of steady timer, but the tradeoffs of all the
-    // corner cases involved are non-trivial, so this is done temporarily
-    userSession->lastUpdated = std::chrono::steady_clock::now();
-    userSession->persistence = PersistenceType::TIMEOUT;
-
-    return userSession;
-  }
 };
 
 class Middleware;
 
-class SessionStore {
- public:
-  std::shared_ptr<UserSession> generateUserSession(
-      const boost::string_view username,
-      PersistenceType persistence = PersistenceType::TIMEOUT) {
-    // TODO(ed) find a secure way to not generate session identifiers if
-    // persistence is set to SINGLE_REQUEST
-    static constexpr std::array<char, 62> alphanum = {
-        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'b', 'C',
-        'D', 'E', 'F', 'g', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
-        'Q', 'r', 'S', 'T', 'U', 'v', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
-        'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
-        'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
+class SessionStore
+{
+  public:
+    std::shared_ptr<UserSession> generateUserSession(
+        const boost::string_view username,
+        PersistenceType persistence = PersistenceType::TIMEOUT)
+    {
+        // TODO(ed) find a secure way to not generate session identifiers if
+        // persistence is set to SINGLE_REQUEST
+        static constexpr std::array<char, 62> alphanum = {
+            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'b', 'C',
+            'D', 'E', 'F', 'g', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+            'Q', 'r', 'S', 'T', 'U', 'v', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
+            'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+            'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
 
-    // entropy: 30 characters, 62 possibilities.  log2(62^30) = 178 bits of
-    // entropy.  OWASP recommends at least 60
-    // https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Entropy
-    std::string sessionToken;
-    sessionToken.resize(20, '0');
-    std::uniform_int_distribution<int> dist(0, alphanum.size() - 1);
-    for (int i = 0; i < sessionToken.size(); ++i) {
-      sessionToken[i] = alphanum[dist(rd)];
-    }
-    // Only need csrf tokens for cookie based auth, token doesn't matter
-    std::string csrfToken;
-    csrfToken.resize(20, '0');
-    for (int i = 0; i < csrfToken.size(); ++i) {
-      csrfToken[i] = alphanum[dist(rd)];
-    }
-
-    std::string uniqueId;
-    uniqueId.resize(10, '0');
-    for (int i = 0; i < uniqueId.size(); ++i) {
-      uniqueId[i] = alphanum[dist(rd)];
-    }
-    auto session = std::make_shared<UserSession>(
-        UserSession{uniqueId, sessionToken, std::string(username), csrfToken,
-                    std::chrono::steady_clock::now(), persistence});
-    auto it = authTokens.emplace(std::make_pair(sessionToken, session));
-    // Only need to write to disk if session isn't about to be destroyed.
-    needWrite = persistence == PersistenceType::TIMEOUT;
-    return it.first->second;
-  }
-
-  std::shared_ptr<UserSession> loginSessionByToken(
-      const boost::string_view token) {
-    applySessionTimeouts();
-    auto sessionIt = authTokens.find(std::string(token));
-    if (sessionIt == authTokens.end()) {
-      return nullptr;
-    }
-    std::shared_ptr<UserSession> userSession = sessionIt->second;
-    userSession->lastUpdated = std::chrono::steady_clock::now();
-    return userSession;
-  }
-
-  std::shared_ptr<UserSession> getSessionByUid(const boost::string_view uid) {
-    applySessionTimeouts();
-    // TODO(Ed) this is inefficient
-    auto sessionIt = authTokens.begin();
-    while (sessionIt != authTokens.end()) {
-      if (sessionIt->second->uniqueId == uid) {
-        return sessionIt->second;
-      }
-      sessionIt++;
-    }
-    return nullptr;
-  }
-
-  void removeSession(std::shared_ptr<UserSession> session) {
-    authTokens.erase(session->sessionToken);
-    needWrite = true;
-  }
-
-  std::vector<const std::string*> getUniqueIds(
-      bool getAll = true,
-      const PersistenceType& type = PersistenceType::SINGLE_REQUEST) {
-    applySessionTimeouts();
-
-    std::vector<const std::string*> ret;
-    ret.reserve(authTokens.size());
-    for (auto& session : authTokens) {
-      if (getAll || type == session.second->persistence) {
-        ret.push_back(&session.second->uniqueId);
-      }
-    }
-    return ret;
-  }
-
-  bool needsWrite() { return needWrite; }
-  int getTimeoutInSeconds() const {
-    return std::chrono::seconds(timeoutInMinutes).count();
-  };
-
-  // Persistent data middleware needs to be able to serialize our authTokens
-  // structure, which is private
-  friend Middleware;
-
-  static SessionStore& getInstance() {
-    static SessionStore sessionStore;
-    return sessionStore;
-  }
-
-  SessionStore(const SessionStore&) = delete;
-  SessionStore& operator=(const SessionStore&) = delete;
-
- private:
-  SessionStore() : timeoutInMinutes(60) {}
-
-  void applySessionTimeouts() {
-    auto timeNow = std::chrono::steady_clock::now();
-    if (timeNow - lastTimeoutUpdate > std::chrono::minutes(1)) {
-      lastTimeoutUpdate = timeNow;
-      auto authTokensIt = authTokens.begin();
-      while (authTokensIt != authTokens.end()) {
-        if (timeNow - authTokensIt->second->lastUpdated >= timeoutInMinutes) {
-          authTokensIt = authTokens.erase(authTokensIt);
-          needWrite = true;
-        } else {
-          authTokensIt++;
+        // entropy: 30 characters, 62 possibilities.  log2(62^30) = 178 bits of
+        // entropy.  OWASP recommends at least 60
+        // https://www.owasp.org/index.php/Session_Management_Cheat_Sheet#Session_ID_Entropy
+        std::string sessionToken;
+        sessionToken.resize(20, '0');
+        std::uniform_int_distribution<int> dist(0, alphanum.size() - 1);
+        for (int i = 0; i < sessionToken.size(); ++i)
+        {
+            sessionToken[i] = alphanum[dist(rd)];
         }
-      }
+        // Only need csrf tokens for cookie based auth, token doesn't matter
+        std::string csrfToken;
+        csrfToken.resize(20, '0');
+        for (int i = 0; i < csrfToken.size(); ++i)
+        {
+            csrfToken[i] = alphanum[dist(rd)];
+        }
+
+        std::string uniqueId;
+        uniqueId.resize(10, '0');
+        for (int i = 0; i < uniqueId.size(); ++i)
+        {
+            uniqueId[i] = alphanum[dist(rd)];
+        }
+        auto session = std::make_shared<UserSession>(UserSession{
+            uniqueId, sessionToken, std::string(username), csrfToken,
+            std::chrono::steady_clock::now(), persistence});
+        auto it = authTokens.emplace(std::make_pair(sessionToken, session));
+        // Only need to write to disk if session isn't about to be destroyed.
+        needWrite = persistence == PersistenceType::TIMEOUT;
+        return it.first->second;
     }
-  }
-  std::chrono::time_point<std::chrono::steady_clock> lastTimeoutUpdate;
-  boost::container::flat_map<std::string, std::shared_ptr<UserSession>>
-      authTokens;
-  std::random_device rd;
-  bool needWrite{false};
-  std::chrono::minutes timeoutInMinutes;
+
+    std::shared_ptr<UserSession>
+        loginSessionByToken(const boost::string_view token)
+    {
+        applySessionTimeouts();
+        auto sessionIt = authTokens.find(std::string(token));
+        if (sessionIt == authTokens.end())
+        {
+            return nullptr;
+        }
+        std::shared_ptr<UserSession> userSession = sessionIt->second;
+        userSession->lastUpdated = std::chrono::steady_clock::now();
+        return userSession;
+    }
+
+    std::shared_ptr<UserSession> getSessionByUid(const boost::string_view uid)
+    {
+        applySessionTimeouts();
+        // TODO(Ed) this is inefficient
+        auto sessionIt = authTokens.begin();
+        while (sessionIt != authTokens.end())
+        {
+            if (sessionIt->second->uniqueId == uid)
+            {
+                return sessionIt->second;
+            }
+            sessionIt++;
+        }
+        return nullptr;
+    }
+
+    void removeSession(std::shared_ptr<UserSession> session)
+    {
+        authTokens.erase(session->sessionToken);
+        needWrite = true;
+    }
+
+    std::vector<const std::string*> getUniqueIds(
+        bool getAll = true,
+        const PersistenceType& type = PersistenceType::SINGLE_REQUEST)
+    {
+        applySessionTimeouts();
+
+        std::vector<const std::string*> ret;
+        ret.reserve(authTokens.size());
+        for (auto& session : authTokens)
+        {
+            if (getAll || type == session.second->persistence)
+            {
+                ret.push_back(&session.second->uniqueId);
+            }
+        }
+        return ret;
+    }
+
+    bool needsWrite()
+    {
+        return needWrite;
+    }
+    int getTimeoutInSeconds() const
+    {
+        return std::chrono::seconds(timeoutInMinutes).count();
+    };
+
+    // Persistent data middleware needs to be able to serialize our authTokens
+    // structure, which is private
+    friend Middleware;
+
+    static SessionStore& getInstance()
+    {
+        static SessionStore sessionStore;
+        return sessionStore;
+    }
+
+    SessionStore(const SessionStore&) = delete;
+    SessionStore& operator=(const SessionStore&) = delete;
+
+  private:
+    SessionStore() : timeoutInMinutes(60)
+    {
+    }
+
+    void applySessionTimeouts()
+    {
+        auto timeNow = std::chrono::steady_clock::now();
+        if (timeNow - lastTimeoutUpdate > std::chrono::minutes(1))
+        {
+            lastTimeoutUpdate = timeNow;
+            auto authTokensIt = authTokens.begin();
+            while (authTokensIt != authTokens.end())
+            {
+                if (timeNow - authTokensIt->second->lastUpdated >=
+                    timeoutInMinutes)
+                {
+                    authTokensIt = authTokens.erase(authTokensIt);
+                    needWrite = true;
+                }
+                else
+                {
+                    authTokensIt++;
+                }
+            }
+        }
+    }
+    std::chrono::time_point<std::chrono::steady_clock> lastTimeoutUpdate;
+    boost::container::flat_map<std::string, std::shared_ptr<UserSession>>
+        authTokens;
+    std::random_device rd;
+    bool needWrite{false};
+    std::chrono::minutes timeoutInMinutes;
 };
 
-}  // namespace persistent_data
-}  // namespace crow
+} // namespace persistent_data
+} // namespace crow
 
 // to_json(...) definition for objects of UserSession type
-namespace nlohmann {
+namespace nlohmann
+{
 template <>
-struct adl_serializer<std::shared_ptr<crow::persistent_data::UserSession>> {
-  static void to_json(
-      nlohmann::json& j,
-      const std::shared_ptr<crow::persistent_data::UserSession>& p) {
-    if (p->persistence !=
-        crow::persistent_data::PersistenceType::SINGLE_REQUEST) {
-      j = nlohmann::json{{"unique_id", p->uniqueId},
-                         {"session_token", p->sessionToken},
-                         {"username", p->username},
-                         {"csrf_token", p->csrfToken}};
+struct adl_serializer<std::shared_ptr<crow::persistent_data::UserSession>>
+{
+    static void
+        to_json(nlohmann::json& j,
+                const std::shared_ptr<crow::persistent_data::UserSession>& p)
+    {
+        if (p->persistence !=
+            crow::persistent_data::PersistenceType::SINGLE_REQUEST)
+        {
+            j = nlohmann::json{{"unique_id", p->uniqueId},
+                               {"session_token", p->sessionToken},
+                               {"username", p->username},
+                               {"csrf_token", p->csrfToken}};
+        }
     }
-  }
 };
-}  // namespace nlohmann
+} // namespace nlohmann
diff --git a/include/ssl_key_handler.hpp b/include/ssl_key_handler.hpp
index 4eac803..47893bf 100644
--- a/include/ssl_key_handler.hpp
+++ b/include/ssl_key_handler.hpp
@@ -10,304 +10,355 @@
 #include <openssl/rand.h>
 #include <openssl/rsa.h>
 #include <openssl/ssl.h>
-#include <random>
-#include <boost/asio.hpp>
 
-namespace ensuressl {
+#include <boost/asio.hpp>
+#include <random>
+
+namespace ensuressl
+{
 static void initOpenssl();
 static void cleanupOpenssl();
 static EVP_PKEY *createRsaKey();
 static EVP_PKEY *createEcKey();
 static void handleOpensslError();
 
-inline bool verifyOpensslKeyCert(const std::string &filepath) {
-  bool privateKeyValid = false;
-  bool certValid = false;
+inline bool verifyOpensslKeyCert(const std::string &filepath)
+{
+    bool privateKeyValid = false;
+    bool certValid = false;
 
-  std::cout << "Checking certs in file " << filepath << "\n";
+    std::cout << "Checking certs in file " << filepath << "\n";
 
-  FILE *file = fopen(filepath.c_str(), "r");
-  if (file != NULL) {
-    EVP_PKEY *pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL);
-    int rc;
-    if (pkey != nullptr) {
-      RSA *rsa = EVP_PKEY_get1_RSA(pkey);
-      if (rsa != nullptr) {
-        std::cout << "Found an RSA key\n";
-        if (RSA_check_key(rsa) == 1) {
-          // private_key_valid = true;
-        } else {
-          std::cerr << "Key not valid error number " << ERR_get_error() << "\n";
+    FILE *file = fopen(filepath.c_str(), "r");
+    if (file != NULL)
+    {
+        EVP_PKEY *pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL);
+        int rc;
+        if (pkey != nullptr)
+        {
+            RSA *rsa = EVP_PKEY_get1_RSA(pkey);
+            if (rsa != nullptr)
+            {
+                std::cout << "Found an RSA key\n";
+                if (RSA_check_key(rsa) == 1)
+                {
+                    // private_key_valid = true;
+                }
+                else
+                {
+                    std::cerr << "Key not valid error number "
+                              << ERR_get_error() << "\n";
+                }
+                RSA_free(rsa);
+            }
+            else
+            {
+                EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
+                if (ec != nullptr)
+                {
+                    std::cout << "Found an EC key\n";
+                    if (EC_KEY_check_key(ec) == 1)
+                    {
+                        privateKeyValid = true;
+                    }
+                    else
+                    {
+                        std::cerr << "Key not valid error number "
+                                  << ERR_get_error() << "\n";
+                    }
+                    EC_KEY_free(ec);
+                }
+            }
+
+            if (privateKeyValid)
+            {
+                X509 *x509 = PEM_read_X509(file, NULL, NULL, NULL);
+                if (x509 == nullptr)
+                {
+                    std::cout << "error getting x509 cert " << ERR_get_error()
+                              << "\n";
+                }
+                else
+                {
+                    rc = X509_verify(x509, pkey);
+                    if (rc == 1)
+                    {
+                        certValid = true;
+                    }
+                    else
+                    {
+                        std::cerr << "Error in verifying private key signature "
+                                  << ERR_get_error() << "\n";
+                    }
+                }
+            }
+
+            EVP_PKEY_free(pkey);
         }
-        RSA_free(rsa);
-      } else {
-        EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey);
-        if (ec != nullptr) {
-          std::cout << "Found an EC key\n";
-          if (EC_KEY_check_key(ec) == 1) {
-            privateKeyValid = true;
-          } else {
-            std::cerr << "Key not valid error number " << ERR_get_error()
-                      << "\n";
-          }
-          EC_KEY_free(ec);
-        }
-      }
-
-      if (privateKeyValid) {
-        X509 *x509 = PEM_read_X509(file, NULL, NULL, NULL);
-        if (x509 == nullptr) {
-          std::cout << "error getting x509 cert " << ERR_get_error() << "\n";
-        } else {
-          rc = X509_verify(x509, pkey);
-          if (rc == 1) {
-            certValid = true;
-          } else {
-            std::cerr << "Error in verifying private key signature "
-                      << ERR_get_error() << "\n";
-          }
-        }
-      }
-
-      EVP_PKEY_free(pkey);
+        fclose(file);
     }
-    fclose(file);
-  }
-  return certValid;
+    return certValid;
 }
 
-inline void generateSslCertificate(const std::string &filepath) {
-  FILE *pFile = NULL;
-  std::cout << "Generating new keys\n";
-  initOpenssl();
+inline void generateSslCertificate(const std::string &filepath)
+{
+    FILE *pFile = NULL;
+    std::cout << "Generating new keys\n";
+    initOpenssl();
 
-  // std::cerr << "Generating RSA key";
-  // EVP_PKEY *pRsaPrivKey = create_rsa_key();
+    // std::cerr << "Generating RSA key";
+    // EVP_PKEY *pRsaPrivKey = create_rsa_key();
 
-  std::cerr << "Generating EC key\n";
-  EVP_PKEY *pRsaPrivKey = createEcKey();
-  if (pRsaPrivKey != nullptr) {
-    std::cerr << "Generating x509 Certificate\n";
-    // Use this code to directly generate a certificate
-    X509 *x509;
-    x509 = X509_new();
-    if (x509 != nullptr) {
-      // get a random number from the RNG for the certificate serial number
-      // If this is not random, regenerating certs throws broswer errors
-      std::random_device rd;
-      int serial = rd();
+    std::cerr << "Generating EC key\n";
+    EVP_PKEY *pRsaPrivKey = createEcKey();
+    if (pRsaPrivKey != nullptr)
+    {
+        std::cerr << "Generating x509 Certificate\n";
+        // Use this code to directly generate a certificate
+        X509 *x509;
+        x509 = X509_new();
+        if (x509 != nullptr)
+        {
+            // get a random number from the RNG for the certificate serial
+            // number If this is not random, regenerating certs throws broswer
+            // errors
+            std::random_device rd;
+            int serial = rd();
 
-      ASN1_INTEGER_set(X509_get_serialNumber(x509), serial);
+            ASN1_INTEGER_set(X509_get_serialNumber(x509), serial);
 
-      // not before this moment
-      X509_gmtime_adj(X509_get_notBefore(x509), 0);
-      // Cert is valid for 10 years
-      X509_gmtime_adj(X509_get_notAfter(x509), 60L * 60L * 24L * 365L * 10L);
+            // not before this moment
+            X509_gmtime_adj(X509_get_notBefore(x509), 0);
+            // Cert is valid for 10 years
+            X509_gmtime_adj(X509_get_notAfter(x509),
+                            60L * 60L * 24L * 365L * 10L);
 
-      // set the public key to the key we just generated
-      X509_set_pubkey(x509, pRsaPrivKey);
+            // set the public key to the key we just generated
+            X509_set_pubkey(x509, pRsaPrivKey);
 
-      // get the subject name
-      X509_NAME *name;
-      name = X509_get_subject_name(x509);
+            // get the subject name
+            X509_NAME *name;
+            name = X509_get_subject_name(x509);
 
-      X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC,
-                                 reinterpret_cast<const unsigned char *>("US"),
-                                 -1, -1, 0);
-      X509_NAME_add_entry_by_txt(
-          name, "O", MBSTRING_ASC,
-          reinterpret_cast<const unsigned char *>("Intel BMC"), -1, -1, 0);
-      X509_NAME_add_entry_by_txt(
-          name, "CN", MBSTRING_ASC,
-          reinterpret_cast<const unsigned char *>("testhost"), -1, -1, 0);
-      // set the CSR options
-      X509_set_issuer_name(x509, name);
+            X509_NAME_add_entry_by_txt(
+                name, "C", MBSTRING_ASC,
+                reinterpret_cast<const unsigned char *>("US"), -1, -1, 0);
+            X509_NAME_add_entry_by_txt(
+                name, "O", MBSTRING_ASC,
+                reinterpret_cast<const unsigned char *>("Intel BMC"), -1, -1,
+                0);
+            X509_NAME_add_entry_by_txt(
+                name, "CN", MBSTRING_ASC,
+                reinterpret_cast<const unsigned char *>("testhost"), -1, -1, 0);
+            // set the CSR options
+            X509_set_issuer_name(x509, name);
 
-      // Sign the certificate with our private key
-      X509_sign(x509, pRsaPrivKey, EVP_sha256());
+            // Sign the certificate with our private key
+            X509_sign(x509, pRsaPrivKey, EVP_sha256());
 
-      pFile = fopen(filepath.c_str(), "wt");
+            pFile = fopen(filepath.c_str(), "wt");
 
-      if (pFile != nullptr) {
-        PEM_write_PrivateKey(pFile, pRsaPrivKey, NULL, NULL, 0, 0, NULL);
+            if (pFile != nullptr)
+            {
+                PEM_write_PrivateKey(pFile, pRsaPrivKey, NULL, NULL, 0, 0,
+                                     NULL);
 
-        PEM_write_X509(pFile, x509);
-        fclose(pFile);
-        pFile = NULL;
-      }
+                PEM_write_X509(pFile, x509);
+                fclose(pFile);
+                pFile = NULL;
+            }
 
-      X509_free(x509);
+            X509_free(x509);
+        }
+
+        EVP_PKEY_free(pRsaPrivKey);
+        pRsaPrivKey = NULL;
     }
 
-    EVP_PKEY_free(pRsaPrivKey);
-    pRsaPrivKey = NULL;
-  }
-
-  // cleanup_openssl();
+    // cleanup_openssl();
 }
 
-EVP_PKEY *createRsaKey() {
-  RSA *pRSA = NULL;
+EVP_PKEY *createRsaKey()
+{
+    RSA *pRSA = NULL;
 #if OPENSSL_VERSION_NUMBER < 0x00908000L
-  pRSA = RSA_generate_key(2048, RSA_3, NULL, NULL);
+    pRSA = RSA_generate_key(2048, RSA_3, NULL, NULL);
 #else
-  RSA_generate_key_ex(pRSA, 2048, NULL, NULL);
+    RSA_generate_key_ex(pRSA, 2048, NULL, NULL);
 #endif
 
-  EVP_PKEY *pKey = EVP_PKEY_new();
-  if ((pRSA != nullptr) && (pKey != nullptr) &&
-      EVP_PKEY_assign_RSA(pKey, pRSA)) {
-    /* pKey owns pRSA from now */
-    if (RSA_check_key(pRSA) <= 0) {
-      fprintf(stderr, "RSA_check_key failed.\n");
-      handleOpensslError();
-      EVP_PKEY_free(pKey);
-      pKey = NULL;
-    }
-  } else {
-    handleOpensslError();
-    if (pRSA != nullptr) {
-      RSA_free(pRSA);
-      pRSA = NULL;
-    }
-    if (pKey != nullptr) {
-      EVP_PKEY_free(pKey);
-      pKey = NULL;
-    }
-  }
-  return pKey;
-}
-
-EVP_PKEY *createEcKey() {
-  EVP_PKEY *pKey = NULL;
-  int eccgrp = 0;
-  eccgrp = OBJ_txt2nid("prime256v1");
-
-  EC_KEY *myecc = EC_KEY_new_by_curve_name(eccgrp);
-  if (myecc != nullptr) {
-    EC_KEY_set_asn1_flag(myecc, OPENSSL_EC_NAMED_CURVE);
-    EC_KEY_generate_key(myecc);
-    pKey = EVP_PKEY_new();
-    if (pKey != nullptr) {
-      if (EVP_PKEY_assign_EC_KEY(pKey, myecc)) {
+    EVP_PKEY *pKey = EVP_PKEY_new();
+    if ((pRSA != nullptr) && (pKey != nullptr) &&
+        EVP_PKEY_assign_RSA(pKey, pRSA))
+    {
         /* pKey owns pRSA from now */
-        if (EC_KEY_check_key(myecc) <= 0) {
-          fprintf(stderr, "EC_check_key failed.\n");
+        if (RSA_check_key(pRSA) <= 0)
+        {
+            fprintf(stderr, "RSA_check_key failed.\n");
+            handleOpensslError();
+            EVP_PKEY_free(pKey);
+            pKey = NULL;
         }
-      }
     }
-  }
-  return pKey;
+    else
+    {
+        handleOpensslError();
+        if (pRSA != nullptr)
+        {
+            RSA_free(pRSA);
+            pRSA = NULL;
+        }
+        if (pKey != nullptr)
+        {
+            EVP_PKEY_free(pKey);
+            pKey = NULL;
+        }
+    }
+    return pKey;
 }
 
-void initOpenssl() {
+EVP_PKEY *createEcKey()
+{
+    EVP_PKEY *pKey = NULL;
+    int eccgrp = 0;
+    eccgrp = OBJ_txt2nid("prime256v1");
+
+    EC_KEY *myecc = EC_KEY_new_by_curve_name(eccgrp);
+    if (myecc != nullptr)
+    {
+        EC_KEY_set_asn1_flag(myecc, OPENSSL_EC_NAMED_CURVE);
+        EC_KEY_generate_key(myecc);
+        pKey = EVP_PKEY_new();
+        if (pKey != nullptr)
+        {
+            if (EVP_PKEY_assign_EC_KEY(pKey, myecc))
+            {
+                /* pKey owns pRSA from now */
+                if (EC_KEY_check_key(myecc) <= 0)
+                {
+                    fprintf(stderr, "EC_check_key failed.\n");
+                }
+            }
+        }
+    }
+    return pKey;
+}
+
+void initOpenssl()
+{
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
-  SSL_load_error_strings();
-  OpenSSL_add_all_algorithms();
-  RAND_load_file("/dev/urandom", 1024);
+    SSL_load_error_strings();
+    OpenSSL_add_all_algorithms();
+    RAND_load_file("/dev/urandom", 1024);
 #endif
 }
 
-void cleanupOpenssl() {
-  CRYPTO_cleanup_all_ex_data();
-  ERR_free_strings();
+void cleanupOpenssl()
+{
+    CRYPTO_cleanup_all_ex_data();
+    ERR_free_strings();
 #if OPENSSL_VERSION_NUMBER < 0x10100000L
-  ERR_remove_thread_state(0);
+    ERR_remove_thread_state(0);
 #endif
-  EVP_cleanup();
+    EVP_cleanup();
 }
 
-void handleOpensslError() { ERR_print_errors_fp(stderr); }
-inline void ensureOpensslKeyPresentAndValid(const std::string &filepath) {
-  bool pemFileValid = false;
+void handleOpensslError()
+{
+    ERR_print_errors_fp(stderr);
+}
+inline void ensureOpensslKeyPresentAndValid(const std::string &filepath)
+{
+    bool pemFileValid = false;
 
-  pemFileValid = verifyOpensslKeyCert(filepath);
+    pemFileValid = verifyOpensslKeyCert(filepath);
 
-  if (!pemFileValid) {
-    std::cerr << "Error in verifying signature, regenerating\n";
-    generateSslCertificate(filepath);
-  }
+    if (!pemFileValid)
+    {
+        std::cerr << "Error in verifying signature, regenerating\n";
+        generateSslCertificate(filepath);
+    }
 }
 
-inline boost::asio::ssl::context getSslContext(
-    const std::string &ssl_pem_file) {
-  boost::asio::ssl::context mSslContext{boost::asio::ssl::context::sslv23};
-  mSslContext.set_options(boost::asio::ssl::context::default_workarounds |
-                          boost::asio::ssl::context::no_sslv2 |
-                          boost::asio::ssl::context::no_sslv3 |
-                          boost::asio::ssl::context::single_dh_use |
-                          boost::asio::ssl::context::no_tlsv1 |
-                          boost::asio::ssl::context::no_tlsv1_1);
+inline boost::asio::ssl::context getSslContext(const std::string &ssl_pem_file)
+{
+    boost::asio::ssl::context mSslContext{boost::asio::ssl::context::sslv23};
+    mSslContext.set_options(boost::asio::ssl::context::default_workarounds |
+                            boost::asio::ssl::context::no_sslv2 |
+                            boost::asio::ssl::context::no_sslv3 |
+                            boost::asio::ssl::context::single_dh_use |
+                            boost::asio::ssl::context::no_tlsv1 |
+                            boost::asio::ssl::context::no_tlsv1_1);
 
-  // m_ssl_context.set_verify_mode(boost::asio::ssl::verify_peer);
-  mSslContext.use_certificate_file(ssl_pem_file,
-                                   boost::asio::ssl::context::pem);
-  mSslContext.use_private_key_file(ssl_pem_file,
-                                   boost::asio::ssl::context::pem);
+    // m_ssl_context.set_verify_mode(boost::asio::ssl::verify_peer);
+    mSslContext.use_certificate_file(ssl_pem_file,
+                                     boost::asio::ssl::context::pem);
+    mSslContext.use_private_key_file(ssl_pem_file,
+                                     boost::asio::ssl::context::pem);
 
-  // Set up EC curves to auto (boost asio doesn't have a method for this)
-  // There is a pull request to add this.  Once this is included in an asio
-  // drop, use the right way
-  // http://stackoverflow.com/questions/18929049/boost-asio-with-ecdsa-certificate-issue
-  if (SSL_CTX_set_ecdh_auto(mSslContext.native_handle(), 1) != 1) {
-    BMCWEB_LOG_ERROR << "Error setting tmp ecdh list\n";
-  }
+    // Set up EC curves to auto (boost asio doesn't have a method for this)
+    // There is a pull request to add this.  Once this is included in an asio
+    // drop, use the right way
+    // http://stackoverflow.com/questions/18929049/boost-asio-with-ecdsa-certificate-issue
+    if (SSL_CTX_set_ecdh_auto(mSslContext.native_handle(), 1) != 1)
+    {
+        BMCWEB_LOG_ERROR << "Error setting tmp ecdh list\n";
+    }
 
-  // From mozilla "compatibility"
-  std::string mozillaCompatibilityCiphers =
-      "ECDHE-ECDSA-CHACHA20-POLY1305:"
-      "ECDHE-RSA-CHACHA20-POLY1305:"
-      "ECDHE-ECDSA-AES128-GCM-SHA256:"
-      "ECDHE-RSA-AES128-GCM-SHA256:"
-      "ECDHE-ECDSA-AES256-GCM-SHA384:"
-      "ECDHE-RSA-AES256-GCM-SHA384:"
-      "DHE-RSA-AES128-GCM-SHA256:"
-      "DHE-RSA-AES256-GCM-SHA384:"
-      "ECDHE-ECDSA-AES128-SHA256:"
-      "ECDHE-RSA-AES128-SHA256:"
-      "ECDHE-ECDSA-AES128-SHA:"
-      "ECDHE-RSA-AES256-SHA384:"
-      "ECDHE-RSA-AES128-SHA:"
-      "ECDHE-ECDSA-AES256-SHA384:"
-      "ECDHE-ECDSA-AES256-SHA:"
-      "ECDHE-RSA-AES256-SHA:"
-      "DHE-RSA-AES128-SHA256:"
-      "DHE-RSA-AES128-SHA:"
-      "DHE-RSA-AES256-SHA256:"
-      "DHE-RSA-AES256-SHA:"
-      "ECDHE-ECDSA-DES-CBC3-SHA:"
-      "ECDHE-RSA-DES-CBC3-SHA:"
-      "EDH-RSA-DES-CBC3-SHA:"
-      "AES128-GCM-SHA256:"
-      "AES256-GCM-SHA384:"
-      "AES128-SHA256:"
-      "AES256-SHA256:"
-      "AES128-SHA:"
-      "AES256-SHA:"
-      "DES-CBC3-SHA:"
-      "!DSS";
+    // From mozilla "compatibility"
+    std::string mozillaCompatibilityCiphers = "ECDHE-ECDSA-CHACHA20-POLY1305:"
+                                              "ECDHE-RSA-CHACHA20-POLY1305:"
+                                              "ECDHE-ECDSA-AES128-GCM-SHA256:"
+                                              "ECDHE-RSA-AES128-GCM-SHA256:"
+                                              "ECDHE-ECDSA-AES256-GCM-SHA384:"
+                                              "ECDHE-RSA-AES256-GCM-SHA384:"
+                                              "DHE-RSA-AES128-GCM-SHA256:"
+                                              "DHE-RSA-AES256-GCM-SHA384:"
+                                              "ECDHE-ECDSA-AES128-SHA256:"
+                                              "ECDHE-RSA-AES128-SHA256:"
+                                              "ECDHE-ECDSA-AES128-SHA:"
+                                              "ECDHE-RSA-AES256-SHA384:"
+                                              "ECDHE-RSA-AES128-SHA:"
+                                              "ECDHE-ECDSA-AES256-SHA384:"
+                                              "ECDHE-ECDSA-AES256-SHA:"
+                                              "ECDHE-RSA-AES256-SHA:"
+                                              "DHE-RSA-AES128-SHA256:"
+                                              "DHE-RSA-AES128-SHA:"
+                                              "DHE-RSA-AES256-SHA256:"
+                                              "DHE-RSA-AES256-SHA:"
+                                              "ECDHE-ECDSA-DES-CBC3-SHA:"
+                                              "ECDHE-RSA-DES-CBC3-SHA:"
+                                              "EDH-RSA-DES-CBC3-SHA:"
+                                              "AES128-GCM-SHA256:"
+                                              "AES256-GCM-SHA384:"
+                                              "AES128-SHA256:"
+                                              "AES256-SHA256:"
+                                              "AES128-SHA:"
+                                              "AES256-SHA:"
+                                              "DES-CBC3-SHA:"
+                                              "!DSS";
 
-  // From mozilla "modern"
-  std::string mozillaModernCiphers =
-      "ECDHE-ECDSA-AES256-GCM-SHA384:"
-      "ECDHE-RSA-AES256-GCM-SHA384:"
-      "ECDHE-ECDSA-CHACHA20-POLY1305:"
-      "ECDHE-RSA-CHACHA20-POLY1305:"
-      "ECDHE-ECDSA-AES128-GCM-SHA256:"
-      "ECDHE-RSA-AES128-GCM-SHA256:"
-      "ECDHE-ECDSA-AES256-SHA384:"
-      "ECDHE-RSA-AES256-SHA384:"
-      "ECDHE-ECDSA-AES128-SHA256:"
-      "ECDHE-RSA-AES128-SHA256";
+    // From mozilla "modern"
+    std::string mozillaModernCiphers = "ECDHE-ECDSA-AES256-GCM-SHA384:"
+                                       "ECDHE-RSA-AES256-GCM-SHA384:"
+                                       "ECDHE-ECDSA-CHACHA20-POLY1305:"
+                                       "ECDHE-RSA-CHACHA20-POLY1305:"
+                                       "ECDHE-ECDSA-AES128-GCM-SHA256:"
+                                       "ECDHE-RSA-AES128-GCM-SHA256:"
+                                       "ECDHE-ECDSA-AES256-SHA384:"
+                                       "ECDHE-RSA-AES256-SHA384:"
+                                       "ECDHE-ECDSA-AES128-SHA256:"
+                                       "ECDHE-RSA-AES128-SHA256";
 
-  std::string aesOnlyCiphers = "AES128+EECDH:AES128+EDH:!aNULL:!eNULL";
+    std::string aesOnlyCiphers = "AES128+EECDH:AES128+EDH:!aNULL:!eNULL";
 
-  if (SSL_CTX_set_cipher_list(mSslContext.native_handle(),
-                              mozillaCompatibilityCiphers.c_str()) != 1) {
-    BMCWEB_LOG_ERROR << "Error setting cipher list\n";
-  }
-  return mSslContext;
+    if (SSL_CTX_set_cipher_list(mSslContext.native_handle(),
+                                mozillaCompatibilityCiphers.c_str()) != 1)
+    {
+        BMCWEB_LOG_ERROR << "Error setting cipher list\n";
+    }
+    return mSslContext;
 }
-}  // namespace ensuressl
+} // namespace ensuressl
 
 #endif
\ No newline at end of file
diff --git a/include/token_authorization_middleware.hpp b/include/token_authorization_middleware.hpp
index 2e286e1..c419c97 100644
--- a/include/token_authorization_middleware.hpp
+++ b/include/token_authorization_middleware.hpp
@@ -1,359 +1,448 @@
 #pragma once
 
-#include <pam_authenticate.hpp>
-#include <persistent_data_middleware.hpp>
-#include <webassets.hpp>
-#include <random>
 #include <crow/app.h>
 #include <crow/common.h>
 #include <crow/http_request.h>
 #include <crow/http_response.h>
+
 #include <boost/container/flat_set.hpp>
+#include <pam_authenticate.hpp>
+#include <persistent_data_middleware.hpp>
+#include <random>
+#include <webassets.hpp>
 
-namespace crow {
+namespace crow
+{
 
-namespace token_authorization {
+namespace token_authorization
+{
 
-class Middleware {
- public:
-  struct Context {
-    std::shared_ptr<crow::persistent_data::UserSession> session;
-  };
+class Middleware
+{
+  public:
+    struct Context
+    {
+        std::shared_ptr<crow::persistent_data::UserSession> session;
+    };
 
-  void beforeHandle(crow::Request& req, Response& res, Context& ctx) {
-    if (isOnWhitelist(req)) {
-      return;
-    }
-
-    ctx.session = performXtokenAuth(req);
-    if (ctx.session == nullptr) {
-      ctx.session = performCookieAuth(req);
-    }
-    if (ctx.session == nullptr) {
-      boost::string_view authHeader = req.getHeaderValue("Authorization");
-      if (!authHeader.empty()) {
-        // Reject any kind of auth other than basic or token
-        if (boost::starts_with(authHeader, "Token ")) {
-          ctx.session = performTokenAuth(authHeader);
-        } else if (boost::starts_with(authHeader, "Basic ")) {
-          ctx.session = performBasicAuth(authHeader);
+    void beforeHandle(crow::Request& req, Response& res, Context& ctx)
+    {
+        if (isOnWhitelist(req))
+        {
+            return;
         }
-      }
-    }
 
-    if (ctx.session == nullptr) {
-      BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed";
-
-      // If it's a browser connecting, don't send the HTTP authenticate header,
-      // to avoid possible CSRF attacks with basic auth
-      if (http_helpers::requestPrefersHtml(req)) {
-        res.result(boost::beast::http::status::temporary_redirect);
-        res.addHeader("Location", "/#/login");
-      } else {
-        res.result(boost::beast::http::status::unauthorized);
-        // only send the WWW-authenticate header if this isn't a xhr from the
-        // browser.  most scripts,
-        if (req.getHeaderValue("User-Agent").empty()) {
-          res.addHeader("WWW-Authenticate", "Basic");
+        ctx.session = performXtokenAuth(req);
+        if (ctx.session == nullptr)
+        {
+            ctx.session = performCookieAuth(req);
         }
-      }
+        if (ctx.session == nullptr)
+        {
+            boost::string_view authHeader = req.getHeaderValue("Authorization");
+            if (!authHeader.empty())
+            {
+                // Reject any kind of auth other than basic or token
+                if (boost::starts_with(authHeader, "Token "))
+                {
+                    ctx.session = performTokenAuth(authHeader);
+                }
+                else if (boost::starts_with(authHeader, "Basic "))
+                {
+                    ctx.session = performBasicAuth(authHeader);
+                }
+            }
+        }
 
-      res.end();
-      return;
+        if (ctx.session == nullptr)
+        {
+            BMCWEB_LOG_WARNING << "[AuthMiddleware] authorization failed";
+
+            // If it's a browser connecting, don't send the HTTP authenticate
+            // header, to avoid possible CSRF attacks with basic auth
+            if (http_helpers::requestPrefersHtml(req))
+            {
+                res.result(boost::beast::http::status::temporary_redirect);
+                res.addHeader("Location", "/#/login");
+            }
+            else
+            {
+                res.result(boost::beast::http::status::unauthorized);
+                // only send the WWW-authenticate header if this isn't a xhr
+                // from the browser.  most scripts,
+                if (req.getHeaderValue("User-Agent").empty())
+                {
+                    res.addHeader("WWW-Authenticate", "Basic");
+                }
+            }
+
+            res.end();
+            return;
+        }
+
+        // TODO get user privileges here and propagate it via MW Context
+        // else let the request continue unharmed
     }
 
-    // TODO get user privileges here and propagate it via MW Context
-    // else let the request continue unharmed
-  }
-
-  template <typename AllContext>
-  void afterHandle(Request& req, Response& res, Context& ctx,
-                   AllContext& allctx) {
-    // TODO(ed) THis should really be handled by the persistent data
-    // middleware, but because it is upstream, it doesn't have access to the
-    // session information.  Should the data middleware persist the current
-    // user session?
-    if (ctx.session != nullptr &&
-        ctx.session->persistence ==
-            crow::persistent_data::PersistenceType::SINGLE_REQUEST) {
-      persistent_data::SessionStore::getInstance().removeSession(ctx.session);
-    }
-  }
-
- private:
-  const std::shared_ptr<crow::persistent_data::UserSession> performBasicAuth(
-      boost::string_view auth_header) const {
-    BMCWEB_LOG_DEBUG << "[AuthMiddleware] Basic authentication";
-
-    std::string authData;
-    boost::string_view param = auth_header.substr(strlen("Basic "));
-    if (!crow::utility::base64Decode(param, authData)) {
-      return nullptr;
-    }
-    std::size_t separator = authData.find(':');
-    if (separator == std::string::npos) {
-      return nullptr;
+    template <typename AllContext>
+    void afterHandle(Request& req, Response& res, Context& ctx,
+                     AllContext& allctx)
+    {
+        // TODO(ed) THis should really be handled by the persistent data
+        // middleware, but because it is upstream, it doesn't have access to the
+        // session information.  Should the data middleware persist the current
+        // user session?
+        if (ctx.session != nullptr &&
+            ctx.session->persistence ==
+                crow::persistent_data::PersistenceType::SINGLE_REQUEST)
+        {
+            persistent_data::SessionStore::getInstance().removeSession(
+                ctx.session);
+        }
     }
 
-    std::string user = authData.substr(0, separator);
-    separator += 1;
-    if (separator > authData.size()) {
-      return nullptr;
-    }
-    std::string pass = authData.substr(separator);
+  private:
+    const std::shared_ptr<crow::persistent_data::UserSession>
+        performBasicAuth(boost::string_view auth_header) const
+    {
+        BMCWEB_LOG_DEBUG << "[AuthMiddleware] Basic authentication";
 
-    BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user;
+        std::string authData;
+        boost::string_view param = auth_header.substr(strlen("Basic "));
+        if (!crow::utility::base64Decode(param, authData))
+        {
+            return nullptr;
+        }
+        std::size_t separator = authData.find(':');
+        if (separator == std::string::npos)
+        {
+            return nullptr;
+        }
 
-    if (!pamAuthenticateUser(user, pass)) {
-      return nullptr;
+        std::string user = authData.substr(0, separator);
+        separator += 1;
+        if (separator > authData.size())
+        {
+            return nullptr;
+        }
+        std::string pass = authData.substr(separator);
+
+        BMCWEB_LOG_DEBUG << "[AuthMiddleware] Authenticating user: " << user;
+
+        if (!pamAuthenticateUser(user, pass))
+        {
+            return nullptr;
+        }
+
+        // TODO(ed) generateUserSession is a little expensive for basic
+        // auth, as it generates some random identifiers that will never be
+        // used.  This should have a "fast" path for when user tokens aren't
+        // needed.
+        // This whole flow needs to be revisited anyway, as we can't be
+        // calling directly into pam for every request
+        return persistent_data::SessionStore::getInstance().generateUserSession(
+            user, crow::persistent_data::PersistenceType::SINGLE_REQUEST);
     }
 
-    // TODO(ed) generateUserSession is a little expensive for basic
-    // auth, as it generates some random identifiers that will never be
-    // used.  This should have a "fast" path for when user tokens aren't
-    // needed.
-    // This whole flow needs to be revisited anyway, as we can't be
-    // calling directly into pam for every request
-    return persistent_data::SessionStore::getInstance().generateUserSession(
-        user, crow::persistent_data::PersistenceType::SINGLE_REQUEST);
-  }
+    const std::shared_ptr<crow::persistent_data::UserSession>
+        performTokenAuth(boost::string_view auth_header) const
+    {
+        BMCWEB_LOG_DEBUG << "[AuthMiddleware] Token authentication";
 
-  const std::shared_ptr<crow::persistent_data::UserSession> performTokenAuth(
-      boost::string_view auth_header) const {
-    BMCWEB_LOG_DEBUG << "[AuthMiddleware] Token authentication";
-
-    boost::string_view token = auth_header.substr(strlen("Token "));
-    auto session =
-        persistent_data::SessionStore::getInstance().loginSessionByToken(token);
-    return session;
-  }
-
-  const std::shared_ptr<crow::persistent_data::UserSession> performXtokenAuth(
-      const crow::Request& req) const {
-    BMCWEB_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication";
-
-    boost::string_view token = req.getHeaderValue("X-Auth-Token");
-    if (token.empty()) {
-      return nullptr;
-    }
-    auto session =
-        persistent_data::SessionStore::getInstance().loginSessionByToken(token);
-    return session;
-  }
-
-  const std::shared_ptr<crow::persistent_data::UserSession> performCookieAuth(
-      const crow::Request& req) const {
-    BMCWEB_LOG_DEBUG << "[AuthMiddleware] Cookie authentication";
-
-    boost::string_view cookieValue = req.getHeaderValue("Cookie");
-    if (cookieValue.empty()) {
-      return nullptr;
+        boost::string_view token = auth_header.substr(strlen("Token "));
+        auto session =
+            persistent_data::SessionStore::getInstance().loginSessionByToken(
+                token);
+        return session;
     }
 
-    auto startIndex = cookieValue.find("SESSION=");
-    if (startIndex == std::string::npos) {
-      return nullptr;
-    }
-    startIndex += sizeof("SESSION=") - 1;
-    auto endIndex = cookieValue.find(";", startIndex);
-    if (endIndex == std::string::npos) {
-      endIndex = cookieValue.size();
-    }
-    boost::string_view authKey =
-        cookieValue.substr(startIndex, endIndex - startIndex);
+    const std::shared_ptr<crow::persistent_data::UserSession>
+        performXtokenAuth(const crow::Request& req) const
+    {
+        BMCWEB_LOG_DEBUG << "[AuthMiddleware] X-Auth-Token authentication";
 
-    const std::shared_ptr<crow::persistent_data::UserSession> session =
-        persistent_data::SessionStore::getInstance().loginSessionByToken(
-            authKey);
-    if (session == nullptr) {
-      return nullptr;
+        boost::string_view token = req.getHeaderValue("X-Auth-Token");
+        if (token.empty())
+        {
+            return nullptr;
+        }
+        auto session =
+            persistent_data::SessionStore::getInstance().loginSessionByToken(
+                token);
+        return session;
     }
+
+    const std::shared_ptr<crow::persistent_data::UserSession>
+        performCookieAuth(const crow::Request& req) const
+    {
+        BMCWEB_LOG_DEBUG << "[AuthMiddleware] Cookie authentication";
+
+        boost::string_view cookieValue = req.getHeaderValue("Cookie");
+        if (cookieValue.empty())
+        {
+            return nullptr;
+        }
+
+        auto startIndex = cookieValue.find("SESSION=");
+        if (startIndex == std::string::npos)
+        {
+            return nullptr;
+        }
+        startIndex += sizeof("SESSION=") - 1;
+        auto endIndex = cookieValue.find(";", startIndex);
+        if (endIndex == std::string::npos)
+        {
+            endIndex = cookieValue.size();
+        }
+        boost::string_view authKey =
+            cookieValue.substr(startIndex, endIndex - startIndex);
+
+        const std::shared_ptr<crow::persistent_data::UserSession> session =
+            persistent_data::SessionStore::getInstance().loginSessionByToken(
+                authKey);
+        if (session == nullptr)
+        {
+            return nullptr;
+        }
 #ifndef BMCWEB_INSECURE_DISABLE_CSRF_PREVENTION
-    // RFC7231 defines methods that need csrf protection
-    if (req.method() != "GET"_method) {
-      boost::string_view csrf = req.getHeaderValue("X-XSRF-TOKEN");
-      // Make sure both tokens are filled
-      if (csrf.empty() || session->csrfToken.empty()) {
-        return nullptr;
-      }
-      // Reject if csrf token not available
-      if (csrf != session->csrfToken) {
-        return nullptr;
-      }
-    }
+        // RFC7231 defines methods that need csrf protection
+        if (req.method() != "GET"_method)
+        {
+            boost::string_view csrf = req.getHeaderValue("X-XSRF-TOKEN");
+            // Make sure both tokens are filled
+            if (csrf.empty() || session->csrfToken.empty())
+            {
+                return nullptr;
+            }
+            // Reject if csrf token not available
+            if (csrf != session->csrfToken)
+            {
+                return nullptr;
+            }
+        }
 #endif
-    return session;
-  }
-
-  // checks if request can be forwarded without authentication
-  bool isOnWhitelist(const crow::Request& req) const {
-    // it's allowed to GET root node without authentica tion
-    if ("GET"_method == req.method()) {
-      if (req.url == "/redfish/v1" || req.url == "/redfish/v1/" ||
-          req.url == "/redfish" || req.url == "/redfish/" ||
-          req.url == "/redfish/v1/odata" || req.url == "/redfish/v1/odata/") {
-        return true;
-      } else if (crow::webassets::routes.find(std::string(req.url)) !=
-                 crow::webassets::routes.end()) {
-        return true;
-      }
+        return session;
     }
 
-    // it's allowed to POST on session collection & login without
-    // authentication
-    if ("POST"_method == req.method()) {
-      if ((req.url == "/redfish/v1/SessionService/Sessions") ||
-          (req.url == "/redfish/v1/SessionService/Sessions/") ||
-          (req.url == "/login")) {
-        return true;
-      }
-    }
+    // checks if request can be forwarded without authentication
+    bool isOnWhitelist(const crow::Request& req) const
+    {
+        // it's allowed to GET root node without authentica tion
+        if ("GET"_method == req.method())
+        {
+            if (req.url == "/redfish/v1" || req.url == "/redfish/v1/" ||
+                req.url == "/redfish" || req.url == "/redfish/" ||
+                req.url == "/redfish/v1/odata" ||
+                req.url == "/redfish/v1/odata/")
+            {
+                return true;
+            }
+            else if (crow::webassets::routes.find(std::string(req.url)) !=
+                     crow::webassets::routes.end())
+            {
+                return true;
+            }
+        }
 
-    return false;
-  }
+        // it's allowed to POST on session collection & login without
+        // authentication
+        if ("POST"_method == req.method())
+        {
+            if ((req.url == "/redfish/v1/SessionService/Sessions") ||
+                (req.url == "/redfish/v1/SessionService/Sessions/") ||
+                (req.url == "/login"))
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
 };
 
 // TODO(ed) see if there is a better way to allow middlewares to request
 // routes.
 // Possibly an init function on first construction?
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...>& app) {
-  static_assert(
-      black_magic::Contains<persistent_data::Middleware, Middlewares...>::value,
-      "token_authorization middleware must be enabled in app to use "
-      "auth routes");
-  BMCWEB_ROUTE(app, "/login")
-      .methods(
-          "POST"_method)([&](const crow::Request& req, crow::Response& res) {
-        boost::string_view contentType = req.getHeaderValue("content-type");
-        boost::string_view username;
-        boost::string_view password;
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app)
+{
+    static_assert(
+        black_magic::Contains<persistent_data::Middleware,
+                              Middlewares...>::value,
+        "token_authorization middleware must be enabled in app to use "
+        "auth routes");
+    BMCWEB_ROUTE(app, "/login")
+        .methods(
+            "POST"_method)([&](const crow::Request& req, crow::Response& res) {
+            boost::string_view contentType = req.getHeaderValue("content-type");
+            boost::string_view username;
+            boost::string_view password;
 
-        bool looksLikeIbm = false;
+            bool looksLikeIbm = false;
 
-        // This object needs to be declared at this scope so the strings
-        // within it are not destroyed before we can use them
-        nlohmann::json loginCredentials;
-        // Check if auth was provided by a payload
-        if (contentType == "application/json") {
-          loginCredentials = nlohmann::json::parse(req.body, nullptr, false);
-          if (loginCredentials.is_discarded()) {
-            res.result(boost::beast::http::status::bad_request);
+            // This object needs to be declared at this scope so the strings
+            // within it are not destroyed before we can use them
+            nlohmann::json loginCredentials;
+            // Check if auth was provided by a payload
+            if (contentType == "application/json")
+            {
+                loginCredentials =
+                    nlohmann::json::parse(req.body, nullptr, false);
+                if (loginCredentials.is_discarded())
+                {
+                    res.result(boost::beast::http::status::bad_request);
+                    res.end();
+                    return;
+                }
+
+                // check for username/password in the root object
+                // THis method is how intel APIs authenticate
+                nlohmann::json::iterator userIt =
+                    loginCredentials.find("username");
+                nlohmann::json::iterator passIt =
+                    loginCredentials.find("password");
+                if (userIt != loginCredentials.end() &&
+                    passIt != loginCredentials.end())
+                {
+                    const std::string* userStr =
+                        userIt->get_ptr<const std::string*>();
+                    const std::string* passStr =
+                        passIt->get_ptr<const std::string*>();
+                    if (userStr != nullptr && passStr != nullptr)
+                    {
+                        username = *userStr;
+                        password = *passStr;
+                    }
+                }
+                else
+                {
+                    // Openbmc appears to push a data object that contains the
+                    // same keys (username and password), attempt to use that
+                    auto dataIt = loginCredentials.find("data");
+                    if (dataIt != loginCredentials.end())
+                    {
+                        // Some apis produce an array of value ["username",
+                        // "password"]
+                        if (dataIt->is_array())
+                        {
+                            if (dataIt->size() == 2)
+                            {
+                                nlohmann::json::iterator userIt2 =
+                                    dataIt->begin();
+                                nlohmann::json::iterator passIt2 =
+                                    dataIt->begin() + 1;
+                                looksLikeIbm = true;
+                                if (userIt2 != dataIt->end() &&
+                                    passIt2 != dataIt->end())
+                                {
+                                    const std::string* userStr =
+                                        userIt2->get_ptr<const std::string*>();
+                                    const std::string* passStr =
+                                        passIt2->get_ptr<const std::string*>();
+                                    if (userStr != nullptr &&
+                                        passStr != nullptr)
+                                    {
+                                        username = *userStr;
+                                        password = *passStr;
+                                    }
+                                }
+                            }
+                        }
+                        else if (dataIt->is_object())
+                        {
+                            nlohmann::json::iterator userIt2 =
+                                dataIt->find("username");
+                            nlohmann::json::iterator passIt2 =
+                                dataIt->find("password");
+                            if (userIt2 != dataIt->end() &&
+                                passIt2 != dataIt->end())
+                            {
+                                const std::string* userStr =
+                                    userIt2->get_ptr<const std::string*>();
+                                const std::string* passStr =
+                                    passIt2->get_ptr<const std::string*>();
+                                if (userStr != nullptr && passStr != nullptr)
+                                {
+                                    username = *userStr;
+                                    password = *passStr;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // check if auth was provided as a headers
+                username = req.getHeaderValue("username");
+                password = req.getHeaderValue("password");
+            }
+
+            if (!username.empty() && !password.empty())
+            {
+                if (!pamAuthenticateUser(username, password))
+                {
+                    res.result(boost::beast::http::status::unauthorized);
+                }
+                else
+                {
+                    auto session = persistent_data::SessionStore::getInstance()
+                                       .generateUserSession(username);
+
+                    if (looksLikeIbm)
+                    {
+                        // IBM requires a very specific login structure, and
+                        // doesn't actually look at the status code.
+                        // TODO(ed).... Fix that upstream
+                        res.jsonValue = {
+                            {"data",
+                             "User '" + std::string(username) + "' logged in"},
+                            {"message", "200 OK"},
+                            {"status", "ok"}};
+
+                        // Hack alert.  Boost beast by default doesn't let you
+                        // declare multiple headers of the same name, and in
+                        // most cases this is fine.  Unfortunately here we need
+                        // to set the Session cookie, which requires the
+                        // httpOnly attribute, as well as the XSRF cookie, which
+                        // requires it to not have an httpOnly attribute. To get
+                        // the behavior we want, we simply inject the second
+                        // "set-cookie" string into the value header, and get
+                        // the result we want, even though we are technicaly
+                        // declaring two headers here.
+                        res.addHeader("Set-Cookie",
+                                      "XSRF-TOKEN=" + session->csrfToken +
+                                          "; Secure\r\nSet-Cookie: SESSION=" +
+                                          session->sessionToken +
+                                          "; Secure; HttpOnly");
+                    }
+                    else
+                    {
+                        // if content type is json, assume json token
+                        res.jsonValue = {{"token", session->sessionToken}};
+                    }
+                }
+            }
+            else
+            {
+                res.result(boost::beast::http::status::bad_request);
+            }
+            res.end();
+        });
+
+    BMCWEB_ROUTE(app, "/logout")
+        .methods(
+            "POST"_method)([&](const crow::Request& req, crow::Response& res) {
+            auto& session =
+                app.template getContext<token_authorization::Middleware>(req)
+                    .session;
+            if (session != nullptr)
+            {
+                persistent_data::SessionStore::getInstance().removeSession(
+                    session);
+            }
             res.end();
             return;
-          }
-
-          // check for username/password in the root object
-          // THis method is how intel APIs authenticate
-          nlohmann::json::iterator userIt = loginCredentials.find("username");
-          nlohmann::json::iterator passIt = loginCredentials.find("password");
-          if (userIt != loginCredentials.end() &&
-              passIt != loginCredentials.end()) {
-            const std::string* userStr = userIt->get_ptr<const std::string*>();
-            const std::string* passStr = passIt->get_ptr<const std::string*>();
-            if (userStr != nullptr && passStr != nullptr) {
-              username = *userStr;
-              password = *passStr;
-            }
-          } else {
-            // Openbmc appears to push a data object that contains the same
-            // keys (username and password), attempt to use that
-            auto dataIt = loginCredentials.find("data");
-            if (dataIt != loginCredentials.end()) {
-              // Some apis produce an array of value ["username",
-              // "password"]
-              if (dataIt->is_array()) {
-                if (dataIt->size() == 2) {
-                  nlohmann::json::iterator userIt2 = dataIt->begin();
-                  nlohmann::json::iterator passIt2 = dataIt->begin() + 1;
-                  looksLikeIbm = true;
-                  if (userIt2 != dataIt->end() && passIt2 != dataIt->end()) {
-                    const std::string* userStr =
-                        userIt2->get_ptr<const std::string*>();
-                    const std::string* passStr =
-                        passIt2->get_ptr<const std::string*>();
-                    if (userStr != nullptr && passStr != nullptr) {
-                      username = *userStr;
-                      password = *passStr;
-                    }
-                  }
-                }
-
-              } else if (dataIt->is_object()) {
-                nlohmann::json::iterator userIt2 = dataIt->find("username");
-                nlohmann::json::iterator passIt2 = dataIt->find("password");
-                if (userIt2 != dataIt->end() && passIt2 != dataIt->end()) {
-                  const std::string* userStr =
-                      userIt2->get_ptr<const std::string*>();
-                  const std::string* passStr =
-                      passIt2->get_ptr<const std::string*>();
-                  if (userStr != nullptr && passStr != nullptr) {
-                    username = *userStr;
-                    password = *passStr;
-                  }
-                }
-              }
-            }
-          }
-        } else {
-          // check if auth was provided as a headers
-          username = req.getHeaderValue("username");
-          password = req.getHeaderValue("password");
-        }
-
-        if (!username.empty() && !password.empty()) {
-          if (!pamAuthenticateUser(username, password)) {
-            res.result(boost::beast::http::status::unauthorized);
-          } else {
-            auto session = persistent_data::SessionStore::getInstance()
-                               .generateUserSession(username);
-
-            if (looksLikeIbm) {
-              // IBM requires a very specific login structure, and doesn't
-              // actually look at the status code.  TODO(ed).... Fix that
-              // upstream
-              res.jsonValue = {
-                  {"data", "User '" + std::string(username) + "' logged in"},
-                  {"message", "200 OK"},
-                  {"status", "ok"}};
-
-              // Hack alert.  Boost beast by default doesn't let you declare
-              // multiple headers of the same name, and in most cases this is
-              // fine.  Unfortunately here we need to set the Session cookie,
-              // which requires the httpOnly attribute, as well as the XSRF
-              // cookie, which requires it to not have an httpOnly attribute.
-              // To get the behavior we want, we simply inject the second
-              // "set-cookie" string into the value header, and get the result
-              // we want, even though we are technicaly declaring two headers
-              // here.
-              res.addHeader("Set-Cookie",
-                            "XSRF-TOKEN=" + session->csrfToken +
-                                "; Secure\r\nSet-Cookie: SESSION=" +
-                                session->sessionToken + "; Secure; HttpOnly");
-            } else {
-              // if content type is json, assume json token
-              res.jsonValue = {{"token", session->sessionToken}};
-            }
-          }
-
-        } else {
-          res.result(boost::beast::http::status::bad_request);
-        }
-        res.end();
-      });
-
-  BMCWEB_ROUTE(app, "/logout")
-      .methods(
-          "POST"_method)([&](const crow::Request& req, crow::Response& res) {
-        auto& session =
-            app.template getContext<token_authorization::Middleware>(req)
-                .session;
-        if (session != nullptr) {
-          persistent_data::SessionStore::getInstance().removeSession(session);
-        }
-        res.end();
-        return;
-      });
+        });
 }
-}  // namespace token_authorization
-}  // namespace crow
+} // namespace token_authorization
+} // namespace crow
diff --git a/include/web_kvm.hpp b/include/web_kvm.hpp
index ad4b352..747a137 100644
--- a/include/web_kvm.hpp
+++ b/include/web_kvm.hpp
@@ -1,181 +1,202 @@
-#include <string>
 #include <crow/app.h>
-#include <boost/endian/arithmetic.hpp>
 
 #include <ast_jpeg_decoder.hpp>
 #include <ast_video_puller.hpp>
+#include <boost/endian/arithmetic.hpp>
+#include <string>
 
-namespace crow {
-namespace kvm {
+namespace crow
+{
+namespace kvm
+{
 
 static const std::string rfb33VersionString = "RFB 003.003\n";
 static const std::string rfb37VersionString = "RFB 003.007\n";
 static const std::string rfb38VersionString = "RFB 003.008\n";
 
-enum class RfbAuthScheme : uint8_t {
-  connection_failed = 0,
-  no_authentication = 1,
-  vnc_authentication = 2
+enum class RfbAuthScheme : uint8_t
+{
+    connection_failed = 0,
+    no_authentication = 1,
+    vnc_authentication = 2
 };
 
-struct PixelFormatStruct {
-  boost::endian::big_uint8_t bitsPerPixel;
-  boost::endian::big_uint8_t depth;
-  boost::endian::big_uint8_t isBigEndian;
-  boost::endian::big_uint8_t isTrueColor;
-  boost::endian::big_uint16_t redMax;
-  boost::endian::big_uint16_t greenMax;
-  boost::endian::big_uint16_t blueMax;
-  boost::endian::big_uint8_t redShift;
-  boost::endian::big_uint8_t greenShift;
-  boost::endian::big_uint8_t blueShift;
-  boost::endian::big_uint8_t pad1;
-  boost::endian::big_uint8_t pad2;
-  boost::endian::big_uint8_t pad3;
+struct PixelFormatStruct
+{
+    boost::endian::big_uint8_t bitsPerPixel;
+    boost::endian::big_uint8_t depth;
+    boost::endian::big_uint8_t isBigEndian;
+    boost::endian::big_uint8_t isTrueColor;
+    boost::endian::big_uint16_t redMax;
+    boost::endian::big_uint16_t greenMax;
+    boost::endian::big_uint16_t blueMax;
+    boost::endian::big_uint8_t redShift;
+    boost::endian::big_uint8_t greenShift;
+    boost::endian::big_uint8_t blueShift;
+    boost::endian::big_uint8_t pad1;
+    boost::endian::big_uint8_t pad2;
+    boost::endian::big_uint8_t pad3;
 };
 
-struct ServerInitializationMsg {
-  boost::endian::big_uint16_t framebufferWidth;
-  boost::endian::big_uint16_t framebufferHeight;
-  PixelFormatStruct pixelFormat;
-  boost::endian::big_uint32_t nameLength;
+struct ServerInitializationMsg
+{
+    boost::endian::big_uint16_t framebufferWidth;
+    boost::endian::big_uint16_t framebufferHeight;
+    PixelFormatStruct pixelFormat;
+    boost::endian::big_uint32_t nameLength;
 };
 
-enum class client_to_server_msg_type : uint8_t {
-  set_pixel_format = 0,
-  fix_color_map_entries = 1,
-  set_encodings = 2,
-  framebuffer_update_request = 3,
-  key_event = 4,
-  pointer_event = 5,
-  client_cut_text = 6
+enum class client_to_server_msg_type : uint8_t
+{
+    set_pixel_format = 0,
+    fix_color_map_entries = 1,
+    set_encodings = 2,
+    framebuffer_update_request = 3,
+    key_event = 4,
+    pointer_event = 5,
+    client_cut_text = 6
 };
 
-enum class server_to_client_message_type : uint8_t {
-  framebuffer_update = 0,
-  set_color_map_entries = 1,
-  bell_message = 2,
-  server_cut_text = 3
+enum class server_to_client_message_type : uint8_t
+{
+    framebuffer_update = 0,
+    set_color_map_entries = 1,
+    bell_message = 2,
+    server_cut_text = 3
 };
 
-struct SetPixelFormatMsg {
-  boost::endian::big_uint8_t pad1;
-  boost::endian::big_uint8_t pad2;
-  boost::endian::big_uint8_t pad3;
-  PixelFormatStruct pixelFormat;
+struct SetPixelFormatMsg
+{
+    boost::endian::big_uint8_t pad1;
+    boost::endian::big_uint8_t pad2;
+    boost::endian::big_uint8_t pad3;
+    PixelFormatStruct pixelFormat;
 };
 
-struct FrameBufferUpdateReq {
-  boost::endian::big_uint8_t incremental;
-  boost::endian::big_uint16_t xPosition;
-  boost::endian::big_uint16_t yPosition;
-  boost::endian::big_uint16_t width;
-  boost::endian::big_uint16_t height;
+struct FrameBufferUpdateReq
+{
+    boost::endian::big_uint8_t incremental;
+    boost::endian::big_uint16_t xPosition;
+    boost::endian::big_uint16_t yPosition;
+    boost::endian::big_uint16_t width;
+    boost::endian::big_uint16_t height;
 };
 
-struct KeyEventMsg {
-  boost::endian::big_uint8_t downFlag;
-  boost::endian::big_uint8_t pad1;
-  boost::endian::big_uint8_t pad2;
-  boost::endian::big_uint32_t key;
+struct KeyEventMsg
+{
+    boost::endian::big_uint8_t downFlag;
+    boost::endian::big_uint8_t pad1;
+    boost::endian::big_uint8_t pad2;
+    boost::endian::big_uint32_t key;
 };
 
-struct PointerEventMsg {
-  boost::endian::big_uint8_t buttonMask;
-  boost::endian::big_uint16_t xPosition;
-  boost::endian::big_uint16_t yPosition;
+struct PointerEventMsg
+{
+    boost::endian::big_uint8_t buttonMask;
+    boost::endian::big_uint16_t xPosition;
+    boost::endian::big_uint16_t yPosition;
 };
 
-struct ClientCutTextMsg {
-  std::vector<uint8_t> data;
+struct ClientCutTextMsg
+{
+    std::vector<uint8_t> data;
 };
 
-enum class encoding_type : uint32_t {
-  raw = 0x00,
-  copy_rectangle = 0x01,
-  rising_rectangle = 0x02,
-  corre = 0x04,
-  hextile = 0x05,
-  zlib = 0x06,
-  tight = 0x07,
-  zlibhex = 0x08,
-  ultra = 0x09,
-  zrle = 0x10,
-  zywrle = 0x011,
-  cache_enable = 0xFFFF0001,
-  xor_enable = 0xFFFF0006,
-  server_state_ultranvc = 0xFFFF8000,
-  enable_keepAlive = 0xFFFF8001,
-  enableftp_protocol_version = 0xFFFF8002,
-  tight_compress_level_0 = 0xFFFFFF00,
-  tight_compress_level_9 = 0xFFFFFF09,
-  x_cursor = 0xFFFFFF10,
-  rich_cursor = 0xFFFFFF11,
-  pointer_pos = 0xFFFFFF18,
-  last_rect = 0xFFFFFF20,
-  new_framebuffer_size = 0xFFFFFF21,
-  tight_quality_level_0 = 0xFFFFFFE0,
-  tight_quality_level_9 = 0xFFFFFFE9
+enum class encoding_type : uint32_t
+{
+    raw = 0x00,
+    copy_rectangle = 0x01,
+    rising_rectangle = 0x02,
+    corre = 0x04,
+    hextile = 0x05,
+    zlib = 0x06,
+    tight = 0x07,
+    zlibhex = 0x08,
+    ultra = 0x09,
+    zrle = 0x10,
+    zywrle = 0x011,
+    cache_enable = 0xFFFF0001,
+    xor_enable = 0xFFFF0006,
+    server_state_ultranvc = 0xFFFF8000,
+    enable_keepAlive = 0xFFFF8001,
+    enableftp_protocol_version = 0xFFFF8002,
+    tight_compress_level_0 = 0xFFFFFF00,
+    tight_compress_level_9 = 0xFFFFFF09,
+    x_cursor = 0xFFFFFF10,
+    rich_cursor = 0xFFFFFF11,
+    pointer_pos = 0xFFFFFF18,
+    last_rect = 0xFFFFFF20,
+    new_framebuffer_size = 0xFFFFFF21,
+    tight_quality_level_0 = 0xFFFFFFE0,
+    tight_quality_level_9 = 0xFFFFFFE9
 };
 
-struct FramebufferRectangle {
-  boost::endian::big_uint16_t x{};
-  boost::endian::big_uint16_t y{};
-  boost::endian::big_uint16_t width{};
-  boost::endian::big_uint16_t height{};
-  boost::endian::big_uint32_t encoding{};
-  std::vector<uint8_t> data;
+struct FramebufferRectangle
+{
+    boost::endian::big_uint16_t x{};
+    boost::endian::big_uint16_t y{};
+    boost::endian::big_uint16_t width{};
+    boost::endian::big_uint16_t height{};
+    boost::endian::big_uint32_t encoding{};
+    std::vector<uint8_t> data;
 };
 
-struct FramebufferUpdateMsg {
-  boost::endian::big_uint8_t messageType{};
-  std::vector<FramebufferRectangle> rectangles;
+struct FramebufferUpdateMsg
+{
+    boost::endian::big_uint8_t messageType{};
+    std::vector<FramebufferRectangle> rectangles;
 };
 
-inline std::string serialize(const FramebufferUpdateMsg& msg) {
-  // calculate the size of the needed vector for serialization
-  size_t vectorSize = 4;
-  for (const auto& rect : msg.rectangles) {
-    vectorSize += 12 + rect.data.size();
-  }
+inline std::string serialize(const FramebufferUpdateMsg& msg)
+{
+    // calculate the size of the needed vector for serialization
+    size_t vectorSize = 4;
+    for (const auto& rect : msg.rectangles)
+    {
+        vectorSize += 12 + rect.data.size();
+    }
 
-  std::string serialized(vectorSize, 0);
+    std::string serialized(vectorSize, 0);
 
-  size_t i = 0;
-  serialized[i++] = static_cast<char>(
-      server_to_client_message_type::framebuffer_update);  // Type
-  serialized[i++] = 0;                                     // Pad byte
-  boost::endian::big_uint16_t numberOfRectangles = msg.rectangles.size();
-  std::memcpy(&serialized[i], &numberOfRectangles, sizeof(numberOfRectangles));
-  i += sizeof(numberOfRectangles);
+    size_t i = 0;
+    serialized[i++] = static_cast<char>(
+        server_to_client_message_type::framebuffer_update); // Type
+    serialized[i++] = 0;                                    // Pad byte
+    boost::endian::big_uint16_t numberOfRectangles = msg.rectangles.size();
+    std::memcpy(&serialized[i], &numberOfRectangles,
+                sizeof(numberOfRectangles));
+    i += sizeof(numberOfRectangles);
 
-  for (const auto& rect : msg.rectangles) {
-    // copy the first part of the struct
-    size_t bufferSize =
-        sizeof(FramebufferRectangle) - sizeof(std::vector<uint8_t>);
-    std::memcpy(&serialized[i], &rect, bufferSize);
-    i += bufferSize;
+    for (const auto& rect : msg.rectangles)
+    {
+        // copy the first part of the struct
+        size_t bufferSize =
+            sizeof(FramebufferRectangle) - sizeof(std::vector<uint8_t>);
+        std::memcpy(&serialized[i], &rect, bufferSize);
+        i += bufferSize;
 
-    std::memcpy(&serialized[i], rect.data.data(), rect.data.size());
-    i += rect.data.size();
-  }
+        std::memcpy(&serialized[i], rect.data.data(), rect.data.size());
+        i += rect.data.size();
+    }
 
-  return serialized;
+    return serialized;
 }
 
-enum class VncState {
-  UNSTARTED,
-  AWAITING_CLIENT_VERSION,
-  AWAITING_CLIENT_AUTH_METHOD,
-  AWAITING_CLIENT_INIT_msg,
-  MAIN_LOOP
+enum class VncState
+{
+    UNSTARTED,
+    AWAITING_CLIENT_VERSION,
+    AWAITING_CLIENT_AUTH_METHOD,
+    AWAITING_CLIENT_INIT_msg,
+    MAIN_LOOP
 };
 
-class ConnectionMetadata {
- public:
-  ConnectionMetadata(){};
+class ConnectionMetadata
+{
+  public:
+    ConnectionMetadata(){};
 
-  VncState vncState{VncState::UNSTARTED};
+    VncState vncState{VncState::UNSTARTED};
 };
 
 using meta_list = std::vector<ConnectionMetadata>;
@@ -183,171 +204,219 @@
 
 ConnectionMetadata meta;
 
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...>& app) {
-  BMCWEB_ROUTE(app, "/kvmws")
-      .websocket()
-      .onopen([&](crow::websocket::Connection& conn) {
-        if (meta.vncState == VncState::UNSTARTED) {
-          meta.vncState = VncState::AWAITING_CLIENT_VERSION;
-          conn.sendBinary(rfb38VersionString);
-        } else {  // SHould never happen
-          conn.close();
-        }
-
-      })
-      .onclose(
-          [&](crow::websocket::Connection& conn, const std::string& reason) {
-            meta.vncState = VncState::UNSTARTED;
-          })
-      .onmessage([&](crow::websocket::Connection& conn, const std::string& data,
-                     bool is_binary) {
-        switch (meta.vncState) {
-          case VncState::AWAITING_CLIENT_VERSION: {
-            std::cout << "Client sent: " << data;
-            if (data == rfb38VersionString || data == rfb37VersionString) {
-              std::string authTypes{1,
-                                    (uint8_t)RfbAuthScheme::no_authentication};
-              conn.sendBinary(authTypes);
-              meta.vncState = VncState::AWAITING_CLIENT_AUTH_METHOD;
-            } else if (data == rfb33VersionString) {
-              // TODO(ed)  Support older protocols
-              meta.vncState = VncState::UNSTARTED;
-              conn.close();
-            } else {
-              // TODO(ed)  Support older protocols
-              meta.vncState = VncState::UNSTARTED;
-              conn.close();
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app)
+{
+    BMCWEB_ROUTE(app, "/kvmws")
+        .websocket()
+        .onopen([&](crow::websocket::Connection& conn) {
+            if (meta.vncState == VncState::UNSTARTED)
+            {
+                meta.vncState = VncState::AWAITING_CLIENT_VERSION;
+                conn.sendBinary(rfb38VersionString);
             }
-          } break;
-          case VncState::AWAITING_CLIENT_AUTH_METHOD: {
-            std::string securityResult{{0, 0, 0, 0}};
-            if (data[0] == (uint8_t)RfbAuthScheme::no_authentication) {
-              meta.vncState = VncState::AWAITING_CLIENT_INIT_msg;
-            } else {
-              // Mark auth as failed
-              securityResult[3] = 1;
-              meta.vncState = VncState::UNSTARTED;
+            else
+            { // SHould never happen
+                conn.close();
             }
-            conn.sendBinary(securityResult);
-          } break;
-          case VncState::AWAITING_CLIENT_INIT_msg: {
-            // Now send the server initialization
-            ServerInitializationMsg serverInitMsg{};
-            serverInitMsg.framebufferWidth = 800;
-            serverInitMsg.framebufferHeight = 600;
-            serverInitMsg.pixelFormat.bitsPerPixel = 32;
-            serverInitMsg.pixelFormat.isBigEndian = 0;
-            serverInitMsg.pixelFormat.isTrueColor = 1;
-            serverInitMsg.pixelFormat.redMax = 255;
-            serverInitMsg.pixelFormat.greenMax = 255;
-            serverInitMsg.pixelFormat.blueMax = 255;
-            serverInitMsg.pixelFormat.redShift = 16;
-            serverInitMsg.pixelFormat.greenShift = 8;
-            serverInitMsg.pixelFormat.blueShift = 0;
-            serverInitMsg.nameLength = 0;
-            std::cout << "size: " << sizeof(serverInitMsg);
-            // TODO(ed) this is ugly.  Crow should really have a span type
-            // interface
-            // to avoid the copy, but alas, today it does not.
-            std::string s(reinterpret_cast<char*>(&serverInitMsg),
-                          sizeof(serverInitMsg));
-            std::cout << "s.size() " << s.size();
-            conn.sendBinary(s);
-            meta.vncState = VncState::MAIN_LOOP;
-          } break;
-          case VncState::MAIN_LOOP: {
-            if (data.size() >= sizeof(client_to_server_msg_type)) {
-              auto type = static_cast<client_to_server_msg_type>(data[0]);
-              std::cout << "Received client message type "
-                        << static_cast<std::size_t>(type) << "\n";
-              switch (type) {
-                case client_to_server_msg_type::set_pixel_format: {
-                } break;
-
-                case client_to_server_msg_type::fix_color_map_entries: {
-                } break;
-                case client_to_server_msg_type::set_encodings: {
-                } break;
-                case client_to_server_msg_type::framebuffer_update_request: {
-                  // Make sure the buffer is long enough to handle what we're
-                  // about to do
-                  if (data.size() >= sizeof(FrameBufferUpdateReq) +
-                                         sizeof(client_to_server_msg_type)) {
-                    auto msg = reinterpret_cast<const FrameBufferUpdateReq*>(
-                        data.data() +  // NOLINT
-                        sizeof(client_to_server_msg_type));
-                    // TODO(ed) find a better way to do this deserialization
-
-                    // Todo(ed) lifecycle of the video puller and decoder
-                    // should be
-                    // with the websocket, not recreated every time
-                    ast_video::SimpleVideoPuller p;
-                    p.initialize();
-                    auto out = p.readVideo();
-                    ast_video::AstJpegDecoder d;
-                    d.decode(out.buffer, out.width, out.height, out.mode,
-                             out.ySelector, out.uvSelector);
-
-                    FramebufferUpdateMsg bufferUpdateMsg;
-
-                    // If the viewer is requesting a full update, force write
-                    // of all pixels
-
-                    FramebufferRectangle thisRect;
-                    thisRect.x = msg->xPosition;
-                    thisRect.y = msg->yPosition;
-                    thisRect.width = out.width;
-                    thisRect.height = out.height;
-                    thisRect.encoding =
-                        static_cast<uint8_t>(encoding_type::raw);
-                    std::cout << "Encoding is " << thisRect.encoding;
-                    thisRect.data.reserve(
-                        static_cast<std::size_t>(thisRect.width) *
-                        static_cast<std::size_t>(thisRect.height) * 4);
-                    std::cout << "Width " << out.width << " Height "
-                              << out.height;
-
-                    for (int i = 0; i < out.width * out.height; i++) {
-                      auto& pixel = d.outBuffer[i];
-                      thisRect.data.push_back(pixel.b);
-                      thisRect.data.push_back(pixel.g);
-                      thisRect.data.push_back(pixel.r);
-                      thisRect.data.push_back(0);
+        })
+        .onclose(
+            [&](crow::websocket::Connection& conn, const std::string& reason) {
+                meta.vncState = VncState::UNSTARTED;
+            })
+        .onmessage([&](crow::websocket::Connection& conn,
+                       const std::string& data, bool is_binary) {
+            switch (meta.vncState)
+            {
+                case VncState::AWAITING_CLIENT_VERSION:
+                {
+                    std::cout << "Client sent: " << data;
+                    if (data == rfb38VersionString ||
+                        data == rfb37VersionString)
+                    {
+                        std::string authTypes{
+                            1, (uint8_t)RfbAuthScheme::no_authentication};
+                        conn.sendBinary(authTypes);
+                        meta.vncState = VncState::AWAITING_CLIENT_AUTH_METHOD;
                     }
-
-                    bufferUpdateMsg.rectangles.push_back(std::move(thisRect));
-                    auto serialized = serialize(bufferUpdateMsg);
-
-                    conn.sendBinary(serialized);
-
-                  }  // TODO(Ed) handle error
-
+                    else if (data == rfb33VersionString)
+                    {
+                        // TODO(ed)  Support older protocols
+                        meta.vncState = VncState::UNSTARTED;
+                        conn.close();
+                    }
+                    else
+                    {
+                        // TODO(ed)  Support older protocols
+                        meta.vncState = VncState::UNSTARTED;
+                        conn.close();
+                    }
                 }
-
                 break;
+                case VncState::AWAITING_CLIENT_AUTH_METHOD:
+                {
+                    std::string securityResult{{0, 0, 0, 0}};
+                    if (data[0] == (uint8_t)RfbAuthScheme::no_authentication)
+                    {
+                        meta.vncState = VncState::AWAITING_CLIENT_INIT_msg;
+                    }
+                    else
+                    {
+                        // Mark auth as failed
+                        securityResult[3] = 1;
+                        meta.vncState = VncState::UNSTARTED;
+                    }
+                    conn.sendBinary(securityResult);
+                }
+                break;
+                case VncState::AWAITING_CLIENT_INIT_msg:
+                {
+                    // Now send the server initialization
+                    ServerInitializationMsg serverInitMsg{};
+                    serverInitMsg.framebufferWidth = 800;
+                    serverInitMsg.framebufferHeight = 600;
+                    serverInitMsg.pixelFormat.bitsPerPixel = 32;
+                    serverInitMsg.pixelFormat.isBigEndian = 0;
+                    serverInitMsg.pixelFormat.isTrueColor = 1;
+                    serverInitMsg.pixelFormat.redMax = 255;
+                    serverInitMsg.pixelFormat.greenMax = 255;
+                    serverInitMsg.pixelFormat.blueMax = 255;
+                    serverInitMsg.pixelFormat.redShift = 16;
+                    serverInitMsg.pixelFormat.greenShift = 8;
+                    serverInitMsg.pixelFormat.blueShift = 0;
+                    serverInitMsg.nameLength = 0;
+                    std::cout << "size: " << sizeof(serverInitMsg);
+                    // TODO(ed) this is ugly.  Crow should really have a span
+                    // type interface to avoid the copy, but alas, today it does
+                    // not.
+                    std::string s(reinterpret_cast<char*>(&serverInitMsg),
+                                  sizeof(serverInitMsg));
+                    std::cout << "s.size() " << s.size();
+                    conn.sendBinary(s);
+                    meta.vncState = VncState::MAIN_LOOP;
+                }
+                break;
+                case VncState::MAIN_LOOP:
+                {
+                    if (data.size() >= sizeof(client_to_server_msg_type))
+                    {
+                        auto type =
+                            static_cast<client_to_server_msg_type>(data[0]);
+                        std::cout << "Received client message type "
+                                  << static_cast<std::size_t>(type) << "\n";
+                        switch (type)
+                        {
+                            case client_to_server_msg_type::set_pixel_format:
+                            {
+                            }
+                            break;
 
-                case client_to_server_msg_type::key_event: {
-                } break;
+                            case client_to_server_msg_type::
+                                fix_color_map_entries:
+                            {
+                            }
+                            break;
+                            case client_to_server_msg_type::set_encodings:
+                            {
+                            }
+                            break;
+                            case client_to_server_msg_type::
+                                framebuffer_update_request:
+                            {
+                                // Make sure the buffer is long enough to handle
+                                // what we're about to do
+                                if (data.size() >=
+                                    sizeof(FrameBufferUpdateReq) +
+                                        sizeof(client_to_server_msg_type))
+                                {
+                                    auto msg = reinterpret_cast<
+                                        const FrameBufferUpdateReq*>(
+                                        data.data() + // NOLINT
+                                        sizeof(client_to_server_msg_type));
+                                    // TODO(ed) find a better way to do this
+                                    // deserialization
 
-                case client_to_server_msg_type::pointer_event: {
-                } break;
+                                    // Todo(ed) lifecycle of the video puller
+                                    // and decoder should be with the websocket,
+                                    // not recreated every time
+                                    ast_video::SimpleVideoPuller p;
+                                    p.initialize();
+                                    auto out = p.readVideo();
+                                    ast_video::AstJpegDecoder d;
+                                    d.decode(out.buffer, out.width, out.height,
+                                             out.mode, out.ySelector,
+                                             out.uvSelector);
 
-                case client_to_server_msg_type::client_cut_text: {
-                } break;
+                                    FramebufferUpdateMsg bufferUpdateMsg;
 
-                default:
-                  break;
-              }
+                                    // If the viewer is requesting a full
+                                    // update, force write of all pixels
+
+                                    FramebufferRectangle thisRect;
+                                    thisRect.x = msg->xPosition;
+                                    thisRect.y = msg->yPosition;
+                                    thisRect.width = out.width;
+                                    thisRect.height = out.height;
+                                    thisRect.encoding = static_cast<uint8_t>(
+                                        encoding_type::raw);
+                                    std::cout << "Encoding is "
+                                              << thisRect.encoding;
+                                    thisRect.data.reserve(
+                                        static_cast<std::size_t>(
+                                            thisRect.width) *
+                                        static_cast<std::size_t>(
+                                            thisRect.height) *
+                                        4);
+                                    std::cout << "Width " << out.width
+                                              << " Height " << out.height;
+
+                                    for (int i = 0; i < out.width * out.height;
+                                         i++)
+                                    {
+                                        auto& pixel = d.outBuffer[i];
+                                        thisRect.data.push_back(pixel.b);
+                                        thisRect.data.push_back(pixel.g);
+                                        thisRect.data.push_back(pixel.r);
+                                        thisRect.data.push_back(0);
+                                    }
+
+                                    bufferUpdateMsg.rectangles.push_back(
+                                        std::move(thisRect));
+                                    auto serialized =
+                                        serialize(bufferUpdateMsg);
+
+                                    conn.sendBinary(serialized);
+
+                                } // TODO(Ed) handle error
+                            }
+
+                            break;
+
+                            case client_to_server_msg_type::key_event:
+                            {
+                            }
+                            break;
+
+                            case client_to_server_msg_type::pointer_event:
+                            {
+                            }
+                            break;
+
+                            case client_to_server_msg_type::client_cut_text:
+                            {
+                            }
+                            break;
+
+                            default:
+                                break;
+                        }
+                    }
+                }
+                break;
+                case VncState::UNSTARTED:
+                    // Error?  TODO
+                    break;
             }
-
-          } break;
-          case VncState::UNSTARTED:
-            // Error?  TODO
-            break;
-        }
-
-      });
+        });
 }
-}  // namespace kvm
-}  // namespace crow
\ No newline at end of file
+} // namespace kvm
+} // namespace crow
\ No newline at end of file
diff --git a/include/webassets.hpp b/include/webassets.hpp
index 5eabffe..7f1c1f5 100644
--- a/include/webassets.hpp
+++ b/include/webassets.hpp
@@ -1,137 +1,161 @@
 #pragma once
 
-#include <experimental/filesystem>
-#include <fstream>
-#include <string>
 #include <crow/app.h>
 #include <crow/http_request.h>
 #include <crow/http_response.h>
 #include <crow/routing.h>
+
 #include <boost/algorithm/string/replace.hpp>
 #include <boost/container/flat_set.hpp>
+#include <experimental/filesystem>
+#include <fstream>
+#include <string>
 
-namespace crow {
-namespace webassets {
+namespace crow
+{
+namespace webassets
+{
 
 namespace filesystem = std::experimental::filesystem;
 
-struct CmpStr {
-  bool operator()(const char* a, const char* b) const {
-    return std::strcmp(a, b) < 0;
-  }
+struct CmpStr
+{
+    bool operator()(const char* a, const char* b) const
+    {
+        return std::strcmp(a, b) < 0;
+    }
 };
 
 static boost::container::flat_set<std::string> routes;
 
-template <typename... Middlewares>
-void requestRoutes(Crow<Middlewares...>& app) {
-  const static boost::container::flat_map<const char*, const char*, CmpStr>
-      contentTypes{
-          {{".css", "text/css;charset=UTF-8"},
-           {".html", "text/html;charset=UTF-8"},
-           {".js", "text/html;charset=UTF-8"},
-           {".png", "image/png;charset=UTF-8"},
-           {".woff", "application/x-font-woff"},
-           {".woff2", "application/x-font-woff2"},
-           {".gif", "image/gif"},
-           {".ico", "image/x-icon"},
-           {".ttf", "application/x-font-ttf"},
-           {".svg", "image/svg+xml"},
-           {".eot", "application/vnd.ms-fontobject"},
-           {".xml", "application/xml"},
-           {".jpg", "image/jpeg"},
-           {".jpeg", "image/jpeg"},
-           {".json", "application/json"},
-           // dev tools don't care about map type, setting to json causes
-           // browser to show as text
-           // https://stackoverflow.com/questions/19911929/what-mime-type-should-i-use-for-javascript-source-map-files
-           {".map", "application/json"}}};
-  filesystem::path rootpath{"/usr/share/www/"};
-  filesystem::recursive_directory_iterator dirIter(rootpath);
-  // In certain cases, we might have both a gzipped version of the file AND a
-  // non-gzipped version.  To avoid duplicated routes, we need to make sure we
-  // get the gzipped version first.  Because the gzipped path should be longer
-  // than the non gzipped path, if we sort in Ascending order, we should be
-  // guaranteed to get the gzip version first.
-  std::vector<filesystem::directory_entry> paths(filesystem::begin(dirIter),
-                                                 filesystem::end(dirIter));
-  std::sort(paths.rbegin(), paths.rend());
+template <typename... Middlewares> void requestRoutes(Crow<Middlewares...>& app)
+{
+    const static boost::container::flat_map<const char*, const char*, CmpStr>
+        contentTypes{
+            {{".css", "text/css;charset=UTF-8"},
+             {".html", "text/html;charset=UTF-8"},
+             {".js", "text/html;charset=UTF-8"},
+             {".png", "image/png;charset=UTF-8"},
+             {".woff", "application/x-font-woff"},
+             {".woff2", "application/x-font-woff2"},
+             {".gif", "image/gif"},
+             {".ico", "image/x-icon"},
+             {".ttf", "application/x-font-ttf"},
+             {".svg", "image/svg+xml"},
+             {".eot", "application/vnd.ms-fontobject"},
+             {".xml", "application/xml"},
+             {".jpg", "image/jpeg"},
+             {".jpeg", "image/jpeg"},
+             {".json", "application/json"},
+             // dev tools don't care about map type, setting to json causes
+             // browser to show as text
+             // https://stackoverflow.com/questions/19911929/what-mime-type-should-i-use-for-javascript-source-map-files
+             {".map", "application/json"}}};
+    filesystem::path rootpath{"/usr/share/www/"};
+    filesystem::recursive_directory_iterator dirIter(rootpath);
+    // In certain cases, we might have both a gzipped version of the file AND a
+    // non-gzipped version.  To avoid duplicated routes, we need to make sure we
+    // get the gzipped version first.  Because the gzipped path should be longer
+    // than the non gzipped path, if we sort in Ascending order, we should be
+    // guaranteed to get the gzip version first.
+    std::vector<filesystem::directory_entry> paths(filesystem::begin(dirIter),
+                                                   filesystem::end(dirIter));
+    std::sort(paths.rbegin(), paths.rend());
 
-  for (const filesystem::directory_entry& dir : paths) {
-    filesystem::path absolutePath = dir.path();
-    filesystem::path relativePath{
-        absolutePath.string().substr(rootpath.string().size() - 1)};
-    if (filesystem::is_directory(dir)) {
-      // don't recurse into hidden directories or symlinks
-      if (boost::starts_with(dir.path().filename().string(), ".") ||
-          filesystem::is_symlink(dir)) {
-        dirIter.disable_recursion_pending();
-      }
-    } else if (filesystem::is_regular_file(dir)) {
-      std::string extension = relativePath.extension();
-      filesystem::path webpath = relativePath;
-      const char* contentEncoding = nullptr;
-
-      if (extension == ".gz") {
-        webpath = webpath.replace_extension("");
-        // Use the non-gzip version for determining content type
-        extension = webpath.extension().string();
-        contentEncoding = "gzip";
-      }
-
-      if (boost::starts_with(webpath.filename().string(), "index.")) {
-        webpath = webpath.parent_path();
-        if (webpath.string().size() == 0 || webpath.string().back() != '/') {
-          // insert the non-directory version of this path
-          routes.insert(webpath);
-          webpath += "/";
+    for (const filesystem::directory_entry& dir : paths)
+    {
+        filesystem::path absolutePath = dir.path();
+        filesystem::path relativePath{
+            absolutePath.string().substr(rootpath.string().size() - 1)};
+        if (filesystem::is_directory(dir))
+        {
+            // don't recurse into hidden directories or symlinks
+            if (boost::starts_with(dir.path().filename().string(), ".") ||
+                filesystem::is_symlink(dir))
+            {
+                dirIter.disable_recursion_pending();
+            }
         }
-      }
+        else if (filesystem::is_regular_file(dir))
+        {
+            std::string extension = relativePath.extension();
+            filesystem::path webpath = relativePath;
+            const char* contentEncoding = nullptr;
 
-      std::pair<boost::container::flat_set<std::string>::iterator, bool>
-          inserted = routes.insert(webpath);
-
-      if (!inserted.second) {
-        // Got a duplicated path.  This is expected in certain situations
-        BMCWEB_LOG_DEBUG << "Got duplicated path " << webpath;
-        continue;
-      }
-      const char* contentType = nullptr;
-
-      auto contentTypeIt = contentTypes.find(extension.c_str());
-      if (contentTypeIt == contentTypes.end()) {
-        BMCWEB_LOG_ERROR << "Cannot determine content-type for " << absolutePath
-                         << " with extension " << extension;
-      } else {
-        contentType = contentTypeIt->second;
-      }
-
-      app.routeDynamic(webpath)(
-          [absolutePath, contentType, contentEncoding](const crow::Request& req,
-                                                       crow::Response& res) {
-            if (contentType != nullptr) {
-              res.addHeader("Content-Type", contentType);
+            if (extension == ".gz")
+            {
+                webpath = webpath.replace_extension("");
+                // Use the non-gzip version for determining content type
+                extension = webpath.extension().string();
+                contentEncoding = "gzip";
             }
 
-            if (contentEncoding != nullptr) {
-              res.addHeader("Content-Encoding", contentEncoding);
+            if (boost::starts_with(webpath.filename().string(), "index."))
+            {
+                webpath = webpath.parent_path();
+                if (webpath.string().size() == 0 ||
+                    webpath.string().back() != '/')
+                {
+                    // insert the non-directory version of this path
+                    routes.insert(webpath);
+                    webpath += "/";
+                }
             }
 
-            // res.set_header("Cache-Control", "public, max-age=86400");
-            std::ifstream inf(absolutePath);
-            if (!inf) {
-              BMCWEB_LOG_DEBUG << "failed to read file";
-              res.result(boost::beast::http::status::internal_server_error);
-              res.end();
-              return;
+            std::pair<boost::container::flat_set<std::string>::iterator, bool>
+                inserted = routes.insert(webpath);
+
+            if (!inserted.second)
+            {
+                // Got a duplicated path.  This is expected in certain
+                // situations
+                BMCWEB_LOG_DEBUG << "Got duplicated path " << webpath;
+                continue;
+            }
+            const char* contentType = nullptr;
+
+            auto contentTypeIt = contentTypes.find(extension.c_str());
+            if (contentTypeIt == contentTypes.end())
+            {
+                BMCWEB_LOG_ERROR << "Cannot determine content-type for "
+                                 << absolutePath << " with extension "
+                                 << extension;
+            }
+            else
+            {
+                contentType = contentTypeIt->second;
             }
 
-            res.body() = {std::istreambuf_iterator<char>(inf),
-                          std::istreambuf_iterator<char>()};
-            res.end();
-          });
+            app.routeDynamic(webpath)(
+                [absolutePath, contentType, contentEncoding](
+                    const crow::Request& req, crow::Response& res) {
+                    if (contentType != nullptr)
+                    {
+                        res.addHeader("Content-Type", contentType);
+                    }
+
+                    if (contentEncoding != nullptr)
+                    {
+                        res.addHeader("Content-Encoding", contentEncoding);
+                    }
+
+                    // res.set_header("Cache-Control", "public, max-age=86400");
+                    std::ifstream inf(absolutePath);
+                    if (!inf)
+                    {
+                        BMCWEB_LOG_DEBUG << "failed to read file";
+                        res.result(
+                            boost::beast::http::status::internal_server_error);
+                        res.end();
+                        return;
+                    }
+
+                    res.body() = {std::istreambuf_iterator<char>(inf),
+                                  std::istreambuf_iterator<char>()};
+                    res.end();
+                });
+        }
     }
-  }
-}  // namespace webassets
-}  // namespace webassets
-}  // namespace crow
+} // namespace webassets
+} // namespace webassets
+} // namespace crow