// return 0 when failed
static int
report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) {
	union sockaddr_all u;
	socklen_t len = sizeof(u);
	int client_fd = accept(s->fd, &u.s, &len);
	if (client_fd < 0) {
		return 0;
	}
	int id = reserve_id(ss);
	if (id < 0) {
		close(client_fd);
		return 0;
	}
	sp_nonblocking(client_fd);
	struct socket *ns = new_fd(ss, id, client_fd, s->opaque, false);
	if (ns == NULL) {
		close(client_fd);
		return 0;
	}
	ns->type = SOCKET_TYPE_PACCEPT;
	result->opaque = s->opaque;
	result->id = s->id;
	result->ud = id;
	result->data = NULL;

	void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
	if (inet_ntop(u.s.sa_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
		result->data = ss->buffer;
	}

	return 1;
}
Exemple #2
0
int
socket_server_udp(struct socket_server *ss, uintptr_t opaque, const char * addr, int port) {
    int fd;
    int family;
    if (port != 0 || addr != NULL) {
        // bind
        fd = do_bind(addr, port, IPPROTO_UDP, &family);
        if (fd < 0) {
            return -1;
        }
    } else {
        family = AF_INET;
        fd = socket(family, SOCK_DGRAM, 0);
        if (fd < 0) {
            return -1;
        }
    }
    sp_nonblocking(fd);

    int id = reserve_id(ss);
    if (id < 0) {
        close(fd);
        return -1;
    }
    struct request_package request;
    request.u.udp.id = id;
    request.u.udp.fd = fd;
    request.u.udp.opaque = opaque;
    request.u.udp.family = family;

    send_request(ss, &request, 'U', sizeof(request.u.udp));
    return id;
}
// return 0 when failed
static int
report_accept(struct socket_server *ss, struct socket *s, union socket_message *result) {
	union sockaddr_all u;
	socklen_t len = sizeof(u);
	int client_fd = accept(s->fd, &u.s, &len);
	if (client_fd < 0) {
		return 0;
	}
	sp_nonblocking(client_fd);
	struct socket *ns = new_fd(ss, client_fd);
	if (ns == NULL) {
		close(client_fd);
		return 0;
	}
	ns->type = SOCKET_TYPE_CONNECTED;
	result->open.id = ns->id;
	result->open.session = s->session;
	result->open.fd = s->fd;
	result->open.addr = NULL;

	void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
	if (inet_ntop(u.s.sa_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
		result->open.addr = ss->buffer;
	}

	return 1;
}
Exemple #4
0
// return 0 when failed, or -1 when file limit
// 
static int
report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) {
	union sockaddr_all u;
	socklen_t len = sizeof(u);
	// 生成被动套接字
	int client_fd = accept(s->fd, &u.s, &len);
	if (client_fd < 0) {
		if (errno == EMFILE || errno == ENFILE) {
			result->opaque = s->opaque;
			result->id = s->id;
			result->ud = 0;
			result->data = strerror(errno);
			return -1;
		} else {
			return 0;
		}
	}
	// 分配id
	int id = reserve_id(ss);
	if (id < 0) {
		close(client_fd);
		return 0;
	}
	// 设置keepalive和非阻塞
	socket_keepalive(client_fd);
	sp_nonblocking(client_fd);
	// 创建socket实例
	struct socket *ns = new_fd(ss, id, client_fd, PROTOCOL_TCP, s->opaque, false);
	if (ns == NULL) {
		close(client_fd);
		return 0;
	}
	// 设置socket类型为PACCEPT
	ns->type = SOCKET_TYPE_PACCEPT;
	result->opaque = s->opaque;
	result->id = s->id;			// 服务器套接字id
	result->ud = id;			// 被动套接字id
	result->data = NULL;		// 连接客户端ip地址:port端口

	void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
	int sin_port = ntohs((u.s.sa_family == AF_INET) ? u.v4.sin_port : u.v6.sin6_port);
	char tmp[INET6_ADDRSTRLEN];
	if (inet_ntop(u.s.sa_family, sin_addr, tmp, sizeof(tmp))) {
		snprintf(ss->buffer, sizeof(ss->buffer), "%s:%d", tmp, sin_port);
		result->data = ss->buffer;
	}

	return 1;
}
static int
bind_socket(struct socket_server *ss, struct request_bind *request, union socket_message *result) {
	struct socket *s = new_fd(ss, request->fd);
	if (s == NULL) {
		result->error.session = request->session;
		result->error.id = 0;
		return SOCKET_ERROR;
	}
	sp_nonblocking(request->fd);
	s->type = SOCKET_TYPE_BIND;
	result->open.id = s->id;
	result->open.session = request->session;
	result->open.fd = request->fd;
	return SOCKET_OPEN;
}
Exemple #6
0
static int
bind_socket(struct socket_server *ss, struct request_bind *request, struct socket_message *result) {
	int id = request->id;
	result->id = id;
	result->opaque = request->opaque;
	result->ud = 0;
	struct socket *s = new_fd(ss, id, request->fd, request->opaque, true);
	if (s == NULL) {
		result->data = NULL;
		return SOCKET_ERROR;
	}
	sp_nonblocking(request->fd);
	s->type = SOCKET_TYPE_BIND;
	result->data = "binding";
	return SOCKET_OPEN;
}
Exemple #7
0
// 绑定其他类型的文件描述符,比如stdin和stdout
// 创建socket实例并加入事件循环
static int
bind_socket(struct socket_server *ss, struct request_bind *request, struct socket_message *result) {
	int id = request->id;
	result->id = id;
	result->opaque = request->opaque;
	result->ud = 0;
	struct socket *s = new_fd(ss, id, request->fd, PROTOCOL_TCP, request->opaque, true);
	if (s == NULL) {
		result->data = "reach skynet socket number limit";
		return SOCKET_ERROR;
	}
	// 套接字设置为非阻塞
	sp_nonblocking(request->fd);
	s->type = SOCKET_TYPE_BIND;
	result->data = "binding";
	return SOCKET_OPEN;
}
Exemple #8
0
// return 0 when failed
static int
report_accept(struct socket_server *ss, struct socket *s, struct socket_message *result) {
	union sockaddr_all u;
	socklen_t len = sizeof(u);
	int client_fd = accept(s->fd, &u.s, &len);
	if (client_fd < 0) {
		//printf("accept error : %s\n", strerror(errno));
		return 0;
	}
	int id = reserve_id(ss);
	if (id < 0) {
		close(client_fd);
		return 0;
	}
	socket_keepalive(client_fd);
	sp_nonblocking(client_fd);
	struct socket *ns = new_fd(ss, id, client_fd, s->opaque, false);
	if (ns == NULL) {
		close(client_fd);
		return 0;
	}
	ns->type = SOCKET_TYPE_PACCEPT;
	result->opaque = s->opaque;
	result->id = s->id;
	result->ud = id;
	result->data = NULL;

	void * sin_addr = (u.s.sa_family == AF_INET) ? (void*)&u.v4.sin_addr : (void *)&u.v6.sin6_addr;
	int sin_port = ntohs((u.s.sa_family == AF_INET) ? u.v4.sin_port : u.v6.sin6_port);
	char tmp[INET6_ADDRSTRLEN];
	if (inet_ntop(u.s.sa_family, sin_addr, tmp, sizeof(tmp))) {
		snprintf(ss->buffer, sizeof(ss->buffer), "%s:%d", tmp, sin_port);
		result->data = ss->buffer;
	}

	return 1;
}
Exemple #9
0
static int
connect_to(struct client* c, int ssh_id){
	if (c->cnt >= TOTAL_CONNECTION) {
		fprintf(stderr, "%s client max connection.....\n", get_time());
		return -1;
	}
	
	const char* ip;
	int port;
	if (ssh_id < 0) {
		if (c->free_connection > 0) return -1;

		struct timeval tv;
		gettimeofday(&tv, NULL);
		if (tv.tv_sec - c->time < FREE_CONNECT_TIME) {
			return -1;
		}else {
			c->time = tv.tv_sec;
		}

		ip = c->remote_ip;
		port = c->remote_port;
	} else {
		ip = "0.0.0.0";
		port = c->ssh_port;
	}

	int id;
	int idx;
	struct client_info* info;
	struct ring_buffer* rb;

	struct addrinfo hints;
	struct addrinfo* res = NULL;
	struct addrinfo* ai_ptr = NULL;
	memset(&hints, 0, sizeof(hints));
	hints.ai_family = AF_UNSPEC;
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_protocol = IPPROTO_TCP;

	char portstr[16];
	sprintf(portstr, "%d", port);
	int status = getaddrinfo(ip, portstr, &hints, &res);
	if (status != 0) {
		return -1;
	}

	int sock = -1;
	for (ai_ptr = res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
		sock = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
		if (sock < 0) {
			continue;
		}

		set_keep_alive(sock);
		sp_nonblocking(sock);
		status = connect(sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if (status != 0 && errno != EINPROGRESS) {
			close(sock);
			sock = -1;
			continue;
		}

		break;
	}

	if (sock < 0) {
		goto _failed;
	}

	id = get_id(c);
	assert(id != -1);

	idx = id % TOTAL_CONNECTION;
	info = &c->all_fds[idx];
	info->fd = sock;
	info->id = id;
	info->to_id = ssh_id;
	snprintf(info->client_ip, sizeof(info->client_ip), "%s:%d", ip, port);

	rb = alloc_ring_buffer(MAX_CLIENT_BUFFER);
	info->buffer = rb;

	c->all_ids[c->cnt++] = id;

	if (ssh_id < 0) {
		c->free_connection += 1;
	}

	if (status != 0) {
		//connect no block, need check after
		FD_SET(sock, &c->fd_wset);
		info->connect_type = SOCKET_CONNECTING;
	}else {
		//success
		FD_SET(sock, &c->fd_rset);
		info->connect_type = SOCKET_CONNECTED;

		struct sockaddr* addr = ai_ptr->ai_addr;
		void* sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in*)addr)->sin_addr : (void*)&((struct sockaddr_in6*)addr)->sin6_addr;

		inet_ntop(ai_ptr->ai_family, sin_addr, info->client_ip, sizeof(info->client_ip));
		fprintf(stderr, "%s connected to %s. \n", get_time(), info->client_ip);
	}

	if (c->max_fd < sock + 1) {
		c->max_fd = sock + 1;
	}

	return id;

_failed:
	freeaddrinfo(res);
	return -1;
}
Exemple #10
0
static void*
client_thread(void* param) {
	struct client_param* cp = (struct client_param*)param;

	struct client c;
	memset(&c, 0, sizeof(c));
	sprintf(c.remote_ip, "%s", cp->remote_ip);
	c.remote_port = cp->p1;
	c.ssh_port = cp->p2;
	c.wait_closed = alloc_ring_buffer(sizeof(int) * TOTAL_CONNECTION);

	FD_ZERO(&c.fd_rset);
	FD_ZERO(&c.fd_wset);
	FD_SET(cp->pid, &c.fd_rset);
	c.max_fd = cp->pid + 1;
	sp_nonblocking(cp->pid);

	while (1) {
		pre_check_close(&c);
		
		if (connect_to(&c, -1) == -1 && c.cnt == 0) {
			c.max_fd = cp->pid + 1;

			int buff = 0;
			int n = (int)read(cp->pid, &buff, sizeof(int));
			if (n > 0) {
				break;
			}

			sleep(1);
			continue;
		}

		fd_set r_set = c.fd_rset;
		fd_set w_set = c.fd_wset;

		int cnt = select(c.max_fd, &r_set, &w_set, NULL, NULL);
		if (cnt == -1) {
			fprintf(stderr, "%s select error: %s.\n", get_time(), strerror(errno));
			continue;
		}

		int i;
		for (i = c.cnt - 1; i >= 0 && cnt > 0; --i) {
			int id = c.all_ids[i] % TOTAL_CONNECTION;
			struct client_info* info = &c.all_fds[id];
			assert(c.all_ids[i] == info->id);

			int fd = info->fd;
			assert(fd > 0);

			if (FD_ISSET(fd, &r_set)) {
				// read
				--cnt;
				if (do_read(&c, info) == -1) continue;
			}

			if (FD_ISSET(fd, &w_set)) {
				//write
				--cnt;
				if (do_write(&c, info, 0) == -1) continue;
			}
		}

		if (FD_ISSET(cp->pid, &r_set)) {
			//exit
			break;
		}
	}

	fprintf(stderr, "%s ====================CLIENT: SEND LAST DATA BEGIN===================.\n", get_time());

	int i;
	for (i = c.cnt - 1; i >= 0; --i) {
		int id = c.all_ids[i] % TOTAL_CONNECTION;
		struct client_info* info = &c.all_fds[id];
		assert(c.all_ids[i] == info->id);

		if (do_write(&c, info,	1) != -1) {
			do_close(&c, info);
		}
	}

	fprintf(stderr, "%s ====================CLIENT: SEND LAST DATA END=====================.\n", get_time());

	free_ring_buffer(c.wait_closed);
	assert(c.cnt == 0);

	return NULL;
}
Exemple #11
0
// return -1 when connecting
static int
open_socket(struct socket_server *ss, struct request_open * request, struct socket_message *result) {
	int id = request->id;
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = NULL;
	struct socket *ns;
	int status;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = NULL;
	struct addrinfo *ai_ptr = NULL;
	char port[16];
	sprintf(port, "%d", request->port);
	memset( &ai_hints, 0, sizeof( ai_hints ) );
	ai_hints.ai_family = AF_UNSPEC;
	ai_hints.ai_socktype = SOCK_STREAM;
	ai_hints.ai_protocol = IPPROTO_TCP;

	status = getaddrinfo( request->host, port, &ai_hints, &ai_list );
	if ( status != 0 ) {
		goto _failed;
	}
	int sock= -1;
	for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
		sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
		if ( sock < 0 ) {
			continue;
		}
		socket_keepalive(sock);
		sp_nonblocking(sock);
		status = connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if ( status != 0 && errno != EINPROGRESS) {
			close(sock);
			sock = -1;
			continue;
		}
		break;
	}

	if (sock < 0) {
		goto _failed;
	}

	ns = new_fd(ss, id, sock, request->opaque, true);
	if (ns == NULL) {
		close(sock);
		goto _failed;
	}

	if(status == 0) {
		ns->type = SOCKET_TYPE_CONNECTED;
		struct sockaddr * addr = ai_ptr->ai_addr;
		void * sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in *)addr)->sin_addr : (void*)&((struct sockaddr_in6 *)addr)->sin6_addr;
		if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
			result->data = ss->buffer;
		}
		freeaddrinfo( ai_list );
		return SOCKET_OPEN;
	} else {
		ns->type = SOCKET_TYPE_CONNECTING;
		sp_write(ss->event_fd, ns->fd, ns, true);
	}

	freeaddrinfo( ai_list );
	return -1;
