Example #1
0
/* non-blocking, returns socket descriptor or -1 if none available
 * NOTE:  This function assumes that the cursor of all buf's is zero,
 *        and it can call buf_reset(source, tag).
 */
int MPINU_rank_of_msg_avail_in_cache(int source, int tag) {
    if (source != MPI_ANY_SOURCE) {
      if (tag == MPI_ANY_TAG) {
	if (buf_avail(source, sizeof(struct msg_hdr)))
          return source;
      }
      else
	while (buf_avail(source, sizeof(struct msg_hdr))) {
	  struct msg_hdr *hdr = buf_peek(source, sizeof(struct msg_hdr));
	  if ( ntohl( hdr->tag ) == tag ) {
	    buf_reset(source, tag); /* clean up for next caller */
	    return source;
	  } else { /* Else skip header and body */
	    buf_skip( source, sizeof(struct msg_hdr) + ntohl(hdr->size) );
	  }
	}
      buf_reset(source, tag); /* clean up for next caller */
    }
    else /* else source == MPI_ANY_SOURCE */
      for (source = 0; source < MPINU_num_slaves; source++) {
	int rank = MPINU_rank_of_msg_avail_in_cache(source, tag);
	if (rank != -1)
	  return rank;
      }
    /* if no source had buf_avail, then no msg avail */
    return -1;
}
Example #2
0
/******************************************************************************
 Function to fetch a header from socket/file descriptor fd. The header may be
 of arbitrary length, since the function allocates as much memory as necessary
 for the header to fit. Most errors are handled.

 The header may be terminated by LF or CRLF.  If the character after LF is SP
 or HT (horizontal tab), the header spans to another line (continuation
 header), as per RFC2068.

 The trailing CRLF or LF are stripped from the header, and it is
 zero-terminated.
******************************************************************************/
uerr_t fetch_next_header(int fd, char **hdr, struct timeval * timeout)
{
  int i, bufsize, res;
  char next;

  bufsize = DYNAMIC_LINE_BUFFER;
  *hdr = kmalloc(bufsize);

  for (i = 0; 1; i++)
  {
    if (i > bufsize - 1)
      *hdr = krealloc(*hdr, (bufsize <<= 1));

    res = buf_readchar(fd, *hdr + i, timeout);

    if (res == 1)
    {
      if ((*hdr)[i] == '\n')
      {
	if (!(i == 0 || (i == 1 && (*hdr)[0] == '\r')))
	{
	  /* If the header is non-empty, we need to check if it continues on
	     to the other line. We do that by getting the next character
	     without actually downloading it (i.e. peeking it). */
	  res = buf_peek(fd, &next, timeout);

	  if (res == 0)
	    return HEOF;
	  else if (res == -1)
	    return HERR;

	  /* If the next character is SP or HT, just continue. */
	  if (next == '\t' || next == ' ')
	    continue;
	}

	/* The header ends. */
	(*hdr)[i] = '\0';

	/* Get rid of '\r'. */
	if (i > 0 && (*hdr)[i - 1] == '\r')
	  (*hdr)[i - 1] = '\0';

	break;
      }
    } else if (res == 0)
      return HEOF;
    else
      return HERR;
  }

  return HOK;
}
Example #3
0
/** Check <b>buf</b> for a variable-length cell according to the rules of link
 * protocol version <b>linkproto</b>.  If one is found, pull it off the buffer
 * and assign a newly allocated var_cell_t to *<b>out</b>, and return 1.
 * Return 0 if whatever is on the start of buf_t is not a variable-length
 * cell.  Return 1 and set *<b>out</b> to NULL if there seems to be the start
 * of a variable-length cell on <b>buf</b>, but the whole thing isn't there
 * yet. */
