예제 #1
0
파일: client.c 프로젝트: feelc/file-up-down
static int client_upload(int sock, char *file_path)
{
	assert(file_path != NULL);
	assert(sock >= 0);

	ldebug("upload file(%s), please wait a moment...", file_path);

	int file_size = 0;
	int total_len = 0;
	struct trans_data_t *ptrans = NULL;

	if (-1 == get_file_size(file_path, &file_size))
	{
		lerror("call get_file_size() failed");
		goto ERR;
	}
	if (!file_size)
	{
		lwarn("file is null, file_path: %s", file_path);
		goto ERR;
	}

	total_len = sizeof(struct trans_data_t) + file_size;
	ptrans = (struct trans_data_t *)calloc(1, total_len);
	if (NULL == ptrans)
	{
		lerror("malloc memory failed, err:%s", strerror(errno));
		abort();
	}
	ptrans->cmd = UD_UPLOAD;
	ptrans->data_len = file_size;
	snprintf(ptrans->filename, MAX_FILE_NAME_LENGTH-1, "%s", basename(file_path));
	ptrans->filename[MAX_FILE_NAME_LENGTH - 1] = '0';

	if (-1 == read_file(ptrans, file_path))
	{
		lerror("call read_data() failed, file_path: %s", file_path);
	}
	
	if (-1 == send_data(sock, ptrans, get_trans_data_t_size(ptrans)))
	{
		lerror("call send_data() failed, sock: %d, data_len: %d", sock, ptrans->data_len);
		return -1;
	}

	ldebug("upload file success");
	return 0;
ERR:
	lwarn("upload file failed");
	if (ptrans != NULL)
	{
		free(ptrans);
	}
	return -1;
}
예제 #2
0
파일: etypes.cpp 프로젝트: jfmrod/hpc-clust
etype etype::operator/(const etype &var)
{
  switch(type){
    case ET_INT: return(etype( *(int*)value / var.i() ));
    case ET_FLOAT: return(etype( *(float*)value / var.f() ));
    case ET_DOUBLE: return(etype( *(double*)value / var.d() ));
    case ET_CHAR: return(etype( *(char*)value / var.c() ));
    case ET_ESTR: lwarn("division not defined for string type"); return(estr());
    case ET_EARRAY: lwarn("division not defined for array type"); return(estrarray());
  }
  lwarn("undefined value");
  return(estr());
}
예제 #3
0
int ipc_accept(void)
{
	struct sockaddr_un saun;
	socklen_t slen = sizeof(struct sockaddr_un);

	if (ipc_sock != -1) {
		lwarn("New connection inbound when one already exists. Dropping old");
		close(ipc_sock);
	}

	ipc_sock = accept(listen_sock, (struct sockaddr *)&saun, &slen);
	if (ipc_sock < 0) {
		lerr("Failed to accept() from listen_sock (%d): %s",
			 listen_sock, strerror(errno));
		return -1;
	}

	/* reset the ipc event counter for each session */
	memset(&ipc_events, 0, sizeof(ipc_events));
	gettimeofday(&ipc_events.start, NULL);

	set_socket_buffers(ipc_sock);

	return ipc_sock;
}
예제 #4
0
파일: daemon.c 프로젝트: ageric/merlin
/* daemon-specific node manipulation */
static void post_process_nodes(void)
{
	uint i, x;

	ldebug("post processing %d masters, %d pollers, %d peers",
	       num_masters, num_pollers, num_peers);

	for (i = 0; i < num_nodes; i++) {
		merlin_node *node = node_table[i];

		if (!node) {
			lerr("node is null. i is %d. num_nodes is %d. wtf?", i, num_nodes);
			continue;
		}

		if (!node->sain.sin_port)
			node->sain.sin_port = htons(default_port);

		node->action = node_action_handler;

		node->ioc = iocache_create(MERLIN_IOC_BUFSIZE);
		if (node->ioc == NULL) {
			lerr("Failed to malloc(%i) for io cache for node %s. Aborting",
				 MERLIN_IOC_BUFSIZE, node->name);
		}

		/*
		 * this lets us support multiple merlin instances on
		 * a single system, but all instances on the same
		 * system will be marked at the same time, so we skip
		 * them on the second pass here.
		 */
		if (node->flags & MERLIN_NODE_FIXED_SRCPORT) {
			continue;
		}

		if (node->sain.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
			node->flags |= MERLIN_NODE_FIXED_SRCPORT;
			ldebug("Using fixed source-port for local %s node %s",
				   node_type(node), node->name);
			continue;
		}
		for (x = i + 1; x < num_nodes; x++) {
			merlin_node *nx = node_table[x];
			if (node->sain.sin_addr.s_addr == nx->sain.sin_addr.s_addr) {
				ldebug("Using fixed source-port for %s node %s",
				       node_type(node), node->name);
				ldebug("Using fixed source-port for %s node %s",
				       node_type(nx), nx->name);
				node->flags |= MERLIN_NODE_FIXED_SRCPORT;
				nx->flags |= MERLIN_NODE_FIXED_SRCPORT;

				if (node->sain.sin_port == nx->sain.sin_port) {
					lwarn("Nodes %s and %s have same ip *and* same port. Voodoo?",
					      node->name, nx->name);
				}
			}
		}
	}
}
예제 #5
0
파일: net.c 프로젝트: op5/merlin
static merlin_node *find_node(struct sockaddr_in *sain)
{
	uint i;
	merlin_node *first = NULL;

	if (!sain)
		return NULL;

	for (i = 0; i < num_nodes; i++) {
		merlin_node *node = node_table[i];
		unsigned short source_port = ntohs(sain->sin_port);
		unsigned short in_port = net_source_port(node);
		ldebug("FINDNODE: node->sain.sin_addr.s_addr: %d", node->sain.sin_addr.s_addr);
		if (node->sain.sin_addr.s_addr == sain->sin_addr.s_addr) {
			if (source_port == in_port) {
				/* perfect match */
				ldebug("Inbound connection matches %s exactly (%s:%d)",
				       node->name, inet_ntoa(sain->sin_addr), in_port);
				return node;
			}

			if (!first && !(node->flags & MERLIN_NODE_FIXED_SRCPORT))
				first = node;
		}
	}

	if (first) {
		lwarn("Inbound connection presumably from %s (%s:%d != %s:%d)",
			  first->name,
			  inet_ntoa(sain->sin_addr), ntohs(sain->sin_port),
			  inet_ntoa(first->sain.sin_addr), net_source_port(first));
	}

	return first;
}
예제 #6
0
파일: server.c 프로젝트: feelc/file-up-down
static int process_download(int sock, struct trans_data_t *ptrans)
{
	assert(ptrans != NULL);
	
	char file_path[MAX_FILE_PATH_LENGTH] = { '\0' };
	snprintf(file_path, MAX_FILE_PATH_LENGTH-1, "%s%s", STORE_SERVER_DATA_PATH, ptrans->filename);
	file_path[MAX_FILE_PATH_LENGTH-1] = '\0';

	if (-1 == get_file_size(file_path, &(ptrans->data_len)))
	{
		lwarn("call get_fail_size failed failed");
		goto FAIL;
	}

	ldebug("be called, filename: %s, size: %d", ptrans->filename, ptrans->data_len);

	if (-1 == read_file(ptrans, file_path))
	{
		lerror("read file failed, file_path: %s", file_path);
		goto FAIL;
	}

	if (-1 == send_data(sock, ptrans, get_trans_data_t_size(ptrans)))
	{
		lerror("send data failed, sock: %d, data_len: %d", sock, ptrans->data_len);
		goto ERR;
	}
	return 0;
FAIL:
	assert(0); //TODO:未完成
	return -1;
ERR:
	return -1;
}
예제 #7
0
파일: daemon.c 프로젝트: ageric/merlin
/*
 * import objects and status from objects.cache and status.log,
 * respecively
 */
