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 #include "../../openttd.h"
00012 #include "../../variables.h"
00013
00014 #include "../network_data.h"
00015 #include "packet.h"
00016 #include "tcp.h"
00017
00018 #include "table/strings.h"
00019
00021 void NetworkTCPSocketHandler::Initialize()
00022 {
00023 this->sock = INVALID_SOCKET;
00024
00025 this->index = 0;
00026 this->last_frame = 0;
00027 this->last_frame_server = 0;
00028 this->lag_test = 0;
00029
00030 this->status = STATUS_INACTIVE;
00031 this->has_quit = false;
00032 this->writable = false;
00033
00034 this->packet_queue = NULL;
00035 this->packet_recv = NULL;
00036
00037 this->command_queue = NULL;
00038 }
00039
00040 void NetworkTCPSocketHandler::Destroy()
00041 {
00042 closesocket(this->sock);
00043 this->writable = false;
00044 this->has_quit = true;
00045
00046
00047 while (this->packet_queue != NULL) {
00048 Packet *p = this->packet_queue->next;
00049 delete this->packet_queue;
00050 this->packet_queue = p;
00051 }
00052 delete this->packet_recv;
00053 this->packet_recv = NULL;
00054
00055 while (this->command_queue != NULL) {
00056 CommandPacket *p = this->command_queue->next;
00057 free(this->command_queue);
00058 this->command_queue = p;
00059 }
00060 }
00061
00070 NetworkRecvStatus NetworkTCPSocketHandler::CloseConnection()
00071 {
00072 NetworkCloseClient(this);
00073
00074
00075 if (!_network_server && _networking) {
00076 _switch_mode = SM_MENU;
00077 _networking = false;
00078 _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
00079
00080 return NETWORK_RECV_STATUS_CONN_LOST;
00081 }
00082
00083 return NETWORK_RECV_STATUS_OKAY;
00084 }
00085
00092 void NetworkTCPSocketHandler::Send_Packet(Packet *packet)
00093 {
00094 Packet *p;
00095 assert(packet != NULL);
00096
00097 packet->PrepareToSend();
00098
00099
00100 p = this->packet_queue;
00101 if (p == NULL) {
00102
00103 this->packet_queue = packet;
00104 } else {
00105
00106 while (p->next != NULL) p = p->next;
00107 p->next = packet;
00108 }
00109 }
00110
00118 bool NetworkTCPSocketHandler::Send_Packets()
00119 {
00120 ssize_t res;
00121 Packet *p;
00122
00123
00124 if (!this->writable) return false;
00125 if (!this->IsConnected()) return false;
00126
00127 p = this->packet_queue;
00128 while (p != NULL) {
00129 res = send(this->sock, (const char*)p->buffer + p->pos, p->size - p->pos, 0);
00130 if (res == -1) {
00131 int err = GET_LAST_ERROR();
00132 if (err != EWOULDBLOCK) {
00133
00134 DEBUG(net, 0, "send failed with error %d", err);
00135 this->CloseConnection();
00136 return false;
00137 }
00138 return true;
00139 }
00140 if (res == 0) {
00141
00142 this->CloseConnection();
00143 return false;
00144 }
00145
00146 p->pos += res;
00147
00148
00149 if (p->pos == p->size) {
00150
00151 this->packet_queue = p->next;
00152 delete p;
00153 p = this->packet_queue;
00154 } else {
00155 return true;
00156 }
00157 }
00158
00159 return true;
00160 }
00161
00167 Packet *NetworkTCPSocketHandler::Recv_Packet(NetworkRecvStatus *status)
00168 {
00169 ssize_t res;
00170 Packet *p;
00171
00172 *status = NETWORK_RECV_STATUS_OKAY;
00173
00174 if (!this->IsConnected()) return NULL;
00175
00176 if (this->packet_recv == NULL) {
00177 this->packet_recv = new Packet(this);
00178 if (this->packet_recv == NULL) error("Failed to allocate packet");
00179 }
00180
00181 p = this->packet_recv;
00182
00183
00184 if (p->pos < sizeof(PacketSize)) {
00185 while (p->pos < sizeof(PacketSize)) {
00186
00187 res = recv(this->sock, (char*)p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
00188 if (res == -1) {
00189 int err = GET_LAST_ERROR();
00190 if (err != EWOULDBLOCK) {
00191
00192 if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
00193 *status = this->CloseConnection();
00194 return NULL;
00195 }
00196
00197 return NULL;
00198 }
00199 if (res == 0) {
00200
00201 *status = this->CloseConnection();
00202 return NULL;
00203 }
00204 p->pos += res;
00205 }
00206
00207
00208 p->ReadRawPacketSize();
00209
00210 if (p->size > SEND_MTU) {
00211 *status = this->CloseConnection();
00212 return NULL;
00213 }
00214 }
00215
00216
00217 while (p->pos < p->size) {
00218 res = recv(this->sock, (char*)p->buffer + p->pos, p->size - p->pos, 0);
00219 if (res == -1) {
00220 int err = GET_LAST_ERROR();
00221 if (err != EWOULDBLOCK) {
00222
00223 if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
00224 *status = this->CloseConnection();
00225 return NULL;
00226 }
00227
00228 return NULL;
00229 }
00230 if (res == 0) {
00231
00232 *status = this->CloseConnection();
00233 return NULL;
00234 }
00235
00236 p->pos += res;
00237 }
00238
00239
00240 this->packet_recv = NULL;
00241
00242 p->PrepareToRead();
00243 return p;
00244 }
00245
00246 bool NetworkTCPSocketHandler::IsPacketQueueEmpty()
00247 {
00248 return this->packet_queue == NULL;
00249 }
00250
00251
00252 #endif