int
fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
{
  char hdr[VAR_CELL_MAX_HEADER_SIZE];
  var_cell_t *result;
  uint8_t command;
  uint16_t length;
  const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS;
  const int circ_id_len = get_circ_id_size(wide_circ_ids);
  const unsigned header_len = get_var_cell_header_size(wide_circ_ids);
  *out = NULL;
  if (buf_datalen(buf) < header_len)
    return 0;
  buf_peek(buf, hdr, header_len);

  command = get_uint8(hdr + circ_id_len);
  if (!(cell_command_is_var_length(command, linkproto)))
    return 0;

  length = ntohs(get_uint16(hdr + circ_id_len + 1));
  if (buf_datalen(buf) < (size_t)(header_len+length))
    return 1;

  result = var_cell_new(length);
  result->command = command;
  if (wide_circ_ids)
    result->circ_id = ntohl(get_uint32(hdr));
  else
    result->circ_id = ntohs(get_uint16(hdr));

  buf_drain(buf, header_len);
  buf_peek(buf, (char*) result->payload, length);
  buf_drain(buf, length);

  *out = result;
  return 1;
}
Example #4
0
/* On receiving a msg_hdr, we first do buf_reset(source, tag),
 * but _not_ on receiving a msg_body */
ssize_t MPINU_recv_msg_hdr_with_cache(int s, int tag,
				      void *buf, size_t len, int flags) {
    int msg_found = 0;
    int source = MPINU_rank_from_socket(s);
    buf_reset(source, tag);
    while ( !msg_found && buf_avail(source, len) ) {
      if ( ntohl( ((struct msg_hdr *)buf_peek(source, len))->tag ) == tag
	   || tag == MPI_ANY_TAG ) {
	buf_dequeue(source, buf, len, flags & MSG_PEEK);
	msg_found = 1;
      }
      else {
        int body_len;
	buf_skip(source, len); /* Skip header */
	body_len = ntohl( ((struct msg_hdr *)buf)->size );
	buf_skip(source, body_len); /* Skip body */
      }
    }
    if ( !msg_found )
      assert( !buf_avail(source, len) );
    while ( !msg_found ) {
      len = MPINU_recvall(MPINU_pg_array[source].sd, buf, len, flags);
      assert( len == sizeof(struct msg_hdr) );
      if ( ntohl( ((struct msg_hdr *)buf)->tag ) == tag
	   || tag == MPI_ANY_TAG )
	msg_found = 1;
      else if ( ! (flags & MSG_PEEK) ) {
#       define STATIC_SIZE 1000
        static char body_buf_array[STATIC_SIZE];
	void *body_buf;
	int body_len;
	buf_enqueue(source, buf, len);  /* Store header */
	/* After storing the header, we have to store the corresponding body */
	body_len = ntohl( ((struct msg_hdr *)buf)->size );
	if (body_len > STATIC_SIZE)
          body_buf = malloc(body_len);
	else
          body_buf = body_buf_array;
        body_len = MPINU_recvall(MPINU_pg_array[source].sd, body_buf, body_len,
			         flags);
	buf_enqueue(source, body_buf, body_len);  /* Store body */
	if (body_len > STATIC_SIZE)
          free(body_buf);
      }
    }
    return len;
}
Example #5
0
/** Read <b>buf</b>, which should contain an Extended ORPort message
 *  from a transport proxy. If well-formed, create and populate
 *  <b>out</b> with the Extended ORport message. Return 0 if the
 *  buffer was incomplete, 1 if it was well-formed and -1 if we
 *  encountered an error while parsing it.  */
