Blame client/iOS/FreeRDP/ios_freerdp.m

Packit 1fb8d4
/*
Packit 1fb8d4
 RDP run-loop
Packit 1fb8d4
Packit 1fb8d4
 Copyright 2013 Thincast Technologies GmbH, Authors: Martin Fleisz, Dorian Johnson
Packit 1fb8d4
Packit 1fb8d4
 This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
Packit Service 5a9772
 If a copy of the MPL was not distributed with this file, You can obtain one at
Packit Service 5a9772
 http://mozilla.org/MPL/2.0/.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#import <freerdp/gdi/gdi.h>
Packit 1fb8d4
#import <freerdp/channels/channels.h>
Packit 1fb8d4
#import <freerdp/client/channels.h>
Packit 1fb8d4
#import <freerdp/client/cmdline.h>
Packit 1fb8d4
#import <freerdp/freerdp.h>
Packit 1fb8d4
#import <freerdp/gdi/gfx.h>
Packit 1fb8d4
Packit 1fb8d4
#import "ios_freerdp.h"
Packit 1fb8d4
#import "ios_freerdp_ui.h"
Packit 1fb8d4
#import "ios_freerdp_events.h"
Packit 1fb8d4
Packit 1fb8d4
#import "RDPSession.h"
Packit 1fb8d4
#import "Utils.h"
Packit 1fb8d4
Packit 1fb8d4
#include <errno.h>
Packit 1fb8d4
Packit 1fb8d4
#define TAG FREERDP_TAG("iOS")
Packit 1fb8d4
Packit 1fb8d4
#pragma mark Connection helpers
Packit 1fb8d4
Packit Service 5a9772
static void ios_OnChannelConnectedEventHandler(void *context, ChannelConnectedEventArgs *e)
Packit 1fb8d4
{
Packit Service 5a9772
	rdpSettings *settings;
Packit Service 5a9772
	mfContext *afc;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !e)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", __FUNCTION__, context, (void *)e);
Packit 1fb8d4
		return;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	afc = (mfContext *)context;
Packit 1fb8d4
	settings = afc->_p.settings;
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (settings->SoftwareGdi)
Packit 1fb8d4
		{
Packit Service 5a9772
			gdi_graphics_pipeline_init(afc->_p.gdi, (RdpgfxClientContext *)e->pInterface);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_WARN(TAG, "GFX without software GDI requested. "
Packit Service 5a9772
			               " This is not supported, add /gdi:sw");
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static void ios_OnChannelDisconnectedEventHandler(void *context, ChannelDisconnectedEventArgs *e)
Packit 1fb8d4
{
Packit Service 5a9772
	rdpSettings *settings;
Packit Service 5a9772
	mfContext *afc;
Packit 1fb8d4
Packit 1fb8d4
	if (!context || !e)
Packit 1fb8d4
	{
Packit Service 5a9772
		WLog_FATAL(TAG, "%s(context=%p, EventArgs=%p", __FUNCTION__, context, (void *)e);
Packit 1fb8d4
		return;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	afc = (mfContext *)context;
Packit 1fb8d4
	settings = afc->_p.settings;
Packit 1fb8d4
Packit 1fb8d4
	if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (settings->SoftwareGdi)
Packit 1fb8d4
		{
Packit Service 5a9772
			gdi_graphics_pipeline_uninit(afc->_p.gdi, (RdpgfxClientContext *)e->pInterface);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			WLog_WARN(TAG, "GFX without software GDI requested. "
Packit Service 5a9772
			               " This is not supported, add /gdi:sw");
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_pre_connect(freerdp *instance)
Packit 1fb8d4
{
Packit 1fb8d4
	int rc;
Packit Service 5a9772
	rdpSettings *settings;
Packit 1fb8d4
Packit 1fb8d4
	if (!instance || !instance->settings)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	settings = instance->settings;
Packit 1fb8d4
Packit Service 5a9772
	settings->AutoLogonEnabled = settings->Password && (strlen(settings->Password) > 0);
Packit 1fb8d4
Packit 1fb8d4
	// Verify screen width/height are sane
Packit Service 5a9772
	if ((settings->DesktopWidth < 64) || (settings->DesktopHeight < 64) ||
Packit Service 5a9772
	    (settings->DesktopWidth > 4096) || (settings->DesktopHeight > 4096))
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: invalid dimensions %d %d", __func__, settings->DesktopWidth,
Packit 1fb8d4
		      settings->DesktopHeight);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	rc = PubSub_SubscribeChannelConnected(instance->context->pubSub,
Packit Service 5a9772
	                                      ios_OnChannelConnectedEventHandler);
Packit 1fb8d4
Packit 1fb8d4
	if (rc != CHANNEL_RC_OK)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Could not subscribe to connect event handler [%l08X]", rc);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	rc = PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
Packit Service 5a9772
	                                         ios_OnChannelDisconnectedEventHandler);
Packit 1fb8d4
Packit 1fb8d4
	if (rc != CHANNEL_RC_OK)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Could not subscribe to disconnect event handler [%l08X]", rc);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Failed to load addins [%l08X]", GetLastError());
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_Pointer_New(rdpContext *context, rdpPointer *pointer)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context || !pointer || !context->gdi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static void ios_Pointer_Free(rdpContext *context, rdpPointer *pointer)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context || !pointer)
Packit 1fb8d4
		return;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_Pointer_Set(rdpContext *context, const rdpPointer *pointer)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_Pointer_SetPosition(rdpContext *context, UINT32 x, UINT32 y)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_Pointer_SetNull(rdpContext *context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_Pointer_SetDefault(rdpContext *context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_register_pointer(rdpGraphics *graphics)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpPointer pointer;
Packit 1fb8d4
Packit 1fb8d4
	if (!graphics)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	pointer.size = sizeof(pointer);
Packit 1fb8d4
	pointer.New = ios_Pointer_New;
Packit 1fb8d4
	pointer.Free = ios_Pointer_Free;
Packit 1fb8d4
	pointer.Set = ios_Pointer_Set;
Packit 1fb8d4
	pointer.SetNull = ios_Pointer_SetNull;
Packit 1fb8d4
	pointer.SetDefault = ios_Pointer_SetDefault;
Packit 1fb8d4
	pointer.SetPosition = ios_Pointer_SetPosition;
Packit 1fb8d4
	graphics_register_pointer(graphics, &pointer);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_post_connect(freerdp *instance)
Packit 1fb8d4
{
Packit Service 5a9772
	mfInfo *mfi;
Packit 1fb8d4
Packit 1fb8d4
	if (!instance)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	mfi = MFI_FROM_INSTANCE(instance);
Packit 1fb8d4
Packit 1fb8d4
	if (!mfi)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!ios_register_pointer(instance->context->graphics))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	ios_allocate_display_buffer(mfi);
Packit 1fb8d4
	instance->update->BeginPaint = ios_ui_begin_paint;
Packit 1fb8d4
	instance->update->EndPaint = ios_ui_end_paint;
Packit 1fb8d4
	instance->update->DesktopResize = ios_ui_resize_window;
Packit 1fb8d4
	[mfi->session performSelectorOnMainThread:@selector(sessionDidConnect)
Packit Service 5a9772
	                               withObject:nil
Packit Service 5a9772
	                            waitUntilDone:YES];
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static void ios_post_disconnect(freerdp *instance)
Packit 1fb8d4
{
Packit 1fb8d4
	gdi_free(instance);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Running the connection
Packit 1fb8d4
Packit Service 5a9772
int ios_run_freerdp(freerdp *instance)
Packit 1fb8d4
{
Packit Service 5a9772
	mfContext *context = (mfContext *)instance->context;
Packit Service 5a9772
	mfInfo *mfi = context->mfi;
Packit Service 5a9772
	rdpChannels *channels = instance->context->channels;
Packit 1fb8d4
	mfi->connection_state = TSXConnectionConnecting;
Packit 1fb8d4
Packit 1fb8d4
	if (!freerdp_connect(instance))
Packit 1fb8d4
	{
Packit 1fb8d4
		NSLog(@"%s: inst->rdp_connect failed", __func__);
Packit 1fb8d4
		return mfi->unwanted ? MF_EXIT_CONN_CANCELED : MF_EXIT_CONN_FAILED;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (mfi->unwanted)
Packit 1fb8d4
		return MF_EXIT_CONN_CANCELED;
Packit 1fb8d4
Packit 1fb8d4
	mfi->connection_state = TSXConnectionConnected;
Packit 1fb8d4
	// Connection main loop
Packit Service 5a9772
	NSAutoreleasePool *pool;
Packit 1fb8d4
	int i;
Packit 1fb8d4
	int fds;
Packit 1fb8d4
	int max_fds;
Packit 1fb8d4
	int rcount;
Packit 1fb8d4
	int wcount;
Packit Service 5a9772
	void *rfds[32];
Packit Service 5a9772
	void *wfds[32];
Packit 1fb8d4
	fd_set rfds_set;
Packit 1fb8d4
	fd_set wfds_set;
Packit 1fb8d4
	struct timeval timeout;
Packit 1fb8d4
	int select_status;
Packit 1fb8d4
	memset(rfds, 0, sizeof(rfds));
Packit 1fb8d4
	memset(wfds, 0, sizeof(wfds));
Packit 1fb8d4
Packit 1fb8d4
	while (!freerdp_shall_disconnect(instance))
Packit 1fb8d4
	{
Packit 1fb8d4
		rcount = wcount = 0;
Packit 1fb8d4
		pool = [[NSAutoreleasePool alloc] init];
Packit 1fb8d4
Packit 1fb8d4
		if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
Packit 1fb8d4
		{
Packit 1fb8d4
			NSLog(@"%s: inst->rdp_get_fds failed", __func__);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
Packit 1fb8d4
		{
Packit 1fb8d4
			NSLog(@"%s: freerdp_chanman_get_fds failed", __func__);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (ios_events_get_fds(mfi, rfds, &rcount, wfds, &wcount) != TRUE)
Packit 1fb8d4
		{
Packit 1fb8d4
			NSLog(@"%s: ios_events_get_fds", __func__);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		max_fds = 0;
Packit 1fb8d4
		FD_ZERO(&rfds_set);
Packit 1fb8d4
		FD_ZERO(&wfds_set);
Packit 1fb8d4
Packit 1fb8d4
		for (i = 0; i < rcount; i++)
Packit 1fb8d4
		{
Packit 1fb8d4
			fds = (int)(long)(rfds[i]);
Packit 1fb8d4
Packit 1fb8d4
			if (fds > max_fds)
Packit 1fb8d4
				max_fds = fds;
Packit 1fb8d4
Packit 1fb8d4
			FD_SET(fds, &rfds_set);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (max_fds == 0)
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		timeout.tv_sec = 1;
Packit 1fb8d4
		timeout.tv_usec = 0;
Packit 1fb8d4
		select_status = select(max_fds + 1, &rfds_set, NULL, NULL, &timeout);
Packit 1fb8d4
Packit 1fb8d4
		// timeout?
Packit 1fb8d4
		if (select_status == 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			continue;
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (select_status == -1)
Packit 1fb8d4
		{
Packit 1fb8d4
			/* these are not really errors */
