JackNetUnixSocket.cpp 14.8 KB
Newer Older
sletz's avatar
sletz committed
1
/*
sletz's avatar
sletz committed
2
Copyright (C) 2008-2011 Romain Moret at Grame
sletz's avatar
sletz committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "JackNetUnixSocket.h"
sletz's avatar
sletz committed
21
22
#include "JackError.h"

sletz's avatar
sletz committed
23
24
#include <unistd.h>
#include <fcntl.h>
sletz's avatar
sletz committed
25

Stephane Letz's avatar
Stephane Letz committed
26
27
using namespace std;

sletz's avatar
sletz committed
28
namespace Jack
29
30
{
    //utility *********************************************************************************************************
Stephane Letz's avatar
Stephane Letz committed
31
    int GetHostName(char * name, int size)
32
    {
Stephane Letz's avatar
Stephane Letz committed
33
34
35
        if (gethostname(name, size) == SOCKET_ERROR) {
            jack_error("Can't get 'hostname' : %s", strerror(NET_ERROR_CODE));
            strcpy(name, "default");
moret's avatar
moret committed
36
            return SOCKET_ERROR;
37
38
39
40
41
42
43
44
        }
        return 0;
    }

    //construct/destruct***********************************************************************************************
    JackNetUnixSocket::JackNetUnixSocket()
    {
        fSockfd = 0;
moret's avatar
moret committed
45
        fPort = 0;
sletz's avatar
sletz committed
46
        fTimeOut = 0;
47
        fSendAddr.sin_family = AF_INET;
Stephane Letz's avatar
Stephane Letz committed
48
49
        fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fSendAddr.sin_zero, 0, 8);
50
        fRecvAddr.sin_family = AF_INET;
Stephane Letz's avatar
Stephane Letz committed
51
52
        fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fRecvAddr.sin_zero, 0, 8);
53
54
    }

Stephane Letz's avatar
Stephane Letz committed
55
    JackNetUnixSocket::JackNetUnixSocket(const char* ip, int port)
56
57
58
    {
        fSockfd = 0;
        fPort = port;
sletz's avatar
sletz committed
59
        fTimeOut = 0;
60
        fSendAddr.sin_family = AF_INET;
Stephane Letz's avatar
Stephane Letz committed
61
62
63
        fSendAddr.sin_port = htons(port);
        inet_aton(ip, &fSendAddr.sin_addr);
        memset(&fSendAddr.sin_zero, 0, 8);
64
        fRecvAddr.sin_family = AF_INET;
Stephane Letz's avatar
Stephane Letz committed
65
66
67
        fRecvAddr.sin_port = htons(port);
        fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fRecvAddr.sin_zero, 0, 8);
68
69
    }

Stephane Letz's avatar
Stephane Letz committed
70
    JackNetUnixSocket::JackNetUnixSocket(const JackNetUnixSocket& socket)
71
    {
72
        fSockfd = 0;
sletz's avatar
sletz committed
73
        fTimeOut = 0;
74
75
76
77
78
        fPort = socket.fPort;
        fSendAddr = socket.fSendAddr;
        fRecvAddr = socket.fRecvAddr;
    }

79
80
81
82
83
    JackNetUnixSocket::~JackNetUnixSocket()
    {
        Close();
    }

Stephane Letz's avatar
Stephane Letz committed
84
    JackNetUnixSocket& JackNetUnixSocket::operator=(const JackNetUnixSocket& socket)
85
    {
Stephane Letz's avatar
Stephane Letz committed
86
        if (this != &socket) {
87
88
89
90
91
            fSockfd = 0;
            fPort = socket.fPort;
            fSendAddr = socket.fSendAddr;
            fRecvAddr = socket.fRecvAddr;
        }
92
        return *this;
93
94
    }

95
96
97
    //socket***********************************************************************************************************
    int JackNetUnixSocket::NewSocket()
    {
Stephane Letz's avatar
Stephane Letz committed
98
        if (fSockfd) {
99
100
101
            Close();
            Reset();
        }
Stephane Letz's avatar
Stephane Letz committed
102
        fSockfd = socket(AF_INET, SOCK_DGRAM, 0);
sletz's avatar
sletz committed
103

sletz's avatar
sletz committed
104
105
        /* Enable address reuse */
        int res, on = 1;
sletz's avatar
sletz committed
106
    #ifdef __APPLE__
