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)
00052 {
00053 this->fd = newfd;
00054 this->state = I_CONNECTED;
00055 }
00056
00057 InspSocket::InspSocket(std::string host, int port, bool listening, unsigned long maxtime)
00058 {
00059 if (listening) {
00060 if ((this->fd = OpenTCPSocket()) == ERROR)
00061 {
00062 this->fd = -1;
00063 this->state = I_ERROR;
00064 this->OnError(I_ERR_SOCKET);
00065 log(DEBUG,"OpenTCPSocket() error");
00066 return;
00067 }
00068 else
00069 {
00070 if (BindSocket(this->fd,this->client,this->server,port,(char*)host.c_str()) == ERROR)
00071 {
00072 this->Close();
00073 this->fd = -1;
00074 this->state = I_ERROR;
00075 this->OnError(I_ERR_BIND);
00076 log(DEBUG,"BindSocket() error %s",strerror(errno));
00077 return;
00078 }
00079 else
00080 {
00081 this->state = I_LISTENING;
00082 log(DEBUG,"New socket now in I_LISTENING state");
00083 return;
00084 }
00085 }
00086 } else {
00087 char* ip;
00088 this->host = host;
00089 hostent* hoste = gethostbyname(host.c_str());
00090 if (!hoste) {
00091 ip = (char*)host.c_str();
00092 } else {
00093 struct in_addr* ia = (in_addr*)hoste->h_addr;
00094 ip = inet_ntoa(*ia);
00095 }
00096
00097 timeout_end = time(NULL)+maxtime;
00098 timeout = false;
00099 if ((this->fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
00100 {
00101 this->state = I_ERROR;
00102 this->OnError(I_ERR_SOCKET);
00103 return;
00104 }
00105 this->port = port;
00106 inet_aton(ip,&addy);
00107 addr.sin_family = AF_INET;
00108 addr.sin_addr = addy;
00109 addr.sin_port = htons(this->port);
00110
00111 int flags;
00112 flags = fcntl(this->fd, F_GETFL, 0);
00113 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
00114
00115 if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)) == -1)
00116 {
00117 if (errno != EINPROGRESS)
00118 {
00119 this->Close();
00120 this->OnError(I_ERR_CONNECT);
00121 this->state = I_ERROR;
00122 return;
00123 }
00124 }
00125 this->state = I_CONNECTING;
00126 return;
00127 }
00128 }
00129
00130 void InspSocket::Close()
00131 {
00132 if (this->fd != -1)
00133 {
00134 this->OnClose();
00135 shutdown(this->fd,2);
00136 close(this->fd);
00137 this->fd = -1;
00138 }
00139 }
00140
00141 char* InspSocket::Read()
00142 {
00143 int n = recv(this->fd,this->ibuf,sizeof(this->ibuf),0);
00144 if (n > 0)
00145 {
00146 ibuf[n] = 0;
00147 return ibuf;
00148 }
00149 else
00150 {
00151 log(DEBUG,"EOF or error on socket");
00152 return NULL;
00153 }
00154 }
00155
00156
00157
00158
00159
00160 int InspSocket::Write(std::string data)
00161 {
00162 char* d = (char*)data.c_str();
00163 unsigned int written = 0;
00164 int n = 0;
00165 int s = data.length();
00166 while ((written < data.length()) && (n >= 0))
00167 {
00168 n = send(this->fd,d,s,0);
00169 if (n > 0)
00170 {
00171
00172
00173
00174
00175 written += n;
00176 s -= n;
00177 d += n;
00178 }
00179 }
00180 return written;
00181 }
00182
00183 bool InspSocket::Poll()
00184 {
00185 if ((time(NULL) > timeout_end) && (this->state == I_CONNECTING))
00186 {
00187
00188
00189
00190
00191 this->OnTimeout();
00192 this->OnError(I_ERR_TIMEOUT);
00193 timeout = true;
00194 this->state = I_ERROR;
00195 return false;
00196 }
00197 polls.fd = this->fd;
00198 state == I_CONNECTING ? polls.events = POLLOUT : polls.events = POLLIN;
00199 int ret = poll(&polls,1,1);
00200
00201 if (ret > 0)
00202 {
00203 int incoming = -1;
00204
00205 switch (this->state)
00206 {
00207 case I_CONNECTING:
00208 this->SetState(I_CONNECTED);
00209 return this->OnConnected();
00210 break;
00211 case I_LISTENING:
00212 length = sizeof (client);
00213 incoming = accept (this->fd, (sockaddr*)&client,&length);
00214 this->OnIncomingConnection(incoming,inet_ntoa(client.sin_addr));
00215 return true;
00216 break;
00217 case I_CONNECTED:
00218 return this->OnDataReady();
00219 break;
00220 default:
00221 break;
00222 }
00223 }
00224 return true;
00225 }
00226
00227 void InspSocket::SetState(InspSocketState s)
00228 {
00229 log(DEBUG,"Socket state change");
00230 this->state = s;
00231 }
00232
00233 InspSocketState InspSocket::GetState()
00234 {
00235 return this->state;
00236 }
00237
00238 bool InspSocket::OnConnected() { return true; }
00239 void InspSocket::OnError(InspSocketError e) { return; }
00240 int InspSocket::OnDisconnect() { return 0; }
00241 int InspSocket::OnIncomingConnection(int newfd, char* ip) { return 0; }
00242 bool InspSocket::OnDataReady() { return true; }
00243 void InspSocket::OnTimeout() { return; }
00244 void InspSocket::OnClose() { return; }
00245
00246 InspSocket::~InspSocket()
00247 {
00248 this->Close();
00249 }
00250
00251
00252
00253
00254