Esempio n. 1
0
/*
 * Handle management socket events asynchronously
 */
void
OnManagement(SOCKET sk, LPARAM lParam)
{
    int res;
    char *pos = NULL;
    char data[MAX_LOG_LENGTH];
    connection_t *c = GetConnByManagement(sk);
    if (c == NULL)
        return;

    switch (WSAGETSELECTEVENT(lParam))
    {
    case FD_CONNECT:
        if (WSAGETSELECTERROR(lParam))
            SendMessage(c->hwndStatus, WM_CLOSE, 0, 0);
        break;

    case FD_READ:
        /* Check if there's a complete line to read */
        res = recv(c->manage.sk, data, sizeof(data), MSG_PEEK);
        if (res < 1)
            return;

        pos = memchr(data, (*c->manage.password ? ':' : '\n'), res);
        if (!pos)
            return;

        /* There is data available: read it */
        res = recv(c->manage.sk, data, pos - data + 1, 0);
        if (res != pos - data + 1)
            return;

        /* Reply to a management password request */
        if (*c->manage.password)
        {
            ManagementCommand(c, c->manage.password, NULL, regular);
            *c->manage.password = '******';
            return;
        }

        /* Handle regular management interface output */
        data[pos - data - 1] = '\0';
        if (data[0] == '>')
        {
            /* Real time notifications */
            pos = data + 1;
            if (strncmp(pos, "LOG:", 4) == 0)
            {
                if (rtmsg_handler[log])
                    rtmsg_handler[log](c, pos + 4);
            }
            else if (strncmp(pos, "STATE:", 6) == 0)
            {
                if (rtmsg_handler[state])
                    rtmsg_handler[state](c, pos + 6);
            }
            else if (strncmp(pos, "HOLD:", 5) == 0)
            {
                if (rtmsg_handler[hold])
                    rtmsg_handler[hold](c, pos + 5);
            }
            else if (strncmp(pos, "PASSWORD:"******"INFO:", 5) == 0)
            {
                /* delay until management interface accepts input */
                Sleep(100);
                if (rtmsg_handler[ready])
                    rtmsg_handler[ready](c, pos + 5);
            }
        }
        else if (c->manage.cmd_queue)
        {
            /* Response to commands */
            mgmt_cmd_t *cmd = c->manage.cmd_queue;
            if (strncmp(data, "SUCCESS:", 8) == 0)
            {
                if (cmd->handler)
                    cmd->handler(c, data + 9);
                UnqueueCommand(c);
            }
            else if (strncmp(data, "ERROR:", 6) == 0)
            {
                if (cmd->handler)
                    cmd->handler(c, NULL);
                UnqueueCommand(c);
            }
            else if (strcmp(data, "END") == 0)
            {
                UnqueueCommand(c);
            }
            else if (cmd->handler)
            {
                cmd->handler(c, data);
            }
        }
        break;

    case FD_WRITE:
        SendCommand(c);
        break;

    case FD_CLOSE:
        closesocket(c->manage.sk);
        c->manage.sk = INVALID_SOCKET;
        while (UnqueueCommand(c))
            ;
        WSACleanup();
        if (rtmsg_handler[stop])
            rtmsg_handler[stop](c, "");
        break;
    }
}
Esempio n. 2
0
/*
 * Handle management socket events asynchronously
 */
