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 bool ircd_connector::SetHostAddress(char* host, int port)
98 memset((void*)&addr, 0, sizeof(addr));
99 addr.sin_family = AF_INET;
100 inet_aton(host,&addr.sin_addr);
101 addr.sin_port = htons(port);
105 bool ircd_connector::MakeOutboundConnection(char* host, int port)
107 hostent* hoste = gethostbyname(host);
110 WriteOpers("Failed to look up hostname for %s, using as an ip address",host);
111 this->SetHostAddress(host,port);
115 WriteOpers("Found hostname for %s",host);
116 this->SetHostAddress(hoste->h_addr,port);
119 this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
122 if(connect(this->fd, (sockaddr*)&addr,sizeof(addr)))
124 WriteOpers("connect() failed for %s",host);
127 int flags = fcntl(this->fd, F_GETFL, 0);
128 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
131 setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
132 setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
137 WriteOpers("socket() failed!");
144 bool connection::BeginLink(char* targethost, int port, char* password, char* servername)
146 char connect[MAXBUF];
148 ircd_connector connector;
152 if (connector.MakeOutboundConnection(targethost,port))
154 // targethost has been turned into an ip...
155 // we dont want this as the server name.
156 connector.SetServerName(servername);
157 sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
158 connector.SetState(STATE_NOAUTH_OUTBOUND);
159 this->connectors.push_back(connector);
160 return this->SendPacket(connect, servername);
164 WriteOpers("Could not create outbound connection to %s:%d",targethost,port);
170 bool connection::AddIncoming(int fd,char* targethost)
172 char connect[MAXBUF];
174 ircd_connector connector;
176 // targethost has been turned into an ip...
177 // we dont want this as the server name.
178 connector.SetServerName(targethost);
179 connector.SetDescriptor(fd);
180 connector.SetState(STATE_NOAUTH_INBOUND);
181 int flags = fcntl(fd, F_GETFL, 0);
182 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
185 setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf));
186 setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
187 this->connectors.push_back(connector);
191 void connection::TerminateLink(char* targethost)
193 // this locates the targethost in the connection::connectors vector of the class,
194 // and terminates it by sending it an SQUIT token and closing its descriptor.
195 // TerminateLink with a null string causes a terminate of ALL links
199 // Returns a pointer to the connector for 'host'
200 ircd_connector* connection::FindHost(std::string host)
202 for (int i = 0; i < this->connectors.size(); i++)
204 if (this->connectors[i].GetServerName() == host)
206 return &this->connectors[i];
212 std::string ircd_connector::GetServerName()
214 return this->servername;
217 void ircd_connector::SetServerName(std::string serv)
219 this->servername = serv;
223 int ircd_connector::GetDescriptor()
228 int ircd_connector::GetState()
234 void ircd_connector::SetState(int state)
239 void ircd_connector::SetDescriptor(int fd)
244 bool connection::SendPacket(char *message, const char* host)
246 ircd_connector* cn = this->FindHost(host);
250 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str());
252 strncat(message,"\n",MAXBUF);
253 // returns false if the packet could not be sent (e.g. target host down)
254 if (send(cn->GetDescriptor(),message,strlen(message),0)<0)
256 log(DEBUG,"send() failed for Connection::SendPacket(): %s",strerror(errno));
263 // receives a packet from any where there is data waiting, first come, first served
264 // fills the message and host values with the host where the data came from.
266 bool connection::RecvPacket(std::deque<std::string> &messages, char* host)
269 memset(data, 0, 32767);
270 for (int i = 0; i < this->connectors.size(); i++)
272 // returns false if the packet could not be sent (e.g. target host down)
274 if (rcvsize = recv(this->connectors[i].GetDescriptor(),data,32767,0))
278 char* l = strtok(data,"\n");
281 char sanitized[32767];
282 memset(sanitized, 0, 32767);
284 for (int pt = 0; pt < strlen(l); pt++)
288 sanitized[ptt++] = l[pt];
291 sanitized[ptt] = '\0';
292 if (strlen(sanitized))
294 messages.push_back(sanitized);
295 strncpy(host,this->connectors[i].GetServerName().c_str(),160);
296 log(DEBUG,"main: Connection::RecvPacket() got '%s' from %s",sanitized,host);
299 l = strtok(NULL,"\n");
305 // nothing new yet -- message and host will be undefined
309 long connection::GenKey()
312 return (random()*time(NULL));