Пример #1
0
/* taken from rabbbitmq-c */
int amqp_simple_wait_method_list_noblock(amqp_connection_state_t state,
										 amqp_channel_t expected_channel,
										 amqp_method_number_t *expected_methods,
										 amqp_method_t *output,
										 struct timeval *timeout) {
	amqp_frame_t frame;
	int res = amqp_simple_wait_frame_noblock(state, &frame, timeout);

	if (AMQP_STATUS_OK != res) {
		return res;
	}

	if (AMQP_FRAME_METHOD != frame.frame_type ||
		expected_channel != frame.channel ||
		!amqp_id_in_reply_list(frame.payload.method.id, expected_methods)) {

		if (AMQP_CHANNEL_CLOSE_METHOD == frame.payload.method.id || AMQP_CONNECTION_CLOSE_METHOD == frame.payload.method.id) {

			*output = frame.payload.method;

			return AMQP_RESPONSE_SERVER_EXCEPTION;
		}

		return AMQP_STATUS_WRONG_METHOD;
	}

	*output = frame.payload.method;
	return AMQP_STATUS_OK;
}
Пример #2
0
amqp_rpc_reply_t
amqp_consume_message(amqp_connection_state_t state, amqp_envelope_t *envelope,
                     struct timeval *timeout, AMQP_UNUSED int flags)
{
  int res;
  amqp_frame_t frame;
  amqp_basic_deliver_t *delivery_method;
  amqp_rpc_reply_t ret;

  memset(&ret, 0, sizeof(amqp_rpc_reply_t));
  memset(envelope, 0, sizeof(amqp_envelope_t));

  res = amqp_simple_wait_frame_noblock(state, &frame, timeout);
  if (AMQP_STATUS_OK != res) {
    ret.reply_type = AMQP_RESPONSE_LIBRARY_EXCEPTION;
    ret.library_error = res;
    goto error_out1;
  }

  if (AMQP_FRAME_METHOD != frame.frame_type
      || AMQP_BASIC_DELIVER_METHOD != frame.payload.method.id) {
    amqp_put_back_frame(state, &frame);
    ret.reply_type = AMQP_RESPONSE_LIBRARY_EXCEPTION;
    ret.library_error = AMQP_STATUS_UNEXPECTED_STATE;
    goto error_out1;
  }

  delivery_method = frame.payload.method.decoded;

  envelope->channel = frame.channel;
  envelope->consumer_tag = amqp_bytes_malloc_dup(delivery_method->consumer_tag);
  envelope->delivery_tag = delivery_method->delivery_tag;
  envelope->redelivered = delivery_method->redelivered;
  envelope->exchange = amqp_bytes_malloc_dup(delivery_method->exchange);
  envelope->routing_key = amqp_bytes_malloc_dup(delivery_method->routing_key);

  if (amqp_bytes_malloc_dup_failed(envelope->consumer_tag) ||
      amqp_bytes_malloc_dup_failed(envelope->exchange) ||
      amqp_bytes_malloc_dup_failed(envelope->routing_key)) {
    ret.reply_type = AMQP_RESPONSE_LIBRARY_EXCEPTION;
    ret.library_error = AMQP_STATUS_NO_MEMORY;
    goto error_out2;
  }

  ret = amqp_read_message(state, envelope->channel, &envelope->message, 0);
  if (AMQP_RESPONSE_NORMAL != ret.reply_type) {
    goto error_out2;
  }

