2 Copied from PLIB into SimGear
4 PLIB - A Suite of Portable Game Libraries
5 Copyright (C) 1998,2002 Steve Baker
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 For further information visit http://plib.sourceforge.net
23 $Id: netChannel.cxx 1906 2004-03-22 19:44:50Z sjbaker $
27 // have all socket-related functions assert that the socket has not
28 // been closed. [a read event may close it, and a write event may try
29 // to write or something...]
30 // Maybe assert valid handle, too?
32 #include "sg_netChannel.hxx"
39 #include <simgear/debug/logstream.hxx>
44 static NetChannel* channels = 0 ;
46 NetChannel::NetChannel ()
50 resolving_host = false;
52 write_blocked = false ;
53 should_delete = false ;
55 next_channel = channels ;
59 NetChannel::~NetChannel ()
63 NetChannel* prev = NULL ;
65 for ( NetChannel* ch = channels; ch != NULL;
66 ch = ch -> next_channel )
70 ch = ch -> next_channel ;
72 prev -> next_channel = ch ;
83 NetChannel::setHandle (int handle, bool is_connected)
86 Socket::setHandle ( handle ) ;
87 connected = is_connected ;
92 NetChannel::open (void)
95 if (Socket::open(true)) {
97 setBlocking ( false ) ;
104 NetChannel::listen ( int backlog )
107 return Socket::listen ( backlog ) ;
111 NetChannel::connect ( const char* h, int p )
115 resolving_host = true;
116 return handleResolve();
120 NetChannel::send (const void * buffer, int size, int flags)
122 int result = Socket::send (buffer, size, flags);
124 if (result == (int)size) {
125 // everything was sent
126 write_blocked = false ;
128 } else if (result >= 0) {
129 // not all of it was sent, but no error
130 write_blocked = true ;
132 } else if (isNonBlockingError ()) {
133 write_blocked = true ;
136 this->handleError (result);
144 NetChannel::recv (void * buffer, int size, int flags)
146 int result = Socket::recv (buffer, size, flags);
150 } else if (result == 0) {
153 } else if (isNonBlockingError ()) {
156 this->handleError (result);
163 NetChannel::close (void)
172 write_blocked = false ;
179 NetChannel::handleReadEvent (void)
185 this->handleAccept();
186 } else if (!connected) {
195 NetChannel::handleWriteEvent (void)
200 write_blocked = false ;
205 NetChannel::handleResolve()
208 if (!IPAddress::lookupNonblocking(host.c_str(), addr)) {
209 return 0; // not looked up yet, wait longer
212 if (!addr.isValid()) {
213 SG_LOG(SG_IO, SG_WARN, "Network: host lookup failed:" << host);
219 resolving_host = false;
221 int result = Socket::connect ( &addr ) ;
225 } else if (isNonBlockingError ()) {
228 // some other error condition
229 handleError (result);
236 NetChannel::poll (unsigned int timeout)
241 enum { MAX_SOCKETS = 256 } ;
242 Socket* reads [ MAX_SOCKETS+1 ] ;
243 Socket* writes [ MAX_SOCKETS+1 ] ;
244 Socket* deletes [ MAX_SOCKETS+1 ] ;
250 for ( ch = channels; ch != NULL; ch = ch -> next_channel )
252 if ( ch -> should_delete )
254 assert(ndeletes<MAX_SOCKETS);
255 deletes[ndeletes++] = ch ;
257 else if ( ! ch -> closed )
259 if (ch -> resolving_host )
261 ch -> handleResolve();
266 if (ch -> readable()) {
267 assert(nreads<MAX_SOCKETS);
268 reads[nreads++] = ch ;
270 if (ch -> writable()) {
271 assert(nwrites<MAX_SOCKETS);
272 writes[nwrites++] = ch ;
276 reads[nreads] = NULL ;
277 writes[nwrites] = NULL ;
278 deletes[ndeletes] = NULL ;
281 for ( i=0; deletes[i]; i++ )
283 ch = (NetChannel*)deletes[i];
289 if (!nreads && !nwrites)
290 return true ; //hmmm- should we shutdown?
292 Socket::select (reads, writes, timeout) ;
294 for ( i=0; reads[i]; i++ )
296 ch = (NetChannel*)reads[i];
297 if ( ! ch -> closed )
298 ch -> handleReadEvent();
301 for ( i=0; writes[i]; i++ )
303 ch = (NetChannel*)writes[i];
304 if ( ! ch -> closed )
305 ch -> handleWriteEvent();
312 NetChannel::loop (unsigned int timeout)
314 while ( poll (timeout) ) ;
318 void NetChannel::handleRead (void) {
319 SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled read");
322 void NetChannel::handleWrite (void) {
323 SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled write");
326 void NetChannel::handleAccept (void) {
327 SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled accept");
330 void NetChannel::handleError (int error) {
331 SG_LOG(SG_IO, SG_WARN,"Network:" << getHandle() << ": errno: " << strerror(errno) <<"(" << errno << ")");
334 } // of namespace simgear