Beispiel #1
0
ape_socket *ape_listen(unsigned int port, char *listen_ip, acetables *g_ape)
{
	int sock;
	struct sockaddr_in addr;
	int reuse_addr = 1;
	
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_listen() - socket()");
		return NULL;
	}
	
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	//addr.sin_addr.s_addr = inet_addr(CONFIG_VAL(Server, ip_listen, g_ape->srv));
	
	addr.sin_addr.s_addr = inet_addr(listen_ip);
	
	memset(&(addr.sin_zero), '\0', 8);
	
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

	if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1)
	{
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_listen() - bind()");
		printf("Error: cannot bind to port %i; %s\n", port, strerror(errno));
		ape_server_is_running = 0;
		return NULL;
	}

	if (listen(sock, 2048) == -1)
	{
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_listen() - listen()");
		return NULL;
	}

	setnonblocking(sock);

	prepare_ape_socket(sock, g_ape);

	g_ape->co[sock]->fd = sock;
	g_ape->co[sock]->state = STREAM_ONLINE;
	g_ape->co[sock]->stream_type = STREAM_SERVER;
	
	events_add(g_ape->events, sock, EVENT_READ);
	
	return g_ape->co[sock];
}
Beispiel #2
0
USERS *adduser(ape_socket *client, const char *host, const char *ip, USERS *allocated, acetables *g_ape)
{
	USERS *nuser = NULL;

	/* Calling module */
	if (allocated == NULL) {
		FIRE_EVENT(allocateuser, nuser, client, host, ip, g_ape);
		
		nuser = init_user(g_ape);
		strncpy(nuser->ip, ip, 16);
		
		nuser->pipe = init_pipe(nuser, USER_PIPE, g_ape);
		nuser->type = (client != NULL ? HUMAN : BOT);
		
		nuser->istmp = 1;
		
		hashtbl_append(g_ape->hSessid, nuser->sessid, (void *)nuser);

		addsubuser(client, host, nuser, g_ape);
	} else {
		FIRE_EVENT(adduser, nuser, allocated, g_ape);
		
		nuser = allocated;
		nuser->istmp = 0;
		
		g_ape->nConnected++;
		
		ape_log(APE_INFO, __FILE__, __LINE__, g_ape, 
			"New user - (ip : %s)", nuser->ip);
	}

	return nuser;
	
}
Beispiel #3
0
ape_socket *ape_connect(char *ip, int port, acetables *g_ape)
{
	int sock, ret;
	struct sockaddr_in addr;
	
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_connect() - socket() : %s", strerror(errno));
		return NULL;
	}

	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);
	memset(&(addr.sin_zero), '\0', 8);

	setnonblocking(sock);
	
	if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == 0 || errno != EINPROGRESS) {
		return NULL;
	}

	prepare_ape_socket(sock, g_ape);
	
	g_ape->co[sock]->buffer_in.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1));
	g_ape->co[sock]->buffer_in.size = DEFAULT_BUFFER_SIZE;

	g_ape->co[sock]->fd = sock;
	g_ape->co[sock]->state = STREAM_PROGRESS;
	g_ape->co[sock]->stream_type = STREAM_OUT;
	
	g_ape->bufout[sock].fd = sock;
	g_ape->bufout[sock].buf = NULL;
	g_ape->bufout[sock].buflen = 0;
	g_ape->bufout[sock].allocsize = 0;

	ret = events_add(g_ape->events, sock, EVENT_READ|EVENT_WRITE);
	
	return g_ape->co[sock];	
}
Beispiel #4
0
int main(int argc, char **argv) 
{
	apeconfig *srv;
	
	int random, im_r00t = 0, pidfd = 0, serverfd;
	unsigned int getrandom = 0, ct_id;
	const char *pidfile = NULL;
	char *confs_path = NULL;
	
	struct _fdevent fdev;
	
	char cfgfile[513] = APE_CONFIG_FILE;
	
	acetables *g_ape;
	
	if (argc > 1 && strcmp(argv[1], "--version") == 0) {
		printf("\n   AJAX Push Engine Server %s - (C) Anthony Catel <*****@*****.**>\n   http://www.ape-project.org/\n\n", _VERSION);
		return 0;
	}
	if (argc > 1 && strcmp(argv[1], "--help") == 0) {
		printf("\n   AJAX Push Engine Server %s - (C) Anthony Catel <*****@*****.**>\n   http://www.ape-project.org/\n", _VERSION);
		printf("\n   usage: aped [options]\n\n");
		printf("   Options:\n     --help             : Display this help\n     --version          : Show version number\n     --cfg <config path>: Load a specific config file (default is %s)\n\n", cfgfile);
		return 0;
	} else if (argc > 2 && strcmp(argv[1], "--cfg") == 0) {
		memset(cfgfile, 0, 513);
		strncpy(cfgfile, argv[2], 512);
		confs_path = get_path(cfgfile);
	} else if (argc > 1) {
		printf("\n   AJAX Push Engine Server %s - (C) Anthony Catel <*****@*****.**>\n   http://www.ape-project.org/\n\n", _VERSION);
		printf("   Unknown parameters - check \"aped --help\"\n\n");
		return 0;
	}
	if (NULL == (srv = ape_config_load(cfgfile))) {
		printf("\nExited...\n\n");
		exit(1);
	}
	
	if (getuid() == 0) {
		im_r00t = 1;
	}

	signal(SIGINT, &signal_handler);
	signal(SIGTERM, &signal_handler);
	
	if (VTICKS_RATE < 1) {
		printf("[ERR] TICKS_RATE cant be less than 1\n");
		return 0;
	}
	
	random = open("/dev/urandom", O_RDONLY);
	if (!random) {
		printf("Cannot open /dev/urandom... exiting\n");
		return 0;
	}
	read(random, &getrandom, 3);
	srand(getrandom);
	close(random);

	g_ape = xmalloc(sizeof(*g_ape));
	g_ape->basemem = 1; // set 1 for testing if growup works
	g_ape->srv = srv;
	g_ape->confs_path = confs_path;
	g_ape->is_daemon = 0;
	
	ape_log_init(g_ape);
	
	fdev.handler = EVENT_UNKNOWN;

	#ifdef USE_EPOLL_HANDLER
	fdev.handler = EVENT_EPOLL;
	#endif
	#ifdef USE_KQUEUE_HANDLER
	fdev.handler = EVENT_KQUEUE;
	#endif

	g_ape->co = xmalloc(sizeof(*g_ape->co) * g_ape->basemem);
	memset(g_ape->co, 0, sizeof(*g_ape->co) * g_ape->basemem);
	
	g_ape->bad_cmd_callbacks = NULL;
	g_ape->bufout = xmalloc(sizeof(struct _socks_bufout) * g_ape->basemem);
	
	g_ape->timers.timers = NULL;
	g_ape->timers.ntimers = 0;
	g_ape->events = &fdev;
	if (events_init(g_ape, &g_ape->basemem) == -1) {
		printf("Fatal error: APE compiled without an event handler... exiting\n");
		return 0;
	};
	
	serverfd = servers_init(g_ape);
	
	ape_log(APE_INFO, __FILE__, __LINE__, g_ape, 
		"APE starting up - pid : %i", getpid());
	
	if (strcmp(CONFIG_VAL(Server, daemon, srv), "yes") == 0 && (pidfile = CONFIG_VAL(Server, pid_file, srv)) != NULL) {
		if ((pidfd = open(pidfile, O_TRUNC | O_WRONLY | O_CREAT, 0655)) == -1) {
			ape_log(APE_WARN, __FILE__, __LINE__, g_ape, 
				"Cant open pid file : %s", CONFIG_VAL(Server, pid_file, srv));
		}
	}
	
	if (im_r00t) {
		struct group *grp = NULL;
		struct passwd *pwd = NULL;
		
		if (inc_rlimit(atoi(CONFIG_VAL(Server, rlimit_nofile, srv))) == -1) {
			ape_log(APE_WARN, __FILE__, __LINE__, g_ape, 
				"Cannot set the max filedescriptos limit (setrlimit) %s", strerror(errno));
		}
		
		/* Set uid when uid section exists */
		if (ape_config_get_section(srv, "uid")) {

			/* Get the user information (uid section) */
			if ((pwd = getpwnam(CONFIG_VAL(uid, user, srv))) == NULL) {
				ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
					"Can\'t find username %s", CONFIG_VAL(uid, user, srv));
				return -1;
			}
			if (pwd->pw_uid == 0) {
				ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
					"%s uid can\'t be 0", CONFIG_VAL(uid, user, srv));
				return -1;			
			}
			
			/* Get the group information (uid section) */
			if ((grp = getgrnam(CONFIG_VAL(uid, group, srv))) == NULL) {
				printf("[ERR] Can\'t find group %s\n", CONFIG_VAL(uid, group, srv));
				ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
					"Can\'t find group %s", CONFIG_VAL(uid, group, srv));
				return -1;
			}
			
			if (grp->gr_gid == 0) {
				ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
				"%s gid can\'t be 0", CONFIG_VAL(uid, group, srv));
			return -1;
			}
		
			setgid(grp->gr_gid);
			setgroups(0, NULL);

			initgroups(CONFIG_VAL(uid, user, srv), grp->gr_gid);
		
			setuid(pwd->pw_uid);
		}

	} else {
		printf("[WARN] You have to run \'aped\' as root to increase r_limit\n");
		ape_log(APE_WARN, __FILE__, __LINE__, g_ape, 
			"You have to run \'aped\' as root to increase r_limit");
	}
	
	if (strcmp(CONFIG_VAL(Server, daemon, srv), "yes") == 0) {
		ape_log(APE_INFO, __FILE__, __LINE__, g_ape, 
			"Starting daemon");
		ape_daemon(pidfd, g_ape);

		events_reload(g_ape->events);
		events_add(g_ape->events, serverfd, EVENT_READ);
	}
	
	if (!g_ape->is_daemon) {	
		printf("   _   ___ ___ \n");
		printf("  /_\\ | _ \\ __|\n");
		printf(" / _ \\|  _/ _| \n");
		printf("/_/ \\_\\_| |___|\nAJAX Push Engine\n\n");

		printf("Bind on port %i\n\n", atoi(CONFIG_VAL(Server, port, srv)));
		printf("Version : %s\n", _VERSION);
		printf("Build   : %s %s\n", __DATE__, __TIME__);
		printf("Author  : Weelya ([email protected])\n\n");		
	}
	signal(SIGPIPE, SIG_IGN);
	
	ape_dns_init(g_ape);
	
	g_ape->cmd_hook.head = NULL;
	g_ape->cmd_hook.foot = NULL;
	
	g_ape->hSessid = hashtbl_init();

	g_ape->hChannel = hashtbl_init();
	g_ape->hPubid = hashtbl_init();
	
	g_ape->proxy.list = NULL;
	g_ape->proxy.hosts = NULL;
	
	g_ape->hCallback = hashtbl_init();

	g_ape->uHead = NULL;
	g_ape->cHead = NULL;
	
	g_ape->nConnected = 0;
	g_ape->plugins = NULL;
	
	g_ape->properties = NULL;

	ct_id = add_ticked(check_timeout, g_ape)->identifier;
	
	do_register(g_ape);
	
	transport_start(g_ape);	
	
	findandloadplugin(g_ape);

	server_is_running = 1;
	server_is_shutdowning = 0;

	/* Starting Up */
	sockroutine(g_ape); /* loop */
	/* Shutdown */	
	
	if (pidfile != NULL) {
		unlink(pidfile);
	}
	
	free(confs_path);

	ape_dns_free(g_ape);

	del_timer_identifier(ct_id, g_ape);

	events_free(g_ape);

	transport_free(g_ape);

	hashtbl_free(g_ape->hSessid, 0);
	hashtbl_free(g_ape->hChannel, 0);
	hashtbl_free(g_ape->hPubid, 0);
	
	do_unregister(g_ape);
	hashtbl_free(g_ape->hCallback, 1);
	
	ape_config_free(srv);

	int i;
	for (i = 0; i < g_ape->basemem; i++) {
		if (g_ape->co[i] != NULL) {
			close_socket(i, g_ape);
			free(g_ape->co[i]);
		}
	}
	free(g_ape->co);

	free(g_ape->bufout);

	free_all_hook_cmd(g_ape);
	free_all_plugins(g_ape);

	free(g_ape);
	
	return 0;
}
Beispiel #5
0
unsigned int sockroutine(acetables *g_ape)
{
	struct _socks_list sl;

	int new_fd, nfds, sin_size = sizeof(struct sockaddr_in), i, tfd = 0;

	struct timeval t_start, t_end;	
	long int ticks = 0, uticks = 0, lticks = 0;
	struct sockaddr_in their_addr;
	
	//sl.co = co;
	sl.tfd = &tfd;

	#if 0
	add_periodical(5, 0, check_idle, &sl, g_ape);
	#endif
	gettimeofday(&t_start, NULL);
	while (ape_server_is_running) {
		/* Linux 2.6.25 provides a fd-driven timer system. It could be usefull to implement */
		int timeout_to_hang = get_first_timer_ms(g_ape);
		nfds = events_poll(g_ape->events, timeout_to_hang);

		if (nfds < 0) {
			ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
				"events_poll() : %s", strerror(errno));
			continue;
		}
		
		if (nfds > 0) {
			for (i = 0; i < nfds; i++) {

				int active_fd = events_get_current_fd(g_ape->events, i);

				if (g_ape->co[active_fd]->stream_type == STREAM_SERVER) {
					int bitev = events_revent(g_ape->events, i);
					
					if (!(bitev & EVENT_READ)) {
						/* Close server socket */
						close_socket(active_fd, g_ape);
						continue;
					}
					
					while (1) {

						//http_state http = {NULL, 0, -1, 0, 0, HTTP_NULL, 0, 0};
					
						new_fd = accept(active_fd, 
							(struct sockaddr *)&their_addr,
							(unsigned int *)&sin_size);

						if (new_fd == -1) {
							break;
						}

						prepare_ape_socket(new_fd, g_ape);
	
						strncpy(g_ape->co[new_fd]->ip_client, inet_ntoa(their_addr.sin_addr), 16);
						
						g_ape->co[new_fd]->buffer_in.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1));
						g_ape->co[new_fd]->buffer_in.size = DEFAULT_BUFFER_SIZE;

						g_ape->co[new_fd]->idle = time(NULL);
						g_ape->co[new_fd]->fd = new_fd;

						g_ape->co[new_fd]->state = STREAM_ONLINE;
						g_ape->co[new_fd]->stream_type = STREAM_IN;
					
						g_ape->bufout[new_fd].fd = new_fd;
						g_ape->bufout[new_fd].buf = NULL;
						g_ape->bufout[new_fd].buflen = 0;
						g_ape->bufout[new_fd].allocsize = 0;
						
						g_ape->co[new_fd]->callbacks.on_disconnect = g_ape->co[active_fd]->callbacks.on_disconnect;
						g_ape->co[new_fd]->callbacks.on_read = g_ape->co[active_fd]->callbacks.on_read;
						g_ape->co[new_fd]->callbacks.on_read_lf = g_ape->co[active_fd]->callbacks.on_read_lf;
						g_ape->co[new_fd]->callbacks.on_data_completly_sent = g_ape->co[active_fd]->callbacks.on_data_completly_sent;
						g_ape->co[new_fd]->callbacks.on_write = g_ape->co[active_fd]->callbacks.on_write;
						
						g_ape->co[new_fd]->attach = g_ape->co[active_fd]->attach;
						
						setnonblocking(new_fd);
						
						events_add(g_ape->events, new_fd, EVENT_READ|EVENT_WRITE);
						
						tfd++;
						
						if (g_ape->co[active_fd]->callbacks.on_accept != NULL) {
							g_ape->co[active_fd]->callbacks.on_accept(g_ape->co[new_fd], g_ape);
						}
					
					}
					continue;
				} else {
					int readb = 0;
					int bitev = events_revent(g_ape->events, i);
						
					if (bitev & EVENT_WRITE) {

						if (g_ape->co[active_fd]->stream_type == STREAM_OUT && g_ape->co[active_fd]->state == STREAM_PROGRESS) {
							
							int serror = 0, ret;
							socklen_t serror_len = sizeof(serror);
						
							ret = getsockopt(active_fd, SOL_SOCKET, SO_ERROR, &serror, &serror_len);
							
							if (ret == 0 && serror == 0) {

								g_ape->co[active_fd]->state = STREAM_ONLINE;
								if (g_ape->co[active_fd]->callbacks.on_connect != NULL) {

									g_ape->co[active_fd]->callbacks.on_connect(g_ape->co[active_fd], g_ape);
								}
							} else { /* This can happen ? epoll seems set EPOLLIN as if the host is disconnecting */

								if (g_ape->co[active_fd]->callbacks.on_disconnect != NULL) {
									g_ape->co[active_fd]->callbacks.on_disconnect(g_ape->co[active_fd], g_ape);
								}

								close_socket(active_fd, g_ape);
								tfd--;
								continue;
							}							
						} else if (g_ape->bufout[active_fd].buf != NULL) {

							if (sendqueue(active_fd, g_ape) == 1) {
								
								if (g_ape->co[active_fd]->callbacks.on_data_completly_sent != NULL) {
									g_ape->co[active_fd]->callbacks.on_data_completly_sent(g_ape->co[active_fd], g_ape);
								}
								
								if (g_ape->co[active_fd]->burn_after_writing) {
									shutdown(active_fd, 2);
									g_ape->co[active_fd]->burn_after_writing = 0;
								}

							}
						} else if (g_ape->co[active_fd]->stream_type == STREAM_DELEGATE) {
							if (g_ape->co[active_fd]->callbacks.on_write != NULL) {
								g_ape->co[active_fd]->callbacks.on_write(g_ape->co[active_fd], g_ape);

							}							
						}
					}

					if (bitev & EVENT_READ) {

						if (g_ape->co[active_fd]->stream_type == STREAM_DELEGATE) {
							if (g_ape->co[active_fd]->callbacks.on_read != NULL) {
								g_ape->co[active_fd]->callbacks.on_read(g_ape->co[active_fd], NULL, 0, g_ape);
								continue;
							}							
						}
						do {
							/*
								TODO : Check if maximum data read can improve perf
								Huge data may attempt to increase third parameter
							*/
							readb = read(active_fd, 
										g_ape->co[active_fd]->buffer_in.data + g_ape->co[active_fd]->buffer_in.length, 
										g_ape->co[active_fd]->buffer_in.size - g_ape->co[active_fd]->buffer_in.length);
						
							if (readb == -1 && errno == EAGAIN) {

								if (g_ape->co[active_fd]->stream_type == STREAM_OUT) {
									
										//proxy_process_eol(&co[active_fd], g_ape);
										//co[active_fd].buffer_in.length = 0;
								} else {
								//	co[active_fd].buffer_in.data[co[active_fd].buffer_in.length] = '\0';
								}
								break;
							} else {
								if (readb < 1) {

									if (g_ape->co[active_fd]->callbacks.on_disconnect != NULL) {
										g_ape->co[active_fd]->callbacks.on_disconnect(g_ape->co[active_fd], g_ape);
									}
									
									close_socket(active_fd, g_ape);
									tfd--;
									
									break;
								} else {
									
									g_ape->co[active_fd]->buffer_in.length += readb;
									
									/* realloc the buffer for the next read (x2) */
									if (g_ape->co[active_fd]->buffer_in.length == g_ape->co[active_fd]->buffer_in.size) {
										g_ape->co[active_fd]->buffer_in.size *= 2;

										g_ape->co[active_fd]->buffer_in.data = xrealloc(g_ape->co[active_fd]->buffer_in.data, 
																sizeof(char) * (g_ape->co[active_fd]->buffer_in.size + 1));

									}
									if (g_ape->co[active_fd]->callbacks.on_read_lf != NULL) {
										unsigned int eol, *len = &g_ape->co[active_fd]->buffer_in.length;
										char *pBuf = g_ape->co[active_fd]->buffer_in.data;

										while ((eol = sneof(pBuf, *len, 4096)) != -1) {
											pBuf[eol-1] = '\0';
											g_ape->co[active_fd]->callbacks.on_read_lf(g_ape->co[active_fd], pBuf, g_ape);
											pBuf = &pBuf[eol];
											*len -= eol;
										}
										if (*len > 4096 || !*len) {
											g_ape->co[active_fd]->buffer_in.length = 0;
										} else if (*len && pBuf != g_ape->co[active_fd]->buffer_in.data) {
											
											memmove(g_ape->co[active_fd]->buffer_in.data, 
												pBuf, 
												*len);

										}

									}
									
									/* on_read can't get along with on_read_lf */
									if (g_ape->co[active_fd]->callbacks.on_read != NULL && g_ape->co[active_fd]->callbacks.on_read_lf == NULL) {
										g_ape->co[active_fd]->callbacks.on_read(g_ape->co[active_fd], &g_ape->co[active_fd]->buffer_in, g_ape->co[active_fd]->buffer_in.length - readb, g_ape);
									}
								} 
							}
						} while(readb >= 0);
					}
				}			
			}
		}
		
		gettimeofday(&t_end, NULL);
		
		ticks = 0;
		
		uticks = 1000000L * (t_end.tv_sec - t_start.tv_sec);
		uticks += (t_end.tv_usec - t_start.tv_usec);
		t_start = t_end;
		lticks += uticks;
		/* Tic tac, tic tac */

		while (lticks >= 1000) {
			lticks -= 1000;
			process_tick(g_ape);
		}		
	}

	return 0;
}
Beispiel #6
0
/* Just a lightweight http request processor */
void process_http(ape_socket *co, acetables *g_ape)
{
	ape_buffer *buffer = &co->buffer_in;
	http_state *http = co->parser.data;
	ape_parser *parser = &co->parser;
	
	char *data = buffer->data;
	int pos, read, p = 0;
	
	if (buffer->length == 0 || parser->ready == 1 || http->error == 1) {
		return;
	}

	/* 0 will be erased by the next read()'ing loop */
	data[buffer->length] = '\0';
	
	data = &data[http->pos];
	
	if (*data == '\0') {
		return;
	}
	
	/* Update the address of http->data and http->uri if buffer->data has changed (realloc) */
	if (http->buffer_addr != NULL && buffer->data != http->buffer_addr) {
		if (http->data != NULL) http->data = &buffer->data[(void *)http->data - (void *)http->buffer_addr];
		if (http->uri != NULL) http->uri = &buffer->data[(void *)http->uri - (void *)http->buffer_addr];
		http->buffer_addr = buffer->data;
	}
	
	switch(http->step) {
		case 0:
			pos = seof(data, '\n');
			if (pos == -1) {
				return;
			}
			
			switch(*(unsigned int *)data) {
#ifdef _LITTLE_ENDIAN
				case 0x20544547: /* GET + space */
#endif
#ifdef _BIG_ENDIAN
				case 0x47455420: /* GET + space */
#endif
					http->type = HTTP_GET;
					p = 4;
					break;
#ifdef _LITTLE_ENDIAN
				case 0x54534F50: /* POST */
#endif
#ifdef _BIG_ENDIAN
				case 0x504F5354: /* POST */
#endif
					http->type = HTTP_POST;
					p = 5;
					break;
				default:
					ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid HTTP method in request: %s", data);
					http->error = 1;
					shutdown(co->fd, 2);
					return;
			}
			
			if (data[p] != '/') {
				http->error = 1;
				shutdown(co->fd, 2);
				return;
			} else {
				int i = p;
				while (p++) {
					switch(data[p]) {
						case ' ':
							http->pos = pos;
							http->step = 1;
							http->uri = &data[i];
							http->buffer_addr = buffer->data;
							data[p] = '\0';
							process_http(co, g_ape);
							return;
						case '?':
							if (data[p+1] != ' ' && data[p+1] != '\r' && data[p+1] != '\n') {
								http->buffer_addr = buffer->data;
								http->data = &data[p+1];
							}
							break;
						case '\r':
						case '\n':
						case '\0':
							ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid line ending in request: %s", data);
							http->error = 1;
							shutdown(co->fd, 2);
							return;
					}
				}
			}
			break;
		case 1:
			pos = seof(data, '\n');
			if (pos == -1) {

				return;
			}
			if (pos == 1 || (pos == 2 && *data == '\r')) {
				if (http->type == HTTP_GET) {
					/* Ok, at this point we have a blank line. Ready for GET */
					buffer->data[http->pos] = '\0';
					urldecode(http->uri);
					parser->onready(parser, g_ape);
					parser->ready = -1;
					buffer->length = 0;
					return;
				} else if (http->type == HTTP_GET_WS) { /* WebSockets handshake needs to read 8 bytes */
					//urldecode(http->uri);
					http->contentlength = 8;
					http->buffer_addr = buffer->data;
					http->data = &buffer->data[http->pos+(pos)];
					http->step = 2;
				} else {
					/* Content-Length is mandatory in case of POST */
					if (http->contentlength == 0) {
						http->error = 1;
						shutdown(co->fd, 2);
						return;
					} else {
						http->buffer_addr = buffer->data; // save the addr
						http->data = &buffer->data[http->pos+(pos)];
						http->step = 2;
					}
				}
			} else {
				struct _http_header_line *hl;

				if ((hl = parse_header_line(data)) != NULL) {
					hl->next = http->hlines;
					http->hlines = hl;
					if (strcasecmp(hl->key.val, "host") == 0) {
						http->host = hl->value.val;
					}
				}
				if (http->type == HTTP_POST) {
					/* looking for content-length instruction */
					if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) {
						int cl = atoi(&data[16]);

						/* Content-length can't be negative... */
						if (cl < 1 || cl > MAX_CONTENT_LENGTH) {
							http->error = 1;
							shutdown(co->fd, 2);
							return;
						}
						/* At this time we are ready to read "cl" bytes contents */
						http->contentlength = cl;

					}
				} else if (http->type == HTTP_GET) {
					if (strncasecmp("Sec-WebSocket-Key1: ", data, 20) == 0) {
						http->type = HTTP_GET_WS;
					}
				}
			}
			http->pos += pos;
			process_http(co, g_ape);
			break;
		case 2:
			read = buffer->length - http->pos; // data length
			http->pos += read;
			http->read += read;
			
			if (http->read >= http->contentlength) {

				parser->ready = 1;
				urldecode(http->uri);
				/* no more than content-length */
				buffer->data[http->pos - (http->read - http->contentlength)] = '\0';
				
				parser->onready(parser, g_ape);
				parser->ready = -1;
				buffer->length = 0;
			}
			break;
		default:
			break;
	}
}
Beispiel #7
0
ape_socket *ape_listen(unsigned int port, char *listen_ip, acetables *g_ape)
{
	int sock;
	struct sockaddr_in addr;
	int reuse_addr = 1;
	ape_socket *co = g_ape->co;
	
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_listen() - socket()");
		return NULL;
	}
	
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	//addr.sin_addr.s_addr = inet_addr(CONFIG_VAL(Server, ip_listen, g_ape->srv));
	
	addr.sin_addr.s_addr = inet_addr(listen_ip);
	
	memset(&(addr.sin_zero), '\0', 8);
	
	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

	if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1)
	{
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_listen() - bind()");
		printf("ERREUR: bind(%i) (non-root ?).. (%s line: %i)\n", port, __FILE__, __LINE__);
		return NULL;
	}

	if (listen(sock, 2048) == -1)
	{
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_listen() - listen()");
		return NULL;
	}
	
	setnonblocking(sock);
	if (sock + 4 >= g_ape->basemem) {
		/* Increase connection & events size */
		growup(&g_ape->basemem, &g_ape->co, g_ape->events, &g_ape->bufout);
		co = g_ape->co;
	}
	
	co[sock].buffer_in.data = NULL;
	co[sock].buffer_in.size = 0;
	co[sock].buffer_in.length = 0;

	co[sock].attach = NULL;
	co[sock].idle = 0;
	co[sock].burn_after_writing = 0;
	co[sock].fd = sock;
	
	co[sock].stream_type = STREAM_SERVER;
	co[sock].state = STREAM_ONLINE;
	
	co[sock].callbacks.on_accept = NULL;
	co[sock].callbacks.on_connect = NULL;
	co[sock].callbacks.on_disconnect = NULL;
	co[sock].callbacks.on_read = NULL;
	co[sock].callbacks.on_read_lf = NULL;
	co[sock].callbacks.on_data_completly_sent = NULL;
	co[sock].callbacks.on_write = NULL;
	
	events_add(g_ape->events, sock, EVENT_READ);
	
	return &co[sock];
}
Beispiel #8
0
ape_socket *ape_connect(char *ip, int port, acetables *g_ape)
{
	int sock, ret;
	struct sockaddr_in addr;
	ape_socket *co = g_ape->co;
	
	if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		ape_log(APE_ERR, __FILE__, __LINE__, g_ape, 
			"ape_connect() - socket() : %s", strerror(errno));
		return NULL;
	}

	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);
	memset(&(addr.sin_zero), '\0', 8);

	setnonblocking(sock);
	
	if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == 0 || errno != EINPROGRESS) {
		return NULL;
	}

	if (sock + 4 >= g_ape->basemem) {
		/* Increase connection & events size */
		growup(&g_ape->basemem, &g_ape->co, g_ape->events, &g_ape->bufout);
		co = g_ape->co;
	}

	ret = events_add(g_ape->events, sock, EVENT_READ|EVENT_WRITE);
	
	co[sock].buffer_in.data = xmalloc(sizeof(char) * (DEFAULT_BUFFER_SIZE + 1));
	co[sock].buffer_in.size = DEFAULT_BUFFER_SIZE;
	co[sock].buffer_in.length = 0;

	co[sock].buffer_in.slot = NULL;
	co[sock].buffer_in.islot = 0;

	co[sock].attach = NULL;
	co[sock].idle = 0;
	co[sock].burn_after_writing = 0;
	co[sock].fd = sock;
	
	co[sock].stream_type = STREAM_OUT;
	co[sock].state = STREAM_PROGRESS;
	
	co[sock].callbacks.on_accept = NULL;
	co[sock].callbacks.on_connect = NULL;
	co[sock].callbacks.on_disconnect = NULL;
	co[sock].callbacks.on_read = NULL;
	co[sock].callbacks.on_read_lf = NULL;
	co[sock].callbacks.on_data_completly_sent = NULL;
	co[sock].callbacks.on_write = NULL;		

	g_ape->bufout[sock].fd = sock;
	g_ape->bufout[sock].buf = NULL;
	g_ape->bufout[sock].buflen = 0;
	g_ape->bufout[sock].allocsize = 0;

	
	return &co[sock];	
}