ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/router/ipsocket.cpp
Revision: 1.1
Committed: 2004-12-05T16:48:36Z (19 years, 7 months ago) by gbeauche
Branch: MAIN
CVS Tags: nigel-build-19, nigel-build-17
Log Message:
import NAT-Router code from original Basilisk II for Windows

File Contents

# User Rev Content
1 gbeauche 1.1 /*
2     * ipsocket.cpp - ip router
3     *
4     * Basilisk II (C) 1997-2001 Christian Bauer
5     *
6     * Windows platform specific code copyright (C) Lauri Pesonen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21     */
22    
23     #include "sysdeps.h"
24     #include "cpu_emulation.h"
25     #include "ws2tcpip.h"
26     #include "prefs.h"
27     #include "ether_windows.h"
28     #include "ether.h"
29     #include "router.h"
30     #include "router_types.h"
31     #include "dynsockets.h"
32     #include "ipsocket.h"
33     #include "icmp.h"
34     #include "tcp.h"
35     #include "udp.h"
36     #include "dump.h"
37    
38    
39     #if DEBUG
40     #pragma optimize("",off)
41     #endif
42    
43     #include "debug.h"
44    
45    
46     socket_t::socket_t( int _proto )
47     {
48     s = INVALID_SOCKET;
49     proto = _proto;
50    
51     ip_src = ip_dest = 0;
52     src_port = dest_port = 0;
53    
54     memset( &overlapped, 0, sizeof(overlapped) );
55     overlapped.hEvent = (HANDLE)this;
56    
57     bytes_received = 0;
58     flags = 0;
59     from_len = sizeof(struct sockaddr_in);
60     memset( &from, 0, sizeof(from) );
61     from.sin_family = AF_INET;
62    
63     buffer_count = 1;
64     buffers[0].len = 1460;
65     buffers[0].buf = new char [buffers[0].len];
66    
67     out_buffers[0].len = 1460;
68     out_buffers[0].buf = new char [out_buffers[0].len];
69    
70     socket_ttl = GetTickCount() + 60000L;
71     permanent = false;
72     }
73    
74     socket_t::~socket_t()
75     {
76     if(s != INVALID_SOCKET) {
77     _closesocket( s ); // slam!
78     s = INVALID_SOCKET;
79     }
80     delete [] out_buffers[0].buf;
81     delete [] buffers[0].buf;
82     }
83    
84     int socket_t::WSARecvFrom()
85     {
86     return _WSARecvFrom(
87     s,
88     buffers,
89     buffer_count,
90     &bytes_received,
91     &flags,
92     (struct sockaddr *)&from,
93     &from_len,
94     &overlapped,
95     proto == IPPROTO_UDP ? udp_read_completion : icmp_read_completion
96     );
97     }
98    
99     bool socket_t::b_recfrom()
100     {
101     bool result;
102    
103     int ret = WSARecvFrom();
104    
105     if(ret == SOCKET_ERROR) {
106     int socket_error = _WSAGetLastError();
107     if(socket_error == WSA_IO_PENDING) {
108     D(bug("WSARecvFrom() i/o pending\r\n"));
109     result = true;
110     } else {
111     D(bug("_WSAGetLastError() returned %d\r\n", socket_error));
112     result = false;
113     }
114     } else /*if(ret == 0) */ {
115     D(bug("WSARecvFrom() ok\r\n"));
116     // Completion routine call is already scheduled.
117     result = true;
118     }
119     return result;
120     }
121    
122     void socket_t::set_ttl( uint8 ttl )
123     {
124     int _ttl = ttl; // defensive programming, I know VCx
125    
126     if(_setsockopt( s, IPPROTO_IP, IP_TTL, (const char *)&_ttl, sizeof(int) ) == SOCKET_ERROR ) {
127     D(bug("could not set ttl to %d.\r\n", ttl));
128     } else {
129     D(bug("ttl set to %d.\r\n", ttl));
130     }
131     }
132    
133    
134     #define MAX_OPEN_SOCKETS 1024
135     static socket_t *all_sockets[MAX_OPEN_SOCKETS];
136     static int open_sockets = 0;
137    
138     int get_socket_index( uint16 src_port, uint16 dest_port, int proto )
139     {
140     int result = -1;
141     for( int i=0; i<open_sockets; i++ ) {
142     socket_t *cmpl = all_sockets[i];
143     if(cmpl->src_port == src_port && cmpl->dest_port == dest_port && cmpl->proto == proto ) {
144     result = i;
145     break;
146     }
147     }
148     return result;
149     }
150    
151     int get_socket_index( uint16 src_port, int proto )
152     {
153     int result = -1;
154     for( int i=0; i<open_sockets; i++ ) {
155     socket_t *cmpl = all_sockets[i];
156     if(cmpl->src_port == src_port && cmpl->proto == proto ) {
157     result = i;
158     break;
159     }
160     }
161     return result;
162     }
163    
164     int get_socket_index( socket_t *cmpl )
165     {
166     int result = -1;
167     for( int i=0; i<open_sockets; i++ ) {
168     if(cmpl == all_sockets[i]) {
169     result = i;
170     break;
171     }
172     }
173     return result;
174     }
175    
176     void delete_socket( socket_t *cmpl )
177     {
178     D(bug("deleting socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
179    
180     EnterCriticalSection( &router_section );
181     int i = get_socket_index( cmpl );
182     if( i >= 0 ) {
183     delete all_sockets[i];
184     all_sockets[i] = all_sockets[--open_sockets];
185     } else {
186     D(bug("Deleted socket not in table!\r\n"));
187     // delete cmpl;
188     }
189     LeaveCriticalSection( &router_section );
190     }
191    
192     socket_t *find_socket( uint16 src_port, uint16 dest_port, int proto )
193     {
194     socket_t *result = 0;
195     EnterCriticalSection( &router_section );
196     int i = get_socket_index( src_port, dest_port, proto );
197     if( i >= 0 ) {
198     result = all_sockets[i];
199     } else {
200     i = get_socket_index( src_port, proto );
201     if( i >= 0 ) {
202     delete_socket( all_sockets[i] );
203     }
204     }
205     LeaveCriticalSection( &router_section );
206    
207     D(bug("find_socket(%d,%d): %s\r\n", src_port, dest_port, result ? "found" : "not found"));
208    
209     return result;
210     }
211    
212     void add_socket( socket_t *cmpl )
213     {
214     D(bug("adding socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
215    
216     EnterCriticalSection( &router_section );
217     if( open_sockets < MAX_OPEN_SOCKETS ) {
218     all_sockets[open_sockets++] = cmpl;
219     } else {
220     // Urgchiyuppijee! (that's finnish language, meaning "do something about this")
221     delete all_sockets[0];
222     all_sockets[0] = cmpl;
223     }
224     LeaveCriticalSection( &router_section );
225     }
226    
227     void close_old_sockets()
228     {
229     DWORD now = GetTickCount();
230    
231     EnterCriticalSection( &router_section );
232     for( int i=open_sockets-1; i>=0; i-- ) {
233     socket_t *cmpl = all_sockets[i];
234     if( !cmpl->permanent && now >= cmpl->socket_ttl ) {
235     D(bug("expiring socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
236     if(cmpl->s == INVALID_SOCKET) {
237     delete all_sockets[i];
238     all_sockets[i] = all_sockets[--open_sockets];
239     } else {
240     // read completion will deallocate
241     _closesocket( cmpl->s );
242     }
243     }
244     }
245     LeaveCriticalSection( &router_section );
246     }
247    
248     void close_all_sockets()
249     {
250     D(bug("closing all(%d) sockets\r\n", open_sockets));
251    
252     EnterCriticalSection( &router_section );
253     for( int i=0; i<open_sockets; i++ ) {
254     socket_t *cmpl = all_sockets[i];
255     D(bug("closing socket(%d,%d)\r\n", cmpl->src_port, cmpl->dest_port));
256     if(cmpl->s == INVALID_SOCKET) {
257     delete all_sockets[i];
258     all_sockets[i] = all_sockets[--open_sockets];
259     } else {
260     // read completion will deallocate
261     _closesocket( cmpl->s );
262     }
263     }
264     LeaveCriticalSection( &router_section );
265     }