]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/connection.cpp
fixes to server name updating during incoming link
[user/henk/code/inspircd.git] / src / connection.cpp
1 #include <connection.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <sys/errno.h>
5 #include <sys/ioctl.h>
6 #include <sys/utsname.h>
7 #include <vector>
8 #include <string>
9 #include "inspircd.h"
10 #include "modules.h"
11
12 using namespace std;
13
14 extern std::vector<Module*> modules;
15 extern std::vector<ircd_module*> factory;
16
17 extern int MODCOUNT;
18
19
20 packet::packet()
21 {
22         srand(time(NULL));
23         id = random();
24 }
25
26 packet::~packet()
27 {
28 }
29
30 connection::connection()
31 {
32         key = GenKey();
33         fd = 0;
34 }
35
36
37 bool connection::CreateListener(char* host, int p)
38 {
39         sockaddr_in host_address;
40         int flags;
41         in_addr addy;
42         int on = 0;
43         struct linger linger = { 0 };
44         
45         fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
46         if (fd <= 0)
47         {
48                 return false;
49         }
50
51         memset((void*)&host_address, 0, sizeof(host_address));
52
53         host_address.sin_family = AF_INET;
54
55         if (!strcmp(host,""))
56         {
57                 host_address.sin_addr.s_addr = htonl(INADDR_ANY);
58         }
59         else
60         {
61                 inet_aton(host,&addy);
62                 host_address.sin_addr = addy;
63         }
64
65         host_address.sin_port = htons(p);
66
67         if (bind(fd,(sockaddr*)&host_address,sizeof(host_address))<0)
68         {
69                 return false;
70         }
71
72         // make the socket non-blocking
73         flags = fcntl(fd, F_GETFL, 0);
74         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
75
76         this->port = p;
77
78         setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on));
79         linger.l_onoff = 1;
80         linger.l_linger = 0;
81         setsockopt(fd,SOL_SOCKET,SO_LINGER,(const char*)&linger,sizeof(linger));
82         
83         // attempt to increase socket sendq and recvq as high as its possible
84         // to get them on linux.
85         int sendbuf = 32768;
86         int recvbuf = 32768;
87         setsockopt(fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 
88         setsockopt(fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
89         
90         listen(this->fd,5);
91
92         return true;
93 }
94
95 bool ircd_connector::SetHostAddress(char* host, int port)
96 {
97         memset((void*)&addr, 0, sizeof(addr));
98         addr.sin_family = AF_INET;
99         inet_aton(host,&addr.sin_addr);
100         addr.sin_port = htons(port);
101         return true;
102 }
103
104 bool ircd_connector::MakeOutboundConnection(char* host, int port)
105 {
106         hostent* hoste = gethostbyname(host);
107         if (!hoste)
108         {
109                 WriteOpers("Failed to look up hostname for %s, using as an ip address",host);
110                 this->SetHostAddress(host,port);
111         }
112         else
113         {
114                 WriteOpers("Found hostname for %s",host);
115                 this->SetHostAddress(hoste->h_addr,port);
116         }
117
118         this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
119         if (this->fd >= 0)
120         {
121                 if(connect(this->fd, (sockaddr*)&addr,sizeof(addr)))
122                 {
123                         WriteOpers("connect() failed for %s",host);
124                         return false;
125                 }
126                 int flags = fcntl(this->fd, F_GETFL, 0);
127                 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
128                 int sendbuf = 32768;
129                 int recvbuf = 32768;
130                 setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 
131                 setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
132                 return true;
133         }
134         else
135         {
136                 WriteOpers("socket() failed!");
137         }
138
139         return false;
140 }
141
142
143 bool connection::BeginLink(char* targethost, int port, char* password, char* servername)
144 {
145         char connect[MAXBUF];
146         
147         ircd_connector connector;
148         
149         if (this->fd)
150         {
151                 if (connector.MakeOutboundConnection(targethost,port))
152                 {
153                         // targethost has been turned into an ip...
154                         // we dont want this as the server name.
155                         connector.SetServerName(servername);
156                         sprintf(connect,"S %s %s :%s",getservername().c_str(),password,getserverdesc().c_str());
157                         connector.SetState(STATE_NOAUTH_OUTBOUND);
158                         this->connectors.push_back(connector);
159                         return this->SendPacket(connect, servername);
160                 }
161                 else
162                 {
163                         WriteOpers("Could not create outbound connection to %s:%d",targethost,port);
164                 }
165         }
166         return false;
167 }
168
169 bool connection::AddIncoming(int fd,char* targethost)
170 {
171         char connect[MAXBUF];
172         
173         ircd_connector connector;
174         
175         // targethost has been turned into an ip...
176         // we dont want this as the server name.
177         connector.SetServerName(targethost);
178         connector.SetDescriptor(fd);
179         connector.SetState(STATE_NOAUTH_INBOUND);
180         this->connectors.push_back(connector);
181         return true;
182 }
183
184 void connection::TerminateLink(char* targethost)
185 {
186         // this locates the targethost in the connection::connectors vector of the class,
187         // and terminates it by sending it an SQUIT token and closing its descriptor.
188         // TerminateLink with a null string causes a terminate of ALL links
189 }
190
191
192 // Returns a pointer to the connector for 'host'
193 ircd_connector* connection::FindHost(std::string host)
194 {
195         for (int i = 0; i < this->connectors.size(); i++)
196         {
197                 if (this->connectors[i].GetServerName() == host)
198                 {
199                         return &this->connectors[i];
200                 }
201         }
202         return NULL;
203 }
204
205 std::string ircd_connector::GetServerName()
206 {
207         return this->servername;
208 }
209
210 void ircd_connector::SetServerName(std::string serv)
211 {
212         this->servername = serv;
213 }
214
215
216 int ircd_connector::GetDescriptor()
217 {
218         return this->fd;
219 }
220
221 int ircd_connector::GetState()
222 {
223         return this->state;
224 }
225
226
227 void ircd_connector::SetState(int state)
228 {
229         this->state = state;
230 }
231
232 void ircd_connector::SetDescriptor(int fd)
233 {
234         this->fd = fd;
235 }
236
237 bool connection::SendPacket(char *message, char* host)
238 {
239         ircd_connector* cn = this->FindHost(host);
240         
241         if (cn)
242         {
243                 log(DEBUG,"main: Connection::SendPacket() sent '%s' to %s",message,cn->GetServerName().c_str());
244
245                 strncat(message,"\n",MAXBUF);
246                 // returns false if the packet could not be sent (e.g. target host down)
247                 if (send(cn->GetDescriptor(),message,strlen(message),0)<0)
248                 {
249                         log(DEBUG,"send() failed for Connection::SendPacket(): %s",strerror(errno));
250                         return false;
251                 }
252                 return true;
253         }
254 }
255
256 // receives a packet from any where there is data waiting, first come, first served
257 // fills the message and host values with the host where the data came from.
258
259 bool connection::RecvPacket(char *message, char* host)
260 {
261         for (int i = 0; i < this->connectors.size(); i++)
262         {
263                 // returns false if the packet could not be sent (e.g. target host down)
264                 int rcvsize = 0;
265                 if (rcvsize = recv(this->connectors[i].GetDescriptor(),message,MAXBUF,0))
266                 {
267                         if (rcvsize > 0)
268                         {
269                                 // something new on this socket, fill the return values and bail
270                                 strncpy(host,this->connectors[i].GetServerName().c_str(),160);
271                                 message[rcvsize-1] = 0;
272                                 return true;
273                         }
274                 }
275         }
276         // nothing new yet -- message and host will be undefined
277         return false;
278 }
279
280 long connection::GenKey()
281 {
282         srand(time(NULL));
283         return (random()*time(NULL));
284 }
285