incremental
diff --git a/src/base64_test.cpp b/src/base64_test.cpp
index 2758dfa..e21655e 100644
--- a/src/base64_test.cpp
+++ b/src/base64_test.cpp
@@ -47,7 +47,7 @@
 }
 
 // Tests using pathalogical cases for all escapings
-TEST(Base64, NaugtyStrings) {
+TEST(Base64, NaugtyStringsEncodeDecode) {
   std::string base64_string;
   std::string decoded_string;
   for (auto& str : naughty_strings) {
@@ -56,3 +56,12 @@
     EXPECT_EQ(str, decoded_string);
   }
 }
+
+// Tests using pathalogical cases for all escapings
+TEST(Base64, NaugtyStringsPathological) {
+  std::string base64_string;
+  std::string decoded_string;
+  for (auto& str : naughty_strings) {
+    base64::base64_decode(str, base64_string);
+  }
+}
\ No newline at end of file
diff --git a/src/getvideo_main.cpp b/src/getvideo_main.cpp
new file mode 100644
index 0000000..f73ee30
--- /dev/null
+++ b/src/getvideo_main.cpp
@@ -0,0 +1,67 @@
+#include <video.h>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
+
+namespace AstVideo {
+class VideoPuller {
+ public:
+  VideoPuller() {}
+
+  void initialize() {
+    std::cout << "Opening /dev/video\n";
+    file.open("/dev/video", std::ios::out | std::ios::in | std::ios::binary);
+    if (!file.is_open()) {
+      std::cout << "Failed to open /dev/video\n";
+    }
+    IMAGE_INFO image_info{};
+
+    file.write(reinterpret_cast<char*>(&image_info), sizeof(image_info));
+
+    file.read(reinterpret_cast<char*>(&image_info), sizeof(image_info));
+    
+    if (file){
+        std::cout << "Read succeeded\n";
+    }
+    
+    auto pt = reinterpret_cast<char*>(&image_info);
+
+    for(int i=0; i<sizeof(image_info); i++){
+        std::cout << std::hex << std::setfill('0') << std::setw(2) << int(*(pt + i)) << " ";
+    }
+    
+    std::cout << "\n";
+
+    std::cout << "typedef struct _video_features {\n";
+    std::cout << "short jpg_fmt: " << image_info.parameter.features.jpg_fmt << "\n";
+    std::cout << "short lumin_tbl;" << image_info.parameter.features.lumin_tbl << "\n";
+    std::cout << "short chrom_tbl;" << image_info.parameter.features.chrom_tbl << "\n";
+    std::cout << "short tolerance_noise;" << image_info.parameter.features.tolerance_noise << "\n";
+    std::cout << "int w;" << image_info.parameter.features.w << "\n";
+    std::cout << "int h;" << image_info.parameter.features.h << "\n";
+    //std::cout << "unsigned char *buf;" << image_info.parameter.features.buf << "\n";
+    std::cout << "} FEATURES_TAG;\n";
+
+    std::cout << "typedef struct _image_info {";
+    std::cout << "short do_image_refresh;" << image_info.do_image_refresh << "\n";
+    std::cout << "char qc_valid;" << image_info.qc_valid << "\n";
+    std::cout << "unsigned int len;" << image_info.len << "\n";
+    std::cout << "int crypttype;" << image_info.crypttype << "\n";
+    std::cout << "char cryptkey[16];" << image_info.cryptkey << "\n";
+    std::cout << "union {\n";
+    std::cout << "    FEATURES_TAG features;\n";
+    std::cout << "    AST_CURSOR_TAG cursor_info;\n";
+    std::cout << "} parameter;\n";
+    std::cout << "} IMAGE_INFO;\n";
+    std::cout << std::endl;
+  }
+  std::fstream file;
+};
+}
+
+int main() {
+  AstVideo::VideoPuller p;
+  p.initialize();
+
+  return 1;
+}
\ No newline at end of file
diff --git a/src/token_authorization_middleware.cpp b/src/token_authorization_middleware.cpp
index 40ade75..30d12c5 100644
--- a/src/token_authorization_middleware.cpp
+++ b/src/token_authorization_middleware.cpp
@@ -1,9 +1,9 @@
+#include <random>
 #include <unordered_map>
-
 #include <boost/algorithm/string/predicate.hpp>
 
 #include <token_authorization_middleware.hpp>
-
+#include <crow/logging.h>
 #include <base64.hpp>
 
 namespace crow {
@@ -17,16 +17,19 @@
     res.code = 401;
     res.end();
   };
+
+  LOG(DEBUG) << "Got route " << req.url;
+
   if (req.url == "/" || boost::starts_with(req.url, "/static/")){
     //TODO this is total hackery to allow the login page to work before the user
     // is authenticated.  Also, it will be quite slow for all pages instead of
     // a one time hit for the whitelist entries.
     // Ideally, this should be done in the url router handler, with tagged routes
     // for the whitelist entries.
+    // Another option would be to whitelist a minimal
     return;
   }
 
-  
   if (req.url == "/login") {
     if (req.method != HTTPMethod::POST){
       return_unauthorized();
@@ -39,8 +42,10 @@
       }
       auto username = login_credentials["username"].s();
       auto password = login_credentials["password"].s();
-
+      
+      // TODO(ed) pull real passwords from PAM
       if (username == "dude" && password == "dude"){
+        //TODO(ed) the RNG should be initialized at start, not every time we want a token
         std::random_device rand;
         random_bytes_engine rbe;
         std::string token('a', 20);
@@ -49,7 +54,6 @@
         base64::base64_encode(token, encoded_token);
         ctx.auth_token = encoded_token;
         this->auth_token2 = encoded_token;
-
       } else {
         return_unauthorized();
         return;
@@ -82,6 +86,7 @@
       return_unauthorized();
       return;
     }
+    // else let the request continue unharmed
   }
 }
 
