Exemple #1
0
void ProtocolGameBase::onConnect()
{
	auto output = OutputMessagePool::getOutputMessage();
	static std::random_device rd;
	static std::ranlux24 generator(rd());
	static std::uniform_int_distribution<uint16_t> randNumber(0x00, 0xFF);

	// Skip checksum
	output->skipBytes(sizeof(uint32_t));

	// Packet length & type
	output->add<uint16_t>(0x0006);
	output->addByte(0x1F);

	// Add timestamp & random number
	m_challengeTimestamp = static_cast<uint32_t>(time(nullptr));
	output->add<uint32_t>(m_challengeTimestamp);

	m_challengeRandom = randNumber(generator);
	output->addByte(m_challengeRandom);

	// Go back and write checksum
	output->skipBytes(-12);
	output->add<uint32_t>(adlerChecksum(output->getOutputBuffer() + sizeof(uint32_t), 8));

	send(std::move(output));
}
Exemple #2
0
void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password, uint16_t version)
{
	Account account;
	if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
		disconnectClient("Account name or password is not correct.", version);
		return;
	}

	auto output = OutputMessagePool::getOutputMessage();
	//Update premium days
	Game::updatePremium(account);

	const std::string& motd = g_config.getString(ConfigManager::MOTD);
	if (!motd.empty()) {
		//Add MOTD
		output->addByte(0x14);

		std::ostringstream ss;
		ss << g_game.getMotdNum() << "\n" << motd;
		output->addString(ss.str());
	}

	//Add session key
	output->addByte(0x28);
	output->addString(accountName + "\n" + password);

	//Add char list
	output->addByte(0x64);

	output->addByte(1); // number of worlds

	output->addByte(0); // world id
	output->addString(g_config.getString(ConfigManager::SERVER_NAME));
	output->addString(g_config.getString(ConfigManager::IP));
	output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
	output->addByte(0);

	uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
	output->addByte(size);
	for (uint8_t i = 0; i < size; i++) {
		output->addByte(0);
		output->addString(account.characters[i]);
	}

	//Add premium days
	output->addByte(0);

	output->addByte(g_config.getBoolean(ConfigManager::FREE_PREMIUM) || account.premiumDays > 0);
	auto time = std::chrono::system_clock::now() + std::chrono::hours(account.premiumDays * 24);
	std::chrono::seconds timestamp = std::chrono::duration_cast<std::chrono::seconds>(time.time_since_epoch());
	output->add<uint32_t>(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : timestamp.count());

	send(output);

	disconnect();
}
Exemple #3
0
void ProtocolLogin::getCharacterList(uint32_t accountName, const std::string& password)
{
	uint32_t serverIp = serverIPs[0].first;
	for (uint32_t i = 0; i < serverIPs.size(); i++) {
		if ((serverIPs[i].first & serverIPs[i].second) == (getConnection()->getIP() & serverIPs[i].second)) {
			serverIp = serverIPs[i].first;
			break;
		}
	}

	Account account;
	if (!IOLoginData::loginserverAuthentication(accountName, password, account)) {
		disconnectClient("Account name or password is not correct.");
		return;
	}

	auto output = OutputMessagePool::getOutputMessage();
	//Update premium days
	Game::updatePremium(account);

	const std::string& motd = g_config.getString(ConfigManager::MOTD);
	if (!motd.empty()) {
		//Add MOTD
		output->addByte(0x14);

		std::ostringstream ss;
		ss << g_game.getMotdNum() << "\n" << motd;
		output->addString(ss.str());
	}

	//Add char list
	output->addByte(0x64);

	uint8_t size = std::min<size_t>(std::numeric_limits<uint8_t>::max(), account.characters.size());
	output->addByte(size);
	for (uint8_t i = 0; i < size; i++) {
		output->addString(account.characters[i]);
		output->addString(g_config.getString(ConfigManager::SERVER_NAME));
		output->add<uint32_t>(serverIp);
		output->add<uint16_t>(g_config.getNumber(ConfigManager::GAME_PORT));
	}

	//Add premium days
	if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
		output->add<uint16_t>(0xFFFF); //client displays free premium
	} else {
		output->add<uint16_t>(account.premiumDays);
	}

	send(output);

	disconnect();
}
Exemple #4
0
void CtrlrSysExEditor::setLength (const int newLength)
{

    currentMessageLength = newLength;

    messageLength->setValue (currentMessageLength, dontSendNotification);

    if (byteValueLabels.size() < currentMessageLength)
    {
        for (int i=byteValueLabels.size(); i<currentMessageLength; i++)
        {
            byteValueLabels.add (addByte (splitMessage[i]));
        }
    }
    else if (byteValueLabels.size() > currentMessageLength)
    {
        byteValueLabels.removeLast (byteValueLabels.size() - currentMessageLength);
    }

    rows.clear();
    for (int i=0; i<=byteValueLabels.size()/16; i++)
    {
        SysExRow *r = new SysExRow(i);
        addAndMakeVisible(r);
        rows.add (r);
    }

    resized();

    sendChangeMessage();
}
Exemple #5
0
unsigned AVIFileSink::addWord(unsigned word) {
  // Add "word" to the file in little-endian order:
  addByte(word); addByte(word>>8);
  addByte(word>>16); addByte(word>>24);

  return 4;
}
	void BitWriter::addBytes(int num, unsigned char* bytes)
	{
		for(int i = 0; i < num; i++)
		{
			addByte(bytes[i]);
		}
	}
