Beispiel #1
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)
	{
		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;
	if (inet_ntop(u.s.sa_family, sin_addr, ss->buffer, sizeof(ss->buffer)))
	{
		result->data = ss->buffer;
	}

	return 1;
}
Beispiel #2
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;
}
static gboolean
server_socket_in_event(G_GNUC_UNUSED GIOChannel *source,
		       G_GNUC_UNUSED GIOCondition condition,
		       gpointer data)
{
	struct one_socket *s = data;

	struct sockaddr_storage address;
	size_t address_length = sizeof(address);
	int fd = accept_cloexec_nonblock(s->fd, (struct sockaddr*)&address,
					 &address_length);
	if (fd >= 0) {
		if (socket_keepalive(fd))
			g_warning("Could not set TCP keepalive option: %s",
				  g_strerror(errno));
		s->parent->callback(fd, (const struct sockaddr*)&address,
				    address_length, get_remote_uid(fd),
				    s->parent->callback_ctx);
	} else {
		g_warning("accept() failed: %s", g_strerror(errno));
	}

	return true;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
0
// connect, for client
// net pool, ip address, port
int net_connect(struct net_pool* np, const char* host, int port)
{
    log_debug("connect : host(ipaddress) = %s, port = %d\n", host, port);

    // hint the system what do here need
    struct addrinfo ai_hints;
    // reserve the result chain
    struct addrinfo* ai_list = NULL;
    // as the element of result chain
    struct addrinfo* ai_ptr;

    char strport[16];
    memset(strport, 0, 16);
    sprintf(strport, "%d", port);

    // set hint information
    memset(&ai_hints, 0, sizeof(struct addrinfo));
    ai_hints.ai_family = AF_UNSPEC; // point that sin_family is unspecified, other choose : AF_INET, AF_INET6
    ai_hints.ai_socktype = SOCK_STREAM;
    ai_hints.ai_protocol = IPPROTO_TCP;

    int status = getaddrinfo(host, strport, &ai_hints, &ai_list);
    if(status != 0)
    {
        freeaddrinfo(ai_list);
        return -1;
    }

    // the sockfd, connected to server
    int fd = -1;
    for(ai_ptr =ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
    {
        fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
        if(fd < 0)
        {
            log_error("socket failure ...");
            continue;
        }

        socket_keepalive(fd);
        poll_setnonblocking(fd);

        // connect to server
        status = connect(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
        if((status != 0) && (errno != EINPROGRESS))
        {
            socket_close(fd);
            fd = -1;
            continue;
        }
        break;
    }

    if(fd < 0)
    {
        freeaddrinfo(ai_list);
        return -1;
    }

    struct net_socket* ns = net_socket_new(np, fd, true);
    if(ns == NULL)
    {
        socket_close(fd);
        freeaddrinfo(ai_list);
        return -1;
    }

    if(status == 0)
    {
        ns->status = SOCKET_STATUS_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);

        // save ip address to ns->info
        inet_ntop(ai_ptr->ai_family, sin_addr, ns->info, sizeof(ns->info));
        log_info("connected immediately id = %d\n", ns->id);
        np->onconnected(np, ns->id);
    }
    else
    {
        ns->status = SOCKET_STATUS_CONNECTING;
        poll_write(np->eventfd, ns->fd, ns, true);
    }

    freeaddrinfo(ai_list);

    return ns->id;
}
Beispiel #7
0
static int socket_req_open(struct _open_req *req, struct socket_message *msg) {
	struct socket *sock;
	int status;
	int fd = -1;
	struct addrinfo ai_hints;
	struct addrinfo *ai_list = 0;
	struct addrinfo *ai_ptr = 0;
	char port[16];
	msg->id = req->id;
	msg->ud = req->ud;
	sprintf(port, "%d", req->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(req->host, port, &ai_hints, &ai_list);
	if (status != 0) {
		msg->data = (void *)gai_strerror(status);
		goto _failed;
	}
	for (ai_ptr = ai_list; ai_ptr != 0; ai_ptr = ai_ptr->ai_next) {
		fd = socket(ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
		if (fd < 0) {
			continue;
		}
		socket_keepalive(fd);
		socket_nonblocking(fd);
		status = connect(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
		if (status != 0 && errno != EINPROGRESS) {
			close(fd);
			fd = -1;
			continue;
		}
		break;
	}
	if (fd < 0) {
		msg->data = strerror(errno);
		goto _failed;
	}
	sock = socket_new(fd, req->id, PROTOCOL_TCP, req->ud, 1);
	if (sock == 0) {
		close(fd);
		msg->data = "socket limit";
		goto _failed;
	}
	if (status == 0) {
		sock->type = SOCKET_TYPE_OPENED;
		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;
		int sin_port = ntohs((ai_ptr->ai_family == AF_INET) ? ((struct sockaddr_in *)addr)->sin_port : ((struct sockaddr_in6 *)addr)->sin6_port);
		char tmp[INET6_ADDRSTRLEN];
		if (inet_ntop(ai_ptr->ai_family, sin_addr, tmp, sizeof(tmp))) {
			snprintf(S.buffer, sizeof(S.buffer), "%s:%d", tmp, sin_port);
			msg->data = S.buffer;
		}
		freeaddrinfo(ai_list);
		return SOCKET_OPEN;
	} else {
		sock->type = SOCKET_TYPE_OPENING;
		event_write(S.event_fd, sock->fd, sock, 1);
	}
	freeaddrinfo(ai_list);
	return -1;
_failed:
	freeaddrinfo(ai_list);
	S.slot[HASH_ID(req->id)].type = SOCKET_TYPE_INVALID;
	return SOCKET_ERR;
}
Beispiel #8
0
socket_t socket_connect(const char* host, WORD port)
{
    socket_t            s = 0;
    struct sockaddr_in  server_addr;
    int                 rslt;

    /* 소켓주소 구조체 초기화 */
    memset(&server_addr, 0, sizeof(server_addr));

    if (isdigit(*host))
	server_addr.sin_addr.s_addr = inet_addr(host);
    else
    {
	struct hostent *hp;

	if ((hp = gethostbyname(host)) == NULL)
	{
	    sys_err("socket_connect(): can not connect to %s:%d", host, port);
	    return -1;
	}

	thecore_memcpy((char* ) &server_addr.sin_addr, hp->h_addr, sizeof(server_addr.sin_addr));
    }

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);

    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
	perror("socket");
	return -1;
    }

    socket_keepalive(s);
    socket_sndbuf(s, 233016);
    socket_rcvbuf(s, 233016);
    socket_timeout(s, 10, 0);
    socket_lingeron(s);

    /*  연결요청 */
    if ((rslt = connect(s, (struct sockaddr *) &server_addr, sizeof(server_addr))) < 0)
    {
	socket_close(s);

#ifdef __WIN32__
	switch (WSAGetLastError())
#else
	    switch (rslt)
#endif
	    {
#ifdef __WIN32__
		case WSAETIMEDOUT:
#else
		case EINTR:
#endif
		    sys_err("HOST %s:%d connection timeout.", host, port);
		    break;
#ifdef __WIN32__
		case WSAECONNREFUSED:
#else
		case ECONNREFUSED:
#endif
		    sys_err("HOST %s:%d port is not opened. connection refused.", host, port);
		    break;
#ifdef __WIN32__
		case WSAENETUNREACH:
#else
		case ENETUNREACH:
#endif
		    sys_err("HOST %s:%d is not reachable from this host.", host, port);
		    break;

		default:
		    sys_err("HOST %s:%d, could not connect.", host, port);
		    break;
	    }

	perror("connect");
	return (-1);
    }

    return (s);
}
Beispiel #9
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;
}