Rev 984 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed
| Rev 984 | Rev 999 | ||
|---|---|---|---|
| Line 16... | Line 16... | ||
| 16 | * You should have received a copy of the GNU General Public License * |
16 | * You should have received a copy of the GNU General Public License * |
| 17 | * along with this program; if not, write to the * |
17 | * along with this program; if not, write to the * |
| 18 | * Free Software Foundation, Inc., * |
18 | * Free Software Foundation, Inc., * |
| 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
| 20 | ***************************************************************************/ |
20 | ***************************************************************************/ |
| - | 21 | ||
| - | 22 | #include "socketeventcallback.h" |
|
| - | 23 | ||
| 21 | 24 | ||
| 22 | #include "asyncsocket.h" |
25 | #include "asyncsocket.h" |
| 23 | 26 | ||
| 24 | int socketCount = 1; |
27 | int socketCount = 1; |
| 25 | 28 | ||
| Line 27... | Line 30... | ||
| 27 | { |
30 | { |
| 28 | myId = socketCount++; |
31 | myId = socketCount++; |
| 29 | mySocket = -1; |
32 | mySocket = -1; |
| 30 | myReconnectTimeout = 0; |
33 | myReconnectTimeout = 0; |
| 31 | myForceReconnect = false; |
34 | myForceReconnect = false; |
| - | 35 | myEventCallback = NULL; |
|
| 32 | } |
36 | } |
| 33 | 37 | ||
| 34 | AsyncSocket::~AsyncSocket() |
38 | AsyncSocket::~AsyncSocket() |
| 35 | { |
39 | { |
| 36 | stop(); |
40 | stop(); |
| Line 239... | Line 243... | ||
| 239 | 243 | ||
| 240 | case ENOTSOCK: |
244 | case ENOTSOCK: |
| 241 | throw new SocketException("sockfd is a descriptor for a file, not a socket."); |
245 | throw new SocketException("sockfd is a descriptor for a file, not a socket."); |
| 242 | 246 | ||
| 243 | //case EACCES: |
247 | //case EACCES: |
| 244 | //throw new SocketException("Search permission is denied on a component of the path prefix. (See also path_resolution(7).)"); |
248 | //throw new SocketException("Search permission is denied on a component of the path prefix. (See also path_resolution(7).)"); |
| 245 | 249 | ||
| 246 | case EADDRNOTAVAIL: |
250 | case EADDRNOTAVAIL: |
| 247 | throw new SocketException("A nonexistent interface was requested or the requested address was not local."); |
251 | throw new SocketException("A nonexistent interface was requested or the requested address was not local."); |
| 248 | 252 | ||
| 249 | case EFAULT: |
253 | case EFAULT: |
| 250 | throw new SocketException("addr points outside the user's accessible address space."); |
254 | throw new SocketException("addr points outside the user's accessible address space."); |
| Line 261... | Line 265... | ||
| 261 | case ENOENT: |
265 | case ENOENT: |
| 262 | throw new SocketException("The file does not exist."); |
266 | throw new SocketException("The file does not exist."); |
| 263 | 267 | ||
| 264 | case ENOMEM: |
268 | case ENOMEM: |
| 265 | throw new SocketException("Insufficient kernel memory was available."); |
269 | throw new SocketException("Insufficient kernel memory was available."); |
| 266 | 270 | ||
| 267 | case ENOTDIR: |
271 | case ENOTDIR: |
| 268 | throw new SocketException("A component of the path prefix is not a directory."); |
272 | throw new SocketException("A component of the path prefix is not a directory."); |
| 269 | 273 | ||
| 270 | case EROFS: |
274 | case EROFS: |
| 271 | throw new SocketException("The socket inode would reside on a read-only file system."); |
275 | throw new SocketException("The socket inode would reside on a read-only file system."); |
| 272 | 276 | ||
| 273 | default: |
277 | default: |
| 274 | throw new SocketException("Unknow exception: " + itos(errno)); |
278 | throw new SocketException("Unknow exception: " + itos(errno)); |
| 275 | break; |
279 | break; |
| 276 | } |
280 | } |
| 277 | } |
281 | } |
| 278 | 282 | ||
| 279 | status = ::listen(mySocket, MAXCONNECTIONS); |
283 | status = ::listen(mySocket, MAXCONNECTIONS); |
| 280 | 284 | ||
| 281 | if (status == -1) |
285 | if (status == -1) |
| 282 | { |
286 | { |
| 283 | silentClose(); |
287 | silentClose(); |
| 284 | switch (errno) |
288 | switch (errno) |
| 285 | { |
289 | { |
| Line 289... | Line 293... | ||
| 289 | case EBADF: |
293 | case EBADF: |
| 290 | throw new SocketException("The argument sockfd is not a valid descriptor."); |
294 | throw new SocketException("The argument sockfd is not a valid descriptor."); |
| 291 | 295 | ||
| 292 | case ENOTSOCK: |
296 | case ENOTSOCK: |
| 293 | throw new SocketException("The argument sockfd is not a socket."); |
297 | throw new SocketException("The argument sockfd is not a socket."); |
| 294 | 298 | ||
| 295 | case EOPNOTSUPP: |
299 | case EOPNOTSUPP: |
| 296 | throw new SocketException("The socket is not of a type that supports the listen() operation."); |
300 | throw new SocketException("The socket is not of a type that supports the listen() operation."); |
| 297 | 301 | ||
| 298 | default: |
302 | default: |
| 299 | throw new SocketException("Unknow exception: " + itos(errno)); |
303 | throw new SocketException("Unknow exception: " + itos(errno)); |
| 300 | break; |
304 | break; |
| 301 | } |
305 | } |
| 302 | } |
306 | } |
| 303 | } |
307 | } |
| 304 | 308 | ||
| 305 | bool AsyncSocket::accept(AsyncSocket* newSocket) |
309 | bool AsyncSocket::accept(AsyncSocket* newSocket) |
| 306 | { |
310 | { |
| Line 309... | Line 313... | ||
| 309 | 313 | ||
| 310 | if (socket > 0) |
314 | if (socket > 0) |
| 311 | { |
315 | { |
| 312 | newSocket->setSocket(socket); |
316 | newSocket->setSocket(socket); |
| 313 | return true; |
317 | return true; |
| 314 | } |
318 | } |
| 315 | 319 | ||
| 316 | return false; |
320 | return false; |
| 317 | } |
321 | } |
| 318 | 322 | ||
| 319 | void AsyncSocket::connect() |
323 | void AsyncSocket::connect() |
| 320 | { |
324 | { |
| 321 | eventAdd(SocketEvent::TYPE_CONNECTING); |
325 | eventAdd(SocketEvent::TYPE_CONNECTING); |
| 322 | 326 | ||
| 323 | create(); |
327 | create(); |
| 324 | 328 | ||
| 325 | memset(&myAddressStruct, 0, sizeof(myAddressStruct)); |
329 | memset(&myAddressStruct, 0, sizeof(myAddressStruct)); |
| 326 | 330 | ||
| 327 | myAddressStruct.sin_family = AF_INET; |
331 | myAddressStruct.sin_family = AF_INET; |
| 328 | myAddressStruct.sin_port = htons(myPort); |
332 | myAddressStruct.sin_port = htons(myPort); |
| 329 | 333 | ||
| 330 | struct hostent *hptr = gethostbyname(myAddress.c_str()); |
334 | struct hostent *hptr = gethostbyname(myAddress.c_str()); |
| 331 | if (hptr == NULL) |
335 | if (hptr == NULL) |
| 332 | { |
336 | { |
| 333 | silentClose(); |
337 | silentClose(); |
| 334 | throw new SocketException("Connect: Could not resolv ip address"); |
338 | throw new SocketException("Connect: Could not resolv ip address"); |
| 335 | } |
339 | } |
| 336 | 340 | ||
| 337 | memcpy(&myAddressStruct.sin_addr, hptr->h_addr, hptr->h_length); |
341 | memcpy(&myAddressStruct.sin_addr, hptr->h_addr, hptr->h_length); |
| 338 | 342 | ||
| 339 | int status = ::connect(mySocket, (sockaddr*)&myAddressStruct, sizeof(myAddressStruct)); |
343 | int status = ::connect(mySocket, (sockaddr*)&myAddressStruct, sizeof(myAddressStruct)); |
| 340 | 344 | ||
| 341 | if (status == -1) |
345 | if (status == -1) |
| Line 352... | Line 356... | ||
| 352 | case EADDRINUSE: |
356 | case EADDRINUSE: |
| 353 | throw new SocketException("Local address is already in use."); |
357 | throw new SocketException("Local address is already in use."); |
| 354 | 358 | ||
| 355 | case EAFNOSUPPORT: |
359 | case EAFNOSUPPORT: |
| 356 | throw new SocketException("The passed address didn't have the correct address family in its sa_family field."); |
360 | throw new SocketException("The passed address didn't have the correct address family in its sa_family field."); |
| 357 | 361 | ||
| 358 | case EAGAIN: |
362 | case EAGAIN: |
| 359 | throw new SocketException("No more free local ports or insufficient entries in the routing cache. For AF_INET see the net.ipv4.ip_local_port_range sysctl in ip(7) on how to increase the number of local ports."); |
363 | throw new SocketException("No more free local ports or insufficient entries in the routing cache. For AF_INET see the net.ipv4.ip_local_port_range sysctl in ip(7) on how to increase the number of local ports."); |
| 360 | 364 | ||
| 361 | case EALREADY: |
365 | case EALREADY: |
| 362 | throw new SocketException("The socket is non-blocking and a previous connection attempt has not yet been completed."); |
366 | throw new SocketException("The socket is non-blocking and a previous connection attempt has not yet been completed."); |
| Line 464... | Line 468... | ||
| 464 | } |
468 | } |
| 465 | 469 | ||
| 466 | void AsyncSocket::eventAdd(unsigned int eventType, string eventData) |
470 | void AsyncSocket::eventAdd(unsigned int eventType, string eventData) |
| 467 | { |
471 | { |
| 468 | SocketEvent socketEvent(eventType, eventData); |
472 | SocketEvent socketEvent(eventType, eventData); |
| - | 473 | ||
| - | 474 | if (myEventCallback == NULL) |
|
| - | 475 | { |
|
| 469 | myEventQueue.push(socketEvent); |
476 | myEventQueue.push(socketEvent); |
| 470 | myEventSemaphore.broadcast(); |
477 | myEventSemaphore.broadcast(); |
| - | 478 | } |
|
| - | 479 | else |
|
| - | 480 | { |
|
| - | 481 | myEventCallback->handleEvent(myId, socketEvent); |
|
| - | 482 | } |
|
| - | 483 | } |
|
| - | 484 | ||
| - | 485 | void AsyncSocket::eventSetCallback(SocketEventCallback* eventCallback) |
|
| - | 486 | { |
|
| - | 487 | myEventCallback = eventCallback; |
|
| 471 | } |
488 | } |