void NetworkMessage::addItem(const Item* item)
{
	const ItemType& it = Item::items[item->getID()];

	add<uint16_t>(it.clientId);
	addByte(0xFF); // MARK_UNMARKED

	if (it.stackable) {
		addByte(std::min<uint16_t>(0xFF, item->getItemCount()));
	} else if (it.isSplash() || it.isFluidContainer()) {
		addByte(fluidMap[item->getFluidType() & 7]);
	}

	if (it.isAnimation) {
		addByte(0xFE); // random phase (0xFF for async)
	}
}
Exemple #8
0
bool RingBuffer::addBytes(uint8_t *b, int count)
{
  for (int i=0; i<count; i++) {
    if (!addByte(b[i]))
      return false;
  }
  return true;
}
Exemple #9
0
void OffsetOrderedList::append(Offset offset)
{
  // At any position in the list there's a current offset.
  // The offset is initially zero.
  // A byte of 255 says add 255 to the current offset.
  // A byte B < 255, says that there's an item in the list whose
  // offset is the current offset + B, and that B + 1 should be
  // added to the current offset.
  Offset curOffset = blocks_.size() > 0  ? blocks_.back()->offset : 0;
  ASSERT(offset >= curOffset);
  Offset count = offset - curOffset;
  while (count >= 255) {
    addByte(255);
    count -= 255;
  }
  addByte(count);
}
Exemple #10
0
 ALWAYS_INLINE void addBytePrint(uint64_t total, const char* extra = "") {
   if (!(addByte() & 0xFFFF)) {
     // 4 updates per second.
     // if (clock() - prev_time > 250) {
     // 	printRatio(total, extra);
     // }
   }
 }
Exemple #11
0
         bool XMLRPC::setCommand(t_int const _command)
         {
            reset();
#if BTG_EXTERNALIZATION_DEBUG
            BTG_NOTICE(logWrapper(), "XMLRPC::setCommand() " << _command << " :" <<getCommandName(_command));
#endif // BTG_EXTERNALIZATION_DEBUG
            XMLRPC_RequestSetMethodName(xmlrpc_request, getCommandName(_command).c_str());
            return addByte(_command);
         }
