FreeRDP/libfreerdp/utils/wait_obj.c
2012-08-14 20:21:00 -04:00

240 lines
3.9 KiB
C

/**
* FreeRDP: A Remote Desktop Protocol client.
* Virtual Channel Manager
*
* Copyright 2009-2011 Jay Sorg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/windows.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/wait_obj.h>
#ifndef _WIN32
#include <sys/time.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
struct wait_obj
{
#ifdef _WIN32
HANDLE event;
#else
int pipe_fd[2];
#endif
int attached;
};
struct wait_obj*
wait_obj_new(void)
{
struct wait_obj* obj;
obj = xnew(struct wait_obj);
obj->attached = 0;
#ifdef _WIN32
obj->event = CreateEvent(NULL, TRUE, FALSE, NULL);
#else
obj->pipe_fd[0] = -1;
obj->pipe_fd[1] = -1;
if (pipe(obj->pipe_fd) < 0)
{
printf("wait_obj_new: pipe failed\n");
xfree(obj);
return NULL;
}
#endif
return obj;
}
struct wait_obj* wait_obj_new_with_fd(void* fd)
{
struct wait_obj* obj;
obj = xnew(struct wait_obj);
obj->attached = 1;
#ifdef _WIN32
obj->event = fd;
#else
obj->pipe_fd[0] = (int)(long)fd;
obj->pipe_fd[1] = -1;
#endif
return obj;
}
void
wait_obj_free(struct wait_obj* obj)
{
if (obj)
{
if (obj->attached == 0)
{
#ifdef _WIN32
if (obj->event)
{
CloseHandle(obj->event);
obj->event = NULL;
}
#else
if (obj->pipe_fd[0] != -1)
{
close(obj->pipe_fd[0]);
obj->pipe_fd[0] = -1;
}
if (obj->pipe_fd[1] != -1)
{
close(obj->pipe_fd[1]);
obj->pipe_fd[1] = -1;
}
#endif
}
xfree(obj);
}
}
int
wait_obj_is_set(struct wait_obj* obj)
{
#ifdef _WIN32
return (WaitForSingleObject(obj->event, 0) == WAIT_OBJECT_0);
#else
fd_set rfds;
int num_set;
struct timeval time;
FD_ZERO(&rfds);
FD_SET(obj->pipe_fd[0], &rfds);
memset(&time, 0, sizeof(time));
num_set = select(obj->pipe_fd[0] + 1, &rfds, 0, 0, &time);
return (num_set == 1);
#endif
}
void
wait_obj_set(struct wait_obj* obj)
{
#ifdef _WIN32
SetEvent(obj->event);
#else
int len;
if (wait_obj_is_set(obj))
return;
len = write(obj->pipe_fd[1], "sig", 4);
if (len != 4)
printf("wait_obj_set: error\n");
#endif
}
void
wait_obj_clear(struct wait_obj* obj)
{
#ifdef _WIN32
ResetEvent(obj->event);
#else
int len;
while (wait_obj_is_set(obj))
{
len = read(obj->pipe_fd[0], &len, 4);
if (len != 4)
printf("wait_obj_clear: error\n");
}
#endif
}
int
wait_obj_select(struct wait_obj** listobj, int numobj, int timeout)
{
int index;
int status;
#ifndef _WIN32
int max;
int sock;
fd_set fds;
struct timeval time;
struct timeval* ptime;
ptime = 0;
if (timeout >= 0)
{
time.tv_sec = timeout / 1000;
time.tv_usec = (timeout * 1000) % 1000000;
ptime = &time;
}
max = 0;
FD_ZERO(&fds);
if (listobj)
{
for (index = 0; index < numobj; index++)
{
sock = listobj[index]->pipe_fd[0];
FD_SET(sock, &fds);
if (sock > max)
max = sock;
}
}
status = select(max + 1, &fds, 0, 0, ptime);
#else
HANDLE *hnds;
hnds = (HANDLE *) xzalloc(sizeof(HANDLE) * (numobj + 1));
for (index = 0; index < numobj; index++)
{
hnds[index] = listobj[index]->event;
}
if (WaitForMultipleObjects(numobj, hnds, FALSE, timeout) == WAIT_FAILED)
status = -1;
else
status = 0;
xfree(hnds);
#endif
return status;
}
void wait_obj_get_fds(struct wait_obj* obj, void** fds, int* count)
{
#ifdef _WIN32
fds[*count] = (void*) obj->event;
#else
if (obj->pipe_fd[0] == -1)
return;
fds[*count] = (void*)(long) obj->pipe_fd[0];
#endif
(*count)++;
}