107
        if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on))) < 0) {
sletz's avatar
sletz committed
108
109
110
    #else
        if ((res = setsockopt(fSockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) < 0) {
    #endif
sletz's avatar
sletz committed
111
112
            StrError(NET_ERROR_CODE);
        }
113
114
115
        return fSockfd;
    }

Stephane Letz's avatar
Stephane Letz committed
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
    bool JackNetUnixSocket::IsLocal(char* ip)
    {
        if (strcmp(ip, "127.0.0.1") == 0) {
            return true;
        }

        char host_name[32];
        gethostname(host_name, sizeof(host_name));

        struct hostent* host = gethostbyname(host_name);
        if (host) {
            for (int i = 0; host->h_addr_list[i] != 0; ++i) {
                struct in_addr addr;
                memcpy(&addr, host->h_addr_list[i], sizeof(struct in_addr));
                if (strcmp(inet_ntoa(addr), ip) == 0) {
                    return true;
                }
            }
            return false;
        } else {
            return false;
        }
    }

140
141
    int JackNetUnixSocket::Bind()
    {
Stephane Letz's avatar
Stephane Letz committed
142
        return bind(fSockfd, reinterpret_cast<socket_address_t*>(&fRecvAddr), sizeof(socket_address_t));
143
144
    }

Stephane Letz's avatar
Stephane Letz committed
145
    int JackNetUnixSocket::BindWith(const char* ip)
146
    {
Stephane Letz's avatar
Stephane Letz committed
147
        int addr_conv = inet_aton(ip, &fRecvAddr.sin_addr);
Stephane Letz's avatar
Stephane Letz committed
148
        if (addr_conv < 0) {
149
            return addr_conv;
Stephane Letz's avatar
Stephane Letz committed
150
        }
151
152
153
        return Bind();
    }

Stephane Letz's avatar
Stephane Letz committed
154
    int JackNetUnixSocket::BindWith(int port)
155
    {
Stephane Letz's avatar
Stephane Letz committed
156
        fRecvAddr.sin_port = htons(port);
157
158
159
160
161
        return Bind();
    }

    int JackNetUnixSocket::Connect()
    {
Stephane Letz's avatar
Stephane Letz committed
162
        return connect(fSockfd, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t));
163
164
    }

Stephane Letz's avatar
Stephane Letz committed
165
    int JackNetUnixSocket::ConnectTo(const char* ip)
166
    {
Stephane Letz's avatar
Stephane Letz committed
167
        int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
Stephane Letz's avatar
Stephane Letz committed
168
        if (addr_conv < 0) {
169
            return addr_conv;
Stephane Letz's avatar
Stephane Letz committed
170
        }
171
172
173
174
175
        return Connect();
    }

    void JackNetUnixSocket::Close()
    {
Stephane Letz's avatar
Stephane Letz committed
176
        if (fSockfd) {
Stephane Letz's avatar
Stephane Letz committed
177
            close(fSockfd);
Stephane Letz's avatar
Stephane Letz committed
178
        }
179
180
181
182
183
184
        fSockfd = 0;
    }

    void JackNetUnixSocket::Reset()
    {
        fSendAddr.sin_family = AF_INET;
Stephane Letz's avatar
Stephane Letz committed
185
186
187
        fSendAddr.sin_port = htons(fPort);
        fSendAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fSendAddr.sin_zero, 0, 8);
188
        fRecvAddr.sin_family = AF_INET;
Stephane Letz's avatar
Stephane Letz committed
189
190
191
        fRecvAddr.sin_port = htons(fPort);
        fRecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        memset(&fRecvAddr.sin_zero, 0, 8);
192
193
194
195
    }

    bool JackNetUnixSocket::IsSocket()
    {
Stephane Letz's avatar
Stephane Letz committed
196
        return(fSockfd) ? true : false;
197
198
199
    }

    //IP/PORT***********************************************************************************************************
Stephane Letz's avatar
Stephane Letz committed
200
    void JackNetUnixSocket::SetPort(int port)
201
202
    {
        fPort = port;
Stephane Letz's avatar
Stephane Letz committed
203
204
        fSendAddr.sin_port = htons(port);
        fRecvAddr.sin_port = htons(port);
205
206
207
208
209
210
211
212
    }

    int JackNetUnixSocket::GetPort()
    {
        return fPort;
    }

    //address***********************************************************************************************************
Stephane Letz's avatar
Stephane Letz committed
213
    int JackNetUnixSocket::SetAddress(const char* ip, int port)