void NetworkMessage::addItem(uint16_t id, uint8_t count)
{
	const ItemType& it = Item::items[id];

	add<uint16_t>(it.clientId);

	addByte(0xFF); // MARK_UNMARKED

	if (it.stackable) {
		addByte(count);
	} else if (it.isSplash() || it.isFluidContainer()) {
		addByte(fluidMap[count & 7]);
	}

	if (it.isAnimation) {
		addByte(0xFE); // random phase (0xFF for async)
	}
}
void ProtocolOld::disconnectClient(const std::string& message)
{
	auto output = OutputMessagePool::getOutputMessage();
	output->addByte(0x0A);
	output->addString(message);
	send(output);

	disconnect();
}
Exemple #14
0
void ProtocolLogin::disconnectClient(const std::string& message, uint16_t version)
{
	auto output = OutputMessagePool::getOutputMessage();

	output->addByte(version >= 1076 ? 0x0B : 0x0A);
	output->addString(message);
	send(output);

	disconnect();
}
Exemple #15
0
autoBlock_t *makeCryptoRandBlock(uint count)
{
	autoBlock_t *block = createBlock(count);

	while(count)
	{
		addByte(block, getCryptoByte());
		count--;
	}
	return block;
}
/** converts interger to bytes and adds the bytes to the output stream.
 *
 *  @param interger value to convert to byte.
 *  @param stream output stream to write the bytes into.
 *  @returns 0 that the byte was successfully entered.
 */
   int intToByte(int integer, Stream *stream){
   int i = integer;
   int j;
   unsigned char add;

   for(j = 0; j < 4; j++){
      add = (i & MASK);
      addByte(stream, add);
      i = i >> 8;
   }
   return 0;
}
boolean Protocol::parseByte(uint8_t data) {
  switch(m_mode) {
  case MODE_HEADER0:
  case MODE_PAYLOAD_READY: // If we get new data before a payload is handled, just start over.
    if(data == HEADER0) {
      reset();
      m_mode = MODE_HEADER1;
      updateCRC(data);
    }
    else {
    }
    break;
  case MODE_HEADER1:
    if(data == HEADER1) {
      m_mode = MODE_LENGTH;
      updateCRC(data);
    }
    else {
      reset();
    }
    break;
  case MODE_LENGTH:
    if(data <= MAX_DATA_SIZE && data > 0) {
      m_mode = MODE_PAYLOAD;
      m_expectedLength = data;
      updateCRC(data);
    }
    else {
      reset();
    }
    break;
  case MODE_PAYLOAD:
    addByte(data);
    if(m_packetLength >= m_expectedLength) {  // TODO: why >= and not just ==?
      m_mode = MODE_CRC;
    } 
    break;
  case MODE_CRC:
    if(data == m_crc) {
      m_mode = MODE_PAYLOAD_READY;
    }
    else {
      reset();
    }
    break;
  default:
    reset();
  }

  return (m_mode == MODE_PAYLOAD_READY);
}
Exemple #18
0
static autoBlock_t *GetSabun(autoBlock_t *fileImage1, autoBlock_t *fileImage2)
{
	autoBlock_t *sabun = newBlock();
	uint index;

	for(index = 0; index < getSize(fileImage2); index++)
	{
		int chr1 = refByte(fileImage1, index);
		int chr2 = getByte(fileImage2, index);

		addByte(sabun, chr1 ^ chr2);
	}
	return sabun;
}
Exemple #19
0
 forceinline void addBytePrint(uint64_t total, const char*extra = "") {
   if (!(addByte() & 0xFFFF)) {
   }
 }
