static void client_vanished_cb (GDBusConnection *connection, const gchar *name, gpointer user_data) { SensorData *data = user_data; guint i; char *sender; if (name == NULL) return; sender = g_strdup (name); for (i = 0; i < NUM_SENSOR_TYPES; i++) { GHashTable *ht; guint watch_id; ht = data->clients[i]; g_assert (ht); watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender)); if (watch_id > 0) client_release (data, sender, i); } g_free (sender); }
static void handle_method_call (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data) { SensorData *data = user_data; DriverType driver_type; GHashTable *ht; guint watch_id; if (g_strcmp0 (method_name, "ClaimAccelerometer") == 0 || g_strcmp0 (method_name, "ReleaseAccelerometer") == 0) driver_type = DRIVER_TYPE_ACCEL; else if (g_strcmp0 (method_name, "ClaimLight") == 0 || g_strcmp0 (method_name, "ClaimAccelerometer") == 0) driver_type = DRIVER_TYPE_LIGHT; else { g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method '%s' does not exist", method_name); return; } ht = data->clients[driver_type]; if (g_str_has_prefix (method_name, "Claim")) { watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender)); if (watch_id > 0) { g_dbus_method_invocation_return_value (invocation, NULL); return; } /* No other clients for this sensor? Start it */ if (driver_type_exists (data, driver_type) && g_hash_table_size (ht) == 0) driver_set_polling (DRIVER_FOR_TYPE(driver_type), TRUE); watch_id = g_bus_watch_name_on_connection (data->connection, sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, client_vanished_cb, data, NULL); g_hash_table_insert (ht, g_strdup (sender), GUINT_TO_POINTER (watch_id)); g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_str_has_prefix (method_name, "Release")) { client_release (data, sender, driver_type); g_dbus_method_invocation_return_value (invocation, NULL); } }
/** * Destroy session. * @param[in] sess */ void session_destroy(struct zsession *sess) { // update counters __atomic_sub_fetch(&zinst()->sessions_cnt, 1, __ATOMIC_RELAXED); if (0 == sess->client->id) { __atomic_sub_fetch(&zinst()->unauth_sessions_cnt, 1, __ATOMIC_RELAXED); } pthread_rwlock_destroy(&sess->lock_client); client_session_remove(sess->client, sess); client_release(sess->client); if(sess->nat) znat_destroy(sess->nat); free(sess); }
static void handle_generic_method_call (SensorData *data, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, DriverType driver_type) { GHashTable *ht; guint watch_id; g_debug ("Handling driver refcounting method '%s' for %s device", method_name, driver_type_to_str (driver_type)); ht = data->clients[driver_type]; if (g_str_has_prefix (method_name, "Claim")) { watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender)); if (watch_id > 0) { g_dbus_method_invocation_return_value (invocation, NULL); return; } /* No other clients for this sensor? Start it */ if (driver_type_exists (data, driver_type) && g_hash_table_size (ht) == 0) driver_set_polling (DRIVER_FOR_TYPE(driver_type), TRUE); watch_id = g_bus_watch_name_on_connection (data->connection, sender, G_BUS_NAME_WATCHER_FLAGS_NONE, NULL, client_vanished_cb, data, NULL); g_hash_table_insert (ht, g_strdup (sender), GUINT_TO_POINTER (watch_id)); g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_str_has_prefix (method_name, "Release")) { client_release (data, sender, driver_type); g_dbus_method_invocation_return_value (invocation, NULL); } }
void CClientMgr::ReleaseClientAndID(CClient *cl) { if (!cl) return; int32 id = cl->GetClientID(); if (id <= 0 || id >= (int32)m_ClientSet.size()) { log_error("要释放的Client的ID错误!"); return; } m_ClientSet[id] = NULL; if (!idmgr_freeid(m_IDPool, id)) { log_error("释放ID错误, ID:%d", id); } cl->SetClientID(0); client_release(cl); }
/** * Authenticate and set client info. * @param[in] sess Client session. * @return Zero on success (or one of *_RC). */ static int session_authenticate(struct zsession *sess) { int ret = OTHER_RC; VALUE_PAIR *request_attrs = NULL, *response_attrs = NULL, *attrs = NULL; char msg[8192]; // WARNING: libfreeradius-client has unsafe working with this buffer. rc_handle *rh = zinst()->radh; struct in_addr ip_addr; char ip_str[INET_ADDRSTRLEN]; struct zcrules rules; crules_init(&rules); ip_addr.s_addr = htonl(sess->ip); if (unlikely(NULL == inet_ntop(AF_INET, &ip_addr, ip_str, sizeof(ip_str)))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_USER_NAME, ip_str, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_USER_PASSWORD, "", -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_NAS_IDENTIFIER, zcfg()->radius_nas_identifier, -1, 0))) { goto end; } if (unlikely(NULL == rc_avpair_add(rh, &request_attrs, PW_CALLING_STATION_ID, ip_str, -1, 0))) { goto end; } ret = rc_auth(rh, 0, request_attrs, &response_attrs, msg); if (OK_RC != ret) { ZERO_LOG(LOG_ERR, "Session authentication failed for %s (code:%d)", ip_str, ret); goto end; } attrs = response_attrs; while (likely(NULL != attrs)) { switch (attrs->attribute) { case PW_FILTER_ID: crules_parse(&rules, attrs->strvalue); break; case PW_SESSION_TIMEOUT: atomic_store_explicit(&sess->max_duration, SEC2USEC(attrs->lvalue), memory_order_release); break; case PW_ACCT_INTERIM_INTERVAL: atomic_store_explicit(&sess->acct_interval, SEC2USEC(attrs->lvalue), memory_order_release); break; } attrs = attrs->next; } if (likely(rules.have.user_id && rules.have.login)) { struct zclient *client = sess->client; client_db_find_or_set_id(zinst()->client_db, rules.user_id, &client); if (client != sess->client) { // found pthread_rwlock_wrlock(&sess->lock_client); atomic_fetch_add_explicit(&client->refcnt, 1, memory_order_relaxed); client_release(sess->client); sess->client = client; client_session_add(sess->client, sess); pthread_rwlock_unlock(&sess->lock_client); } else { client_apply_rules(sess->client, &rules); } atomic_fetch_sub_explicit(&zinst()->unauth_sessions_cnt, 1, memory_order_release); // log successful authentication { UT_string rules_str; utstring_init(&rules_str); utstring_reserve(&rules_str, 1024); attrs = response_attrs; while (likely(NULL != attrs)) { switch (attrs->attribute) { case PW_FILTER_ID: utstring_printf(&rules_str, " %s", attrs->strvalue); break; default: break; } attrs = attrs->next; } zero_syslog(LOG_INFO, "Authenticated session %s (rules:%s)", ip_str, utstring_body(&rules_str)); utstring_done(&rules_str); } } else { ret = OTHER_RC; ZERO_LOG(LOG_ERR, "Session authentication failed for %s (code:%d)", ip_str, ret); } end: crules_free(&rules); if (request_attrs) rc_avpair_free(request_attrs); if (response_attrs) rc_avpair_free(response_attrs); return ret; }
TEST_F(UnresponsiveClient, does_not_hang_server) { mt::CrossProcessAction server_send_events; mt::CrossProcessAction client_connect; mt::CrossProcessAction client_release; mt::CrossProcessAction server_finish; SessionListener sessions; init_server([&] { server.override_the_session_listener([&] { return mt::fake_shared(sessions); }); }); run_in_server([&] { mt::AutoJoinThread t{ [&] { server_send_events.exec([&] { for (int i = 0; i < 1000; ++i) { sessions.for_each( [i] (std::shared_ptr<ms::Session> const& session) { session->default_surface()->resize({i + 1, i + 1}); }); } }); }}; server_finish.exec([]{}); }); auto const client_code = [&] { MirConnection* connection = nullptr; MirSurface* surface = nullptr; client_connect.exec([&] { connection = mir_connect_sync(mir_test_socket, __PRETTY_FUNCTION__); surface = mtf::make_any_surface(connection); }); client_release.exec([&] { // We would normally explicitly release the surface at this // point. However, because we have been filling the server // send socket buffer, releasing the surface may cause the // server to try to write to a full socket buffer when // responding, leading the server to believe that the client // is blocked, and causing a premature client disconnection. mir_connection_release(connection); }); }; auto client_process = new_client_process(client_code); if (is_test_process()) { client_connect(); kill(client_pid(), SIGSTOP); try { server_send_events(std::chrono::seconds{10}); } catch(...) { ADD_FAILURE() << "Server blocked while sending events"; } kill(client_pid(), SIGCONT); client_release(); server_finish(); auto const result = client_process->wait_for_termination(); EXPECT_THAT(result.exit_code, testing::Eq(EXIT_SUCCESS)); } }