_failed:
	freeaddrinfo( ai_list );
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERROR;
}
Exemple #12
0
// return -1 when connecting
// 打开套接字
// 正常返回 SOCKET_OPEN
// 其他返回 -1,包括 连接中 的情况
static int
open_socket(struct socket_server *ss, struct request_open * request, struct socket_message *result) {
	int id = request->id;
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = NULL;
	struct socket *ns;
	int status;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = NULL;
	struct addrinfo *ai_ptr = NULL;
	char port[16];
	sprintf(port, "%d", request->port);
	memset(&ai_hints, 0, sizeof( ai_hints ) );
	// 地址族暂不指定
	ai_hints.ai_family = AF_UNSPEC;
	ai_hints.ai_socktype = SOCK_STREAM;
	ai_hints.ai_protocol = IPPROTO_TCP;

	// host和port获取地址,支持ipv4和ipv6
	status = getaddrinfo( request->host, port, &ai_hints, &ai_list );
	if ( status != 0 ) {
		result->data = (void *)gai_strerror(status);
		goto _failed;
	}
	int sock= -1;
	for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next ) {
		// 创建socket套接字
		sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
		if ( sock < 0 ) {
			continue;
		}
		// 设置keepalive和非阻塞
		socket_keepalive(sock);
		sp_nonblocking(sock);
		// 连接套接字
		status = connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if ( status != 0 && errno != EINPROGRESS) {
			// O_NONBLOCK is set for the file descriptor for the socket and the connection cannot be immediately established; the connection shall be established asynchronously.
			// 当套接字被设置为非阻塞后,连接不会被立即建立,所以errno会返回EINPROGRESS
			close(sock);
			sock = -1;
			continue;
		}
		break;
	}

	if (sock < 0) {
		result->data = strerror(errno);
		goto _failed;
	}

	// 创建socket实例
	ns = new_fd(ss, id, sock, PROTOCOL_TCP, request->opaque, true);
	if (ns == NULL) {
		close(sock);
		result->data = "reach skynet socket number limit";
		goto _failed;
	}

	if(status == 0) {
		// socket修改为已连接类型
		ns->type = SOCKET_TYPE_CONNECTED;
		struct sockaddr * addr = ai_ptr->ai_addr;
 		// 区分ipv4和ipv6,ip地址放入result->data
		void * sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in *)addr)->sin_addr : (void*)&((struct sockaddr_in6 *)addr)->sin6_addr;
		if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer))) {
			result->data = ss->buffer;
		}
		freeaddrinfo( ai_list );
		return SOCKET_OPEN;
	} else {
		// socket修改为连接中类型,在socket_server_poll方法中调用report_connect方法修改为SOCKET_TYPE_CONNECTED,并返回SOCKET_OPEN
		ns->type = SOCKET_TYPE_CONNECTING;
		// 打开事件循环中fd的可写权限
		sp_write(ss->event_fd, ns->fd, ns, true);
	}

	freeaddrinfo( ai_list );
	return -1;