diff --git a/src/udpclient.cpp b/src/udpclient.cpp
new file mode 100644
index 0000000..5f04a9a
--- /dev/null
+++ b/src/udpclient.cpp
@@ -0,0 +1,99 @@
+//
+// client.cpp
+// ~~~~~~~~~~
+//
+// Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#include <array>
+#include <boost/array.hpp>
+#include <boost/asio.hpp>
+#include <iostream>
+
+using boost::asio::ip::udp;
+
+int main(int argc, char* argv[]) {
+  try {
+    boost::asio::io_service io_service;
+
+    udp::resolver resolver(io_service);
+    udp::resolver::query query(udp::v4(), "10.243.48.31", "623");
+    udp::endpoint receiver_endpoint = *resolver.resolve(query);
+
+    udp::socket socket(io_service);
+    socket.open(udp::v4());
+
+    std::string username = "root";
+    std::string password = "two";
+    uint8_t privilege_level = 4;
+    uint8_t seq_number = 1;
+    uint8_t command = 0x38;  // AUTH_CAP_CMD
+    // std::array<uint8_t> ChannelAuthCap{0x80 | (0x0f & channel),
+    // privilege_level&0x0f};
+
+    uint8_t srcaddr = 0x81;  // 0xC8?
+    uint8_t dstaddr = 0x20;
+
+    uint8_t net_function = 0x06;
+    uint8_t lun = 0;
+
+    uint8_t netfn_lun = static_cast<uint8_t>((net_function << 2) + lun);
+    uint8_t channel_number =
+        0x0E + 0x80;  // E is defined in spec as this channel
+                      // 0x80 is requesting IPMI 2.0
+    uint8_t byte1 = static_cast<uint8_t>(channel_number | 0x80);
+    boost::array<uint8_t, 2> payload{byte1, privilege_level};
+
+    int payload_sum = 0;
+    for (auto element : payload) {
+      payload_sum += element;
+    }
+
+    uint8_t chk1 = (1 + ((~(dstaddr + netfn_lun)) & 0xff)) & 0xff;
+    uint8_t chk2 = srcaddr + (seq_number << 2) + command + payload_sum;
+    chk2 = (1 + ((~chk2) & 0xff)) & 0xff;
+
+    uint8_t ptype = 0;
+    uint8_t session_id = 0;
+
+    uint8_t seq_number2 = 0;
+    uint8_t seq_number_lun = seq_number << 2 + lun;
+
+    uint8_t seq2 = 0xff;  //????
+    uint8_t rmcp_class = 0x07;
+
+    std::vector<uint8_t> send_buf = {
+        0x06,       0x00,           seq2,
+        rmcp_class, 0x06,           ptype,
+        session_id, seq_number2,    0x00,
+        0x00,       0x00,           0x00,
+        0x00,       0x00,           0x09,
+        0x00,       dstaddr,        netfn_lun,
+        chk1,       srcaddr,        seq_number_lun,
+        command,    channel_number, privilege_level,
+        chk2};
+
+    for (auto character : send_buf) {
+      std::cout << std::hex << static_cast<unsigned>(character) << " ";
+    }
+    std::cout << std::endl;
+    socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);
+
+    boost::array<unsigned char, 32> recv_buf;
+    udp::endpoint sender_endpoint;
+    size_t len =
+        socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);
+
+    for (auto character : recv_buf) {
+      std::cout << std::hex << static_cast<unsigned>(character) << " ";
+    }
+
+    std::cout << std::endl;
+  } catch (std::exception& e) {
+    std::cerr << e.what() << std::endl;
+  }
+
+  return 0;
+}
\ No newline at end of file
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index c5c3eed..c55bd4d 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -20,6 +20,8 @@
 #include "crow/utility.h"
 #include "crow/websocket.h"
 
