void NetSocket::HandleInput() { // read in data from the socket and compose it into discrete packets that the game can read bool packetReceived = false; u_long packetSize = 0; // read the socket into the receiver buffer which acts as a ring buffer int rc = recv(m_Sock, m_RecvBuf + m_RecvBegin + m_RecvOffset, RECV_BUFFER_SIZE - (m_RecvBegin + m_RecvOffset), 0); if (rc == 0) { return; } if (rc == SOCKET_ERROR) { m_DeleteFlag = 1; return; } // header size = 4 bytes const int hdrSize = sizeof(u_long); // get the end of the new data read in unsigned int newData = m_RecvOffset + rc; int processedData = 0; while (newData > hdrSize) { // we support two types of packets: // Binary packet - size is a positive 4 byte int at the start of data // Text packet - size 0, parser searches for carriage return // convert the first 4 bytes received to host order - this is the size of this packet packetSize = *(reinterpret_cast<u_long*>(m_RecvBuf + m_RecvBegin)); packetSize = ntohl(packetSize); if (m_BinaryProtocol) { // if the data is less than the packet size, then we haven't finished // reading this packet and dont have enough data to get the next packet if (newData < packetSize) { break; } if (packetSize > MAX_PACKET_SIZE) { // buffer overrun HandleException(); return; } // we know the packet size and have the entire thing read in if (newData >= packetSize) { // create the packet from the receiver buffer (m_RecvBegin + hrdSize so we dont read the header *size* into the data) shared_ptr<BinaryPacket> packet(CB_NEW BinaryPacket(&m_RecvBuf[m_RecvBegin + hdrSize], packetSize - hdrSize)); m_InList.push_back(packet); packetReceived = true; processedData += packetSize; newData -= packetSize; // move the receiver head up by the packet size amount m_RecvBegin += packetSize; } } else { // text protocol waits for a carriage return and creates a string // scan the memory we just read for this character char* cr = static_cast<char*>(memchr(&m_RecvBuf[m_RecvBegin], 0x0a, rc)); if (cr) { // if found, change the '\n' in the text packet to a null terminator *(cr + 1) = 0; shared_ptr<TextPacket> packet(CB_NEW TextPacket(&m_RecvBuf[m_RecvBegin])); m_InList.push_back(packet); packetSize = cr - &m_RecvBuf[m_RecvBegin]; packetReceived = true; processedData += packetSize; newData -= packetSize; // move the receiver head up by the packet size amount m_RecvBegin += packetSize; } } } g_pSocketManager->AddToInbound(rc); m_RecvOffset = newData; if (packetReceived) { if (m_RecvOffset == 0) { m_RecvBegin = 0; } else if (m_RecvBegin + m_RecvOffset + MAX_PACKET_SIZE > RECV_BUFFER_SIZE) { // dont want to allow data to overrun the receiver buffer, so copy leftover bits // to the beginning and reset the heads int leftover = m_RecvOffset; memcpy(m_RecvBuf, &m_RecvBuf[m_RecvBegin], m_RecvOffset); m_RecvBegin = 0; } } }
// // NetSocket::VHandleInput - Chapter 19, page 671 // void NetSocket::VHandleInput() { bool bPktRecieved = false; u_long packetSize = 0; int rc = recv(m_sock, m_recvBuf+m_recvBegin+m_recvOfs, RECV_BUFFER_SIZE-(m_recvBegin+m_recvOfs), 0); char metrics[1024]; sprintf_s(metrics, 1024, "Incoming: %6d bytes. Begin %6d Offset %4d\n", rc, m_recvBegin, m_recvOfs); std::stringstream ss; ss << "Network" << metrics; LOG_WRITE(ss.str()); if (rc==0) { return; } if (rc==SOCKET_ERROR) { m_deleteFlag = 1; return; } const int hdrSize = sizeof(u_long); unsigned int newData = m_recvOfs + rc; int processedData = 0; while (newData > hdrSize) { // There are two types of packets at the lowest level of our design: // BinaryPacket - Sends the size as a positive 4 byte integer // TextPacket - Sends 0 for the size, the parser will search for a CR packetSize = *(reinterpret_cast<u_long*>(m_recvBuf+m_recvBegin)); packetSize = ntohl(packetSize); if (m_bBinaryProtocol) { // we don't have enough new data to grab the next packet if (newData < packetSize) break; if (packetSize > MAX_PACKET_SIZE) { // prevent nasty buffer overruns! HandleException(); return; } if (newData >= packetSize) { // we know how big the packet is...and we have the whole thing // //[mrmike] - a little code to aid debugging network packets here! //char test[1024]; //memcpy(test, &m_recvBuf[m_recvBegin+hdrSize], packetSize); //test[packetSize+1]='\r'; //test[packetSize+2]='\n'; //test[packetSize+3]=0; //LOG_WRITE("Network", test); shared_ptr<BinaryPacket> pkt(QSE_NEW BinaryPacket(&m_recvBuf[m_recvBegin+hdrSize], packetSize-hdrSize)); m_InList.push_back(pkt); bPktRecieved = true; processedData += packetSize; newData -= packetSize; m_recvBegin += packetSize; } } else { // the text protocol waits for a carraige return and creates a string char *cr = static_cast<char *>(memchr(&m_recvBuf[m_recvBegin], 0x0a, rc)); if (cr) { *(cr+1) = 0; shared_ptr<TextPacket> pkt(QSE_NEW TextPacket(&m_recvBuf[m_recvBegin])); m_InList.push_back(pkt); packetSize = cr - &m_recvBuf[m_recvBegin]; bPktRecieved = true; processedData += packetSize; newData -= packetSize; m_recvBegin += packetSize; } } } g_pSocketManager->AddToInbound(rc); m_recvOfs = newData; if (bPktRecieved) { if (m_recvOfs == 0) { m_recvBegin = 0; } else if (m_recvBegin + m_recvOfs + MAX_PACKET_SIZE > RECV_BUFFER_SIZE) { // we don't want to overrun the buffer - so we copy the leftover bits // to the beginning of the recieve buffer and start over int leftover = m_recvOfs; memcpy(m_recvBuf, &m_recvBuf[m_recvBegin], m_recvOfs); m_recvBegin = 0; } } }