00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 using namespace std;
00018
00019 #include "inspircd_config.h"
00020 #include <sys/time.h>
00021 #include <sys/resource.h>
00022 #include <sys/types.h>
00023 #include <sys/socket.h>
00024 #include <netinet/in.h>
00025 #include <string>
00026 #include <unistd.h>
00027 #include <fcntl.h>
00028 #include <poll.h>
00029 #include <sstream>
00030 #include <iostream>
00031 #include <fstream>
00032 #include "socket.h"
00033 #include "inspircd.h"
00034 #include "inspircd_io.h"
00035 #include "inspircd_util.h"
00036 #include "inspstring.h"
00037 #include "helperfuncs.h"
00038
00039 extern FILE *log_file;
00040 extern int boundPortCount;
00041 extern int openSockfd[MAXSOCKS];
00042 extern time_t TIME;
00043 extern bool unlimitcore;
00044 extern int MaxConn;
00045
00046 InspSocket::InspSocket()
00047 {
00048 this->state = I_DISCONNECTED;
00049 }
00050
00051 InspSocket::InspSocket(int newfd, char* ip)
00052 {
00053 this->fd = newfd;
00054 this->state = I_CONNECTED;
00055 this->IP = ip;
00056 }
00057
00058 InspSocket::InspSocket(std::string host, int port, bool listening, unsigned long maxtime)
00059 {
00060 if (listening) {
00061 if ((this->fd = OpenTCPSocket()) == ERROR)
00062 {
00063 this->fd = -1;
00064 this->state = I_ERROR;
00065 this->OnError(I_ERR_SOCKET);
00066 log(DEBUG,"OpenTCPSocket() error");
00067 return;
00068 }
00069 else
00070 {
00071 if (BindSocket(this->fd,this->client,this->server,port,(char*)host.c_str()) == ERROR)
00072 {
00073 this->Close();
00074 this->fd = -1;
00075 this->state = I_ERROR;
00076 this->OnError(I_ERR_BIND);
00077 log(DEBUG,"BindSocket() error %s",strerror(errno));
00078 return;
00079 }
00080 else
00081 {
00082 this->state = I_LISTENING;
00083 log(DEBUG,"New socket now in I_LISTENING state");
00084 return;
00085 }
00086 }
00087 } else {
00088 char* ip;
00089 this->host = host;
00090 hostent* hoste = gethostbyname(host.c_str());
00091 if (!hoste) {
00092 ip = (char*)host.c_str();
00093 } else {
00094 struct in_addr* ia = (in_addr*)hoste->h_addr;
00095 ip = inet_ntoa(*ia);
00096 }
00097
00098 this->IP = ip;
00099
00100 timeout_end = time(NULL)+maxtime;
00101 timeout = false;
00102 if ((this->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00103 {
00104 this->state = I_ERROR;
00105 this->OnError(I_ERR_SOCKET);
00106 return;
00107 }
00108 this->port = port;
00109 inet_aton(ip,&addy);
00110 addr.sin_family = AF_INET;
00111 addr.sin_addr = addy;
00112 addr.sin_port = htons(this->port);
00113
00114 int flags;
00115 flags = fcntl(this->fd, F_GETFL, 0);
00116 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
00117
00118 if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)) == -1)
00119 {
00120 if (errno != EINPROGRESS)
00121 {
00122 this->Close();
00123 this->OnError(I_ERR_CONNECT);
00124 this->state = I_ERROR;
00125 return;
00126 }
00127 }
00128 this->state = I_CONNECTING;
00129 return;
00130 }
00131 }
00132
00133 void InspSocket::Close()
00134 {
00135 if (this->fd != -1)
00136 {
00137 this->OnClose();
00138 shutdown(this->fd,2);
00139 close(this->fd);
00140 this->fd = -1;
00141 }
00142 }
00143
00144 std::string InspSocket::GetIP()
00145 {
00146 return this->IP;
00147 }
00148
00149 char* InspSocket::Read()
00150 {
00151 int n = recv(this->fd,this->ibuf,sizeof(this->ibuf),0);
00152 if (n > 0)
00153 {
00154 ibuf[n] = 0;
00155 return ibuf;
00156 }
00157 else
00158 {
00159 log(DEBUG,"EOF or error on socket");
00160 return NULL;
00161 }
00162 }
00163
00164
00165
00166
00167
00168 int InspSocket::Write(std::string data)
00169 {
00170 char* d = (char*)data.c_str();
00171 unsigned int written = 0;
00172 int n = 0;
00173 int s = data.length();
00174 while ((written < data.length()) && (n >= 0))
00175 {
00176 n = send(this->fd,d,s,0);
00177 if (n > 0)
00178 {
00179
00180
00181
00182
00183 written += n;
00184 s -= n;
00185 d += n;
00186 }
00187 }
00188 return written;
00189 }
00190
00191 bool InspSocket::Poll()
00192 {
00193 if ((time(NULL) > timeout_end) && (this->state == I_CONNECTING))
00194 {
00195
00196
00197
00198
00199 this->OnTimeout();
00200 this->OnError(I_ERR_TIMEOUT);
00201 timeout = true;
00202 this->state = I_ERROR;
00203 return false;
00204 }
00205 polls.fd = this->fd;
00206 state == I_CONNECTING ? polls.events = POLLOUT : polls.events = POLLIN;
00207 int ret = poll(&polls,1,1);
00208
00209 if (ret > 0)
00210 {
00211 int incoming = -1;
00212
00213 switch (this->state)
00214 {
00215 case I_CONNECTING:
00216 this->SetState(I_CONNECTED);
00217 return this->OnConnected();
00218 break;
00219 case I_LISTENING:
00220 length = sizeof (client);
00221 incoming = accept (this->fd, (sockaddr*)&client,&length);
00222 this->OnIncomingConnection(incoming,inet_ntoa(client.sin_addr));
00223 return true;
00224 break;
00225 case I_CONNECTED:
00226 return this->OnDataReady();
00227 break;
00228 default:
00229 break;
00230 }
00231 }
00232 return true;
00233 }
00234
00235 void InspSocket::SetState(InspSocketState s)
00236 {
00237 log(DEBUG,"Socket state change");
00238 this->state = s;
00239 }
00240
00241 InspSocketState InspSocket::GetState()
00242 {
00243 return this->state;
00244 }
00245
00246 bool InspSocket::OnConnected() { return true; }
00247 void InspSocket::OnError(InspSocketError e) { return; }
00248 int InspSocket::OnDisconnect() { return 0; }
00249 int InspSocket::OnIncomingConnection(int newfd, char* ip) { return 0; }
00250 bool InspSocket::OnDataReady() { return true; }
00251 void InspSocket::OnTimeout() { return; }
00252 void InspSocket::OnClose() { return; }
00253
00254 InspSocket::~InspSocket()
00255 {
00256 this->Close();
00257 }
00258
00259
00260
00261
00262