+#include "app_type.hpp"
+
 #include "color_cout_g3_sink.hpp"
 #include "token_authorization_middleware.hpp"
 #include "webassets.hpp"
@@ -40,7 +42,11 @@
 static const std::string rfb_3_7_version_string = "RFB 003.007\n";
 static const std::string rfb_3_8_version_string = "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 pixel_format_struct {
   boost::endian::big_uint8_t bits_per_pixel;
@@ -163,12 +169,14 @@
   serialized[i++] = 0;  // Type
   serialized[i++] = 0;  // Pad byte
   boost::endian::big_uint16_t number_of_rectangles;
-  std::memcpy(&serialized[i], &number_of_rectangles, sizeof(number_of_rectangles));
+  std::memcpy(&serialized[i], &number_of_rectangles,
+              sizeof(number_of_rectangles));
   i += sizeof(number_of_rectangles);
 
   for (const auto& rect : msg.rectangles) {
     // copy the first part of the struct
-    size_t buffer_size = sizeof(framebuffer_rectangle) - sizeof(std::vector<uint8_t>);
+    size_t buffer_size =
+        sizeof(framebuffer_rectangle) - sizeof(std::vector<uint8_t>);
     std::memcpy(&serialized[i], &rect, buffer_size);
     i += buffer_size;
 
@@ -179,7 +187,13 @@
   return serialized;
 }
 
