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