  ret.reply_type = AMQP_RESPONSE_NORMAL;
  return ret;

error_out2:
  amqp_bytes_free(envelope->routing_key);
  amqp_bytes_free(envelope->exchange);
  amqp_bytes_free(envelope->consumer_tag);
error_out1:
  return ret;
}
Пример #3
0
static int lc_bus_consume_message_atomic(amqp_connection_state_t *conn,
        uint32_t flag, amqp_envelope_t *envelope,
        amqp_frame_t *frame, amqp_message_t *message, char *buf, int buf_len)
{
    static struct timeval timeout = { tv_sec: RECV_TIMEOUT, tv_usec: 0 };
    size_t body_remaining = 0, offset = 0;
    int res = LC_BUS_OK;
    amqp_basic_deliver_t *deliver = NULL;

    if (!envelope || !frame || !message) {
        return 0;
    }

    amqp_maybe_release_buffers(*conn);
#if 0
    amqp_consume_message(*conn, envelope, &timeout, 0);
#endif

    res = amqp_simple_wait_frame_noblock(*conn, frame, &timeout);
    if (res) {
        LB_SYSLOG(LOG_ERR, "waiting for method frame, ret=%d.\n", res);
        if (res != AMQP_STATUS_TIMEOUT) {
            return -1;
        }
        return 0;
    }
    if (frame->frame_type != AMQP_FRAME_METHOD ||
        frame->payload.method.id != AMQP_BASIC_DELIVER_METHOD) {
        LB_SYSLOG(LOG_WARNING, "got frame type 0x%X (expect AMQP_FRAME_METHOD "
                "0x%X) method 0x%X (expect AMQP_BASIC_DELIVER_METHOD 0x%X), "
                "ignore this message.\n", frame->frame_type, AMQP_FRAME_METHOD,
                frame->payload.method.id, AMQP_BASIC_DELIVER_METHOD);
        return 0;
    }
    LB_SYSLOG(LOG_INFO, "got frame type 0x%X method 0x%X.\n",
            frame->frame_type, frame->payload.method.id);
    deliver = (amqp_basic_deliver_t *)frame->payload.method.decoded;

    res = amqp_simple_wait_frame_noblock(*conn, frame, &timeout);
    if (res) {
        LB_SYSLOG(LOG_ERR, "waiting for header frame, ret=%d\n", res);
        if (res != AMQP_STATUS_TIMEOUT) {
            return -1;
        }
        return 0;
    }
    if (frame->frame_type != AMQP_FRAME_HEADER) {
        LB_SYSLOG(LOG_ERR, "got frame type 0x%X (expect "
                "AMQP_FRAME_HEADER 0x%X).\n",
                frame->frame_type, AMQP_FRAME_HEADER);
        return 0;
    }
    body_remaining = frame->payload.properties.body_size;
    LB_SYSLOG(LOG_INFO, "got frame type 0x%X (AMQP_FRAME_HEADER), "
            "AMQP_FRAME_BODY len %zd\n",
            frame->frame_type, body_remaining);

    while (body_remaining) {
        res = amqp_simple_wait_frame_noblock(*conn, frame, &timeout);
        if (res) {
            LB_SYSLOG(LOG_ERR, "waiting for body frame, ret=%d\n", res);
            if (res != AMQP_STATUS_TIMEOUT) {
                return -1;
            }
            return 0;
        }
        if (frame->frame_type != AMQP_FRAME_BODY) {
            LB_SYSLOG(LOG_ERR, "expected header, got frame type 0x%X\n",
                    frame->frame_type);
            return 0;
        }
        LB_SYSLOG(LOG_DEBUG, "got body len %zd\n",
                frame->payload.body_fragment.len);

        memcpy(buf + offset, frame->payload.body_fragment.bytes,
                MINV(buf_len - offset, frame->payload.body_fragment.len));
        if (buf_len - offset < frame->payload.body_fragment.len) {
            offset = buf_len;
        } else {
            offset += frame->payload.body_fragment.len;
        }
        body_remaining -= frame->payload.body_fragment.len;
    }

    if (flag & LC_BUS_CONSUME_WITH_ACK) {
        res = amqp_basic_ack(
                    *conn,
                    LC_BUS_CHANNEL,
                    deliver->delivery_tag,
                    0  /* multiple */
                    );
        if (res) {
            LB_SYSLOG(LOG_ERR, "basic ack, channel=%u ret=%d\n",
                    LC_BUS_CHANNEL, res);
            return 0;
        }
    }

    if (buf_len == offset) {
        /* buffer is not enough */
        return 0;
    }
    return offset;
}
Пример #4
0
unsigned int rmq_receive()
{
  pwr_tStatus sts;
  int search_remtrans = 0;
  remtrans_item* remtrans;
  amqp_rpc_reply_t ret;
  amqp_envelope_t envelope;
  struct timeval t = { 2, 0 };
  rabbit_header header;
  int msg_received = 0;

  amqp_maybe_release_buffers(ctx->conn);
  ret = amqp_consume_message(ctx->conn, &envelope, &t, 0);
  switch (ret.reply_type) {
  case AMQP_RESPONSE_NORMAL: {
    break;
  }
  case AMQP_RESPONSE_NONE:
    return REM__SUCCESS;
  case AMQP_RESPONSE_SERVER_EXCEPTION:
    return REM__EXCEPTION;
  case AMQP_RESPONSE_LIBRARY_EXCEPTION:
    switch (ret.library_error) {
    case AMQP_STATUS_TIMEOUT: {
      amqp_destroy_envelope(&envelope);
      return REM__TIMEOUT;
    }
    case AMQP_STATUS_UNEXPECTED_STATE: {
      amqp_frame_t frame;

      sts = amqp_simple_wait_frame_noblock(ctx->conn, &frame, &t);
      if (sts == AMQP_STATUS_TIMEOUT) {
        printf("Wait frame timeout\n");
        return REM__EXCEPTION;
      } else if (sts == AMQP_STATUS_OK) {
        if (frame.frame_type == AMQP_FRAME_METHOD) {
          switch (frame.payload.method.id) {
          case AMQP_BASIC_ACK_METHOD:
            printf("Basic ack method called\n");
            break;
          case AMQP_BASIC_RETURN_METHOD:
            printf("Basic return method called\n");
            break;
          case AMQP_CHANNEL_CLOSE_METHOD:
            printf("Channel close method called\n");
            break;
          case AMQP_CONNECTION_CLOSE_METHOD:
            printf("Connection close method called\n");
            break;
          default:;
          }
        }
        return REM__EXCEPTION;
      } else
        return REM__EXCEPTION;
    }
    }
    // Reconnect...
    rmq_close(1);
    return REM__EXCEPTION;
  default:
    printf("Unknown Reply type: %d\n", ret.reply_type);
  }

  if (debug)
    printf("Received message %d\n", (int)envelope.message.body.len);

  if (envelope.message.body.len > 0 && rn_rmq->DisableHeader) {
    /* Header disabled, take the first receive remtrans object */

    remtrans = rn.remtrans;
    search_remtrans = 1;

    while (remtrans && search_remtrans) {
      /* Match? */
      if (remtrans->objp->Direction == REMTRANS_IN) {
        search_remtrans = false;
        sts = RemTrans_Receive(remtrans, (char*)envelope.message.body.bytes,
            envelope.message.body.len);
        msg_received = 1;
      }
      remtrans = (remtrans_item*)remtrans->next;
    }
    if (search_remtrans) {
      rn_rmq->ErrCount++;
      errh_Info("RabbitMQ Receive no remtrans %s", rn_rmq->ReceiveQueue);
    }
  } else if (envelope.message.body.len >= sizeof(rabbit_header)) {
    memcpy(&header, envelope.message.body.bytes, sizeof(rabbit_header));

    /* Convert the header to host byte order */
    header.msg_size = ntohs(header.msg_size);
    header.msg_id[0] = ntohs(header.msg_id[0]);
    header.msg_id[1] = ntohs(header.msg_id[1]);

    search_remtrans = 1;
    remtrans = rn.remtrans;
    while (remtrans && search_remtrans) {
      if (remtrans->objp->Address[0] == header.msg_id[0]
          && remtrans->objp->Address[1] == header.msg_id[1]
          && remtrans->objp->Direction == REMTRANS_IN) {
        search_remtrans = false;
        sts = RemTrans_Receive(remtrans,
            (char*)envelope.message.body.bytes + sizeof(rabbit_header),
            envelope.message.body.len);
        if (sts != STATUS_OK && sts != STATUS_BUFF)
          errh_Error("Error from RemTrans_Receive, queue %s, status %d",
              rn_rmq->ReceiveQueue, sts, 0);
        msg_received = 1;
        break;
      }
      remtrans = (remtrans_item*)remtrans->next;
    }
    if (search_remtrans) {
      rn_rmq->ErrCount++;
      errh_Info("No remtrans for received message, queue %s, class %d, type %d",
          rn_rmq->ReceiveQueue, header.msg_id[0], header.msg_id[1]);
    }
  }

  if (ctx->op->Acknowledge) {
    if (msg_received)
      amqp_basic_ack(ctx->conn, ctx->channel, envelope.delivery_tag, 0);
    else
      /* Requeue the message */
      amqp_basic_nack(ctx->conn, ctx->channel, envelope.delivery_tag, 0, 1);
  }
  amqp_destroy_envelope(&envelope);

  return sts;
}
Пример #5
0
int main(int argc, char** argv)
{
  int channel = 1, status = AMQP_STATUS_OK, cnfnlen;
  amqp_socket_t *socket = NULL;
  amqp_connection_state_t conn;
  amqp_rpc_reply_t ret;
  amqp_message_t *reply = NULL;
  amqp_frame_t frame;
  struct timeval timeout;
  MYSQL db_inst;
  char ch, *cnfname = NULL, *cnfpath = NULL;
  static const char* fname = "consumer.cnf";

  if((c_inst = calloc(1,sizeof(CONSUMER))) == NULL){
    fprintf(stderr, "Fatal Error: Cannot allocate enough memory.\n");
    return 1;
  }

  if(signal(SIGINT,sighndl) == SIG_IGN){
    signal(SIGINT,SIG_IGN);
  }

  while((ch = getopt(argc,argv,"c:"))!= -1){
    switch(ch){
    case 'c':
      cnfnlen = strlen(optarg);
      cnfpath = strdup(optarg);
      break;
    default:

      break;
    }
  }

  cnfname = calloc(cnfnlen + strlen(fname) + 1,sizeof(char));

  if(cnfpath){

    /**Config file path as argument*/
    strcpy(cnfname,cnfpath);
    if(cnfpath[cnfnlen-1] != '/'){
      strcat(cnfname,"/");
    }

  }  
  
  strcat(cnfname,fname);

  timeout.tv_sec = 1;
  timeout.tv_usec = 0;
  all_ok = 1;
  out_fd = NULL;



  /**Parse the INI file*/
  if(ini_parse(cnfname,handler,NULL) < 0){
    
    /**Try to parse a config in the same directory*/
    if(ini_parse(fname,handler,NULL) < 0){
      fprintf(stderr, "Fatal Error: Error parsing configuration file!\n");
    goto fatal_error;

    }
  }

  if(out_fd == NULL){
    out_fd = stdout;
  }

  fprintf(out_fd,"\n--------------------------------------------------------------\n");
  
  /**Confirm that all parameters were in the configuration file*/
  if(!c_inst->hostname||!c_inst->vhost||!c_inst->user||
     !c_inst->passwd||!c_inst->dbpasswd||!c_inst->queue||
     !c_inst->dbserver||!c_inst->dbname||!c_inst->dbuser){
    fprintf(stderr, "Fatal Error: Inadequate configuration file!\n");
    goto fatal_error;    
  }

  connectToServer(&db_inst);

  if((conn = amqp_new_connection()) == NULL || 
     (socket = amqp_tcp_socket_new(conn)) == NULL){
    fprintf(stderr, "Fatal Error: Cannot create connection object or socket.\n");
    goto fatal_error;
  }
  
  if(amqp_socket_open(socket, c_inst->hostname, c_inst->port)){
    fprintf(stderr, "RabbitMQ Error: Cannot open socket.\n");
    goto error;
  }
  
  ret = amqp_login(conn, c_inst->vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, c_inst->user, c_inst->passwd);

  if(ret.reply_type != AMQP_RESPONSE_NORMAL){
    fprintf(stderr, "RabbitMQ Error: Cannot login to server.\n");
    goto error;
  }

  amqp_channel_open(conn, channel);
  ret = amqp_get_rpc_reply(conn);

  if(ret.reply_type != AMQP_RESPONSE_NORMAL){
    fprintf(stderr, "RabbitMQ Error: Cannot open channel.\n");
    goto error;
  }  

  reply = malloc(sizeof(amqp_message_t));
  if(!reply){
    fprintf(stderr, "Error: Cannot allocate enough memory.\n");
    goto error;
  }
  amqp_basic_consume(conn,channel,amqp_cstring_bytes(c_inst->queue),amqp_empty_bytes,0,0,0,amqp_empty_table);

  while(all_ok){
     
    status = amqp_simple_wait_frame_noblock(conn,&frame,&timeout);

    /**No frames to read from server, possibly out of messages*/
    if(status == AMQP_STATUS_TIMEOUT){ 
      sleep(timeout.tv_sec);
      continue;
    }

    if(frame.payload.method.id == AMQP_BASIC_DELIVER_METHOD){

      amqp_basic_deliver_t* decoded = (amqp_basic_deliver_t*)frame.payload.method.decoded;
	
      amqp_read_message(conn,channel,reply,0);

      if(sendMessage(&db_inst,reply)){

	fprintf(stderr,"RabbitMQ Error: Received malformed message.\n");
	amqp_basic_reject(conn,channel,decoded->delivery_tag,0);	
	amqp_destroy_message(reply);

      }else{

	amqp_basic_ack(conn,channel,decoded->delivery_tag,0);
	amqp_destroy_message(reply);	

      }
      
    }else{
      fprintf(stderr,"RabbitMQ Error: Received method from server: %s\n",amqp_method_name(frame.payload.method.id));
      all_ok = 0;
      goto error;
    }

  }

  fprintf(out_fd,"Shutting down...\n");
 error:

  mysql_close(&db_inst);
  mysql_library_end();
  if(c_inst && c_inst->query_stack){

    while(c_inst->query_stack){
      DELIVERY* d = c_inst->query_stack->next;
      amqp_destroy_message(c_inst->query_stack->message);
      free(c_inst->query_stack);
      c_inst->query_stack = d;
    }

  }
  
  amqp_channel_close(conn, channel, AMQP_REPLY_SUCCESS);
  amqp_connection_close(conn, AMQP_REPLY_SUCCESS);
  amqp_destroy_connection(conn);
 fatal_error:

  if(out_fd){
    fclose(out_fd);
  }

  
  if(c_inst){

    free(c_inst->hostname);
    free(c_inst->vhost);
    free(c_inst->user);
    free(c_inst->passwd);
    free(c_inst->queue);
    free(c_inst->dbserver);
    free(c_inst->dbname);
    free(c_inst->dbuser);
    free(c_inst->dbpasswd);    
    free(c_inst);
    
  }

  
  
  return all_ok;
}
Пример #6
0
/* Threads */
void *janus_rmq_in_thread(void *data) {
	if(rmq_client == NULL) {
		JANUS_LOG(LOG_ERR, "No RabbitMQ connection??\n");
		return NULL;
	}
	JANUS_LOG(LOG_VERB, "Joining RabbitMQ in thread\n");

	struct timeval timeout;
	timeout.tv_sec = 0;
	timeout.tv_usec = 20000;
	amqp_frame_t frame;
	while(!rmq_client->destroy && !g_atomic_int_get(&stopping)) {
		amqp_maybe_release_buffers(rmq_client->rmq_conn);
		/* Wait for a frame */
		int res = amqp_simple_wait_frame_noblock(rmq_client->rmq_conn, &frame, &timeout);
		if(res != AMQP_STATUS_OK) {
			/* No data */
			if(res == AMQP_STATUS_TIMEOUT)
				continue;
			JANUS_LOG(LOG_VERB, "Error on amqp_simple_wait_frame_noblock: %d (%s)\n", res, amqp_error_string2(res));
			break;
		}
		/* We expect method first */
		JANUS_LOG(LOG_VERB, "Frame type %d, channel %d\n", frame.frame_type, frame.channel);
		if(frame.frame_type != AMQP_FRAME_METHOD)
			continue;
		JANUS_LOG(LOG_VERB, "Method %s\n", amqp_method_name(frame.payload.method.id));
		gboolean admin = FALSE;
		if(frame.payload.method.id == AMQP_BASIC_DELIVER_METHOD) {
			amqp_basic_deliver_t *d = (amqp_basic_deliver_t *)frame.payload.method.decoded;
			JANUS_LOG(LOG_VERB, "Delivery #%u, %.*s\n", (unsigned) d->delivery_tag, (int) d->routing_key.len, (char *) d->routing_key.bytes);
			/* Check if this is a Janus or Admin API request */
			if(rmq_client->admin_api_enabled) {
				if(d->routing_key.len == rmq_client->to_janus_admin_queue.len) {
					size_t i=0;
					admin = TRUE;
					char *inq = (char *)d->routing_key.bytes;
					char *expq = (char *)rmq_client->to_janus_admin_queue.bytes;
					for(i=0; i< d->routing_key.len; i++) {
						if(inq[i] != expq[i]) {
							admin = FALSE;
							break;
						}
					}
				}
			}
			JANUS_LOG(LOG_VERB, "  -- This is %s API request\n", admin ? "an admin" : "a Janus");
		}
		/* Then the header */
		amqp_simple_wait_frame(rmq_client->rmq_conn, &frame);
		JANUS_LOG(LOG_VERB, "Frame type %d, channel %d\n", frame.frame_type, frame.channel);
		if(frame.frame_type != AMQP_FRAME_HEADER)
			continue;
		amqp_basic_properties_t *p = (amqp_basic_properties_t *)frame.payload.properties.decoded;
		if(p->_flags & AMQP_BASIC_REPLY_TO_FLAG) {
			JANUS_LOG(LOG_VERB, "  -- Reply-to: %.*s\n", (int) p->reply_to.len, (char *) p->reply_to.bytes);
		}
		char *correlation = NULL;
		if(p->_flags & AMQP_BASIC_CORRELATION_ID_FLAG) {
			correlation = g_malloc0(p->correlation_id.len+1);
			sprintf(correlation, "%.*s", (int) p->correlation_id.len, (char *) p->correlation_id.bytes);
			JANUS_LOG(LOG_VERB, "  -- Correlation-id: %s\n", correlation);
		}
		if(p->_flags & AMQP_BASIC_CONTENT_TYPE_FLAG) {
			JANUS_LOG(LOG_VERB, "  -- Content-type: %.*s\n", (int) p->content_type.len, (char *) p->content_type.bytes);
		}
		/* And the body */
		uint64_t total = frame.payload.properties.body_size, received = 0;
		char *payload = g_malloc0(total+1), *index = payload;
		while(received < total) {
			amqp_simple_wait_frame(rmq_client->rmq_conn, &frame);
			JANUS_LOG(LOG_VERB, "Frame type %d, channel %d\n", frame.frame_type, frame.channel);
			if(frame.frame_type != AMQP_FRAME_BODY)
				break;
			sprintf(index, "%.*s", (int) frame.payload.body_fragment.len, (char *) frame.payload.body_fragment.bytes);
			received += frame.payload.body_fragment.len;
			index = payload+received;
		}
		JANUS_LOG(LOG_VERB, "Got %"SCNu64"/%"SCNu64" bytes from the %s queue (%"SCNu64")\n",
			received, total, admin ? "admin API" : "Janus API", frame.payload.body_fragment.len);
		JANUS_LOG(LOG_VERB, "%s\n", payload);
		/* Parse the JSON payload */
		json_error_t error;
		json_t *root = json_loads(payload, 0, &error);
		g_free(payload);
		/* Notify the core, passing both the object and, since it may be needed, the error
		 * We also specify the correlation ID as an opaque request identifier: we'll need it later */
		gateway->incoming_request(&janus_rabbitmq_transport, rmq_session, correlation, admin, root, &error);
	}
	JANUS_LOG(LOG_INFO, "Leaving RabbitMQ in thread\n");
	return NULL;
}