Packit Service 5a9772
			if (!((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINPROGRESS) ||
Packit 1fb8d4
			      (errno == EINTR))) /* signal occurred */
Packit 1fb8d4
			{
Packit 1fb8d4
				NSLog(@"%s: select failed!", __func__);
Packit 1fb8d4
				break;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		// Check the libfreerdp fds
Packit 1fb8d4
		if (freerdp_check_fds(instance) != true)
Packit 1fb8d4
		{
Packit 1fb8d4
			NSLog(@"%s: inst->rdp_check_fds failed.", __func__);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		// Check input event fds
Packit 1fb8d4
		if (ios_events_check_fds(mfi, &rfds_set) != TRUE)
Packit 1fb8d4
		{
Packit 1fb8d4
			// This event will fail when the app asks for a disconnect.
Packit Service 5a9772
			// NSLog(@"%s: ios_events_check_fds failed: terminating connection.", __func__);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		// Check channel fds
Packit 1fb8d4
		if (freerdp_channels_check_fds(channels, instance) != TRUE)
Packit 1fb8d4
		{
Packit 1fb8d4
			NSLog(@"%s: freerdp_chanman_check_fds failed", __func__);
Packit 1fb8d4
			break;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		[pool release];
Packit 1fb8d4
		pool = nil;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CGContextRelease(mfi->bitmap_context);
Packit 1fb8d4
	mfi->bitmap_context = NULL;
Packit 1fb8d4
	mfi->connection_state = TSXConnectionDisconnected;
Packit 1fb8d4
	// Cleanup
Packit 1fb8d4
	freerdp_disconnect(instance);
Packit 1fb8d4
	gdi_free(instance);
Packit 1fb8d4
	cache_free(instance->context->cache);
Packit 1fb8d4
	[pool release];
Packit 1fb8d4
	pool = nil;
Packit 1fb8d4
	return MF_EXIT_SUCCESS;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Context callbacks
Packit 1fb8d4
Packit Service 5a9772
static BOOL ios_client_new(freerdp *instance, rdpContext *context)
Packit 1fb8d4
{
Packit Service 5a9772
	mfContext *ctx = (mfContext *)context;
Packit 1fb8d4
Packit 1fb8d4
	if (!instance || !context)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if ((ctx->mfi = calloc(1, sizeof(mfInfo))) == NULL)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit Service 5a9772
	ctx->mfi->context = (mfContext *)context;
Packit 1fb8d4
	ctx->mfi->_context = context;
Packit 1fb8d4
	ctx->mfi->context->settings = instance->settings;
Packit 1fb8d4
	ctx->mfi->instance = instance;
Packit 1fb8d4
Packit 1fb8d4
	if (!ios_events_create_pipe(ctx->mfi))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	instance->PreConnect = ios_pre_connect;
Packit 1fb8d4
	instance->PostConnect = ios_post_connect;
Packit 1fb8d4
	instance->PostDisconnect = ios_post_disconnect;
Packit 1fb8d4
	instance->Authenticate = ios_ui_authenticate;
Packit 1fb8d4
	instance->GatewayAuthenticate = ios_ui_gw_authenticate;
Packit 1fb8d4
	instance->VerifyCertificate = ios_ui_verify_certificate;
Packit 1fb8d4
	instance->VerifyChangedCertificate = ios_ui_verify_changed_certificate;
Packit 1fb8d4
	instance->LogonErrorInfo = NULL;
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static void ios_client_free(freerdp *instance, rdpContext *context)
Packit 1fb8d4
{
Packit Service 5a9772
	mfInfo *mfi;
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit Service 5a9772
	mfi = ((mfContext *)context)->mfi;
Packit 1fb8d4
	ios_events_free_pipe(mfi);
Packit 1fb8d4
	free(mfi);
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS *pEntryPoints)
Packit 1fb8d4
{
Packit 1fb8d4
	ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
Packit 1fb8d4
	pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
Packit 1fb8d4
	pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
Packit 1fb8d4
	pEntryPoints->GlobalInit = NULL;
Packit 1fb8d4
	pEntryPoints->GlobalUninit = NULL;
Packit 1fb8d4
	pEntryPoints->ContextSize = sizeof(mfContext);
Packit 1fb8d4
	pEntryPoints->ClientNew = ios_client_new;
Packit 1fb8d4
	pEntryPoints->ClientFree = ios_client_free;
Packit 1fb8d4
	pEntryPoints->ClientStart = NULL;
Packit 1fb8d4
	pEntryPoints->ClientStop = NULL;
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#pragma mark -
Packit 1fb8d4
#pragma mark Initialization and cleanup
Packit 1fb8d4
Packit Service 5a9772
freerdp *ios_freerdp_new()
Packit 1fb8d4
{
Packit Service 5a9772
	rdpContext *context;
Packit 1fb8d4
	RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
Packit 1fb8d4
	RdpClientEntry(&clientEntryPoints);
Packit 1fb8d4
	context = freerdp_client_context_new(&clientEntryPoints);
Packit 1fb8d4
Packit 1fb8d4
	if (!context)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	return context->instance;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
void ios_freerdp_free(freerdp *instance)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!instance || !instance->context)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	freerdp_client_context_free(instance->context);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void ios_init_freerdp()
Packit 1fb8d4
{
Packit 1fb8d4
	signal(SIGPIPE, SIG_IGN);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void ios_uninit_freerdp()
Packit 1fb8d4
{
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
/* compatibilty functions */
Packit Service 5a9772
size_t fwrite$UNIX2003(const void *ptr, size_t size, size_t nmemb, FILE *stream)
Packit 1fb8d4
{
Packit 1fb8d4
	return fwrite(ptr, size, nmemb, stream);
Packit 1fb8d4
}