214
    {
Stephane Letz's avatar
Stephane Letz committed
215
        int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
Stephane Letz's avatar
Stephane Letz committed
216
        if (addr_conv < 0) {
217
            return addr_conv;
Stephane Letz's avatar
Stephane Letz committed
218
        }
Stephane Letz's avatar
Stephane Letz committed
219
        fSendAddr.sin_port = htons(port);
220
221
222
223
224
        return 0;
    }

    char* JackNetUnixSocket::GetSendIP()
    {
Stephane Letz's avatar
Stephane Letz committed
225
        return inet_ntoa(fSendAddr.sin_addr);
226
227
228
229
    }

    char* JackNetUnixSocket::GetRecvIP()
    {
Stephane Letz's avatar
Stephane Letz committed
230
        return inet_ntoa(fRecvAddr.sin_addr);
231
232
233
    }

    //utility************************************************************************************************************
Stephane Letz's avatar
Stephane Letz committed
234
    int JackNetUnixSocket::GetName(char* name)
235
    {
Stephane Letz's avatar
Stephane Letz committed
236
        return gethostname(name, 255);
237
238
    }

Stephane Letz's avatar
Stephane Letz committed
239
    int JackNetUnixSocket::JoinMCastGroup(const char* ip)
240
241
    {
        struct ip_mreq multicast_req;
Stephane Letz's avatar
Stephane Letz committed
242
243
244
        inet_aton(ip, &multicast_req.imr_multiaddr);
        multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);
        return SetOption(IPPROTO_IP, IP_ADD_MEMBERSHIP, &multicast_req, sizeof(multicast_req));
245
246
247
    }

    //options************************************************************************************************************
Stephane Letz's avatar
Stephane Letz committed
248
    int JackNetUnixSocket::SetOption(int level, int optname, const void* optval, socklen_t optlen)
249
    {
Stephane Letz's avatar
Stephane Letz committed
250
        return setsockopt(fSockfd, level, optname, optval, optlen);
251
252
    }

Stephane Letz's avatar
Stephane Letz committed
253
    int JackNetUnixSocket::GetOption(int level, int optname, void* optval, socklen_t* optlen)
254
    {
Stephane Letz's avatar
Stephane Letz committed
255
        return getsockopt(fSockfd, level, optname, optval, optlen);
256
257
    }

moret's avatar
moret committed
258
    //timeout************************************************************************************************************
sletz's avatar
sletz committed
259
260

#if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
261
    int JackNetUnixSocket::SetTimeOut(int us)
sletz's avatar
sletz committed
262
263
264
    {
        int	flags;
        fTimeOut = us;
sletz's avatar
sletz committed
265

sletz's avatar
sletz committed
266
267
268
269
        if ((flags = fcntl(fSockfd, F_GETFL, 0)) < 0) {
		    jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_GETFL");
		    return -1;
	    }
sletz's avatar
sletz committed
270

sletz's avatar
sletz committed
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
	    flags |= O_NONBLOCK;
	    if (fcntl(fSockfd, F_SETFL, flags) < 0) {
		    jack_error("JackNetUnixSocket::SetTimeOut error in fcntl F_SETFL");
		    return 1;
	    }

        return 0;
    }

    int JackNetUnixSocket::WaitRead()
    {
        if (fTimeOut > 0) {

            struct timeval tv;
	        fd_set fdset;
            ssize_t	res;
sletz's avatar
sletz committed
287

sletz's avatar
sletz committed
288
289
            tv.tv_sec = fTimeOut / 1000000;
	        tv.tv_usec = fTimeOut % 1000000;
sletz's avatar
sletz committed
290

sletz's avatar
sletz committed
291
292
	        FD_ZERO(&fdset);
	        FD_SET(fSockfd, &fdset);
sletz's avatar
sletz committed
293

sletz's avatar
sletz committed
294
295
	        do {
		        res = select(fSockfd + 1, &fdset, NULL, NULL, &tv);
Stephane Letz's avatar
Stephane Letz committed
296
	        } while (res < 0 && errno == EINTR);
sletz's avatar
sletz committed
297

sletz's avatar
sletz committed
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
	        if (res < 0) {
 		        return res;
            } else if (res == 0) {
                errno = ETIMEDOUT;
		        return -1;
	        }
        }

        return 0;
    }

    int JackNetUnixSocket::WaitWrite()
    {
        if (fTimeOut > 0) {

            struct timeval tv;
	        fd_set fdset;
            ssize_t	res;
sletz's avatar
sletz committed
316

sletz's avatar
sletz committed
317
            tv.tv_sec = fTimeOut / 1000000;
sletz's avatar
sletz committed
318
319
            tv.tv_usec = fTimeOut % 1000000;

sletz's avatar
sletz committed
320
321
	        FD_ZERO(&fdset);
	        FD_SET(fSockfd, &fdset);
sletz's avatar
sletz committed
322

sletz's avatar
sletz committed
323
324
	        do {
		        res = select(fSockfd + 1, NULL, &fdset, NULL, &tv);
Stephane Letz's avatar
Stephane Letz committed
325
	        } while (res < 0 && errno == EINTR);
sletz's avatar
sletz committed
326

sletz's avatar
sletz committed
327
328
329
330
331
332
333
334
335
336
337
338
	        if (res < 0) {
		        return res;
            } else if (res == 0) {
                errno = ETIMEDOUT;
		        return -1;
	        }
        }

        return 0;
    }