static int import_objects_and_status(char *cfg, char *cache, char *status)
{
	char *cmd;
	int result = 0;

	/* don't bother if we're not using a datbase */
	if (!use_database)
		return 0;

	/* ... or if an import is already in progress */
	if (importer_pid) {
		lwarn("Import already in progress. Ignoring import event");
		return 0;
	}

	if (!import_program) {
		lerr("No import program specified. Ignoring import event");
		return 0;
	}

	asprintf(&cmd, "%s --nagios-cfg='%s' "
			 "--db-type='%s' --db-name='%s' --db-user='******' --db-pass='******' --db-host='%s' --db-conn_str='%s'",
			 import_program, cfg,
			 sql_db_type(), sql_db_name(), sql_db_user(), sql_db_pass(), sql_db_host(), sql_db_conn_str());
	if (cache && *cache) {
		char *cmd2 = cmd;
		asprintf(&cmd, "%s --cache='%s'", cmd2, cache);
		free(cmd2);

		if (db_track_current && status && *status) {
			cmd2 = cmd;
			asprintf(&cmd, "%s --status-log='%s'", cmd2, status);
			free(cmd2);
		}
	}

	if (sql_db_port()) {
		char *cmd2 = cmd;
		asprintf(&cmd, "%s --db-port='%u'", cmd2, sql_db_port());
		free(cmd2);
	}

	run_program("import", cmd, &importer_pid);
	free(cmd);

	/*
	 * If the import program started successfully, we
	 * ask the module to stall events until it's done
	 */
	if (importer_pid > 0) {
		ipc_send_ctrl(CTRL_STALL, CTRL_GENERIC);
	}

	return result;
}
예제 #8
0
파일: control.c 프로젝트: ageric/merlin
/*
 * Handles merlin control events inside the module. Control events
 * that relate to cross-host communication only never reaches this.
 */