int
fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
{
  char hdr[EXT_OR_CMD_HEADER_SIZE];
  uint16_t len;

  if (buf_datalen(buf) < EXT_OR_CMD_HEADER_SIZE)
    return 0;
  buf_peek(buf, hdr, sizeof(hdr));
  len = ntohs(get_uint16(hdr+2));
  if (buf_datalen(buf) < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
    return 0;
  *out = ext_or_cmd_new(len);
  (*out)->cmd = ntohs(get_uint16(hdr));
  (*out)->len = len;
  buf_drain(buf, EXT_OR_CMD_HEADER_SIZE);
  buf_get_bytes(buf, (*out)->body, len);
  return 1;
}
Example #6
0
static ssize_t smtp_parse(connection_t *c, int *code, char **reply) {
	char digits[4] = { 0, 0, 0, 0 }, *str;
	smtp_state_t fsm;
	int i, multi;
	unsigned char *p;
	size_t len;

	len = buf_len(c->buf);
	p = buf_peek(c->buf, 0, len);

	*code = -1; *reply = NULL;
	for(i = multi = fsm = 0; i < len && fsm != SMTP_DONE; i++) {
		if(fsm <= SMTP_DIGIT_3 && (*p < '0' || *p > '9')) return -1;
		else if(fsm == SMTP_MULTI && *p != ' ' && *p != '-') return -1;
		else switch(fsm++) {
		case SMTP_DIGIT_1: digits[0] = *p++; break;
		case SMTP_DIGIT_2: digits[1] = *p++; break;
		case SMTP_DIGIT_3: digits[2] = *p++; break;
		case SMTP_MULTI: multi = (*p++ == '-'); break;
		case SMTP_TEXT: if(*p++ != '\n') { fsm--; break; }
			/* fall through if newline */
		case SMTP_CRLF: fsm++; if(multi) fsm = SMTP_DIGIT_1;
			/* fall through if not multiline reply */
		case SMTP_DONE: break;
		}
	}

	if(fsm != SMTP_DONE)
		return 0;

	if(code) *code = atoi(digits);

	p = buf_read_next(c->buf, i, NULL);
	str = calloc(1, i + 1);
	if((*reply = str) != NULL) while(i--) {
		if(p[i] == '\r' || p[i] == '\n') str[i] = ' ';
		else str[i] = p[i];
	}

	buf_read_done(c->buf);

	return 1;
}
Example #7
0
void handle_sconn_read(void* arg) {
    LOG_TRACE("sconn read handle read.");

    sconn_t *sconn = (sconn_t *) arg;
    buf_t *buf = sconn->buf_recv;
    apr_socket_t *sock = sconn->pjob->pfd.desc.s;

    apr_status_t status = APR_SUCCESS;
    //status = apr_socket_recv(pfd->desc.s, (char *)buf, &n);
    status = buf_from_sock(buf, sock);

    // invoke msg handling.
    size_t sz_c = 0;
    while ((sz_c = buf_sz_content(buf)) > SZ_SZMSG) {
	uint32_t sz_msg = 0;
	SAFE_ASSERT(buf_peek(buf, (uint8_t*)&sz_msg, SZ_SZMSG) == SZ_SZMSG);
	SAFE_ASSERT(sz_msg > 0);
	if (sz_c >= sz_msg + SZ_SZMSG + SZ_MSGID) {
	    SAFE_ASSERT(buf_read(buf, (uint8_t*)&sz_msg, SZ_SZMSG) == SZ_SZMSG);
	    msgid_t msgid = 0;
	    SAFE_ASSERT(buf_read(buf, (uint8_t*)&msgid, SZ_MSGID) == SZ_MSGID);
    	    LOG_TRACE("next message size: %d, type: %x", (int32_t)sz_msg, (int32_t)msgid);

	    rpc_state *state = malloc(sizeof(rpc_state));
            state->sz_input = sz_msg;
            state->raw_input = malloc(sz_msg);
	    state->raw_output = NULL;
	    state->sz_output = 0;
            state->sconn = sconn;
	    state->msgid = msgid;

	    SAFE_ASSERT(buf_read(buf, (uint8_t*)state->raw_input, sz_msg) == sz_msg);
	    //            apr_thread_pool_push(tp_on_read_, (*(ctx->on_recv)), (void*)state, 0, NULL);
//            mpr_thread_pool_push(tp_read_, (void*)state);
//            apr_atomic_inc32(&n_data_recv_);
            //(*(ctx->on_recv))(NULL, state);
            // FIXME call

	    if (msgid & NEW_THREAD_CALL) {
		apr_thread_pool_t *tp = sconn->tp;
		SAFE_ASSERT(tp != NULL);
		apr_thread_pool_push(tp, msg_call, state, 0, NULL);
	    } else {
		msg_call(NULL, state);
	    }
	    
	} else {
	    break;
	}
    }

    if (status == APR_SUCCESS) {
	
    } else if (status == APR_EOF) {
        LOG_INFO("sconn poll on read, received eof, close socket");
	poll_mgr_remove_job(sconn->pjob->mgr, sconn->pjob);
    } else if (status == APR_ECONNRESET) {
        LOG_INFO("on read. connection reset, close socket");
	poll_mgr_remove_job(sconn->pjob->mgr, sconn->pjob);
        // TODO [improve] you may retry connect
    } else if (status == APR_EAGAIN) {
        LOG_TRACE("sconn poll on read, socket busy, resource temporarily unavailable.");
        // do nothing.
    } else {
        LOG_ERROR("unkown error on poll reading. %s\n", apr_strerror(status, malloc(100), 100));
        SAFE_ASSERT(0);
    }
}
Example #8
0
void handle_client_read(void *arg) {
    client_t *cli = (client_t*) arg;
    buf_t *buf = cli->buf_recv;
    apr_socket_t *sock = cli->pjob->pfd.desc.s;

    apr_status_t status = buf_from_sock(buf, sock);

    // invoke msg handling.
    size_t sz_c = 0;
    while ((sz_c = buf_sz_content(buf)) > SZ_SZMSG) {
	uint32_t sz_msg = 0;
	buf_peek(buf, (uint8_t*)&sz_msg, sizeof(sz_msg));
	if (sz_c >= sz_msg + SZ_SZMSG + SZ_MSGID) {
	    buf_read(buf, (uint8_t*)&sz_msg, SZ_SZMSG);
	    msgid_t msgid = 0;
	    buf_read(buf, (uint8_t*)&msgid, SZ_MSGID);

	    rpc_state *state = (rpc_state*)malloc(sizeof(rpc_state));
            state->sz_input = sz_msg;
            state->raw_input = (uint8_t *)malloc(sz_msg);
	    //            state->ctx = ctx;

	    buf_read(buf, state->raw_input, sz_msg);
//            state->ctx = ctx;
/*
            apr_thread_pool_push(tp_on_read_, (*(ctx->on_recv)), (void*)state, 0, NULL);
//            mpr_thread_pool_push(tp_read_, (void*)state);
*/
//            apr_atomic_inc32(&n_data_recv_);
            //(*(ctx->on_recv))(NULL, state);
            // FIXME call

            rpc_state* (**fun)(void*) = NULL;
            size_t sz;
            mpr_hash_get(cli->comm->ht, &msgid, SZ_MSGID, (void**)&fun, &sz);
            SAFE_ASSERT(fun != NULL);
            LOG_TRACE("going to call function %x", *fun);
	    //            ctx->n_rpc++;
	    //            ctx->sz_recv += n;
            (**fun)(state);

            free(state->raw_input);
            free(state);
	} else {
	    break;
	}
    }

    if (status == APR_SUCCESS) {
	
    } else if (status == APR_EOF) {
        LOG_DEBUG("cli poll on read, received eof, close socket");
	poll_mgr_remove_job(cli->pjob->mgr, cli->pjob);
    } else if (status == APR_ECONNRESET) {
        LOG_ERROR("cli poll on read. connection reset.");
	poll_mgr_remove_job(cli->pjob->mgr, cli->pjob);
        // TODO [improve] you may retry connect
    } else if (status == APR_EAGAIN) {
        LOG_DEBUG("cli poll on read. read socket busy, resource temporarily unavailable.");
        // do nothing.
    } else {
        LOG_ERROR("unkown error on poll reading. %s\n", 
		  apr_strerror(status, (char*)malloc(100), 100));
        SAFE_ASSERT(0);
    }
}