dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hdsd / scd / scd_command_reader.cpp
diff --git a/dol/src/dol/visitor/hdsd/scd/scd_command_reader.cpp b/dol/src/dol/visitor/hdsd/scd/scd_command_reader.cpp
new file mode 100644 (file)
index 0000000..7c9d904
--- /dev/null
@@ -0,0 +1,119 @@
+#include "scd_command_reader.h"
+
+#include <arpa/inet.h>
+
+#include "scd_logging.h"
+
+
+scd_command_reader::scd_command_reader():
+    _command(NULL), _is_reading(false), _success(false) {}
+
+
+scd_command_reader::~scd_command_reader()
+{
+    if (_is_reading || _success)
+    {
+        delete _command;
+    }
+}
+
+
+void scd_command_reader::set_socket(scd_socket& sock) { _socket = &sock; }
+
+
+void scd_command_reader::read()
+{
+    if (!_is_reading)
+    {
+        if (_success)
+            return;
+
+        _is_reading = true;
+        _header_read = false;
+        _remaining = SCD_CM_HEADER;
+        _off = 0;
+        _command = new scd_command;
+    }
+
+    // receive header
+    if (!_header_read)
+    {
+        // read header
+        size_t read = _socket->recv(_header_buf + _off, _remaining);
+        _remaining -= read;
+        _off += read;
+
+        if (_remaining == 0)
+        {
+            // read values from buffer
+            uint16_t* intbuf = reinterpret_cast<uint16_t*>(_header_buf);
+            _command->_type = ntohs( intbuf[0] );
+            _command->_subtype = ntohs( intbuf[1] );
+            _command->_msglen = ntohs( intbuf[2] );
+
+            _header_read = true;
+
+            // allocate buffer for further receiption
+            if (_command->_msglen > 0)
+            {
+                if (_command->_msglen > SCD_CM_MAXLEN)
+                {
+                    // illegal command
+                    _command->_msglen = 0;
+                    delete _command;
+                    _is_reading = false;
+                }
+                else
+                {
+                    _command->_msg = new char[_command->_msglen];
+                    _remaining = _command->_msglen;
+                    _off = 0;
+                }
+            }
+            else
+            {
+                // command without payload
+                _command->_msglen = 0; // to prevent negative values
+                _remaining = 0;
+                _is_reading = false;
+                _success = true;
+            }
+        }
+    }
+
+    // receive msg
+    if (_header_read && _is_reading)
+    {
+        size_t read = _socket->recv(_command->_msg + _off, _remaining);
+        _remaining -= read;
+        _off += read;
+
+        if (_remaining == 0)
+        {
+            _is_reading = false;
+            _success = true;
+        }
+    }
+
+} // read()
+
+
+bool scd_command_reader::is_reading() { return _is_reading; }
+
+
+bool scd_command_reader::has_command() { return _success; }
+
+
+scd_command* scd_command_reader::get_command()
+{
+    if (!_success)
+    {
+        return NULL;
+    }
+    else
+    {
+        _success = false;
+        return _command;
+    }
+
+} // get_command()