void handle_control(merlin_node *node, merlin_event *pkt)
{
	const char *ctrl;
	if (!pkt) {
		lerr("handle_control() called with NULL packet");
		return;
	}

	ctrl = ctrl_name(pkt->hdr.code);
	linfo("Received control packet code %d (%s) from %s",
		  pkt->hdr.code, ctrl, node ? node->name : "local Merlin daemon");

	/* protect against bogus headers */
	if (!node && (pkt->hdr.code == CTRL_INACTIVE || pkt->hdr.code == CTRL_ACTIVE)) {
		lerr("Received %s with unknown node id %d", ctrl, pkt->hdr.selection);
		return;
	}
	switch (pkt->hdr.code) {
	case CTRL_INACTIVE:
		/*
		 * must memset() node->info before the disconnect handler
		 * so we discard it in the peer id calculation dance if
		 * we get data from it before it sends us a CTRL_ACTIVE
		 * packet
		 */
		memset(&node->info, 0, sizeof(node->info));
		node_set_state(node, STATE_NONE, "Received CTRL_INACTIVE");
		break;
	case CTRL_ACTIVE:
		/*
		 * Only mark the node as connected if the CTRL_ACTIVE packet
		 * checks out properly and the info is new. If it *is* new,
		 * we must re-do the peer assignment thing.
		 */
		if (!handle_ctrl_active(node, pkt)) {
			node_set_state(node, STATE_CONNECTED, "Received CTRL_ACTIVE");
			assign_peer_ids();
		}
		break;
	case CTRL_STALL:
		ctrl_stall_start();
		break;
	case CTRL_RESUME:
		ctrl_stall_stop();
		assign_peer_ids();
		break;
	case CTRL_STOP:
		linfo("Received (and ignoring) CTRL_STOP event. What voodoo is this?");
		break;
	default:
		lwarn("Unknown control code: %d", pkt->hdr.code);
	}
}
예제 #9
0
파일: etypes.cpp 프로젝트: jfmrod/hpc-clust
etype etype::operator+(const etype &var)
{
  switch(type){
    case ET_INT: return(etype( *(int*)value + var.i() ));
    case ET_FLOAT: return(etype( *(float*)value + var.f() ));
    case ET_DOUBLE: return(etype( *(double*)value + var.d() ));
    case ET_CHAR: return(etype( *(char*)value + var.c() ));
    case ET_ESTR: return(etype( *(estr*)value + var.s() ));
    case ET_EARRAY: return(etype( *(estrarray*)value + var ));
  }
  lwarn("undefined value");
  return(estr());
}
예제 #10
0
파일: etypes.cpp 프로젝트: jfmrod/hpc-clust
double etype::d() const
{
  switch(type){
    case ET_INT: return((double)*(int*)value);
    case ET_FLOAT: return((double)*(float*)value);
    case ET_DOUBLE: return(*(double*)value);
    case ET_CHAR:   return((double)*(char*)value);
    case ET_ESTR:   return((*(estr*)value).d());
    case ET_EARRAY:  return( (*(estrarray*)value)[0].d() );
  }
  lwarn("undefined value");
  return(0.0);
}
예제 #11
0
파일: etypes.cpp 프로젝트: jfmrod/hpc-clust
bool etype::cmp_value(void *_value) const
{
  switch(type){
    case ET_INT: return(COMPARE(value,_value,int));
    case ET_FLOAT: return(COMPARE(value,_value,float));
    case ET_DOUBLE: return(COMPARE(value,_value,double));
    case ET_CHAR: return(COMPARE(value,_value,char));
    case ET_ESTR: return(COMPARE(value,_value,estr));
//    case ET_EARRAY: return(COMPARE(value,_value,estrarray));
   default:
    lwarn("undefined value");	
  }
  return(false);
}
예제 #12
0
파일: etypes.cpp 프로젝트: jfmrod/hpc-clust
estrarray etype::a() const
{
  switch(type){
    case ET_INT:
    case ET_FLOAT:
    case ET_DOUBLE:
    case ET_CHAR:
    case ET_ESTR:
      return(estrarray(*this));
    case ET_EARRAY:  return(*(estrarray*)value);
  }

  lwarn("undefined value");
  return(estrarray());
}
예제 #13
0
void grok_db_compound(struct cfg_comp *c)
{
	unsigned int vi;

	use_database = 1;
	for (vi = 0; vi < c->vars; vi++) {
		struct cfg_var *v = c->vlist[vi];
		if (!strcmp(v->key, "log_report_data")) {
			db_log_reports = strtobool(v->value);
		} else if (!prefixcmp(v->key, "log_notification")) {
			db_log_notifications = strtobool(v->value);
		} else if (!prefixcmp(v->key, "track_current")) {
			lwarn("Option '%s' in the database compound is deprecated", v->key);
		} else if (!strcmp(v->key, "enabled")) {
			use_database = strtobool(v->value);
		} else {
			sql_config(v->key, v->value);
		}
	}
}
예제 #14
0
파일: hooks.c 프로젝트: op5/merlin
neb_cb_result * merlin_mod_hook(int cb, void *data)
{
	merlin_event pkt;
	int result = 0;
	neb_cb_result *neb_result = NULL;
	static time_t last_pulse = 0, last_flood_warning = 0;
	time_t now;

	if (!data) {
		lerr("eventbroker module called with NULL data");
		return neb_cb_result_create(-1);
	} else if (cb < 0 || cb > NEBCALLBACK_NUMITEMS) {
		lerr("merlin_mod_hook() called with invalid callback id");
		return neb_cb_result_create(-1);
	}

	/*
	 * must reset this here so events we don't check for
	 * dupes are always sent properly
	 */
	check_dupes = 0;

	/* self-heal nodes that have missed out on the fact that we're up */
	now = time(NULL);
	if(!last_pulse || now - last_pulse > 15)
		node_send_ctrl_active(&ipc, CTRL_GENERIC, &ipc.info);
	last_pulse = now;

	memset(&pkt, 0, sizeof(pkt));
	pkt.hdr.type = cb;
	pkt.hdr.selection = DEST_BROADCAST;
	switch (cb) {
	case NEBCALLBACK_NOTIFICATION_DATA:
		neb_result = hook_notification(&pkt, data);
		break;

	case NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA:
		result = hook_contact_notification_method(&pkt, data);
		break;

	case NEBCALLBACK_HOST_CHECK_DATA:
		result = hook_host_result(&pkt, data);
		break;

	case NEBCALLBACK_SERVICE_CHECK_DATA:
		result = hook_service_result(&pkt, data);
		break;

	case NEBCALLBACK_COMMENT_DATA:
		result = hook_comment(&pkt, data);
		break;

	case NEBCALLBACK_DOWNTIME_DATA:
		result = hook_downtime(&pkt, data);
		break;

	case NEBCALLBACK_EXTERNAL_COMMAND_DATA:
		result = hook_external_command(&pkt, data);
		break;

	case NEBCALLBACK_FLAPPING_DATA:
		/*
		 * flapping doesn't go to the network. check processing
		 * will generate flapping alerts on all nodes anyway,
		 */
	case NEBCALLBACK_PROGRAM_STATUS_DATA:
	case NEBCALLBACK_PROCESS_DATA:
		/* these make no sense to ship across the wire */
		pkt.hdr.code = MAGIC_NONET;
		result = send_generic(&pkt, data);
		break;

	case NEBCALLBACK_HOST_STATUS_DATA:
	case NEBCALLBACK_SERVICE_STATUS_DATA:
		/*
		 * Don't handle status updates coming from Naemon.
		 * If we need to send status updates for any reason it is done through
		 * Merlin directly. For normal state updates, we let each node handle
		 * check results so they keep their own state.
		 */
		break;
	case NEBCALLBACK_EVENT_HANDLER_DATA:
		result = hook_event_handler(&pkt, data);
		break;
	default:
		lerr("Unhandled callback '%s' in merlin_hook()", callback_name(cb));
	}

	if (neb_result != NULL) {
		/*
		 * We have a rich callback result, propagate return code
		 * to preserve flood warnings
		 */
		result = neb_cb_result_returncode(neb_result);
	}
	else {
		/*
		 * No rich callback result, create one
		 */
		neb_result = neb_cb_result_create_full(result, "No callback result description available");
	}

	if (result < 0 && now - last_flood_warning > 30) {
		/* log a warning every 30 seconds */
		last_flood_warning = now;
		lwarn("Daemon is flooded and backlogging failed");
	}


	return neb_result;
}
예제 #15
0
파일: daemon.c 프로젝트: ageric/merlin
/*
 * if the import isn't done yet waitpid() will return 0
 * and we won't touch importer_pid at all.
 */
static void reap_child_process(void)
{
	int status, pid, i;

	if (!num_children)
		return;

	pid = waitpid(-1, &status, WNOHANG);
	if (pid < 0) {
		if (errno == ECHILD) {
			/* no child running. Just reset */
			num_children = importer_pid = 0;
		} else {
			/* some random error. log it */
			lerr("waitpid(-1...) failed: %s", strerror(errno));
		}

		return;
	}

	/* child may not be done yet */
	if (!pid)
		return;

	/* we reaped an actual child, so decrement the counter */
	num_children--;

	/* looks like we reaped some helper we spawned */
	linfo("Child with pid %d successfully reaped", pid);

	if (pid == importer_pid) {
		if (WIFEXITED(status)) {
			if (!WEXITSTATUS(status)) {
				linfo("import program finished. Resuming normal operations");
			} else {
				lwarn("import program exited with return code %d", WEXITSTATUS(status));
			}
		} else {
			lerr("import program stopped or killed. That's a Bad Thing(tm)");
		}
		/* successfully reaped, so reset and resume */
		importer_pid = 0;
		ipc_send_ctrl(CTRL_RESUME, CTRL_GENERIC);
		return;
	}

	/* not the importer program, so it must be an oconf push or fetch */
	if (pid == csync.push.pid) {
		linfo("CSYNC: global push finished. Resuming");
		csync.push.pid = 0;
		return;
	} else if (pid == csync.fetch.pid) {
		linfo("CSYNC: global fetch finished. Resuming");
		csync.fetch.pid = 0;
		return;
	}

	for (i = 0; i < num_nodes; i++) {
		merlin_node *node = node_table[i];
		if (!node->csync)
			continue;

		if (pid == node->csync->push.pid) {
			linfo("CSYNC: push finished for %s", node->name);
			node->csync->push.pid = 0;
			return;
		} else if (pid == node->csync->fetch.pid) {
			linfo("CSYNC: fetch finished from %s", node->name);
			node->csync->fetch.pid = 0;
			return;
		}
	}
}
예제 #16
0
파일: net.c 프로젝트: op5/merlin
/*
 * Initiate a connection attempt to a node and mark it as PENDING.
 * Note that since we're using sockets in non-blocking mode (in order
 * to be able to effectively multiplex), the connection attempt will
 * never be completed in this function
 */
