bool TCPConnection::SendData(bool &sent_something, char* errbuf) { if (errbuf) errbuf[0] = 0; /************ Get first send packet on queue and send it! ************/ uchar* data = 0; int32 size = 0; int status = 0; if (ServerSendQueuePop(&data, &size)) { #ifdef _WINDOWS status = send(connection_socket, (const char *) data, size, 0); #else status = send(connection_socket, data, size, MSG_NOSIGNAL); if(errno==EPIPE) status = SOCKET_ERROR; #endif if (status >= 1) { #if TCPN_LOG_RAW_DATA_OUT >= 1 struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Wrote " << status << " bytes to network. " << inet_ntoa(in) << ":" << GetrPort(); std::cout << std::endl; #if TCPN_LOG_RAW_DATA_OUT == 2 int32 tmp = status; if (tmp > 32) tmp = 32; DumpPacket(data, status); #elif TCPN_LOG_RAW_DATA_OUT >= 3 DumpPacket(data, status); #endif #endif sent_something = true; if (status < (signed)size) { #if TCPN_LOG_RAW_DATA_OUT >= 1 struct in_addr in; in.s_addr = GetrIP(); CoutTimestamp(true); std::cout << ": Pushed " << (size - status) << " bytes back onto the send queue. " << inet_ntoa(in) << ":" << GetrPort(); std::cout << std::endl; #endif // If there's network congestion, the number of bytes sent can be less than // what we tried to give it... Push the extra back on the queue for later ServerSendQueuePushFront(&data[status], size - status); } else if (status > (signed)size) { return false; } // else if (status == size) {} } else { ServerSendQueuePushFront(data, size); } safe_delete_array(data); if (status == SOCKET_ERROR) { #ifdef _WINDOWS if (WSAGetLastError() != WSAEWOULDBLOCK) #else if (errno != EWOULDBLOCK) #endif { if (errbuf) { #ifdef _WINDOWS snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %i", WSAGetLastError()); #else snprintf(errbuf, TCPConnection_ErrorBufferSize, "TCPConnection::SendData(): send(): Errorcode: %s", strerror(errno)); #endif } //if we get an error while disconnecting, just jump to disconnected MState.lock(); if(pState == TCPS_Disconnecting) pState = TCPS_Disconnected; MState.unlock(); return false; } } } return true; }
bool LoginServer::Process() { #ifdef WIN32 SOCKADDR_IN to; #else struct sockaddr_in to; #endif memset((char *) &to, 0, sizeof(to)); to.sin_family = AF_INET; to.sin_port = port; to.sin_addr.s_addr = ip; if (statusupdate_timer->Check()) { this->SendStatus(); } if (staleauth_timer->Check()) { staleauth_timer->Start(); loginserver->CheckStale(); } /************ Get all packets from packet manager out queue and process them ************/ ServerPacket *pack = 0; while(pack = ServerOutQueue.pop()) { switch(pack->opcode) { case 0: break; case ServerOP_KeepAlive: { // ignore this -- froglok23 -- WHY? } break; case ServerOP_LSClientAuth: { this->ProcessServerOP_LSClientAuth(pack); } break; case ServerOP_LSFatalError: { this->ProcessServerOP_LSFatalError(pack); } break; case ServerOP_SystemwideMessage: { this->ProcessServerOP_SystemwideMessage(pack); break; } case ServerOP_UsertoWorldReq: { this->ProcessServerOP_UsertoWorldReq(pack); break; } case 0x0109: case 0x010a: case 0x0106: case 0x0107: { //Yeahlight: These opcodes occasionally appear with a packet size of 18 when a player attempts to enter a zone. Leave these packets unresolved is freezing the client this->ProcessServerOP_Unknown(pack); this->SendPacket(pack); break; } default: { this->ProcessServerOP_Unknown(pack); break; } } safe_delete(pack);//delete pack; //Yeahlight: Zone freeze debug if(ZONE_FREEZE_DEBUG && rand()%ZONE_FREEZE_DEBUG == 1) EQC_FREEZE_DEBUG(__LINE__, __FILE__); } /************ Get first send packet on queue and send it! ************/ SPackSendQueue* p = 0; int status = 0; while(p = ServerSendQueuePop()) { #ifdef WIN32 status = send(send_socket, (const char *) p->buffer, p->size, 0); #else status = send(send_socket, p->buffer, p->size, 0); #endif safe_delete(p);//delete p; if (status == SOCKET_ERROR) { cout << "Loginserver send(): status=" << status << ", Errorcode: " << EQC::Common::GetLastSocketError() << endl; return false; } //Yeahlight: Zone freeze debug if(ZONE_FREEZE_DEBUG && rand()%ZONE_FREEZE_DEBUG == 1) EQC_FREEZE_DEBUG(__LINE__, __FILE__); } /************ Processing finished ************/ if (timeout_timer->Check()) { this->SendKeepAlive(); } return true; }