00001 #include <cstdio>
00002 #include <malloc.h>
00003 #include <alloca.h>
00004 #include <string.h>
00005 #include <sys/socket.h>
00006 #include <sys/types.h>
00007 #include <sys/ioctl.h>
00008 #include <poll.h>
00009 #include <netinet/in.h>
00010 #include <arpa/inet.h>
00011 #include <errno.h>
00012 #include <netdb.h>
00013 #include "engine/mutex.h"
00014 #include "net/packet.h"
00015 #include "net/client_common.h"
00016 #include "tools/log.h"
00017 #include "tools/assert.h"
00018
00019
00020 ClientCommon::ClientCommon(int _fd) : Mutex(RECURSIVE_MUTEX), fd(_fd), buffer(NULL), buffer_len(0), reconnect(false)
00021 {
00022 }
00023
00024 ClientCommon::~ClientCommon()
00025 {
00026 Disconnect();
00027 free(buffer);
00028 }
00029
00030 void ClientCommon::Disconnect()
00031 {
00032 Lock();
00033 if(fd != -1)
00034 {
00035 shutdown(fd, SHUT_RDWR);
00036 close(fd);
00037 }
00038 fd = -1;
00039 free(buffer);
00040 buffer = NULL;
00041 buffer_len = 0;
00042 Unlock();
00043 OnDisconnect();
00044 }
00045
00046 bool ClientCommon::Send(const char* buf, unsigned int len)
00047 {
00048 Lock();
00049 while(true)
00050 {
00051 if(IsConnected())
00052 {
00053 if(write(fd, buf, len) <= 0)
00054 {
00055 log(LogError, "Write to host %s failed : %s", GetAddress().c_str(), strerror(errno));
00056 Disconnect();
00057 continue;
00058 }
00059 else
00060 {
00061 Unlock();
00062 return true;
00063 }
00064 }
00065 if(!reconnect)
00066 {
00067 Unlock();
00068 return false;
00069 }
00070 sleep(1);
00071 Reconnect();
00072 }
00073 Unlock();
00074 return true;
00075 }
00076
00077 bool ClientCommon::Send(Packet* p)
00078 {
00079 Lock();
00080 char* pckt = NULL;
00081 unsigned int len = 0;
00082 p->DumpRaw(pckt, len);
00083 if(len <= 4)
00084 log(LogWarning, "Sending an empty packet to host %s", GetAddress().c_str());
00085 bool success = Send(pckt, len);
00086 free(pckt);
00087 Unlock();
00088 return success;
00089 }
00090
00091 bool ClientCommon::Send(const std::string & str)
00092 {
00093 if(str.size() == 0)
00094 {
00095 log(LogError, "Trying to send an empty string to host %s", GetAddress().c_str());
00096 return false;
00097 }
00098 return Send(str.c_str(), str.size());
00099 }
00100
00101 bool ClientCommon::Receive(unsigned int len)
00102 {
00103 Lock();
00104 buffer = (char*)realloc(buffer, buffer_len + len);
00105 memset(buffer + buffer_len, 0, len);
00106 while(true)
00107 {
00108 if(IsConnected())
00109 {
00110 ssize_t read_len = read(fd, buffer + buffer_len, len);
00111
00112 if( read_len == -1)
00113 {
00114 log(LogError, "Read of len %i from host %s failed : %s", len, GetAddress().c_str(), strerror(errno));
00115 Disconnect();
00116 continue;
00117 }
00118 else
00119 if( read_len == 0)
00120 {
00121 log(LogError, "Read from host %s failed : the host disconnected", GetAddress().c_str());
00122 Disconnect();
00123 continue;
00124 }
00125 buffer_len += read_len;
00126 break;
00127 }
00128 if(!reconnect)
00129 {
00130 Unlock();
00131 return false;
00132 }
00133 sleep(1);
00134 Reconnect();
00135 }
00136 Unlock();
00137 return true;
00138 }
00139
00140 std::string ClientCommon::ReceiveToEOL()
00141 {
00142 Lock();
00143 bool eol_found = false;
00144 unsigned int eol_pos = 0;
00145
00146 while(!eol_found)
00147 {
00148 if(!IsConnected() && !reconnect)
00149 {
00150 Unlock();
00151 return "";
00152 }
00153
00154 for(; eol_pos < buffer_len; eol_pos++)
00155 if(buffer[eol_pos] == '\n')
00156 {
00157 eol_found = true;
00158 break;
00159 }
00160
00161 if(eol_found)
00162 break;
00163
00164 if(!Receive())
00165 return "";
00166 }
00167
00168 std::string str(buffer, eol_pos);
00169
00170 while((buffer[eol_pos] == '\n' || buffer[eol_pos] == '\r') && eol_pos < buffer_len)
00171 eol_pos++;
00172
00173 if(eol_pos == buffer_len)
00174 {
00175 free(buffer);
00176 buffer = NULL;
00177 buffer_len = 0;
00178 }
00179 else
00180 {
00181 char* tmp = (char*)malloc(buffer_len - eol_pos);
00182 memcpy(tmp, buffer + eol_pos, buffer_len - eol_pos);
00183 free(buffer);
00184 buffer = tmp;
00185 buffer_len -= eol_pos;
00186 }
00187
00188 Unlock();
00189 return str;
00190 }
00191
00192 Packet* ClientCommon::ReceivePacket()
00193 {
00194 Lock();
00195
00196 unsigned int packet_size = 0;
00197 while(IsConnected() && (!packet_size || packet_size > buffer_len))
00198 {
00199 if(buffer_len > 4)
00200 packet_size = ntohl(*(unsigned int*)buffer);
00201 if(buffer_len <= 4 || packet_size > buffer_len)
00202 Receive();
00203 }
00204
00205 if(!IsConnected() || !buffer)
00206 {
00207 Unlock();
00208 return NULL;
00209 }
00210
00211 char* tmp = (char*)alloca(packet_size);
00212 memcpy(tmp, buffer, packet_size);
00213
00214 Packet* p = new Packet(tmp);
00215
00216 if(buffer_len == packet_size)
00217 {
00218 free(buffer);
00219 buffer = NULL;
00220 buffer_len = 0;
00221 }
00222 else
00223 {
00224 char* tmp_buf = (char*)malloc(buffer_len - packet_size);
00225 memcpy(tmp_buf, buffer + packet_size, buffer_len - packet_size);
00226 buffer_len -= packet_size;
00227 free(buffer);
00228 buffer = tmp_buf;
00229 }
00230 Unlock();
00231 return p;
00232 }
00233
00234 int ClientCommon::BytesReceived()
00235 {
00236 Lock();
00237 struct pollfd poll_str = { fd, POLLIN, 0};
00238
00239 if(poll(&poll_str, 1, 1) == -1)
00240 {
00241 Disconnect();
00242 Unlock();
00243 return -1;
00244 }
00245
00246 if(poll_str.revents & POLLERR
00247 || poll_str.revents & POLLHUP
00248 || poll_str.revents & POLLRDHUP
00249 || poll_str.revents & POLLNVAL)
00250 {
00251 Disconnect();
00252 Unlock();
00253 return -1;
00254 }
00255
00256 if(!(poll_str.revents & POLLIN))
00257 {
00258 Unlock();
00259 return 0;
00260 }
00261
00262 int received = 0;
00263 if( ioctl( fd, FIONREAD, &received) == -1 )
00264 {
00265 Disconnect();
00266 Unlock();
00267 return -1;
00268 }
00269 Unlock();
00270 return received;
00271 }
00272
00273 const std::string ClientCommon::GetIp()
00274 {
00275 std::string ip;
00276 Lock();
00277 ip = client_host;
00278 Unlock();
00279 return ip;
00280 }
00281
00282 int ClientCommon::GetPort()
00283 {
00284 int port;
00285 Lock();
00286 port = client_port;
00287 Unlock();
00288 return port;
00289 }
00290
00291