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