00001 #include <cstdio>
00002 #include <sys/socket.h>
00003 #include <sys/types.h>
00004 #include <netinet/in.h>
00005 #include <arpa/inet.h>
00006 #include <errno.h>
00007 #include <netdb.h>
00008 #include <string.h>
00009 #include "net/client.h"
00010 #include "engine/mutex.h"
00011 #include "tools/log.h"
00012
00013 Mutex getaddrinfo_mutex;
00014
00015 Client::Client(bool _reconnect)
00016 {
00017 client_host = "";
00018 client_port = -1;
00019 connecting = false;
00020 connected = false;
00021 reconnect = _reconnect;
00022 }
00023
00024 Client::~Client()
00025 {
00026 if(IsConnected())
00027 log(LogInfo, "Disconnecting from %s", GetAddress().c_str());
00028 }
00029
00030 void Client::Connect(std::string _host, int _port)
00031 {
00032 if(IsConnected())
00033 return;
00034
00035 info_mutex.Lock();
00036 connecting = true;
00037 client_host = _host;
00038 client_port = _port;
00039 info_mutex.Unlock();
00040
00041 Lock();
00042
00043 log(LogInfo, "Connecting to %s:%i", _host.c_str(), _port);
00044
00045 if((fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00046 log(LogPanic, "Could not create socket : %s", strerror(errno));
00047
00048 struct addrinfo hints;
00049 struct addrinfo *addr;
00050 memset(&hints, 0, sizeof(struct addrinfo));
00051 hints.ai_socktype = SOCK_STREAM;
00052 hints.ai_family = AF_INET;
00053
00054 int ret;
00055 std::string port_str = int2str(_port);
00056 getaddrinfo_mutex.Lock();
00057 if((ret = getaddrinfo(_host.c_str(), port_str.c_str(), &hints, &addr)) != 0)
00058 {
00059 log(LogError, "getaddrinfo failed: %s", strerror(ret));
00060 getaddrinfo_mutex.Unlock();
00061 Unlock();
00062 return;
00063 }
00064 getaddrinfo_mutex.Unlock();
00065
00066 if(connect(fd, (struct sockaddr*)addr->ai_addr, sizeof(struct sockaddr_in)) != 0)
00067 {
00068 log(LogError, "Could not connect to %s:%i : %s", _host.c_str(), _port, strerror(errno));
00069 Disconnect();
00070 Unlock();
00071 }
00072 else
00073 {
00074 Unlock();
00075 info_mutex.Lock();
00076 connected = true;
00077 info_mutex.Unlock();
00078 }
00079 info_mutex.Lock();
00080 connecting = false;
00081 info_mutex.Unlock();
00082 return;
00083 }
00084
00085 void Client::Connect()
00086 {
00087 Connect(client_host, client_port);
00088 }
00089
00090 bool Client::IsConnecting()
00091 {
00092 info_mutex.Lock();
00093 bool r = connecting;
00094 info_mutex.Unlock();
00095 return r;
00096 }
00097
00098 bool Client::IsConnected()
00099 {
00100 info_mutex.Lock();
00101 bool r = connected;
00102 info_mutex.Unlock();
00103 return r;
00104 }
00105
00106 const std::string Client::GetAddress()
00107 {
00108 std::string str;
00109 info_mutex.Lock();
00110 str = client_host + std::string(":") + int2str(client_port);
00111 info_mutex.Unlock();
00112 return str;
00113 }
00114
00115 void Client::OnDisconnect()
00116 {
00117 info_mutex.Lock();
00118 connected = false;
00119 info_mutex.Unlock();
00120 }
00121