Back to index

tor  0.2.3.19-rc
Functions
cpuworker.h File Reference

Header file for cpuworker.c. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void cpu_init (void)
 Initialize the cpuworker subsystem.
void cpuworkers_rotate (void)
 Called when the onion key has changed and we need to spawn new cpuworkers.
int connection_cpu_finished_flushing (connection_t *conn)
 Called when we're done sending a request to a cpuworker.
int connection_cpu_reached_eof (connection_t *conn)
 If the cpuworker closes the connection, mark it as closed and spawn a new one as needed.
int connection_cpu_process_inbuf (connection_t *conn)
 Called when we get data from a cpuworker.
int assign_onionskin_to_cpuworker (connection_t *cpuworker, or_circuit_t *circ, char *onionskin)
 Try to tell a cpuworker to perform the public key operations necessary to respond to onionskin for the circuit circ.

Detailed Description

Header file for cpuworker.c.

Definition in file cpuworker.h.


Function Documentation

int assign_onionskin_to_cpuworker ( connection_t cpuworker,
or_circuit_t circ,
char *  onionskin 
)

Try to tell a cpuworker to perform the public key operations necessary to respond to onionskin for the circuit circ.

If cpuworker is defined, assert that he's idle, and use him. Else, look for an idle cpuworker and use him. If none idle, queue task onto the pending onion list and return. Return 0 if we successfully assign the task, or -1 on failure.

Definition at line 444 of file cpuworker.c.

{
  char qbuf[1];
  char tag[TAG_LEN];
  time_t now = approx_time();
  static time_t last_culled_cpuworkers = 0;

  /* Checking for wedged cpuworkers requires a linear search over all
   * connections, so let's do it only once a minute.
   */
#define CULL_CPUWORKERS_INTERVAL 60

  if (last_culled_cpuworkers + CULL_CPUWORKERS_INTERVAL <= now) {
    cull_wedged_cpuworkers();
    spawn_enough_cpuworkers();
    last_culled_cpuworkers = now;
  }

  if (1) {
    if (num_cpuworkers_busy == num_cpuworkers) {
      log_debug(LD_OR,"No idle cpuworkers. Queuing.");
      if (onion_pending_add(circ, onionskin) < 0) {
        tor_free(onionskin);
        return -1;
      }
      return 0;
    }

    if (!cpuworker)
      cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER,
                                               CPUWORKER_STATE_IDLE);

    tor_assert(cpuworker);

    if (!circ->p_conn) {
      log_info(LD_OR,"circ->p_conn gone. Failing circ.");
      tor_free(onionskin);
      return -1;
    }
    tag_pack(tag, circ->p_conn->_base.global_identifier,
             circ->p_circ_id);

    cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
    /* touch the lastwritten timestamp, since that's how we check to
     * see how long it's been since we asked the question, and sometimes
     * we check before the first call to connection_handle_write(). */
    cpuworker->timestamp_lastwritten = time(NULL);
    num_cpuworkers_busy++;

    qbuf[0] = CPUWORKER_TASK_ONION;
    connection_write_to_buf(qbuf, 1, cpuworker);
    connection_write_to_buf(tag, sizeof(tag), cpuworker);
    connection_write_to_buf(onionskin, ONIONSKIN_CHALLENGE_LEN, cpuworker);
    tor_free(onionskin);
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called when we're done sending a request to a cpuworker.

Definition at line 61 of file cpuworker.c.

{
  tor_assert(conn);
  tor_assert(conn->type == CONN_TYPE_CPUWORKER);
  return 0;
}

Here is the caller graph for this function:

Called when we get data from a cpuworker.

If the answer is not complete, wait for a complete answer. If the answer is complete, process it as appropriate.

Definition at line 130 of file cpuworker.c.

{
  char success;
  char buf[LEN_ONION_RESPONSE];
  uint64_t conn_id;
  circid_t circ_id;
  connection_t *tmp_conn;
  or_connection_t *p_conn = NULL;
  circuit_t *circ;

  tor_assert(conn);
  tor_assert(conn->type == CONN_TYPE_CPUWORKER);

  if (!connection_get_inbuf_len(conn))
    return 0;

  if (conn->state == CPUWORKER_STATE_BUSY_ONION) {
    if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE)
      return 0; /* not yet */
    tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE);

    connection_fetch_from_buf(&success,1,conn);
    connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);

    /* parse out the circ it was talking about */
    tag_unpack(buf, &conn_id, &circ_id);
    circ = NULL;
    tmp_conn = connection_get_by_global_id(conn_id);
    if (tmp_conn && !tmp_conn->marked_for_close &&
        tmp_conn->type == CONN_TYPE_OR)
      p_conn = TO_OR_CONN(tmp_conn);

    if (p_conn)
      circ = circuit_get_by_circid_orconn(circ_id, p_conn);

    if (success == 0) {
      log_debug(LD_OR,
                "decoding onionskin failed. "
                "(Old key or bad software.) Closing.");
      if (circ)
        circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
      goto done_processing;
    }
    if (!circ) {
      /* This happens because somebody sends us a destroy cell and the
       * circuit goes away, while the cpuworker is working. This is also
       * why our tag doesn't include a pointer to the circ, because we'd
       * never know if it's still valid.
       */
      log_debug(LD_OR,"processed onion for a circ that's gone. Dropping.");
      goto done_processing;
    }
    tor_assert(! CIRCUIT_IS_ORIGIN(circ));
    if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
                         buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
      log_warn(LD_OR,"onionskin_answer failed. Closing.");
      circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
      goto done_processing;
    }
    log_debug(LD_OR,"onionskin_answer succeeded. Yay.");
  } else {
    tor_assert(0); /* don't ask me to do handshakes yet */
  }

 done_processing:
  conn->state = CPUWORKER_STATE_IDLE;
  num_cpuworkers_busy--;
  if (conn->timestamp_created < last_rotation_time) {
    connection_mark_for_close(conn);
    num_cpuworkers--;
    spawn_enough_cpuworkers();
  } else {
    process_pending_task(conn);
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

If the cpuworker closes the connection, mark it as closed and spawn a new one as needed.

Definition at line 108 of file cpuworker.c.

{
  log_warn(LD_GENERAL,"Read eof. CPU worker died unexpectedly.");
  if (conn->state != CPUWORKER_STATE_IDLE) {
    /* the circ associated with this cpuworker will have to wait until
     * it gets culled in run_connection_housekeeping(), since we have
     * no way to find out which circ it was. */
    log_warn(LD_GENERAL,"...and it left a circuit queued; abandoning circ.");
    num_cpuworkers_busy--;
  }
  num_cpuworkers--;
  spawn_enough_cpuworkers(); /* try to regrow. hope we don't end up
                                spinning. */
  connection_mark_for_close(conn);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void cpu_init ( void  )

Initialize the cpuworker subsystem.

Definition at line 54 of file cpuworker.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void cpuworkers_rotate ( void  )

Called when the onion key has changed and we need to spawn new cpuworkers.

Close all currently idle cpuworkers, and mark the last rotation time as now.

Definition at line 92 of file cpuworker.c.

Here is the call graph for this function:

Here is the caller graph for this function: