代码如下: /** Creates a new connection based on the settings found in the “instance” parameter * It will use the callbacks registered on the structure to process the pre/post connect operations * that the caller requires. * @see struct rdp_freerdp in freerdp.h * * @param instance – pointer to a rdp_freerdp structure that contains base information to establish * the connection. On return, this function will be initialized with the new connection’s settings. * * @return TRUE if successful. FALSE otherwise. * */BOOL freerdp_connect(freerdp* instance){UINT status2 = CHANNEL_RC_OK;rdpRdp* rdp;BOOL status = TRUE;rdpSettings* settings;ConnectionResultEventArgs e;if (!instance)return FALSE;WINPR_ASSERT(instance->context);/* We always set the return code to 0 before we start the connect sequence*/instance->ConnectionCallbackState = CLIENT_STATE_INITIAL;freerdp_set_last_error_log(instance->context, FREERDP_ERROR_SUCCESS);clearChannelError(instance->context);ResetEvent(instance->context->abortEvent);rdp = instance->context->rdp;WINPR_ASSERT(rdp);settings = instance->settings;WINPR_ASSERT(settings);freerdp_channels_register_instance(instance->context->channels, instance);if (!freerdp_settings_set_default_order_support(settings))return FALSE;IFCALLRET(instance->PreConnect, status, instance);instance->ConnectionCallbackState = CLIENT_STATE_PRECONNECT_PASSED;if (status)status2 = freerdp_channels_pre_connect(instance->context->channels, instance);/*如果键盘是KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002类型的, 需要进一步指定keyboardtype keyboardsubtype和keybooardfunctionkey */if (settings->KeyboardLayout == KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002){settings->KeyboardType = 7;settings->KeyboardSubType = 2;settings->KeyboardFunctionKey = 12;}if (!status || (status2 != CHANNEL_RC_OK)){freerdp_set_last_error_if_not(instance->context, FREERDP_ERROR_PRE_CONNECT_FAILED);WLog_ERR(TAG, “freerdp_pre_connect failed”);goto freerdp_connect_finally;}status = rdp_client_connect(rdp);/* Pointers might have changed inbetween */if (rdp && rdp->settings){/* –authonly tests the connection without a UI */if (rdp->settings->AuthenticationOnly){WLog_ERR(TAG, “Authentication only, exit status %” PRId32 “”, status);goto freerdp_connect_finally;}if (rdp->settings->DumpRemoteFx){rdp->update->pcap_rfx = pcap_open(rdp->settings->DumpRemoteFxFile, TRUE);if (rdp->update->pcap_rfx)rdp->update->dump_rfx = TRUE;}}if (status){pointer_cache_register_callbacks(instance->context->update);IFCALLRET(instance->PostConnect, status, instance);instance->ConnectionCallbackState = CLIENT_STATE_POSTCONNECT_PASSED;if (status)status2 = freerdp_channels_post_connect(instance->context->channels, instance);}else{if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_CONNECT_TRANSPORT_FAILED)status = freerdp_reconnect(instance);elsegoto freerdp_connect_finally;}if (!status || (status2 != CHANNEL_RC_OK) || !update_post_connect(instance->update)){WLog_ERR(TAG, “freerdp_post_connect failed”);freerdp_set_last_error_if_not(instance->context, FREERDP_ERROR_POST_CONNECT_FAILED);status = FALSE;goto freerdp_connect_finally;}if (instance->settings->PlayRemoteFx){wStream* s;rdpUpdate* update;pcap_record record;update = instance->update;update->pcap_rfx = pcap_open(settings->PlayRemoteFxFile, FALSE);status = FALSE;if (!update->pcap_rfx)goto freerdp_connect_finally;elseupdate->play_rfx = TRUE;status = TRUE;while (pcap_has_next_record(update->pcap_rfx) && status){pcap_get_next_record_header(update->pcap_rfx, &record);s = transport_take_from_pool(rdp->transport, record.length);if (!s)break;record.data = Stream_Buffer(s);pcap_get_next_record_content(update->pcap_rfx, &record);Stream_SetLength(s, record.length);Stream_SetPosition(s, 0);if (!update_begin_paint(update))status = FALSE;else{if (update_recv_surfcmds(update, s) < 0)status = FALSE;if (!update_end_paint(update))status = FALSE;}Stream_Release(s);}pcap_close(update->pcap_rfx);update->pcap_rfx = NULL;goto freerdp_connect_finally;}if (rdp->errorInfo == ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES)freerdp_set_last_error_log(instance->context, FREERDP_ERROR_INSUFFICIENT_PRIVILEGES);transport_set_connected_event(rdp->transport);freerdp_connect_finally:EventArgsInit(&e, “freerdp”);e.result = status ? 0 : -1;PubSub_OnConnectionResult(instance->context->pubSub, instance->context, &e);if (!status)freerdp_disconnect(instance);return status;} 主要功能:
主要进行链接服务器前的客户端接口绑定,channels的连接前处理, 链接, 连接后的客户端接口处理, channels连接后处理,链接失败处理逻辑
重置一些必要参数:setting,rdp,status,wStream,Event,Error等.
代码分析:
IFCALLRET(instance->PreConnect, status, instance);
调用连接前函数,PreConnect , 通过跟踪代码发现调用
下面的函数
/** * 获取本机的显示器分辨率信息,加载channels信息,设置键盘信息 * @param instance * @return */static BOOL wl_pre_connect(freerdp* instance){rdpSettings* settings;wlfContext* context;const UwacOutput* output;UwacSize resolution;if (!instance)return FALSE;context = (wlfContext*)instance->context;settings = instance->settings;if (!context || !settings)return FALSE;settings->OsMajorType = OSMAJORTYPE_UNIX;settings->OsMinorType = OSMINORTYPE_NATIVE_WAYLAND;PubSub_SubscribeChannelConnected(instance->context->pubSub, wlf_OnChannelConnectedEventHandler);PubSub_SubscribeChannelDisconnected(instance->context->pubSub, wlf_OnChannelDisconnectedEventHandler);if (settings->Fullscreen){// Use the resolution of the first display outputoutput = UwacDisplayGetOutput(context->display, 0);if ((output != NULL) && (UwacOutputGetResolution(output, &resolution) == UWAC_SUCCESS)){settings->DesktopWidth = (UINT32)resolution.width;settings->DesktopHeight = (UINT32)resolution.height;}else{WLog_WARN(TAG, “Failed to get output resolution! Check your display settings”);}}if (!freerdp_client_load_addins(instance->context->channels, instance->settings))return FALSE;return TRUE;}
可以看到将分辨率信息赋值给settings。
加载channels信息, 通过freerdp_client_load_addins进行参数传递。
链接RDP服务器函数接口, 包括协议选择, socket建立等
为记录remoteFX的dump信息创建文件
目前就分析到这个地方,后面继续进行分析。待续~~~~。