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