void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason) { struct event_data post; int need_notify = 0; /* is user already being disconnected ? */ if (user_is_disconnecting(user)) { return; } /* stop reading from user */ net_shutdown_r(net_con_get_sd(user->connection)); net_con_close(user->connection); user->connection = 0; LOG_TRACE("hub_disconnect_user(), user=%p, reason=%d, state=%d", user, reason, user->state); need_notify = user_is_logged_in(user) && hub->status == hub_status_running; user->quit_reason = reason; user_set_state(user, state_cleanup); if (need_notify) { memset(&post, 0, sizeof(post)); post.id = UHUB_EVENT_USER_QUIT; post.ptr = user; event_queue_post(hub->queue, &post); } else { hub_schedule_destroy_user(hub, user); } }
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr) { struct hub_user* user = NULL; LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con)); user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user)); if (user == NULL) return NULL; /* OOM */ user->send_queue = ioq_send_create(); user->recv_queue = ioq_recv_create(); user->connection = con; net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ); memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap)); user_set_state(user, state_protocol); flood_control_reset(&user->flood_chat); flood_control_reset(&user->flood_connect); flood_control_reset(&user->flood_search); flood_control_reset(&user->flood_update); flood_control_reset(&user->flood_extras); user->hub = hub; return user; }
void ADC_client_disconnect(struct ADC_client* client) { ADC_TRACE; if (client->con && net_con_get_sd(client->con) != -1) { net_con_close(client->con); client->con = 0; } }
/* * This will generate the same challenge to the same user, always. * The challenge is made up of the time of the user connected * seconds since the unix epoch (modulus 1 million) * and the SID of the user (0-1 million). */ const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user) { char buf[64]; uint64_t tiger_res[3]; static char tiger_buf[MAX_CID_LEN+1]; // FIXME: Generate a better nonce scheme. snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection)); tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res); base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf); tiger_buf[MAX_CID_LEN] = 0; return (const char*) tiger_buf; }
void net_on_accept(struct net_connection* con, int event, void *arg) { struct hub_info* hub = (struct hub_info*) arg; struct hub_probe* probe = 0; struct ip_addr_encap ipaddr; int server_fd = net_con_get_sd(con); #ifdef PLUGIN_SUPPORT plugin_st status; #endif for (;;) { int fd = net_accept(server_fd, &ipaddr); if (fd == -1) { if (net_error() == EWOULDBLOCK) { break; } else { LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error())); break; } } #ifdef PLUGIN_SUPPORT status = plugin_check_ip_early(hub, &ipaddr); if (status == st_deny) { plugin_log_connection_denied(hub, &ipaddr); net_close(fd); continue; } plugin_log_connection_accepted(hub, &ipaddr); #endif probe = probe_create(hub, fd, &ipaddr); if (!probe) { LOG_ERROR("Unable to create probe after socket accepted. Out of memory?"); net_close(fd); break; } } }
/** * Check if a connection job is completed. * @return -1 on completed with an error, 0 on not yet completed, or 1 if completed successfully (connected). */ static int net_connect_job_check(struct net_connect_job* job) { struct net_connection* con = job->con; int af = job->addr.ss_family; enum net_connect_status status; int ret = net_connect(net_con_get_sd(con), (struct sockaddr*) &job->addr, af == AF_INET ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6)); if (ret == 0 || (ret == -1 && net_error() == EISCONN)) { LOG_TRACE("net_connect_job_check(): Socket connected!"); job->con = NULL; net_con_clear_timeout(con); net_connect_callback(job->handle, net_connect_status_ok, con); return 1; } else if (ret == -1 && (net_error() == EALREADY || net_error() == EINPROGRESS || net_error() == EWOULDBLOCK || net_error() == EINTR)) { return 0; } LOG_TRACE("net_connect_job_check(): Socket error!"); switch (net_error()) { case ECONNREFUSED: status = net_connect_status_refused; break; case ENETUNREACH: status = net_connect_status_unreachable; break; default: status = net_connect_status_socket_error; } net_connect_callback(job->handle, status, NULL); return -1; }