#else
Stephane Letz's avatar
Stephane Letz committed
339
    int JackNetUnixSocket::SetTimeOut(int us)
340
    {
Stephane Letz's avatar
Stephane Letz committed
341
        jack_log("JackNetUnixSocket::SetTimeout %d usecs", us);
342
        struct timeval timeout;
moret's avatar
moret committed
343

344
        //less than 1 sec
Stephane Letz's avatar
Stephane Letz committed
345
        if (us < 1000000) {
346
            timeout.tv_sec = 0;
moret's avatar
moret committed
347
            timeout.tv_usec = us;
Stephane Letz's avatar
Stephane Letz committed
348
        } else {
349
        //more than 1 sec
350
351
352
353
            float sec = float(us) / 1000000.f;
            timeout.tv_sec = (int)sec;
            float usec = (sec - float(timeout.tv_sec)) * 1000000;
            timeout.tv_usec =(int)usec;
354
        }
Stephane Letz's avatar
Stephane Letz committed
355
        return SetOption(SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
356
    }
sletz's avatar
sletz committed
357
#endif
358
359
360
361
362

    //local loop**********************************************************************************************************
    int JackNetUnixSocket::SetLocalLoop()
    {
        char disable = 0;
Stephane Letz's avatar
Stephane Letz committed
363
        return SetOption(IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof(disable));
364
365
366
    }

    //network operations**************************************************************************************************
Stephane Letz's avatar
Stephane Letz committed
367
    int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags)
368
    {
sletz's avatar
sletz committed
369
    #if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
370
        if (WaitWrite() < 0) {
sletz's avatar
sletz committed
371
            return -1;
Stephane Letz's avatar
Stephane Letz committed
372
        }
sletz's avatar
sletz committed
373
    #endif
374
375
376
377
378
        int res;
        if ((res = sendto(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), sizeof(socket_address_t))) < 0) {
            jack_error("SendTo fd = %ld err = %s", fSockfd, strerror(errno));
        }
        return res;
379
380
    }

Stephane Letz's avatar
Stephane Letz committed
381
    int JackNetUnixSocket::SendTo(const void* buffer, size_t nbytes, int flags, const char* ip)
382
    {
Stephane Letz's avatar
Stephane Letz committed
383
        int addr_conv = inet_aton(ip, &fSendAddr.sin_addr);
384
        if (addr_conv < 1) {
385
            return addr_conv;
386
        }
sletz's avatar
sletz committed
387
    #if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
388
        if (WaitWrite() < 0) {
sletz's avatar
sletz committed
389
            return -1;
Stephane Letz's avatar
Stephane Letz committed
390
        }
sletz's avatar
sletz committed
391
    #endif
Stephane Letz's avatar
Stephane Letz committed
392
        return SendTo(buffer, nbytes, flags);
393
394
    }

Stephane Letz's avatar
Stephane Letz committed
395
    int JackNetUnixSocket::Send(const void* buffer, size_t nbytes, int flags)
396
    {
sletz's avatar
sletz committed
397
    #if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
398
        if (WaitWrite() < 0) {
sletz's avatar
sletz committed
399
            return -1;
Stephane Letz's avatar
Stephane Letz committed
400
        }
sletz's avatar
sletz committed
401
    #endif
402
403
404
405
406
        int res;
        if ((res = send(fSockfd, buffer, nbytes, flags)) < 0) {
            jack_error("Send fd = %ld err = %s", fSockfd, strerror(errno));
        }
        return res;
407
408
    }

Stephane Letz's avatar
Stephane Letz committed
409
    int JackNetUnixSocket::RecvFrom(void* buffer, size_t nbytes, int flags)
