/** * @brief * Net socket server */ /* * Copyright (c) 2017, ETH Zurich. * All rights reserved. * * This file is distributed under the terms in the attached LICENSE file. * If you do not find this file, copies can be found by writing to: * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "netss.h" struct socket_connection; struct network_connection { struct network_connection *next; struct capref buffer_cap; struct descq *queue; uint64_t queue_id; regionid_t region_id; void *buffer_start; uint64_t buffer_size; void *buffers[NO_OF_BUFFERS]; uint64_t next_free, next_used; struct net_sockets_binding *binding; struct descq *buffer_queue; struct socket_connection *sockets; }; #define MAX_SEND_FRAMES 2 struct send_frame { genoffset_t offset; genoffset_t sent, length; }; struct socket_connection { struct socket_connection *next; struct network_connection *connection; uint32_t descriptor; struct send_frame send_frames[MAX_SEND_FRAMES]; struct udp_pcb *udp_socket; struct tcp_pcb *tcp_socket; }; static struct network_connection *network_connections = NULL; static struct descq *exp_queue; static struct socket_connection * find_socket_connection(struct network_connection *nc, uint32_t descriptor) { struct socket_connection *socket; socket = nc->sockets; while (socket) { if (socket->descriptor == descriptor) break; socket = socket->next; } return socket; } static struct socket_connection * allocate_socket(struct network_connection *nc) { struct socket_connection *last, *socket; uint32_t last_descriptor = 0; last = NULL; socket = nc->sockets; while (socket) { if (socket->descriptor != last_descriptor + 1) break; last = socket; last_descriptor = last->descriptor; socket = socket->next; } socket = malloc(sizeof(struct socket_connection)); assert(socket); memset(socket, 0, sizeof(struct socket_connection)); if (last) { socket->next = last->next; last->next = socket; } else { nc->sockets = socket; } socket->descriptor = last_descriptor + 1; socket->connection = nc; socket->udp_socket = NULL; socket->tcp_socket = NULL; memset(socket->send_frames, 0, sizeof(socket->send_frames)); return socket; } static void net_udp_receive(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port) { struct socket_connection *connection = arg; struct network_connection *nc = connection->connection; errval_t err; assert(p->tot_len + sizeof(struct net_buffer) <= BUFFER_SIZE); uint32_t length = p->tot_len; void *buffer = nc->buffers[nc->next_free]; if (!buffer) { debug_printf("%s: drop\n", __func__); pbuf_free(p); return; } assert(buffer); nc->buffers[nc->next_free] = NULL; nc->next_free = (nc->next_free + 1) % NO_OF_BUFFERS; assert(sizeof(struct net_buffer) + length <= BUFFER_SIZE); struct net_buffer *nb = buffer; nb->size = length; nb->descriptor = connection->descriptor; nb->host_address.s_addr = addr->addr; nb->port = port; // debug_printf("%s(%d): %p -> %p %p %d\n", __func__, connection->descriptor, buffer, nb->user_callback, nb->user_state, nb->size); void *shb_data = buffer + sizeof(struct net_buffer); struct pbuf *it; uint32_t pos; it = p; for (pos = 0; pos < length; ) { assert(it); memcpy((void *)shb_data + pos, it->payload, it->len); pos += it->len; it = it->next; } pbuf_free(p); err = devq_enqueue((struct devq *)nc->queue, nc->region_id, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, 0, 0, NET_EVENT_RECEIVED); assert(err_is_ok(err)); err = devq_notify((struct devq *)nc->queue); assert(err_is_ok(err)); // debug_printf("%s: notifing\n", __func__); // struct net_sockets_binding *binding = connection->connection->binding; // debug_printf("%s: done\n", __func__); } static err_t net_tcp_receive(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t error) { struct socket_connection *socket = arg; struct network_connection *nc = socket->connection; errval_t err; uint32_t length = 0; void *buffer = nc->buffers[nc->next_free]; struct net_buffer *nb = buffer; // debug_printf("%s(%d): pcb:%p p:%p\n", __func__, socket->descriptor, pcb, p); if (p) { // debug_printf("%s(%d): %d\n", __func__, socket->descriptor, p->tot_len); assert(p->len == p->tot_len); length = p->tot_len; if (!buffer) { debug_printf("%s: drop\n", __func__); pbuf_free(p); return ERR_OK; } assert(buffer); nb->size = length; nb->descriptor = socket->descriptor; nb->accepted_descriptor = 0; nb->host_address.s_addr = 0; nb->port = 0; // debug_printf("%s(%d): %p -> %d\n", __func__, socket->descriptor, buffer, nb->size); void *shb_data = buffer + sizeof(struct net_buffer); memcpy((void *)shb_data, p->payload, length); tcp_recved(pcb, p->tot_len); pbuf_free(p); } else { assert(buffer); nb->size = 0; nb->descriptor = socket->descriptor; nb->accepted_descriptor = 0; nb->host_address.s_addr = 0; nb->port = 0; // debug_printf("%s(%d): close\n", __func__, socket->descriptor); // debug_printf_to_log("%s(%d): close", __func__, socket->descriptor); tcp_err(socket->tcp_socket, NULL); // debug_printf("%s(%d): close\n", __func__, socket->descriptor); // debug_printf("%s(%d): %p -> %p %p %d\n", __func__, connection->descriptor, buffer, nb->user_callback, nb->user_state, nb->size); } nc->buffers[nc->next_free] = NULL; nc->next_free = (nc->next_free + 1) % NO_OF_BUFFERS; assert(sizeof(struct net_buffer) + length <= BUFFER_SIZE); // debug_printf("%s.%d: enqueue 1 %lx:%ld %d\n", __func__, __LINE__, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, nb->descriptor); err = devq_enqueue((struct devq *)nc->queue, nc->region_id, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, 0, 0, NET_EVENT_RECEIVED); assert(err_is_ok(err)); err = devq_notify((struct devq *)nc->queue); assert(err_is_ok(err)); // debug_printf("%s: notifing\n", __func__); // struct net_sockets_binding *binding = connection->connection->binding; // debug_printf("%s: done\n", __func__); return ERR_OK; } static void net_tcp_error(void *arg, err_t tcp_err) { struct socket_connection *socket = arg; struct network_connection *nc = socket->connection; errval_t err; // debug_printf("%s(%d): error %d\n", __func__, socket->descriptor, tcp_err); // debug_printf_to_log("%s(%d): error %d", __func__, socket->descriptor, tcp_err); tcp_sent(socket->tcp_socket, NULL); tcp_recv(socket->tcp_socket, NULL); socket->tcp_socket = NULL; // invalidate void *buffer = nc->buffers[nc->next_free]; assert(buffer); struct net_buffer *nb = buffer; nb->size = 0; nb->descriptor = socket->descriptor; nb->accepted_descriptor = 0; nb->host_address.s_addr = 0; nb->port = 0; nc->buffers[nc->next_free] = NULL; nc->next_free = (nc->next_free + 1) % NO_OF_BUFFERS; err = devq_enqueue((struct devq *)nc->queue, nc->region_id, buffer - nc->buffer_start, sizeof(struct net_buffer), 0, 0, NET_EVENT_RECEIVED); assert(err_is_ok(err)); // debug_printf_to_log("%s(%d): close", __func__, socket->descriptor); err = devq_notify((struct devq *)nc->queue); assert(err_is_ok(err)); // uint32_t length = 0; // void *buffer = nc->buffers[nc->next_free]; // struct net_buffer *nb = buffer; // // assert(buffer); // nb->size = 0; // nb->descriptor = socket->descriptor; // nb->accepted_descriptor = 0; // nb->host_address.s_addr = 0; // nb->port = 0; // debug_printf("%s(%d): close on error\n", __func__, socket->descriptor); // nc->buffers[nc->next_free] = NULL; // nc->next_free = (nc->next_free + 1) % NO_OF_BUFFERS; // assert(sizeof(struct net_buffer) + length <= BUFFER_SIZE); // // // debug_printf("%s.%d: enqueue 1 %lx:%ld %d\n", __func__, __LINE__, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, nb->descriptor); // err = devq_enqueue((struct devq *)nc->queue, nc->region_id, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, // 0, 0, 1); // assert(err_is_ok(err)); // err = devq_notify((struct devq *)nc->queue); // assert(err_is_ok(err)); } static err_t net_tcp_sent(void *arg, struct tcp_pcb *pcb, uint16_t len) { struct socket_connection *socket = arg; struct network_connection *nc = socket->connection; bool notify = false; errval_t err; while (len > 0) { // debug_printf_to_log("%s(%d): %d %lx:%ld:%ld %lx:%ld:%ld", __func__, socket->descriptor, len, // socket->send_frames[0].offset, socket->send_frames[0].sent, socket->send_frames[0].length, // socket->send_frames[1].offset, socket->send_frames[1].sent, socket->send_frames[1].length); // debug_printf("%s(%d): %d %zx:%zd:%zd %zx:%zd:%zd\n", __func__, socket->descriptor, len, // socket->send_frames[0].offset, socket->send_frames[0].sent, socket->send_frames[0].length, // socket->send_frames[1].offset, socket->send_frames[1].sent, socket->send_frames[1].length); if (!socket->send_frames[0].length) debug_print_log(); assert(socket->send_frames[0].length); if (len < (socket->send_frames[0].length - socket->send_frames[0].sent)) { socket->send_frames[0].sent += len; len = 0; } else { len -= socket->send_frames[0].length - socket->send_frames[0].sent; socket->send_frames[0].length += sizeof(struct net_buffer); // debug_printf_to_log("%s.%d: enqueue %lx:%zd\n", __func__, __LINE__, socket->send_frames[0].offset, socket->send_frames[0].length); // err = devq_enqueue((struct devq *)nc->queue, nc->region_id, socket->send_frames[0].offset, socket->send_frames[0].length, 0, 0, NET_EVENT_SENT); if (!err_is_ok(err)) debug_printf("%s: err %zd\n", __func__, err); assert(err_is_ok(err)); notify = true; socket->send_frames[0] = socket->send_frames[1]; socket->send_frames[1].sent = 0; socket->send_frames[1].length = 0; socket->send_frames[1].offset = 0; } } if (notify) { err = devq_notify((struct devq *)nc->queue); assert(err_is_ok(err)); } return ERR_OK; } static err_t net_tcp_accepted(void *arg, struct tcp_pcb *newpcb, err_t error) { struct socket_connection *socket = arg; struct network_connection *nc = socket->connection; struct socket_connection *accepted_socket; newpcb->flags |= TF_NODELAY; accepted_socket = allocate_socket(nc); accepted_socket->udp_socket = NULL; accepted_socket->tcp_socket = newpcb; tcp_arg(accepted_socket->tcp_socket, accepted_socket); tcp_recv(accepted_socket->tcp_socket, net_tcp_receive); tcp_err(accepted_socket->tcp_socket, net_tcp_error); tcp_sent(accepted_socket->tcp_socket, net_tcp_sent); // debug_printf("%s(%d): -> %d\n", __func__, socket->descriptor, accepted_socket->descriptor); // errval_t err = nc->binding->tx_vtbl.accepted(nc->binding, BLOCKING_CONT, socket->descriptor, accepted_socket->descriptor, 0, 0, SYS_ERR_OK); // assert(err_is_ok(err)); errval_t err; uint32_t length = 0; void *buffer = nc->buffers[nc->next_free]; struct net_buffer *nb = buffer; nb->size = 0; nb->descriptor = socket->descriptor; nb->accepted_descriptor = accepted_socket->descriptor; nb->host_address.s_addr = newpcb->remote_ip.addr; nb->port = newpcb->remote_port; // debug_printf_to_log("%s(%d): accepted", __func__, accepted_socket->descriptor); nc->buffers[nc->next_free] = NULL; nc->next_free = (nc->next_free + 1) % NO_OF_BUFFERS; assert(sizeof(struct net_buffer) + length <= BUFFER_SIZE); // debug_printf("%s.%d: enqueue 1 %lx:%ld %d\n", __func__, __LINE__, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, nb->descriptor); err = devq_enqueue((struct devq *)nc->queue, nc->region_id, buffer - nc->buffer_start, sizeof(struct net_buffer) + length, 0, 0, NET_EVENT_ACCEPT); assert(err_is_ok(err)); err = devq_notify((struct devq *)nc->queue); assert(err_is_ok(err)); return ERR_OK; } static errval_t net_request_descq_ep(struct net_sockets_binding *binding, uint16_t core, struct capref* ep) { errval_t err; err = slot_alloc(ep); if (err_is_fail(err)) { return err; } err = descq_create_ep(exp_queue, core, ep); if (err_is_fail(err)) { slot_free(*ep); } return err; } static errval_t net_register_queue(struct net_sockets_binding *binding, uint64_t queue_id) { struct network_connection *nc; nc = network_connections; while (nc) { if (nc->queue_id == queue_id) break; nc = nc->next; } assert(nc); binding->st = nc; nc->binding = binding; devq_set_state((struct devq *)nc->queue, nc); return SYS_ERR_OK; } static errval_t net_udp_socket(struct net_sockets_binding *binding, uint32_t *descriptor) { struct network_connection *nc; struct socket_connection *socket; nc = binding->st; socket = allocate_socket(nc); *descriptor = socket->descriptor; struct udp_pcb *pcb = udp_new(); assert(pcb); socket->udp_socket = pcb; udp_recv(socket->udp_socket, net_udp_receive, socket); return SYS_ERR_OK; } static errval_t net_tcp_socket(struct net_sockets_binding *binding, uint32_t *descriptor) { struct network_connection *nc; struct socket_connection *socket; nc = binding->st; socket = allocate_socket(nc); *descriptor = socket->descriptor; struct tcp_pcb *pcb = tcp_new(); assert(pcb); pcb->flags |= TF_NODELAY; socket->tcp_socket = pcb; tcp_arg(pcb, socket); tcp_recv(socket->tcp_socket, net_tcp_receive); return SYS_ERR_OK; } static errval_t net_bind(struct net_sockets_binding *binding, uint32_t descriptor, uint32_t ip_address, uint16_t port, errval_t *error, uint16_t *bound_port) { struct network_connection *nc; struct socket_connection *socket; nc = binding->st; socket = find_socket_connection(nc, descriptor); assert(socket); if (socket->udp_socket) { ip_addr_t ip; ip.addr = ip_address; *error = udp_bind(socket->udp_socket, &ip, port); assert(err_is_ok(*error)); *bound_port = socket->udp_socket->local_port; *error = SYS_ERR_OK; } else if (socket->tcp_socket) { ip_addr_t ip; ip.addr = ip_address; // debug_printf("%s(%d): %x %d\n", __func__, socket->descriptor, ip.addr, port); *error = tcp_bind(socket->tcp_socket, &ip, port); assert(err_is_ok(*error)); *bound_port = socket->tcp_socket->local_port; *error = SYS_ERR_OK; } return SYS_ERR_OK; } static errval_t net_listen(struct net_sockets_binding *binding, uint32_t descriptor, uint8_t backlog, errval_t *error) { struct network_connection *nc; struct socket_connection *socket; if (descriptor == -1) { debug_print_log(); return SYS_ERR_OK; } nc = binding->st; socket = find_socket_connection(nc, descriptor); assert(socket); assert(socket->tcp_socket); socket->tcp_socket = tcp_listen(socket->tcp_socket); // debug_printf("%s(%d): listen %p\n", __func__, descriptor, socket->tcp_socket); tcp_accept(socket->tcp_socket, net_tcp_accepted); tcp_err(socket->tcp_socket, net_tcp_error); // socket->tcp_socket = tcp_listen_with_backlog(socket->tcp_socket, backlog); assert(socket->tcp_socket); *error = SYS_ERR_OK; return SYS_ERR_OK; } static err_t net_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t error) { struct socket_connection *socket = arg; struct network_connection *nc = socket->connection; errval_t err = nc->binding->tx_vtbl.connected(nc->binding, BLOCKING_CONT, socket->descriptor, SYS_ERR_OK, tpcb->remote_ip.addr, tpcb->remote_port); assert(err_is_ok(err)); return SYS_ERR_OK; } static errval_t net_connect(struct net_sockets_binding *binding, uint32_t descriptor, uint32_t ip_address, uint16_t port, errval_t *error) { struct network_connection *nc; struct socket_connection *socket; nc = binding->st; socket = find_socket_connection(nc, descriptor); assert(socket); if (socket->udp_socket) { ip_addr_t addr; err_t e; addr.addr = ip_address; e = udp_connect(socket->udp_socket, &addr, port); assert(e == ERR_OK); *error = SYS_ERR_OK; } else if (socket->tcp_socket) { ip_addr_t addr; err_t e; addr.addr = ip_address; e = tcp_connect(socket->tcp_socket, &addr, port, net_tcp_connected); assert(e == ERR_OK); *error = SYS_ERR_OK; } return SYS_ERR_OK; } static void net_delete_socket(struct network_connection *nc, uint32_t descriptor) { struct socket_connection *socket, *last; errval_t err; // debug_printf_to_log("%s(%d): tcp_close", __func__, descriptor); socket = nc->sockets; last = NULL; while (socket) { if (socket->descriptor == descriptor) break; last = socket; socket = socket->next; } if (!socket) debug_print_log(); assert(socket); if (socket->udp_socket) { udp_recv(socket->udp_socket, NULL, NULL); udp_remove(socket->udp_socket); } else if (socket->tcp_socket) { tcp_recv(socket->tcp_socket, NULL); // you can receive packets after you close the socket tcp_sent(socket->tcp_socket, NULL); // tcp_accept(socket->tcp_socket, NULL); err_t e; e = tcp_close(socket->tcp_socket); assert(e == ERR_OK); } // debug_printf_to_log("%s(%d): %p:%ld:%ld %p:%ld:%ld", __func__, socket->descriptor, // socket->send_frames[0].offset, socket->send_frames[0].sent, socket->send_frames[0].length, // socket->send_frames[1].offset, socket->send_frames[1].sent, socket->send_frames[1].length); while (socket->send_frames[0].length) { // invaldate all sent frames void *buffer; struct net_buffer *nb; // debug_printf_to_log("%s(%d): %p:%ld:%ld %p:%ld:%ld", __func__, socket->descriptor, // socket->send_frames[0].offset, socket->send_frames[0].sent, socket->send_frames[0].length, // socket->send_frames[1].offset, socket->send_frames[1].sent, socket->send_frames[1].length); socket->send_frames[0].length += sizeof(struct net_buffer); buffer = socket->send_frames[0].offset + nc->buffer_start; nb = buffer; nb->descriptor = descriptor; // debug_printf_to_log("%s.%d: enqueue %lx:%zd\n", __func__, __LINE__, socket->send_frames[0].offset, socket->send_frames[0].length); err = devq_enqueue((struct devq *)nc->queue, nc->region_id, socket->send_frames[0].offset, socket->send_frames[0].length, 0, 0, NET_EVENT_SENT); assert(err_is_ok(err)); socket->send_frames[0] = socket->send_frames[1]; socket->send_frames[1].sent = 0; socket->send_frames[1].length = 0; socket->send_frames[1].offset = 0; } // debug_printf("%s(%d):\n", __func__, descriptor); // debug_printf("%s: %ld:%p %ld:%p\n", __func__, nc->next_free, nc->buffers[nc->next_free], nc->next_used, nc->buffers[nc->next_used]); if (last) last->next = socket->next; else nc->sockets = socket->next; free(socket); } static uint64_t qid = 1; static errval_t q_create(struct descq* q, uint64_t* queue_id) { struct network_connection *nc; nc = malloc(sizeof(struct network_connection)); assert(nc); nc->next = network_connections; network_connections = nc; nc->sockets = NULL; nc->binding = NULL; nc->queue = q; *queue_id = qid++; nc->queue_id = *queue_id; memset(nc->buffers, 0, sizeof(nc->buffers)); nc->next_free = 0; nc->next_used = 0; return SYS_ERR_OK; } static errval_t q_destroy(struct descq* q) { return SYS_ERR_OK; } static errval_t q_notify(struct descq* q) { struct devq* queue = (struct devq *)q; errval_t err = SYS_ERR_OK; //errval_t err2 = SYS_ERR_OK; regionid_t rid; genoffset_t offset; genoffset_t length; genoffset_t valid_data; genoffset_t valid_length; uint64_t event; struct network_connection *nc; bool notify = 0; // debug_printf("%s: \n", __func__); nc = devq_get_state(queue); for (int i = 0; i < NETSOCKET_LOOP_ITER; i++) { err = devq_dequeue(queue, &rid, &offset, &length, &valid_data, &valid_length, &event); if (err_is_fail(err)) { break; } else { void *buffer; buffer = offset + nc->buffer_start; struct net_buffer *nb = buffer; //debug_printf_to_log("%s: dequeue %lx:%ld %ld %d:%d", __func__, offset, length, event, nb->descriptor, nb->size); //debug_printf(" offset %lu length %lu \n", offset, length); if (event == NET_EVENT_RECEIVE) { assert(!nc->buffers[nc->next_used]); nc->buffers[nc->next_used] = nc->buffer_start + offset; nc->next_used = (nc->next_used + 1) % NO_OF_BUFFERS; } else if (event == NET_EVENT_SEND) { struct socket_connection *socket; void *shb_data = (void *)buffer + sizeof(struct net_buffer); // debug_printf("%s: %p\n", __func__, buffer); // find the socket socket = find_socket_connection(nc, nb->descriptor); if (!socket) debug_printf("%s(%d): %p\n", __func__, nb->descriptor, socket); assert(socket); // debug_printf("buffer: %d %d %x %d %p %p\n", nb->size, nb->descriptor, nb->host_address, nb->port, socket->udp_socket, socket->tcp_socket); if (socket->udp_socket) { struct udp_pcb *pcb = socket->udp_socket; struct pbuf *p; p = pbuf_alloc(PBUF_TRANSPORT, nb->size, PBUF_RAM); assert(p); memcpy(p->payload, shb_data, nb->size); ip_addr_t addr; uint16_t port; port = nb->port; addr.addr = nb->host_address.s_addr; // debug_printf("%s.%d: enqueue 2 %lx:%d\n", __func__, __LINE__, offset, nb->size); err = devq_enqueue(queue, rid, offset, length, 0, 0, NET_EVENT_SENT); assert(err_is_ok(err)); notify = 1; // debug_printf("%s(%d): %d\n", __func__, socket->descriptor, p->tot_len); if (port && addr.addr) { err_t e; e = udp_sendto(pcb, p, &addr, port); if (e != ERR_OK) debug_printf("%s(%d): err:%d\n", __func__, socket->descriptor, e); assert(e == ERR_OK); } else { err_t e; e = udp_send(pcb, p); if (e != ERR_OK) debug_printf("%s(%d): err:%d\n", __func__, socket->descriptor, e); assert(e == ERR_OK); } pbuf_free(p); } else if (socket->tcp_socket) { err_t e; // debug_printf("%s: dequeue %lx:%ld %ld\n", __func__, offset, length, event); if (socket->send_frames[0].length == 0) { } else { assert(socket->send_frames[1].length == 0); } // debug_printf("%s: tcp_write %d %d\n", __func__, tcp_sndbuf(socket->tcp_socket), nb->size); e = tcp_write(socket->tcp_socket, shb_data, nb->size, TCP_WRITE_FLAG_COPY); if (e != ERR_OK) debug_printf("%s: e=%d\n", __func__, e); assert(e == ERR_OK); e = tcp_output(socket->tcp_socket); assert(e == ERR_OK); if (socket->send_frames[0].length == 0) { socket->send_frames[0].offset = offset; socket->send_frames[0].length = length - sizeof(struct net_buffer); } else { socket->send_frames[1].offset = offset; socket->send_frames[1].length = length - sizeof(struct net_buffer); } // debug_printf_to_log("%s(%d): tcp_send %lx:%ld %p:%ld:%ld %p:%ld:%ld", __func__, socket->descriptor, offset, length, // socket->send_frames[0].offset, socket->send_frames[0].sent, socket->send_frames[0].length, // socket->send_frames[1].offset, socket->send_frames[1].sent, socket->send_frames[1].length); // debug_printf("%s.%d: enqueue 2 %lx:%zd\n", __func__, __LINE__, offset, length); // err = devq_enqueue(queue, rid, offset, length, 0, 0, 2); // assert(err_is_ok(err)); // notify = 1; } else { err = devq_enqueue(queue, rid, offset, length, 0, 0, NET_EVENT_SENT); assert(err_is_ok(err)); notify = 1; } } else if (event == NET_EVENT_CLOSE) { // struct net_buffer *nb = offset + nc->buffer_start; // debug_printf("%s(%d): close\n", __func__, nb->descriptor); net_delete_socket(nc, nb->descriptor); err = devq_enqueue(queue, rid, offset, length, 0, 0, NET_EVENT_CLOSED); assert(err_is_ok(err)); notify = 1; } else { debug_printf("%s: unknown event %ld!", __func__, event); assert(0); } } } if (notify) { // debug_printf("notify>\n"); err = devq_notify(queue); // debug_printf("notify<\n"); assert(err_is_ok(err)); } return SYS_ERR_OK; } static errval_t q_reg(struct descq* q, struct capref cap, regionid_t rid) { struct frame_identity pa; struct network_connection *nc; nc = devq_get_state((struct devq *)q); errval_t err = frame_identify(cap, &pa); assert(err_is_ok(err)); nc->buffer_cap = cap; nc->region_id = rid; nc->buffer_size = pa.bytes; err = vspace_map_one_frame(&nc->buffer_start, pa.bytes, cap, NULL, NULL); assert(err_is_ok(err)); return SYS_ERR_OK; } static errval_t q_dereg(struct descq* q, regionid_t rid) { return SYS_ERR_OK; } static errval_t q_control(struct descq* q, uint64_t cmd, uint64_t value, uint64_t* res) { return SYS_ERR_OK; } static struct net_sockets_rpc_rx_vtbl rpc_rx_vtbl = { .request_descq_ep_call = net_request_descq_ep, .register_queue_call = net_register_queue, .new_udp_socket_call = net_udp_socket, .new_tcp_socket_call = net_tcp_socket, .bind_call = net_bind, .connect_call = net_connect, .listen_call = net_listen, }; static errval_t connect_cb(void *st, struct net_sockets_binding *binding) { binding->rpc_rx_vtbl = rpc_rx_vtbl; return SYS_ERR_OK; } static void export_cb(void *st, errval_t err, iref_t iref) { char* service_name = (char* ) st; assert(err_is_ok(err)); err = nameservice_register(service_name, iref); assert(err_is_ok(err)); } int main(int argc, char *argv[]) { errval_t err; if (argc < 4) { printf("%s: missing arguments! \n", argv[0]); return -1; } debug_printf("Net socket server started for %s.\n", argv[2]); char card_name[64]; snprintf(card_name, sizeof(card_name), "%s:%s", argv[2], argv[argc - 1]); char *ip = NULL; char *netmask = NULL; char *gw = NULL; while (1) { int option_index = 0; int c; static struct option long_options[] = { {"ip", required_argument, 0, 1}, {"netmask", required_argument, 0, 2}, {"gw", required_argument, 0, 3}, {0, 0, 0, 0} }; c = getopt_long_only(argc, argv, "", long_options, &option_index); if (c == -1) break; switch (c) { case 1: ip = optarg; break; case 2: netmask = optarg; break; case 3: gw = optarg; break; default: break; } } if (ip) printf("option ip [%s]\n", ip); if (netmask) printf("option nm [%s]\n", netmask); if (gw) printf("option gw [%s]\n", gw); if (ip) { // setting static IP, no DHCP err = oct_init(); assert(err_is_ok(err)); err = oct_set(NET_CONFIG_STATIC_IP_RECORD_FORMAT, inet_addr(ip), gw ? inet_addr(gw): 0, netmask ? inet_addr(netmask): 0); assert(err_is_ok(err)); } // EP to driver given by kaluga, TODO fix oldsytel driver like MLX4 struct capref ep = { .cnode = build_cnoderef(cap_argcn, CNODE_TYPE_OTHER), .slot = 0 }; /* connect to the network */ #ifdef POLLING debug_printf("Net socket server polling \n"); err = networking_init_with_ep(card_name, ep, (!ip ? NET_FLAGS_DO_DHCP: 0) | NET_FLAGS_DEFAULT_QUEUE | NET_FLAGS_BLOCKING_INIT | NET_FLAGS_POLLING ); #else debug_printf("Net socket server using interrupts \n"); err = networking_init_with_ep(card_name, ep, (!ip ? NET_FLAGS_DO_DHCP: 0) | NET_FLAGS_DEFAULT_QUEUE | NET_FLAGS_BLOCKING_INIT); #endif if (err_is_fail(err)) { USER_PANIC_ERR(err, "Failed to initialize the network"); } struct descq_func_pointer f; f.notify = q_notify; f.create = q_create; f.destroy = q_destroy; f.reg = q_reg; f.dereg = q_dereg; f.control = q_control; char queue_name[64]; char service_name[64]; sprintf(queue_name, "net_sockets_queue_%s", argv[2]); sprintf(service_name, "net_sockets_service_%s", argv[2]); err = descq_create(&exp_queue, DESCQ_DEFAULT_SIZE, queue_name, true, NULL, &f); assert(err_is_ok(err)); err = net_sockets_export(service_name, export_cb, connect_cb, get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT); assert(err_is_ok(err)); struct waitset *ws = get_default_waitset(); #ifdef POLLING #define POLLING_YIELD_IDLE 10 uint16_t polling_yield = POLLING_YIELD_IDLE; #endif while(1) { #ifdef POLLING err = event_dispatch_non_block(ws); switch(err_no(err)) { case SYS_ERR_OK: polling_yield = POLLING_YIELD_IDLE; break; case LIB_ERR_NO_EVENT: polling_yield--; break; default: USER_PANIC_ERR(err, "error happened while dispatching event."); } err = networking_poll(); switch(err_no(err)) { case SYS_ERR_OK: polling_yield = POLLING_YIELD_IDLE; break; case LIB_ERR_NO_EVENT: polling_yield--; break; default: USER_PANIC_ERR(err, "error happened while dispatching event."); } if (polling_yield == 0) { thread_yield(); polling_yield = POLLING_YIELD_IDLE; } #else event_dispatch(ws); #endif } debug_printf("Net socket server termiated.\n"); return 0; }