int net_try_connect(merlin_node *node)
{
	int sockopt = 1;
	struct sockaddr *sa = (struct sockaddr *)&node->sain;
	int should_log = 0;
	struct timeval connect_timeout = { MERLIN_CONNECT_TIMEOUT, 0 };
	struct sockaddr_in sain;
	time_t interval = MERLIN_CONNECT_INTERVAL;
	int result;

	/* don't log obsessively */
	if (node->last_conn_attempt_logged + 30 <= time(NULL)) {
		should_log = 1;
		node->last_conn_attempt_logged = time(NULL);
	}

	if (!(node->flags & MERLIN_NODE_CONNECT)) {
		if (should_log) {
			linfo("CONN: Connect attempt blocked by config to %s node %s",
				  node_type(node), node->name);
		}
		return 0;
	}

	/* don't bother trying to connect if it's pending or done */
	switch (node->state) {
	case STATE_NEGOTIATING:
		if (node->conn_sock < 0)
			break;
	case STATE_CONNECTED:
	case STATE_PENDING:
		ldebug("CONN: node %s state is %s, so bailing",
		       node->name, node_state_name(node->state));
		return 0;
	}

	/* if it's not yet time to connect, don't even try it */
	if (node->last_conn_attempt + interval > time(NULL)) {
		return 0;
	}

	/* mark the time so we can time it out ourselves if need be */
	node->last_conn_attempt = time(NULL);

	/* create the socket if necessary */
	if (node->conn_sock < 0) {
		node_disconnect(node, "struct reset (no real disconnect)");
		node->conn_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (node->conn_sock < 0) {
			lerr("CONN: Failed to obtain connection socket for node %s: %s", node->name, strerror(errno));
			lerr("CONN: Aborting connection attempt to %s", node->name);
			return -1;
		}
	}

	sa->sa_family = AF_INET;
	if (should_log) {
		linfo("CONN: Connecting to %s %s@%s:%d", node_type(node), node->name,
		      inet_ntoa(node->sain.sin_addr),
		      ntohs(node->sain.sin_port));
	}

	if (setsockopt(node->conn_sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int))) {
		ldebug("CONN: Failed to set sockopt SO_REUSEADDR for node %s connect socket %d: %s",
		       node->name, node->conn_sock, strerror(errno));
	}
	if (node->flags & MERLIN_NODE_FIXED_SRCPORT) {
		ldebug("CONN: Using fixed source port %d for %s node %s",
			   net_source_port(node), node_type(node), node->name);
		/*
		 * first we bind() to a local port calculated by our own
		 * listening port + the target port.
		 */
		sain.sin_family = AF_INET;
		sain.sin_port = htons(net_source_port(node));
		sain.sin_addr.s_addr = 0;
		if (bind(node->conn_sock, (struct sockaddr *)&sain, sizeof(sain))) {
			lerr("CONN: Failed to bind() outgoing socket %d for node %s to port %d: %s",
				 node->conn_sock, node->name, ntohs(sain.sin_port), strerror(errno));
			if (errno == EBADF || errno == EADDRINUSE) {
				close(node->conn_sock);
				node->conn_sock = -1;
				return -1;
			}
		}
	}

	if (fcntl(node->conn_sock, F_SETFL, O_NONBLOCK) < 0) {
		lwarn("CONN: Failed to set socket %d for %s non-blocking: %s", node->conn_sock, node->name, strerror(errno));
	}
	if (setsockopt(node->conn_sock, SOL_SOCKET, SO_RCVTIMEO,
	               &connect_timeout, sizeof(connect_timeout)) < 0)
	{
		ldebug("CONN: Failed to set receive timeout for %d, node %s: %s",
		       node->conn_sock, node->name, strerror(errno));
	}
	if (setsockopt(node->conn_sock, SOL_SOCKET, SO_SNDTIMEO,
	               &connect_timeout, sizeof(connect_timeout)) < 0)
	{
		ldebug("CONN: Failed to set send timeout for %d, node %s: %s",
		       node->conn_sock, node->name, strerror(errno));
	}

	if (connect(node->conn_sock, sa, sizeof(struct sockaddr_in)) < 0) {
		if (errno == EINPROGRESS) {
			/*
			 * non-blocking socket and connect() can't be completed
			 * immediately (ie, the normal case)
			 */
			node_set_state(node, STATE_PENDING, "Connecting");
		}
		else if (errno == EALREADY) {
			ldebug("CONN: Connect already in progress for socket %d to %s. This should never happen", node->conn_sock, node->name);
			node_set_state(node, STATE_PENDING, "connect() already in progress");
		} else {
			/* a real connection error */
			ldebug("CONN: connect() via %d to %s failed: %s",
			       node->conn_sock, node->name, strerror(errno));
			close(node->conn_sock);
			node->conn_sock = -1;
			if (should_log) {
				node_disconnect(node, "CONN: connect() failed to %s node '%s' (%s:%d): %s",
								node_type(node), node->name,
								inet_ntoa(node->sain.sin_addr),
								ntohs(node->sain.sin_port),
								strerror(errno));
			} else {
				node_disconnect(node, NULL);
			}
			return -1;
		}
	}

	result = iobroker_register_out(nagios_iobs, node->conn_sock, node, conn_writable);
	if (result < 0) {
		node_disconnect(node, "IOB: Failed to register %s connect socket %d with iobroker: %s",
		                node->name, node->conn_sock, iobroker_strerror(result));
		close(node->conn_sock);
		node->conn_sock = -1;
		return -1;
	}

	return 0;
}
예제 #17
0
파일: cs4231a.c 프로젝트: ft-/ox820-qemu
static void cs_write (void *opaque, target_phys_addr_t addr,
                      uint64_t val64, unsigned size)
{
    CSState *s = opaque;
    uint32_t saddr, iaddr, val;

    saddr = addr;
    val = val64;

    switch (saddr) {
    case Index_Address:
        if (!(s->regs[Index_Address] & MCE) && (val & MCE)
            && (s->dregs[Interface_Configuration] & (3 << 3)))
            s->aci_counter = conf.aci_counter;

        s->regs[Index_Address] = val & ~(1 << 7);
        break;

    case Index_Data:
        if (!(s->dregs[MODE_And_ID] & MODE2))
            iaddr = s->regs[Index_Address] & 0x0f;
        else
            iaddr = s->regs[Index_Address] & 0x1f;

        switch (iaddr) {
        case RESERVED:
        case RESERVED_2:
        case RESERVED_3:
            lwarn ("attempt to write %#x to reserved indirect register %d\n",
                   val, iaddr);
            break;

        case FS_And_Playback_Data_Format:
            if (s->regs[Index_Address] & MCE) {
                cs_reset_voices (s, val);
            }
            else {
                if (s->dregs[Alternate_Feature_Status] & PMCE) {
                    val = (val & ~0x0f) | (s->dregs[iaddr] & 0x0f);
                    cs_reset_voices (s, val);
                }
                else {
                    lwarn ("[P]MCE(%#x, %#x) is not set, val=%#x\n",
                           s->regs[Index_Address],
                           s->dregs[Alternate_Feature_Status],
                           val);
                    break;
                }
            }
            s->dregs[iaddr] = val;
            break;

        case Interface_Configuration:
            val &= ~(1 << 5);   /* D5 is reserved */
            s->dregs[iaddr] = val;
            if (val & PPIO) {
                lwarn ("PIO is not supported (%#x)\n", val);
                break;
            }
            if (val & PEN) {
                if (!s->dma_running) {
                    cs_reset_voices (s, s->dregs[FS_And_Playback_Data_Format]);
                }
            }
            else {
                if (s->dma_running) {
                    DMA_release_DREQ (s->dma);
                    AUD_set_active_out (s->voice, 0);
                    s->dma_running = 0;
                }
            }
            break;

        case Error_Status_And_Initialization:
            lwarn ("attempt to write to read only register %d\n", iaddr);
            break;

        case MODE_And_ID:
            dolog ("val=%#x\n", val);
            if (val & MODE2)
                s->dregs[iaddr] |= MODE2;
            else
                s->dregs[iaddr] &= ~MODE2;
            break;

        case Alternate_Feature_Enable_I:
            if (val & TE)
                lerr ("timer is not yet supported\n");
            s->dregs[iaddr] = val;
            break;

        case Alternate_Feature_Status:
            if ((s->dregs[iaddr] & PI) && !(val & PI)) {
                /* XXX: TI CI */
                qemu_irq_lower (s->pic);
                s->regs[Status] &= ~INT;
            }
            s->dregs[iaddr] = val;
            break;

        case Version_Chip_ID:
            lwarn ("write to Version_Chip_ID register %#x\n", val);
            s->dregs[iaddr] = val;
            break;

        default:
            s->dregs[iaddr] = val;
            break;
        }
        dolog ("written value %#x to indirect register %d\n", val, iaddr);
        break;

    case Status:
        if (s->regs[Status] & INT) {
            qemu_irq_lower (s->pic);
        }
        s->regs[Status] &= ~INT;
        s->dregs[Alternate_Feature_Status] &= ~(PI | CI | TI);
        break;

    case PIO_Data:
        lwarn ("attempt to write value %#x to PIO register\n", val);
        break;
    }
}
예제 #18
0
파일: client.c 프로젝트: feelc/file-up-down
int main(int argc, char **argv)
{
	int ch = 0;
	int cmd = UD_MIN;
	int sock = -1;
	char *file = NULL;
	char * const short_options = "uds:t:";
	struct option log_options[] = {
		{ "upload",		0,	NULL,	'u' },
		{ "download",	0,	NULL,	'd' },
		{ "file",	1,	NULL,	's' },
	};

	if (argc < 2)
	{
		help();
		return -1;
	}

	while ((ch = getopt_long(argc, argv, short_options, log_options, NULL)) != EOF)
	{
		switch (ch)
		{
		case 'u':
			cmd = UD_UPLOAD;
			break;
		case 'd':
			cmd = UD_DOWNLOAD;
			break;
		case 's':
			file = optarg;
			break;
			break;
		default:
			lwarn("unknown argument, %s", argv[optind]);
			break;
		}
	}

	if (-1 == check_param(cmd, file))
	{
		lerror("check param failed");
		help();
		goto ERR;
	}

	linfo("cmd: %s, file: %s", string_cmd(cmd), file);

	sock = create_client_socket();
	if (-1 == sock)
	{
		lerror("call create_and_connect_socket() failed");
		goto ERR;
	}
	ldebug("create socket success, sock: %d", sock);

	switch (cmd)
	{
	case UD_UPLOAD:
		(void)client_upload(sock, file);
		break;
	case UD_DOWNLOAD:
		(void)client_download(sock, file);
		break;
	default:
		break;
	}

	return 0;
ERR:
	if (sock >= 0)
	{
		close(sock);
	}
	return -1;
}
예제 #19
0
파일: main.c 프로젝트: alagoutte/flex
void check_options (void)
{
	int     i;
    const char * m4 = NULL;

	if (lex_compat) {
		if (C_plus_plus)
			flexerror (_("Can't use -+ with -l option"));

		if (fulltbl || fullspd)
			flexerror (_("Can't use -f or -F with -l option"));

		if (reentrant || bison_bridge_lval)
			flexerror (_
				   ("Can't use --reentrant or --bison-bridge with -l option"));

		yytext_is_array = true;
		do_yylineno = true;
		use_read = false;
	}


#if 0
	/* This makes no sense whatsoever. I'm removing it. */
	if (do_yylineno)
		/* This should really be "maintain_backup_tables = true" */
		reject_really_used = true;
#endif

	if (csize == unspecified) {
		if ((fulltbl || fullspd) && !useecs)
			csize = DEFAULT_CSIZE;
		else
			csize = CSIZE;
	}

	if (interactive == unspecified) {
		if (fulltbl || fullspd)
			interactive = false;
		else
			interactive = true;
	}

	if (fulltbl || fullspd) {
		if (usemecs)
			flexerror (_
				   ("-Cf/-CF and -Cm don't make sense together"));

		if (interactive)
			flexerror (_("-Cf/-CF and -I are incompatible"));

		if (lex_compat)
			flexerror (_
				   ("-Cf/-CF are incompatible with lex-compatibility mode"));


		if (fulltbl && fullspd)
			flexerror (_
				   ("-Cf and -CF are mutually exclusive"));
	}

	if (C_plus_plus && fullspd)
		flexerror (_("Can't use -+ with -CF option"));

	if (C_plus_plus && yytext_is_array) {
		lwarn (_("%array incompatible with -+ option"));
		yytext_is_array = false;
	}

	if (C_plus_plus && (reentrant))
		flexerror (_("Options -+ and --reentrant are mutually exclusive."));

	if (C_plus_plus && bison_bridge_lval)
		flexerror (_("bison bridge not supported for the C++ scanner."));


	if (useecs) {		/* Set up doubly-linked equivalence classes. */

		/* We loop all the way up to csize, since ecgroup[csize] is
		 * the position used for NUL characters.
		 */
		ecgroup[1] = NIL;

		for (i = 2; i <= csize; ++i) {
			ecgroup[i] = i - 1;
			nextecm[i - 1] = i;
		}

		nextecm[csize] = NIL;
	}

	else {
		/* Put everything in its own equivalence class. */
		for (i = 1; i <= csize; ++i) {
			ecgroup[i] = i;
			nextecm[i] = BAD_SUBSCRIPT;	/* to catch errors */
		}
	}

    if (extra_type)
        buf_m4_define( &m4defs_buf, "M4_EXTRA_TYPE_DEFS", extra_type);

	if (!use_stdout) {
		FILE   *prev_stdout;

		if (!did_outfilename) {
			char   *suffix;

			if (C_plus_plus)
				suffix = "cc";
			else
				suffix = "c";

			snprintf (outfile_path, sizeof(outfile_path), outfile_template,
				 prefix, suffix);

			outfilename = outfile_path;
		}

		prev_stdout = freopen (outfilename, "w+", stdout);

		if (prev_stdout == NULL)
			lerr (_("could not create %s"), outfilename);

		outfile_created = 1;
	}


    /* Setup the filter chain. */
    output_chain = filter_create_int(NULL, filter_tee_header, headerfilename);
    if ( !(m4 = getenv("M4"))) {
	    char *slash;
		m4 = M4;
		if ((slash = strrchr(M4, '/')) != NULL) {
			m4 = slash+1;
			/* break up $PATH */
			const char *path = getenv("PATH");
			if (!path) {
				m4 = M4;
			} else {
				int m4_length = strlen(m4);
				do {
					size_t length = strlen(path);
					struct stat sbuf;

					const char *endOfDir = strchr(path, ':');
					if (!endOfDir)
						endOfDir = path+length;

					{
						char *m4_path = calloc(endOfDir-path + 1 + m4_length + 1, 1);

						memcpy(m4_path, path, endOfDir-path);
						m4_path[endOfDir-path] = '/';
						memcpy(m4_path + (endOfDir-path) + 1, m4, m4_length + 1);
						if (stat(m4_path, &sbuf) == 0 &&
							(S_ISREG(sbuf.st_mode)) && sbuf.st_mode & S_IXUSR) {
							m4 = m4_path;
							break;
						}
						free(m4_path);
					}
					path = endOfDir+1;
				} while (path[0]);
				if (!path[0])
				    m4 = M4;
			}
		}
	}
    filter_create_ext(output_chain, m4, "-P", 0);
    filter_create_int(output_chain, filter_fix_linedirs, NULL);

    /* For debugging, only run the requested number of filters. */
    if (preproc_level > 0) {
        filter_truncate(output_chain, preproc_level);
        filter_apply_chain(output_chain);
    }
    yyout = stdout;


	/* always generate the tablesverify flag. */
	buf_m4_define (&m4defs_buf, "M4_YY_TABLES_VERIFY", tablesverify ? "1" : "0");
	if (tablesext)
		gentables = false;

	if (tablesverify)
		/* force generation of C tables. */
		gentables = true;


	if (tablesext) {
		FILE   *tablesout;
		struct yytbl_hdr hdr;
		char   *pname = 0;
		size_t  nbytes = 0;

		buf_m4_define (&m4defs_buf, "M4_YY_TABLES_EXTERNAL", NULL);

		if (!tablesfilename) {
			nbytes = strlen (prefix) + strlen (tablesfile_template) + 2;
			tablesfilename = pname = calloc(nbytes, 1);
			snprintf (pname, nbytes, tablesfile_template, prefix);
		}

		if ((tablesout = fopen (tablesfilename, "w")) == NULL)
			lerr (_("could not create %s"), tablesfilename);
		free(pname);
		tablesfilename = 0;

		yytbl_writer_init (&tableswr, tablesout);

		nbytes = strlen (prefix) + strlen ("tables") + 2;
		tablesname = calloc(nbytes, 1);
		snprintf (tablesname, nbytes, "%stables", prefix);
		yytbl_hdr_init (&hdr, flex_version, tablesname);

		if (yytbl_hdr_fwrite (&tableswr, &hdr) <= 0)
			flexerror (_("could not write tables header"));
	}

	if (skelname && (skelfile = fopen (skelname, "r")) == NULL)
		lerr (_("can't open skeleton file %s"), skelname);

	if (reentrant) {
        buf_m4_define (&m4defs_buf, "M4_YY_REENTRANT", NULL);
		if (yytext_is_array)
			buf_m4_define (&m4defs_buf, "M4_YY_TEXT_IS_ARRAY", NULL);
	}

	if ( bison_bridge_lval)
		buf_m4_define (&m4defs_buf, "M4_YY_BISON_LVAL", NULL);

	if ( bison_bridge_lloc)
        buf_m4_define (&m4defs_buf, "<M4_YY_BISON_LLOC>", NULL);

    if (strchr(prefix, '[') || strchr(prefix, ']'))
        flexerror(_("Prefix cannot include '[' or ']'"));
    buf_m4_define(&m4defs_buf, "M4_YY_PREFIX", prefix);

	if (did_outfilename)
		line_directive_out (stdout, 0);

	if (do_yylineno)
		buf_m4_define (&m4defs_buf, "M4_YY_USE_LINENO", NULL);

	/* Create the alignment type. */
	buf_strdefine (&userdef_buf, "YY_INT_ALIGNED",
		       long_align ? "long int" : "short int");

    /* Define the start condition macros. */
    {
        struct Buf tmpbuf;
        buf_init(&tmpbuf, sizeof(char));
        for (i = 1; i <= lastsc; i++) {
             char *str, *fmt = "#define %s %d\n";
             size_t strsz;

             strsz = strlen(fmt) + strlen(scname[i]) + (size_t)(1 + ceil (log10(i))) + 2;
             str = malloc(strsz);
             if (!str)
               flexfatal(_("allocation of macro definition failed"));
             snprintf(str, strsz, fmt,      scname[i], i - 1);
             buf_strappend(&tmpbuf, str);
             free(str);
        }
        buf_m4_define(&m4defs_buf, "M4_YY_SC_DEFS", tmpbuf.elts);
        buf_destroy(&tmpbuf);
    }

    /* This is where we begin writing to the file. */

    /* Dump the %top code. */
    if( top_buf.elts)
        outn((char*) top_buf.elts);

    /* Dump the m4 definitions. */
    buf_print_strings(&m4defs_buf, stdout);
    m4defs_buf.nelts = 0; /* memory leak here. */

    /* Place a bogus line directive, it will be fixed in the filter. */
    if (gen_line_dirs)
        outn("#line 0 \"M4_YY_OUTFILE_NAME\"\n");

	/* Dump the user defined preproc directives. */
	if (userdef_buf.elts)
		outn ((char *) (userdef_buf.elts));

	skelout ();
	/* %% [1.0] */
}
예제 #20
0
void eseqclusterData::getCluster(const eintarray& seqs, eintarray& seqcluster,float& cdist)
{
  if (seqs.size()<2) { lwarn("seqs is empty or contains only one sequence: "+estr(seqs.size())); return; }
  if (mergearr.size()==0 || count==0) { lwarn("empty merge array, load the cluster merge file"); return; }

  int i,j,k;

  earray<eintarray> otus;
  otus.init(count);
  eintarray otuarr;
  otuarr.init(count);
  for (i=0; i<otuarr.size(); ++i){
    otuarr[i]=i;
    otus[i].add(i);
  }

//  cout << "# finding cluster for: " << seqs.size() << endl;

  // point at the seq we merged with
  float lastdist=mergearr[0].dist;
  bool allin=false;
  for (i=0; i<mergearr.size(); ++i){
    if (lastdist != mergearr[i].dist){
      allin=true;
      for (k=seqs[0]; k!=otuarr[k]; k=otuarr[k]);
      otuarr[seqs[0]]=k;
      for (j=1; j<seqs.size(); ++j){
        for (k=seqs[j]; k!=otuarr[k]; k=otuarr[k]);
        otuarr[seqs[j]]=k;
        if (otuarr[seqs[0]] != otuarr[seqs[j]]) { allin=false; break; }
      }
      if (allin) break;
      lastdist=mergearr[i].dist;
//      cout << "# lastdist: " << lastdist << endl;
    }

   
    otuarr[mergearr[i].y]=mergearr[i].x;
/*
    otus[mergearr[i].x]+=otus[mergearr[i].y];
    for (j=0; j<otus[mergearr[i].y].size(); ++j)
      otuarr[otus[mergearr[i].y][j]]=mergearr[i].x;
    otus[mergearr[i].y].clear();
*/
  }

//  cout << "# finished" << endl;

  if (allin){
    cdist=lastdist;
    for (k=seqs[0]; k!=otuarr[k]; k=otuarr[k]);
    otuarr[seqs[0]]=k;
    for (i=0; i<otuarr.size(); ++i){
      for (k=i; k!=otuarr[k]; k=otuarr[k]);
      otuarr[i]=k;
      if (otuarr[i]==otuarr[seqs[0]])
        seqcluster.add(i);
    }
    return;
  }
  for (j=0; j<seqs.size(); ++j){
    for (k=seqs[j]; k!=otuarr[k]; k=otuarr[k]);
    otuarr[seqs[j]]=k;
  }
//  estr str;
//  for (j=0; j<seqs.size(); ++j)
//    str+=","+estr(otuarr[seqs[j]]);
//  cout << str.substr(1) << endl; 
  cdist=-1.0;
}
예제 #21
0
파일: daemon.c 프로젝트: ageric/merlin
static int handle_ipc_event(merlin_event *pkt)
{
	int result = 0;
	unsigned int i;

	if (pkt->hdr.type == CTRL_PACKET) {
		switch (pkt->hdr.code) {
		case CTRL_PATHS:
			read_nagios_paths(pkt);
			return 0;

		case CTRL_ACTIVE:
			/*
			 * handle_ctrl_active() should basically never return
			 * anything but 0 or 1 from our module. If it does, it
			 * will already have logged everything the user needs
			 * to know, so we can just return without further
			 * actions, even if the info returned is the same as
			 * we already have, but if no problems were found we
			 * forward the packet to the network anyway.
			 */
			result = handle_ctrl_active(&ipc, pkt);
			if (result < 0) {
				/* ipc is incompatible with us. weird */
				return 0;
			}

			/*
			 * info checks out, so we forward it. If ipc resent same
			 * info, we won't do the config sync check
			 */
			if (result >= 1) {
				break;
			}

			/*
			 * info checks out and is new. Check to see if we
			 * should run any config sync actions.
			 */
			for (i = 0; i < num_nodes; i++) {
				merlin_node *node = node_table[i];
				/* skip nodes that have no start or mtime */
				if (!node->info.start.tv_sec || !node->info.last_cfg_change)
					continue;
				csync_node_active(node_table[i]);
			}

			break;

		case CTRL_INACTIVE:
			/* this should really never happen, but forward it if it does */
			memset(&ipc.info, 0, sizeof(ipc.info));
			break;
		default:
			lwarn("forwarding control packet %d to the network",
				  pkt->hdr.code);
			break;
		}
	}

	/*
	 * we must send to the network before we run mrm_db_update(),
	 * since the latter deblockifies the packet and makes it
	 * unusable in network transfers without repacking, but only
	 * if this isn't magically marked as a NONET event
	 */
	if (pkt->hdr.code != MAGIC_NONET)
		result = net_send_ipc_data(pkt);

	/* skip sending control packets to database */
	if (use_database && pkt->hdr.type != CTRL_PACKET)
		result |= mrm_db_update(&ipc, pkt);

	return result;
}
예제 #22
0
파일: daemon.c 프로젝트: ageric/merlin
int main(int argc, char **argv)
{
	int i, result;

	progname = strrchr(argv[0], '/');
	progname = progname ? progname + 1 : argv[0];

	is_module = 0;
	ipc_init_struct();
	gettimeofday(&self.start, NULL);


	/*
	 * Solaris doesn't support MSG_NOSIGNAL, so
	 * we ignore SIGPIPE globally instead
	 */
	signal(SIGPIPE, SIG_IGN);

	for (i = 1; i < argc; i++) {
		char *opt, *arg = argv[i];

		if (*arg != '-') {
			if (!merlin_conf) {
				merlin_conf = arg;
				continue;
			}
			goto unknown_argument;
		}

		if (!strcmp(arg, "-h") || !strcmp(arg, "--help"))
			usage(NULL);
		if (!strcmp(arg, "-k") || !strcmp(arg, "--kill")) {
			killing = 1;
			continue;
		}
		if (!strcmp(arg, "-d") || !strcmp(arg, "--debug")) {
			debug++;
			continue;
		}

		if ((opt = strchr(arg, '=')))
			opt++;
		else if (i < argc - 1)
			opt = argv[i + 1];
		else
			usage("Unknown argument, or argument '%s' requires a parameter", arg);

		i++;
		if (!strcmp(arg, "--config") || !strcmp(arg, "-c")) {
			merlin_conf = opt;
			continue;
		}
		unknown_argument:
		usage("Unknown argument: %s", arg);
	}

	if (!merlin_conf)
		usage("No config-file specified\n");

	if (!grok_config(merlin_conf)) {
		fprintf(stderr, "%s contains errors. Bailing out\n", merlin_conf);
		return 1;
	}

	if (!pidfile)
		pidfile = "/var/run/merlin.pid";

	if (killing)
		return kill_daemon(pidfile);

	if (use_database && !import_program) {
		lwarn("Using database, but no import program configured. Are you sure about this?");
		lwarn("If not, make sure you specify the import_program directive in");
		lwarn("the \"daemon\" section of your merlin configuration file");
	}

	ipc.action = ipc_action_handler;
	result = ipc_init();
	if (result < 0) {
		printf("Failed to initalize ipc socket: %s\n", strerror(errno));
		return 1;
	}
	if (net_init() < 0) {
		printf("Failed to initialize networking: %s\n", strerror(errno));
		return 1;
	}

	if (!debug) {
		if (daemonize(merlin_user, NULL, pidfile, 0) < 0)
			exit(EXIT_FAILURE);

		/*
		 * we'll leak these file-descriptors, but that
		 * doesn't really matter as we just want accidental
		 * output to go somewhere where it'll be ignored
		 */
		fclose(stdin);
		open("/dev/null", O_RDONLY);
		fclose(stdout);
		open("/dev/null", O_WRONLY);
		fclose(stderr);
		open("/dev/null", O_WRONLY);
	}

	signal(SIGINT, clean_exit);
	signal(SIGTERM, clean_exit);
	signal(SIGUSR1, sigusr_handler);
	signal(SIGUSR2, sigusr_handler);

	sql_init();
	if (use_database) {
		sql_query("TRUNCATE TABLE program_status");
		sql_query("INSERT INTO program_status(instance_id, instance_name, is_running) "
		          "VALUES(0, 'Local Nagios daemon', 0)");
		for (i = 0; i < (int)num_nodes; i++) {
			char *node_name;
			merlin_node *node = noc_table[i];

			sql_quote(node->name, &node_name);
			sql_query("INSERT INTO program_status(instance_id, instance_name, is_running) "
			          "VALUES(%d, %s, 0)", node->id + 1, node_name);
			safe_free(node_name);
		}
	}
	state_init();
	linfo("Merlin daemon %s successfully initialized", merlin_version);
	polling_loop();

	clean_exit(0);

	return 0;
}
예제 #23
0
파일: net.c 프로젝트: ageric/merlin
/*
 * Initiate a connection attempt to a node and mark it as PENDING.
 * Note that since we're using sockets in non-blocking mode (in order
 * to be able to effectively multiplex), the connection attempt will
 * never be completed in this function
 */
