Пример #1
0
extern "C" void SystemNative_ReadEvents(int32_t sock, NetworkChangeEvent onNetworkChange)
{
    char buffer[4096];
    iovec iov = {buffer, sizeof(buffer)};
    sockaddr_nl sanl;
    msghdr msg = { .msg_name = reinterpret_cast<void*>(&sanl), .msg_namelen = sizeof(sockaddr_nl), .msg_iov = &iov, .msg_iovlen = 1 };
    ssize_t len;
    while (CheckInterrupted(len = recvmsg(sock, &msg, 0)));
    if (len == -1)
    {
        // Probably means the socket has been closed.
        return;
    }

    for (nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buffer); NLMSG_OK(hdr, UnsignedCast(len)); NLMSG_NEXT(hdr, len))
    {
        switch (hdr->nlmsg_type)
        {
            case NLMSG_DONE:
                return; // End of a multi-part message; stop reading.
            case NLMSG_ERROR:
                return;
            case RTM_NEWADDR:
                onNetworkChange(sock, NetworkChangeKind::AddressAdded);
                break;
            case RTM_DELADDR:
                onNetworkChange(sock, NetworkChangeKind::AddressRemoved);
                break;
            case RTM_NEWLINK:
                onNetworkChange(sock, ReadNewLinkMessage(hdr));
                break;
            case RTM_DELLINK:
                onNetworkChange(sock, NetworkChangeKind::LinkRemoved);
                break;
            default:
                break;
        }
    }
}

NetworkChangeKind ReadNewLinkMessage(nlmsghdr* hdr)
{
    assert(hdr != nullptr);
    ifinfomsg* ifimsg;
    ifimsg = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
    if (ifimsg->ifi_family == AF_INET)
    {
        if ((ifimsg->ifi_flags & IFF_UP) != 0)
        {
            return NetworkChangeKind::LinkAdded;
        }
    }

    return NetworkChangeKind::None;
}
Пример #2
0
extern "C" NetworkChangeKind SystemNative_ReadSingleEvent(int32_t sock)
{
    char buffer[4096];
    iovec iov = {buffer, sizeof(buffer)};
    sockaddr_nl sanl;
    msghdr msg = { .msg_name = reinterpret_cast<void*>(&sanl), .msg_namelen = sizeof(sockaddr_nl), .msg_iov = &iov, .msg_iovlen = 1 };
    ssize_t len;
    while (CheckInterrupted(len = recvmsg(sock, &msg, 0)));
    if (len == -1)
    {
        // Probably means the socket has been closed.
        // If so, the managed side will ignore the return value.
        return NetworkChangeKind::None;
    }

    nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buffer);
    // This channel should only send a single message at a time.
    // This means there should be no multi-part messages (NLM_F_MULTI).
    assert((hdr->nlmsg_flags & NLM_F_MULTI) == 0);
    switch (hdr->nlmsg_type)
    {
        case NLMSG_DONE:
            return NetworkChangeKind::None;
        case NLMSG_ERROR:
            return NetworkChangeKind::None;
        case RTM_NEWADDR:
            return NetworkChangeKind::AddressAdded;
        case RTM_DELADDR:
            return NetworkChangeKind::AddressRemoved;
        case RTM_NEWLINK:
            return ReadNewLinkMessage(hdr);
        case RTM_DELLINK:
            return NetworkChangeKind::LinkRemoved;
        default:
            return NetworkChangeKind::None;
    }
}

NetworkChangeKind ReadNewLinkMessage(nlmsghdr* hdr)
{
    assert(hdr != nullptr);
    ifinfomsg* ifimsg;
    ifimsg = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
    if (ifimsg->ifi_family == AF_INET)
    {
        if ((ifimsg->ifi_flags & IFF_UP) != 0)
        {
            return NetworkChangeKind::LinkAdded;
        }
    }

    return NetworkChangeKind::None;
}
Пример #3
0
extern "C" NetworkChangeKind ReadSingleEvent(int32_t sock)
{
    char buffer[4096];
    iovec iov = { buffer, sizeof(buffer) };
    sockaddr_nl sanl;
    msghdr msg = { reinterpret_cast<void*>(&sanl), sizeof(sockaddr_nl), &iov, 1, NULL, 0, 0};
    ssize_t len = recvmsg(sock, &msg, 0);
    if (len == -1)
    {
        // Probably means the socket has been closed.
        // If so, the managed side will ignore the return value.
        return NetworkChangeKind::None;
    }

    nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buffer);
    // This channel should only send a single message at a time.
    // This means there should be no multi-part messages (NLM_F_MULTI).
    assert ((hdr->nlmsg_flags & NLM_F_MULTI) == 0);
    switch (hdr->nlmsg_type)
    {
        case NLMSG_DONE:
            return NetworkChangeKind::None;
        case NLMSG_ERROR:
            return NetworkChangeKind::None;
        case RTM_NEWADDR:
            return NetworkChangeKind::AddressAdded;
        case RTM_DELADDR:
            return NetworkChangeKind::AddressRemoved;
        case RTM_NEWLINK:
            return ReadNewLinkMessage(hdr);
        case RTM_DELLINK:
            return NetworkChangeKind::LinkRemoved;
        default:
            return NetworkChangeKind::None;
    }
}