ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/router/ipsocket.cpp
Revision: 1.2
Committed: 2008-01-01T09:40:34Z (16 years, 11 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +1 -1 lines
Log Message:
Happy New Year!

File Contents

# Content
1 /*
2 * ipsocket.cpp - ip router
3 *
4 * Basilisk II (C) 1997-2008 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 }