_failed:
	freeaddrinfo( ai_list );
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERROR;
}
Exemple #13
0
int socket_proxy::_connect(bool blocking)
{
    bool ret;
    int status;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = NULL;
	struct addrinfo *ai_ptr = NULL;
	char port[16];
	sprintf(port, "%d", this->port);
	memset( &ai_hints, 0, sizeof( ai_hints ) );
	ai_hints.ai_family = AF_UNSPEC;
	ai_hints.ai_socktype = SOCK_STREAM;
	ai_hints.ai_protocol = IPPROTO_TCP;
    int sock= -1;

    // 获取地址列表,(不用gethostbyname、gethostbyadd,这两个函数仅支持IPV4)
    // 第一个参数是IP地址或主机名称,第二个参数是服务名(可以是端口或服务名称,如ftp、http等)
	status = getaddrinfo( this->host, port, &ai_hints, &ai_list );
	if ( status != 0 )
    {
		goto _failed;
	}
	for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next )
    {
		sock = socket( ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol );
		if ( sock < 0 )
        {
			continue;
		}
		socket_keepalive(sock);
		if (!blocking)
        {
			sp_nonblocking(sock);   // blocking为false,设置为非阻塞模式,即用非阻塞connect
		}
		status = ::connect( sock, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if ( status != 0 && errno != EINPROGRESS)
        {
			close(sock);
			sock = -1;
			continue;   // 连接出错,跳过本循环,连接下一个地址
		}
		if (blocking)
        {
			sp_nonblocking(sock);   //到此为止,不管blocking是真是假,都设置为非阻塞模式,即IO模型使用的是non blocking
		}
		break;
	}
    
	if (sock < 0)
    {
		goto _failed;
	}
    
    this->fd = sock;

	ret = ss->new_fd(this, true);   // 加入epoll管理
    if (!ret)
    {
        close(sock);
        goto _failed;
    }
	if(status == 0)
    {   //说明connect已连接成功
		this->type = SOCKET_TYPE_CONNECTED;
		struct sockaddr * addr = ai_ptr->ai_addr;
		void * sin_addr = (ai_ptr->ai_family == AF_INET) ? (void*)&((struct sockaddr_in *)addr)->sin_addr : (void*)&((struct sockaddr_in6 *)addr)->sin6_addr;
		if (inet_ntop(ai_ptr->ai_family, sin_addr, ss->buffer, sizeof(ss->buffer)))
        {
			//result->data = ss->buffer;
		}
		freeaddrinfo( ai_list );
		return SOCKET_OPEN;
	}
    else
    {    // 说明非阻塞套接字尝试连接中
		this->type = SOCKET_TYPE_CONNECTING;
		sp_write(ss->event_fd, this->fd, this, true);   // 非阻塞字尝试连接中,必需将关注其可写事件,稍后epoll触发才可以捕捉到已连接
	}
    
	freeaddrinfo( ai_list );
	return -1;
_failed:
	freeaddrinfo( ai_list );
	//ss->slot[id % MAX_SOCKET].type = SOCKET_TYPE_INVALID;
    this->type = SOCKET_TYPE_INVALID;
	return 0;
}