Beispiel #1
0
/* Put some data onto the connection, printf style.
 */
bool
hub_putf(const char *format, ...)
{
    va_list args;
    size_t oldcur;
    int res;

    oldcur = hub_sendq->cur;
    va_start(args, format);
    res = byteq_vappendf(hub_sendq, format, args);
    va_end(args);

    if (res < 0) {
        warn(_("Cannot append to hub send queue - %s\n"), errstr);
        hub_disconnect();
        return false;
    }

    dump_command(_("-->"), hub_sendq->buf+oldcur, hub_sendq->cur-oldcur);

    res = byteq_write(hub_sendq, hub_socket);
    if (res == 0 || (res < 0 && errno != EAGAIN)) {
        warn_socket_error(res, true, _("hub"));
        hub_disconnect();
        return false;
    }

    if (oldcur == 0 && hub_sendq->cur > 0)
        FD_SET(hub_socket, &write_fds);

    update_hub_activity();

    return true;
}
Beispiel #2
0
void
hub_connect(struct sockaddr_in *addr)
{
    hub_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (hub_socket < 0) {
        warn(_("Cannot create socket - %s\n"), errstr);
        hub_disconnect();
        return;
    }

    /* Set non-blocking I/O on socket. */
    if (!fd_set_nonblock_flag(hub_socket, true)) {
        warn(_("Cannot set non-blocking flag - %s\n"), errstr);
        hub_disconnect();
        return;
    }

    screen_putf(_("Connecting to hub on %s.\n"), sockaddr_in_str(addr));
    if (connect(hub_socket, (struct sockaddr *) addr, sizeof(struct sockaddr_in)) < 0
            && errno != EINPROGRESS) {
        warn(_("%s: Cannot connect - %s\n"), sockaddr_in_str(addr), errstr);
        hub_disconnect();
        return;
    }

    if (&hub_addr != addr)
        hub_addr = *addr;
    FD_SET(hub_socket, &write_fds);
    hub_state = DC_HUB_CONNECT;
}
Beispiel #3
0
void
hub_now_writable(void)
{
    if (hub_state == DC_HUB_CONNECT) {
        int error;
        socklen_t size = sizeof(error);
        socklen_t addr_len;

        if (getsockopt(hub_socket, SOL_SOCKET, SO_ERROR, &error, &size) < 0) {
            warn(_("Cannot get error status - %s\n"), errstr);
            hub_disconnect();
            return;
        }
        if (error != 0) { /* The connect call on the socket failed. */
            warn(_("Cannot connect - %s\n"), strerror(error) /* not errno! */);
            /* XXX: need to know hub address to put in error message */
            hub_disconnect();
            return;
        }

        addr_len = sizeof(local_addr);
        if (getsockname(hub_socket, (struct sockaddr *) &local_addr, &addr_len) < 0) {
            warn(_("Cannot get socket address - %s\n"), errstr);
            hub_disconnect();
            return;
        }
        if (force_listen_addr.s_addr != INADDR_NONE)
            local_addr.sin_addr = force_listen_addr;

        screen_putf(_("Connected to hub from %s.\n"), sockaddr_in_str(&local_addr));
        update_hub_activity();

        FD_CLR(hub_socket, &write_fds);
        FD_SET(hub_socket, &read_fds);
        hub_state = DC_HUB_LOCK;
    } else {
        int res;

        if (hub_sendq->cur > 0) {
            res = byteq_write(hub_sendq, hub_socket);
            if (res == 0 || (res < 0 && errno != EAGAIN)) {
                warn_socket_error(res, true, _("hub"));
                hub_disconnect();
                return;
            }
        }
        if (hub_sendq->cur == 0)
            FD_CLR(hub_socket, &write_fds);
    }
}
Beispiel #4
0
static void psfreedom_disconnect (struct usb_gadget *gadget)
{
  struct psfreedom_device *dev = get_gadget_data (gadget);
  unsigned long flags;
  int i;

  spin_lock_irqsave (&dev->lock, flags);
  INFO (dev, "Got disconnected\n");

  /* Reinitialize all device variables*/
  dev->challenge_len = 0;
  dev->response_len = 0;
  dev->current_port = 0;
  for (i = 0; i < 6; i++)
    dev->hub_ports[i].status = dev->hub_ports[i].change = 0;
  for (i = 0; i < 7; i++)
    dev->port_address[i] = 0;
  hub_disconnect (gadget);
  devices_disconnect (gadget);
  if (timer_added)
    del_timer (&psfreedom_state_machine_timer);
  timer_added = 0;
  dev->switch_to_port_delayed = -1;
  dev->status = INIT;

  spin_unlock_irqrestore (&dev->lock, flags);
}
Beispiel #5
0
/* This function is called by handle_connection_fd_event when there is input
 * available on the connection socket.
 */