-enum class VncState { UNSTARTED, AWAITING_CLIENT_VERSION, AWAITING_CLIENT_AUTH_METHOD, AWAITING_CLIENT_INIT_MESSAGE, MAIN_LOOP };
+enum class VncState {
+  UNSTARTED,
+  AWAITING_CLIENT_VERSION,
+  AWAITING_CLIENT_AUTH_METHOD,
+  AWAITING_CLIENT_INIT_MESSAGE,
+  MAIN_LOOP
+};
 
 class connection_metadata {
  public:
@@ -190,15 +204,17 @@
 
 int main(int argc, char** argv) {
   auto worker(g3::LogWorker::createLogWorker());
-
-  auto handle = worker->addDefaultLogger(argv[0], "/tmp/");
+  std::string logger_name("bmcweb");
+  std::string folder("/tmp/");
+  auto handle = worker->addDefaultLogger(logger_name, folder);
   g3::initializeLogging(worker.get());
-  auto sink_handle = worker->addSink(std::make_unique<crow::ColorCoutSink>(), &crow::ColorCoutSink::ReceiveLogMessage);
+  auto sink_handle = worker->addSink(std::make_unique<crow::ColorCoutSink>(),
+                                     &crow::ColorCoutSink::ReceiveLogMessage);
 
   std::string ssl_pem_file("server.pem");
   ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file);
 
-  crow::App<crow::TokenAuthorizationMiddleware> app;
+  BmcAppType app;
   crow::webassets::request_routes(app);
 
   crow::logger::setLogLevel(crow::LogLevel::INFO);
@@ -213,7 +229,8 @@
 
   CROW_ROUTE(app, "/login")
       .methods("POST"_method)([&](const crow::request& req) {
-        auto auth_token = app.get_context<crow::TokenAuthorizationMiddleware>(req).auth_token;
+        auto auth_token =
+            app.get_context<crow::TokenAuthorizationMiddleware>(req).auth_token;
         crow::json::wvalue x;
         x["token"] = auth_token;
 
@@ -262,21 +279,29 @@
         meta.vnc_state = VncState::AWAITING_CLIENT_VERSION;
         conn.send_binary(rfb_3_8_version_string);
       })
-      .onclose([&](crow::websocket::connection& conn, const std::string& reason) {
-
-      })
-      .onmessage([&](crow::websocket::connection& conn, const std::string& data, bool is_binary) {
+      .onclose(
+          [&](crow::websocket::connection& conn, const std::string& reason) {
+            meta.vnc_state = VncState::UNSTARTED;
+          })
+      .onmessage([&](crow::websocket::connection& conn, const std::string& data,
+                     bool is_binary) {
         switch (meta.vnc_state) {
           case VncState::AWAITING_CLIENT_VERSION: {
-            std::cout << "Client sent: " << data;
-            if (data == rfb_3_8_version_string || data == rfb_3_7_version_string) {
-              std::string auth_types{1, (uint8_t)RfbAuthScheme::no_authentication};
+            LOG(DEBUG) << "Client sent: " << data;
+            if (data == rfb_3_8_version_string ||
+                data == rfb_3_7_version_string) {
+              std::string auth_types{1,
+                                     (uint8_t)RfbAuthScheme::no_authentication};
               conn.send_binary(auth_types);
               meta.vnc_state = VncState::AWAITING_CLIENT_AUTH_METHOD;
             } else if (data == rfb_3_3_version_string) {
-              // TODO(ed)
+              // TODO(ed)  Support older protocols
+              meta.vnc_state = VncState::UNSTARTED;
+              conn.close();
             } else {
-              // TODO(ed)
+              // TODO(ed)  Support older protocols
+              meta.vnc_state = VncState::UNSTARTED;
+              conn.close();
             }
           } break;
           case VncState::AWAITING_CLIENT_AUTH_METHOD: {
@@ -305,10 +330,12 @@
             server_init_msg.pixel_format.green_shift = 8;
             server_init_msg.pixel_format.blue_shift = 0;
             server_init_msg.name_length = 0;
-            std::cout << "size: " << sizeof(server_init_msg);
-            // TODO(ed) this is ugly.  Crow should really have a span type interface
+            LOG(DEBUG) << "size: " << sizeof(server_init_msg);
+            // 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*>(&server_init_msg), sizeof(server_init_msg));
+            std::string s(reinterpret_cast<char*>(&server_init_msg),
+                          sizeof(server_init_msg));
             LOG(DEBUG) << "s.size() " << s.size();
             conn.send_binary(s);
             meta.vnc_state = VncState::MAIN_LOOP;
@@ -316,7 +343,7 @@
           case VncState::MAIN_LOOP: {
             if (data.size() >= sizeof(client_to_server_message_type)) {
               auto type = static_cast<client_to_server_message_type>(data[0]);
-              std::cout << "Got type " << (uint32_t)type << "\n";
+              LOG(DEBUG) << "Got type " << (uint32_t)type << "\n";
               switch (type) {
                 case client_to_server_message_type::set_pixel_format: {
                 } break;
@@ -325,21 +352,29 @@
                 } break;
                 case client_to_server_message_type::set_encodings: {
                 } break;
-                case client_to_server_message_type::framebuffer_update_request: {
-                  // Make sure the buffer is long enough to handle what we're about to do
-                  if (data.size() >= sizeof(frame_buffer_update_request_message) + sizeof(client_to_server_message_type)) {
-                    auto msg = reinterpret_cast<const frame_buffer_update_request_message*>(data.data() + sizeof(client_to_server_message_type));
+                case client_to_server_message_type::
+                    framebuffer_update_request: {
+                  // Make sure the buffer is long enough to handle what we're
+                  // about to do
+                  if (data.size() >=
+                      sizeof(frame_buffer_update_request_message) +
+                          sizeof(client_to_server_message_type)) {
+                    auto msg = reinterpret_cast<
+                        const frame_buffer_update_request_message*>(
+                        data.data() + sizeof(client_to_server_message_type));
 
-                    std::cout << "framebuffer_update_request_message\n";
-                    std::cout << "    incremental=" << msg->incremental << "\n";
-                    std::cout << "    x=" << msg->x_position;
-                    std::cout << " y=" << msg->y_position << "\n";
-                    std::cout << "    width=" << msg->width;
-                    std::cout << " height=" << msg->height << "\n";
+                    LOG(DEBUG) << "framebuffer_update_request_message\n";
+                    LOG(DEBUG) << "    incremental=" << msg->incremental
+                               << "\n";
+                    LOG(DEBUG) << "    x=" << msg->x_position;
+                    LOG(DEBUG) << " y=" << msg->y_position << "\n";
+                    LOG(DEBUG) << "    width=" << msg->width;
+                    LOG(DEBUG) << " height=" << msg->height << "\n";
 
                     framebuffer_update_message buffer_update_message;
 
-                    // If the viewer is requesting a full update, force write of all
+                    // If the viewer is requesting a full update, force write of
+                    // all
                     // pixels
 
                     framebuffer_rectangle this_rect;
@@ -347,20 +382,29 @@
                     this_rect.y = msg->y_position;
                     this_rect.width = msg->width;
                     this_rect.height = msg->height;
-                    this_rect.encoding = static_cast<uint8_t>(encoding_type::raw);
+                    this_rect.encoding =
+                        static_cast<uint8_t>(encoding_type::raw);
 
-                    this_rect.data.reserve(this_rect.width * this_rect.height * 4);
+                    this_rect.data.reserve(this_rect.width * this_rect.height *
+                                           4);
 
-                    for (unsigned int x_index = 0; x_index < this_rect.width; x_index++) {
-                      for (unsigned int y_index = 0; y_index < this_rect.height; y_index++) {
-                        this_rect.data.push_back(static_cast<uint8_t>(0));                            // Blue
-                        this_rect.data.push_back(static_cast<uint8_t>(0));                            // Green
-                        this_rect.data.push_back(static_cast<uint8_t>(x_index * 0xFF / msg->width));  // RED
-                        this_rect.data.push_back(static_cast<uint8_t>(0));                            // UNUSED
+                    for (unsigned int x_index = 0; x_index < this_rect.width;
+                         x_index++) {
+                      for (unsigned int y_index = 0; y_index < this_rect.height;
+                           y_index++) {
+                        this_rect.data.push_back(
+                            static_cast<uint8_t>(0));  // Blue
+                        this_rect.data.push_back(
+                            static_cast<uint8_t>(0));  // Green
+                        this_rect.data.push_back(static_cast<uint8_t>(
+                            x_index * 0xFF / msg->width));  // RED
+                        this_rect.data.push_back(
+                            static_cast<uint8_t>(0));  // UNUSED
                       }
                     }
 
-                    buffer_update_message.rectangles.push_back(std::move(this_rect));
+                    buffer_update_message.rectangles.push_back(
+                        std::move(this_rect));
                     auto serialized = serialize(buffer_update_message);
 
                     conn.send_binary(serialized);
@@ -397,23 +441,38 @@
       .onopen([&](crow::websocket::connection& conn) {
 
       })
-      .onclose([&](crow::websocket::connection& conn, const std::string& reason) {
+      .onclose(
+          [&](crow::websocket::connection& conn, const std::string& reason) {
 
-      })
-      .onmessage([&](crow::websocket::connection& conn, const std::string& data, bool is_binary) {
+          })
+      .onmessage([&](crow::websocket::connection& conn, const std::string& data,
+                     bool is_binary) {
         boost::asio::io_service io_service;
-        boost::asio::ip::udp::udp::socket socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0));
-        boost::asio::ip::udp::resolver resolver(io_service);
-        boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), "10.243.48.31", "623");
-        boost::asio::ip::udp::resolver::iterator iter = resolver.resolve(query);
-        socket.send_to(boost::asio::buffer(data), *iter);
+        using boost::asio::ip::udp;
+        udp::resolver resolver(io_service);
+        udp::resolver::query query(udp::v4(), "10.243.48.31", "623");
+        udp::endpoint receiver_endpoint = *resolver.resolve(query);
+
+        udp::socket socket(io_service);
+        socket.open(udp::v4());
+
+        socket.send_to(boost::asio::buffer(data), receiver_endpoint);
+
+        std::array<char, 255> recv_buf;
+
+        udp::endpoint sender_endpoint;
+        size_t len =
+            socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);
+        // TODO(ed) THis is ugly.  Find a way to not make a copy (ie, use
+        // std::string::data())
+        std::string str(std::begin(recv_buf), std::end(recv_buf));
+        LOG(DEBUG) << "Got " << str << "back \n";
+        conn.send_binary(str);
+
       });
 
-  auto rules = app.get_rules();
-  for (auto& rule : rules) {
-    LOG(DEBUG) << "Static route: " << rule;
-  }
-
-  // app.port(18080).ssl(std::move(get_ssl_context(ssl_pem_file))).concurrency(4).run();
-  app.port(18080).concurrency(4).run();
+  app.port(18080)
+      //.ssl(std::move(ensuressl::get_ssl_context(ssl_pem_file)))
+      .run();
+  // app.port(18080).run();
 }