int net_try_connect(merlin_node *node)
{
	int sockopt = 1;
	struct sockaddr *sa = (struct sockaddr *)&node->sain;
	int connected = 0, should_log = 0;
	struct timeval connect_timeout = { MERLIN_CONNECT_TIMEOUT, 0 };
	struct sockaddr_in sain;
	time_t interval = MERLIN_CONNECT_INTERVAL;

	/* don't log obsessively */
	if (node->last_conn_attempt_logged + 30 <= time(NULL)) {
		should_log = 1;
		node->last_conn_attempt_logged = time(NULL);
	}

	if (!(node->flags & MERLIN_NODE_CONNECT)) {
		if (should_log) {
			linfo("Connect attempt blocked by config to %s node %s",
				  node_type(node), node->name);
		}
		return 0;
	}

	/* if it's not yet time to connect, don't even try it */
	if (node->last_conn_attempt + interval > time(NULL)) {
		ldebug("connect to %s blocked for %lu more seconds", node->name,
			   node->last_conn_attempt + interval - time(NULL));
		return 0;
	}

	/* mark the time so we can time it out ourselves if need be */
	node->last_conn_attempt = time(NULL);

	/* create the socket if necessary */
	if (node->sock < 0) {
		node_disconnect(node, "struct reset (no real disconnect)");
		node->sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (node->sock < 0) {
			lerr("Failed to obtain socket for node %s: %s", node->name, strerror(errno));
			lerr("Aborting connection attempt to %s", node->name);
			return -1;
		}
	}

	/*
	 * don't try to connect to a node if an attempt is already pending,
	 * but do check if the connection has completed successfully
	 */
	if (node->state == STATE_PENDING || node->state == STATE_CONNECTED) {
		if (net_is_connected(node))
			node_set_state(node, STATE_CONNECTED, "Attempted connect completed");
		return 0;
	}

	sa->sa_family = AF_INET;
	if (should_log) {
		linfo("Connecting to %s %s@%s:%d", node_type(node), node->name,
		      inet_ntoa(node->sain.sin_addr),
		      ntohs(node->sain.sin_port));
	}

	(void)setsockopt(node->sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int));
	if (node->flags & MERLIN_NODE_FIXED_SRCPORT) {
		ldebug("Using fixed source port for %s node %s",
			   node_type(node), node->name);
		/*
		 * first we bind() to a local port calculated by our own
		 * listening port + the target port.
		 */
		sain.sin_family = AF_INET;
		sain.sin_port = htons(net_source_port(node));
		sain.sin_addr.s_addr = 0;
		if (bind(node->sock, (struct sockaddr *)&sain, sizeof(sain))) {
			lerr("Failed to bind() outgoing socket for node %s to port %d: %s",
				 node->name, ntohs(sain.sin_port), strerror(errno));
		}
	}

	if (fcntl(node->sock, F_SETFL, O_NONBLOCK) < 0) {
		lwarn("Failed to set socket for %s non-blocking: %s", node->name, strerror(errno));
	}
	if (setsockopt(node->sock, SOL_SOCKET, SO_RCVTIMEO,
	               &connect_timeout, sizeof(connect_timeout)) < 0)
	{
		ldebug("Failed to set receive timeout for node %s: %s",
		       node->name, strerror(errno));
	}
	if (setsockopt(node->sock, SOL_SOCKET, SO_SNDTIMEO,
	               &connect_timeout, sizeof(connect_timeout)) < 0)
	{
		ldebug("Failed to set send timeout for node %s: %s",
		       node->name, strerror(errno));
	}

	if (connect(node->sock, sa, sizeof(struct sockaddr_in)) < 0) {
		if (errno == EINPROGRESS || errno == EALREADY) {
			node_set_state(node, STATE_PENDING, "connect() already in progress");
		} else if (errno == EISCONN) {
			connected = 1;
		} else {
			if (should_log) {
				node_disconnect(node, "connect() failed to %s node '%s' (%s:%d): %s",
								node_type(node), node->name,
								inet_ntoa(node->sain.sin_addr),
								ntohs(node->sain.sin_port),
								strerror(errno));
			} else {
				node_disconnect(node, NULL);
			}
			return -1;
		}
	}

	if (connected || net_is_connected(node)) {
		linfo("Successfully connected to %s %s@%s:%d",
			  node_type(node), node->name, inet_ntoa(node->sain.sin_addr),
			  ntohs(node->sain.sin_port));
		node_set_state(node, STATE_CONNECTED, "connect() successful");
	} else {
		if (should_log) {
			linfo("Connection pending to %s %s@%s:%d",
			      node_type(node), node->name,
			      inet_ntoa(node->sain.sin_addr),
			      ntohs(node->sain.sin_port));
		}
		node_set_state(node, STATE_PENDING, "connect() in progress");
	}

	return 0;
}