Comparar commits

...

5 Commits

Autor SHA1 Mensagem Data
Toshi Kikuchi 66b887c089 [hack] Always disable netsvc
Change-Id: I83833682edd554fbe90ea4ea7b95ff192a888651
2016-09-07 10:49:59 -07:00
Toshi Kikuchi 7a1078e674 WIP: add connect and getaddrinfo
Change-Id: I63c14c98d731f34dac1ad934eb785a849e9837b8
2016-09-07 10:32:54 -07:00
Toshi Kikuchi 5b4d86a89c [uapp] EXPERIMENTAL: a simple socket test program
FYI.

Change-Id: I2747d38254bb429360d9e6a15aa43f4d8d0e7647
2016-09-07 10:32:54 -07:00
Toshi Kikuchi 728414bf8d [mxio] EXPERIMENTAL: BSD socket API using remoteio
Change-Id: I01e2ab728b3875baad4edfeeb39c5c4e469b8368
2016-09-07 10:32:54 -07:00
Toshi Kikuchi a9c7afff30 [devmgr][dmctl] mount socket server on /dev/socket
Change-Id: I9f6590a45242573f4de5558f3bd337823ed4bf76
2016-09-07 10:32:54 -07:00
7 arquivos alterados com 318 adições e 44 exclusões
+28 -14
Ver Arquivo
@@ -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 = {
+1 -1
Ver Arquivo
@@ -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);
}
+20 -8
Ver Arquivo
@@ -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;
}
+21
Ver Arquivo
@@ -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
+87
Ver Arquivo
@@ -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;
}
-21
Ver Arquivo
@@ -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);
}
+161
Ver Arquivo
@@ -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);
}