Subversion Repositories HomeAutomation

Rev

Rev 976 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 976 Rev 981
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 <map>
-
 
23
 
-
 
24
 
-
 
25
#include <vector>
-
 
26
 
21
 
27
 
22
#include "asyncsocket.h"
28
#include "asyncsocket.h"
23
 
29
 
-
 
30
map<string, AsyncSocket*> AsyncSocket::mySockets;
24
Semaphore AsyncSocket::mySemaphore;
31
Mutex AsyncSocket::mySocketsMutex;
25
 
32
 
26
AsyncSocket::AsyncSocket()
33
AsyncSocket::AsyncSocket()
27
{
34
{
-
 
35
    myId = itos(time(NULL)) + itos(mySockets.size());
-
 
36
 
-
 
37
    mySockets[myId] = this;
-
 
38
 
-
 
39
    cout << "DEBUG: Started " << myId << endl;
-
 
40
 
28
    mySocket = -1;
41
    mySocket = -1;
29
    myReconnectTimeout = 0;
42
    myReconnectTimeout = 0;
30
    myForceReconnect = false;
43
    myForceReconnect = false;
-
 
44
 
31
 
45
 
32
    Thread<AsyncSocket>();
46
    Thread<AsyncSocket>();
33
}
47
}
34
 
48
 
35
AsyncSocket::~AsyncSocket()
49
AsyncSocket::~AsyncSocket()
36
{
50
{
-
 
51
    mySemaphore.unlock();
-
 
52
 
37
    if (mySocket != -1)
53
    if (mySocket != -1)
38
    {
54
    {
39
        ::close(mySocket);
55
        ::close(mySocket);
40
        mySocket = -1;
56
        mySocket = -1;
41
    }
57
    }
-
 
58
 
-
 
59
    mySockets.erase(myId);
42
   
60
 
43
    stop();
61
    stop();
44
}
62
}
45
 
63
 
