87509674e2df3a2f1fef1374cf14a8bf9d1b0775
[ircu2.10.12-pk.git] / tools / Bounce / Bounce.cpp
1 #include "Bounce.h"
2
3 /*
4  *  Lacking Comments. :)
5  *  12/04/2000 --Gte
6  */
7
8 int main() {
9   Bounce* application = new Bounce();
10
11   /*
12    *  Ignore SIGPIPE.
13    */
14   struct sigaction act; 
15   act.sa_handler = SIG_IGN;
16   act.sa_flags = 0;
17   sigemptyset(&act.sa_mask);
18   sigaction(SIGPIPE, &act, 0);
19
20   /*
21    *  Create new application object, bind listeners and begin
22    *  polling them.
23    */
24   application->bindListeners();
25
26   while (1) {
27     application->checkSockets();
28   } 
29 }
30
31 void Bounce::bindListeners() { 
32   FILE* configFd;
33   char tempBuf[256];
34   int localPort = 0;
35   int remotePort = 0;
36   char* remoteServer;
37   char* vHost; 
38  
39   /*
40    *  Open config File.
41    */
42   
43   if(!(configFd = fopen("bounce.conf", "r")))
44   {
45     printf("Error, unable to open config.\n");
46     exit(0);
47   } 
48
49   while (fgets(tempBuf, 256, configFd) != NULL) { 
50     if((tempBuf[0] != '#') && (tempBuf[0] != '\r')) {
51     switch(tempBuf[0])
52     {
53       case 'P': { /* Add new port listener */ 
54       strtok(tempBuf, ":");
55       vHost = strtok(NULL, ":");
56       localPort = atoi(strtok(NULL, ":"));
57       remoteServer = strtok(NULL, ":");
58       remotePort = atoi(strtok(NULL, ":")); 
59
60       Listener* newListener = new Listener();
61       strcpy(newListener->myVhost, vHost); 
62       strcpy(newListener->remoteServer, remoteServer);
63       newListener->remotePort = remotePort;
64       newListener->localPort = localPort;
65       printf("Adding new Listener: Local: %s:%i, Remote: %s:%i\n", vHost, localPort, remoteServer, remotePort);
66
67       newListener->beginListening();
68       listenerList.insert(listenerList.begin(), newListener); 
69       break;
70       }
71     }
72     } 
73   } 
74 }
75
76 void Bounce::checkSockets() { 
77 /*
78  *  Build up a Select FD set, and Select() 'em.
79  */
80   typedef std::list<Listener*> listenerContainer;
81   typedef listenerContainer::iterator listIter;
82
83   typedef std::list<Connection*> connectionContainer;
84   typedef connectionContainer::iterator connIter; 
85
86   struct timeval tv;
87   fd_set readfds; 
88   tv.tv_sec = 0;
89   tv.tv_usec = 1000;
90   int tempFd = 0;
91   int tempFd2 = 0;
92   int highestFd = 0;
93   int delCheck = 0;
94   char* tempBuf;
95
96   FD_ZERO(&readfds);
97
98   listIter a = listenerList.begin();
99   while(a != listenerList.end())
100   { 
101     tempFd = (*a)->fd; 
102     FD_SET(tempFd, &readfds);
103     if (highestFd < tempFd) highestFd = tempFd;
104     a++;
105   }
106
107   connIter b = connectionsList.begin();
108   while(b != connectionsList.end())
109   { 
110     tempFd = (*b)->localSocket->fd;
111     tempFd2 = (*b)->remoteSocket->fd;
112     FD_SET(tempFd, &readfds);
113     if (highestFd < tempFd) highestFd = tempFd;
114     FD_SET(tempFd2, &readfds);
115     if (highestFd < tempFd2) highestFd = tempFd2;
116     b++;
117   }
118
119   select(highestFd+1, &readfds, NULL, NULL, &tv); 
120
121   /*
122    *  Check all connections for reading/writing
123    *  First check Local FD's.
124    */
125   b = connectionsList.begin();
126   while(b != connectionsList.end())
127   { 
128     tempFd = (*b)->localSocket->fd;
129  
130     if (FD_ISSET(tempFd, &readfds))
131     { 
132       tempBuf = (*b)->localSocket->read();
133       if ((tempBuf[0] == 0)) // Connection closed on one of our sockets.
134       {
135         close((*b)->localSocket->fd);
136         close((*b)->remoteSocket->fd); 
137         printf("Closing FD: %i\n", (*b)->localSocket->fd);
138         printf("Closing FD: %i\n", (*b)->remoteSocket->fd); 
139         delete(*b);
140         delCheck = 1;
141         b = connectionsList.erase(b); 
142       } else {
143         (*b)->remoteSocket->write(tempBuf, (*b)->localSocket->lastReadSize); 
144       }
145     } 
146  
147   if (!delCheck) b++;
148   delCheck = 0;
149   } 
150
151   /*
152    *  Now check Remote FD's..
153    */
154   b = connectionsList.begin();
155   while(b != connectionsList.end())
156   { 
157     tempFd = (*b)->remoteSocket->fd;
158     if (FD_ISSET(tempFd, &readfds))
159     {
160       tempBuf = (*b)->remoteSocket->read();
161       if ((tempBuf[0] == 0)) // Connection closed on one of our sockets.
162       {
163         close((*b)->localSocket->fd);
164         close((*b)->remoteSocket->fd); 
165         printf("Closing FD: %i\n", (*b)->localSocket->fd);
166         printf("Closing FD: %i\n", (*b)->remoteSocket->fd);
167         delete(*b);
168         delCheck = 1;
169         b = connectionsList.erase(b); 
170       } else {
171         (*b)->localSocket->write(tempBuf, (*b)->remoteSocket->lastReadSize);
172       }
173     }
174   if (!delCheck) b++;
175   delCheck = 0;
176   } 
177  
178   /*
179    *  Check all listeners for new connections.
180    */
181   a = listenerList.begin();
182   while(a != listenerList.end())
183   { 
184     tempFd = (*a)->fd; 
185     if (FD_ISSET(tempFd, &readfds))
186     { 
187       recieveNewConnection(*a);
188     }
189     a++;
190   } 
191
192 }
193
194 void Bounce::recieveNewConnection(Listener* listener)
195 {
196   Connection* newConnection = new Connection(); 
197   newConnection->localSocket = listener->handleAccept();
198
199   Socket* remoteSocket = new Socket();
200   newConnection->remoteSocket = remoteSocket; 
201   if(remoteSocket->connectTo(listener->remoteServer, listener->remotePort)) { 
202     connectionsList.insert(connectionsList.begin(), newConnection);
203   } else {
204     newConnection->localSocket->write("Unable to connect to remote host..\n");
205     close(newConnection->localSocket->fd);
206     delete(newConnection);
207     delete(remoteSocket);
208   } 
209 }
210  
211  
212 Socket* Listener::handleAccept() {
213   int new_fd = 0;
214   int sin_size = sizeof(struct sockaddr_in);
215
216   Socket* newSocket = new Socket();
217   new_fd = accept(fd, (struct sockaddr*)&newSocket->address, (socklen_t*)&sin_size);
218   newSocket->fd = new_fd; 
219   return newSocket;
220 }
221  
222 void Listener::beginListening() {
223   struct sockaddr_in my_addr;
224   int bindRes;
225   int optval;
226   optval = 1;
227
228   fd = socket(AF_INET, SOCK_STREAM, 0); /* Check for no FD's left?! */
229
230   my_addr.sin_family = AF_INET;
231   my_addr.sin_port = htons(localPort);
232   my_addr.sin_addr.s_addr = inet_addr(myVhost);
233   bzero(&(my_addr.sin_zero), 8);
234
235   setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
236
237   bindRes = bind(fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
238   if(bindRes == 0)
239   {
240     listen(fd, 10);
241   } else { 
242      /*
243       *  If we can't bind a listening port, we might aswell drop out.
244       */
245      printf("Unable to bind to %s:%i!\n", myVhost, localPort);
246      exit(0);
247    } 
248 }
249
250 Socket::Socket() {
251   fd = -1;
252   lastReadSize = 0;
253 }
254
255 int Socket::write(char *message, int len)
256
257    if (fd == -1) return 0; 
258  
259    int amount = ::write(fd, message, len); 
260    printf("Wrote %i Bytes.\n", amount);
261    return amount; 
262 }
263
264 int Socket::write(char *message)
265
266    if (fd == -1) return 0; 
267  
268    int amount = ::write(fd, message, strlen(message)); 
269    printf("Wrote %i Bytes.\n", amount);
270    return amount; 
271 }
272
273
274 int Socket::connectTo(char *hostname, unsigned short portnum) { 
275   struct hostent     *hp;
276  
277   if ((hp = gethostbyname(hostname)) == NULL) { 
278      return 0; 
279   }          
280
281   memset(&address,0,sizeof(address));
282   memcpy((char *)&address.sin_addr,hp->h_addr,hp->h_length);
283   address.sin_family= hp->h_addrtype;
284   address.sin_port= htons((u_short)portnum);
285
286   if ((fd = socket(hp->h_addrtype,SOCK_STREAM,0)) < 0)
287     return 0; 
288  
289   if (connect(fd, (struct sockaddr*)&address, sizeof(address)) < 0) {
290     close(fd);
291     fd = -1; 
292     return 0;
293   } 
294   return(1);
295 }
296
297 char* Socket::read()
298
299   int amountRead = 0;
300   static char buffer[4096];
301
302   amountRead = ::read(fd, &buffer, 4096);
303
304   if ((amountRead == -1)) buffer[0] = '\0';
305   buffer[amountRead] = '\0';
306
307   printf("Read %i Bytes.\n", amountRead);
308   /* Record this incase we're dealing with binary data with 0's in it. */
309   lastReadSize = amountRead;
310   return (char *)&buffer;
311 }