Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00014 #ifdef ENABLE_NETWORK
00015
00016 #include "../../stdafx.h"
00017 #include "../../debug.h"
00018
00019 #include "tcp.h"
00020
00021 NetworkTCPSocketHandler::NetworkTCPSocketHandler(SOCKET s) :
00022 NetworkSocketHandler(),
00023 packet_queue(NULL), packet_recv(NULL),
00024 sock(s), writable(false)
00025 {
00026 }
00027
00028 NetworkTCPSocketHandler::~NetworkTCPSocketHandler()
00029 {
00030 this->CloseConnection();
00031
00032 if (this->sock != INVALID_SOCKET) closesocket(this->sock);
00033 this->sock = INVALID_SOCKET;
00034 }
00035
00036 NetworkRecvStatus NetworkTCPSocketHandler::CloseConnection(bool error)
00037 {
00038 this->writable = false;
00039 NetworkSocketHandler::CloseConnection(error);
00040
00041
00042 while (this->packet_queue != NULL) {
00043 Packet *p = this->packet_queue->next;
00044 delete this->packet_queue;
00045 this->packet_queue = p;
00046 }
00047 delete this->packet_recv;
00048 this->packet_recv = NULL;
00049
00050 return NETWORK_RECV_STATUS_OKAY;
00051 }
00052
00059 void NetworkTCPSocketHandler::SendPacket(Packet *packet)
00060 {
00061 Packet *p;
00062 assert(packet != NULL);
00063
00064 packet->PrepareToSend();
00065
00066
00067
00068
00069 packet->buffer = ReallocT(packet->buffer, packet->size);
00070
00071
00072 p = this->packet_queue;
00073 if (p == NULL) {
00074
00075 this->packet_queue = packet;
00076 } else {
00077
00078 while (p->next != NULL) p = p->next;
00079 p->next = packet;
00080 }
00081 }
00082
00093 SendPacketsState NetworkTCPSocketHandler::SendPackets(bool closing_down)
00094 {
00095 ssize_t res;
00096 Packet *p;
00097
00098
00099 if (!this->writable) return SPS_NONE_SENT;
00100 if (!this->IsConnected()) return SPS_CLOSED;
00101
00102 p = this->packet_queue;
00103 while (p != NULL) {
00104 res = send(this->sock, (const char*)p->buffer + p->pos, p->size - p->pos, 0);
00105 if (res == -1) {
00106 int err = GET_LAST_ERROR();
00107 if (err != EWOULDBLOCK) {
00108
00109 if (!closing_down) {
00110 DEBUG(net, 0, "send failed with error %d", err);
00111 this->CloseConnection();
00112 }
00113 return SPS_CLOSED;
00114 }
00115 return SPS_PARTLY_SENT;
00116 }
00117 if (res == 0) {
00118
00119 if (!closing_down) this->CloseConnection();
00120 return SPS_CLOSED;
00121 }
00122
00123 p->pos += res;
00124
00125
00126 if (p->pos == p->size) {
00127
00128 this->packet_queue = p->next;
00129 delete p;
00130 p = this->packet_queue;
00131 } else {
00132 return SPS_PARTLY_SENT;
00133 }
00134 }
00135
00136 return SPS_ALL_SENT;
00137 }
00138
00144 Packet *NetworkTCPSocketHandler::ReceivePacket()
00145 {
00146 ssize_t res;
00147
00148 if (!this->IsConnected()) return NULL;
00149
00150 if (this->packet_recv == NULL) {
00151 this->packet_recv = new Packet(this);
00152 }
00153
00154 Packet *p = this->packet_recv;
00155
00156
00157 if (p->pos < sizeof(PacketSize)) {
00158 while (p->pos < sizeof(PacketSize)) {
00159
00160 res = recv(this->sock, (char*)p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
00161 if (res == -1) {
00162 int err = GET_LAST_ERROR();
00163 if (err != EWOULDBLOCK) {
00164
00165 if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
00166 this->CloseConnection();
00167 return NULL;
00168 }
00169
00170 return NULL;
00171 }
00172 if (res == 0) {
00173
00174 this->CloseConnection();
00175 return NULL;
00176 }
00177 p->pos += res;
00178 }
00179
00180
00181 p->ReadRawPacketSize();
00182
00183 if (p->size > SEND_MTU) {
00184 this->CloseConnection();
00185 return NULL;
00186 }
00187 }
00188
00189
00190 while (p->pos < p->size) {
00191 res = recv(this->sock, (char*)p->buffer + p->pos, p->size - p->pos, 0);
00192 if (res == -1) {
00193 int err = GET_LAST_ERROR();
00194 if (err != EWOULDBLOCK) {
00195
00196 if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
00197 this->CloseConnection();
00198 return NULL;
00199 }
00200
00201 return NULL;
00202 }
00203 if (res == 0) {
00204
00205 this->CloseConnection();
00206 return NULL;
00207 }
00208
00209 p->pos += res;
00210 }
00211
00212
00213 this->packet_recv = NULL;
00214
00215 p->PrepareToRead();
00216 return p;
00217 }
00218
00224 bool NetworkTCPSocketHandler::CanSendReceive()
00225 {
00226 fd_set read_fd, write_fd;
00227 struct timeval tv;
00228
00229 FD_ZERO(&read_fd);
00230 FD_ZERO(&write_fd);
00231
00232 FD_SET(this->sock, &read_fd);
00233 FD_SET(this->sock, &write_fd);
00234
00235 tv.tv_sec = tv.tv_usec = 0;
00236 #if !defined(__MORPHOS__) && !defined(__AMIGA__)
00237 select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
00238 #else
00239 WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
00240 #endif
00241
00242 this->writable = !!FD_ISSET(this->sock, &write_fd);
00243 return FD_ISSET(this->sock, &read_fd) != 0;
00244 }
00245
00246 #endif