Subversion Repositories HomeAutomation

Rev

Rev 984 | Show entire file | Regard 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 45... Line 49...
45
        // If we have choosen to not use automatic reconnect do not start reconnect loop
49
        // If we have choosen to not use automatic reconnect do not start reconnect loop
46
        if (myReconnectTimeout == 0)
50
        if (myReconnectTimeout == 0)
47
        {
51
        {
48
            // Connect to somewhere
52
            // Connect to somewhere
49
            connect();
53
            connect();
50
        }
54
        }
51
        else
55
        else
52
        {
56
        {
53
            // Start the reconnect loop
57
            // Start the reconnect loop
54
            reconnectLoop();
58
            reconnectLoop();
55
        }
59
        }
56
    }
60
    }
57
 
61
 
58
    bool loop = true;
62
    bool loop = true;
59
    try
63
    try
60
    {
64
    {
61
        while (loop)
65
        while (loop)
62
        {
66
        {
Line 73... Line 77...
73
    }
77
    }
74
    catch (SocketException *e)
78
    catch (SocketException *e)
75
    {
79
    {
76
        // Something bad happend and we can not continue
80
        // Something bad happend and we can not continue
77
        eventAdd(SocketEvent::TYPE_CONNECTION_DIED, e->getDescription());
81
        eventAdd(SocketEvent::TYPE_CONNECTION_DIED, e->getDescription());
78
    }
82
    }
79
 
83
 
80
    // Clean up socket if we would want to restart
84
    // Clean up socket if we would want to restart
81
    silentClose();
85
    silentClose();
82
}
86
}
83
 
87
 
Line 107... Line 111...
107
            case EINTR:
111
            case EINTR:
108
            throw new SocketException("The receive was interrupted by delivery of a signal before any data were available; see signal(7).");
112
            throw new SocketException("The receive was interrupted by delivery of a signal before any data were available; see signal(7).");
109
 
113
 
110
            case EINVAL:
114
            case EINVAL:
111
            throw new SocketException("Invalid argument passed.");
115
            throw new SocketException("Invalid argument passed.");
112
 
116
 
113
            case ENOMEM:
117
            case ENOMEM:
114
            throw new SocketException("Could not allocate memory for recvmsg().");
118
            throw new SocketException("Could not allocate memory for recvmsg().");
115
 
119
 
116
            case ENOTCONN:
120
            case ENOTCONN:
117
            throw new SocketException("The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).");
121
            throw new SocketException("The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).");
Line 128... Line 132...
128
                reconnectLoop();
132
                reconnectLoop();
129
            }
133
            }
130
            else
134
            else
131
            {
135
            {
132
                // Otherwise we would like to end the main loop
136
                // Otherwise we would like to end the main loop
133
                return false;
137
                return false;
134
            }
138
            }
135
            break;
139
            break;
136
 
140
 
137
            default:
141
            default:
138
            throw new SocketException("Unknow exception: " + itos(errno));
142
            throw new SocketException("Unknow exception: " + itos(errno));
139
            break;
143
            break;
140
        }
144
        }
141
    }
145
    }
142
    else if (status == 0)
146
    else if (status == 0)
143
    {
147
    {
144
        // Remote host have done a normal shutdown
148
        // Remote host have done a normal shutdown
145
        eventAdd(SocketEvent::TYPE_CONNECTION_CLOSED);
149
        eventAdd(SocketEvent::TYPE_CONNECTION_CLOSED);
146
 
150
 
147
        if (myReconnectTimeout > 0)
151
        if (myReconnectTimeout > 0)
148
        {
152
        {
149
            reconnectLoop();
153
            reconnectLoop();
150
        }
154
        }
151
        else
155
        else
152
        {
156
        {
153
            return false;
157
            return false;
154
        }
158
        }
155
    }
159
    }
156
    else if (status > 0)
160
    else if (status > 0)
157
    {
161
    {
158
        // We have received data
162
        // We have received data
159
        eventAdd(SocketEvent::TYPE_DATA, buffer);
163
        eventAdd(SocketEvent::TYPE_DATA, buffer);
160
    }
164
    }
Line 178... Line 182...
178
}
182
}
179
 
183
 
180
void AsyncSocket::reconnectLoop()
184
void AsyncSocket::reconnectLoop()
181
{
185
{
182
    while (true)
186
    while (true)
183
    {
187
    {
184
        try
188
        try
185
        {
189
        {
186
            connect();
190
            connect();
187
            return;
191
            return;
188
        }
192
        }
189
        catch (SocketException *e)
193
        catch (SocketException *e)
190
        {
194
        {
191
            eventAdd(SocketEvent::TYPE_CONNECTION_FAILED, e->getDescription());
195
            eventAdd(SocketEvent::TYPE_CONNECTION_FAILED, e->getDescription());
192
            eventAdd(SocketEvent::TYPE_WAITING_RECONNECT);
196
            eventAdd(SocketEvent::TYPE_WAITING_RECONNECT);
193
            sleep(myReconnectTimeout);
197
            sleep(myReconnectTimeout);
194
        }
198
        }
195
    }
199
    }
Line 297... Line 301...
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
{
307
    int addr_length = sizeof(myAddressStruct);
311
    int addr_length = sizeof(myAddressStruct);
308
    int socket = ::accept(mySocket, (sockaddr*)&myAddressStruct, (socklen_t*)&addr_length);
312
    int socket = ::accept(mySocket, (sockaddr*)&myAddressStruct, (socklen_t*)&addr_length);
Line 312... Line 316...
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
 
Line 333... Line 337...
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)
342
    {
346
    {
343
        silentClose();
347
        silentClose();
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.");
363
 
367
 
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
}