]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/connection.cpp
*** empty log message ***
[user/henk/code/inspircd.git] / src / connection.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  Inspire is copyright (C) 2002-2004 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 using namespace std;
18
19 #include <connection.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <poll.h>
23 #include <sys/errno.h>
24 #include <sys/ioctl.h>
25 #include <sys/utsname.h>
26 #include <vector>
27 #include <string>
28 #include <deque>
29 #include <sstream>
30 #include "inspircd.h"
31 #include "modules.h"
32 #include "inspstring.h"
33 #include "helperfuncs.h"
34
35
36 extern std::vector<Module*> modules;
37 extern std::vector<ircd_module*> factory;
38
39 extern int MODCOUNT;
40
41 extern time_t TIME;
42
43
44 /**
45  * The InspIRCd mesh network is maintained by a tree of objects which reference *themselves*.
46  * Every local server has an array of 32 *serverrecs, known as me[]. Each of these represents
47  * a local listening port, and is not null if the user has opened a listening port on the server.
48  * It is assumed nobody will ever want to open more than 32 listening server ports at any one
49  * time (i mean come on, why would you want more, the ircd works fine with ONE).
50  * Each me[] entry has multiple classes within it of type ircd_connector. These are stored in a vector
51  * and each represents a server linked via this socket. If the connection was created outbound,
52  * the connection is bound to the default ip address by using me[defaultRoute] (defaultRoute being
53  * a global variable which indicates the default server to make connections on). If the connection
54  * was created inbound, it is attached to the port the connection came in on. There may be as many
55  * ircd_connector objects as needed in each me[] entry. Each ircd_connector implements the specifics
56  * of an ircd connection in the mesh, however each ircd may have multiple ircd_connector connections
57  * to it, to maintain the mesh link.
58  */
59
60 char* xsumtable = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
61
62 // creates a random id for a line for detection of duplicate messages
63 std::string CreateSum()
64 {
65         char sum[9];
66         sum[0] = ':';
67         sum[8] = '\0';
68         for(int q = 1; q < 8; q++)
69                 sum[q] = xsumtable[rand()%52];
70         return sum;
71 }
72
73 connection::connection()
74 {
75         fd = 0;
76 }
77
78
79 char* ircd_connector::GetServerIP()
80 {
81         return this->host;
82 }
83
84 int ircd_connector::GetServerPort()
85 {
86         return this->port;
87 }
88
89 bool ircd_connector::SetHostAndPort(char* newhost, int newport)
90 {
91         strncpy(this->host,newhost,160);
92         this->port = newport;
93         return true;
94 }
95
96 bool ircd_connector::SetHostAddress(char* newhost, int newport)
97 {
98         strncpy(this->host,newhost,160);
99         this->port = newport;
100         memset((void*)&addr, 0, sizeof(addr));
101         addr.sin_family = AF_INET;
102         inet_aton(host,&addr.sin_addr);
103         addr.sin_port = htons(port);
104         return true;
105 }
106
107 void ircd_connector::SetServerPort(int p)
108 {
109         this->port = p;
110 }
111
112 void ircd_connector::AddBuffer(std::string a)
113 {
114         std::string b = "";
115         for (int i = 0; i < a.length(); i++)
116                 if (a[i] != '\r')
117                         b = b + a[i];
118
119         std::stringstream stream(ircdbuffer);
120         stream << b;
121         log(DEBUG,"AddBuffer: %s",b.c_str());
122         ircdbuffer = stream.str();
123 }
124
125 bool ircd_connector::BufferIsComplete()
126 {
127         for (int i = 0; i < ircdbuffer.length(); i++)
128                 if (ircdbuffer[i] == '\n')
129                         return true;
130         return false;
131 }
132
133 void ircd_connector::ClearBuffer()
134 {
135         ircdbuffer = "";
136 }
137
138 std::string ircd_connector::GetBuffer()
139 {
140         // Fix by Brain 28th Apr 2005
141         // seems my stringstream code isnt liked by linux
142         // EVEN THOUGH IT IS CORRECT! Fixed by using a different
143         // (SLOWER) algorithm...
144         char* line = (char*)ircdbuffer.c_str();
145         std::string ret = "";
146         while ((*line != '\n') && (strlen(line)))
147         {
148                 ret = ret + *line;
149                 line++;
150         }
151         if ((*line == '\n') || (*line == '\r'))
152                 line++;
153         ircdbuffer = line;
154         return ret;
155 }
156
157 bool ircd_connector::MakeOutboundConnection(char* newhost, int newport)
158 {
159         log(DEBUG,"MakeOutboundConnection: Original param: %s",newhost);
160         ClearBuffer();
161         hostent* hoste = gethostbyname(newhost);
162         if (!hoste)
163         {
164                 log(DEBUG,"MakeOutboundConnection: gethostbyname was NULL, setting %s",newhost);
165                 this->SetHostAddress(newhost,newport);
166                 SetHostAndPort(newhost,newport);
167         }
168         else
169         {
170                 struct in_addr* ia = (in_addr*)hoste->h_addr;
171                 log(DEBUG,"MakeOutboundConnection: gethostbyname was valid, setting %s",inet_ntoa(*ia));
172                 this->SetHostAddress(inet_ntoa(*ia),newport);
173                 SetHostAndPort(inet_ntoa(*ia),newport);
174         }
175
176         this->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
177         if (this->fd >= 0)
178         {
179                 if(connect(this->fd, (sockaddr*)&this->addr,sizeof(this->addr)))
180                 {
181                         WriteOpers("connect() failed for %s",host);
182                         RemoveServer(this->servername.c_str());
183                         return false;
184                 }
185                 int flags = fcntl(this->fd, F_GETFL, 0);
186                 fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
187                 int sendbuf = 32768;
188                 int recvbuf = 32768;
189                 setsockopt(this->fd,SOL_SOCKET,SO_SNDBUF,(const void *)&sendbuf,sizeof(sendbuf)); 
190                 setsockopt(this->fd,SOL_SOCKET,SO_RCVBUF,(const void *)&recvbuf,sizeof(sendbuf));
191                 return true;
192         }
193         else
194         {
195                 WriteOpers("socket() failed!");
196                 RemoveServer(this->servername.c_str());
197         }
198
199         return false;
200 }
201
202
203 void ircd_connector::SetVersionString(std::string newversion)
204 {
205         log(DEBUG,"Set version of %s to %s",this->servername.c_str(),newversion.c_str());
206         this->version = newversion;
207 }
208
209 std::string ircd_connector::GetVersionString()
210 {
211         return this->version;
212 }
213
214
215 std::string ircd_connector::GetServerName()
216 {
217         return this->servername;
218 }
219
220 std::string ircd_connector::GetDescription()
221 {
222         return this->description;
223 }
224
225 void ircd_connector::SetServerName(std::string serv)
226 {
227         this->servername = serv;
228 }
229
230 void ircd_connector::SetDescription(std::string desc)
231 {
232         this->description = desc;
233 }
234
235
236 int ircd_connector::GetDescriptor()
237 {
238         return this->fd;
239 }
240
241 int ircd_connector::GetState()
242 {
243         return this->state;
244 }
245
246
247 void ircd_connector::SetState(int newstate)
248 {
249         this->state = newstate;
250         if (state == STATE_DISCONNECTED)
251         {
252                 NetSendMyRoutingTable();
253         }
254 }
255
256 void ircd_connector::CloseConnection()
257 {
258         int flags = fcntl(this->fd, F_GETFL, 0);
259         fcntl(this->fd, F_SETFL, flags ^ O_NONBLOCK);
260         close(this->fd);
261         flags = fcntl(this->fd, F_GETFL, 0);
262         fcntl(this->fd, F_SETFL, flags | O_NONBLOCK);
263 }
264
265 void ircd_connector::SetDescriptor(int newfd)
266 {
267         this->fd = newfd;
268 }