void NetworkMessage::addDouble(double value, uint8_t precision/* = 2*/)
{
	addByte(precision);
	add<uint32_t>((value * std::pow(static_cast<float>(10), precision)) + std::numeric_limits<int32_t>::max());
}
void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string& characterName)
{
	auto output = OutputMessagePool::getOutputMessage();

	if (requestedInfo & REQUEST_BASIC_SERVER_INFO) {
		output->addByte(0x10);
		output->addString(g_config.getString(ConfigManager::SERVER_NAME));
		output->addString(g_config.getString(ConfigManager::IP));
		output->addString(std::to_string(g_config.getNumber(ConfigManager::LOGIN_PORT)));
	}

	if (requestedInfo & REQUEST_OWNER_SERVER_INFO) {
		output->addByte(0x11);
		output->addString(g_config.getString(ConfigManager::OWNER_NAME));
		output->addString(g_config.getString(ConfigManager::OWNER_EMAIL));
	}

	if (requestedInfo & REQUEST_MISC_SERVER_INFO) {
		output->addByte(0x12);
		output->addString(g_config.getString(ConfigManager::MOTD));
		output->addString(g_config.getString(ConfigManager::LOCATION));
		output->addString(g_config.getString(ConfigManager::URL));
		output->add<uint64_t>((OTSYS_TIME() - ProtocolStatus::start) / 1000);
	}

	if (requestedInfo & REQUEST_PLAYERS_INFO) {
		output->addByte(0x20);
		output->add<uint32_t>(g_game.getPlayersOnline());
		output->add<uint32_t>(g_config.getNumber(ConfigManager::MAX_PLAYERS));
		output->add<uint32_t>(g_game.getPlayersRecord());
	}

	if (requestedInfo & REQUEST_MAP_INFO) {
		output->addByte(0x30);
		output->addString(g_config.getString(ConfigManager::MAP_NAME));
		output->addString(g_config.getString(ConfigManager::MAP_AUTHOR));
		uint32_t mapWidth, mapHeight;
		g_game.getMapDimensions(mapWidth, mapHeight);
		output->add<uint16_t>(mapWidth);
		output->add<uint16_t>(mapHeight);
	}

	if (requestedInfo & REQUEST_EXT_PLAYERS_INFO) {
		output->addByte(0x21); // players info - online players list

		const auto& players = g_game.getPlayers();
		output->add<uint32_t>(players.size());
		for (const auto& it : players) {
			output->addString(it.second->getName());
			output->add<uint32_t>(it.second->getLevel());
		}
	}

	if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) {
		output->addByte(0x22); // players info - online status info of a player
		if (g_game.getPlayerByName(characterName) != nullptr) {
			output->addByte(0x01);
		} else {
			output->addByte(0x00);
		}
	}

	if (requestedInfo & REQUEST_SERVER_SOFTWARE_INFO) {
		output->addByte(0x23); // server software info
		output->addString(STATUS_SERVER_NAME);
		output->addString(STATUS_SERVER_VERSION);
		output->addString(CLIENT_VERSION_STR);
	}
	send(output);
	disconnect();
}
Exemple #22
0
unsigned AVIFileSink::add4ByteString(char const* str) {
  addByte(str[0]); addByte(str[1]); addByte(str[2]);
  addByte(str[3] == '\0' ? ' ' : str[3]); // e.g., for "AVI "

  return 4;
}
Exemple #23
0
unsigned AVIFileSink::addHalfWord(unsigned short halfWord) {
  // Add "halfWord" to the file in little-endian order:
  addByte((unsigned char)halfWord); addByte((unsigned char)(halfWord>>8));

  return 2;
}
void NetworkMessage::addPosition(const Position& pos)
{
	add<uint16_t>(pos.x);
	add<uint16_t>(pos.y);
	addByte(pos.z);
}
/** Takes a unsigned character and adds it to the output stream.
 *
 *  @param add character of byte to add to the stream.
 *  @param stream output stream to write the byte into.
 *  @returns 0 that the byte was successfully entered.
 */