410
    {
Stephane Letz's avatar
Stephane Letz committed
411
        socklen_t addr_len = sizeof(socket_address_t);
sletz's avatar
sletz committed
412
    #if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
413
        if (WaitRead() < 0) {
sletz's avatar
sletz committed
414
            return -1;
Stephane Letz's avatar
Stephane Letz committed
415
        }
sletz's avatar
sletz committed
416
    #endif
417
418
419
420
421
        int res;
        if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fRecvAddr), &addr_len)) < 0) {
            jack_error("RecvFrom fd = %ld err = %s", fSockfd, strerror(errno));
        }
        return res;        
422
423
    }

Stephane Letz's avatar
Stephane Letz committed
424
    int JackNetUnixSocket::Recv(void* buffer, size_t nbytes, int flags)
425
    {
sletz's avatar
sletz committed
426
    #if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
427
        if (WaitRead() < 0) {
sletz's avatar
sletz committed
428
            return -1;
Stephane Letz's avatar
Stephane Letz committed
429
        }
sletz's avatar
sletz committed
430
    #endif
431
432
433
434
435
        int res;
        if ((res = recv(fSockfd, buffer, nbytes, flags)) < 0) {
            jack_error("Recv fd = %ld err = %s", fSockfd, strerror(errno));
        }
        return res;        
436
437
    }

Stephane Letz's avatar
Stephane Letz committed
438
    int JackNetUnixSocket::CatchHost(void* buffer, size_t nbytes, int flags)
439
    {
Stephane Letz's avatar
Stephane Letz committed
440
        socklen_t addr_len = sizeof(socket_address_t);
sletz's avatar
sletz committed
441
    #if defined(__sun__) || defined(sun)
Stephane Letz's avatar
Stephane Letz committed
442
        if (WaitRead() < 0) {
sletz's avatar
sletz committed
443
            return -1;
Stephane Letz's avatar
Stephane Letz committed
444
        }
sletz's avatar
sletz committed
445
    #endif
446
447
448
449
450
        int res;
        if ((res = recvfrom(fSockfd, buffer, nbytes, flags, reinterpret_cast<socket_address_t*>(&fSendAddr), &addr_len)) < 0) {
            jack_error("CatchHost fd = %ld err = %s", fSockfd, strerror(errno));
        }
        return res;                
451
452
453
454
    }

    net_error_t JackNetUnixSocket::GetError()
    {
Stephane Letz's avatar
Stephane Letz committed
455
        switch (errno) {
moret's avatar
moret committed
456
            case EAGAIN:
sletz's avatar
sletz committed
457
            case ETIMEDOUT:
moret's avatar
moret committed
458
                return NET_NO_DATA;
sletz's avatar
sletz committed
459

moret's avatar
moret committed
460
461
462
            case ECONNABORTED:
            case ECONNREFUSED:
            case ECONNRESET:
sletz's avatar
sletz committed
463
            case EINVAL:
moret's avatar
moret committed
464
465
            case EHOSTDOWN:
            case EHOSTUNREACH:
sletz's avatar
sletz committed
466
467
            case ENETDOWN:
            case ENETUNREACH:
moret's avatar
moret committed
468
                return NET_CONN_ERROR;
sletz's avatar
sletz committed
469

moret's avatar
moret committed
470
            default:
sletz's avatar
sletz committed
471
472
                //return NET_OP_ERROR;
                return NET_CONN_ERROR;
473
474
        }
    }
Stephane Letz's avatar
Stephane Letz committed
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
        
    void JackNetUnixSocket::PrintError()
    {
        switch (errno) {
                
            case EAGAIN:
                jack_error("JackNetUnixSocket : EAGAIN");
                break;
            case ETIMEDOUT:
                jack_error("JackNetUnixSocket : ETIMEDOUT");
                break;
            case ECONNABORTED:
                jack_error("JackNetUnixSocket : ECONNABORTED");
                break;
            case ECONNREFUSED:
                jack_error("JackNetUnixSocket : ECONNREFUSED");
                break;
            case ECONNRESET:
                jack_error("JackNetUnixSocket : ECONNRESET");
                break;
            case EINVAL:
                jack_error("JackNetUnixSocket : EINVAL");
                break;
            case EHOSTDOWN:
                jack_error("JackNetUnixSocket : EHOSTDOWN");
                break;
            case EHOSTUNREACH:
                jack_error("JackNetUnixSocket : EHOSTUNREACH");
                break;
            case ENETDOWN:
                jack_error("JackNetUnixSocket : ENETDOWN");
                break;
            case ENETUNREACH:
                jack_error("JackNetUnixSocket : ENETUNREACH");
                break;
            default:
                jack_error("JackNetUnixSocket : %d", errno);
                break;
        }
    }    
sletz's avatar
sletz committed
515
}