]> git.mxchange.org Git - simgear.git/blob - simgear/io/sg_netChannel.cxx
Change IPAddress to use getaddrinfo internally, and store the sockaddr data via a...
[simgear.git] / simgear / io / sg_netChannel.cxx
1 /*
2   Copied from PLIB into SimGear
3   
4      PLIB - A Suite of Portable Game Libraries
5      Copyright (C) 1998,2002  Steve Baker
6  
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.
11  
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.
16  
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
20  
21      For further information visit http://plib.sourceforge.net
22
23      $Id: netChannel.cxx 1906 2004-03-22 19:44:50Z sjbaker $
24 */
25
26 // TODO:
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?
31
32 #include "sg_netChannel.hxx"
33
34 #include <memory>
35 #include <cassert>
36 #include <cstring>
37 #include <errno.h>
38
39 #include <simgear/debug/logstream.hxx>
40
41 namespace simgear  {
42
43 static NetChannel* channels = 0 ;
44
45 NetChannel::NetChannel ()
46 {
47   closed = true ;
48   connected = false ;
49   accepting = false ;
50   write_blocked = false ;
51   should_delete = false ;
52
53   next_channel = channels ;
54   channels = this ;
55 }
56   
57 NetChannel::~NetChannel ()
58 {
59   close();
60
61   NetChannel* prev = NULL ;
62
63   for ( NetChannel* ch = channels; ch != NULL;
64                     ch = ch -> next_channel )
65   {
66     if (ch == this)
67     {
68       ch = ch -> next_channel ;
69       if ( prev != NULL )
70         prev -> next_channel = ch ;
71       else
72         channels = ch ;
73       next_channel = 0 ;
74       break;
75     }
76     prev = ch ;
77   }
78 }
79   
80 void
81 NetChannel::setHandle (int handle, bool is_connected)
82 {
83   close () ;
84   Socket::setHandle ( handle ) ;
85   connected = is_connected ;
86   //if ( connected ) this->handleConnect();
87   closed = false ;
88 }
89
90 bool
91 NetChannel::open (void)
92 {
93   close();
94   if (Socket::open(true)) {
95     closed = false ;
96     setBlocking ( false ) ;
97     return true ;
98   }
99   return false ;
100 }
101
102 int
103 NetChannel::listen ( int backlog )
104 {
105   accepting = true ;
106   return Socket::listen ( backlog ) ;
107 }
108
109 int
110 NetChannel::connect ( const char* host, int port )
111 {
112   int result = Socket::connect ( host, port ) ;
113   if (result == 0) {
114     connected = true ;
115     //this->handleConnect();
116     return 0;
117   } else if (isNonBlockingError ()) {
118     return 0;
119   } else {
120     // some other error condition
121     this->handleError (result);
122     close();
123     return -1;
124   }
125 }
126
127 int
128 NetChannel::send (const void * buffer, int size, int flags)
129 {
130   int result = Socket::send (buffer, size, flags);
131   
132   if (result == (int)size) {
133     // everything was sent
134     write_blocked = false ;
135     return result;
136   } else if (result >= 0) {
137     // not all of it was sent, but no error
138     write_blocked = true ;
139     return result;
140   } else if (isNonBlockingError ()) {
141     write_blocked = true ;
142     return 0;
143   } else {
144     this->handleError (result);
145     close();
146     return -1;
147   }
148   
149 }
150
151 int
152 NetChannel::recv (void * buffer, int size, int flags)
153 {
154   int result = Socket::recv (buffer, size, flags);
155   
156   if (result > 0) {
157     return result;
158   } else if (result == 0) {
159     close();
160     return 0;
161   } else if (isNonBlockingError ()) {
162     return 0;
163   } else {
164     this->handleError (result);
165     close();
166     return -1;
167   }
168 }
169
170 void
171 NetChannel::close (void)
172 {
173   if ( !closed )
174   {
175     this->handleClose();
176   
177     closed = true ;
178     connected = false ;
179     accepting = false ;
180     write_blocked = false ;
181   }
182
183   Socket::close () ;
184 }
185
186 void
187 NetChannel::handleReadEvent (void)
188 {
189   if (accepting) {
190     if (!connected) {
191       connected = true ;
192       //this->handleConnect();
193     }
194     this->handleAccept();
195   } else if (!connected) {
196     connected = true ;
197     //this->handleConnect();
198     this->handleRead();
199   } else {
200     this->handleRead();
201   }
202 }
203
204 void
205 NetChannel::handleWriteEvent (void)
206 {
207   if (!connected) {
208     connected = true ;
209     //this->handleConnect();
210   }
211   write_blocked = false ;
212   this->handleWrite();
213 }
214
215 bool
216 NetChannel::poll (unsigned int timeout)
217 {
218   if (!channels)
219     return false ;
220   
221   enum { MAX_SOCKETS = 256 } ;
222   Socket* reads [ MAX_SOCKETS+1 ] ;
223   Socket* writes [ MAX_SOCKETS+1 ] ;
224   Socket* deletes [ MAX_SOCKETS+1 ] ;
225   int nreads = 0 ;
226   int nwrites = 0 ;
227   int ndeletes = 0 ;
228   int nopen = 0 ;
229   NetChannel* ch;
230   for (  ch = channels; ch != NULL; ch = ch -> next_channel )
231   {
232     if ( ch -> should_delete )
233     {
234       assert(ndeletes<MAX_SOCKETS);
235       deletes[ndeletes++] = ch ;
236     }
237     else if ( ! ch -> closed )
238     {
239       nopen++ ;
240       if (ch -> readable()) {
241         assert(nreads<MAX_SOCKETS);
242         reads[nreads++] = ch ;
243       }
244       if (ch -> writable()) {
245         assert(nwrites<MAX_SOCKETS);
246         writes[nwrites++] = ch ;
247       }
248     }
249   }
250   reads[nreads] = NULL ;
251   writes[nwrites] = NULL ;
252   deletes[ndeletes] = NULL ;
253
254   int i ;
255   for ( i=0; deletes[i]; i++ )
256   {
257     ch = (NetChannel*)deletes[i];
258     delete ch ;
259   }
260
261   if (!nopen)
262     return false ;
263   if (!nreads && !nwrites)
264     return true ; //hmmm- should we shutdown?
265
266   Socket::select (reads, writes, timeout) ;
267
268   for ( i=0; reads[i]; i++ )
269   {
270     ch = (NetChannel*)reads[i];
271     if ( ! ch -> closed )
272       ch -> handleReadEvent();
273   }
274
275   for ( i=0; writes[i]; i++ )
276   {
277     ch = (NetChannel*)writes[i];
278     if ( ! ch -> closed )
279       ch -> handleWriteEvent();
280   }
281
282   return true ;
283 }
284
285 void
286 NetChannel::loop (unsigned int timeout)
287 {
288   while ( poll (timeout) ) ;
289 }
290
291
292 void NetChannel::handleRead (void) {
293   SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled read");
294 }
295
296 void NetChannel::handleWrite (void) {
297   SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled write");
298 }
299
300 void NetChannel::handleAccept (void) {
301   SG_LOG(SG_IO, SG_WARN, "Network:" << getHandle() << ": unhandled accept");
302 }
303
304 void NetChannel::handleError (int error) {
305   SG_LOG(SG_IO, SG_WARN,"Network:" << getHandle() << ": errno: " << strerror(errno) <<"(" << errno << ")");
306 }
307
308 } // of namespace simgear