ConnectionFileDescriptor.cpp revision 42bee0587010de0f101f0cfd74f9dc9e72cb1588
1//===-- ConnectionFileDescriptor.cpp ----------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/ConnectionFileDescriptor.h"
11
12// C Includes
13#include <arpa/inet.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <netdb.h>
17#include <netinet/in.h>
18#include <netinet/tcp.h>
19#include <sys/socket.h>
20#include <sys/types.h>
21#include <sys/un.h>
22#include <string.h>
23#include <stdlib.h>
24
25// C++ Includes
26// Other libraries and framework includes
27// Project includes
28#include "lldb/lldb-private-log.h"
29#include "lldb/Interpreter/Args.h"
30#include "lldb/Core/Communication.h"
31#include "lldb/Core/Log.h"
32#include "lldb/Core/RegularExpression.h"
33#include "lldb/Core/Timer.h"
34
35using namespace lldb;
36using namespace lldb_private;
37
38ConnectionFileDescriptor::ConnectionFileDescriptor () :
39    Connection(),
40    m_fd (-1),
41    m_is_socket (false),
42    m_should_close_fd (false)
43{
44    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT,
45                                 "%p ConnectionFileDescriptor::ConnectionFileDescriptor ()",
46                                 this);
47}
48
49ConnectionFileDescriptor::ConnectionFileDescriptor (int fd, bool owns_fd) :
50    Connection(),
51    m_fd (fd),
52    m_is_socket (false),
53    m_should_close_fd (owns_fd)
54{
55    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT,
56                                 "%p ConnectionFileDescriptor::ConnectionFileDescriptor (fd = %i, owns_fd = %i)",
57                                 this, fd, owns_fd);
58}
59
60
61ConnectionFileDescriptor::~ConnectionFileDescriptor ()
62{
63    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION |  LIBLLDB_LOG_OBJECT,
64                                 "%p ConnectionFileDescriptor::~ConnectionFileDescriptor ()",
65                                 this);
66    Disconnect (NULL);
67}
68
69bool
70ConnectionFileDescriptor::IsConnected () const
71{
72    return m_fd >= 0;
73}
74
75ConnectionStatus
76ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr)
77{
78    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
79                                 "%p ConnectionFileDescriptor::Connect (url = '%s')",
80                                 this, s);
81
82    if (s && s[0])
83    {
84        char *end = NULL;
85        if (strstr(s, "listen://"))
86        {
87            // listen://HOST:PORT
88            unsigned long listen_port = ::strtoul(s + strlen("listen://"), &end, 0);
89            return SocketListen (listen_port, error_ptr);
90        }
91        else if (strstr(s, "unix-accept://"))
92        {
93            // unix://SOCKNAME
94            return NamedSocketAccept (s + strlen("unix-accept://"), error_ptr);
95        }
96        else if (strstr(s, "connect://"))
97        {
98            return SocketConnect (s + strlen("connect://"), error_ptr);
99        }
100        else if (strstr(s, "file://"))
101        {
102            // file:///PATH
103            const char *path = s + strlen("file://");
104            m_fd = ::open (path, O_RDWR);
105            if (m_fd == -1)
106            {
107                if (error_ptr)
108                    error_ptr->SetErrorToErrno();
109                return eConnectionStatusError;
110            }
111
112            int flags = ::fcntl (m_fd, F_GETFL, 0);
113            if (flags >= 0)
114            {
115                if ((flags & O_NONBLOCK) == 0)
116                {
117                    flags |= O_NONBLOCK;
118                    ::fcntl (m_fd, F_SETFL, flags);
119                }
120            }
121            m_should_close_fd = true;
122            return eConnectionStatusSuccess;
123        }
124        if (error_ptr)
125            error_ptr->SetErrorStringWithFormat ("Unsupported connection URL: '%s'.\n", s);
126        return eConnectionStatusError;
127    }
128    if (error_ptr)
129        error_ptr->SetErrorString("NULL connection URL.");
130    return eConnectionStatusError;
131}
132
133ConnectionStatus
134ConnectionFileDescriptor::Disconnect (Error *error_ptr)
135{
136    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
137                                 "%p ConnectionFileDescriptor::Disconnect ()",
138                                 this);
139    if (m_should_close_fd == false)
140    {
141        m_fd = -1;
142        return eConnectionStatusSuccess;
143    }
144    return Close (m_fd, error_ptr);
145}
146
147size_t
148ConnectionFileDescriptor::Read (void *dst, size_t dst_len, ConnectionStatus &status, Error *error_ptr)
149{
150    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
151    if (log)
152        log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu)...",
153                     this, m_fd, dst, dst_len);
154
155    Error error;
156    ssize_t bytes_read = ::read (m_fd, dst, dst_len);
157    if (bytes_read == 0)
158    {
159        error.SetErrorStringWithFormat("End-of-file.\n");
160        status = eConnectionStatusLostConnection;
161    }
162    else if (bytes_read < 0)
163    {
164        error.SetErrorToErrno();
165    }
166    else
167    {
168        error.Clear();
169    }
170
171    if (log)
172        log->Printf ("%p ConnectionFileDescriptor::Read () ::read (fd = %i, dst = %p, dst_len = %zu) => %zi, error = %s",
173                     this,
174                     m_fd,
175                     dst,
176                     dst_len,
177                     bytes_read,
178                     error.AsCString());
179
180    if (error_ptr)
181        *error_ptr = error;
182
183    if (error.Fail())
184    {
185        uint32_t error_value = error.GetError();
186        switch (error_value)
187        {
188        case EAGAIN:    // The file was marked for non-blocking I/O, and no data were ready to be read.
189            status = eConnectionStatusSuccess;
190            return 0;
191
192        case EBADF:     // fildes is not a valid file or socket descriptor open for reading.
193        case EFAULT:    // Buf points outside the allocated address space.
194        case EINTR:     // A read from a slow device was interrupted before any data arrived by the delivery of a signal.
195        case EINVAL:    // The pointer associated with fildes was negative.
196        case EIO:       // An I/O error occurred while reading from the file system.
197                        // The process group is orphaned.
198                        // The file is a regular file, nbyte is greater than 0,
199                        // the starting position is before the end-of-file, and
200                        // the starting position is greater than or equal to the
201                        // offset maximum established for the open file
202                        // descriptor associated with fildes.
203        case EISDIR:    // An attempt is made to read a directory.
204        case ENOBUFS:   // An attempt to allocate a memory buffer fails.
205        case ENOMEM:    // Insufficient memory is available.
206            status = eConnectionStatusError;
207            break;  // Break to close....
208
209        case ENXIO:     // An action is requested of a device that does not exist..
210                        // A requested action cannot be performed by the device.
211        case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket.
212        case ENOTCONN:  // A read is attempted on an unconnected socket.
213            status = eConnectionStatusLostConnection;
214            break;  // Break to close....
215
216        case ETIMEDOUT: // A transmission timeout occurs during a read attempt on a socket.
217            status = eConnectionStatusTimedOut;
218            return 0;
219        }
220
221//      if (log)
222//          error->Log(log, "::read ( %i, %p, %zu ) => %i", m_fd, dst, dst_len, bytesread);
223        Close (m_fd, NULL);
224        return 0;
225    }
226    return bytes_read;
227}
228
229size_t
230ConnectionFileDescriptor::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
231{
232    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
233    if (log)
234        log->Printf ("%p ConnectionFileDescriptor::Write (src = %p, src_len = %zu)", this, src, src_len);
235
236    if (!IsConnected ())
237    {
238        if (error_ptr)
239            error_ptr->SetErrorString("Not connected.");
240        status = eConnectionStatusNoConnection;
241        return 0;
242    }
243
244
245    Error error;
246
247    ssize_t bytes_sent = 0;
248
249    if (m_is_socket)
250        bytes_sent = ::send (m_fd, src, src_len, 0);
251    else
252        bytes_sent = ::write (m_fd, src, src_len);
253
254    if (bytes_sent < 0)
255        error.SetErrorToErrno ();
256    else
257        error.Clear ();
258
259    if (log)
260    {
261        if (m_is_socket)
262            log->Printf ("%p ConnectionFileDescriptor::Write()  ::send (socket = %i, src = %p, src_len = %zu, flags = 0) => %zi (error = %s)",
263                         this, m_fd, src, src_len, bytes_sent, error.AsCString());
264        else
265            log->Printf ("%p ConnectionFileDescriptor::Write()  ::write (fd = %i, src = %p, src_len = %zu) => %zi (error = %s)",
266                         this, m_fd, src, src_len, bytes_sent, error.AsCString());
267    }
268
269    if (error_ptr)
270        *error_ptr = error;
271
272    if (error.Fail())
273    {
274        switch (error.GetError())
275        {
276        case EAGAIN:
277        case EINTR:
278            status = eConnectionStatusSuccess;
279            return 0;
280
281        case ECONNRESET:// The connection is closed by the peer during a read attempt on a socket.
282        case ENOTCONN:  // A read is attempted on an unconnected socket.
283            status = eConnectionStatusLostConnection;
284            break;  // Break to close....
285
286        default:
287            status = eConnectionStatusError;
288            break;  // Break to close....
289        }
290
291        Close (m_fd, NULL);
292        return 0;
293    }
294
295    status = eConnectionStatusSuccess;
296    return bytes_sent;
297}
298
299ConnectionStatus
300ConnectionFileDescriptor::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
301{
302    LogSP log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION));
303    if (log)
304        log->Printf("%p ConnectionFileDescriptor::BytesAvailable (timeout_usec = %u)", this, timeout_usec);
305    struct timeval *tv_ptr;
306    struct timeval tv;
307    if (timeout_usec == UINT32_MAX)
308    {
309        // Infinite wait...
310        tv_ptr = NULL;
311    }
312    else
313    {
314        TimeValue time_value;
315        time_value.OffsetWithMicroSeconds (timeout_usec);
316        tv = time_value.GetAsTimeVal();
317        tv_ptr = &tv;
318    }
319
320    while (IsConnected())
321    {
322        fd_set read_fds;
323        FD_ZERO (&read_fds);
324        FD_SET (m_fd, &read_fds);
325        int nfds = m_fd + 1;
326
327        Error error;
328
329
330        log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
331        if (log)
332            log->Printf("%p ConnectionFileDescriptor::Write()  ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p)...",
333                        this, nfds, m_fd, tv_ptr);
334
335        const int num_set_fds = ::select (nfds, &read_fds, NULL, NULL, tv_ptr);
336        if (num_set_fds < 0)
337            error.SetErrorToErrno();
338        else
339            error.Clear();
340
341        log = lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION);
342        if (log)
343            log->Printf("%p ConnectionFileDescriptor::Write()  ::select (nfds = %i, fd = %i, NULL, NULL, timeout = %p) => %d, error = %s",
344                        this, nfds, m_fd, tv_ptr, num_set_fds, error.AsCString());
345
346        if (error_ptr)
347            *error_ptr = error;
348
349        if (error.Fail())
350        {
351            switch (error.GetError())
352            {
353            case EBADF:     // One of the descriptor sets specified an invalid descriptor.
354            case EINVAL:    // The specified time limit is invalid. One of its components is negative or too large.
355            default:        // Other unknown error
356                return eConnectionStatusError;
357
358            case EAGAIN:    // The kernel was (perhaps temporarily) unable to
359                            // allocate the requested number of file descriptors,
360                            // or we have non-blocking IO
361            case EINTR:     // A signal was delivered before the time limit
362                            // expired and before any of the selected events
363                            // occurred.
364                break;      // Lets keep reading to until we timeout
365            }
366        }
367        else if (num_set_fds == 0)
368        {
369            return eConnectionStatusTimedOut;
370        }
371        else if (num_set_fds > 0)
372        {
373            return eConnectionStatusSuccess;
374        }
375    }
376
377    if (error_ptr)
378        error_ptr->SetErrorString("Not connected.");
379    return eConnectionStatusLostConnection;
380}
381
382ConnectionStatus
383ConnectionFileDescriptor::Close (int& fd, Error *error_ptr)
384{
385    if (error_ptr)
386        error_ptr->Clear();
387    bool success = true;
388    if (fd >= 0)
389    {
390        lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
391                                             "%p ConnectionFileDescriptor::Close (fd = %i)",
392                                             this,
393                                             fd);
394
395        success = ::close (fd) == 0;
396        if (!success && error_ptr)
397        {
398            // Only set the error if we have been asked to since something else
399            // might have caused us to try and shut down the connection and may
400            // have already set the error.
401            error_ptr->SetErrorToErrno();
402        }
403        fd = -1;
404    }
405    m_is_socket = false;
406    if (success)
407        return eConnectionStatusSuccess;
408    else
409        return eConnectionStatusError;
410}
411
412ConnectionStatus
413ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *error_ptr)
414{
415    ConnectionStatus result = eConnectionStatusError;
416    struct sockaddr_un saddr_un;
417
418    m_is_socket = true;
419
420    int listen_socket = ::socket (AF_UNIX, SOCK_STREAM, 0);
421    if (listen_socket == -1)
422    {
423        if (error_ptr)
424            error_ptr->SetErrorToErrno();
425        return eConnectionStatusError;
426    }
427
428    saddr_un.sun_family = AF_UNIX;
429    ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
430    saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
431    saddr_un.sun_len = SUN_LEN (&saddr_un);
432
433    if (::bind (listen_socket, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) == 0)
434    {
435        if (::listen (listen_socket, 5) == 0)
436        {
437            m_fd = ::accept (listen_socket, NULL, 0);
438            if (m_fd > 0)
439            {
440                m_should_close_fd = true;
441
442                if (error_ptr)
443                    error_ptr->Clear();
444                result = eConnectionStatusSuccess;
445            }
446        }
447    }
448
449    if (result != eConnectionStatusSuccess)
450    {
451        if (error_ptr)
452            error_ptr->SetErrorToErrno();
453    }
454    // We are done with the listen port
455    Close (listen_socket, NULL);
456    return result;
457}
458
459ConnectionStatus
460ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr)
461{
462    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
463                                 "%p ConnectionFileDescriptor::SocketListen (port = %i)",
464                                 this, listen_port_num);
465
466    Close (m_fd, NULL);
467    m_is_socket = true;
468    int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
469    if (listen_port == -1)
470    {
471        if (error_ptr)
472            error_ptr->SetErrorToErrno();
473        return eConnectionStatusError;
474    }
475
476    // enable local address reuse
477    SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1);
478
479    struct sockaddr_in sa;
480    ::memset (&sa, 0, sizeof sa);
481    sa.sin_family = AF_INET;
482    sa.sin_port = htons (listen_port_num);
483    sa.sin_addr.s_addr = htonl (INADDR_ANY);
484
485    int err = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa));
486    if (err == -1)
487    {
488        if (error_ptr)
489            error_ptr->SetErrorToErrno();
490        Close (listen_port, NULL);
491        return eConnectionStatusError;
492    }
493
494    err = ::listen (listen_port, 1);
495    if (err == -1)
496    {
497        if (error_ptr)
498            error_ptr->SetErrorToErrno();
499        Close (listen_port, NULL);
500        return eConnectionStatusError;
501    }
502
503    m_fd = ::accept (listen_port, NULL, 0);
504    if (m_fd == -1)
505    {
506        if (error_ptr)
507            error_ptr->SetErrorToErrno();
508        Close (listen_port, NULL);
509        return eConnectionStatusError;
510    }
511
512    // We are done with the listen port
513    Close (listen_port, NULL);
514
515    m_should_close_fd = true;
516
517    // Keep our TCP packets coming without any delays.
518    SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
519    if (error_ptr)
520        error_ptr->Clear();
521    return eConnectionStatusSuccess;
522}
523
524ConnectionStatus
525ConnectionFileDescriptor::SocketConnect (const char *host_and_port, Error *error_ptr)
526{
527    lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
528                                 "%p ConnectionFileDescriptor::SocketConnect (host/port = %s)",
529                                 this, host_and_port);
530    Close (m_fd, NULL);
531    m_is_socket = true;
532
533    RegularExpression regex ("([^:]+):([0-9]+)");
534    if (regex.Execute (host_and_port, 2) == false)
535    {
536        if (error_ptr)
537            error_ptr->SetErrorStringWithFormat("Invalid host:port specification: '%s'.\n", host_and_port);
538        return eConnectionStatusError;
539    }
540    std::string host_str;
541    std::string port_str;
542    if (regex.GetMatchAtIndex (host_and_port, 1, host_str) == false ||
543        regex.GetMatchAtIndex (host_and_port, 2, port_str) == false)
544    {
545        if (error_ptr)
546            error_ptr->SetErrorStringWithFormat("Invalid host:port specification '%s'.\n", host_and_port);
547        return eConnectionStatusError;
548    }
549
550    int32_t port = Args::StringToSInt32 (port_str.c_str(), INT32_MIN);
551    if (port == INT32_MIN)
552    {
553        if (error_ptr)
554            error_ptr->SetErrorStringWithFormat("Invalid port '%s'.\n", port_str.c_str());
555        return eConnectionStatusError;
556    }
557    // Create the socket
558    m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
559    if (m_fd == -1)
560    {
561        if (error_ptr)
562            error_ptr->SetErrorToErrno();
563        return eConnectionStatusError;
564    }
565
566    m_should_close_fd = true;
567
568    // Enable local address reuse
569    SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
570
571    struct sockaddr_in sa;
572    ::bzero (&sa, sizeof (sa));
573    sa.sin_family = AF_INET;
574    sa.sin_port = htons (port);
575
576    int inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
577
578    if (inet_pton_result <= 0)
579    {
580        struct hostent *host_entry = gethostbyname (host_str.c_str());
581        if (host_entry)
582            host_str = ::inet_ntoa (*(struct in_addr *)*host_entry->h_addr_list);
583        inet_pton_result = ::inet_pton (AF_INET, host_str.c_str(), &sa.sin_addr);
584        if (inet_pton_result <= 0)
585        {
586
587            if (error_ptr)
588            {
589                if (inet_pton_result == -1)
590                    error_ptr->SetErrorToErrno();
591                else
592                    error_ptr->SetErrorStringWithFormat("Invalid host string: '%s'.\n", host_str.c_str());
593            }
594            Close (m_fd, NULL);
595            return eConnectionStatusError;
596        }
597    }
598
599    if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
600    {
601        if (error_ptr)
602            error_ptr->SetErrorToErrno();
603        Close (m_fd, NULL);
604        return eConnectionStatusError;
605    }
606
607    // Keep our TCP packets coming without any delays.
608    SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
609    if (error_ptr)
610        error_ptr->Clear();
611    return eConnectionStatusSuccess;
612}
613
614int
615ConnectionFileDescriptor::SetSocketOption(int fd, int level, int option_name, int option_value)
616{
617    return ::setsockopt(fd, level, option_name, &option_value, sizeof(option_value));
618}
619
620
621