46
void AsyncSocket::run()
64
void AsyncSocket::run()
47
{
65
{
48
    SyslogStream &slog = SyslogStream::getInstance();
66
    SyslogStream &slog = SyslogStream::getInstance();
49
 
67
 
50
    if (myReconnectTimeout == 0)
68
    if (!isConnected())
51
    {
69
    {
-
 
70
        if (myReconnectTimeout == 0)
-
 
71
        {
52
        connect();
72
            connect();
53
    }
73
        }
54
    else
74
        else
55
    {
75
        {
56
        reconnectLoop();
76
            reconnectLoop();
-
 
77
        }
57
    }
78
    }
58
 
79
 
59
    char buf[MAXBUFFER + 1];
80
    char buf[MAXBUFFER + 1];
60
    string data;
81
    string data;
61
    int status;
82
    int status;
62
    int rc;
83
    int rc;
63
    int timeSince = time(NULL) + 10;
84
    int timeSince = time(NULL) + 10;
64
   
-
 
65
   
-
 
66
 
85
 
67
    try
86
    try
68
    {
87
    {
69
        while (1)
88
        while (1)
70
        {
89
        {
71
            AsyncSocket::mySemaphore.lock();
90
            AsyncSocket::mySemaphore.lock();
72
 
91
 
73
            if (myReconnectTimeout == 0)
-
 
74
            {
-
 
75
                rc = mySemaphore.wait();
-
 
76
            }
-
 
77
            else
-
 
78
            {
-
 
79
                rc = mySemaphore.wait(10);
92
            rc = mySemaphore.wait(10);
80
            }
-
 
81
 
93
 
82
            AsyncSocket::mySemaphore.unlock();
94
            AsyncSocket::mySemaphore.unlock();
83
 
95
 
84
            if (myForceReconnect)
96
            if (myForceReconnect)
85
            {
97
            {
86
                slog << "Disconnected from server.\n";
98
                slog << "Disconnected from server.\n";
87
                reconnectLoop();
99
                reconnectLoop();
88
                timeSince = time(NULL) + 10;
100
                timeSince = time(NULL) + 10;
89
                continue;
101
                continue;
90
            }
102
            }
91
 
103
 
92
            //cout << "Socket awoken...\n";
104
            //cout << "Socket awoken...\n";
93
           
105
           
94
            if (rc == ETIMEDOUT)
106
            if (rc == ETIMEDOUT)
95
            {
107
            {
Line 103... Line 115...
103
            {
115
            {
104
                while (myOutQueue.size() > 0)
116
                while (myOutQueue.size() > 0)
105
                {
117
                {
106
                    data = myOutQueue.pop();
118
                    data = myOutQueue.pop();
107
 
119
 
108
                    //slog << "Sending: " << data << "\n";
-
 
109
 
-
 
110
                    status = ::send(mySocket, data.c_str(), data.size(), 0);
-
 
111
 
-
 
112
                    //slog << "Status: " << status << "\n";
-
 
113
 
-
 
114
                    if (status == -1)
-
 
115
                    {
-
 
116
                        switch (errno)
-
 
117
                        {
-
 
118
                            case EACCES:
-
 
119
                            throw new SocketException("(For  Unix  domain sockets, which are identified by pathname) Write permission is denied on the destination socket file, or search permission is denied for one of the directories the path prefix.  (See path_resolution(7).)");
120
                    sendDataDirect(data);
120
 
-
 
121
                            case EAGAIN:
-
 
122
                            //slog << "The socket is marked non-blocking and the requested operation would block.\n";
-
 
123
                            break;
-
 
124
 
-
 
125
                            case EBADF:
-
 
126
                            throw new SocketException("An invalid descriptor was specified.");
-
 
127
 
-
 
128
                            case ECONNRESET:
-
 
129
                            throw new SocketException("Connection reset by peer.");
-
 
130
 
-
 
131
                            case EDESTADDRREQ:
-
 
132
                            throw new SocketException("The socket is not connection-mode, and no peer address is set.");
-
 
133
 
-
 
134
                            case EFAULT:
-
 
135
                            throw new SocketException("An invalid user space address was specified for an argument.");
-
 
136
 
-
 
137
                            case EINTR:
-
 
138
                            throw new SocketException("A signal occurred before any data was transmitted; see signal(7).");
-
 
139
 
-
 
140
                            case EINVAL:
-
 
141
                            throw new SocketException("1Invalid argument passed.");
-
 
142
 
-
 
143
                            case EISCONN:
-
 
144
                            throw new SocketException("The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.)");
-
 
145
 
-
 
146
                            case EMSGSIZE:
-
 
147
                            throw new SocketException("The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.");
-
 
148
 
-
 
149
                            case ENOBUFS:
-
 
150
                            throw new SocketException("The output queue for a network interface was full.  This generally indicates that the interface has stopped sending, but may be caused by transient congestion.  (Normally, this does not occur in Linux.  Packets are just silently dropped when a device queue overflows.)");
-
 
151
 
-
 
152
                            case ENOMEM:
-
 
153
                            throw new SocketException("No memory available.");
-
 
154
 
-
 
155
                            case ENOTCONN:
-
 
156
                            throw new SocketException("The socket is not connected, and no target has been given.");
-
 
157
 
-
 
158
                            case ENOTSOCK:
-
 
159
                            throw new SocketException("The argument s is not a socket.");
-
 
160
 
-
 
161
                            case EOPNOTSUPP:
-
 
162
                            throw new SocketException("Some bit in the flags argument is inappropriate for the socket type.");
-
 
163
 
-
 
164
                            case EPIPE:
-
 
165
                            throw new SocketException("The  local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.");
-
 
166
 
-
 
167
                            default:
-
 
168
                            slog << "Unknow exception: " + itos(errno) + "\n";
-
 
169
                            break;
-
 
170
                        }
-
 
171
                    }
-
 
172
                }
121
                }
173
 
122
 
174
                memset(buf, 0, MAXBUFFER + 1);
123
                memset(buf, 0, MAXBUFFER + 1);
175
 
124
 
176
                status = ::recv(mySocket, buf, MAXBUFFER, 0);
125
                status = ::recv(mySocket, buf, MAXBUFFER, 0);
Line 223... Line 172...
223
                    timeSince = time(NULL);
172
                    timeSince = time(NULL);
224
                }
173
                }
225
                else if (status > 0)
174
                else if (status > 0)
226
                {
175
                {
227
                    timeSince = time(NULL) + 10;
176
                    timeSince = time(NULL) + 10;
228
 
177
 
229
                    data = buf;
178
                    data = buf;
230
 
179
 
231
                    //slog << "Receiving: " + data + "\n";
180
                    //slog << "Receiving: " + data + "\n";
232
 
181
 
233
                    myInQueue.push(data);
182
                    myInQueue.push(data);
Line 247... Line 196...
247
    {
196
    {
248
        slog << "Exception: " + e->getDescription() + "\n";
197
        slog << "Exception: " + e->getDescription() + "\n";
249
        //mySemaphore.unlock();
198
        //mySemaphore.unlock();
250
        setEvent(ASYNCSOCKET_EVENT_DIED);
199
        setEvent(ASYNCSOCKET_EVENT_DIED);
251
        stop();
200
        stop();
252
    }
201
    }
253
 
202
 
254
    close();
203
    close();
255
 
204
 
256
    //mySemaphore.unlock();
205
    //mySemaphore.unlock();
257
}
206
}
258
 
207
 
259
void AsyncSocket::reconnectLoop()
208
void AsyncSocket::reconnectLoop()
260
{
209
{
261
    if (myReconnectTimeout == 0)
210
    if (myReconnectTimeout == 0)
262
    {
211
    {
-
 
212
        close();
263
        throw new SocketException("Connection is closed.");
213
        throw new SocketException("Connection is closed.");
264
    }
214
    }
265
 
215
 
266
    SyslogStream &slog = SyslogStream::getInstance();
216
    SyslogStream &slog = SyslogStream::getInstance();
267
 
217
 
Line 275... Line 225...
275
        catch (SocketException *e)
225
        catch (SocketException *e)
276
        {
226
        {
277
            slog << "Could not connect: " + e->getDescription() + "\n";
227
            slog << "Could not connect: " + e->getDescription() + "\n";
278
            slog << "Will try again in " + itos(myReconnectTimeout) + " seconds\n";
228
            slog << "Will try again in " + itos(myReconnectTimeout) + " seconds\n";
279
            sleep(myReconnectTimeout);
229
            sleep(myReconnectTimeout);
-
 
230
        }
-
 
231
    }
-
 
232
}
-
 
233
 
-
 
234
void AsyncSocket::create()
-
 
235
{
-
 
236
    close();
-
 
237
 
-
 
238
    mySocket = ::socket(AF_INET, SOCK_STREAM, 0);
-
 
239
 
-
 
240
    int on = 1;
-
 
241
    int status = setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
-
 
242
    if (status == -1)
-
 
243
    {
-
 
244
        close();
-
 
245
        throw new SocketException("Create:Reuseaddress: " + itos(errno));
-
 
246
    }
-
 
247
}
-
 
248
 
-
 
249
void AsyncSocket::startListen()
-
 
250
{
-
 
251
    create();
-
 
252
 
-
 
253
    myAddressStruct.sin_family = AF_INET;
-
 
254
    myAddressStruct.sin_addr.s_addr = INADDR_ANY;
-
 
255
    myAddressStruct.sin_port = htons(myPort);
-
 
256
 
-
 
257
    int status = ::bind(mySocket, (struct sockaddr *)&myAddressStruct, sizeof(myAddressStruct));
-
 
258
 
-
 
259
    if (status == -1)
-
 
260
    {
-
 
261
        close();
-
 
262
        switch (errno)
-
 
263
        {
-
 
264
            case EACCES:
-
 
265
            throw new SocketException("The address is protected, and the user is not the superuser.");
-
 
266
 
-
 
267
            case EADDRINUSE:
-
 
268
            throw new SocketException("The given address is already in use.");
-
 
269
 
-
 
270
            case EBADF:
-
 
271
            throw new SocketException("sockfd is not a valid descriptor.");
-
 
272
 
-
 
273
            case EINVAL:
-
 
274
            throw new SocketException("The socket is already bound to an address.");
-
 
275
 
-
 
276
            case ENOTSOCK:
-
 
277
            throw new SocketException("sockfd is a descriptor for a file, not a socket.");
-
 
278
 
-
 
279
            //case EACCES:
-
 
280
            //throw new SocketException("Search permission is denied on a component of the path prefix. (See also path_resolution(7).)");
-
 
281
 
-
 
282
            case EADDRNOTAVAIL:
-
 
283
            throw new SocketException("A nonexistent interface was requested or the requested address was not local.");
-
 
284
 
-
 
285
            case EFAULT:
-
 
286
            throw new SocketException("addr points outside the user's accessible address space.");
-
 
287
 
-
 
288
            //case EINVAL:
-
 
289
            //throw new SocketException("The addrlen is wrong, or the socket was not in the AF_UNIX family.");
-
 
290
 
-
 
291
            case ELOOP:
-
 
292
            throw new SocketException("Too many symbolic links were encountered in resolving addr.");
-
 
293
 
-
 
294
            case ENAMETOOLONG:
-
 
295
            throw new SocketException("addr is too long.");
-
 
296
 
-
 
297
            case ENOENT:
-
 
298
            throw new SocketException("The file does not exist.");
-
 
299
 
-
 
300
            case ENOMEM:
-
 
301
            throw new SocketException("Insufficient kernel memory was available.");
-
 
302
 
-
 
303
            case ENOTDIR:
-
 
304
            throw new SocketException("A component of the path prefix is not a directory.");
-
 
305
 
-
 
306
            case EROFS:
-
 
307
            throw new SocketException("The socket inode would reside on a read-only file system.");
-
 
308
 
-
 
309
            default:
-
 
310
            throw new SocketException("Unknow exception: " + itos(errno));
-
 
311
            break;
-
 
312
        }
-
 
313
    }
-
 
314
 
-
 
315
    status = ::listen(mySocket, MAXCONNECTIONS);
-
 
316
 
-
 
317
    if (status == -1)
-
 
318
    {
-
 
319
        close();
-
 
320
        switch (errno)
-
 
321
        {
-
 
322
            case EADDRINUSE:
-
 
323
            throw new SocketException("Another socket is already listening on the same port.");
-
 
324
 
-
 
325
            case EBADF:
-
 
326
            throw new SocketException("The argument sockfd is not a valid descriptor.");
-
 
327
 
-
 
328
            case ENOTSOCK:
-
 
329
            throw new SocketException("The argument sockfd is not a socket.");
-
 
330
 
-
 
331
            case EOPNOTSUPP:
-
 
332
            throw new SocketException("The socket is not of a type that supports the listen() operation.");
-
 
333
 
-
 
334
            default:
-
 
335
            throw new SocketException("Unknow exception: " + itos(errno));
-
 
336
            break;
280
        }
337
        }
-
 
338
    }
-
 
339
}
-
 
340
 
-
 
341
bool AsyncSocket::accept(AsyncSocket* newSocket)
-
 
342
{
-
 
343
    int addr_length = sizeof(myAddressStruct);
-
 
344
    int socket = ::accept(mySocket, (sockaddr*)&myAddressStruct, (socklen_t*)&addr_length);
-
 
345
 
-
 
346
    if (socket > 0)
-
 
347
    {
-
 
348
        newSocket->setSocket(socket);
-
 
349
        return true;
281
    }
350
    }
-
 
351
 
-
 
352
    return false;
282
}
353
}
283
 
354
 
284
void AsyncSocket::connect()
355
void AsyncSocket::connect()
285
{
356
{
286
    SyslogStream &slog = SyslogStream::getInstance();
357
    SyslogStream &slog = SyslogStream::getInstance();
287
 
358
 
288
    close();
359
    create();
289
 
-
 
290
    slog << "Trying to connect...\n";
-
 
291
 
-
 
292
    mySocket = ::socket(AF_INET, SOCK_STREAM, 0);
-
 
293
 
360
 
294
    int on = 1;
361
    int on = 1;
295
    int status = setsockopt(mySocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
-
 
296
    if (status == -1)
-
 
297
    {
-
 
298
        throw new SocketException("Connect:Reuseaddress: " + itos(errno));
-
 
299
    }
-
 
300
 
-
 
301
    ///FIXME: Verify that this works
362
    ///FIXME: Verify that this works
302
    status = setsockopt(mySocket, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(on));
363
    int status = setsockopt(mySocket, SOL_SOCKET, SO_KEEPALIVE, (const char*)&on, sizeof(on));
303
    if (status == -1)
364
    if (status == -1)
304
    {
365
    {
-
 
366
        close();
305
        throw new SocketException("Connect:Keepalive: " + itos(errno));
367
        throw new SocketException("Connect:Keepalive: " + itos(errno));
306
    }
368
    }
307
 
369
 
308
    ///FIXME: Verify that this works
370
    ///FIXME: Verify that this works
309
    status = setsockopt(mySocket, SOL_TCP, TCP_KEEPIDLE, (const char*)&on, sizeof(on));
371
    status = setsockopt(mySocket, SOL_TCP, TCP_KEEPIDLE, (const char*)&on, sizeof(on));
310
    if (status == -1)
372
    if (status == -1)
311
    {
373
    {
-
 
374
        close();
312
        throw new SocketException("Connect:Keepidle: " + itos(errno));
375
        throw new SocketException("Connect:Keepidle: " + itos(errno));
313
    }
376
    }
314
 
377
 
315
    memset(&myAddressStruct, 0, sizeof(myAddressStruct));
378
    memset(&myAddressStruct, 0, sizeof(myAddressStruct));
316
 
379
 
Line 318... Line 381...
318
    myAddressStruct.sin_port = htons(myPort);
381
    myAddressStruct.sin_port = htons(myPort);
319
 
382
 
320
    struct hostent *hptr = gethostbyname(myAddress.c_str());
383
    struct hostent *hptr = gethostbyname(myAddress.c_str());
321
    if (hptr == NULL)
384
    if (hptr == NULL)
322
    {
385
    {
-
 
386
        close();
323
        throw new SocketException("Connect: Could not resolv ip address");
387
        throw new SocketException("Connect: Could not resolv ip address");
324
    }
388
    }
325
 
389
 
326
    memcpy(&myAddressStruct.sin_addr, hptr->h_addr, hptr->h_length);
390
    memcpy(&myAddressStruct.sin_addr, hptr->h_addr, hptr->h_length);
327
    /*
391
    /*
Line 332... Line 396...
332
        if (errno == EAFNOSUPPORT)
396
        if (errno == EAFNOSUPPORT)
333
            throw new SocketException("Connect: EAFNOSUPPORT");
397
            throw new SocketException("Connect: EAFNOSUPPORT");
334
    }
398
    }
335
    */
399
    */
336
 
400
 
-
 
401
    slog << "Trying to connect...\n";
337
   
402
 
338
    status = ::connect(mySocket, (sockaddr*)&myAddressStruct, sizeof(myAddressStruct));
403
    status = ::connect(mySocket, (sockaddr*)&myAddressStruct, sizeof(myAddressStruct));
339
 
404
 
340
    if (status == -1)
405
    if (status == -1)
341
    {
406
    {
-
 
407
        close();
342
        switch (errno)
408
        switch (errno)
343
        {
409
        {
344
            case EACCES:
410
            case EACCES:
345
            throw new SocketException("For Unix domain sockets, which are identified by pathname: Write permission is denied on the socket file, or search per- mission is denied for one of the directories in the path prefix.  (See also path_resolution(7).)");
411
            throw new SocketException("For Unix domain sockets, which are identified by pathname: Write permission is denied on the socket file, or search per- mission is denied for one of the directories in the path prefix.  (See also path_resolution(7).)");
346
 
412
 
Line 400... Line 466...
400
 
466
 
401
    fcntl(mySocket, F_SETOWN, getpid());
467
    fcntl(mySocket, F_SETOWN, getpid());
402
    int flags = fcntl(mySocket, F_GETFL);
468
    int flags = fcntl(mySocket, F_GETFL);
403
 
469
 
404
    if (flags < 0)
470
    if (flags < 0)
-
 
471
    {
-
 
472
        close();
405
        throw new SocketException("Async socket fcntl failed");
473
        throw new SocketException("Async socket fcntl failed");
-
 
474
    }
406
 
475
 
407
    fcntl(mySocket, F_SETFL, flags | O_NONBLOCK | FASYNC);
476
    fcntl(mySocket, F_SETFL, flags | O_NONBLOCK | FASYNC);
408
 
477
 
409
    myForceReconnect = false;
478
    myForceReconnect = false;
410
 
479
 
411
    slog << "Connection established.\n";
480
    slog << "Connection established.\n";
412
}
481
}
413
 
482
 
414
void AsyncSocket::close()
483
void AsyncSocket::close()
415
{
484
{
416
    if (mySocket != -1)
485
    if (mySocket != -1)
417
    {
486
    {
418
        ::close(mySocket);
487
        ::close(mySocket);
419
        mySocket = -1;
488
        mySocket = -1;
420
        setEvent(ASYNCSOCKET_EVENT_CLOSED);
489
        setEvent(ASYNCSOCKET_EVENT_CLOSED);
421
    }
490
    }
422
}
491
}
-
 
492
 
-
 
493
bool AsyncSocket::isConnected()
-
 
494
{
-
 
495
    return mySocket != -1;
-
 
496
}
423
 
497
 
424
void AsyncSocket::setReconnectTimeout(unsigned int timeout)
498
void AsyncSocket::setReconnectTimeout(unsigned int timeout)
425
{
499
{
426
    myReconnectTimeout = timeout;
500
    myReconnectTimeout = timeout;
427
}
501
}
Line 434... Line 508...
434
int AsyncSocket::getEvent()
508
int AsyncSocket::getEvent()
435
{
509
{
436
    int event = myEvent;
510
    int event = myEvent;
437
    myEvent = ASYNCSOCKET_EVENT_NONE;
511
    myEvent = ASYNCSOCKET_EVENT_NONE;
438
    return event;
512
    return event;
439
}
513
}
440
 
514
 
441
void AsyncSocket::waitForEvent()
515
void AsyncSocket::waitForEvent()
442
{
516
{
443
    myEventSemaphore.wait();
517
    myEventSemaphore.wait();
444
}
518
}
Line 447... Line 521...
447
{
521
{
448
    myEventSemaphore.unlock();
522
    myEventSemaphore.unlock();
449
}
523
}
450
 
524
 
451
void AsyncSocket::setAddress(string address, int port)
525
void AsyncSocket::setAddress(string address, int port)
452
{
526
{
453
    myAddress = address;
527
    myAddress = address;
454
    myPort = port;
528
    myPort = port;
-
 
529
}
-
 
530
 
-
 
531
void AsyncSocket::setPort(int port)
-
 
532
{
-
 
533
    myPort = port;
-
 
534
}
-
 
535
 
-
 
536
void AsyncSocket::setSocket(int socket)
-
 
537
{
-
 
538
    mySocket = socket;
-
 
539
}
-
 
540
 
-
 
541
int AsyncSocket::getSocket()
-
 
542
{
-
 
543
    return mySocket;
455
}
544
}
456
 
545
 
457
bool AsyncSocket::availableData()
546
bool AsyncSocket::availableData()
458
{
547
{
459
    return (myInQueue.size() > 0);
548
    return (myInQueue.size() > 0);
460
}
549
}
461
 
550
 
462
string AsyncSocket::getData()
551
string AsyncSocket::getData()
463
{
552
{
464
    return myInQueue.pop();
553
    return myInQueue.pop();
465
}
554
}
466
 
555
 
467
bool AsyncSocket::sendData(string data)
556
bool AsyncSocket::sendData(string data)
468
{
557
{
469
    myOutQueue.push(data);
558
    myOutQueue.push(data);
470
    mySemaphore.broadcast();
559
    mySemaphore.broadcast();
471
    return true;
560
    return true;
-
 
561
}
-
 
562
 
-
 
563
void AsyncSocket::sendDataDirect(string data)
-
 
564
{
-
 
565
    SyslogStream &slog = SyslogStream::getInstance();
-
 
566
 
-
 
567
    //slog << "Sending: " << data << "\n";
-
 
568
 
-
 
569
    int status = ::send(mySocket, data.c_str(), data.size(), 0);
-
 
570
 
-
 
571
    //slog << "Status: " << status << "\n";
-
 
572
 
-
 
573
    if (status == -1)
-
 
574
    {
-
 
575
        switch (errno)
-
 
576
        {
-
 
577
            case EACCES:
-
 
578
            throw new SocketException("(For  Unix  domain sockets, which are identified by pathname) Write permission is denied on the destination socket file, or search permission is denied for one of the directories the path prefix.  (See path_resolution(7).)");
-
 
579
 
-
 
580
            case EAGAIN:
-
 
581
            //slog << "The socket is marked non-blocking and the requested operation would block.\n";
-
 
582
            break;
-
 
583
 
-
 
584
            case EBADF:
-
 
585
            throw new SocketException("An invalid descriptor was specified.");
-
 
586
 
-
 
587
            case ECONNRESET:
-
 
588
            throw new SocketException("Connection reset by peer.");
-
 
589
 
-
 
590
            case EDESTADDRREQ:
-
 
591
            throw new SocketException("The socket is not connection-mode, and no peer address is set.");
-
 
592
 
-
 
593
            case EFAULT:
-
 
594
            throw new SocketException("An invalid user space address was specified for an argument.");
-
 
595
 
-
 
596
            case EINTR:
-
 
597
            throw new SocketException("A signal occurred before any data was transmitted; see signal(7).");
-
 
598
 
-
 
599
            case EINVAL:
-
 
600
            throw new SocketException("1Invalid argument passed.");
-
 
601
 
-
 
602
            case EISCONN:
-
 
603
            throw new SocketException("The connection-mode socket was connected already but a recipient was specified. (Now either this error is returned, or the recipient specification is ignored.)");
-
 
604
 
-
 
605
            case EMSGSIZE:
-
 
606
            throw new SocketException("The socket type requires that message be sent atomically, and the size of the message to be sent made this impossible.");
-
 
607
 
-
 
608
            case ENOBUFS:
-
 
609
            throw new SocketException("The output queue for a network interface was full.  This generally indicates that the interface has stopped sending, but may be caused by transient congestion.  (Normally, this does not occur in Linux.  Packets are just silently dropped when a device queue overflows.)");
-
 
610
 
-
 
611
            case ENOMEM:
-
 
612
            throw new SocketException("No memory available.");
-
 
613
 
-
 
614
            case ENOTCONN:
-
 
615
            throw new SocketException("The socket is not connected, and no target has been given.");
-
 
616
 
-
 
617
            case ENOTSOCK:
-
 
618
            throw new SocketException("The argument s is not a socket.");
-
 
619
 
-
 
620
            case EOPNOTSUPP:
-
 
621
            throw new SocketException("Some bit in the flags argument is inappropriate for the socket type.");
-
 
622
 
-
 
623
            case EPIPE:
-
 
624
            throw new SocketException("The  local end has been shut down on a connection oriented socket. In this case the process will also receive a SIGPIPE unless MSG_NOSIGNAL is set.");
-
 
625
 
-
 
626
            default:
-
 
627
            slog << "Unknow exception: " + itos(errno) + "\n";
-
 
628
            break;
-
 
629
        }
-
 
630
    }
472
}
631
}
473
 
632
 
474
void AsyncSocket::setEvent(int event)
633
void AsyncSocket::setEvent(int event)
475
{
634
{
476
    myEventSemaphore.lock();
635
    myEventSemaphore.lock();
477
    myEvent = event;
636
    myEvent = event;
Line 486... Line 645...
486
}
645
}
487
 
646
 
488
void AsyncSocket::signalHandler(int signum)
647
void AsyncSocket::signalHandler(int signum)
489
{
648
{
490
    //FIXME: We must know which socket is ready to read by using select... 
649
    //FIXME: We must know which socket is ready to read by using select... 
491
    //cout << "DEBUG: signalHandler signum: " << signum << endl;
650
    cout << "DEBUG: signalHandler signum: " << signum << endl;
-
 
651
 
-
 
652
    map<string, AsyncSocket*>::iterator iter;
-
 
653
 
-
 
654
    mySocketsMutex.lock();
-
 
655
    for (iter = mySockets.begin(); iter != mySockets.end(); iter++)///FIXME: We should check order and length
-
 
656
    {
-
 
657
        cout << "DEBUG: signalHandler: calling: " << iter->second->getId() << endl;
492
    mySemaphore.broadcast();
658
        iter->second->mySemaphore.broadcast();
-
 
659
    }
-
 
660
    mySocketsMutex.unlock();
-
 
661
   
493
}
662
}