void
hub_input_available(void)
{
    int start = 0;
    int c;
    int res;

    res = byteq_read(hub_recvq, hub_socket);
    if (res == 0 || (res < 0 && errno != EAGAIN)) {
        warn_socket_error(res, false, _("hub"));
        hub_disconnect();
        return;
    }

    for (c = hub_recvq_last; c < hub_recvq->cur; c++) {
        if (hub_recvq->buf[c] == '|') {
            /* Got a complete command. */
            if (c - start > 0)
                dump_command(_("<--"), hub_recvq->buf + start, c - start + 1);
            hub_recvq->buf[c] = '\0'; /* Just to be on the safe side... */
            hub_handle_command(hub_recvq->buf + start, c - start);
            start = c+1;
            if (hub_socket < 0)
                return;
        }
    }

    if (start != 0)
        byteq_remove(hub_recvq, start);

    hub_recvq_last = hub_recvq->cur;

    update_hub_activity();
}
Beispiel #6
0
static bool
check_state(char *buf, DCUserState state)
{
    if (hub_state != state) {
        warn(_("Received %s message in wrong state.\n"), strtok(buf, " "));
        hub_disconnect();
        return false;
    }
    return true;
}
Beispiel #7
0
static void c_disconnect(char *args) {
  struct ui_tab *tab = ui_tab_cur->data;
  if(args[0])
    ui_m(NULL, 0, "This command does not accept any arguments.");
  else if(tab->type == UIT_HUB) {
    if(!tab->hub->net->conn && !tab->hub->reconnect_timer && !tab->hub->net->connecting)
      ui_m(NULL, 0, "Not connected.");
    else
      hub_disconnect(tab->hub, FALSE);
  } else if(tab->type == UIT_MAIN) {
    ui_m(NULL, 0, "Disconnecting all hubs.");
    GList *n = ui_tabs;
    for(; n; n=n->next) {
      tab = n->data;
      if(tab->type == UIT_HUB && (tab->hub->net->conn || tab->hub->net->connecting || tab->hub->reconnect_timer))
        hub_disconnect(tab->hub, FALSE);
    }
  } else
    ui_m(NULL, 0, "This command can only be used on the main tab or on hub tabs.");
}
Beispiel #8
0
static void c_reconnect(char *args) {
  struct ui_tab *tab = ui_tab_cur->data;
  if(args[0])
    ui_m(NULL, 0, "This command does not accept any arguments.");
  else if(tab->type == UIT_HUB) {
    if(tab->hub->net->conn || tab->hub->net->connecting || tab->hub->reconnect_timer)
      hub_disconnect(tab->hub, FALSE);
    c_connect(""); // also checks for the existence of "hubaddr"
  } else if(tab->type == UIT_MAIN) {
    ui_m(NULL, 0, "Reconnecting all hubs.");
    GList *n = ui_tabs;
    for(; n; n=n->next) {
      tab = n->data;
      if(tab->type != UIT_HUB)
        continue;
      if(tab->hub->net->conn || tab->hub->net->connecting || tab->hub->reconnect_timer)
        hub_disconnect(tab->hub, FALSE);
      ui_tab_cur = n;
      c_connect("");
    }
    ui_tab_cur = g_list_find(ui_tabs, ui_main);
  } else
    ui_m(NULL, 0, "This command can only be used on the main tab or on hub tabs.");
}
Beispiel #9
0
void hub_reconnect()
{
    hub_disconnect();
    hub_connect(&hub_addr);
}
Beispiel #10
0
static void
hub_handle_command(char *buf, uint32_t len)
{
    char *hub_my_nick; /* XXX */

    hub_my_nick = main_to_hub_string(my_nick);

    if (len >= 6 && strncmp(buf, "$Lock ", 6) == 0) {
        char *key;

        if (!check_state(buf, (DCUserState) DC_HUB_LOCK))
            goto hub_handle_command_cleanup;

        key = (char*) memmem(buf+6, len-6, " Pk=", 4);
        if (key == NULL) {
            warn(_("Invalid $Lock message: Missing Pk value\n"));
            key = buf+len;
        }
        key = decode_lock(buf+6, key-buf-6, DC_CLIENT_BASE_KEY);
        if (strleftcmp("EXTENDEDPROTOCOL", buf+6) == 0) {
            if (!hub_putf("$Supports TTHSearch NoGetINFO NoHello|")) {
                free(key);
                goto hub_handle_command_cleanup;
            }
        }
        if (!hub_putf("$Key %s|", key)) {
            free(key);
            goto hub_handle_command_cleanup;
        }
        free(key);
        if (!hub_putf("$ValidateNick %s|", hub_my_nick))
            goto hub_handle_command_cleanup;
        hub_state = DC_HUB_HELLO;
    }
    else if (len >= 10 && strncmp(buf, "$Supports ", 10) == 0) {
        char *p0, *p1;

        hub_extensions = 0;
        for (p0 = buf+10; (p1 = strchr(p0, ' ')) != NULL; p0 = p1+1) {
            *p1 = '\0';
            parse_hub_extension(p0);
        }
        if (*p0 != '\0')
            parse_hub_extension(p0);
    }
    else if (strcmp(buf, "$GetPass") == 0) {
        if (my_password == NULL) {
            screen_putf(_("Hub requires password.\n"));
            hub_disconnect();
            goto hub_handle_command_cleanup;
        }
        screen_putf(_("Sending password to hub.\n"));
        if (!hub_putf("$MyPass %s|", my_password))
            goto hub_handle_command_cleanup;
    }
    else if (strcmp(buf, "$BadPass") == 0) {
        warn(_("Password not accepted.\n"));
        hub_disconnect();
    }
    else if (strcmp(buf, "$LogedIn") == 0) {
        screen_putf(_("You have received operator status.\n"));
    }
    else if (len >= 9 && strncmp(buf, "$HubName ", 9) == 0) {
        free(hub_name);
        hub_name = hub_to_main_string(buf + 9);
        screen_putf(_("Hub name is %s.\n"), quotearg(hub_name));
    }
    else if (strcmp(buf, "$GetNetInfo") == 0) {
        hub_putf("$NetInfo %d$1$%c|", my_ul_slots, is_active ? 'A' : 'P');
    }
    else if (strcmp(buf, "$ValidateDenide") == 0) {
        if (!check_state(buf, (DCUserState) DC_HUB_HELLO))
            goto hub_handle_command_cleanup;
        /* DC++ disconnects immediately if this is received.
         * But shouldn't we give the client a chance to change the nick?
         * Also what happens if we receive this when correctly logged in?
         */
        warn(_("Hub did not accept nick. Nick may be in use.\n"));
        hub_disconnect();
    }
    else if (len >= 7 && strncmp(buf, "$Hello ", 7) == 0) {
        DCUserInfo *ui;
        char *conv_nick;

        conv_nick = hub_to_main_string(buf + 7);

        if (hub_state == DC_HUB_HELLO) {
            if (strcmp(buf+7, hub_my_nick) == 0) {
                screen_putf(_("Nick accepted. You are now logged in.\n"));
            } else {
                /* This probably won't happen, but better safe... */
                free(my_nick);
                my_nick = xstrdup(conv_nick);
                free(hub_my_nick);
                hub_my_nick = xstrdup(buf + 7);
                screen_putf(_("Nick accepted but modified to %s. You are now logged in.\n"), quotearg(my_nick));
            }

            ui = user_info_new(conv_nick);
            ui->info_quered = true; /* Hub is sending this automaticly */
            hmap_put(hub_users, ui->nick, ui);

            free (conv_nick);

            if (!hub_putf("$Version 1,0091|"))
                goto hub_handle_command_cleanup;
            if (!hub_putf("$GetNickList|"))
                goto hub_handle_command_cleanup;
            if (!send_my_info())
                goto hub_handle_command_cleanup;

            hub_state = DC_HUB_LOGGED_IN;
        } else {
            flag_putf(DC_DF_JOIN_PART, _("User %s logged in.\n"), quotearg(conv_nick));
            ui = user_info_new(conv_nick);
            hmap_put(hub_users, ui->nick, ui);
            free (conv_nick);
            if ((hub_extensions & HUB_EXT_NOGETINFO) == 0) {
                if (!hub_putf("$GetINFO %s %s|", buf+7, hub_my_nick))
                    goto hub_handle_command_cleanup;
                ui->info_quered = true;
            }
        }
    }
    else if (len >= 8 && strncmp(buf, "$MyINFO ", 8) == 0) {
        DCUserInfo *ui;
        char *token;
        uint32_t len;
        char* conv_buf;
        char *work_buf;

        buf += 8;
        work_buf = conv_buf = hub_to_main_string(buf);
        token = strsep(&work_buf, " ");
        if (strcmp(token, "$ALL") != 0) {
            warn(_("Invalid $MyINFO message: Missing $ALL parameter, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }

        token = strsep(&work_buf, " ");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing nick parameter, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        ui = (DCUserInfo*) hmap_get(hub_users, token);
        if (ui == NULL) {
            /*
             * if the full buf has not been converted from hub to local charset,
             * we should try to convert nick only
             */
            /*
            char *conv_nick = hub_to_main_string(token);
            if ((ui = hmap_get(hub_users, conv_nick)) == NULL) {
            */
            ui = user_info_new(token);
            ui->info_quered = true;
            hmap_put(hub_users, ui->nick, ui);
            /*
            }
            free(conv_nick);
            */
        }

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing description parameter, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        free(ui->description);
        ui->description = xstrdup(token);

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing description separator, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing connection speed, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        len = strlen(token);
        free(ui->speed);
        if (len == 0) {
            ui->speed = xstrdup("");
            ui->level = 0; /* XXX: or 1? acceptable level? */
        } else {
            ui->speed = xstrndup(token, len-1);
            ui->level = token[len-1];
        }

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing e-mail address, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        free(ui->email);
        ui->email = xstrdup(token);

        token = strsep(&work_buf, "$");
        if (token == NULL) {
            warn(_("Invalid $MyINFO message: Missing share size, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }
        if (!parse_uint64(token, &ui->share_size)) {
            warn(_("Invalid $MyINFO message: Invalid share size, ignoring\n"));
            free(conv_buf);
            goto hub_handle_command_cleanup;
        }

        if (ui->active_state == DC_ACTIVE_RECEIVED_PASSIVE
                || ui->active_state == DC_ACTIVE_KNOWN_ACTIVE)
            ui->active_state = DC_ACTIVE_UNKNOWN;

        /* XXX: Now that user's active_state may have changed, try queue again? */
        free(conv_buf);
    }
    else if (strcmp(buf, "$HubIsFull") == 0) {
        warn(_("Hub is full.\n"));
        /* DC++ does not disconnect immediately. So I guess we won't either. */
        /* Maybe we should be expecting an "hub follow" message? */
        /* hub_disconnect(); */
    }
    else if (len >= 3 && (buf[0] == '<' || strncmp(buf, " * ", 3) == 0)) {
        char *head;
        char *tail;
        char *msg;
        bool first = true;
        /*
        int scrwidth;
        size_t firstlen;
        size_t otherlen;

        screen_get_size(NULL, &scrwidth);
        firstlen = scrwidth - strlen(_("Public:"));
        otherlen = scrwidth - strlen(_(" | "));
        */

        msg = prepare_chat_string_for_display(buf);

        for (head = msg; (tail = strchr(head, '\n')) != NULL; head = tail+1) {
            /*PtrV *wrapped;*/

            if (tail[-1] == '\r') /* end > buf here, buf[0] == '<' or ' ' */
                tail[-1] = '\0';
            else
                tail[0] = '\0';

            /*wrapped = wordwrap(quotearg(buf), first ? firstlen : otherlen, otherlen);
            for (c = 0; c < wrapped->cur; c++)
            flag_putf(DC_DF_PUBLIC_CHAT, first ? _("Public: %s\n") : _(" | %s\n"), );
            ptrv_foreach(wrapped, free);
            ptrv_free(wrapped);*/
            flag_putf(DC_DF_PUBLIC_CHAT, first ? _("Public: %s\n") : _(" | %s\n"), quotearg(head));
            first = false;
        }
        flag_putf(DC_DF_PUBLIC_CHAT, first ? _("Public: %s\n") : _(" | %s\n"), quotearg(head));
        free(msg);
    }
    else if (len >= 5 && strncmp(buf, "$To: ", 5) == 0) {
        char *msg;
        char *tail;
        char *frm;
        char *head;
        bool first = true;

        msg = strchr(buf+5, '$');
        if (msg == NULL) {
            warn(_("Invalid $To message: Missing text separator, ignoring\n"));
            goto hub_handle_command_cleanup;
        }
        *msg = '\0';
        msg++;

        /* FIXME: WTF is this? Remove multiple "From: "? Why!? */
        frm = buf+5;
        while ((tail = strstr(msg, "From: ")) != NULL && tail < msg)
            frm = tail+6;

        msg = prepare_chat_string_for_display(msg);
        frm = prepare_chat_string_for_display(frm);
        for (head = msg; (tail = strchr(head, '\n')) != NULL; head = tail+1) {
            if (tail[-1] == '\r') /* tail > buf here because head[0] == '<' or ' ' */
                tail[-1] = '\0';
            else
                tail[0] = '\0';
            if (first) {
                screen_putf(_("Private: [%s] %s\n"), quotearg_n(0, frm), quotearg_n(1, head));
                first = false;
            } else {
                screen_putf(_(" | %s\n"), quotearg(head));
            }
        }
        if (first) {
            screen_putf(_("Private: [%s] %s\n"), quotearg_n(0, frm), quotearg_n(1, head));
        } else {
            screen_putf(_(" | %s\n"), quotearg(head));
        }
        free(msg);
        free(frm);
    }
    else if (len >= 13 && strncmp(buf, "$ConnectToMe ", 13) == 0) {
        struct sockaddr_in addr;

        buf += 13;
        if (strsep(&buf, " ") == NULL) {
            warn(_("Invalid $ConnectToMe message: Missing or invalid nick\n"));
            goto hub_handle_command_cleanup;
        }
        if (!parse_ip_and_port(buf, &addr, 0)) {
            warn(_("Invalid $ConnectToMe message: Invalid address specification.\n"));
            goto hub_handle_command_cleanup;
        }

        flag_putf(DC_DF_CONNECTIONS, _("Connecting to user on %s\n"), sockaddr_in_str(&addr));
        user_connection_new(&addr, -1);
    }
    else if (len >= 16 && strncmp(buf, "$RevConnectToMe ", 16) == 0) {
        char *nick;
        char *local_nick;
        DCUserInfo *ui;

        nick = strtok(buf+16, " ");
        if (nick == NULL) {
            warn(_("Invalid $RevConnectToMe message: Missing nick parameter\n"));
            goto hub_handle_command_cleanup;
        }
        if (strcmp(nick, hub_my_nick) == 0) {
            warn(_("Invalid $RevConnectToMe message: Remote nick is our nick\n"));
            goto hub_handle_command_cleanup;
        }
        local_nick = hub_to_main_string(nick);
        ui = (DCUserInfo*) hmap_get(hub_users, local_nick);
        if (ui == NULL) {
            warn(_("Invalid $RevConnectToMe message: Unknown user %s, ignoring\n"), quotearg(local_nick));
            free(local_nick);
            goto hub_handle_command_cleanup;
        }
        free(local_nick);

        if (ui->conn_count >= DC_USER_MAX_CONN) {
            warn(_("No more connections to user %s allowed.\n"), quotearg(ui->nick));
            goto hub_handle_command_cleanup;
        }

        if (!is_active) {
            if (ui->active_state == DC_ACTIVE_SENT_PASSIVE) {
                warn(_("User %s is also passive. Cannot establish connection.\n"), quotearg(ui->nick));
                /* We could set this to DC_ACTIVE_UNKNOWN too. This would mean
                 * we would keep sending RevConnectToMe next time the download
                 * queue is modified or some timer expired and told us to retry
                 * download. The remote would then send back RevConnectToMe
                 * and this would happen again. This way we would try again -
                 * maybe remote has become active since last time we checked?
                 * But no - DC++ only replies with RevConnectToMe to our first
                 * RevConnectToMe. After that it ignores them all.
                 */
                ui->active_state = DC_ACTIVE_RECEIVED_PASSIVE;
                if (hmap_remove(pending_userinfo, ui->nick) != NULL)
                    ui->refcount--;
                goto hub_handle_command_cleanup;
            }
            if (ui->active_state != DC_ACTIVE_RECEIVED_PASSIVE) {
                /* Inform remote that we are also passive. */
                if (!hub_putf("$RevConnectToMe %s %s|", hub_my_nick, nick))
                    goto hub_handle_command_cleanup;
            }
        }
        ui->active_state = DC_ACTIVE_RECEIVED_PASSIVE;

        if (!hub_connect_user(ui))
            goto hub_handle_command_cleanup;
    }
    else if ( (len >= 10 && strncmp(buf, "$NickList ", 10) == 0)
              || (len >= 8 && strncmp(buf, "$OpList ", 8) == 0) ) {
        char *nick;
        char *end;
        int oplist;
        char *conv_nick;

        if ( strncmp(buf, "$NickList ", 10) == 0) {
            nick = buf + 10;
            oplist = 0;
        } else {
            nick = buf + 8;
            oplist = 1;
        }

        for (; (end = strstr(nick, "$$")) != NULL; nick = end+2) {
            DCUserInfo *ui;
            *end = '\0';

            conv_nick = hub_to_main_string(nick);

            ui = (DCUserInfo*) hmap_get(hub_users, conv_nick);
            if (ui == NULL) {
                ui = user_info_new(conv_nick);
                hmap_put(hub_users, ui->nick, ui);
            }

            free(conv_nick);

            if (!ui->info_quered && (hub_extensions & HUB_EXT_NOGETINFO) == 0) {
                if (!hub_putf("$GetINFO %s %s|", nick, hub_my_nick))  {
                    goto hub_handle_command_cleanup;
                }
                ui->info_quered = true;
            }

            if (oplist)
                ui->is_operator = true;
        }
    }
    else if (len >= 6 && strncmp(buf, "$Quit ", 6) == 0) {
        DCUserInfo *ui;
        char *conv_nick = hub_to_main_string(buf+6);

        // I don't want these messages.
        //flag_putf(DC_DF_JOIN_PART, "User %s quits.\n", quotearg(conv_nick));
        ui = (DCUserInfo*) hmap_remove(hub_users, conv_nick);
        if (ui == NULL) {
            /* Some hubs print quit messages for users that never joined,
             * so print this as debug only.
             */
            flag_putf(DC_DF_DEBUG, _("Invalid $Quit message: Unknown user %s.\n"), quotearg(conv_nick));
        } else
            user_info_free(ui);
        free(conv_nick);
    }
    else if (len >= 8 && strncmp(buf, "$Search ", 8) == 0) {
        char *source;
        int parse_result = 0;
        DCSearchSelection sel;
        sel.patterns = NULL;

        buf += 8;
        source = strsep(&buf, " ");
        if (source == NULL) {
            warn(_("Invalid $Search message: Missing source specification.\n"));
            goto hub_handle_command_cleanup;
        }
        /* charset handling is in parse_search_selection */
        parse_result = parse_search_selection(buf, &sel);
        if (parse_result != 1) {
            if (sel.patterns != NULL) {
                int i = 0;
                for (i = 0; i < sel.patterncount; i++) {
                    search_string_free(sel.patterns+i);
                }
                free(sel.patterns);
            }
            if (parse_result == 0)
                warn(_("Invalid $Search message: %s: Invalid search specification.\n"), buf);
            goto hub_handle_command_cleanup;
        }
        if (strncmp(source, "Hub:", 4) == 0) {
            DCUserInfo *ui;
            char *conv_nick = hub_to_main_string(source+4);
            ui = (DCUserInfo*) hmap_get(hub_users, conv_nick);

            if (ui == NULL) {
                warn(_("Invalid $Search message: Unknown user %s.\n"), quotearg(conv_nick));
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                free(conv_nick);
                goto hub_handle_command_cleanup;
            }
            free(conv_nick);

            if (strcmp(ui->nick, my_nick) == 0) {
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                goto hub_handle_command_cleanup;
            }
            perform_inbound_search(&sel, ui, NULL);
            if (sel.patterns != NULL) {
                int i = 0;
                for (i = 0; i < sel.patterncount; i++) {
                    search_string_free(sel.patterns+i);
                }
                free(sel.patterns);
            }
        } else {
            struct sockaddr_in addr;
            if (!parse_ip_and_port(source, &addr, DC_CLIENT_UDP_PORT)) {
                warn(_("Invalid $Search message: Invalid address specification.\n"));
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                goto hub_handle_command_cleanup;
            }
            if (local_addr.sin_addr.s_addr == addr.sin_addr.s_addr && listen_port == ntohs(addr.sin_port)) {
                if (sel.patterns != NULL) {
                    int i = 0;
                    for (i = 0; i < sel.patterncount; i++) {
                        search_string_free(sel.patterns+i);
                    }
                    free(sel.patterns);
                }
                goto hub_handle_command_cleanup;
            }
            perform_inbound_search(&sel, NULL, &addr);
            if (sel.patterns != NULL) {
                int i = 0;
                for (i = 0; i < sel.patterncount; i++) {
                    search_string_free(sel.patterns+i);
                }
                free(sel.patterns);
            }
        }
    } else if (len >= 4 && strncmp(buf, "$SR ", 4) == 0) {
        handle_search_result(buf, len);
    } else if (len == 0) {
        /* Ignore empty commands. */
    }
hub_handle_command_cleanup:
    free(hub_my_nick);
}
Beispiel #11
0
int
main (int argc, char **argv)
{
    uint32_t c;
    char *config_file;
    bool custom_config;
    char *tmpdir;
    struct sigaction sigact;

    set_quoting_style(NULL, escape_quoting_style);

    if (setlocale(LC_ALL, "") == NULL)
        warn(_("%s: Cannot set locale: %s\n"), argv[0], errstr);
#ifdef ENABLE_NLS
    if (bindtextdomain(PACKAGE, LOCALEDIR) == NULL)
        warn(_("%s: Cannot bind message domain: %s\n"), argv[0], errstr);
    if (textdomain(PACKAGE) == NULL)
        warn(_("%s: Cannot set message domain: %s\n"), argv[0], errstr);
#endif

    custom_config = false;
    get_package_file("config", &config_file);

    while (true) {
        c = getopt_long(argc, argv, short_opts, long_opts, NULL);
        if (c == -1)
            break;

        switch (c) {
        case 'c': /* --config */
            custom_config = true;
            free(config_file);
            config_file = xstrdup(optarg);
            break;
        case 'n': /* --no-config */
            free(config_file);
            config_file = NULL;
            break;
        case HELP_OPT: /* --help */
            printf(_("Usage: %s [OPTION]...\n"), quotearg(argv[0]));
            puts(_("Start microdc, a command-line based Direct Connect client.\n"));
            printf(_("  -n, --no-config  do not read config file on startup\n"));
            printf(_("      --help       display this help and exit\n"));
            printf(_("      --version    output version information and exit\n"));
            printf(_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
            exit(EXIT_SUCCESS);
        case VERSION_OPT: /* --version */
            version_etc(stdout, NULL, PACKAGE, VERSION, /*"Oskar Liljeblad",*/ "Vladimir Chugunov", NULL);
            exit(EXIT_SUCCESS);
        default:
            exit(EXIT_FAILURE);
        }
    }

    if (pipe(signal_pipe) < 0) {
        warn(_("Cannot create pipe pair - %s\n"), errstr);
        goto cleanup;
    }

    main_process_id = getpid();
    sigact.sa_handler = signal_received;
    if (sigemptyset(&sigact.sa_mask) < 0) {
        warn(_("Cannot empty signal set - %s\n"), errstr);
        goto cleanup;
    }
    sigact.sa_flags = SA_RESTART;
#ifdef HAVE_STRUCT_SIGACTION_SA_RESTORER
    sigact.sa_restorer = NULL;
#endif
    /* Note: every signal registered with a non-ignore action here must
     * also be registered in user.c, either with an action or as ignored.
     */
    if (sigaction(SIGINT,  &sigact, NULL) < 0 ||
            sigaction(SIGTERM, &sigact, NULL) < 0 ||
            sigaction(SIGUSR1, &sigact, NULL) < 0 ||
            sigaction(SIGCHLD, &sigact, NULL) < 0) {
        warn(_("Cannot register signal handler - %s\n"), errstr);
        goto cleanup;
    }
    sigact.sa_handler = SIG_IGN;
    if (sigaction(SIGPIPE, &sigact, NULL) < 0) {
        warn(_("Cannot register signal handler - %s\n"), errstr);
        goto cleanup;
    }

    FD_ZERO(&read_fds);
    FD_ZERO(&write_fds);
    FD_SET(signal_pipe[0], &read_fds);
    /*FD_SET(STDIN_FILENO, &read_fds);*/

    hub_recvq = byteq_new(128);
    hub_sendq = byteq_new(128);
    user_conns = hmap_new();
    hub_users = hmap_new();
    pending_userinfo = hmap_new();

    set_main_charset("");
    set_hub_charset("");
    set_fs_charset("");

    user_conn_unknown_free = ptrv_new();
    delete_files = ptrv_new();
    delete_dirs = ptrv_new();
    search_udpmsg_out = ptrv_new();
    our_searches = ptrv_new();
    search_recvq = byteq_new(8192); // same size as DC++
    my_nick = xstrdup(PACKAGE);
    my_description = xstrdup("");
    my_email = xstrdup("");
    my_speed = xstrdup("56Kbps");
    my_tag = xasprintf("%s V:%s", PACKAGE, VERSION);
    download_dir = xstrdup(".");
    tmpdir = tempdir();
    if (tmpdir == NULL) {
        warn(_("Cannot find directory for temporary files - %s\n"), errstr);
        goto cleanup;
    }
    {
        char *filename = xasprintf("%s.%d", PACKAGE, getpid());
        listing_dir = catfiles(tmpdir, filename);
        free(filename);
    }
    ptrv_append(delete_dirs, xstrdup(listing_dir));
    is_active = false;
    listen_port = 0;
    if (!local_file_list_update_init())
        goto cleanup;
    if (!set_active(false, listen_port))
        goto cleanup;
    if (!enable_search())
        goto cleanup;
    my_ul_slots = 3;

    if (!lookup_init())
        goto cleanup;
    if (!file_list_parse_init())
        goto cleanup;
    command_init();

    if (!local_file_list_init()) {
        goto cleanup;
    }

    if (config_file != NULL) {
        run_script(config_file, !custom_config);
        free(config_file);
        config_file = NULL;
    }

    screen_prepare();

    while (running) {
        fd_set res_read_fds;
        fd_set res_write_fds;
        int res;
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;

        screen_redisplay_prompt();

        res_read_fds = read_fds;
        res_write_fds = write_fds;
        res = TEMP_FAILURE_RETRY(select(FD_SETSIZE, &res_read_fds, &res_write_fds, NULL, &tv));
        if (res < 0) {
            warn(_("Cannot select - %s\n"), errstr);
            break;
        }

        if (running && FD_ISSET(signal_pipe[0], &res_read_fds))
            read_signal_input();
        if (running && FD_ISSET(STDIN_FILENO, &res_read_fds))
            screen_read_input();
        if (running && listen_socket >= 0 && FD_ISSET(listen_socket, &res_read_fds))
            handle_listen_connection();
        if (running && hub_socket >= 0 && FD_ISSET(hub_socket, &res_read_fds))
            hub_input_available();
        if (running && hub_socket >= 0 && FD_ISSET(hub_socket, &res_write_fds))
            hub_now_writable();
        if (running)
            check_hub_activity();
        if (running && search_socket >= 0 && FD_ISSET(search_socket, &res_read_fds))
            search_input_available();
        if (running && search_socket >= 0 && FD_ISSET(search_socket, &res_write_fds))
            search_now_writable();
        if (running && FD_ISSET(lookup_request_mq->fd, &res_write_fds))
            lookup_request_fd_writable();
        if (running && FD_ISSET(lookup_result_mq->fd, &res_read_fds))
            lookup_result_fd_readable();
        if (running && FD_ISSET(parse_request_mq->fd, &res_write_fds))
            parse_request_fd_writable();
        if (running && FD_ISSET(parse_result_mq->fd, &res_read_fds))
            parse_result_fd_readable();
        if (running && FD_ISSET(update_request_mq->fd, &res_write_fds))
            update_request_fd_writable();
        if (running && FD_ISSET(update_result_mq->fd, &res_read_fds))
            update_result_fd_readable();

        if (running) {
            HMapIterator it;

            hmap_iterator(user_conns, &it);
            while (running && it.has_next(&it)) {
                DCUserConn *uc = (DCUserConn*) it.next(&it);
                if (uc->put_mq != NULL && FD_ISSET(uc->put_mq->fd, &res_write_fds))
                    user_request_fd_writable(uc);
                if (uc->get_mq != NULL && FD_ISSET(uc->get_mq->fd, &res_read_fds))
                    user_result_fd_readable(uc);
            }
        }
    }

cleanup:

    hub_disconnect();
    screen_finish();
    command_finish();
    local_file_list_update_finish();
    file_list_parse_finish();
    lookup_finish();

    byteq_free(hub_recvq);
    byteq_free(hub_sendq);
    hmap_free(hub_users); /* Emptied by hub_disconnect */
    hmap_free(pending_userinfo); /* Emptied by hub_disconnect */

    byteq_free(search_recvq);

    ptrv_foreach(user_conn_unknown_free, free);
    ptrv_free(user_conn_unknown_free);

    ptrv_foreach(search_udpmsg_out, free);
    ptrv_free(search_udpmsg_out);

    ptrv_foreach(our_searches, (PtrVForeachCallback) free_search_request);
    ptrv_free(our_searches);

    hmap_foreach_value(user_conns, (void (*) (void*)) user_conn_cancel);
    /* XXX: follow up and wait for user connections to die? */
    hmap_free(user_conns);

    if (our_filelist != NULL)
        filelist_free(our_filelist);

    set_main_charset(NULL);
    set_hub_charset(NULL);
    set_fs_charset(NULL);

    free(hub_name);
    free(my_nick);
    free(my_description);
    free(my_email);
    free(my_speed);
    free(my_tag);
    free(download_dir);
    free(listing_dir);

    if (delete_files != NULL) {
        for (c = 0; c < delete_files->cur; c++) {
            char *filename = (char*) delete_files->buf[c];
            struct stat st;

            if (stat(filename, &st) < 0) {
                if (errno != ENOENT)
                    warn(_("%s: Cannot get file status - %s\n"), quotearg(filename), errstr);
                free(filename);
                continue;
            }
            if (unlink(filename) < 0)
                warn(_("%s: Cannot remove file - %s\n"), quotearg(filename), errstr);
            free(filename);
        }
        ptrv_free(delete_files);
    }

    if (delete_dirs != NULL) {
        for (c = 0; c < delete_dirs->cur; c++) {
            char *filename = (char*) delete_dirs->buf[c];
            struct stat st;

            if (stat(filename, &st) < 0) {
                if (errno != ENOENT)
                    warn(_("%s: Cannot get file status - %s\n"), quotearg(filename), errstr);
                free(filename);
                continue;
            }
            if (rmdir(filename) < 0)
                warn(_("%s: Cannot remove file - %s\n"), quotearg(filename), errstr);
            free(filename);
        }
        ptrv_free(delete_dirs);
    }

    if (search_socket >= 0 && close(search_socket) < 0)
        warn(_("Cannot close search results socket - %s\n"), errstr);
    if (listen_socket >= 0 && close(listen_socket) < 0)
        warn(_("Cannot close user connections socket - %s\n"), errstr);
    if (signal_pipe[0] >= 0 && close(signal_pipe[0]) < 0)
        warn(_("Cannot close signal pipe - %s\n"), errstr);
    if (signal_pipe[1] >= 0 && close(signal_pipe[1]) < 0)
        warn(_("Cannot close signal pipe - %s\n"), errstr);

    free(config_file);

    exit(EXIT_SUCCESS);
}
Beispiel #12
0
static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
    struct usb_host_interface *desc;
    struct usb_endpoint_descriptor *endpoint;
    struct usb_device *dev;
    struct usb_hub *hub;
    unsigned long flags;

    desc = intf->altsetting + intf->act_altsetting;
    dev = interface_to_usbdev(intf);

    /* Some hubs have a subclass of 1, which AFAICT according to the */
    /*  specs is not defined, but it works */
    if ((desc->desc.bInterfaceSubClass != 0) &&
            (desc->desc.bInterfaceSubClass != 1)) {
descriptor_error:
        dev_err (&intf->dev, "bad descriptor, ignoring hub\n");
        return -EIO;
    }

    /* Multiple endpoints? What kind of mutant ninja-hub is this? */
    if (desc->desc.bNumEndpoints != 1) {
        goto descriptor_error;
    }

    endpoint = &desc->endpoint[0].desc;

    /* Output endpoint? Curiouser and curiouser.. */
    if (!(endpoint->bEndpointAddress & USB_DIR_IN)) {
        goto descriptor_error;
    }

    /* If it's not an interrupt endpoint, we'd better punt! */
    if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
            != USB_ENDPOINT_XFER_INT) {
        goto descriptor_error;
        return -EIO;
    }

    /* We found a hub */
    dev_info (hubdev (dev), "USB hub found\n");

    hub = kmalloc(sizeof(*hub), GFP_KERNEL);
    if (!hub) {
        err("couldn't kmalloc hub struct");
        return -ENOMEM;
    }

    memset(hub, 0, sizeof(*hub));

    INIT_LIST_HEAD(&hub->event_list);
    hub->intf = intf;
    init_MUTEX(&hub->khubd_sem);

    /* Record the new hub's existence */
    spin_lock_irqsave(&hub_event_lock, flags);
    INIT_LIST_HEAD(&hub->hub_list);
    list_add(&hub->hub_list, &hub_list);
    spin_unlock_irqrestore(&hub_event_lock, flags);

    usb_set_intfdata (intf, hub);

    if (hub_configure(hub, endpoint) >= 0) {
        strcpy (intf->dev.name, "Hub");
        return 0;
    }

    hub_disconnect (intf);
    return -ENODEV;
}