Comparar commits
5 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 66b887c089 | |||
| 7a1078e674 | |||
| 5b4d86a89c | |||
| 728414bf8d | |||
| a9c7afff30 |
@@ -27,6 +27,7 @@ static ssize_t dmctl_write(mx_device_t* dev, const void* buf, size_t count, mx_o
|
||||
}
|
||||
|
||||
mx_status_t vfs_install_remote(mx_handle_t h);
|
||||
mx_status_t socket_install_remote(mx_handle_t h);
|
||||
|
||||
static ssize_t dmctl_ioctl(mx_device_t* dev, uint32_t op,
|
||||
const void* in_buf, size_t in_len,
|
||||
@@ -40,22 +41,35 @@ static ssize_t dmctl_ioctl(mx_device_t* dev, uint32_t op,
|
||||
if ((in_len < 1) || (((char*)in_buf)[in_len - 1] != 0)) {
|
||||
return ERR_INVALID_ARGS;
|
||||
}
|
||||
if (strcmp(in_buf, "fs:/data")) {
|
||||
if (!strcmp(in_buf, "fs:/data")) {
|
||||
mx_handle_t h[2];
|
||||
mx_status_t r;
|
||||
if ((r = mx_msgpipe_create(h, 0)) < 0) {
|
||||
return r;
|
||||
}
|
||||
if ((r = vfs_install_remote(h[1])) < 0) {
|
||||
mx_handle_close(h[0]);
|
||||
mx_handle_close(h[1]);
|
||||
return r;
|
||||
}
|
||||
memcpy(out_buf, h, sizeof(mx_handle_t));
|
||||
return sizeof(mx_handle_t);
|
||||
} else if (!strcmp(in_buf, "fs:/dev/socket")) {
|
||||
mx_handle_t h[2];
|
||||
mx_status_t r;
|
||||
if ((r = mx_msgpipe_create(h, 0)) < 0) {
|
||||
return r;
|
||||
}
|
||||
if ((r = socket_install_remote(h[1])) < 0) {
|
||||
mx_handle_close(h[0]);
|
||||
mx_handle_close(h[1]);
|
||||
return r;
|
||||
}
|
||||
memcpy(out_buf, h, sizeof(mx_handle_t));
|
||||
return sizeof(mx_handle_t);
|
||||
} else {
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
mx_handle_t h[2];
|
||||
mx_status_t r;
|
||||
if ((r = mx_msgpipe_create(h, 0)) < 0) {
|
||||
return r;
|
||||
}
|
||||
if ((r = vfs_install_remote(h[1])) < 0) {
|
||||
mx_handle_close(h[0]);
|
||||
mx_handle_close(h[1]);
|
||||
return r;
|
||||
}
|
||||
memcpy(out_buf, h, sizeof(mx_handle_t));
|
||||
return sizeof(mx_handle_t);
|
||||
}
|
||||
|
||||
static mx_protocol_device_t dmctl_device_proto = {
|
||||
|
||||
@@ -130,7 +130,7 @@ int service_starter(void* arg) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (getenv("netsvc.disable") == NULL) {
|
||||
if (0 /* getenv("netsvc.disable") == NULL */) {
|
||||
// launch the network service
|
||||
devmgr_launch("netsvc", 1, argv_netsvc, -1);
|
||||
}
|
||||
|
||||
@@ -161,14 +161,13 @@ mx_status_t memfs_readdir(vnode_t* parent, void* cookie, void* data, size_t len)
|
||||
return dn_readdir(parent->dnode, cookie, data, len);
|
||||
}
|
||||
|
||||
static mx_status_t _mem_create(mnode_t* parent, mnode_t** out,
|
||||
static mx_status_t _mem_create(vnode_t* parent, mnode_t** out,
|
||||
const char* name, size_t namelen,
|
||||
bool isdir);
|
||||
|
||||
static mx_status_t mem_create(vnode_t* vn, vnode_t** out, const char* name, size_t len, uint32_t mode) {
|
||||
mnode_t* parent = vn->pdata;
|
||||
mnode_t* mem;
|
||||
mx_status_t r = _mem_create(parent, &mem, name, len, S_ISDIR(mode));
|
||||
mx_status_t r = _mem_create(vn, &mem, name, len, S_ISDIR(mode));
|
||||
if (r >= 0) {
|
||||
vn_acquire(&mem->vn);
|
||||
*out = &mem->vn;
|
||||
@@ -243,10 +242,10 @@ static mnode_t mem_root = {
|
||||
},
|
||||
};
|
||||
|
||||
static mx_status_t _mem_create(mnode_t* parent, mnode_t** out,
|
||||
static mx_status_t _mem_create(vnode_t* parent, mnode_t** out,
|
||||
const char* name, size_t namelen,
|
||||
bool isdir) {
|
||||
if ((parent == NULL) || (parent->vn.dnode == NULL)) {
|
||||
if ((parent == NULL) || (parent->dnode == NULL)) {
|
||||
return ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
@@ -264,7 +263,7 @@ static mx_status_t _mem_create(mnode_t* parent, mnode_t** out,
|
||||
|
||||
mx_status_t r;
|
||||
dnode_t* dn;
|
||||
if ((r = dn_lookup(parent->vn.dnode, &dn, name, namelen)) == NO_ERROR) {
|
||||
if ((r = dn_lookup(parent->dnode, &dn, name, namelen)) == NO_ERROR) {
|
||||
free(mem);
|
||||
return ERR_ALREADY_EXISTS;
|
||||
}
|
||||
@@ -274,7 +273,7 @@ static mx_status_t _mem_create(mnode_t* parent, mnode_t** out,
|
||||
free(mem);
|
||||
return r;
|
||||
}
|
||||
dn_add_child(parent->vn.dnode, dn);
|
||||
dn_add_child(parent->dnode, dn);
|
||||
|
||||
if (isdir) {
|
||||
mem->vn.dnode = dn;
|
||||
@@ -309,6 +308,7 @@ static mnode_t vfs_root = {
|
||||
};
|
||||
|
||||
static mnode_t* vn_data;
|
||||
static mnode_t* vn_socket;
|
||||
|
||||
vnode_t* vfs_get_root(void) {
|
||||
if (vfs_root_dn.vnode == NULL) {
|
||||
@@ -317,7 +317,8 @@ vnode_t* vfs_get_root(void) {
|
||||
dn_add_child(&vfs_root_dn, devfs_get_root()->dnode);
|
||||
dn_add_child(&vfs_root_dn, bootfs_get_root()->dnode);
|
||||
dn_add_child(&vfs_root_dn, memfs_get_root()->dnode);
|
||||
_mem_create(&vfs_root, &vn_data, "data", 4, true);
|
||||
_mem_create(&vfs_root.vn, &vn_data, "data", 4, true);
|
||||
_mem_create(devfs_get_root(), &vn_socket, "socket", 6, true);
|
||||
}
|
||||
return &vfs_root.vn;
|
||||
}
|
||||
@@ -332,3 +333,14 @@ mx_status_t vfs_install_remote(mx_handle_t h) {
|
||||
mtx_unlock(&vfs_lock);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
mx_status_t socket_install_remote(mx_handle_t h) {
|
||||
mtx_lock(&vfs_lock);
|
||||
if (vn_socket->vn.remote > 0) {
|
||||
mx_handle_close(vn_socket->vn.remote);
|
||||
}
|
||||
vn_socket->vn.remote = h;
|
||||
vn_socket->vn.flags |= V_FLAG_REMOTE;
|
||||
mtx_unlock(&vfs_lock);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
MODULE_TYPE := userapp
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/socktest.c
|
||||
|
||||
MODULE_NAME := socktest
|
||||
|
||||
MODULE_LIBS := \
|
||||
ulib/mxio \
|
||||
ulib/magenta \
|
||||
ulib/musl
|
||||
|
||||
include make/module.mk
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int sock_test(int16_t port) {
|
||||
int s;
|
||||
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (s < 0) {
|
||||
printf("socket failed (%d)\n", s);
|
||||
return -1;
|
||||
}
|
||||
printf("s = %d\n", s);
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
printf("bind failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (listen(s, 1) < 0) {
|
||||
printf("listen failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int conn = accept(s, NULL, NULL);
|
||||
if (conn < 0) {
|
||||
close(s);
|
||||
printf("accept failed\n");
|
||||
return -1;
|
||||
}
|
||||
printf("connected (conn = %d)\n", conn);
|
||||
|
||||
char buf[1024];
|
||||
int nread;
|
||||
nread = read(conn, buf, sizeof(buf));
|
||||
if (nread < 0) {
|
||||
printf("read failed (%d)\n", nread);
|
||||
close(conn);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
printf("read success (nread = %d)\n", nread);
|
||||
|
||||
for (int i = 0; i < nread; i++)
|
||||
printf("%c", buf[i]);
|
||||
printf("\n");
|
||||
|
||||
int nwrite;
|
||||
nwrite = write(conn, buf, nread);
|
||||
if (nwrite < 0) {
|
||||
printf("write failed (%d)\n", nwrite);
|
||||
close(conn);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
printf("write success (nwrite = %d)\n", nwrite);
|
||||
|
||||
close(conn);
|
||||
close(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int16_t port = 7;
|
||||
if (argc > 1) {
|
||||
port = atoi(argv[1]);
|
||||
printf("port is set to %d\n", port);
|
||||
}
|
||||
int r;
|
||||
r = sock_test(port);
|
||||
return r;
|
||||
}
|
||||
@@ -135,11 +135,6 @@ int rmdir(const char* path) {
|
||||
|
||||
// Socket stubbing.
|
||||
|
||||
int socket(int domain, int type, int protocol) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int socketpair(int domain, int type, int protocol, int fd[2]) {
|
||||
errno = ENOSYS;
|
||||
return -1;
|
||||
@@ -152,22 +147,6 @@ int shutdown(int fd, int how) {
|
||||
return checksocket(fd, ENOTSOCK, ENOSYS);
|
||||
}
|
||||
|
||||
int bind(int fd, const struct sockaddr* addr, socklen_t len) {
|
||||
return checksocket(fd, ENOTSOCK, ENOSYS);
|
||||
}
|
||||
|
||||
int connect(int fd, const struct sockaddr* addr, socklen_t len) {
|
||||
return checksocket(fd, ENOTSOCK, ENOSYS);
|
||||
}
|
||||
|
||||
int listen(int fd, int backlog) {
|
||||
return checksocket(fd, ENOTSOCK, ENOSYS);
|
||||
}
|
||||
|
||||
int accept4(int fd, struct sockaddr* restrict addr, socklen_t* restrict len, int flags) {
|
||||
return checksocket(fd, ENOTSOCK, ENOSYS);
|
||||
}
|
||||
|
||||
int getsockname(int fd, struct sockaddr* restrict addr, socklen_t* restrict len) {
|
||||
return checksocket(fd, ENOTSOCK, ENOSYS);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <sys/uio.h>
|
||||
#include <threads.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <magenta/processargs.h>
|
||||
#include <magenta/syscalls.h>
|
||||
@@ -967,3 +970,161 @@ mode_t umask(mode_t mask) {
|
||||
mtx_unlock(&mxio_lock);
|
||||
return oldmask;
|
||||
}
|
||||
|
||||
// TODO
|
||||
// these socket APIs are tentatively using remote I/O protocol,
|
||||
// Many of them are mapped to ioctl currently.
|
||||
// That'll be changing once socket I/O's own protocol is ready.
|
||||
|
||||
int socket(int domain, int type, int protocol) {
|
||||
mxio_t* io = NULL;
|
||||
mx_status_t r;
|
||||
int fd;
|
||||
int flags = 0;
|
||||
uint32_t mode = 0;
|
||||
|
||||
// TODO: pass domain, type, protocol
|
||||
domain = domain;
|
||||
type = type;
|
||||
protocol = protocol;
|
||||
|
||||
if ((r = __mxio_open(&io, NULL, "/dev/socket", flags, mode)) < 0) {
|
||||
return ERROR(r);
|
||||
}
|
||||
if ((fd = mxio_bind_to_fd(io, -1, 0)) < 0) {
|
||||
io->ops->close(io);
|
||||
mxio_release(io);
|
||||
return ERRNO(EMFILE);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
|
||||
// TODO: for now, map APIs to ioctl
|
||||
#define IOCTL(kind, family, number) \
|
||||
((((kind) & 0xF) << 20) | (((family) & 0xFF) << 8) | ((number) & 0xFF))
|
||||
|
||||
int connect(int fd, const struct sockaddr* addr, socklen_t len) {
|
||||
mxio_t* io = fd_to_io(fd);
|
||||
if (io == NULL) {
|
||||
return ERRNO(EBADF);
|
||||
}
|
||||
uint32_t op = IOCTL(0, 0, 1);
|
||||
|
||||
ssize_t r = io->ops->ioctl(io, op, addr, len, NULL, 0);
|
||||
mxio_release(io);
|
||||
return r;
|
||||
}
|
||||
|
||||
int bind(int fd, const struct sockaddr* addr, socklen_t len) {
|
||||
mxio_t* io = fd_to_io(fd);
|
||||
if (io == NULL) {
|
||||
return ERRNO(EBADF);
|
||||
}
|
||||
uint32_t op = IOCTL(0, 0, 2);
|
||||
|
||||
ssize_t r = io->ops->ioctl(io, op, addr, len, NULL, 0);
|
||||
mxio_release(io);
|
||||
return r;
|
||||
}
|
||||
|
||||
int listen(int fd, int backlog) {
|
||||
mxio_t* io = fd_to_io(fd);
|
||||
if (io == NULL) {
|
||||
return ERRNO(EBADF);
|
||||
}
|
||||
uint32_t op = IOCTL(0, 0, 3);
|
||||
|
||||
ssize_t r = io->ops->ioctl(io, op, &backlog, sizeof(backlog), NULL, 0);
|
||||
mxio_release(io);
|
||||
return r;
|
||||
}
|
||||
|
||||
int accept4(int fd, struct sockaddr* restrict addr, socklen_t* restrict len, int flags) {
|
||||
mxio_t* io = fd_to_io(fd);
|
||||
if (io == NULL) {
|
||||
return ERRNO(EBADF);
|
||||
}
|
||||
uint32_t op = IOCTL(1/* get_handle */, 0, 4);
|
||||
|
||||
// TODO: support flags
|
||||
struct {
|
||||
mx_handle_t h;
|
||||
struct sockaddr addr;
|
||||
socklen_t len;
|
||||
} reply;
|
||||
|
||||
ssize_t r = io->ops->ioctl(io, op, NULL, 0, &reply, sizeof(reply));
|
||||
mxio_release(io);
|
||||
|
||||
int new_fd = -1;
|
||||
if (r < 0) {
|
||||
new_fd = ERROR(r);
|
||||
} else {
|
||||
mx_handle_t h = reply.h;
|
||||
mxio_t *io2 = NULL;
|
||||
r = mxio_from_handles(MXIO_PROTOCOL_REMOTE, &h, 1, &io2);
|
||||
if (r < 0) {
|
||||
new_fd = ERROR(r);
|
||||
} else {
|
||||
if ((new_fd = mxio_bind_to_fd(io2, -1, 0)) < 0) {
|
||||
io->ops->close(io2);
|
||||
mxio_release(io2);
|
||||
return ERRNO(EMFILE);
|
||||
}
|
||||
if (addr != NULL && len != NULL) {
|
||||
memcpy(addr, &reply.addr, *len < reply.len ? *len : reply.len);
|
||||
}
|
||||
if (len != NULL) {
|
||||
*len = reply.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new_fd;
|
||||
}
|
||||
|
||||
#define GAI_PACKET_NODE_MAXLEN 128
|
||||
#define GAI_PACKET_SERVICE_MAXLEN 128
|
||||
|
||||
typedef struct gai_packet {
|
||||
char node[GAI_PACKET_NODE_MAXLEN];
|
||||
char service[GAI_PACKET_SERVICE_MAXLEN];
|
||||
struct addrinfo ai;
|
||||
} gai_packet_t;
|
||||
|
||||
int getaddrinfo(const char* __restrict node,
|
||||
const char* __restrict service,
|
||||
const struct addrinfo* __restrict hints,
|
||||
struct addrinfo** __restrict res) {
|
||||
mxio_t* io = NULL;
|
||||
mx_status_t r;
|
||||
|
||||
if ((r = __mxio_open(&io, NULL, "/dev/socket", 0, 0)) < 0) {
|
||||
return ERROR(r);
|
||||
}
|
||||
|
||||
gai_packet_t packet;
|
||||
if (node == NULL || service == NULL || res == NULL)
|
||||
return ERRNO(EINVAL);
|
||||
strncpy(packet.node, node, GAI_PACKET_NODE_MAXLEN);
|
||||
packet.node[GAI_PACKET_NODE_MAXLEN-1] = '\0';
|
||||
strncpy(packet.service, service, GAI_PACKET_SERVICE_MAXLEN);
|
||||
packet.service[GAI_PACKET_SERVICE_MAXLEN-1] = '\0';
|
||||
memcpy(&packet.ai, hints, sizeof(struct addrinfo));
|
||||
|
||||
uint32_t op = IOCTL(0, 0, 5);
|
||||
ssize_t r_gai = io->ops->ioctl(io, op, &packet, sizeof(packet), NULL, 0);
|
||||
mxio_close(io);
|
||||
mxio_release(io);
|
||||
|
||||
if (r_gai == 0) {
|
||||
struct addrinfo* ai = calloc(1, sizeof(struct addrinfo));
|
||||
memcpy(ai, &packet.ai, sizeof(struct addrinfo));
|
||||
*res = ai;
|
||||
}
|
||||
return r_gai;
|
||||
}
|
||||
|
||||
void freeaddrinfo(struct addrinfo* res) {
|
||||
free(res);
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário