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