コード例 #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];
}
コード例 #2
0
void ape_dns_init(acetables *g_ape)
{
	int sock = dns_init(NULL, 1);

	prepare_ape_socket(sock, g_ape);
	
	g_ape->co[sock]->fd = sock;
	g_ape->co[sock]->stream_type = STREAM_DELEGATE;

	g_ape->co[sock]->callbacks.on_read = ape_dns_read;
	g_ape->co[sock]->callbacks.on_write = ape_dns_write;

	events_add(g_ape->events, sock, EVENT_READ|EVENT_WRITE);

	dns_timer_id = add_ticked(ape_dns_timeout, NULL)->identifier;
}
コード例 #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];	
}
コード例 #4
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;
}