浅析dbus server接收一个client连接大体流程
当一个client向dbus server发送连接之后,dbus server端socket_handle_watch()回调函数被执行,处理此次client发出的主动连接.(对于 socket_handle_watch()分析见 《浅析dbus系统watch函数是如何注册登记的》)
socket_handle_watch
static dbus_bool_t
socket_handle_watch (DBusWatch *watch,
unsigned int flags,
void *data)
{
......
int client_fd;
int listen_fd;
listen_fd = dbus_watch_get_socket (watch); // 该watch对应的fd句柄
client_fd = _dbus_accept (listen_fd); // 接受client的连接,生成client对应句柄[luther.gliethttp]
handle_new_client_fd_and_unlock (server, client_fd); //
......
}
==>handle_new_client_fd_and_unlock (server, client_fd);
==*>_dbus_transport_new_for_socket (client_fd, &server->guid_hex, NULL);
==**>_dbus_transport_init_base (&socket_transport->base, &socket_vtable, server_guid, address)
==***>_dbus_auth_server_new (server_guid) 或者 _dbus_auth_client_new ()
DBusAuth*
_dbus_auth_server_new (const DBusString *guid)
{
DBusAuth *auth;
DBusAuthServer *server_auth;
DBusString guid_copy;
if (!_dbus_string_init (&guid_copy))
return NULL;
if (!_dbus_string_copy (guid, 0, &guid_copy, 0))
{
_dbus_string_free (&guid_copy);
return NULL;
}
auth = _dbus_auth_new (sizeof (DBusAuthServer));
if (auth == NULL)
{
_dbus_string_free (&guid_copy);
return NULL;
}
auth->side = auth_side_server;
auth->state = &server_state_waiting_for_auth; // 等待auth认证
server_auth = DBUS_AUTH_SERVER (auth);
server_auth->guid = guid_copy;
/* perhaps this should be per-mechanism with a lower
* max
*/
server_auth->failures = 0;
server_auth->max_failures = 6;
return auth;
}
DBusAuth*
_dbus_auth_client_new (void)
{
DBusAuth *auth;
DBusString guid_str;
if (!_dbus_string_init (&guid_str))
return NULL;
auth = _dbus_auth_new (sizeof (DBusAuthClient));
if (auth == NULL)
{
_dbus_string_free (&guid_str);
return NULL;
}
DBUS_AUTH_CLIENT (auth)->guid_from_server = guid_str;
auth->side = auth_side_client;
auth->state = &client_state_need_send_auth; // 标识client需要认证
/* Start the auth conversation by sending AUTH for our default
* mechanism */
if (!send_auth (auth, &all_mechanisms[0]))
// 发送认证命令,默认就是将aut->outgoing头部变为:auth->outgoing = "AUTH EXTERNAL 31303030\r\n"
{
_dbus_auth_unref (auth);
return NULL;
}
return auth;
}
static dbus_bool_t
send_auth (DBusAuth *auth, const DBusAuthMechanismHandler *mech)
{
DBusString auth_command;
if (!_dbus_string_init (&auth_command))
return FALSE;
if (!_dbus_string_append (&auth_command,
"AUTH "))
{
_dbus_string_free (&auth_command);
return FALSE;
}
if (!_dbus_string_append (&auth_command,
mech->mechanism))
{
_dbus_string_free (&auth_command);
return FALSE;
}
if (mech->client_initial_response_func != NULL)
{
if (!_dbus_string_append (&auth_command, " "))
{
_dbus_string_free (&auth_command);
return FALSE;
}
// 最终将调用handle_client_initial_response_external_mech(auth, "AUTH EXTERNAL ");
// handle_client_initial_response_external_mech()函数将geteuid()获得的EUID整数值
// 转为ascii型hex十六进制值,追加到response字符串结尾[luther.gliethttp]
// 所以最后auth_command中字符串内容为(假设我们获得的EUID为"1000",即'1' '0' '0' '0'
// ,即49 48 48 48,即0x31 30 30 30):
// auth_command = "AUTH EXTERNAL 31303030"
if (!(* mech->client_initial_response_func) (auth, &auth_command))
{
_dbus_string_free (&auth_command);
return FALSE;
}
}
if (!_dbus_string_append (&auth_command,
"\r\n"))
{
_dbus_string_free (&auth_command);
return FALSE;
}
if (!_dbus_string_copy (&auth_command, 0,
&auth->outgoing,
// 这样auth->outgoing = "AUTH EXTERNAL 31303030\r\n"
_dbus_string_get_length (&auth->outgoing)))
{
_dbus_string_free (&auth_command);
return FALSE;
}
_dbus_string_free (&auth_command);
shutdown_mech (auth); // 关闭该auth之前获得的认证信息,之后释放auth->mech = NULL;
auth->mech = mech;
goto_state (auth, &client_state_waiting_for_data); // 标识client已经认证成功,进入下一个state,等待数据到来.
return TRUE;
}
static dbus_bool_t
handle_client_initial_response_external_mech (DBusAuth *auth,
DBusString *response)
{
/* We always append our UID as an initial response, so the server
* doesn't have to send back an empty challenge to check whether we
* want to specify an identity. i.e. this avoids a round trip that
* the spec for the EXTERNAL mechanism otherwise requires.
*/
DBusString plaintext;
if (!_dbus_string_init (&plaintext))
return FALSE;
if (!_dbus_append_user_from_current_process (&plaintext))
goto failed;
if (!_dbus_string_hex_encode (&plaintext, 0,
// 将geteuid()获得的EUID整数值转为ascii型hex十六进制值,追加到response字符串结尾[luther.gliethttp]
response,
_dbus_string_get_length (response)))
goto failed;
_dbus_string_free (&plaintext);
return TRUE;
failed:
_dbus_string_free (&plaintext);
return FALSE;
}
==>_dbus_transport_set_auth_mechanisms (transport, (const char **) server->auth_mechanisms)
dbus_bool_t
_dbus_transport_set_auth_mechanisms (DBusTransport *transport,
const char **mechanisms)
{
return _dbus_auth_set_mechanisms (transport->auth, mechanisms);
// 将server->auth_mechanisms的所有认证复制一份到transport->auth->allowed_mechs中.
// 那server->auth_mechanisms是什么时候得到数值的呢,
// main==>bus_context_new
// ==>parser = bus_config_load (config_file, TRUE, NULL, error); // 解析system.conf这个XML文件内容
// 我们的system.conf文件定义了如下一条auth认证语句:
// EXTERNAL
// ==>process_config_first_time_only
// ==*>auth_mechanisms[0] = "EXTERNAL";
// ==*>setup_server (context, server, auth_mechanisms, error)
// ==**>dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms);
// 这样server->auth_mechanisms就等于auth_mechanisms
// 所以server->auth_mechanisms[0] = "EXTERNAL";
// 所以transport->auth->allowed_mechs[0] = "EXTERNAL";
}
==*>connection = _dbus_connection_new_for_transport (transport);
==**>_dbus_transport_set_connection (transport, connection) // 将监控client_fd的socket_transport->write_watch和read_watch添加到context->loop中
dbus_bool_t
_dbus_transport_set_connection (DBusTransport *transport,
DBusConnection *connection)
{
_dbus_assert (transport->vtable->connection_set != NULL);
_dbus_assert (transport->connection == NULL);
transport->connection = connection;
_dbus_transport_ref (transport);
if (!(* transport->vtable->connection_set) (transport)) // 引用socket_connection_set()函数添加client_fd到待poll结构中.
transport->connection = NULL;
_dbus_transport_unref (transport);
return transport->connection != NULL;
}
==***>socket_connection_set
static const DBusTransportVTable socket_vtable = {
socket_finalize,
socket_handle_watch,
socket_disconnect,
socket_connection_set,
socket_do_iteration,
socket_live_messages_changed,
socket_get_socket_fd
};
static dbus_bool_t
socket_connection_set (DBusTransport *transport)
{
DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
_dbus_watch_set_handler (socket_transport->write_watch,
_dbus_connection_handle_watch, // 当dbus有数据需要发送到client_fd时,执行该handler处理
transport->connection, NULL);
_dbus_watch_set_handler (socket_transport->read_watch,
_dbus_connection_handle_watch, // 当client_fd有数据发送过来时,执行该handler处理
transport->connection, NULL);
if (!_dbus_connection_add_watch_unlocked (transport->connection, // 可以参考 《浅析dbus系统watch函数是如何注册登记的》
socket_transport->write_watch))
return FALSE;
if (!_dbus_connection_add_watch_unlocked (transport->connection,
socket_transport->read_watch))
{
_dbus_connection_remove_watch_unlocked (transport->connection,
socket_transport->write_watch);
return FALSE;
}
check_read_watch (transport);
check_write_watch (transport);
return TRUE;
}
==****>check_read_watch // 检测auth否,如果还没有,那么将执行auth状态机,启动认证流程[luther.gliethttp]
static void
check_read_watch (DBusTransport *transport)
{
DBusTransportSocket *socket_transport = (DBusTransportSocket*) transport;
dbus_bool_t need_read_watch;
_dbus_verbose ("%s: fd = %d\n",
_DBUS_FUNCTION_NAME, socket_transport->fd);
if (transport->connection == NULL)
return;
if (transport->disconnected)
{
_dbus_assert (socket_transport->read_watch == NULL);
return;
}
_dbus_transport_ref (transport);
if (_dbus_transport_get_is_authenticated (transport))
need_read_watch =
_dbus_counter_get_value (transport->live_messages_size) < transport->max_live_messages_size;
else
{
if (transport->receive_credentials_pending)
need_read_watch = TRUE;
else
{
/* The reason to disable need_read_watch when not WAITING_FOR_INPUT
* is to avoid spinning on the file descriptor when we're waiting
* to write or for some other part of the auth process
*/
DBusAuthState auth_state;
auth_state = _dbus_auth_do_work (transport->auth);
/* If we need memory we install the read watch just in case,
* if there's no need for it, it will get de-installed
* next time we try reading. If we're authenticated we
* install it since we normally have it installed while
* authenticated.
*/
if (auth_state == DBUS_AUTH_STATE_WAITING_FOR_INPUT ||
auth_state == DBUS_AUTH_STATE_WAITING_FOR_MEMORY ||
auth_state == DBUS_AUTH_STATE_AUTHENTICATED)
need_read_watch = TRUE;
else
need_read_watch = FALSE;
}
}
_dbus_verbose (" setting read watch enabled = %d\n", need_read_watch);
_dbus_connection_toggle_watch_unlocked (transport->connection,
socket_transport->read_watch,
need_read_watch);
_dbus_transport_unref (transport);
}
==*>new_connection_function = server->new_connection_function;
/* main ==>bus_context_new ==>process_config_first_time_only ==>setup_server ==>dbus_server_set_new_connection_function (server, // 设置回调函数 new_connection_callback, context, NULL); 最后server->new_connection_function = new_connection_callback; ==>new_connection_callback */
==*>(* new_connection_function) (server, connection, new_connection_data);
new_connection_callback
==>bus_connections_setup_connection
==*>dbus_connection_set_watch_functions (connection, add_connection_watch, remove_connection_watch, NULL, connection, NULL);
==*> add_connection_watch
static dbus_bool_t add_connection_watch (DBusWatch *watch, void *data) { DBusConnection *connection = data;
return _dbus_loop_add_watch (connection_get_loop (connection), watch, connection_watch_callback, connection, NULL); }
==**> _dbus_loop_add_watch
dbus_bool_t _dbus_loop_add_watch (DBusLoop *loop, DBusWatch *watch, DBusWatchFunction function, void *data, DBusFreeFunction free_data_func) { WatchCallback *wcb;
wcb = watch_callback_new (watch, function, data, free_data_func); if (wcb == NULL) return FALSE;
if (!add_callback (loop, (Callback*) wcb)) // 添加到 loop->callbacks链表上
{ wcb->callback.free_data_func = NULL; /* don't want to have this side effect */ callback_unref ((Callback*) wcb); return FALSE; } return TRUE; }
==***> add_callback
==****>_dbus_list_append (&loop->callbacks, cb)
看看什么时候调用loop->callbacks链表上登记的所有watch连接
****> main
****> _dbus_loop_run (bus_context_get_loop (context)) // 执行context->loop为上下文的循环
****> _dbus_loop_iterate
dbus_bool_t
_dbus_loop_iterate (DBusLoop *loop,
dbus_bool_t block)
{
#define N_STACK_DESCRIPTORS 64
......
if (loop->callbacks == NULL)
goto next_iteration;
if (loop->watch_count > N_STACK_DESCRIPTORS) {
fds = dbus_new0 (DBusPollFD, loop->watch_count);
while (fds == NULL)
{
_dbus_wait_for_memory ();
fds = dbus_new0 (DBusPollFD, loop->watch_count);
}
watches_for_fds = dbus_new (WatchCallback*, loop->watch_count);
while (watches_for_fds == NULL)
{
_dbus_wait_for_memory ();
watches_for_fds = dbus_new (WatchCallback*, loop->watch_count);
}
} else {
fds = stack_fds;
watches_for_fds = stack_watches_for_fds;
}
/* fill our array of fds and watches */
n_fds = 0;
link = _dbus_list_get_first_link (&loop->callbacks);
while (link != NULL)
{
......
fds[n_fds].fd = dbus_watch_get_socket (wcb->watch);
fds[n_fds].revents = 0;
fds[n_fds].events = 0;
if (flags & DBUS_WATCH_READABLE)
fds[n_fds].events |= _DBUS_POLLIN;
if (flags & DBUS_WATCH_WRITABLE)
fds[n_fds].events |= _DBUS_POLLOUT;
......
n_ready = _dbus_poll (fds, n_fds, timeout);
// 执行poll,监控_dbus_loop_add_watch函数登记到context->loop->callbacks上的所有watch单元对应的fd.
// add_server_watch 或者 add_connection_watch 或者 add_babysitter_watch都将调用
// _dbus_loop_add_watch向context->loop->callbacks追加watch单元.
}
}
****> server_watch_callback
****> dbus_watch_handle
****> 首先请参考《浅析dbus系统watch函数是如何注册登记的》
****> socket_handle_watch // 感知client链接
|