106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton//===-- ConnectionMachPort.cpp ----------------------------*- C++ -*-===//
206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton//
306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton//                     The LLVM Compiler Infrastructure
406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton//
506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton// This file is distributed under the University of Illinois Open Source
606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton// License. See LICENSE.TXT for details.
706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton//
806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton//===----------------------------------------------------------------------===//
906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#if defined(__APPLE__)
1006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
1106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#include "lldb/Core/ConnectionMachPort.h"
1206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
1306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton// C Includes
1406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#include <servers/bootstrap.h>
1506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
1606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton// C++ Includes
1706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton// Other libraries and framework includes
1806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton// Project includes
1906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#include "lldb/lldb-private-log.h"
2006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#include "lldb/Core/Communication.h"
2106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#include "lldb/Core/Log.h"
2206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
2306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonusing namespace lldb;
2406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonusing namespace lldb_private;
2506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
2606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonstruct MessageType
2706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
2806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    mach_msg_header_t head;
2906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    ConnectionMachPort::PayloadType payload;
3006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton};
3106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
3206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
3306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
3406d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::ConnectionMachPort () :
3506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    Connection(),
3606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    m_task(mach_task_self()),
3706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    m_port(MACH_PORT_TYPE_NONE)
3806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
3906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
4006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
4106d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::~ConnectionMachPort ()
4206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
4306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    Disconnect (NULL);
4406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
4506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
4606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonbool
4706d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::IsConnected () const
4806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
4906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return  m_port != MACH_PORT_TYPE_NONE;
5006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
5106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
5206d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionStatus
5306d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::Connect (const char *s, Error *error_ptr)
5406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
5506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (IsConnected())
5606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
5706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
5806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetErrorString ("already connected");
5906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return eConnectionStatusError;
6006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
6106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
6206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (s == NULL || s[0] == '\0')
6306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
6406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
6506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetErrorString ("empty connect URL");
6606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return eConnectionStatusError;
6706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
6806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
6906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    ConnectionStatus status = eConnectionStatusError;
7006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
7106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (strncmp (s, "bootstrap-checkin://", strlen("bootstrap-checkin://")))
7206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
7306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        s += strlen("bootstrap-checkin://");
7406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
7506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (*s)
7606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
7706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            status = BootstrapCheckIn (s, error_ptr);
7806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
7906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        else
8006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
8106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            if (error_ptr)
8206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                error_ptr->SetErrorString ("bootstrap port name is empty");
8306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
8406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
8506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    else if (strncmp (s, "bootstrap-lookup://", strlen("bootstrap-lookup://")))
8606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
8706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        s += strlen("bootstrap-lookup://");
8806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (*s)
8906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
9006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            status = BootstrapLookup (s, error_ptr);
9106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
9206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        else
9306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
9406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            if (error_ptr)
9506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                error_ptr->SetErrorString ("bootstrap port name is empty");
9606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
9706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
9806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    else
9906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
10006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
10106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s);
10206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
10306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
10406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
10506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (status == eConnectionStatusSuccess)
10606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
10706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
10806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->Clear();
10906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
11006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    else
11106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
11206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        Disconnect(NULL);
11306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
11406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
11506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return status;
11606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
11706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
11806d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionStatus
11906d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::BootstrapCheckIn (const char *port, Error *error_ptr)
12006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
12106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    mach_port_t bootstrap_port = MACH_PORT_TYPE_NONE;
12206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
12306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    /* Getting bootstrap server port */
12406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    kern_return_t kret = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
12506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (kret == KERN_SUCCESS)
12606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
12706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        name_t port_name;
12806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        int len = snprintf(port_name, sizeof(port_name), "%s", port);
12906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (len < sizeof(port_name))
13006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
13106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            kret = ::bootstrap_check_in (bootstrap_port,
13206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                         port_name,
13306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                         &m_port);
13406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
13506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        else
13606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
13706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            Disconnect(NULL);
13806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            if (error_ptr)
13906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                error_ptr->SetErrorString ("bootstrap is too long");
14006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            return eConnectionStatusError;
14106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
14206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
14306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
14406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (kret != KERN_SUCCESS)
14506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
14606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        Disconnect(NULL);
14706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
14806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetError (kret, eErrorTypeMachKernel);
14906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return eConnectionStatusError;
15006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
15106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return eConnectionStatusSuccess;
15206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
15306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
15406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonlldb::ConnectionStatus
15506d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::BootstrapLookup (const char *port,
15606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     Error *error_ptr)
15706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
15806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    name_t port_name;
15906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
16006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (port && port[0])
16106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
16206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (::snprintf (port_name, sizeof (port_name), "%s", port) >= sizeof (port_name))
16306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        {
16406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            if (error_ptr)
16506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                error_ptr->SetErrorString ("port netname is too long");
16606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            return eConnectionStatusError;
16706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        }
16806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
16906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    else
17006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
17106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
17206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetErrorString ("empty port netname");
17306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return eConnectionStatusError;
17406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
17506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
17606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    mach_port_t bootstrap_port = MACH_PORT_TYPE_NONE;
17706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
17806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    /* Getting bootstrap server port */
17906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    kern_return_t kret = task_get_bootstrap_port(mach_task_self(), &bootstrap_port);
18006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (kret == KERN_SUCCESS)
18106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
18206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        kret = ::bootstrap_look_up (bootstrap_port,
18306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                    port_name,
18406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                    &m_port);
18506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
18606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
18706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (kret != KERN_SUCCESS)
18806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
18906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
19006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetError (kret, eErrorTypeMachKernel);
19106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return eConnectionStatusError;
19206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
19306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
19406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return eConnectionStatusSuccess;
19506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
19606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
19706d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionStatus
19806d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::Disconnect (Error *error_ptr)
19906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
20006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    kern_return_t kret;
20106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
20206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    // TODO: verify if we need to netname_check_out for
20306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    // either or both
20406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (m_port != MACH_PORT_TYPE_NONE)
20506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
20606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        kret = ::mach_port_deallocate (m_task, m_port);
20706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        if (error_ptr)
20806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton            error_ptr->SetError (kret, eErrorTypeMachKernel);
20906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        m_port = MACH_PORT_TYPE_NONE;
21006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
21106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
21206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return eConnectionStatusSuccess;
21306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
21406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
21506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonsize_t
21663afdb07641f04aa7b60d895120b056124d3469bGreg ClaytonConnectionMachPort::Read (void *dst,
21763afdb07641f04aa7b60d895120b056124d3469bGreg Clayton                          size_t dst_len,
21863afdb07641f04aa7b60d895120b056124d3469bGreg Clayton                          uint32_t timeout_usec,
21963afdb07641f04aa7b60d895120b056124d3469bGreg Clayton                          ConnectionStatus &status,
22063afdb07641f04aa7b60d895120b056124d3469bGreg Clayton                          Error *error_ptr)
22106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
22206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    PayloadType payload;
22306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
22406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    kern_return_t kret = Receive (payload);
22506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (kret == KERN_SUCCESS)
22606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
22706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        memcpy (dst, payload.data, payload.data_length);
22806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        status = eConnectionStatusSuccess;
22906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return payload.data_length;
23006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
23106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
23206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (error_ptr)
23306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        error_ptr->SetError (kret, eErrorTypeMachKernel);
23406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    status = eConnectionStatusError;
23506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return 0;
23606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
23706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
23806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonsize_t
23906d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr)
24006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
24106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    PayloadType payload;
24206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    payload.command = 0;
24306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    payload.data_length = src_len;
24406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    const size_t max_payload_size = sizeof(payload.data);
24506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (src_len > max_payload_size)
24606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        payload.data_length = max_payload_size;
24706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    memcpy (payload.data, src, payload.data_length);
24806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
24906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (Send (payload) == KERN_SUCCESS)
25006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    {
25106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        status = eConnectionStatusSuccess;
25206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        return payload.data_length;
25306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    }
25406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    status = eConnectionStatusError;
25506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return 0;
25606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
25706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
25806d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionStatus
25906d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::BytesAvailable (uint32_t timeout_usec, Error *error_ptr)
26006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
26106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    return eConnectionStatusLostConnection;
26206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
26306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
26406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonkern_return_t
26506d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::Send (const PayloadType &payload)
26606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
26706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	struct MessageType message;
26806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
26906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	/* (i) Form the message : */
27006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
27106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	/* (i.a) Fill the header fields : */
27206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	message.head.msgh_bits = MACH_MSGH_BITS_REMOTE (MACH_MSG_TYPE_MAKE_SEND) |
27306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                             MACH_MSGH_BITS_OTHER (MACH_MSGH_BITS_COMPLEX);
27406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	message.head.msgh_size = sizeof(MessageType);
27506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	message.head.msgh_local_port = MACH_PORT_NULL;
27606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	message.head.msgh_remote_port = m_port;
27706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
27806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	/* (i.b) Explain the message type ( an integer ) */
27906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    //	message.type.msgt_name = MACH_MSG_TYPE_INTEGER_32;
28006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    //	message.type.msgt_size = 32;
28106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    //	message.type.msgt_number = 1;
28206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    //	message.type.msgt_inline = TRUE;
28306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    //	message.type.msgt_longform = FALSE;
28406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    //	message.type.msgt_deallocate = FALSE;
28506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	/* message.type.msgt_unused = 0; */ /* not needed, I think */
28606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
28706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	/* (i.c) Fill the message with the given integer : */
28806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	message.payload = payload;
28906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
29006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	/* (ii) Send the message : */
29106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	kern_return_t kret = ::mach_msg (&message.head,
29206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_SEND_MSG,
29306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     message.head.msgh_size,
29406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     0,
29506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_PORT_NULL,
29606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_MSG_TIMEOUT_NONE,
29706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_PORT_NULL);
29806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
29906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	return kret;
30006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
30106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
30206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Claytonkern_return_t
30306d7cc86937caca0acf2b990a02a641dc9c7579aGreg ClaytonConnectionMachPort::Receive (PayloadType &payload)
30406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton{
30506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	MessageType message;
30606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	message.head.msgh_size = sizeof(MessageType);
30706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
30806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	kern_return_t kret = ::mach_msg (&message.head,
30906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_RCV_MSG,
31006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     0,
31106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     sizeof(MessageType),
31206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     m_port,
31306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_MSG_TIMEOUT_NONE,
31406d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton                                     MACH_PORT_NULL);
31506d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
31606d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton    if (kret == KERN_SUCCESS)
31706d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton        payload = message.payload;
31806d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
31906d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton	return kret;
32006d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton}
32106d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
32206d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton
32306d7cc86937caca0acf2b990a02a641dc9c7579aGreg Clayton#endif // #if defined(__APPLE__)
324