/** * \brief Function to allocate memory for a broker connection struct. * \param conn_p Pointer to the address of the new connection struct. */ void init_connection(struct broker_conn **conn_p) { LOG_DEBUG_FN("fn: init_connection"); struct broker_conn *conn; if (!(conn = calloc(1, sizeof(struct broker_conn)))) { LOG_ERROR("Allocating space for the broker connection failed"); free_connection(conn); } if (!(conn->client.clientid = calloc(UMQTT_CLIENTID_MAX_LEN, sizeof(char)))) { LOG_ERROR("Allocating space for the clientid failed"); free_connection(conn); } if (!(conn->client.username = calloc(UMQTT_USERNAME_MAX_LEN, sizeof(char)))) { LOG_ERROR("Allocating space for the username failed"); free_connection(conn); } if (!(conn->client.password = calloc(UMQTT_PASSWORD_MAX_LEN, sizeof(char)))) { LOG_ERROR("Allocating space for the password failed"); free_connection(conn); } *conn_p = conn; return; }
int get_reply_message(DBusConnection* conn, DBusError *err, DBusMessage *dbus_msg, DBusMessage *dbus_reply, struct sudo_result_contents * sudo_result, DBusMessageIter * msg_iter){ int ret = -1,count =0; ret = dbus_message_get_args(dbus_reply, err, DBUS_TYPE_UINT32,&sudo_result->header, DBUS_TYPE_STRING,&sudo_result->result_str, DBUS_TYPE_ARRAY,DBUS_TYPE_STRING,&sudo_result->command_array, &sudo_result->command_array_out_size, DBUS_TYPE_INVALID); if (!ret) { fprintf (stderr,"Failed to parse reply, killing connection\n"); free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,dbus_reply); return SSS_SUDO_REPLY_ERR; } if(sudo_result->header != SSS_SUDO_REPLY_HEADER){ sudo_log(SUDO_CONV_ERROR_MSG, "Reply header mismatch - Detected unreliable packet. Access denied\n"); return SSS_SUDO_REPLY_ERR; } fprintf(stdout,"----------Reply--------:\n" "Header : %d \nResult status : %s\n" "Command : ", sudo_result->header,sudo_result->result_str); for(count =0;count< sudo_result->command_array_out_size;count++){ printf("%s ", sudo_result->command_array[count]); } if (!dbus_message_iter_init(dbus_reply, msg_iter)) { fprintf(stderr, "Reply iterator failed!\n"); free_connection(conn,err,(hash_table_t *)NULL,dbus_msg,dbus_reply); return SSS_SUDO_REPLY_ERR; } printf("\n"); dbus_message_iter_next(msg_iter); dbus_message_iter_next(msg_iter); dbus_message_iter_next(msg_iter); if(dbus_msg_iter_to_dhash(msg_iter, &sudo_result->env_table_out) != SSS_SBUS_CONV_SUCCESS){ fprintf(stderr, "env message iterator corrupted!\n"); free_connection(conn,err,(hash_table_t *)NULL,dbus_msg,dbus_reply); return SSS_SUDO_REPLY_ERR; } printf("---------Reply End----------\n"); return SSS_SUDO_REPLY_OK; }
/** * Shutdown a connection and all associated. Also frees the * proxy_connection structure and removes it from the * connection_context. * * @access private * @param fd_set master * @param connection_context * * @param int hsocket * @return int success */ int _shutdown_connections(fd_set *master, connection_context *ctx, int hSocket) { proxy_connection *conn; /* Retrieve the connection context */ if (NULL == (conn= get_connection_by_socket (ctx, hSocket))) { ERR ("Unable to find proxy connection in context"); return 0; } /* Perform filter shutdown */ csta_filter_shutdown(conn); /* Close all associated sockets */ if (conn->hServer) { close (conn->hServer); FD_CLR(conn->hServer, master); } if (conn->hClient) { close (conn->hClient); FD_CLR(conn->hClient, master); } /* Now free anything left */ delete_connection(ctx, conn); free_connection(&conn); return 1; }
/* close all open network connections */ void close_network_connections(meshlink_handle_t *mesh) { if(mesh->connections) { for(list_node_t *node = mesh->connections->head, *next; node; node = next) { next = node->next; connection_t *c = node->data; c->outgoing = NULL; terminate_connection(mesh, c, false); } } if(mesh->outgoings) list_delete_list(mesh->outgoings); if(mesh->self && mesh->self->connection) { terminate_connection(mesh, mesh->self->connection, false); free_connection(mesh->self->connection); } for(int i = 0; i < mesh->listen_sockets; i++) { io_del(&mesh->loop, &mesh->listen_socket[i].tcp); io_del(&mesh->loop, &mesh->listen_socket[i].udp); close(mesh->listen_socket[i].tcp.fd); close(mesh->listen_socket[i].udp.fd); } exit_requests(mesh); exit_edges(mesh); exit_nodes(mesh); exit_connections(mesh); if(mesh->myport) free(mesh->myport); return; }
/** Process a timer on client socket. * @param ev Timer event that has a struct Connection as its * associated data. */ static void client_timer_callback(struct Event* ev) { struct Client* cptr; struct Connection* con; assert(0 != ev_timer(ev)); assert(0 != t_data(ev_timer(ev))); assert(ET_DESTROY == ev_type(ev) || ET_EXPIRE == ev_type(ev)); con = (struct Connection*) t_data(ev_timer(ev)); assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY); cptr = con_client(con); assert(0 == cptr || con == cli_connect(cptr)); if (ev_type(ev)== ET_DESTROY) { con_freeflag(con) &= ~FREEFLAG_TIMER; /* timer has expired... */ if (!con_freeflag(con) && !cptr) free_connection(con); /* client is being destroyed */ } else { Debug((DEBUG_LIST, "Client process timer for %C expired; processing", cptr)); read_packet(cptr, 0); /* read_packet will re-add timer if needed */ } assert(0 == cptr || 0 == cli_connect(cptr) || con == cli_connect(cptr)); }
void cql::cql_session_impl_t::close() { boost::recursive_mutex::scoped_lock lock(_mutex); if(_Iam_closed) return; for (connection_pool_t::iterator host_it = _connection_pool.begin(); host_it != _connection_pool.end(); ++host_it) { cql_connections_collection_t* connections = host_it->second; for (cql_connections_collection_t::iterator conn_it = connections->begin(); conn_it != connections->end(); ++conn_it) { free_connection(conn_it->second); } connections->clear(); } _connection_pool.clear(); if (_trashcan) { _trashcan = boost::shared_ptr<cql_trashcan_t>(); } log(0, "size of session::_connection_poll is " + boost::lexical_cast<std::string>(_connection_pool.size())); _Iam_closed = true; }
static void request_handler (aeEventLoop * el, int fd, void *data, int mask) { workerState *ws = (workerState *) data; simpleBuf *sb = &ws->out; int tw; if (ws->reconn_after > 0LL) { ws->reconn_after = 0LL; } tw = sb_write (sb, fd); if (tw < 0) { fprintf (stderr, "[smr-client] failed to sb_write:%d\n", tw); free_connection (ws, 1); return; } if (sb->ep - sb->cp == 0) { sb->cp = sb->buf; //reset sb aeDeleteFileEvent (el, fd, AE_WRITABLE); ws->wprepared = 0; } return; }
void ICACHE_FLASH_ATTR client_reconnect_cb(void* conn, sint8 err) { struct espconn* pconn = (struct espconn*)conn; os_printf("client connection error: [%d]\n", err); free_connection(pconn); //server_listen(); }
void websocket_close(struct websocket *ws, enum ws_status_code status_code) { if (ws->upgrade_complete) { websocket_send_close_frame(ws, status_code, NULL, 0); } free_connection(ws->connection); }
static bool handle_writing_data_to_event(connection_data *connection) { buffer *data = &connection->data; assert(data->start <= data->capacity); while (true) { int n = write(connection->fd, data->bytes + data->start, data->size - data->start); //logger_.log("%d B was written", n); // <--- this is the greatest WTF I have ever seen :( assert( !((n == -1 && errno == EINTR)) ); if (n != -1) { assert(n > 0 && (n <= (int)data->size) ); data->start += n; if (data->start == data->size) break; } else if (n == -1) { // TO DO: // EAGAIN means that we cannot send more data now (because of e.g full recv buffer on client side) // but there are some data to send. So we should break loop but before that // remember state and modify epoll context for writing like: // modify_epoll_context(epoll_fd, EPOLL_CTL_ADD, connection->fd, EPOLLOUT, connection); // Now we have spin loop here but we just want to sleep in epoll_wait. if (errno == EAGAIN) { // we leave data->start as it is return false; } logger_.log("Error during writing. Connection was closed on %d", connection->fd); free_connection(connection); if (global_write_handler != NULL) global_write_handler(n, NULL); data->start = 0; return true; } } if (data->start != data->size) { logger_.log("start = %zu, data->size = %zu!", data->start, data->size); assert(false); } if (global_write_handler != NULL) global_write_handler(data->size, connection); data->start = 0; return true; }
void exit_connections(meshlink_handle_t *mesh) { if(mesh->connections) list_delete_list(mesh->connections); free_connection(mesh->everyone); mesh->connections = NULL; mesh->everyone = NULL; }
static void ssl_rdwr_handler(connections_head_t *head, connection_t *conn) { /* We have data on the fd waiting to be read. Read and * display it. We must read what ever data is availabe * completely, as we are running in edge-triggered mode * and won't get a notification again for the same data */ int done = 0; ssize_t count, wrlen; char buf[512]; SSL_SESSION *sess; sess = SSL_get_session(conn->ssl); printf("The session is %p\n", sess); while (1) { count = SSL_read(conn->ssl, buf, sizeof buf); if (-1 == count) { /* If errno == EAGAIN, that means we have read all * data. So go back to the main loop. */ if (errno != EAGAIN) { ERROR_MSG("SSL_read\n"); done = 1; } break; } else if (0 == count) { /* End of file. The remote has closed the * connection */ done = 1; printf("%s|%d|remote close socket\n", __FILE__, __LINE__); break; } wrlen = SSL_write(conn->ssl, buf, count); if (wrlen <= 0) { if (errno != EAGAIN) { ERROR_MSG("SSL_write"); done = 1; } } else { /* write ok, wait for the next read */ break; } } if (done) { printf("Closed connection on descriptor %d\n", conn->fd); /* Closing the descriptor wil make epoll remove it * from the set of descriptors which are monitored. */ free_connection(head, conn); } }
/* close all open network connections */ void close_network_connections(void) { avl_node_t *node, *next; connection_t *c; char *envp[5]; int i; for(node = connection_tree->head; node; node = next) { next = node->next; c = node->data; c->outgoing = NULL; terminate_connection(c, false); } for(list_node_t *node = outgoing_list->head; node; node = node->next) { outgoing_t *outgoing = node->data; if(outgoing->event) event_del(outgoing->event); } list_delete_list(outgoing_list); if(myself && myself->connection) { subnet_update(myself, NULL, false); terminate_connection(myself->connection, false); free_connection(myself->connection); } for(i = 0; i < listen_sockets; i++) { close(listen_socket[i].tcp); close(listen_socket[i].udp); } xasprintf(&envp[0], "NETNAME=%s", netname ? : ""); xasprintf(&envp[1], "DEVICE=%s", device ? : ""); xasprintf(&envp[2], "INTERFACE=%s", iface ? : ""); xasprintf(&envp[3], "NAME=%s", myself->name); envp[4] = NULL; exit_requests(); exit_edges(); exit_subnets(); exit_nodes(); exit_connections(); exit_events(); execute_script("tinc-down", envp); if(myport) free(myport); for(i = 0; i < 4; i++) free(envp[i]); close_device(); return; }
/** * @brief read from a connection */ void *connection_reader(void *arg) { struct message *msg; conn_node *c; c=(conn_node *) arg; #ifndef NDEBUG print( DEBUG, "started (fd=%d, tid=%lu)", c->fd, pthread_self() ); #endif while((msg = read_message(c->fd))) { pthread_mutex_lock(&(c->control.mutex)); while(c->freeze) { pthread_cond_wait(&(c->control.cond), &(c->control.mutex)); } pthread_mutex_unlock(&(c->control.mutex)); if(enqueue_message(&(c->incoming), msg)) { print( ERROR, "cannot enqueue received message" ); dump_message(msg); free_message(msg); } } stop_connection(c); pthread_mutex_lock(&(c->control.mutex)); while(!c->writer_done || !c->worker_done) { pthread_cond_wait(&(c->control.cond), &(c->control.mutex)); } pthread_mutex_unlock(&(c->control.mutex)); pthread_mutex_lock(&(connections.control.mutex)); list_del(&(connections.list), (node *)c); pthread_mutex_unlock(&(connections.control.mutex)); pthread_cond_broadcast(&(connections.control.cond)); close(c->fd); #ifndef NDEBUG print( DEBUG, "connection closed (fd=%d)", c->fd ); #endif // add me to the death list send_me_to_graveyard(); free_connection(c); return 0; }
void stream_on_close(uv_handle_t* handle) { uv_handle_t* stream = handle; connection* conn = stream->data; if (conn->state != CLOSED) { conn->state = CLOSED; connection* conn = (connection*)handle->data; free_connection(conn); } }
/* * Shut down database module * No function should be called after this */ void db_close(db_con_t* _h) { struct pool_con* con; if (!_h) { LOG(L_ERR, "db_close: Invalid parameter value\n"); return; } con = (struct pool_con*)_h->tail; if (pool_remove(con) != 0) { free_connection((struct my_con*)con); } pkg_free(_h); }
cql::cql_session_impl_t::cql_connections_collection_t::iterator cql::cql_session_impl_t::try_remove_connection( cql_connections_collection_t* const connections, const cql_uuid_t& connection_id) { // TODO: How we can guarantee that any other thread is not using // this connection object ? cql_connections_collection_t::iterator tmp, iter = connections->find(connection_id); tmp = iter; if (iter != connections->end()) { ++tmp; free_connection(iter->second); connections->erase(iter); } return tmp; }
void rtmp_core_init_connnect(rtmp_connection_t *conn) { rtmp_session_t *session; session = rtmp_session_create(conn); if (session == NULL) { rtmp_log(RTMP_LOG_ERR,"[%d]create session error!",conn->fd); free_connection(conn); return ; } conn->data = session; session->handshake->stage = RTMP_HANDSHAKE_SERVER_C0C1; rtmp_server_handshake(session); return; }
static int worker_cron (aeEventLoop * el, long long id, void *data) { workerState *ws = (workerState *) data; long long ts = currtime_millis (); int ret; if (ws->reconn_after != 0LL && ts > ws->reconn_after) { if (ws->fd >= 0) { free_connection (ws, 1); } else { char ebuf[512]; (void) command_start (ws, ebuf, sizeof (ebuf)); } } if (ws->tps > 0) { long long token_val; token_val = (ws->tps * SINGLE_TOKEN_VAL) / 1000 * WORKER_CRON_INTERVAL; ws->token_val += token_val; if (ws->token_val > ws->tps * SINGLE_TOKEN_VAL) { ws->token_val = ws->tps * SINGLE_TOKEN_VAL; } if (ws->wprepare_at_token && ws->token_val >= SINGLE_TOKEN_VAL) { ret = emit_command (ws); assert (ret == 0); ws->wprepare_at_token = 0; } } return WORKER_CRON_INTERVAL; }
void setup_outgoing_connection(outgoing_t *outgoing) { connection_t *c; node_t *n; outgoing->event = NULL; n = lookup_node(outgoing->name); if(n) if(n->connection) { ifdebug(CONNECTIONS) logger(LOG_INFO, "Already connected to %s", outgoing->name); n->connection->outgoing = outgoing; return; } c = new_connection(); c->name = xstrdup(outgoing->name); c->outcipher = myself->connection->outcipher; c->outdigest = myself->connection->outdigest; c->outmaclength = myself->connection->outmaclength; c->outcompression = myself->connection->outcompression; init_configuration(&c->config_tree); read_connection_config(c); outgoing->cfg = lookup_config(c->config_tree, "Address"); if(!outgoing->cfg) { logger(LOG_ERR, "No address specified for %s", c->name); free_connection(c); return; } c->outgoing = outgoing; c->last_ping_time = now; connection_add(c); do_outgoing_connection(c); }
static void handle_reading_data_from_event(connection_data *connection) { buffer *data = &connection->data; data->size = 0; while (true) { if (data->size == data->capacity) reallocate_buffer_exp(data); int n = read(connection->fd, data->bytes + data->size, data->capacity - data->size); if (n == -1) { assert(errno == EAGAIN); break; } else if(n == 0) { logger_.log("Error during reading. Connection was closed on %d", connection->fd); free_connection(connection); if (global_read_handler != NULL) global_read_handler(n, NULL); return; } else { assert(n > 0); data->size += n; } } if (global_read_handler != NULL) global_read_handler(data->size, connection); }
static int proc_slave_connect( int fd, rscntxt_t *cntxt) { Log("proc slave connect\n"); msgheader_t header; header.message_type = RES_CONNECT; header.device_type = DEVICE_SLAVE; header.token = 0; ++cntxt->curr_max_token; uint32 token = cntxt->curr_max_token; connection_t *conn = new_connection(); if (NULL == conn) { LogE("Failed new connection"); return -1; } conn->token = token; conn->conn_fd = fd; if (add_list_elem(cntxt->conn_list, conn) < 0) { LogE("Failed add conn to conn_list"); free_connection(conn); conn = NULL; return -1; } header.token = htonl(conn->token); if (send(fd, &header, sizeof(header),0) != sizeof(header)) { LogE("Failed send RES_CONNECT to client"); return -1; } printf("token:%d\n", conn->token); return 0; }
/** * Get RX paquet from a TLS client connection and send it to user * authentication threads: * - nuauthdatas->localid_auth_queue (see ::localid_auth()), if connection * state is #AUTH_STATE_HELLOMODE * - nuauthdatas->connections_queue (see search_and_fill()), otherwise * * \param c_session SSL RX packet * \return Returns 1 if read is done, EOF if read is completed */ static int treat_nufw_request(nufw_session_t * c_session) { unsigned char cdgram[CLASSIC_NUFW_PACKET_SIZE]; unsigned char *dgram = cdgram; int dgram_size; connection_t *current_conn; int ret, message_length, offset, i; if (c_session == NULL) return NU_EXIT_OK; /* read header from nufw */ dgram_size = nussl_read(c_session->nufw_client, (char *)dgram, sizeof(nufw_to_nuauth_message_header_t)); if (dgram_size < 0) { if (!strcmp("Resource temporarily unavailable", nussl_get_error(c_session->nufw_client))) { return NU_EXIT_OK; } else { log_message(INFO, DEBUG_AREA_GW, "nufw failure at %s:%d (%s)", __FILE__, __LINE__, nussl_get_error(c_session->nufw_client)); return NU_EXIT_ERROR; } return NU_EXIT_ERROR; } else if (dgram_size == 0) { log_message(INFO, DEBUG_AREA_GW, "nufw disconnect at %s:%d", __FILE__, __LINE__); return NU_EXIT_ERROR; } if (dgram_size < (int) sizeof(nufw_to_nuauth_message_header_t)) { log_message(INFO, DEBUG_AREA_GW, "nufw short read at %s:%d", __FILE__, __LINE__); /* can not recuperate from this state with current code */ declare_dead_nufw_session(c_session); return NU_EXIT_ERROR; } message_length = get_nufw_message_length_from_packet(dgram, dgram_size); if (message_length <= 0) { log_message(INFO, DEBUG_AREA_GW, "message length invalid at %s:%d", __FILE__, __LINE__); /* can not recuperate from this state with current code */ declare_dead_nufw_session(c_session); return NU_EXIT_ERROR; } /* read data */ offset = sizeof(nufw_to_nuauth_message_header_t); i = 0; do { debug_log_message(VERBOSE_DEBUG, DEBUG_AREA_GW, "nufw read pass %d", i); dgram_size = nussl_read(c_session->nufw_client, (char *) (dgram + offset), message_length - offset); if (dgram_size != message_length - offset) { if (dgram_size < 0) { log_message(INFO, DEBUG_AREA_GW, "nufw failure at %s:%d (%s)", __FILE__, __LINE__, nussl_get_error(c_session->nufw_client)); return NU_EXIT_ERROR; } else if (dgram_size == 0) { log_message(INFO, DEBUG_AREA_GW, "nufw disconnect at %s:%d", __FILE__, __LINE__); return NU_EXIT_ERROR; } else { log_message(INFO, DEBUG_AREA_GW, "(pass %d) nufw incomplete read (%d vs %d) at %s:%d", i, dgram_size, message_length - sizeof(nufw_to_nuauth_message_header_t), __FILE__, __LINE__); /* give one last chance ? */ offset += dgram_size; } } else { break; } i++; } while (i < 3); if (i == 3) { log_message(INFO, DEBUG_AREA_GW, "nufw read impossible at %s:%d", __FILE__, __LINE__); declare_dead_nufw_session(c_session); return NU_EXIT_ERROR; } /* Bad luck, this is first packet, we have to test nufw proto version */ if (c_session->proto_version == PROTO_UNKNOWN) { c_session->proto_version = get_proto_version_from_packet(dgram, (size_t) message_length); if (!c_session->proto_version) { declare_dead_nufw_session(c_session); return NU_EXIT_ERROR; } } dgram_size = message_length; /* decode data */ do { ret = authpckt_decode(&dgram, (unsigned int *) &dgram_size, ¤t_conn); switch (ret) { case NU_EXIT_ERROR: /* better to have a disconnect than going in space */ declare_dead_nufw_session(c_session); return NU_EXIT_ERROR; case NU_EXIT_OK: if (current_conn != NULL) { current_conn->socket = 0; /* session will be used by created element */ increase_nufw_session_usage(c_session); current_conn->tls = c_session; /* if we absolutely want to log we've got to have a working pool thread */ if (nuauthconf->drop_if_no_logging && (nuauthdatas->loggers_pool_full == TRUE)) { current_conn->decision = DECISION_DROP; current_conn->state = AUTH_STATE_DONE; apply_decision(current_conn); free_connection(current_conn); return NU_EXIT_ERROR; } /* gonna feed the birds */ if (current_conn->state == AUTH_STATE_HELLOMODE) { debug_log_message(DEBUG, DEBUG_AREA_GW, "(*) NuFW auth request (hello mode): packetid=%u", (uint32_t) GPOINTER_TO_UINT (current_conn-> packet_id-> data)); struct internal_message *message = g_new0(struct internal_message, 1); message->type = INSERT_MESSAGE; message->datas = current_conn; current_conn->state = AUTH_STATE_AUTHREQ; g_async_queue_push(nuauthdatas-> localid_auth_queue, message); } else { debug_log_message(DEBUG, DEBUG_AREA_GW, "(*) NuFW auth request (nufw mode): packetid=%u", (uint32_t) GPOINTER_TO_UINT (current_conn-> packet_id-> data)); g_async_queue_push(nuauthdatas-> connections_queue, current_conn); } }
void do_with_listen(struct worker_context *ctx, netresult_t result) { if ( NET_OP_NOTIFY == result._op_type ) { WARNING("listen fd[%d] error.", g_listen_fd); return ; } int err; int sock; int avg_conn; struct sockaddr_in addr; socklen_t addrlen; struct connection *conn; while (1) { avg_conn = atomic_read(&g_active_conn_num) / atomic_read(&g_worker_num); if ( ctx->_active_conn_num >= avg_conn + WORKER_CONN_NUM_DELTA ) { DEBUG("drop accept ignore unbalance, avg conn num[%d], worker[%d] active conn num[%d].", avg_conn, ctx->_wid, ctx->_active_conn_num); break; } addrlen = sizeof(addr); sock = accept(g_listen_fd, (struct sockaddr *)&addr, &addrlen); if ( sock < 0 ) { err = errno; if ( EINTR == err ) { continue; } else if ( EAGAIN == err ) { return ; } else if ( EMFILE == err || ENFILE == err ) { atomic_add(1, &g_conn_nofile_err_num); } else if ( ENOBUFS == err || ENOMEM == err ) { atomic_add(1, &g_conn_nomem_err_num); } else if ( ECONNABORTED == err ) { atomic_add(1, &g_conn_aborted_err_num); } else { atomic_add(1, &g_conn_other_err_num); } WARNING("accept ret error[%s] on fd[%d].", strerror_t(err), g_listen_fd); return ; } else if ( atomic_read(&g_active_conn_num) > g_conf._max_active_conn_num ) { atomic_add(1, &g_conn_denied_by_limit_num); SAFE_CLOSE(sock); WARNING("deny connection, too many active connections[> %d].", g_conf._max_active_conn_num); } else { atomic_add(1, &g_active_conn_num); conn = alloc_connection(ctx); if ( NULL != conn ) { conn->_client._fd = sock; if ( NULL == inet_ntop(AF_INET, &addr.sin_addr, conn->_client._ip_str, sizeof(conn->_client._ip_str)) ) { WARNING("inet_ntop error[%s], addr[%X].", strerror_t(errno), *(int *)&addr.sin_addr); conn->_client._ip_str[0] = '\0'; } if ( epex_attach(ctx->_epoll, sock, conn, g_conf._client_connection_timeout) ) { if ( epex_read_any(ctx->_epoll, sock, conn->_client._header, MAX_HTTP_HEADER_LEN, NULL, g_conf._client_read_timeout) ) { DEBUG("worker[%d] accept connection[%d][%p] ok.", ctx->_wid, sock, conn); ++ctx->_active_conn_num; continue; } else { WARNING("failed to submit read request."); epex_detach(ctx->_epoll, sock, NULL); free_connection(ctx, conn); SAFE_CLOSE(sock); } } else { WARNING("failed to attach sock[%d] to epoll.", sock); free_connection(ctx, conn); SAFE_CLOSE(sock); } } else { WARNING("failed to alloc connection."); } atomic_add(-1, &g_active_conn_num); } } }
int frame_sudo_message(DBusConnection* conn, DBusError *err, DBusMessage *dbus_msg, struct sss_sudo_msg_contents * sudo_msg, DBusMessageIter * msg_iter){ int ret = -1,count =0; DBusMessageIter sub_iter; char ** command_array; if(!dbus_message_iter_open_container(msg_iter, DBUS_TYPE_STRUCT, NULL, &sub_iter)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if (!dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_UINT32, &sudo_msg->userid)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if (!dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING, &sudo_msg->cwd)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if (!dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING, &sudo_msg->tty)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if (!dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING, &sudo_msg->fq_command)) { fprintf(stderr, "Out Of Memory! - at FQ command\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if (!dbus_message_iter_close_container(msg_iter,&sub_iter)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if (!dbus_message_iter_append_basic(msg_iter, DBUS_TYPE_UINT32, &sudo_msg->command_count)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if(!dbus_message_iter_open_container(msg_iter, DBUS_TYPE_ARRAY, "s", &sub_iter)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } for(command_array = sudo_msg->command ; *command_array != NULL ; command_array++) { if (!dbus_message_iter_append_basic(&sub_iter, DBUS_TYPE_STRING, command_array)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } } if (!dbus_message_iter_close_container(msg_iter,&sub_iter)) { fprintf(stderr, "Out Of Memory!\n"); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } //////// if(dbus_dhash_to_msg_iter(&sudo_msg->settings_table,msg_iter) != SSS_SBUS_CONV_SUCCESS){ fprintf(stderr,"fatal: message framing failed."); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } if(dbus_dhash_to_msg_iter(&sudo_msg->env_table,msg_iter) != SSS_SBUS_CONV_SUCCESS){ fprintf(stderr,"fatal: message framing failed."); free_connection(conn,&err,sudo_msg->settings_table,dbus_msg,(DBusMessage *)NULL); free_connection(NULL,NULL,sudo_msg->env_table,NULL,NULL); return SSS_SUDO_MESSAGE_ERR; } return SSS_SUDO_MESSAGE_OK; }
static void handle_closing(connection_data *connection) { logger_.log("Client associated with socket %d is gone...", connection->fd); free_connection(connection); }
int sss_sudo_make_request(struct sudo_result_contents ** sudo_result_out) { char ** command_array,**ui; int err_status,count; dbus_uint32_t header,command_array_out_size; struct sudo_result_contents * sudo_result = NULL; DBusConnection* conn; DBusError err; DBusMessage* dbus_msg; DBusMessage* dbus_reply; DBusMessageIter msg_iter; dbus_bool_t ret = -1; fprintf(stdout,"Sending message\n"); if(validate_message_content() != SSS_SUDO_VALIDATION_SUCCESS) { return SSS_SUDO_VALIDATION_ERR; } err_status = create_env_hash_table(msg.user_env,&msg.env_table); if(err_status != HASH_SUCCESS) { fprintf(stderr, "ccouldn't create table: %s\n", hash_error_string(err_status)); return SSS_SUDO_MESSAGE_ERR; } err_status = create_settings_hash_table(&msg.settings_table); if(err_status != HASH_SUCCESS) { fprintf(stderr, "ccouldn't create table: %s\n", hash_error_string(err_status)); return SSS_SUDO_MESSAGE_ERR; } /* initialise the errors */ dbus_error_init(&err); /* connect to the system bus and check for errors */ conn = dbus_connection_open_private(SSS_SUDO_SERVICE_PIPE, &err); if (dbus_error_is_set(&err)) { fprintf(stderr, "Connection Error (%s)\n", err.message); dbus_error_free(&err); return SSS_SUDO_CONNECTION_ERR; } if (NULL == conn) { return SSS_SUDO_CONNECTION_ERR; } /* create a new method call and check for errors */ dbus_msg = dbus_message_new_method_call( NULL, /* target */ SUDO_SERVER_PATH, /* object */ SUDO_SERVER_INTERFACE, /* interface */ SUDO_METHOD_QUERY); /* method name */ if (NULL == dbus_msg) { fprintf(stderr, "Message Null\n"); free_connection(conn,&err,msg.settings_table,(DBusMessage *)NULL,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } /* append arguments */ dbus_message_iter_init_append(dbus_msg, &msg_iter); if(dbus_error_is_set(&err)){ fprintf(stderr, "Failed to initialize the iterator.\n"); free_connection(conn,&err,msg.settings_table,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } ret = frame_sudo_message(conn, &err, dbus_msg, &msg, &msg_iter); if( ret != SSS_SUDO_MESSAGE_OK){ sudo_log(SUDO_CONV_ERROR_MSG,"Failed to frame the message to sssd - Fatal (Access denied)\n"); free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_MESSAGE_ERR; } /* send message and get a handle for a reply */ dbus_reply = dbus_connection_send_with_reply_and_block (conn,dbus_msg, SUDO_CLIENT_TIMEOUT, &err); fprintf(stdout,"Request Sent\n"); if (dbus_error_is_set(&err)) { fprintf(stderr, "Connection send-reply Error (%s)\n", err.message); free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_REPLY_ERR; } if (NULL == dbus_reply) { fprintf(stderr, "reply failed\n"); free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,(DBusMessage *)NULL); return SSS_SUDO_REPLY_ERR; } sudo_result= (struct sudo_result_contents *)malloc(sizeof(struct sudo_result_contents)); ret = get_reply_message(conn, &err, dbus_msg, dbus_reply, sudo_result, &msg_iter); if(ret != SSS_SUDO_REPLY_OK){ } /* free connection now */ free_connection(conn,&err,(hash_table_t *)NULL,dbus_msg,dbus_reply); *sudo_result_out = sudo_result; return SSS_SUDO_SEND_AND_RECIEVE_OK; }
int main(int argc, char **argv) { int ret; int c, option_index = 0; /* select variables */ fd_set read_fds; int nfds = 0; /* mqtt variables */ char topic[MAX_TOPIC_LEN] = MQTT_DEFAULT_TOPIC; char broker_ip[16] = MQTT_BROKER_IP; int broker_port = MQTT_BROKER_PORT; char clientid[UMQTT_CLIENTID_MAX_LEN] = "\0"; uint8_t retain = 0; char msg[MAX_MSG_LEN] = "\0"; size_t len = MAX_MSG_LEN; struct broker_conn *conn; struct mqtt_packet *pkt = NULL; /* reading variables */ struct reading *r = NULL; ret = reading_init(&r); if (ret) { return -1; } /* set reading date to now */ time_t t = time(0); /* Reading sensor id remaps */ struct sensor_remaps rmaps; rmaps.count = 0; char *rmap_buf[64]; /* tty variables */ char buf[RX_BUF_LEN]; size_t buf_len = RX_BUF_LEN; device_type_t type = RAW_DEV; struct tty_conn *tty; ret = tty_conn_init(&tty); if (ret) { free_reading(r); return -1; } /* set TTY defaults */ strcpy(tty->path, DEFAULT_TTY_DEV); tty->baud = DEFAULT_TTY_BAUD; static struct option long_options[] = { /* These options set a flag. */ {"help", no_argument, 0, 'h'}, {"verbose", required_argument, 0, 'v'}, {"type", required_argument, 0, 'T'}, {"device_id", required_argument, 0, 'd'}, {"sensor_id", required_argument, 0, 's'}, {"json", no_argument, 0, 'j'}, {"ini", no_argument, 0, 'i'}, {"remap", required_argument, 0, 'R'}, {"retain", no_argument, 0, 'r'}, {"tty-dev", required_argument, 0, 'D'}, {"baud", required_argument, 0, 'B'}, {"topic", required_argument, 0, 't'}, {"broker", required_argument, 0, 'b'}, {"port", required_argument, 0, 'p'}, {"clientid", required_argument, 0, 'c'}, {0, 0, 0, 0} }; /* get arguments */ while (1) { if ((c = getopt_long(argc, argv, "hv:s:d:T:D:B:jirt:b:p:c:R:", long_options, &option_index)) != -1) { switch (c) { case 'h': return print_usage(); case 'v': /* set log level */ if (optarg) { set_log_level_str(optarg); } break; case 'r': /* set retain flag */ retain = 1; break; case 't': /* Set topic */ if (optarg) { strcpy(topic, optarg); } else { log_stderr(LOG_ERROR, "The topic flag should be followed by a topic"); return print_usage(); } break; case 'T': /* Set the device type */ if (optarg) { if (strstr(optarg, CC_DEVICE_STR)) { type = CURRENT_COST_DEV; } else if (strstr(optarg, FLOW_DEVICE_STR)) { type = FLOW_DEV; } else { /* default */ type = RAW_DEV; } } else { log_stderr(LOG_ERROR, "The device type flag should be followed by a device type"); return print_usage(); } break; case 'R': /* Remap a devices sensor id with another sensor id */ if (optarg) { strcpy((char *)rmap_buf, optarg); rmaps.id[rmaps.count] = atoi((char *)rmap_buf); rmaps.rmap_id[rmaps.count] = atoi(strchr((char *)rmap_buf, ':') + 1); log_stdout(LOG_INFO, "Remapping sensor ID: %d to %d", rmaps.id[rmaps.count], rmaps.rmap_id[rmaps.count]); rmaps.count++; } else { log_stderr(LOG_ERROR, "The remap flag should be followed by two sensor IDs"); return print_usage(); } break; case 'D': /* Set the TTY device file */ if (optarg) { strcpy(tty->path, optarg); } else { log_stderr(LOG_ERROR, "The device flag should be followed by a tty device"); return print_usage(); } break; case 'B': /* Set the device file */ if (optarg) { tty->baud = atoi(optarg); } else { log_stderr(LOG_ERROR, "The baud rate flag should be followed by a baud rate"); return print_usage(); } break; case 'd': /* Set a device_id */ if (optarg) { r->device_id = atoi(optarg); } else { log_stderr(LOG_ERROR, "The device_id flag should be followed by a device_id"); return print_usage(); } break; case 's': /* Set a sensor_id */ if (optarg && r->count) { r->meas[r->count - 1]->sensor_id = atoi(optarg); } else { log_stderr(LOG_ERROR, "The sensor_id flag should follow a measurement flag, and" " should be followed by a sensor_id"); return print_usage(); } break; case 'b': /* Change the default broker ip */ if (optarg) { strcpy(broker_ip, optarg); } else { log_stderr(LOG_ERROR, "The broker flag should be followed by an IP address"); return print_usage(); } break; case 'p': /* change the default port */ if (optarg) { broker_port = *optarg; } else { log_stderr(LOG_ERROR, "The port flag should be followed by a port"); return print_usage(); } break; case 'c': /* Set clientid */ if (optarg) { strcpy(clientid, optarg); } else { log_stderr(LOG_ERROR, "The clientid flag should be followed by a clientid"); return print_usage(); } break; } } else { /* Final arguement */ break; } } /* init connections */ log_stdout(LOG_INFO, "Initialising broker socket connection"); init_linux_socket_connection(&conn, broker_ip, sizeof(broker_ip), broker_port); if (!conn) { log_stdout(LOG_ERROR, "Initialising socket connection"); return -1; } if (clientid[0]) { broker_set_clientid(conn, clientid, sizeof(clientid)); } log_stdout(LOG_INFO, "Connecting to broker"); struct linux_broker_socket *skt = '\0'; if ((ret = broker_connect(conn))) { log_stderr(LOG_ERROR, "Connecting to broker"); free_connection(conn); return ret; } else { skt = (struct linux_broker_socket *)conn->context; log_stdout(LOG_INFO, "Connected to broker:\nip: %s port: %d", skt->ip, skt->port); } /* test tty config */ log_stdout(LOG_INFO, "TTY device: %s, baud: %d", tty->path, tty->baud); if (tty_conn_check_config(tty)) { log_stdout(LOG_ERROR, "Testing TTY device config"); return -1; } /* Open tty device */ ret = tty_conn_open(tty); if (ret) { log_stderr(LOG_ERROR, "Opening TTY device"); free_connection(conn); free_tty_conn(tty); return ret; } /* wait for data - main program loop */ while (1) { /* select init */ FD_ZERO(&read_fds); nfds = ((tty->fd > skt->sockfd) ? tty->fd : skt->sockfd) + 1; FD_SET(tty->fd, &read_fds); FD_SET(skt->sockfd, &read_fds); ret = select(nfds, &read_fds, NULL, NULL, NULL); if (ret == -1) { if (errno == EINTR) { log_stderr(LOG_ERROR, "Select: %s: %s", tty->path, strerror(errno)); continue; } log_stderr(LOG_ERROR, "Select failed: %s: %s", tty->path, strerror(errno)); continue; } else if (!ret) { /* should never get here since disabled timeout */ log_stdout(LOG_DEBUG, "select timed out"); } /* Determine if any fds are ready */ if (FD_ISSET(tty->fd, &read_fds)) { /* packet border */ log_stdout(LOG_INFO, "------------------------------------------------------------"); /* set reading time to now */ t = time(0); localtime_r(&t, &r->t); buf_len = RX_BUF_LEN; ret = tty_conn_read(tty, (char *)&buf, &buf_len); if (ret && ret != SS_CONTINUE) { log_stderr(LOG_ERROR, "Read: %d:%s", errno, strerror(errno)); break; } else if (ret == SS_CONTINUE) { continue; } else if (buf_len) { /* process tty data */ log_stdout(LOG_INFO, "Processing received data"); if (CURRENT_COST_DEV == type) { ret = process_cc_buffer(buf, &buf_len); if (ret == SS_CONTINUE) { log_stdout(LOG_INFO, "No data available"); continue; } /* process reading */ free_measurements(r); ret = convert_cc_dev_reading(r, buf, buf_len); if (ret) { log_stderr(LOG_ERROR, "failed to decode output"); continue; } remap_reading_sensor_ids(r, &rmaps); log_stdout(LOG_INFO, "Received new reading:"); print_reading(r); } else if (FLOW_DEV == type) { /* not currently supported */ } else if (RAW_DEV == type) { /* Simply copy buffer to message payload */ memcpy((void *)msg, (void *)buf, (buf_len < len ? buf_len : len)); log_stdout(LOG_INFO, "RAW payload ready"); } if (type != RAW_DEV) { /* process message */ log_stdout(LOG_INFO, "Processing reading"); ret = convert_reading_json(r, msg, &len); if (ret) { log_stderr(LOG_ERROR, "failed to encode reading into JSON"); continue; } } } else if (FD_ISSET(skt->sockfd, &read_fds)) { /* process MQTT input */ /* need to test this to ensure packets are processed upon recipt */ ret = read_socket_packet(conn, pkt); if (ret) { log_stderr(LOG_ERROR, "failed to process packet input"); continue; } } /* Process output MQTT packet is fall through case */ /* Create publish packet on new data */ pkt = construct_packet_headers(PUBLISH); if (!pkt || (ret = set_publish_variable_header(pkt, topic, strlen(topic)))) { log_stderr(LOG_ERROR, "Setting up packet"); ret = UMQTT_ERROR; goto free; } ret = set_publish_fixed_flags(pkt, retain, 0, 0); if (ret) { log_stderr(LOG_ERROR, "Setting publish flags"); ret = UMQTT_ERROR; goto free; } ret = init_packet_payload(pkt, PUBLISH, (uint8_t *)msg, strlen(msg)); if (ret) { log_stderr(LOG_ERROR, "Attaching payload"); ret = UMQTT_ERROR; goto free; } finalise_packet(pkt); log_stdout(LOG_INFO, "Constructed MQTT PUBLISH packet:"); log_stdout(LOG_INFO, "Topic: %s", topic); log_stdout(LOG_INFO, "Message: %s", msg); /* Send packet */ ret = broker_send_packet(conn, pkt); if (ret) { log_stderr(LOG_ERROR, "Sending packet failed"); } else { log_stdout(LOG_INFO, "Successfully sent packet to broker"); } free_packet(pkt); buf_len = RX_BUF_LEN; } } free: log_stdout(LOG_INFO, "Disconnecting from broker"); broker_disconnect(conn); free_reading(r); close_tty_conn(tty); free_tty_conn(tty); free_connection(conn); free_packet(pkt); return ret; }
nu_error_t parse_dgram(connection_t * connection, unsigned char *dgram, unsigned int dgram_size, connection_t ** conn, nufw_message_t msg_type) { unsigned char *orig_dgram = dgram; unsigned int ip_hdr_size; struct iphdr *ip = (struct iphdr *) dgram; /* get ip headers till tracking is filled */ ip_hdr_size = get_ip_headers(&connection->tracking, dgram, dgram_size); if (ip_hdr_size == 0) { log_message(WARNING, DEBUG_AREA_PACKET | DEBUG_AREA_GW, "Can't parse IP headers"); free_connection(connection); return NU_EXIT_ERROR; } dgram += ip_hdr_size; dgram_size -= ip_hdr_size; /* get saddr and daddr */ /* check if proto is in Hello mode list (when hello authentication is used) */ if (nuauthconf->hello_authentication && localid_authenticated_protocol(connection)) { connection->state = AUTH_STATE_HELLOMODE; connection->auth_quality = AUTHQ_HELLO; *conn = connection; } else { connection->state = AUTH_STATE_AUTHREQ; } switch (connection->tracking.protocol) { case IPPROTO_TCP: { tcp_state_t tcp_state = get_tcp_headers(&connection->tracking, dgram, dgram_size); switch (tcp_state) { case TCP_STATE_OPEN: break; case TCP_STATE_CLOSE: if (msg_type == AUTH_CONTROL) { connection->state = AUTH_STATE_DONE; log_message(WARNING, DEBUG_AREA_GW, "nufw sends non SYN TCP packet, ignoring"); free_connection(connection); return NU_EXIT_NO_RETURN; } break; case TCP_STATE_ESTABLISHED: if (msg_type == AUTH_CONTROL) { connection->state = AUTH_STATE_DONE; log_message(WARNING, DEBUG_AREA_GW, "nufw sends SYN ACK TCP packet, ignoring"); free_connection(connection); return NU_EXIT_NO_RETURN; } break; default: log_message(WARNING, DEBUG_AREA_PACKET | DEBUG_AREA_GW, "Non-SYN TCP headers, we should not have received this packet"); connection->state = AUTH_STATE_DONE; free_connection(connection); return NU_EXIT_NO_RETURN; } break; } break; case IPPROTO_UDP: if (get_udp_headers (&connection->tracking, dgram, dgram_size) < 0) { free_connection(connection); return NU_EXIT_OK; } break; case IPPROTO_ICMP: if (get_icmp_headers (&connection->tracking, dgram, dgram_size) < 0) { free_connection(connection); return NU_EXIT_OK; } break; case IPPROTO_ICMPV6: if (get_icmpv6_headers (&connection->tracking, dgram, dgram_size) < 0) { free_connection(connection); return NU_EXIT_OK; } break; default: if (connection->state != AUTH_STATE_HELLOMODE) { log_message(WARNING, DEBUG_AREA_PACKET | DEBUG_AREA_GW, "Can't parse protocol %u", connection->tracking.protocol); free_connection(connection); return NU_EXIT_ERROR; } } if (ntohs(ip->tot_len) > STORED_PAYLOAD_SIZE) connection->payload_len = STORED_PAYLOAD_SIZE; else connection->payload_len = ntohs(ip->tot_len); memcpy(connection->payload, orig_dgram, connection->payload_len); return NU_EXIT_CONTINUE; }
int main(int argc, char *argv[]) { int lsfd; int ret, n, i; struct epoll_event event; struct epoll_event *events = NULL; connection_t *conn; connections_head_t *head = NULL; if (argc != 2) { fprintf(stdout, "Usage: %s [port]\n", argv[0]); exit(EXIT_FAILURE); } /* init connections cache */ head = init_connections(MAX_CONNECTIONS); if (NULL == head) { ERROR_MSG("init_connections\n"); goto error; } /* init SSL data */ ret = init_OpenSSL(); if (ret != 0) { ERROR_MSG("init_OpenSSL\n"); goto error; } head->ctx = init_ssl_ctx(SRV_CERTFILE, SRV_PRIKEY, SRV_CAFILE); if (NULL == head->ctx) { ERROR_MSG("init_ssl_ctx error\n"); goto error; } /* init epoll's data */ head->epfd = epoll_create(MAX_CONNECTIONS); if (-1 == head->epfd) { ERROR_MSG("epoll_create\n"); goto error; } events = calloc(MAX_EVENTS, sizeof(struct epoll_event)); if (NULL == events) { ERROR_MSG("calloc\n"); goto error; } /* listen's data */ lsfd = start_listen(argv[1]); if (lsfd < 0) { ERROR_MSG("start_listen\n"); goto error; } /* add the lsfd to events */ conn = get_connection(head); if (NULL == conn) { ERROR_MSG("get_connection\n"); goto error; } conn->fd = lsfd; conn->handler = accept_handler; event.data.ptr = conn; event.events = EPOLLIN | EPOLLET; ret = epoll_ctl(head->epfd, EPOLL_CTL_ADD, lsfd, &event); if (-1 == ret) { ERROR_MSG("epoll_ctl\n"); goto error; } /* The event loop */ while (1) { n = epoll_wait(head->epfd, events, MAX_EVENTS, -1); for (i = 0; i < n; ++i) { conn = events[i].data.ptr; if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP) || !(events[i].events & EPOLLIN)) { /* it will delete the event from events at the same time * due to invoked close */ free_connection(head, conn); } else { if (conn->handler) { conn->handler(head, conn); } } } } error: if (events) free(events); destroy_connections(head); return EXIT_SUCCESS; }