コード例 #1
0
ファイル: fd.cpp プロジェクト: simonsouth/haiku
/*!	Duplicates an FD from another team to this/the kernel team.
	\param fromTeam The team which owns the FD.
	\param fd The FD to duplicate.
	\param kernel If \c true, the new FD will be created in the kernel team,
			the current userland team otherwise.
	\return The newly created FD or an error code, if something went wrong.
*/
int
dup_foreign_fd(team_id fromTeam, int fd, bool kernel)
{
	// get the I/O context for the team in question
	Team* team = Team::Get(fromTeam);
	if (team == NULL)
		return B_BAD_TEAM_ID;
	BReference<Team> teamReference(team, true);

	io_context* fromContext = team->io_context;

	// get the file descriptor
	file_descriptor* descriptor = get_fd(fromContext, fd);
	if (descriptor == NULL)
		return B_FILE_ERROR;
	CObjectDeleter<file_descriptor> descriptorPutter(descriptor, put_fd);

	// create a new FD in the target I/O context
	int result = new_fd(get_current_io_context(kernel), descriptor);
	if (result >= 0) {
		// the descriptor reference belongs to the slot, now
		descriptorPutter.Detach();
	}

	return result;
}
コード例 #2
0
static int
create_socket_fd(net_socket* socket, bool kernel)
{
	// Get the socket's non-blocking flag, so we can set the respective
	// open mode flag.
	int32 nonBlock;
	socklen_t nonBlockLen = sizeof(int32);
	status_t error = sStackInterface->getsockopt(socket, SOL_SOCKET,
		SO_NONBLOCK, &nonBlock, &nonBlockLen);
	if (error != B_OK)
		return error;

	// allocate a file descriptor
	file_descriptor* descriptor = alloc_fd();
	if (descriptor == NULL)
		return B_NO_MEMORY;

	// init it
	descriptor->type = FDTYPE_SOCKET;
	descriptor->ops = &sSocketFDOps;
	descriptor->u.socket = socket;
	descriptor->open_mode = O_RDWR | (nonBlock ? O_NONBLOCK : 0);

	// publish it
	int fd = new_fd(get_current_io_context(kernel), descriptor);
	if (fd < 0)
		free(descriptor);

	return fd;
}
コード例 #3
0
ファイル: fd.cpp プロジェクト: simonsouth/haiku
static int
dup_fd(int fd, bool kernel)
{
	struct io_context* context = get_current_io_context(kernel);
	struct file_descriptor* descriptor;
	int status;

	TRACE(("dup_fd: fd = %d\n", fd));

	// Try to get the fd structure
	descriptor = get_fd(context, fd);
	if (descriptor == NULL)
		return B_FILE_ERROR;

	// now put the fd in place
	status = new_fd(context, descriptor);
	if (status < 0)
		put_fd(descriptor);
	else {
		mutex_lock(&context->io_mutex);
		fd_set_close_on_exec(context, status, false);
		mutex_unlock(&context->io_mutex);
	}

	return status;
}
コード例 #4
0
ファイル: fd.cpp プロジェクト: mmanley/Antares
/*!	Duplicates an FD from another team to this/the kernel team.
	\param fromTeam The team which owns the FD.
	\param fd The FD to duplicate.
	\param kernel If \c true, the new FD will be created in the kernel team,
			the current userland team otherwise.
	\return The newly created FD or an error code, if something went wrong.
*/
int
dup_foreign_fd(team_id fromTeam, int fd, bool kernel)
{
	// get the I/O context for the team in question
	InterruptsSpinLocker teamsLocker(gTeamSpinlock);
	struct team* team = team_get_team_struct_locked(fromTeam);
	if (team == NULL)
		return B_BAD_TEAM_ID;

	io_context* fromContext = team->io_context;
	vfs_get_io_context(fromContext);

	teamsLocker.Unlock();

	CObjectDeleter<io_context> _(fromContext, vfs_put_io_context);

	// get the file descriptor
	file_descriptor* descriptor = get_fd(fromContext, fd);
	if (descriptor == NULL)
		return B_FILE_ERROR;
	CObjectDeleter<file_descriptor> descriptorPutter(descriptor, put_fd);

	// create a new FD in the target I/O context
	int result = new_fd(get_current_io_context(kernel), descriptor);
	if (result >= 0) {
		// the descriptor reference belongs to the slot, now
		descriptorPutter.Detach();
	}

	return result;
}
コード例 #5
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;
	}
	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;
}
コード例 #6
0
// 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;
}
コード例 #7
0
void do_dup2(PCB *pcb){
	int fd_old = pcb->registers[5],
		fd_new = pcb->registers[6];

	struct File_Descriptor *new_fd_obj,
		*old_fd_obj, *curr_fd_obj;

	if(fd_old == fd_new){
		syscall_return(pcb, fd_new);
	}

	if(fd_new >= 0 && fd_new < MaxFds && valid_fd(pcb, fd_old, -1)){
		
		old_fd_obj = pcb->fd_table[fd_old];

		int close = 0;

		curr_fd_obj = pcb->fd_table[fd_new];

		new_fd_obj = new_fd(fd_new, old_fd_obj->permission);
		
		dup_fd(old_fd_obj,new_fd_obj);

		if(curr_fd_obj != senitel_fd){
			close_fd(pcb, fd_new);
		}

		pcb->fd_table[new_fd_obj->id] = new_fd_obj;

		syscall_return(pcb, fd_new);
	}else{
		syscall_return(pcb,-1*EBADF);
	}
}
コード例 #8
0
ファイル: dup.c プロジェクト: xinglunxu/kos-operating-system
void do_dup(PCB *pcb) {
    int fd_old = pcb->registers[5],
        fd_new;

    struct File_Descriptor *new_fd_obj,
               *old_fd_obj;

    if(valid_fd(pcb, fd_old, -1)) {

        old_fd_obj = pcb->fd_table[fd_old];

        fd_new = next_fd(pcb);

        if(fd_new > -1) {
            new_fd_obj = new_fd(fd_new, old_fd_obj->permission);

            dup_fd(old_fd_obj,new_fd_obj);

            pcb->fd_table[new_fd_obj->id] = new_fd_obj;

        } else {
            syscall_return(pcb, -1*EMFILE);
        }

        //printf("process %d duping to new fd %d!\n",pcb->pid, fd_new);

        syscall_return(pcb, fd_new);
    } else {
        syscall_return(pcb,-1*EBADF);
    }
}
コード例 #9
0
ファイル: socket_server.c プロジェクト: puXiaoyi/skynet
// 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;
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: socket_server.c プロジェクト: Lvshen/company_coc
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;
}
コード例 #12
0
ファイル: socket_server.c プロジェクト: puXiaoyi/skynet
// 绑定其他类型的文件描述符,比如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;
}
コード例 #13
0
static int
listen_socket(struct socket_server *ss, struct request_listen * request, union socket_message *result) {
	// only support ipv4
	// todo: support ipv6 by getaddrinfo
	uint32_t addr = INADDR_ANY;
	if (request->host[0]) {
		addr=inet_addr(request->host);
	}
	int listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (listen_fd < 0) {
		result->error.id = 0;
		result->error.session = request->session;

		return SOCKET_ERROR;
	}
	int reuse = 1;
	if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(int))==-1) {
		goto _failed;
	}

	struct sockaddr_in my_addr;
	memset(&my_addr, 0, sizeof(struct sockaddr_in));
	my_addr.sin_family = AF_INET;
	my_addr.sin_port = htons(request->port);
	my_addr.sin_addr.s_addr = addr;
	if (bind(listen_fd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) {
		goto _failed;
	}
	if (listen(listen_fd, request->backlog) == -1) {
		goto _failed;
	}
	struct socket *s = new_fd(ss, listen_fd);
	if (s == NULL) {
		goto _failed;
	}
	s->type = SOCKET_TYPE_LISTEN;
	s->session = request->session;
	return -1;
_failed:
	close(listen_fd);
	result->error.id = 0;
	result->error.session = request->session;

	return SOCKET_ERROR;
}
コード例 #14
0
ファイル: socket_server.c プロジェクト: bye-Tyrael/skynet
static void
add_udp_socket(struct socket_server *ss, struct request_udp *udp) {
    int id = udp->id;
    int protocol;
    if (udp->family == AF_INET6) {
        protocol = PROTOCOL_UDPv6;
    } else {
        protocol = PROTOCOL_UDP;
    }
    struct socket *ns = new_fd(ss, id, udp->fd, protocol, udp->opaque, true);
    if (ns == NULL) {
        close(udp->fd);
        ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;
        return;
    }
    ns->type = SOCKET_TYPE_CONNECTED;
    memset(ns->p.udp_address, 0, sizeof(ns->p.udp_address));
}
コード例 #15
0
ファイル: socket_server.c プロジェクト: Lvshen/company_coc
static int
listen_socket(struct socket_server *ss, struct request_listen * request, struct socket_message *result) {
	int id = request->id;
	int listen_fd = request->fd;
	struct socket *s = new_fd(ss, id, listen_fd, request->opaque, false);
	if (s == NULL) {
		goto _failed;
	}
	s->type = SOCKET_TYPE_PLISTEN;
	return -1;
_failed:
	close(listen_fd);
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = NULL;
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;

	return SOCKET_ERROR;
}
コード例 #16
0
ファイル: socket_server.c プロジェクト: puXiaoyi/skynet
// 监听套接字
static int
listen_socket(struct socket_server *ss, struct request_listen * request, struct socket_message *result) {
	int id = request->id;
	int listen_fd = request->fd;
	// 创建socket实例,并修改为PListen类型
	struct socket *s = new_fd(ss, id, listen_fd, PROTOCOL_TCP, request->opaque, false);
	if (s == NULL) {
		goto _failed;
	}
	s->type = SOCKET_TYPE_PLISTEN;
	return -1;
_failed:
	close(listen_fd);
	result->opaque = request->opaque;
	result->id = id;
	result->ud = 0;
	result->data = "reach skynet socket number limit";
	ss->slot[HASH_ID(id)].type = SOCKET_TYPE_INVALID;

	return SOCKET_ERROR;
}
コード例 #17
0
ファイル: socket_server.c プロジェクト: Lvshen/company_coc
// 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;
}
コード例 #18
0
ファイル: socket_server.c プロジェクト: puXiaoyi/skynet
// 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;
}
コード例 #19
0
ファイル: socket_server.c プロジェクト: Lvshen/company_coc
// 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;
}