tcp.cpp
Go to the documentation of this file.00001
00002
00007 #ifdef ENABLE_NETWORK
00008
00009 #include "../../stdafx.h"
00010 #include "../../debug.h"
00011
00012 #include "packet.h"
00013 #include "tcp.h"
00014
00015 NetworkTCPSocketHandler::NetworkTCPSocketHandler(SOCKET s) :
00016 NetworkSocketHandler(s),
00017 packet_queue(NULL), packet_recv(NULL), writable(false)
00018 {
00019 }
00020
00021 NetworkTCPSocketHandler::~NetworkTCPSocketHandler()
00022 {
00023 this->CloseConnection();
00024
00025 if (this->sock != INVALID_SOCKET) closesocket(this->sock);
00026 this->sock = INVALID_SOCKET;
00027 }
00028
00029 NetworkRecvStatus NetworkTCPSocketHandler::CloseConnection()
00030 {
00031 this->writable = false;
00032 this->has_quit = true;
00033
00034
00035 while (this->packet_queue != NULL) {
00036 Packet *p = this->packet_queue->next;
00037 delete this->packet_queue;
00038 this->packet_queue = p;
00039 }
00040 delete this->packet_recv;
00041 this->packet_recv = NULL;
00042
00043 return NETWORK_RECV_STATUS_OKAY;
00044 }
00045
00052 void NetworkTCPSocketHandler::Send_Packet(Packet *packet)
00053 {
00054 Packet *p;
00055 assert(packet != NULL);
00056
00057 packet->PrepareToSend();
00058
00059
00060 p = this->packet_queue;
00061 if (p == NULL) {
00062
00063 this->packet_queue = packet;
00064 } else {
00065
00066 while (p->next != NULL) p = p->next;
00067 p->next = packet;
00068 }
00069 }
00070
00078 bool NetworkTCPSocketHandler::Send_Packets()
00079 {
00080 ssize_t res;
00081 Packet *p;
00082
00083
00084 if (!this->writable) return false;
00085 if (!this->IsConnected()) return false;
00086
00087 p = this->packet_queue;
00088 while (p != NULL) {
00089 res = send(this->sock, (const char*)p->buffer + p->pos, p->size - p->pos, 0);
00090 if (res == -1) {
00091 int err = GET_LAST_ERROR();
00092 if (err != EWOULDBLOCK) {
00093
00094 DEBUG(net, 0, "send failed with error %d", err);
00095 this->CloseConnection();
00096 return false;
00097 }
00098 return true;
00099 }
00100 if (res == 0) {
00101
00102 this->CloseConnection();
00103 return false;
00104 }
00105
00106 p->pos += res;
00107
00108
00109 if (p->pos == p->size) {
00110
00111 this->packet_queue = p->next;
00112 delete p;
00113 p = this->packet_queue;
00114 } else {
00115 return true;
00116 }
00117 }
00118
00119 return true;
00120 }
00121
00127 Packet *NetworkTCPSocketHandler::Recv_Packet(NetworkRecvStatus *status)
00128 {
00129 ssize_t res;
00130 Packet *p;
00131
00132 *status = NETWORK_RECV_STATUS_OKAY;
00133
00134 if (!this->IsConnected()) return NULL;
00135
00136 if (this->packet_recv == NULL) {
00137 this->packet_recv = new Packet(this);
00138 if (this->packet_recv == NULL) error("Failed to allocate packet");
00139 }
00140
00141 p = this->packet_recv;
00142
00143
00144 if (p->pos < sizeof(PacketSize)) {
00145 while (p->pos < sizeof(PacketSize)) {
00146
00147 res = recv(this->sock, (char*)p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
00148 if (res == -1) {
00149 int err = GET_LAST_ERROR();
00150 if (err != EWOULDBLOCK) {
00151
00152 if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
00153 *status = this->CloseConnection();
00154 return NULL;
00155 }
00156
00157 return NULL;
00158 }
00159 if (res == 0) {
00160
00161 *status = this->CloseConnection();
00162 return NULL;
00163 }
00164 p->pos += res;
00165 }
00166
00167
00168 p->ReadRawPacketSize();
00169
00170 if (p->size > SEND_MTU) {
00171 *status = this->CloseConnection();
00172 return NULL;
00173 }
00174 }
00175
00176
00177 while (p->pos < p->size) {
00178 res = recv(this->sock, (char*)p->buffer + p->pos, p->size - p->pos, 0);
00179 if (res == -1) {
00180 int err = GET_LAST_ERROR();
00181 if (err != EWOULDBLOCK) {
00182
00183 if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
00184 *status = this->CloseConnection();
00185 return NULL;
00186 }
00187
00188 return NULL;
00189 }
00190 if (res == 0) {
00191
00192 *status = this->CloseConnection();
00193 return NULL;
00194 }
00195
00196 p->pos += res;
00197 }
00198
00199
00200 this->packet_recv = NULL;
00201
00202 p->PrepareToRead();
00203 return p;
00204 }
00205
00206 bool NetworkTCPSocketHandler::IsPacketQueueEmpty()
00207 {
00208 return this->packet_queue == NULL;
00209 }
00210
00211 #endif