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