int charToByte(unsigned char add, Stream *stream){

   addByte(stream, add);

   return 0;
}
Exemple #26
0
SigNat sign(PublicKey group, RogueKey rogue, Secret secret, Cert cert, Message msg)
{
  char bsn[MAX_CHAR_ARRAY_LENGTH], m[MAX_CHAR_ARRAY_LENGTH];
  char error[MAX_CHAR_ARRAY_LENGTH],c_h[MAX_CHAR_ARRAY_LENGTH];
  char hash[MAX_CHAR_ARRAY_LENGTH], inner[MAX_CHAR_ARRAY_LENGTH];
  BigInt n_v, c, sv, sf0, sf1, se, see, sew, sr, ser, sw;
  Origin b;
  BigInt n,gPrime,g,h,r0,r1,s;
  BigInt biga,e, p2;
  BigInt f0,f1,v;
  Tuple wr,rf0rf1,rwrr,rewrer;
  BigInt bigt1, bigt2, temp1, temp2, temp3, temp4, temp5, temp6, temp7, w, r;
  BigInt zeta,bign_V,rf0,rf1, rv, bigt2inv, tilde_TPrime2,n_t;
  BigInt tilde_T1t, tilde_rf, tilde_N_V,rw,rr,re,ree,rew, rer,hinv, tilde_T1, tilde_T2;
  Hash hashPub, hashHost ,hashTpm1, hashTpm2;
  Responses ss;
  SigNat signat;

  strcpy(bsn,msg.bsn); strcpy(m,msg.m);
  b = msg.b; n_v = msg.n_v;
  if(noOfBits(n_v) > hash_bits){
    strcpy(error,"n_v out of bounds");
    Abort(error);
  }
  n=group.n; gPrime=group.gPrime; g=group.g; h=group.h;
  r0=group.r0; r1=group.r1; s=group.s;
  
  biga = cert.biga; e = cert.e;
  f0 = secret.f; f1=secret.s; v=secret.t;
  wr = pick2(rsa_modulus_bits+distribution_bits);
  w = wr.r; r = wr.m;
  bigt1 = BImodMult(biga,BImodPower(h,wr.r,n),n);
  
  temp1 = BIpower(g,w); temp2 = BIpower(h,e); temp3 = BIpower(gPrime,r);
  temp4 = BImul(temp1, temp2); temp5 = BImul(temp4, temp3);
  bigt2 = BImod(temp5,n);
  
  zeta = base(bsn,rogue);
  bign_V = tag(rogue,zeta,f0,f1);

  rv = pick(random_bits+distribution_bits+hash_bits);
  rf0rf1 = pick2(halfkeyBits+distribution_bits+hash_bits);
  rf0 = rf0rf1.r; rf1 = rf0rf1.m;
  
  temp1 = BIpower(r0,rf0); temp2 = BIpower(r1,rf1); temp3 = BIpower(s,rv);
  temp4 = BImul(temp1, temp2); temp5 = BImul(temp4, temp3);
  tilde_T1t = BImod(temp5,n);

  temp1 = BIshiftLeft(rf1,halfkeyBits);
  temp2 = BIadd(rf0, temp1);
  tilde_rf = BImod(temp2,rogue.rho);
  tilde_N_V = BImodPower(zeta,tilde_rf,rogue.bigGamma);
  
  re = pick(prime_random_bits+distribution_bits+hash_bits);
  ree = pick(2*prime_total_bits+distribution_bits+hash_bits+1);
  rwrr = pick2(rsa_modulus_bits+2*distribution_bits+hash_bits);
  rw = rwrr.r; rr = rwrr.m;
  rewrer = pick2(prime_total_bits+rsa_modulus_bits+2*distribution_bits+hash_bits+1);
  rew = rewrer.r; rer = rewrer.m;
  hinv = BImodInv(h,n);

  temp1 = tilde_T1t; temp2 = BIpower(bigt1,re); temp3 = BIpower(hinv,rew);
  temp4 = BImul(temp1, temp2); temp5 = BImul(temp4, temp3);
  tilde_T1 = BImod(temp5,n);

  temp1 = BIpower(g,rw); temp2 = BIpower(h,re); temp3 = BIpower(gPrime,rr);
  temp4 = BImul(temp1, temp2); temp5 = BImul(temp4, temp3);
  tilde_T2 = BImod(temp5,n);
  
  bigt2inv = BImodInv(bigt2,n);
  temp1 = BIpower(bigt2inv,re); temp2 = BIpower(g,rew); temp3 = BIpower(h,ree); temp4 = BIpower(gPrime,rer);
  temp5 = BImul(temp1, temp2); temp6 = BImul(temp5, temp3); temp7 = BImul(temp6, temp4);
  tilde_TPrime2 = BImod(temp7,n);

  //hash public inputs
  hashPub = getSha1Hash();
  addBI(&hashPub,group.n); addBI(&hashPub,group.g); addBI(&hashPub,group.gPrime); addBI(&hashPub,group.h);
  addBI(&hashPub,group.r0); addBI(&hashPub,group.r1); addBI(&hashPub,group.s); addBI(&hashPub,group.z);
  addBI(&hashPub,rogue.gamma); addBI(&hashPub,rogue.bigGamma); addBI(&hashPub,rogue.rho);
  addBI(&hashPub,zeta); addBI(&hashPub,bigt1); addBI(&hashPub,bigt2); addBI(&hashPub,bign_V);
  strcpy(hash,hashResult(hashPub));

  //hash host inputs
  hashHost = getSha1Hash();
  addBI(&hashHost,tilde_T1); addBI(&hashHost,tilde_T2); addBI(&hashHost,tilde_TPrime2);
  addBI(&hashHost,tilde_N_V); addBI(&hashHost,n_v);
  strcpy(c_h,hashResult(hashHost));

  n_t = pick(distribution_bits);
  
  hashTpm1 = getSha1Hash();
  addBytes(&hashTpm1,c_h); 
  addBI(&hashTpm1,n_t); 
  strcpy(inner,hashResult(hashTpm1));
  hashTpm2 = getSha1Hash();
  addBytes(&hashTpm2,inner); 
  if(b == Card)
    addByte(&hashTpm2,0);
  else if (b == Verifier)
    addByte(&hashTpm2,1);
  else
    ;
  addBytes(&hashTpm2, m);
  c = BItoNumber(hashResult(hashTpm2));
  sv = rval(rv,v,c);
  sf0 = rval(rf0,f0,c);
  sf1 = rval(rf1,f1,c);
  p2 = BIshiftLeft(BItoNumber("1"),prime_total_bits-1);
  se = rval(re,BIsub(e, p2),c);
  see = rval(ree,BImul(e,e),c);
  sw = rval(rw,w,c);
  sew = rval(rew,BImul(e,w),c);
  sr = rval(rr,r,c);
  ser = rval(rer,BImul(e,r),c);

  ss.sv = sv; 
  ss.sf0 = sf0; 
  ss.sf1 = sf1; 
  ss.se = se; 
  ss.see = see; 
  ss.sw = sw; 
  ss.sew = sew; 
  ss.sr = sr; 
  ss.ser = ser;
  
  signat.zeta = zeta;
  signat.bigt1 = bigt1;
  signat.bigt2 = bigt2;
  signat.bign_V = bign_V;
  signat.c = c;
  signat.n_t = n_t;
  signat.ss = ss;

  return signat;
}
Exemple #27
0
    void run()
    {
        if (_arguments.count() == 1) {
            console.write("Usage: run [-c] <name of file to send>\n");
            return;
        }
        int fileNameArgument = 1;
        bool comFile = false;
        if (_arguments[1] == String("-c")) {
            comFile = true;
            fileNameArgument = 2;
        }
        String fileName = _arguments[fileNameArgument];
        String data = File(fileName).contents();
        int l = data.length();

        _com = AutoHandle(CreateFile(
            L"COM3",
            GENERIC_READ | GENERIC_WRITE,
            0,              // must be opened with exclusive-access
            NULL,           // default security attributes
            OPEN_EXISTING,  // must use OPEN_EXISTING
            0,              // not overlapped I/O
            NULL),          // hTemplate must be NULL for comm devices
            String("COM port"));

        //IF_ZERO_THROW(SetupComm(_com, 1024, 1024));

        DCB deviceControlBlock;
        SecureZeroMemory(&deviceControlBlock, sizeof(DCB));
        IF_ZERO_THROW(GetCommState(_com, &deviceControlBlock));
        deviceControlBlock.DCBlength = sizeof(DCB);
        deviceControlBlock.BaudRate = 19200;
        deviceControlBlock.fBinary = TRUE;
        deviceControlBlock.fParity = FALSE;
        deviceControlBlock.fOutxCtsFlow = FALSE;
        deviceControlBlock.fOutxDsrFlow = FALSE;
        // DTR_CONTROL_ENABLE causes Arduino to reset on connect
        //deviceControlBlock.fDtrControl = DTR_CONTROL_ENABLE;
        deviceControlBlock.fDtrControl = DTR_CONTROL_DISABLE;
        deviceControlBlock.fDsrSensitivity = FALSE;
        deviceControlBlock.fTXContinueOnXoff = TRUE;
        deviceControlBlock.fOutX = TRUE;
        deviceControlBlock.fInX = TRUE;
        deviceControlBlock.fErrorChar = FALSE;
        deviceControlBlock.fNull = FALSE;
        deviceControlBlock.fRtsControl = RTS_CONTROL_DISABLE;
        deviceControlBlock.fAbortOnError = TRUE;
        deviceControlBlock.wReserved = 0;
        deviceControlBlock.ByteSize = 8;
        deviceControlBlock.Parity = NOPARITY;
        deviceControlBlock.StopBits = ONESTOPBIT;
        deviceControlBlock.XonChar = 17;
        deviceControlBlock.XoffChar = 19;
        IF_ZERO_THROW(SetCommState(_com, &deviceControlBlock));

        //COMMTIMEOUTS timeOuts;
        //SecureZeroMemory(&timeOuts, sizeof(COMMTIMEOUTS));
        //timeOuts.ReadIntervalTimeout = 0;
        //timeOuts.ReadTotalTimeoutMultiplier = 0;
        //timeOuts.ReadTotalTimeoutConstant = 0;
        //IF_ZERO_THROW(SetCommTimeouts(_com, &timeOuts));

        IF_ZERO_THROW(SetCommMask(_com, EV_RXCHAR));
        //IF_ZERO_THROW(ClearCommBreak(_com));
        //IF_ZERO_THROW(PurgeComm(_com, PURGE_RXCLEAR | PURGE_TXCLEAR));
        //IF_ZERO_THROW(FlushFileBuffers(_com));
        //DWORD error;
        //IF_ZERO_THROW(ClearCommError(_com, &error, NULL));

        //_com.set(CreateFile(L"run.output", GENERIC_WRITE, 0, NULL,
        //    CREATE_ALWAYS, 0, NULL));

        Sleep(2000);

        ReaderThread thread(this);
        //thread.start();

        sendByte(0x7f);      // Put Arduino in raw mode
        sendByte(0x76);      // Clear keyboard buffer
        sendByte(0x72);      // Put Arduino in tester mode
        //sendByte(0x78);      // Put Arduino in tester raw mode

        // The buffer in the Arduino only holds 255 bytes, so we have to send
        // it in chunks. We do this by buffering the data on the host PC side,
        // and sending the buffer when it's full or when we're done.
        _bufferCount = 0;
        // When running a .com file, we need the instruction pointer to start
        // at 0x100. We do this by prepending 0x100 NOP bytes at the beginning.
        // In DOS this area would contain the Program Segment Prefix structure.
        console.write(hex(l) + "\n");
        Byte checkSum = 0;
        if (comFile) {
            addLength(l + 0x100);
            for (int i = 0; i < 0x100; ++i) {
                addByte(0x90);
                checkSum += 0x90;
            }
        }
        else
            addLength(l);
        for (int i = 0; i < l; ++i) {
            addByte(data[i]);       // Send data byte
            checkSum += data[i];
            if ((i & 0xff) == 0)
                console.write(".");
        }
        addByte(checkSum);
        flush();
        IF_ZERO_THROW(FlushFileBuffers(_com));

        console.write("Upload complete.\n");
        // Dump bytes from COM port to stdout until we receive ^Z
        //thread.join();
    }
	void BitWriter::operator+=(LByte byte_in)
	{
		addByte(byte_in);
	}