void
OnManagement(SOCKET sk, LPARAM lParam)
{
    int res;
    char *data;
    ULONG data_size, offset;

    connection_t *c = GetConnByManagement(sk);
    if (c == NULL)
        return;

    switch (WSAGETSELECTEVENT(lParam))
    {
    case FD_CONNECT:
        if (WSAGETSELECTERROR(lParam))
        {
            if (time(NULL) < c->manage.timeout)
                connect(c->manage.sk, (SOCKADDR *)&c->manage.skaddr, sizeof(c->manage.skaddr));
            else
            {
                /* Connection to MI timed out. */
                c->state = timedout;
                rtmsg_handler[stop](c, "");
            }
        }
        break;

    case FD_READ:
        if (ioctlsocket(c->manage.sk, FIONREAD, &data_size) != 0
        ||  data_size == 0)
            return;

        data = malloc(c->manage.saved_size + data_size);
        if (data == NULL)
            return;

        res = recv(c->manage.sk, data + c->manage.saved_size, data_size, 0);
        if (res != (int) data_size)
        {
            free(data);
            return;
        }

        /* Copy previously saved management data */
        if (c->manage.saved_size)
        {
            memcpy(data, c->manage.saved_data, c->manage.saved_size);
            data_size += c->manage.saved_size;
            free(c->manage.saved_data);
            c->manage.saved_data = NULL;
            c->manage.saved_size = 0;
        }

        offset = 0;
        while (offset < data_size)
        {
            char *pos;
            char *line = data + offset;
            size_t line_size = data_size - offset;

            pos = memchr(line, (*c->manage.password ? ':' : '\n'), line_size);
            if (pos == NULL)
            {
                c->manage.saved_data = malloc(line_size);
                if (c->manage.saved_data)
                {
                    c->manage.saved_size = line_size;
                    memcpy(c->manage.saved_data, line, c->manage.saved_size);
                }
                break;
            }

            offset += (pos - line) + 1;

            /* Reply to a management password request */
            if (*c->manage.password)
            {
                ManagementCommand(c, c->manage.password, NULL, regular);
                *c->manage.password = '******';
                continue;
            }

            /* Handle regular management interface output */
            line[pos - line - 1] = '\0';
            if (line[0] == '>')
            {
                /* Real time notifications */
                pos = line + 1;
                if (strncmp(pos, "LOG:", 4) == 0)
                {
                    if (rtmsg_handler[log])
                        rtmsg_handler[log](c, pos + 4);
                }
                else if (strncmp(pos, "STATE:", 6) == 0)
                {
                    if (rtmsg_handler[state])
                        rtmsg_handler[state](c, pos + 6);
                }
                else if (strncmp(pos, "HOLD:", 5) == 0)
                {
                    if (rtmsg_handler[hold])
                        rtmsg_handler[hold](c, pos + 5);
                }
                else if (strncmp(pos, "PASSWORD:"******"PROXY:", 6) == 0)
                {
                    if (rtmsg_handler[proxy])
                        rtmsg_handler[proxy](c, pos + 6);
                }
                else if (strncmp(pos, "INFO:", 5) == 0)
                {
                    /* delay until management interface accepts input */
                    Sleep(100);
                    if (rtmsg_handler[ready])
                        rtmsg_handler[ready](c, pos + 5);
                }
            }
            else if (c->manage.cmd_queue)
            {
                /* Response to commands */
                mgmt_cmd_t *cmd = c->manage.cmd_queue;
                if (strncmp(line, "SUCCESS:", 8) == 0)
                {
                    if (cmd->handler)
                        cmd->handler(c, line + 9);
                    UnqueueCommand(c);
                }
                else if (strncmp(line, "ERROR:", 6) == 0)
                {
                    if (cmd->handler)
                        cmd->handler(c, NULL);
                    UnqueueCommand(c);
                }
                else if (strcmp(line, "END") == 0)
                {
                    UnqueueCommand(c);
                }
                else if (cmd->handler)
                {
                    cmd->handler(c, line);
                }
            }
        }
        free(data);
        break;

    case FD_WRITE:
        SendCommand(c);
        break;

    case FD_CLOSE:
        if (c->manage.saved_size)
        {
            free(c->manage.saved_data);
            c->manage.saved_data = NULL;
            c->manage.saved_size = 0;
        }
        closesocket(c->manage.sk);
        c->manage.sk = INVALID_SOCKET;
        while (UnqueueCommand(c))
            ;
        WSACleanup();
        if (rtmsg_handler[stop])
            rtmsg_handler[stop](c, "");
        break;
    }
}