From e27e529e589ef89fbe010ebf7c5635ec2873f64f Mon Sep 17 00:00:00 2001 From: Determinant Date: Wed, 12 Jun 2019 19:14:40 -0400 Subject: WIP: error handling --- src/conn.cpp | 114 +++++++++++++++++++++++++++++++------------------------- src/network.cpp | 9 +++-- src/util.cpp | 26 ++++++++++--- 3 files changed, 89 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/conn.cpp b/src/conn.cpp index 5fc59f3..7f485fd 100644 --- a/src/conn.cpp +++ b/src/conn.cpp @@ -170,34 +170,38 @@ void ConnPool::Conn::disp_terminate() { void ConnPool::accept_client(int fd, int) { int client_fd; struct sockaddr client_addr; - socklen_t addr_size = sizeof(struct sockaddr_in); - if ((client_fd = accept(fd, &client_addr, &addr_size)) < 0) - SALTICIDAE_LOG_ERROR("error while accepting the connection: %s", - strerror(errno)); - else - { - int one = 1; - if (setsockopt(client_fd, SOL_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)) < 0) - throw ConnPoolError(std::string("setsockopt failed")); - if (fcntl(client_fd, F_SETFL, O_NONBLOCK) == -1) - throw ConnPoolError(std::string("unable to set nonblocking socket")); + try { + socklen_t addr_size = sizeof(struct sockaddr_in); + if ((client_fd = accept(fd, &client_addr, &addr_size)) < 0) + throw ConnPoolError(SALTI_ERROR_ACCEPT, errno); + else + { + int one = 1; + if (setsockopt(client_fd, SOL_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)) < 0) + throw ConnPoolError(SALTI_ERROR_ACCEPT, errno); + if (fcntl(client_fd, F_SETFL, O_NONBLOCK) == -1) + throw ConnPoolError(SALTI_ERROR_ACCEPT, errno); - NetAddr addr((struct sockaddr_in *)&client_addr); - conn_t conn = create_conn(); - conn->self_ref = conn; - conn->send_buffer.set_capacity(queue_capacity); - conn->seg_buff_size = seg_buff_size; - conn->fd = client_fd; - conn->cpool = this; - conn->mode = Conn::PASSIVE; - conn->addr = addr; - add_conn(conn); - SALTICIDAE_LOG_INFO("accepted %s", std::string(*conn).c_str()); - auto &worker = select_worker(); - conn->worker = &worker; - conn->on_setup(); - update_conn(conn, true); - worker.feed(conn, client_fd); + NetAddr addr((struct sockaddr_in *)&client_addr); + conn_t conn = create_conn(); + conn->self_ref = conn; + conn->send_buffer.set_capacity(queue_capacity); + conn->seg_buff_size = seg_buff_size; + conn->fd = client_fd; + conn->cpool = this; + conn->mode = Conn::PASSIVE; + conn->addr = addr; + add_conn(conn); + SALTICIDAE_LOG_INFO("accepted %s", std::string(*conn).c_str()); + auto &worker = select_worker(); + conn->worker = &worker; + conn->on_setup(); + update_conn(conn, true); + worker.feed(conn, client_fd); + } + } catch (ConnPoolError &e) { + SALTICIDAE_LOG_ERROR("%s", e.what()); + throw e; } } @@ -229,24 +233,29 @@ void ConnPool::_listen(NetAddr listen_addr) { ev_listen.clear(); close(listen_fd); } - if ((listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - throw ConnPoolError(std::string("cannot create socket for listening")); - if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0 || - setsockopt(listen_fd, SOL_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)) < 0) - throw ConnPoolError(std::string("setsockopt failed")); - if (fcntl(listen_fd, F_SETFL, O_NONBLOCK) == -1) - throw ConnPoolError(std::string("unable to set nonblocking socket")); + try { + if ((listen_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + throw ConnPoolError(SALTI_ERROR_LISTEN, errno); + if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0 || + setsockopt(listen_fd, SOL_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)) < 0) + throw ConnPoolError(SALTI_ERROR_LISTEN, errno); + if (fcntl(listen_fd, F_SETFL, O_NONBLOCK) == -1) + throw ConnPoolError(SALTI_ERROR_LISTEN, errno); - struct sockaddr_in sockin; - memset(&sockin, 0, sizeof(struct sockaddr_in)); - sockin.sin_family = AF_INET; - sockin.sin_addr.s_addr = INADDR_ANY; - sockin.sin_port = listen_addr.port; + struct sockaddr_in sockin; + memset(&sockin, 0, sizeof(struct sockaddr_in)); + sockin.sin_family = AF_INET; + sockin.sin_addr.s_addr = INADDR_ANY; + sockin.sin_port = listen_addr.port; - if (bind(listen_fd, (struct sockaddr *)&sockin, sizeof(sockin)) < 0) - throw ConnPoolError(std::string("binding error")); - if (::listen(listen_fd, max_listen_backlog) < 0) - throw ConnPoolError(std::string("listen error")); + if (bind(listen_fd, (struct sockaddr *)&sockin, sizeof(sockin)) < 0) + throw ConnPoolError(SALTI_ERROR_LISTEN, errno); + if (::listen(listen_fd, max_listen_backlog) < 0) + throw ConnPoolError(SALTI_ERROR_LISTEN, errno); + } catch (ConnPoolError &e) { + SALTICIDAE_LOG_ERROR("%s", e.what()); + throw e; + } ev_listen = FdEvent(disp_ec, listen_fd, std::bind(&ConnPool::accept_client, this, _1, _2)); ev_listen.add(FdEvent::READ); @@ -256,13 +265,18 @@ void ConnPool::_listen(NetAddr listen_addr) { ConnPool::conn_t ConnPool::_connect(const NetAddr &addr) { int fd; int one = 1; - if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) - throw ConnPoolError(std::string("cannot create socket for remote")); - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0 || - setsockopt(fd, SOL_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)) < 0) - throw ConnPoolError(std::string("setsockopt failed")); - if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) - throw ConnPoolError(std::string("unable to set nonblocking socket")); + try { + if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + throw ConnPoolError(SALTI_ERROR_CONNECT, errno); + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&one, sizeof(one)) < 0 || + setsockopt(fd, SOL_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)) < 0) + throw ConnPoolError(SALTI_ERROR_CONNECT, errno); + if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) + throw ConnPoolError(SALTI_ERROR_CONNECT, errno); + } catch (ConnPoolError &e) { + SALTICIDAE_LOG_ERROR("%s", e.what()); + throw e; + } conn_t conn = create_conn(); conn->self_ref = conn; conn->send_buffer.set_capacity(queue_capacity); diff --git a/src/network.cpp b/src/network.cpp index 49bad48..30ef0eb 100644 --- a/src/network.cpp +++ b/src/network.cpp @@ -44,9 +44,10 @@ void msgnetwork_config_queue_capacity(msgnetwork_config_t *self, size_t cap) { self->queue_capacity(cap); } -bool msgnetwork_send_msg(msgnetwork_t *self, - const msg_t *msg, const msgnetwork_conn_t *conn) { - return self->_send_msg(*msg, *conn); +void msgnetwork_send_msg_by_move(msgnetwork_t *self, + msg_t *_moved_msg, const msgnetwork_conn_t *conn) { + self->_send_msg(std::move(*_moved_msg), *conn); + delete _moved_msg; } msgnetwork_conn_t *msgnetwork_connect(msgnetwork_t *self, const netaddr_t *addr) { @@ -167,7 +168,7 @@ void peernetwork_send_msg_by_move(peernetwork_t *self, void peernetwork_multicast_msg_by_move(peernetwork_t *self, msg_t *_moved_msg, const netaddr_array_t *paddrs) { - self->multicast_msg(std::move(*_moved_msg), *paddrs); + self->_multicast_msg(std::move(*_moved_msg), *paddrs); delete _moved_msg; } diff --git a/src/util.cpp b/src/util.cpp index a0d5044..f762b4c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -34,6 +34,22 @@ namespace salticidae { +const char *SALTICIDAE_ERROR_STRINGS[] = { + "", + "generic", + "unable to accept", + "unable to listen", + "unable to connect", + "peer already exists", + "peer does not exist", + "invalid NetAddr format", + "invalid OptVal format", + "option name already exists", + "unknown action", + "configuration file line too long", + "invalid option format" +}; + const char *TTY_COLOR_RED = "\x1b[31m"; const char *TTY_COLOR_GREEN = "\x1b[32m"; const char *TTY_COLOR_YELLOW = "\x1b[33m"; @@ -91,8 +107,6 @@ const std::string get_current_datetime() { return std::string(buf); } -SalticidaeError::SalticidaeError() : msg("unknown") {} - void Logger::set_color() { if (is_tty()) { @@ -182,7 +196,7 @@ void Config::add_opt(const std::string &optname, const optval_t &optval, Action char short_opt, const std::string &optdoc) { if (conf.count(optname)) - throw SalticidaeError("option name already exists"); + throw SalticidaeError(SALTI_ERROR_OPTNAME_ALREADY_EXISTS); opts.push_back(new Opt(optname, optdoc, optval, action, short_opt, opts.size())); @@ -199,7 +213,7 @@ void Config::update(Opt &p, const char *optval) { case SET_VAL: p.optval->set_val(optval); break; case APPEND: p.optval->append(optval); break; default: - throw SalticidaeError("unknown action"); + throw SalticidaeError(SALTI_ERROR_OPT_UNKNOWN_ACTION); } } @@ -220,7 +234,7 @@ bool Config::load(const std::string &fname) { if (strlen(buff) == BUFF_SIZE - 1) { fclose(conf_f); - throw SalticidaeError("configuration file line too long"); + throw SalticidaeError(SALTI_ERROR_CONFIG_LINE_TOO_LONG); } std::string line(buff); size_t pos = line.find("="); @@ -269,7 +283,7 @@ size_t Config::parse(int argc, char **argv) { if (id == -1) break; if (id == '?') - throw SalticidaeError("invalid option format"); + throw SalticidaeError(SALTI_ERROR_OPT_INVALID); if (id >= 0x100) update(*(opts[id - 0x100]), optarg); else -- cgit v1.2.3