reworked the asyncio some and completed it. parallel and serial uses it now. disk.c is a likely candidate for the future, but there are some problems with disk.c that we will have to look into first. parallel and serial works better, they do not hang the session, but are still yerky at large chunks... possibly we could split the chunks, but the terminal server does not seem to like partial transfers, i've tried some variations.. :) fns->write() could be split in smaller pieces, but what should the thresholds be.
git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@591 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
parent
4e03600214
commit
f8b90aeb7b
12
parallel.c
12
parallel.c
@ -64,13 +64,14 @@ parallel_enum_devices(int *id, char *optarg)
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
parallel_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition, uint32 flags,
|
||||
char *filename, HANDLE * handle)
|
||||
parallel_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposition,
|
||||
uint32 flags, char *filename, HANDLE * handle)
|
||||
{
|
||||
int parallel_fd;
|
||||
|
||||
parallel_fd = open(g_rdpdr_device[device_id].local_path, O_RDWR);
|
||||
if (parallel_fd == -1) {
|
||||
if (parallel_fd == -1)
|
||||
{
|
||||
perror("open");
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
@ -78,6 +79,11 @@ parallel_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 dispo
|
||||
g_rdpdr_device[device_id].handle = parallel_fd;
|
||||
|
||||
*handle = parallel_fd;
|
||||
|
||||
/* all read and writes should be non blocking */
|
||||
if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1)
|
||||
perror("fcntl");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
189
rdpdr.c
189
rdpdr.c
@ -22,15 +22,12 @@
|
||||
#define IRP_MN_QUERY_DIRECTORY 0x01
|
||||
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
|
||||
|
||||
//#define MAX_ASYNC_IO_REQUESTS 10
|
||||
|
||||
extern char hostname[16];
|
||||
extern DEVICE_FNS serial_fns;
|
||||
extern DEVICE_FNS printer_fns;
|
||||
extern DEVICE_FNS parallel_fns;
|
||||
extern DEVICE_FNS disk_fns;
|
||||
|
||||
|
||||
static VCHANNEL *rdpdr_channel;
|
||||
|
||||
/* If select() times out, the request for the device with handle g_min_timeout_fd is aborted */
|
||||
@ -40,17 +37,19 @@ uint32 g_num_devices;
|
||||
/* Table with information about rdpdr devices */
|
||||
RDPDR_DEVICE g_rdpdr_device[RDPDR_MAX_DEVICES];
|
||||
|
||||
#if 0
|
||||
/* Used to store incoming io request, until they are ready to be completed */
|
||||
/* using a linked list ensures that they are processed in the right order, */
|
||||
/* if multiple ios are being done on the same fd */
|
||||
struct async_iorequest
|
||||
{
|
||||
uint32 fd, major, minor, offset, device, id, length;
|
||||
uint32 fd, major, minor, offset, device, id, length, partial_len;
|
||||
long timeout, /* Total timeout */
|
||||
itv_timeout; /* Interval timeout (between serial characters) */
|
||||
uint8 *buffer;
|
||||
DEVICE_FNS *fns;
|
||||
} g_iorequest[MAX_ASYNC_IO_REQUESTS];
|
||||
#endif
|
||||
|
||||
struct async_iorequest *next; /* next element in list */
|
||||
} g_iorequest;
|
||||
|
||||
/* Return device_id for a given handle */
|
||||
int
|
||||
@ -77,37 +76,61 @@ convert_to_unix_filename(char *filename)
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Add a new io request to the table containing pending io requests so it won't block rdesktop */
|
||||
BOOL
|
||||
add_async_iorequest(uint32 device, uint32 file, uint32 id, uint32 major, uint32 length,
|
||||
DEVICE_FNS * fns, long total_timeout, long interval_timeout, uint8 * buffer)
|
||||
{
|
||||
int i;
|
||||
struct async_iorequest *iorq;
|
||||
|
||||
for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
|
||||
iorq = &g_iorequest;
|
||||
while (iorq->fd != 0)
|
||||
{
|
||||
iorq = &g_iorequest[i];
|
||||
// create new element if needed
|
||||
if (iorq->next == NULL)
|
||||
iorq->next =
|
||||
(struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
|
||||
|
||||
if (iorq->fd == 0)
|
||||
iorq = iorq->next;
|
||||
}
|
||||
|
||||
/* first element is special since it doesn't get deleted */
|
||||
/* don't want to get io out of order */
|
||||
if (g_iorequest.fd == 0)
|
||||
{
|
||||
iorq = &g_iorequest;
|
||||
/* look for first occurrence of fd */
|
||||
while (iorq->next != NULL)
|
||||
{
|
||||
if (iorq->fd == file)
|
||||
break;
|
||||
iorq = iorq->next;
|
||||
}
|
||||
/* if same create new link at end of chain instead */
|
||||
if (iorq->fd == file)
|
||||
{
|
||||
while (iorq->next != NULL)
|
||||
iorq = iorq->next;
|
||||
iorq->next =
|
||||
(struct async_iorequest *) xmalloc(sizeof(struct async_iorequest));
|
||||
iorq = iorq->next;
|
||||
}
|
||||
else
|
||||
iorq = &g_iorequest; /* didn't find fs use first entry */
|
||||
}
|
||||
|
||||
iorq->device = device;
|
||||
iorq->fd = file;
|
||||
iorq->id = id;
|
||||
iorq->major = major;
|
||||
iorq->length = length;
|
||||
iorq->partial_len = 0;
|
||||
iorq->fns = fns;
|
||||
iorq->timeout = total_timeout;
|
||||
iorq->itv_timeout = interval_timeout;
|
||||
iorq->buffer = buffer;
|
||||
return True;
|
||||
}
|
||||
}
|
||||
error("IO request table full. Increase MAX_ASYNC_IO_REQUESTS in rdpdr.c!\n");
|
||||
return False;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
rdpdr_send_connect(void)
|
||||
@ -290,15 +313,13 @@ rdpdr_process_irp(STREAM s)
|
||||
case DEVICE_TYPE_SERIAL:
|
||||
|
||||
fns = &serial_fns;
|
||||
/* should be async when aio is finished */
|
||||
/*rw_blocking = False; */
|
||||
rw_blocking = False;
|
||||
break;
|
||||
|
||||
case DEVICE_TYPE_PARALLEL:
|
||||
|
||||
fns = ¶llel_fns;
|
||||
/* should be async when aio is finished */
|
||||
/*rw_blocking = False;*/
|
||||
rw_blocking = False;
|
||||
break;
|
||||
|
||||
case DEVICE_TYPE_PRINTER:
|
||||
@ -308,6 +329,7 @@ rdpdr_process_irp(STREAM s)
|
||||
|
||||
case DEVICE_TYPE_DISK:
|
||||
|
||||
/*rw_blocking = False; */
|
||||
fns = &disk_fns;
|
||||
break;
|
||||
|
||||
@ -374,15 +396,14 @@ rdpdr_process_irp(STREAM s)
|
||||
#if WITH_DEBUG_RDP5
|
||||
DEBUG(("RDPDR IRP Read (length: %d, offset: %d)\n", length, offset));
|
||||
#endif
|
||||
// if (rw_blocking) // Complete read immediately
|
||||
// {
|
||||
if (rw_blocking) // Complete read immediately
|
||||
{
|
||||
buffer = (uint8 *) xrealloc((void *) buffer, length);
|
||||
status = fns->read(file, buffer, length, offset, &result);
|
||||
buffer_len = result;
|
||||
break;
|
||||
// }
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Add request to table
|
||||
pst_buf = (uint8 *) xmalloc(length);
|
||||
serial_get_timeout(file, length, &total_timeout, &interval_timeout);
|
||||
@ -396,7 +417,6 @@ rdpdr_process_irp(STREAM s)
|
||||
|
||||
status = STATUS_CANCELLED;
|
||||
break;
|
||||
#endif
|
||||
case IRP_MJ_WRITE:
|
||||
|
||||
buffer_len = 1;
|
||||
@ -413,12 +433,12 @@ rdpdr_process_irp(STREAM s)
|
||||
#if WITH_DEBUG_RDP5
|
||||
DEBUG(("RDPDR IRP Write (length: %d)\n", result));
|
||||
#endif
|
||||
// if (rw_blocking) // Complete immediately
|
||||
// {
|
||||
if (rw_blocking) // Complete immediately
|
||||
{
|
||||
status = fns->write(file, s->p, length, offset, &result);
|
||||
break;
|
||||
// }
|
||||
#if 0
|
||||
}
|
||||
|
||||
// Add to table
|
||||
pst_buf = (uint8 *) xmalloc(length);
|
||||
in_uint8a(s, pst_buf, length);
|
||||
@ -432,7 +452,6 @@ rdpdr_process_irp(STREAM s)
|
||||
|
||||
status = STATUS_CANCELLED;
|
||||
break;
|
||||
#endif
|
||||
|
||||
case IRP_MJ_QUERY_INFORMATION:
|
||||
|
||||
@ -676,20 +695,17 @@ rdpdr_init()
|
||||
return (rdpdr_channel != NULL);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Add file descriptors of pending io request to select() */
|
||||
void
|
||||
rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * timeout)
|
||||
{
|
||||
int i;
|
||||
long select_timeout = 0; // Timeout value to be used for select() (in millisecons).
|
||||
struct async_iorequest *iorq;
|
||||
|
||||
for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
|
||||
iorq = &g_iorequest;
|
||||
while (iorq != NULL)
|
||||
{
|
||||
iorq = &g_iorequest[i];
|
||||
|
||||
if (iorq->fd != 0) // Found a pending io request
|
||||
if (iorq->fd != 0)
|
||||
{
|
||||
switch (iorq->major)
|
||||
{
|
||||
@ -712,13 +728,14 @@ rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * t
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
|
||||
FD_SET(iorq->fd, wfds);
|
||||
break;
|
||||
|
||||
}
|
||||
*n = MAX(*n, iorq->fd);
|
||||
}
|
||||
|
||||
iorq = iorq->next;
|
||||
}
|
||||
}
|
||||
|
||||
@ -727,11 +744,11 @@ rdpdr_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv, BOOL * t
|
||||
void
|
||||
rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
|
||||
{
|
||||
int i;
|
||||
NTSTATUS status;
|
||||
uint32 result = 0, buffer_len = 0;
|
||||
uint32 result = 0;
|
||||
DEVICE_FNS *fns;
|
||||
struct async_iorequest *iorq;
|
||||
struct async_iorequest *prev;
|
||||
|
||||
if (timed_out)
|
||||
{
|
||||
@ -739,55 +756,89 @@ rdpdr_check_fds(fd_set * rfds, fd_set * wfds, BOOL timed_out)
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk through array of pending io_rq's
|
||||
for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
|
||||
iorq = &g_iorequest;
|
||||
prev = NULL;
|
||||
while (iorq != NULL)
|
||||
{
|
||||
iorq = &g_iorequest[i];
|
||||
|
||||
if (iorq->fd != 0)
|
||||
{
|
||||
switch (iorq->major)
|
||||
{
|
||||
|
||||
case IRP_MJ_READ:
|
||||
|
||||
if (FD_ISSET(iorq->fd, rfds))
|
||||
{
|
||||
// Read, and send data.
|
||||
/* Read the data */
|
||||
fns = iorq->fns;
|
||||
status = fns->read(iorq->fd, iorq->buffer,
|
||||
iorq->length, 0, &result);
|
||||
buffer_len = result;
|
||||
|
||||
rdpdr_send_completion(iorq->device, iorq->id,
|
||||
status, result, iorq->buffer,
|
||||
buffer_len);
|
||||
status = fns->read(iorq->fd,
|
||||
iorq->buffer + iorq->partial_len,
|
||||
iorq->length - iorq->partial_len,
|
||||
0, &result);
|
||||
iorq->partial_len += result;
|
||||
#if WITH_DEBUG_RDP5
|
||||
DEBUG(("RDPDR: %d bytes of data read\n", result));
|
||||
#endif
|
||||
/* only delete link if all data has been transfered */
|
||||
if (iorq->partial_len == iorq->length)
|
||||
{
|
||||
/* send the data */
|
||||
status = STATUS_SUCCESS;
|
||||
rdpdr_send_completion(iorq->device,
|
||||
iorq->id, status,
|
||||
iorq->length,
|
||||
iorq->buffer, result);
|
||||
|
||||
xfree(iorq->buffer);
|
||||
iorq->fd = 0;
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = iorq->next;
|
||||
xfree(iorq);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MJ_WRITE:
|
||||
|
||||
if (FD_ISSET(iorq->fd, wfds))
|
||||
{
|
||||
// Write data and send completion.
|
||||
/* Write data. */
|
||||
fns = iorq->fns;
|
||||
status = fns->write(iorq->fd, iorq->buffer,
|
||||
iorq->length, 0, &result);
|
||||
rdpdr_send_completion(iorq->device, iorq->id,
|
||||
status, result, "", 1);
|
||||
status = fns->write(iorq->fd,
|
||||
iorq->buffer +
|
||||
iorq->partial_len,
|
||||
iorq->length -
|
||||
iorq->partial_len, 0, &result);
|
||||
iorq->partial_len += result;
|
||||
#if WITH_DEBUG_RDP5
|
||||
DEBUG(("RDPDR: %d bytes of data written\n",
|
||||
result));
|
||||
#endif
|
||||
/* only delete link if all data has been transfered */
|
||||
if (iorq->partial_len == iorq->length)
|
||||
{
|
||||
/* send a status success */
|
||||
status = STATUS_SUCCESS;
|
||||
rdpdr_send_completion(iorq->device,
|
||||
iorq->id, status,
|
||||
iorq->length, "", 1);
|
||||
|
||||
xfree(iorq->buffer);
|
||||
iorq->fd = 0;
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = iorq->next;
|
||||
xfree(iorq);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
prev = iorq;
|
||||
iorq = iorq->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Abort a pending io request for a given handle and major */
|
||||
@ -795,13 +846,13 @@ BOOL
|
||||
rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status)
|
||||
{
|
||||
uint32 result;
|
||||
int i;
|
||||
struct async_iorequest *iorq;
|
||||
struct async_iorequest *prev;
|
||||
|
||||
for (i = 0; i < MAX_ASYNC_IO_REQUESTS; i++)
|
||||
iorq = &g_iorequest;
|
||||
prev = NULL;
|
||||
while (iorq != NULL)
|
||||
{
|
||||
iorq = &g_iorequest[i];
|
||||
|
||||
// Only remove from table when major is not set, or when correct major is supplied.
|
||||
// Abort read should not abort a write io request.
|
||||
if ((iorq->fd == fd) && (major == 0 || iorq->major == major))
|
||||
@ -810,9 +861,17 @@ rdpdr_abort_io(uint32 fd, uint32 major, NTSTATUS status)
|
||||
rdpdr_send_completion(iorq->device, iorq->id, status, result, "", 1);
|
||||
xfree(iorq->buffer);
|
||||
iorq->fd = 0;
|
||||
if (prev != NULL)
|
||||
{
|
||||
prev->next = iorq->next;
|
||||
xfree(iorq);
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
prev = iorq;
|
||||
iorq = iorq->next;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
#endif
|
||||
|
13
serial.c
13
serial.c
@ -399,7 +399,13 @@ serial_create(uint32 device_id, uint32 access, uint32 share_mode, uint32 disposi
|
||||
|
||||
tcsetattr(serial_fd, TCSANOW, ptermios);
|
||||
*/
|
||||
|
||||
*handle = serial_fd;
|
||||
|
||||
/* all read and writes should be non blocking */
|
||||
if (fcntl(*handle, F_SETFL, O_NONBLOCK) == -1)
|
||||
perror("fcntl");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -418,11 +424,10 @@ serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 *
|
||||
SERIAL_DEVICE *pser_inf;
|
||||
struct termios *ptermios;
|
||||
|
||||
// timeout = 90;
|
||||
timeout = 90;
|
||||
pser_inf = get_serial_info(handle);
|
||||
ptermios = pser_inf->ptermios;
|
||||
|
||||
#if 0
|
||||
// Set timeouts kind of like the windows serial timeout parameters. Multiply timeout
|
||||
// with requested read size
|
||||
if (pser_inf->read_total_timeout_multiplier | pser_inf->read_total_timeout_constant)
|
||||
@ -450,8 +455,10 @@ serial_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 *
|
||||
ptermios->c_cc[VMIN] = 1;
|
||||
}
|
||||
tcsetattr(handle, TCSANOW, ptermios);
|
||||
#endif
|
||||
|
||||
|
||||
*result = read(handle, data, length);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
20
xwin.c
20
xwin.c
@ -1271,8 +1271,10 @@ xwin_process_events(void)
|
||||
int
|
||||
ui_select(int rdp_socket)
|
||||
{
|
||||
int n = (rdp_socket > g_x_socket) ? rdp_socket + 1 : g_x_socket + 1;
|
||||
int n = (rdp_socket > g_x_socket) ? rdp_socket : g_x_socket;
|
||||
fd_set rfds, wfds;
|
||||
struct timeval tv;
|
||||
BOOL s_timeout = False;
|
||||
|
||||
while (True)
|
||||
{
|
||||
@ -1291,19 +1293,31 @@ ui_select(int rdp_socket)
|
||||
if (g_dsp_busy)
|
||||
{
|
||||
FD_SET(g_dsp_fd, &wfds);
|
||||
n = (g_dsp_fd + 1 > n) ? g_dsp_fd + 1 : n;
|
||||
n = (g_dsp_fd > n) ? g_dsp_fd : n;
|
||||
}
|
||||
#endif
|
||||
/* default timeout */
|
||||
tv.tv_sec = 60;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
switch (select(n, &rfds, &wfds, NULL, NULL))
|
||||
/* add redirection handles */
|
||||
rdpdr_add_fds(&n, &rfds, &wfds, &tv, &s_timeout);
|
||||
|
||||
n++;
|
||||
|
||||
switch (select(n, &rfds, &wfds, NULL, &tv))
|
||||
{
|
||||
case -1:
|
||||
error("select: %s\n", strerror(errno));
|
||||
|
||||
case 0:
|
||||
s_timeout = True;
|
||||
rdpdr_check_fds(&rfds, &wfds, (BOOL) True);
|
||||
continue;
|
||||
}
|
||||
|
||||
rdpdr_check_fds(&rfds, &wfds, (BOOL) False);
|
||||
|
||||
if (FD_ISSET(rdp_socket, &rfds))
|
||||
return 1;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user