void Connection::Entry(CPoint point) { int floatSize = sizeof(float); int clientNoLength = 2; int positionLength = floatSize * 2; int dataLength = clientNoLength + positionLength; int length = COMMUNICATION_HEADER_LENGTH + dataLength; int clientNo = m_clientNo; ToLittleEndian((char *)&dataLength, sizeof(int)); ToLittleEndian((char *)&clientNo, sizeof(int)); ToLittleEndian((char *)&point.x, floatSize); ToLittleEndian((char *)&point.y, floatSize); char data[length]; data[0] = 0x00; data[1] = CommunicationType_Entry; data[2] = ((char *)&dataLength)[0]; data[3] = ((char *)&dataLength)[1]; data[4] = ((char *)&clientNo)[0]; data[5] = ((char *)&clientNo)[1]; for (int i = 0; i < floatSize; i++) { data[6 + i] = ((char *)&point.x)[i]; } for (int j = 0; j < floatSize; j++) { data[6 + floatSize + j] = ((char *)&point.y)[j]; } m_pSocketUDP->CreateBroadcast(m_port); m_pSocketUDP->SendData(data, length); }
void Connection::EntryResponse(bool isValid, int clientNo) { int dataLength = 2; int floatSize = sizeof(float); char temporaryBuffer[1024] = {0}; int temporaryLength = 0; // 全クライアント番号とクライアントの座標を送信する for (int i = 0; i < MAX_MULTI_PLAYER; i++) { if (0 == m_pClients[i] || clientNo == i) { continue; } CPoint position; if (!m_pDelegate->GetClientPosition(i, &position)) { continue; } unsigned short no = i; ToLittleEndian((char *)&no, sizeof(unsigned short)); ToLittleEndian((char *)&position.x, floatSize); ToLittleEndian((char *)&position.y, floatSize); temporaryBuffer[temporaryLength + 0] = ((char *)&no)[0]; temporaryBuffer[temporaryLength + 1] = ((char *)&no)[1]; for (int j = 0; j < (floatSize * 2); j++) { if (j < floatSize) { temporaryBuffer[temporaryLength + 2 + j] = ((char *)&position.x)[j]; } else { temporaryBuffer[temporaryLength + 2 + j] = ((char *)&position.y)[j - floatSize]; } } temporaryLength += 2 + (floatSize * 2); } dataLength += temporaryLength; int length = COMMUNICATION_HEADER_LENGTH + dataLength; ToLittleEndian((char *)&dataLength, sizeof(int)); ToLittleEndian((char *)&floatSize, sizeof(int)); char data[length]; data[0] = 0x00; data[1] = CommunicationType_EntryResponse; data[2] = ((char *)&dataLength)[0]; data[3] = ((char *)&dataLength)[1]; data[4] = (isValid) ? 0x01 : 0x00; data[5] = ((char *)&floatSize)[0]; memcpy(&data[6], &temporaryBuffer[0], temporaryLength); m_pSocketUDP->CreateSender(m_pClients[clientNo]->pIP, m_pClients[clientNo]->port); m_pSocketUDP->SendData(data, length); }
void HPRC4LikeCipher::Init(const uint8 *key, uint32 size) { // align key to 32 bits std::vector<uint32> keycopy((size + sizeof(uint32) - 1) / sizeof(uint32)); DEBUG(ASSERT(keycopy.size() * sizeof(uint32) >= size)); // the last 3 bytes may be incomplete, null those before copying keycopy[keycopy.size() - 1] = 0; memcpy(&keycopy[0], key, size); #if IS_BIG_ENDIAN for(uint32 i = 0; i < keycopy.size(); ++i) ToLittleEndian(keycopy[i]); #endif MTRand mt; mt.seed((uint32*)&keycopy[0], keycopy.size()); for(uint32 i = 0; i < 256; ++i) _sbox[i] = i | (mt.randInt() << 8); // lowest bit is always the exchange index, like in original RC4 uint32 a = 0, b = 0; for(uint32 i = 0; i < std::max<uint32>(256, size); ++i) { b += key[a] + _sbox[i & 0xFF]; iswap(_sbox[i & 0xFF], _sbox[b & 0xFF]); ++a; a %= size; } }
void Connection::Exit() { int dataLength = 2; int clientNo = m_clientNo; ToLittleEndian((char *)&dataLength, sizeof(int)); ToLittleEndian((char *)&clientNo, sizeof(int)); char data[6] = {0}; data[0] = 0x00; data[1] = CommunicationType_Exit; data[2] = ((char *)&dataLength)[0]; data[3] = ((char *)&dataLength)[1]; data[4] = ((char *)&clientNo)[0]; data[5] = ((char *)&clientNo)[1]; m_pSocketUDP->CreateBroadcast(m_port); m_pSocketUDP->SendData(data, 6); }
void Connection::Search(RetryConnection *pRetryConnection) { if (!IsUnknown() || 0 == CSocket::GetIP()) { return; } if (0 == pRetryConnection) { pRetryConnection = new RetryConnection(10, 3, CommunicationType_Search); m_retryConnections.push_back(pRetryConnection); } else { pRetryConnection->counter = 10; } const char *pIP = CSocket::GetIP(); unsigned short port = m_port; int portLength = 2; int ipLength = (int)(strlen(pIP) + 1); int dataLength = portLength + ipLength; int length = COMMUNICATION_HEADER_LENGTH + dataLength; ToLittleEndian((char *)&dataLength, sizeof(int)); ToLittleEndian((char *)&port, sizeof(unsigned short)); char data[length]; data[0] = 0x00; data[1] = CommunicationType_Search; data[2] = ((char *)&dataLength)[0]; data[3] = ((char *)&dataLength)[1]; data[4] = ((char *)&port)[0]; data[5] = ((char *)&port)[1]; for (int i = 0; i < ipLength; i++) { data[6 + i] = pIP[i]; } m_pSocketUDP->SendData(data, length); }
void WriteLittleEndian(T v) { v = ToLittleEndian(v); Write(&v,sizeof(v)); }
T ReadLittleEndian() { T v; Read(&v,sizeof(v)); return ToLittleEndian(v); }
void Connection::CommunicationInterpretation(const char *pData) { //CLog("type %d", pData[1]); switch (pData[1]) { case CommunicationType_Search: { int dataLength = pData[2] + pData[3] * 0x0100; int ipLength = dataLength - 2; unsigned short port = pData[4] + pData[5] * 0x0100; char ip[ipLength]; for (int i = 0; i < ipLength; i++) { ip[i] = pData[6 + i]; } bool isMyIp = (0 == strcmp(CSocket::GetIP(), (const char *)&ip)); bool isMyPort = m_port == port; if (!isMyIp || !isMyPort) { SearchResponse(ip, port); } } break; case CommunicationType_SearchResponse: { RemoveRetryConnection(CommunicationType_Search); int dataLength = pData[2] + pData[3] * 0x0100; if (1 == dataLength) { // とりあえず無視。 } else { m_clientNo = pData[4] + pData[5] * 0x0100; m_serverPort = pData[6] + pData[7] * 0x0100; int ipLength = dataLength - 4; m_pServerIP = new char[ipLength]; for (int i = 0; i < ipLength; i++) { m_pServerIP[i] = pData[8 + i]; } const char *pSelfIP = CSocket::GetIP(); char *pIP = new char[strlen(pSelfIP)]; memcpy(pIP, pSelfIP, strlen(pSelfIP)); m_pClients[SERVER_NO] = new ConnectionClient(m_pServerIP, m_serverPort); m_pClients[m_clientNo] = new ConnectionClient(pIP, m_port); m_pDelegate->DidDetectServer(); } } break; case CommunicationType_Entry: { int dataLength = pData[2] + pData[3] * 0x0100; int clientNo = pData[4] + pData[5] * 0x0100; if (m_clientNo != clientNo) { bool isInvalidClientNo = (0 > clientNo || MAX_MULTI_PLAYER < clientNo || (IsServer() && 0 == m_pClients[clientNo]) || IsClient() && 0 != m_pClients[clientNo]); if (!isInvalidClientNo) { int floatSize = (dataLength - 2) / 2; CPoint point = CPoint(BytesToFloat(&pData[6]), BytesToFloat(&pData[6 + floatSize])); ToLittleEndian((char *)&point.x, floatSize); ToLittleEndian((char *)&point.y, floatSize); if (IsClient()) { m_pClients[clientNo] = new ConnectionClient(); } m_pDelegate->NewPlayerEntry(clientNo, point); } if (IsServer()) { EntryResponse(!isInvalidClientNo, clientNo); } } } break; case CommunicationType_EntryResponse: { m_isReady = true; int dataLength = pData[2] + pData[3] * 0x0100; //int isEntry = pData[4]; int floatSize = pData[5]; if (2 < dataLength) { int temporaryLength = 0; while (dataLength > (temporaryLength + 2)) { int clientNo = pData[6 + temporaryLength] + pData[7 + temporaryLength] * 0x0100; if (m_clientNo == clientNo) { continue; } CPoint point; memcpy(&point.x, &pData[8 + temporaryLength], floatSize); memcpy(&point.y, &pData[8 + temporaryLength + floatSize], floatSize); m_pDelegate->NewPlayerEntry(clientNo, point); if (IsClient()) { m_pClients[clientNo] = new ConnectionClient(); } temporaryLength += 2 + (floatSize * 2); } } m_pDelegate->DidStartClient(m_clientNo); } break; case CommunicationType_Move: { int dataLength = pData[2] + pData[3] * 0x0100; int clientNo = pData[4] + pData[5] * 0x0100; if (m_clientNo != clientNo) { bool isInvalidClientNo = (0 > clientNo || MAX_MULTI_PLAYER < clientNo || 0 == m_pClients[clientNo]); if (!isInvalidClientNo) { int floatSize = (dataLength - 2) / 2; CPoint point = CPoint(BytesToFloat(&pData[6]), BytesToFloat(&pData[6 + floatSize])); ToLittleEndian((char *)&point.x, floatSize); ToLittleEndian((char *)&point.y, floatSize); m_pDelegate->UpdatePlayerPosition(clientNo, point); } } } break; case CommunicationType_Exit: { int clientNo = pData[4] + pData[5] * 0x0100; if (m_clientNo != clientNo) { bool isInvalidClientNo = (0 > clientNo || MAX_MULTI_PLAYER < clientNo || 0 == m_pClients[clientNo]); if (!isInvalidClientNo) { m_pDelegate->ExitPlayer(clientNo); delete m_pClients[clientNo]; m_pClients[clientNo] = 0; } } } break; default: break; } }
void Connection::SearchResponse(const char *pIP, unsigned short port) { if (IsUnknown()) { return; } int length = COMMUNICATION_HEADER_LENGTH; if (IsClient()) { length += 1; char data[length]; data[0] = 0x00; data[1] = CommunicationType_SearchResponse; data[2] = 0x01; data[3] = 0x00; data[4] = 0x01; m_pSocketUDP->CreateSender(pIP, port); m_pSocketUDP->SendData(data, length); return; } // クライアント配列に登録してクライアント番号を決めておく unsigned short clientNo = UNKNOWN_CLIENT_NO; for (int i = 0; i < MAX_MULTI_PLAYER; i++) { if (0 == m_pClients[i]) { char *pClientIp = new char[strlen(pIP)]; memcpy(pClientIp, pIP, strlen(pIP)); m_pClients[i] = new ConnectionClient(pClientIp, port); clientNo = i; break; } } const char *pSelfIP = CSocket::GetIP(); unsigned short selfPort = m_port; int clientNoLength = 2; int portLength = 2; int ipLength = (int)(strlen(pSelfIP) + 1); int dataLength = clientNoLength + portLength + ipLength; length += dataLength; ToLittleEndian((char *)&dataLength, sizeof(int)); ToLittleEndian((char *)&clientNo, sizeof(unsigned short)); ToLittleEndian((char *)&selfPort, sizeof(unsigned short)); char data[length]; data[0] = 0x00; data[1] = CommunicationType_SearchResponse; data[2] = ((char *)&dataLength)[0]; data[3] = ((char *)&dataLength)[1]; data[4] = ((char *)&clientNo)[0]; data[5] = ((char *)&clientNo)[1]; data[6] = ((char *)&selfPort)[0]; data[7] = ((char *)&selfPort)[1]; for (int i = 0; i < ipLength; i++) { data[8 + i] = pSelfIP[i]; } m_pSocketUDP->CreateSender(pIP, port); m_pSocketUDP->SendData(data, length); }
void HPRC4LikeCipher::Apply(uint8 *buf, uint32 size) { // remaining bytes from last round, to keep cipher consistent // this will probably invalidate proper memory alignment, though if(_rb) { if(_rb < size) { uint8 r = _rb; _DoRemainingBytes(buf, _rb); buf += r; size -= r; } else { _DoRemainingBytes(buf, (uint8)size); return; } } uint32 isize = size / 4; size -= (isize * 4); // remaining bytes uint32 *sbox = &_sbox[0]; uint32 x = _x, y = _y; // process as much as possible as uint32 blocks // optimization: it seems that having x, y, t as uint32 and using & 0xFF everytime // is more efficient then using uint8 and the fact that 0xFF overflows to 0x00 if(isize) { uint32 *ibuf = (uint32*)buf; uint32 t; do { ++x; x &= 0xFF; y += sbox[x]; y &= 0xFF; iswap(sbox[x], sbox[y]); t = sbox[x] + sbox[y]; t &= 0xFF; #if IS_LITTLE_ENDIAN *ibuf++ ^= sbox[t]; #else uint32 m = sbox[t]; ToLittleEndian(m); *ibuf++ ^= m; #endif // leave lowest 8 bits intact (which are used for permutation), and mix the upper 24 bytes sbox[t] = (sbox[t] & 0xFF) | (0xFFFFFF00 & (sbox[t] ^ sbox[y] ^ sbox[x])); } while(--isize); buf = (uint8*)ibuf; } _x = (uint8)x; _y = (uint8)y; // are there remaining bytes at the end of the buffer? if(size) { // we have to start a new round ++_x; _y += (uint8)sbox[_x]; iswap(sbox[_x], sbox[_y]); _rb = sizeof(uint32); // after _DoRemainingBytes(), it will hold the amount of bytes to do in the next round _DoRemainingBytes(buf,(uint8)size); } }