1 #include <connection.h>
6 #include <sys/utsname.h>
15 extern std::vector<Module*> modules;
16 extern std::vector<ircd_module*> factory;
31 connection::connection()
38 bool connection::CreateListener(char* host, int p)
40 sockaddr_in host_address;
44 struct linger linger = { 0 };
46 fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
52 memset((void*)&host_address, 0, sizeof(host_address));
54 host_address.sin_family = AF_INET;
58 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
62 inet_aton(host,&addy);
63 host_address.sin_addr = addy;
66 host_address.sin_port = htons(p);
68 if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
73 // make the socket non-blocking
74 flags = fcntl(fd, F_GETFL, 0);
75 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
79 setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
82 setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger));
84 // attempt to increase socket sendq and recvq as high as its possible
85 // to get them on linux.
88 setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
89 setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
96 char* ircd_connector::GetServerIP()
101 int ircd_connector::GetServerPort()
106 bool ircd_connector::SetHostAndPort(char* host, int port)
108 strncpy(this->host,host,160);
113 bool ircd_connector::SetHostAddress(char* host, int port)
115 strncpy(this->host,host,160);
117 memset((void*)&addr, 0, sizeof(addr));
118 addr.sin_family = AF_INET;
119 inet_aton(host,&addr.sin_addr);
120 addr.sin_port = htons(port);
124 bool ircd_connector::MakeOutboundConnection(char* host, int port)
126 hostent* hoste = gethostbyname(host);
129 WriteOpers("Failed to look up hostname for %s, using as an ip address",host);
130 this->SetHostAddress(host,port);
131 SetHostAndPort(host,port);
135 WriteOpers("Found hostname for %s",host);
136 this->SetHostAddress(hoste->h_addr,port);
137 SetHostAndPort(hoste->h_addr,port);
140 this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
143 if(connect(this->fd, (sockaddr*)&addr,sizeof(addr)))
145 WriteOpers("connect() failed for %s",host);
148 int flags = fcntl(this->fd, F_GETFL, 0);
149 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
152 setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
153 setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
158 WriteOpers("socket() failed!");
165 bool connection::BeginLink(char* targethost, int port, char* password, char* servername)
167 char connect[MAXBUF];
169 ircd_connector connector;
173 if (connector.MakeOutboundConnection(targethost,port))
175 // targethost has been turned into an ip...
176 // we dont want this as the server name.
177 connector.SetServerName(servername);
178 sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
179 connector.SetState(STATE_NOAUTH_OUTBOUND);
180 this->connectors.push_back(connector);
181 return this->SendPacket(connect, servername);
185 WriteOpers("Could not create outbound connection to %s:%d",targethost,port);
191 bool connection::MeshCookie(char* targethost, int port, long cookie, char* servername)
193 char connect[MAXBUF];
195 ircd_connector connector;
197 WriteOpers("Establishing meshed link to %s:%d",servername,port);
201 if (connector.MakeOutboundConnection(targethost,port))
203 // targethost has been turned into an ip...
204 // we dont want this as the server name.
205 connector.SetServerName(servername);
206 sprintf(connect,"- %d %s :%s",cookie,getservername().c_str(),getserverdesc().c_str());
207 connector.SetState(STATE_NOAUTH_OUTBOUND);
208 this->connectors.push_back(connector);
209 return this->SendPacket(connect, servername);
213 WriteOpers("Could not create outbound connection to %s:%d",targethost,port);
219 bool connection::AddIncoming(int fd,char* targethost, int sourceport)
221 char connect[MAXBUF];
223 ircd_connector connector;
225 // targethost has been turned into an ip...
226 // we dont want this as the server name.
227 connector.SetHostAndPort(targethost, sourceport);
228 connector.SetServerName(targethost);
229 connector.SetDescriptor(fd);
230 connector.SetState(STATE_NOAUTH_INBOUND);
231 int flags = fcntl(fd, F_GETFL, 0);
232 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
235 setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
236 setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
237 log(DEBUG,"connection::AddIncoming() Added connection: %s:%d",host,sourceport);
238 this->connectors.push_back(connector);
242 void connection::TerminateLink(char* targethost)
244 // this locates the targethost in the connection::connectors vector of the class,
245 // and terminates it by sending it an SQUIT token and closing its descriptor.
246 // TerminateLink with a null string causes a terminate of ALL links
250 // Returns a pointer to the connector for 'host'
251 ircd_connector* connection::FindHost(std::string host)
253 for (int i = 0; i < this->connectors.size(); i++)
255 if (this->connectors[i].GetServerName() == host)
257 return &this->connectors[i];
263 std::string ircd_connector::GetServerName()
265 return this->servername;
268 void ircd_connector::SetServerName(std::string serv)
270 this->servername = serv;
274 int ircd_connector::GetDescriptor()
279 int ircd_connector::GetState()
285 void ircd_connector::SetState(int state)
290 void ircd_connector::SetDescriptor(int fd)
295 bool connection::SendPacket(char *message, const char* host)
297 ircd_connector* cn = this->FindHost(host);
301 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str());
303 strncat(message,"\n",MAXBUF);
304 // returns false if the packet could not be sent (e.g. target host down)
305 if (send(cn->GetDescriptor(),message,strlen(message),0)<0)
307 log(DEBUG,"send() failed for Connection::SendPacket(): %s",strerror(errno));
314 // receives a packet from any where there is data waiting, first come, first served
315 // fills the message and host values with the host where the data came from.
317 bool connection::RecvPacket(std::deque<std::string> &messages, char* host)
320 memset(data, 0, 32767);
321 for (int i = 0; i < this->connectors.size(); i++)
323 // returns false if the packet could not be sent (e.g. target host down)
325 if (rcvsize = recv(this->connectors[i].GetDescriptor(),data,32767,0))
329 char* l = strtok(data,"\n");
332 char sanitized[32767];
333 memset(sanitized, 0, 32767);
335 for (int pt = 0; pt < strlen(l); pt++)
339 sanitized[ptt++] = l[pt];
342 sanitized[ptt] = '\0';
343 if (strlen(sanitized))
345 messages.push_back(sanitized);
346 strncpy(host,this->connectors[i].GetServerName().c_str(),160);
347 log(DEBUG,"main: Connection::RecvPacket() got '%s' from %s",sanitized,host);
350 l = strtok(NULL,"\n");
356 // nothing new yet -- message and host will be undefined
360 long connection::GenKey()
363 return (random()*time(NULL));