Exemplo n.º 1
0
void rq_blacklist_init(rq_blacklist_t *blacklist, rq_t *rq, const char *queue, int expires)
{
	assert(blacklist);
	assert(rq);
	assert(queue);
	assert(expires > 0);

	blacklist->rq = rq;
	blacklist->queue = (char *) queue;

  blacklist->expires = expires; 
  
  blacklist->cache = (list_t *) malloc(sizeof(list_t));
  ll_init(blacklist->cache);

  blacklist->waiting = (list_t *) malloc(sizeof(list_t));
  ll_init(blacklist->waiting);

	blacklist->risp = risp_init();
	assert(blacklist->risp != NULL);
	risp_add_invalid(blacklist->risp, cmdInvalid);
	risp_add_command(blacklist->risp, BL_CMD_CLEAR, 	 &cmdClear);
	risp_add_command(blacklist->risp, BL_CMD_ACCEPT,   &cmdAccept);
 	risp_add_command(blacklist->risp, BL_CMD_DENY,     &cmdDeny);
}
Exemplo n.º 2
0
rq_http_t * rq_http_new (rq_t *rq, char *queue, void (*handler)(rq_http_req_t *req), void *arg)
{
	rq_http_t *http;

	assert(rq);
	assert(queue);
	assert(handler);
	assert((arg && handler) || (arg == NULL));

	// create http object.
	http = malloc(sizeof(*http));
	http->rq = rq;
	http->queue = strdup(queue);
	assert(strlen(queue) < 256);
	http->handler = handler;
	http->arg = arg;

	http->req_list = ll_init(NULL);
	assert(http->req_list);
	
	http->safe_buffer = NULL;
	http->safe_len = 0;

	// create RISP object
	http->risp = risp_init(NULL);
	assert(http->risp);
	risp_add_command(http->risp, HTTP_CMD_CLEAR, 	   &cmdClear);
	risp_add_command(http->risp, HTTP_CMD_EXECUTE,     &cmdExecute);
	risp_add_command(http->risp, HTTP_CMD_METHOD_GET,  &cmdMethodGet);
	risp_add_command(http->risp, HTTP_CMD_METHOD_POST, &cmdMethodPost);
	risp_add_command(http->risp, HTTP_CMD_METHOD_HEAD, &cmdMethodHead);
	risp_add_command(http->risp, HTTP_CMD_HOST,        &cmdHost);
	risp_add_command(http->risp, HTTP_CMD_PATH,        &cmdPath);
	risp_add_command(http->risp, HTTP_CMD_PARAMS,      &cmdParams);
	risp_add_command(http->risp, HTTP_CMD_CODE,        &cmdCode);

// 	risp_add_command(http->risp, HTTP_CMD_SET_HEADER,  &cmdHeader);
// 	risp_add_command(http->risp, HTTP_CMD_LENGTH,      &cmdLength);
// 	risp_add_command(http->risp, HTTP_CMD_REMOTE_HOST, &cmdRemoteHost);
// 	risp_add_command(http->risp, HTTP_CMD_LANGUAGE,    &cmdLanguage);
// 	risp_add_command(http->risp, HTTP_CMD_FILE,        &cmdParams);
// 	risp_add_command(http->risp, HTTP_CMD_KEY,         &cmdKey);
// 	risp_add_command(http->risp, HTTP_CMD_VALUE,       &cmdValue);
// 	risp_add_command(http->risp, HTTP_CMD_FILENAME,    &cmdFilename);

	rq_consume(rq, http->queue, 200, RQ_PRIORITY_NORMAL, 0, message_handler, NULL, NULL, http);

	return(http);
}
Exemplo n.º 3
0
int main(int argc, char **argv)
{
	// parameters that are provided.
	char *srv = "127.0.0.1";
	int port = DEFAULT_PORT;
	char *cafile = NULL;
	char *certfile = NULL;
	char *keyfile = NULL;
	data_t data;

	data.stream = NULL;
	data.session = NULL;
	data.name = NULL;
	data.message = NULL;
	
	int c;
	while ((c = getopt(argc, argv, 
		"s:" /* server hostname or ip */
		"p:" /* port to connect to */
		"a:" /* CA file */
		"c:" /* Certificate Chain */
		"k:" /* Private Key file */
		"n:" /* name of the message sender */
		"m:" /* message to send */
		"h"  /* command usage */
	)) != -1) {
		switch (c) {
			case 'p':
				port = atoi(optarg);
				assert(port > 0);
				break;
			case 's':
				srv = strdup(optarg);
				assert(srv);
				break;
			case 'a':
				assert(cafile == NULL);
				cafile = optarg;
				assert(cafile);
				break;
			case 'c':
				assert(certfile == NULL);
				certfile = optarg;
				assert(certfile);
				break;
			case 'k':
				assert(keyfile == NULL);
				keyfile = optarg;
				assert(keyfile);
				break;
			case 'n':
				data.name = strdup(optarg);
				assert(data.name);
				break;
			case 'm':
				data.message = strdup(optarg);
				assert(data.message);
				break;
			case 'h':
				printf("Usage: ./risp_chat_send -s [server] -p [port] -n \"name of sender\" -m \"Message\"\n\n");
				exit(1);
				break;
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}

	// get an initialised risp structure.
	RISP risp = risp_init();
	assert(risp);

	// add the callback routines for the commands we are going to receive.
	risp_add_command(risp, CMD_NOP,              cmdNop);
	risp_add_command(risp, CMD_HELLO_ACK,        cmdHelloAck);

	// add a handler to let us know if we receive a command we aren't expecting.
	risp_add_invalid(risp, &cmdInvalid);

	// initialise the RISP stream library.  This will also initialise libevent (which we verify with an assert).  
	data.stream = rispstream_init(NULL);
	assert(data.stream);
	struct event_base *evbase = rispstream_get_eventbase(data.stream);
	assert(evbase);

	// Attach our RISP handlers to the stream.
	rispstream_attach_risp(data.stream, risp);

	// The stream can use the event system to trap signals, so we will use that.
	rispstream_break_on_signal(data.stream, SIGINT, break_cb);

	// if the keys are encrypted, they will need the passphrase.  Set a callback routine to Ask the user for this password.
	if (keyfile) {
		rispstream_set_passphrase_callback(data.stream, passphrase_cb);
	}
	
	// if the user has specified to use certificates, then they needed to be loaded into the 
	// rispstream instance.  Once certificates are applied, all client connections must also
	// be secure.
	if (certfile && keyfile) {
		fprintf(stderr, "Loading Certificate and Private Keys\n");
		int result = rispstream_add_client_certs(data.stream, cafile, certfile, keyfile);
		if (result != 0) {
			fprintf(stderr, "Unable to load Certificate and Private Key files.\n");
			exit(1);
		}
		assert(result == 0);
		printf("Certificate files loaded.\n");
	}

	// Initiate a connection.  Note that it will only QUEUE the request, and will not actually attempt 
	// the connection until the stream is being processed (rispstream_process).
	assert(srv);
	assert(port > 0);
	rispstream_connect(data.stream, srv, port, &data, connect_cb, close_cb);
	
	// this function will process the stream (assuming the connection succeeds).  
	// When there are no more events, it will exit.
	// When the socket closes, this function should exit.
	rispstream_process(data.stream);	
	fprintf(stderr, "FINISHED.  SHUTTING DOWN\n");
	
	// Not really needed, but good to do it out of habbit before actually cleaning up the risp object itself.
	rispstream_detach_risp(data.stream);
	
	// since the connect has completed, it either failed to do anything, or it connected, processing completed, 
	// and the socket was closed.  So now we shutdown the stream.
	rispstream_shutdown(data.stream);

	// clean up the risp structure.
	risp_shutdown(risp);
	risp = NULL;
	
	return 0;
}
Exemplo n.º 4
0
int main(int argc, char **argv)
{
	int c;
	risp_t *risp;
	int sent;
	char *srv = "127.0.0.1";
	char *filename = NULL;
	int port = DEFAULT_PORT;
	int avail;
	int processed;
	int len;
	int done = 0, t;

	node_t node;

	// initialise the node data.
	node.handle = INVALID_HANDLE;
	node.verbose = 0;
	node.finished = 0;
	expbuf_init(&node.in, 1024);
	expbuf_init(&node.out, 1024);
	expbuf_init(&node.data.file, 0);
	expbuf_init(&node.data.data, 0);
	node.data.op = CMD_NOP;
	node.data.size = 0;
	node.data.offset = 0;

	node.filehandle = INVALID_HANDLE;
	node.size = 0;
	node.offset = 0;


	while ((c = getopt(argc, argv, "f:p:s:v")) != -1) {
		switch (c) {
			case 'f':
				filename = optarg;
				assert(filename != NULL);
				break;
			case 'p':
				port = atoi(optarg);
				assert(port > 0);
				break;
			case 's':
				srv = optarg;
				assert(srv != NULL);
				break;
			case 'v':
				node.verbose ++;
				break;
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}

	if (filename == NULL) {
		fprintf(stderr, "Need a filename.\n\n");
		exit(1);
	}

	// get an initialised risp structure.
	risp = risp_init();
	if (risp == NULL) {
		printf("Unable to initialise RISP library.\n");
	}
	else {
		risp_add_command(risp, CMD_CLEAR, 	&cmdClear);
		risp_add_command(risp, CMD_EXECUTE, &cmdExecute);
		risp_add_command(risp, CMD_OFFSET,  &cmdOffset);
		risp_add_command(risp, CMD_SIZE,    &cmdSize);
		risp_add_command(risp, CMD_FILE,    &cmdFile);
		risp_add_command(risp, CMD_DATA,    &cmdData);
		risp_add_command(risp, CMD_PUT,     &cmdPut);
		risp_add_command(risp, CMD_GET,     &cmdGet);
		
		len = strlen(filename);
		assert(len < 256);

		assert(node.out.length == 0);
		
		addCmd(&node.out, CMD_CLEAR);
		addCmd(&node.out, CMD_GET);
		addCmdShortStr(&node.out, CMD_FILE, len, filename);
		addCmd(&node.out, CMD_EXECUTE);
		
		// and process it a lot of time.
		printf("Sending request for: %s\n", filename);
		
		// connect to the remote socket.
		node.handle = sock_connect(srv, port);
		if (node.handle <= 0) {
			printf("Unable to connect to %s:%d\n", srv, port);
		}
		else {
			while (sigtrap == 0 && node.finished == 0) {

				// continue to send data to the socket over and over as quickly as possible.
				while (node.out.length > 0) {
					assert(node.handle > 0);
					sent = sock_send(node.handle, node.out.data, node.out.length);
					if (sent < 0) { sigtrap ++; }
					else {
						assert(sent > 0);
						assert(sent <= node.out.length);
						if (sent == node.out.length) { expbuf_clear(&node.out); }
						else { expbuf_purge(&node.out, sent); }
					}	
				}

				// if we didn't generate a fail during the write, then we do a read.
				if (sigtrap == 0) {

					avail = node.in.max - node.in.length;
					if (avail < 1024) {
						expbuf_shrink(&node.in, 1024);
						avail = 1024;
					}

					sent = sock_receive(node.handle, node.in.data + node.in.length, avail);
					if (sent < 0) { sigtrap ++; }
					else {
						assert(sent > 0);
						node.in.length += sent;
						assert(node.in.length <= node.in.max);
						if (sent == avail) {
							// we filled the incoming buffer, so we need to double it.
							expbuf_shrink(&node.in, node.in.max * 2);
						}
						processed = risp_process(risp, &node, node.in.length, (unsigned char *) node.in.data);
// 						printf("Processed %d.\n", processed);
						if (processed > 0) {
							expbuf_purge(&node.in, processed);

							if (node.offset > 0 && node.size > 0) {
								t = (node.offset / (node.size/100));
								if (t > done) {
									done = t;
									printf("Done - %c%d\n", '%', done);
								}
							}
						}
					}
				}
			}
			
			// close the socket.
			if (node.handle >= 0) {
				close(node.handle);
			}
		}
	
		// clean up the risp structure.
		risp_shutdown(risp);
	}
	
	return 0;
}
Exemplo n.º 5
0
int main(int argc, char **argv)
{
	// parameters that are provided.
	char *srv = "127.0.0.1";
	int port = DEFAULT_PORT;

	// this data object will be passed to all the callback routines.  Initialise it.
	data_t data;
	data.handle = -1;
	data.msg_id = 0;
	data.latest_msg_id = 0;
	data.name = NULL;

	// get the command line options.
	int c;
	while ((c = getopt(argc, argv, "p:s:h")) != -1) {
		switch (c) {
			case 'p':
				port = atoi(optarg);
				assert(port > 0);
				break;
			case 's':
				srv = strdup(optarg);
				assert(srv != NULL);
				break;				
			case 'h':
				printf("usage:\n\nrisp_chat_stream2 [-s server] [-p port] [-h]\n");
				exit(1);
				break;
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}

	// set the signal trap, so we can break out of the loop when user presses Ctrl-C.
	signal(SIGINT, sig_handler);
	
	// get an initialised risp structure.
	RISP_PTR risp = risp_init();
	assert(risp);

	// add the callback routines for the commands we are going to receive.
	risp_add_command(risp, CMD_NOP,              &cmdNop);
	risp_add_command(risp, CMD_HELLO_ACK,        &cmdHelloAck);
	risp_add_command(risp, CMD_MSG_ID,           &cmdMsgID);
	risp_add_command(risp, CMD_LATEST_MSG_ID,    &cmdLatestMsgID);
	risp_add_command(risp, CMD_NAME,             &cmdName);
	risp_add_command(risp, CMD_MESSAGE,          &cmdMessage);

	risp_add_invalid(risp, &cmdInvalid);

	
	// connect to the remote socket. We will leave it in blocking mode.  When we do the recv, we 
	// will specify that the recv operation is non-blocking.
	assert(srv && port > 0);
	data.handle = sock_connect(srv, port);
	if (data.handle <= 0) {
		printf("Unable to connect to %s:%d\n", srv, port);
	}
	else {
		// now that we are connected, first we need to send the HELLO and NO_FOLLOW commands.  
		// These commands could have been lumped together in a single send, but for the purpose of 
		// demonstrating RISP, this code does each operationg specifically.
		if (sendInit(data.handle) != 0) {
			// couldn't send the command, close the handle, and exit.
			close(data.handle);
			data.handle = -1;
		}
		
		// setup the initial buffer.  Since we dont really know how much data we will receive from 
		// the server, we will grow the buffer as needed.
		int max = 0;
		char *buffer = NULL;
		int used = 0;
		int goodbye_sent = 0;	// if we have sent a GOODBYE, we dont want to 
		
		// we will loop until the socket is closed.  If the user presses Ctrl-C, we will send a 
		// GOODBYE command to the server, which will then close the socket.  If the user presses 
		// Ctrl-C more than once, we will not wait for the server, and will close the socket 
		// directly.  Every time the user presses Ctrl-C, it should break out of the sleep, so it 
		// should respond pretty quickly.
		while (data.handle >= 0) {
		
// 			printf(".");
			
			assert(used <= max);
			
			if (max-used < CHUNK_SIZE) { 
				max += CHUNK_SIZE;
				buffer = realloc(buffer, max);
				assert(buffer);
// 				fprintf(stderr, "Increased Max Buffer to %d\n", max);
			}
			
			// check for data on the socket.  We will do the receive in non-blocking mode, so if 
			// there is no data, it will return immediately. If we received no data, we will wait for 
			// 1 second before trying again.  If we have waited for 5 seconds, then we need to 
			// send a NOP to keep the connection alive.
			char *ptr = buffer + used;
			int avail = max - used;
// 			fprintf(stderr, "About to recv.  avail=%d\n", avail);
			int result = recv(data.handle, ptr, avail, MSG_DONTWAIT);
// 			printf("Recv: result=%d, used=%d, max=%d\n", result, used, max);
			if (result < 0) {
				assert(result == -1);
				if (errno == EWOULDBLOCK || errno == EAGAIN) {
					// there was no data to read from the socket.
					// we will now sleep for 1 second.  If the user pressed Ctrl-C, then the sleep 
					// function will exit immediately. Only do the sleep if Ctrl-C hasn't been hit.
					if (_sigtrap == 0) { sleep(1); }
				}
				else {
					fprintf(stderr, "Unexpected result received from socket. errno=%d '%s'\n", errno, strerror(errno));
				}
			}
			else if (result == 0) {
				// socket has closed.
				close(data.handle);
				data.handle = -1;
			}
			else {
				assert(result > 0);
				assert(result <= avail);
				assert(used >= 0);
				used += result;
				assert(used <= max);
				
				// if we have some data received, then we need to process it.
// 				fprintf(stderr, "Processing: %d\n", used);
				risp_length_t processed = risp_process(risp, &data, used, buffer);
// 				fprintf(stderr, "Processed: %ld\n", processed);
				assert(processed >= 0);
				assert(processed <= used);
				
				if (processed < used) { 
					// Our commands have probably been fragmented.
					
// 					fprintf(stderr, "Fragmented commands: processed=%ld, used=%d, max=%d\n", processed, used, max);
					fflush(stdout);
					
					if (processed > 0) {
						// we need to remove from the buffer the data that we have processed.  
						// This is a simple approach, but not the most efficient.
						assert(sizeof(*buffer) == 1);
						char *ptr = buffer+processed;
						size_t length = used-processed;
						assert((processed + length) == used);
						
// 						fprintf(stderr, "Moving data.  length=%ld\n", length);
						
						memmove(buffer, ptr, length);
						
						used -= processed;
						assert(used > 0);
						assert(used < max);
						
// 						fprintf(stderr, "After move. used=%d, max=%d\n", used, max);
					}
				} 
				else { used = 0; }
				
				assert(used >= 0 && used <= max);
			}
			
			
			if (data.handle >= 0) {
				if (_sigtrap == 1 && goodbye_sent == 0) {
					fprintf(stderr, "Closing...\n");
					
					// TODO: shouldn't just close the socket.  Should instead send GOODBYE command and wait for socket to close.
					if (sendGoodbye(data.handle) != 0) {
						close(data.handle);
						data.handle = -1;
					}
					
					goodbye_sent ++;
				}
				else if (_sigtrap > 1) {
					close(data.handle);
					data.handle = -1;
				}
			}
		}
	}

	// clean up the risp structure.
	risp_shutdown(risp);
	risp = NULL;
	
	return 0;
}
Exemplo n.º 6
0
//-----------------------------------------------------------------------------
// Main... process command line parameters, and then setup our listening 
// sockets and event loop.
int main(int argc, char **argv) 
{
	rq_service_t   *service;
	control_t      *control  = NULL;
	char *queue;

///============================================================================
/// Initialization.
///============================================================================

	// create the 'control' object that will be passed to all the handlers so
	// that they have access to the information that they require.
	control = (control_t *) malloc(sizeof(control_t));
	init_control(control);

	// create new service object.
	service = rq_svc_new();
	control->rqsvc = service;

	// add the command-line options that are specific to this service.
	rq_svc_setname(service, PACKAGE " " VERSION);
	rq_svc_setoption(service, 'f', "filename", "blacklist .csv file.");
	rq_svc_setoption(service, 'q', "queue",    "Queue to listen on for requests.");
	rq_svc_process_args(service, argc, argv);
	rq_svc_initdaemon(service);
	
	assert(control->evbase == NULL);
	control->evbase = event_base_new();
	assert(control->evbase);
	rq_svc_setevbase(service, control->evbase);


	// initialise the risp system for processing what we receive on the queue.
	assert(control);
	assert(control->risp == NULL);
	control->risp = risp_init(NULL);
	assert(control->risp != NULL);
	risp_add_command(control->risp, BL_CMD_NOP,      &cmdNop);
	risp_add_command(control->risp, BL_CMD_CLEAR, 	 &cmdClear);
	risp_add_command(control->risp, BL_CMD_CHECK,    &cmdCheck);
	risp_add_command(control->risp, BL_CMD_IP,       &cmdIP);
	
	// initialise signal handlers.
	assert(control);
	assert(control->evbase);
	assert(control->sigint_event == NULL);
	control->sigint_event = evsignal_new(control->evbase, SIGINT, sigint_handler, control);
	assert(control->sigint_event);
	event_add(control->sigint_event, NULL);
	assert(control->sighup_event == NULL);
	control->sighup_event = evsignal_new(control->evbase, SIGHUP, sighup_handler, control);
	assert(control->sighup_event);
	event_add(control->sighup_event, NULL);

	// load the config file that we assume is supplied.
	assert(control->configfile == NULL);
	control->configfile = rq_svc_getoption(service, 'f');
	if (control->configfile == NULL) {
		fprintf(stderr, "Configfile is required\n");
		exit(EXIT_FAILURE);
	}
	else {
		if (config_load(control) < 0) {
			fprintf(stderr, "Errors loading config file: %s\n", control->configfile);
			exit(EXIT_FAILURE);
		}
	}

	// Tell the rq subsystem to connect to the rq servers.  It gets its info
	// from the common paramaters that it expects.
	rq_svc_connect(service, NULL, NULL, NULL);
	
	// initialise the queue that we are consuming, provide callback handler.
	queue = rq_svc_getoption(service, 'q');
	assert(queue);
	assert(service->rq);
	rq_consume(service->rq, queue, 200, RQ_PRIORITY_NORMAL, 0, message_handler, NULL, NULL, control);

	// we also want to make sure that when we lose the connection to the
	// controller, we indicate that we lost connection to the queue, unless we
	// have already established another controller connection.

///============================================================================
/// Main Event Loop.
///============================================================================

	// enter the processing loop.  This function will not return until there is
	// nothing more to do and the service has shutdown.  Therefore everything
	// needs to be setup and running before this point.  Once inside the
	// rq_process function, everything is initiated by the RQ event system.
	assert(control != NULL);
	assert(control->evbase);
	event_base_loop(control->evbase, 0);

///============================================================================
/// Shutdown
///============================================================================

	assert(control);
	assert(control->evbase);
	event_base_free(control->evbase);
	control->evbase = NULL;

	// the rq service sub-system has no real way of knowing when the event-base
	// has been cleared, so we need to tell it.
	rq_svc_setevbase(service, NULL);
	control->rqsvc = NULL;


	// unload the config entries.
	assert(control);
	if (control->entries) {
		config_unload(control);
	}
	assert(control->entries == NULL);

	// make sure signal handlers have been cleared.
	assert(control);
	assert(control->sigint_event == NULL);
	assert(control->sighup_event == NULL);

	// cleanup risp library.
	assert(control);
	assert(control->risp);
	control->risp = risp_shutdown(control->risp);
	assert(control->risp == NULL);

	// we are done, cleanup what is left in the control structure.
	cleanup_control(control);
	free(control);

	rq_svc_cleanup(service);

	return 0;
}
Exemplo n.º 7
0
//-----------------------------------------------------------------------------
// Main... process command line parameters, and then setup our listening 
// sockets and event loop.
int main(int argc, char **argv) 
{
	char *interface = "0.0.0.0";
	char *cafile = NULL;
	char *certfile = NULL;
	char *keyfile = NULL;
	char *userfile = NULL;
	int port = DEFAULT_PORT;
	bool verbose = false;

	// set stderr non-buffering (for running under, say, daemontools)
	setbuf(stderr, NULL);

	while (1) {
		int option_index = 0;
		static struct option long_options[] = {
			{"interface", required_argument, 0,  'l' },
			{"port",      required_argument, 0,  'p' },
			{"client-ca", required_argument, 0,  'c' },
			{"cert",      required_argument, 0,  's' },
			{"key",       required_argument, 0,  'k' },
			{"userfile",  required_argument, 0,  'u' },
			{"help",      no_argument,       0,  'h' },
			{"verbose",   no_argument,       0,  'v' },
			{0,           0,                 0,  0 }
		};

		int c = getopt_long(argc, argv,
			"l:" /* listening interface (IP) */
			"p:" /* port to listen on */
			"c:" /* Client Certificate Chain */
			"s:" /* Server Certificate */
			"k:" /* Private Key file for Server Certificate */
			"u:" /* Userfile for authentication */
			"h"  /* help... show usage info */
			"v"  /* verbosity */
			, long_options, &option_index);
		if (c == -1)
			break;

		switch (c) {
			case 0:
				fprintf(stderr, "Unknown option %s", long_options[option_index].name);
				if (optarg) { fprintf(stderr, " with arg %s", optarg); }
				printf("\n");
				break;
			case 'h':
				usage();
				exit(EXIT_SUCCESS);
			case 'v':
				verbose++;
				break;
			case 'p':
				assert(optarg);
				port = atoi(optarg);
				assert(port > 0);
				break;
			case 'l':
				interface = optarg;
				assert(interface);
				break;
			case 'c':
				assert(cafile == NULL);
				cafile = optarg;
				assert(cafile);
				break;
			case 's':
				assert(certfile == NULL);
				certfile = optarg;
				assert(certfile);
				break;
			case 'k':
				assert(keyfile == NULL);
				keyfile = optarg;
				assert(keyfile);
				break;
			case 'u':
				assert(userfile == NULL);
				userfile = optarg;
				assert(userfile);
				break;
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}

	if (verbose > 1) { fprintf(stderr, "Interface: %s\n", interface); }
	if (verbose > 1) { fprintf(stderr, "Listening Port: %d\n", port); }
	if (verbose > 1) { fprintf(stderr, "CA File: %s\n", cafile); }
	if (verbose > 1) { fprintf(stderr, "Cert File: %s\n", certfile); }
	if (verbose > 1) { fprintf(stderr, "Key File: %s\n", keyfile); }

	if (verbose) fprintf(stderr, "Finished processing command-line args\n");
	

	// initialise the rispstream.  We dont pass any parameters in, we build up functionality after.
	RISPSTREAM stream = rispstream_init(NULL);
	assert(stream);

	// Initialise the risp system.
	RISP risp = risp_init();
	assert(risp);
	risp_add_invalid(risp, cmdInvalid);
	risp_add_command(risp, CMD_NOP, 				&cmdNop);
	risp_add_command(risp, CMD_HELLO,				&cmdHello);
	risp_add_command(risp, CMD_GOODBYE,				&cmdGoodbye);
	risp_add_command(risp, CMD_ECHO,				&cmdEcho);
	risp_add_command(risp, CMD_NOECHO,				&cmdNoEcho);
	risp_add_command(risp, CMD_FOLLOW,				&cmdFollow);
	risp_add_command(risp, CMD_NOFOLLOW,			&cmdNoFollow);
	risp_add_command(risp, CMD_NOUPDATE,			&cmdNoUpdate);
	risp_add_command(risp, CMD_GET_LATEST_MDG_ID,	&cmdGetLatestMsgID);
	risp_add_command(risp, CMD_SEND_MSG,			&cmdSendMsg);
	risp_add_command(risp, CMD_SEND_SINCE,			&cmdSendSince);
	risp_add_command(risp, CMD_NAME,				&cmdName);
	risp_add_command(risp, CMD_MESSAGE,				&cmdMessage);
	
	// there are some commands that are illegal to be received from the client.  
	// If we receive them, then we should close the session
	risp_add_command(risp, CMD_HELLO_ACK,			&cmdIllegal);
	risp_add_command(risp, CMD_MSG_ID,				&cmdIllegal);
	risp_add_command(risp, CMD_LATEST_MSG_ID,		&cmdIllegal);

	// attach our RISP object (which has all the commands added) to the stream.  
	// It will use this object to decode the stream of data as it arrives.
	assert(stream && risp);
	rispstream_attach_risp(stream, risp);

	// create the object that will be tracking the sessions and the data that needs to flow 
	// between them, and let the stream sub-system know.
	maindata_t *data = maindata_init();
	assert(data);
	rispstream_set_userdata(stream, data);

	// if the user specified a userfile, it will load the contents into the maindata structure.  This will be used to validate client connections.
	if (userfile) {
		load_userfile(userfile, data);
		assert(data->users);
		
		if (verbose > 0) {
			int u=0;
			while (data->users[u]) { fprintf(stderr, "User: '******'\n", data->users[u]); u++; }
		}
	}
	else {
		assert(data->users == NULL);
	}
	
	// if the user has specified to use certificates, then they needed to be loaded into the 
	// rispstream instance.  Once certificates are applied, all client connections must also
	// be secure.
	if (cafile && certfile && keyfile) {
		if (verbose > 1) { fprintf(stderr, "Loading CA, Certificate and Private Keys\n"); }
		int result = rispstream_add_server_certs(stream, cafile, certfile, keyfile);
		if (result != 0) {
			fprintf(stderr, "Unable to load Certificate and Private Key files.\n");
			exit(1);
		}
		assert(result == 0);
		
		assert(stream);
		assert(cafile);
		rispstream_require_client_certs(stream, cafile);
		
		if (verbose) { fprintf(stderr, "Certificate files loaded.\n"); }
	}
	
	// When the user presses Ctrl-C, we want the service to exit (cleanly).  
	// We can tell rispstream to handle that (since the stream will be handling libevent).  
	// When a user presses Ctrl-C, rispstream will detect, and will execute a callback routine.  
	// In this case, our callback routine is break_cb().
	assert(stream);
	rispstream_break_on_signal(stream, SIGINT, break_cb);
    
	// Now we want to tell rispstream to listen on a socket for new connections.  
	// When a new connection comes in, a callback function is called.  
	// The callback function will return with a pointer to a base data object.  
	// That object will be passed to the risp callback routines when commands are received.  
	// It essentially allows you to have some data specific to that session.
	assert(stream);
	rispstream_listen(stream, interface, port, newconn_cb, connclosed_cb);

	// Now that the listen socket and event is created, we need to process the streams that result.  
	// This function will continue to run until one of the callbacks tells rispstream to shutdown.   
	// This is a blocking function.
	rispstream_process(stream);
	
	//--------
	// Shutting Down.
	// When the above function exits, it means we are shutting down.
	
	// Since rispstream did not create the risp object, we should detach it, to make it clear that risp is being cleaned up elsewhere.  
	// If it was still attached when rispstream_shutdown() is called, it will generate an assert.
	rispstream_detach_risp(stream);
	
	// shutdown rispstream.. it should be fairly empty and idle at this point though.
	rispstream_shutdown(stream);
	stream = NULL;
	
	// cleanup risp library.
	assert(risp);
	risp_shutdown(risp);
	risp = NULL;
    
	if (verbose) fprintf(stderr, "\n\nExiting.\n");

	return 0;
}
Exemplo n.º 8
0
Arquivo: rfxd.c Projeto: hyper/librisp
static void timeout_handler(const int fd, const short which, void *arg) {
	struct timeval t = {.tv_sec = 1, .tv_usec = 0};
	timeout_t *ptr;
	unsigned int inmem, outmem, filemem;
	int i;
	
	ptr  = (timeout_t *) arg;

	assert(ptr != NULL);
	assert(ptr->clockevent.ev_base != NULL);

	// reset the timer to go off again in 1 second.
	evtimer_del(&ptr->clockevent);
	evtimer_set(&ptr->clockevent, timeout_handler, arg);
	event_base_set(ptr->clockevent.ev_base, &ptr->clockevent);
	evtimer_add(&ptr->clockevent, &t);
	
 	assert(fd == INVALID_HANDLE);
	assert(ptr->server != NULL);

	assert(ptr->stats != NULL);
	
	if (ptr->stats->in_bytes || ptr->stats->out_bytes || ptr->stats->commands || ptr->stats->operations) {

		inmem=0;
		outmem=0;
		filemem = 0;

		for(i=0; i<ptr->server->maxconns; i++) {
			if (ptr->server->nodes[i] != NULL) {
				inmem += ptr->server->nodes[i]->in.length;
				outmem += ptr->server->nodes[i]->out.length;
				filemem += ptr->server->nodes[i]->filebuf.length;
			}
		}

		if (inmem > 0) { inmem /= 1024; }
		if (outmem > 0) { outmem /= 1024; }
		if (filemem > 0) { filemem /= 1024; }

	
		printf("Bytes [%u/%u], Commands [%u], Operations[%u], Mem[%uk/%uk/%uk], Cycles[%u], Undone[%u], RW[%u/%u]\n", ptr->stats->in_bytes, ptr->stats->out_bytes, ptr->stats->commands, ptr->stats->operations, inmem, outmem, filemem, ptr->stats->cycles, ptr->stats->undone, ptr->stats->reads, ptr->stats->writes);
		ptr->stats->in_bytes = 0;
		ptr->stats->out_bytes = 0;
		ptr->stats->commands = 0;
		ptr->stats->operations = 0;
		ptr->stats->cycles = 0;
		ptr->stats->undone = 0;
		ptr->stats->reads = 0;
		ptr->stats->writes = 0;
	}
}



void timeout_init(timeout_t *ptr, struct event_base *base) 
{
	struct timeval t = {.tv_sec = 1, .tv_usec = 0};
	assert(ptr != NULL);
	assert(ptr->clockevent.ev_base == NULL);
	
	evtimer_set(&ptr->clockevent, timeout_handler, (void *) ptr);
	event_base_set(ptr->clockevent.ev_base, &ptr->clockevent);
	evtimer_add(&ptr->clockevent, &t);
	assert(ptr->clockevent.ev_base != NULL);
}




//-----------------------------------------------------------------------------
// Main... process command line parameters, and then setup our listening 
// sockets and event loop.
int main(int argc, char **argv) 
{
	int c;
	settings_t     *settings = NULL;
	server_t       *server   = NULL;
	timeout_t      *timeout  = NULL;
	stats_t        *stats    = NULL;
	risp_t         *risp     = NULL;

	// handle SIGINT 
	signal(SIGINT, sig_handler);
	
	// init settings
	settings = (settings_t *) malloc(sizeof(settings_t));
	assert(settings != NULL);
	settings_init(settings);

	// set stderr non-buffering (for running under, say, daemontools)
	setbuf(stderr, NULL);


	// process arguments 
	/// Need to check the options in here, there're possibly ones that we dont need.
	while ((c = getopt(argc, argv, "p:k:c:hvd:u:P:l:s:")) != -1) {
		switch (c) {
			case 'p':
				settings->port = atoi(optarg);
				assert(settings->port > 0);
				break;
			case 'c':
				settings->maxconns = atoi(optarg);
				assert(settings->maxconns > 0);
				break;
			case 'h':
				usage();
				exit(EXIT_SUCCESS);
			case 'v':
				settings->verbose++;
				break;
			case 'd':
				assert(settings->daemonize == false);
				settings->daemonize = true;
				break;
			case 's':
				assert(settings->storepath == NULL);
				settings->storepath = optarg;
				assert(settings->storepath != NULL);
				assert(settings->storepath[0] != '\0');
				break;
			case 'u':
				assert(settings->username == NULL);
				settings->username = optarg;
				assert(settings->username != NULL);
				assert(settings->username[0] != '\0');
				break;
			case 'P':
				assert(settings->pid_file == NULL);
				settings->pid_file = optarg;
				assert(settings->pid_file != NULL);
				assert(settings->pid_file[0] != '\0');
				break;
			case 'l':
				assert(settings->interface == NULL);
				settings->interface = strdup(optarg);
				assert(settings->interface != NULL);
				assert(settings->interface[0] != '\0');
				break;
				
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				return 1;
		}
	}

	if (settings->verbose) printf("Finished processing command-line args\n");

	// If needed, increase rlimits to allow as many connections as needed.
	if (settings->verbose) printf("Settings Max connections: %d\n", settings->maxconns);
	assert(settings->maxconns > 0);
 	set_maxconns(settings->maxconns);

	// if we are supplied with a username, drop privs to it.  This will only 
	// work if we are running as root, and is really only needed when running as 
	// a daemon.
	if (settings->username != NULL) {
		if (settings->verbose) printf("Dropping privs and changing username: '******'\n", settings->username);
		if (drop_privs(settings->username) != 0) {
			usage();
			exit(EXIT_FAILURE);
		}
	}

	// daemonize if requested
	// if we want to ensure our ability to dump core, don't chdir to /
	if (settings->daemonize) {
		int res;
		if (settings->verbose) printf("Daemonising\n");
		res = daemon(0, settings->verbose);
		if (res == -1) {
			fprintf(stderr, "failed to daemon() in order to daemonize\n");
			exit(EXIT_FAILURE);
		}
	}

	// initialize main thread libevent instance
	if (settings->verbose) printf("Initialising the event system.\n");
	main_event_base = event_init();


	if (settings->verbose) printf("Ignoring SIGPIPE interrupts\n");
	ignore_sigpipe();
    
	// save the PID in if we're a daemon, do this after thread_init due to a 
	// file descriptor handling bug somewhere in libevent
	if (settings->daemonize && settings->pid_file) {
		if (settings->verbose) printf("Saving Pid file: %s\n", settings->pid_file);
		save_pid(getpid(), settings->pid_file);
	}

	// create and init the 'server' structure.
	if (settings->verbose) printf("Starting server listener on port %d.\n", settings->port);
	server = server_new(settings->port, settings->maxconns, settings->interface);
	if (server == NULL) {
		fprintf(stderr, "Failed to listen on port %d\n", settings->port);
		exit(EXIT_FAILURE);
	}
	assert(server != NULL);
	server->verbose = settings->verbose;

	server->storepath = settings->storepath;
	
	
	// add the server to the event base
	assert(main_event_base != NULL);
	server_add_event(server, main_event_base);



	// initialise clock event.  The clock event is used to keep up our node 
	// network.  If we dont have enough connections, we will need to make some 
	// requests.  
	// create the timeout structure, and the timeout event.   This is used to 
	// perform certain things spread over time.   Such as indexing the 
	// 'complete' paths that we have, and ensuring that the 'chunks' parts are 
	// valid.
	if (settings->verbose) printf("Setting up Timeout event.\n");
	timeout = (timeout_t *) malloc(sizeof(timeout_t));

	assert(timeout != NULL);
	assert(main_event_base != NULL);
	if (settings->verbose) printf("Initialising timeout.\n");
	timeout_init(timeout, main_event_base);
	timeout->server = server;

	stats = (stats_t *) malloc(sizeof(stats_t));
	stats->out_bytes = 0;
	stats->in_bytes = 0;
	stats->commands = 0;
	stats->operations = 0;

	server->stats = stats;
	timeout->stats = stats;

	// Initialise the risp system.
	risp = risp_init();
	assert(risp != NULL);
	risp_add_invalid(risp, cmdInvalid);
	risp_add_command(risp, CMD_CLEAR, 	     &cmdClear);
	risp_add_command(risp, CMD_EXECUTE,      &cmdExecute);
	risp_add_command(risp, CMD_LIST,         &cmdList);
	risp_add_command(risp, CMD_LISTING, 	 &cmdListing);
	risp_add_command(risp, CMD_LISTING_DONE, &cmdListingDone);
	risp_add_command(risp, CMD_PUT,      	 &cmdPut);
	risp_add_command(risp, CMD_GET,          &cmdGet);
	risp_add_command(risp, CMD_SIZE,         &cmdSize);
	risp_add_command(risp, CMD_OFFSET,       &cmdOffset);
	risp_add_command(risp, CMD_FILE,         &cmdFile);
	risp_add_command(risp, CMD_DATA,         &cmdData);

	assert(server->risp == NULL);
	server->risp = risp;

	

	// enter the event loop.
	if (settings->verbose) printf("Starting Event Loop\n\n");
		event_base_loop(main_event_base, 0);
    
	// cleanup risp library.
	risp_shutdown(risp);
	risp = NULL;
    
	// cleanup 'server', which should cleanup all the 'nodes'
    
	if (settings->verbose) printf("\n\nExiting.\n");
    
	// remove the PID file if we're a daemon
	if (settings->daemonize && settings->pid_file != NULL) {
		if (settings->verbose) printf("Removing pid file: %s\n", settings->pid_file);
		remove_pidfile(settings->pid_file);
	}

	assert(settings != NULL);
	settings_cleanup(settings);
	settings = NULL;

	return 0;
}
Exemplo n.º 9
0
Arquivo: commands.c Projeto: hyper/rqd
void command_init(risp_t *risp)
{
	assert(risp);
	risp_add_command(risp, RQ_CMD_CLEAR,        &cmdClear);
	risp_add_command(risp, RQ_CMD_PING,         &cmdPing);
	risp_add_command(risp, RQ_CMD_PONG,         &cmdPong);
	risp_add_command(risp, RQ_CMD_REQUEST,      &cmdRequest);
	risp_add_command(risp, RQ_CMD_REPLY,        &cmdReply);
	risp_add_command(risp, RQ_CMD_DELIVERED,    &cmdDelivered);
	risp_add_command(risp, RQ_CMD_BROADCAST,    &cmdBroadcast);
	risp_add_command(risp, RQ_CMD_NOREPLY,      &cmdNoReply);
	risp_add_command(risp, RQ_CMD_CONSUME,      &cmdConsume);
	risp_add_command(risp, RQ_CMD_CANCEL_QUEUE, &cmdCancelQueue);
	risp_add_command(risp, RQ_CMD_CONSUMING,    &cmdConsuming);
	risp_add_command(risp, RQ_CMD_CLOSING,      &cmdClosing);
	risp_add_command(risp, RQ_CMD_EXCLUSIVE,    &cmdExclusive);
	risp_add_command(risp, RQ_CMD_QUEUEID,      &cmdQueueID);
	risp_add_command(risp, RQ_CMD_ID,           &cmdId);
	risp_add_command(risp, RQ_CMD_TIMEOUT,      &cmdTimeout);
	risp_add_command(risp, RQ_CMD_MAX,          &cmdMax);
	risp_add_command(risp, RQ_CMD_PRIORITY,     &cmdPriority);
	risp_add_command(risp, RQ_CMD_QUEUE,        &cmdQueue);
	risp_add_command(risp, RQ_CMD_PAYLOAD,      &cmdPayload);
}
Exemplo n.º 10
0
//-----------------------------------------------------------------------------
// Main... process command line parameters, and if we have enough information, then create an empty stash.
int main(int argc, char **argv) 
{
	int c;
	master_t master;
	storage_t *storage;
	
	const char *filename = NULL;
	
	assert(argc >= 0);
	assert(argv);
	
	// initialise the master structure that we will be passing through the risp process.
	master.risp_top = NULL;
	master.risp_op = NULL;
	master.risp_payload = NULL;
	master.risp_data = NULL;
	
	
	// process arguments
	/// Need to check the options in here, there're possibly ones that we dont need.
	while ((c = getopt(argc, argv, "hvf:")) != -1) {
		switch (c) {
			case 'h':
				usage();
				exit(EXIT_SUCCESS);
			case 'v':
				verbose++;
				break;
			case 'f':
				filename = optarg;
				break;
				
			default:
				fprintf(stderr, "Illegal argument \"%c\"\n", c);
				exit(1);
		}
	}
	
	// check that our required params are there:
	if (filename == NULL) {
		fprintf(stderr, "requires: -f <filename>\n");
		exit(1);
	}

	// create the top-level risp interface.
	master.risp_top = risp_init(NULL);
	assert(master.risp_top != NULL);
	risp_add_command(master.risp_top, STASH_CMD_CLEAR,         &cmdClear);
	risp_add_command(master.risp_top, STASH_CMD_FILE_SEQ,      &cmdFileSeq);
	risp_add_command(master.risp_top, STASH_CMD_OPERATION,     &cmdOperation);
	risp_add_command(master.risp_top, STASH_CMD_NEXT_VOLUME,   &cmdNextVolume);

	master.risp_op = risp_init(NULL);
	assert(master.risp_op);
	
	master.risp_payload = risp_init(NULL);
	assert(master.risp_payload);
	risp_add_command(master.risp_payload, STASH_CMD_CREATE_USER,      &cmdCreateUser);
	risp_add_command(master.risp_payload, STASH_CMD_CREATE_NAMESPACE, &cmdCreateNamespace);
	risp_add_command(master.risp_payload, STASH_CMD_SET_PASSWORD,     &cmdSetPassword);
	risp_add_command(master.risp_payload, STASH_CMD_GRANT,            &cmdGrant);
	risp_add_command(master.risp_payload, STASH_CMD_CREATE_TABLE,     &cmdCreateTable);
	risp_add_command(master.risp_payload, STASH_CMD_CREATE_KEY,       &cmdCreateKey);
	risp_add_command(master.risp_payload, STASH_CMD_CREATE_NAME,      &cmdCreateName);
	risp_add_command(master.risp_payload, STASH_CMD_CREATE_ROW,       &cmdCreateRow);
	risp_add_command(master.risp_payload, STASH_CMD_SET,              &cmdSet);
	risp_add_command(master.risp_payload, STASH_CMD_DELETE,           &cmdDelete);
	
	
	// 	risp_add_command(master.risp_payload, STASH_CMD_DROP_USER,       &cmdDropUser);
	
	master.risp_data = risp_init(NULL);
	assert(master.risp_data);
	
	storage = storage_init(NULL);
	assert(storage);
		
	if (storage_lock_file(storage, filename) == 0) {
		fprintf(stderr, "Unable to open file, it appears to be locked.\n");
		exit(1);
	}
	else {
		
		// we were able to lock the file, so we can continue.   From this point on, we cannot exit without unlocking the file.
		
		// TODO: We should intercept the signals at this point to ensure that the lock gets released.
		
		// process the main meta file;
		storage_process_file(storage, filename, master.risp_top, &master);
		
		storage_unlock_file(storage, filename);
		
	}

	// cleanup the risp interface.
	assert(master.risp_top);
	risp_shutdown(master.risp_top);
	master.risp_top = NULL;
	
	assert(master.risp_op);
	risp_shutdown(master.risp_op);
	master.risp_op = NULL;
	
	assert(master.risp_payload);
	risp_shutdown(master.risp_payload);
	master.risp_payload = NULL;
	
	assert(master.risp_data);
	risp_shutdown(master.risp_data);
	master.risp_data = NULL;
	

	assert(storage);
	storage_free(storage);
	storage = NULL;

	assert(master.risp_top == NULL);
	
	return 0;
}