win32 bits

git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@1348 423420c4-83ab-492f-b58f-81f9feb106b5
This commit is contained in:
Jay Sorg 2006-12-23 03:23:59 +00:00
parent b924730d4f
commit c1aa0656a4

191
tcp.c
View File

@ -2,12 +2,12 @@
rdesktop: A Remote Desktop Protocol client. rdesktop: A Remote Desktop Protocol client.
Protocol services - TCP layer Protocol services - TCP layer
Copyright (C) Matthew Chapman 1999-2005 Copyright (C) Matthew Chapman 1999-2005
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
@ -18,6 +18,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#ifndef _WIN32
#include <unistd.h> /* select read write close */ #include <unistd.h> /* select read write close */
#include <sys/socket.h> /* socket connect setsockopt */ #include <sys/socket.h> /* socket connect setsockopt */
#include <sys/time.h> /* timeval */ #include <sys/time.h> /* timeval */
@ -26,19 +27,52 @@
#include <netinet/tcp.h> /* TCP_NODELAY */ #include <netinet/tcp.h> /* TCP_NODELAY */
#include <arpa/inet.h> /* inet_addr */ #include <arpa/inet.h> /* inet_addr */
#include <errno.h> /* errno */ #include <errno.h> /* errno */
#endif
#include "rdesktop.h" #include "rdesktop.h"
#ifdef _WIN32
#define socklen_t int
#define TCP_CLOSE(_sck) closesocket(_sck)
#define TCP_STRERROR "tcp error"
#define TCP_BLOCKS (WSAGetLastError() == WSAEWOULDBLOCK)
#else
#define TCP_CLOSE(_sck) close(_sck)
#define TCP_STRERROR strerror(errno)
#define TCP_BLOCKS (errno == EWOULDBLOCK)
#endif
#ifndef INADDR_NONE #ifndef INADDR_NONE
#define INADDR_NONE ((unsigned long) -1) #define INADDR_NONE ((unsigned long) -1)
#endif #endif
static int sock; static int g_sock;
static struct stream in; static struct stream g_in;
#ifndef WITH_SCARD #ifndef WITH_SCARD
static struct stream out; static struct stream g_out;
#endif #endif
int g_tcp_port_rdp = TCP_PORT_RDP; int g_tcp_port_rdp = TCP_PORT_RDP;
/* wait till socket is ready to write or timeout */
static BOOL
tcp_can_send(int sck, int millis)
{
fd_set wfds;
struct timeval time;
int sel_count;
time.tv_sec = millis / 1000;
time.tv_usec = (millis * 1000) % 1000000;
FD_ZERO(&wfds);
FD_SET(sck, &wfds);
sel_count = select(sck + 1, 0, &wfds, 0, &time);
if (sel_count > 0)
{
return True;
}
return False;
}
/* Initialise TCP transport data packet */ /* Initialise TCP transport data packet */
STREAM STREAM
tcp_init(uint32 maxlen) tcp_init(uint32 maxlen)
@ -49,7 +83,7 @@ tcp_init(uint32 maxlen)
scard_lock(SCARD_LOCK_TCP); scard_lock(SCARD_LOCK_TCP);
result = scard_tcp_init(); result = scard_tcp_init();
#else #else
result = &out; result = &g_out;
#endif #endif
if (maxlen > result->size) if (maxlen > result->size)
@ -78,13 +112,20 @@ tcp_send(STREAM s)
#endif #endif
while (total < length) while (total < length)
{ {
sent = send(sock, s->data + total, length - total, 0); sent = send(g_sock, s->data + total, length - total, 0);
if (sent <= 0) if (sent <= 0)
{ {
error("send: %s\n", strerror(errno)); if (sent == -1 && TCP_BLOCKS)
return; {
tcp_can_send(g_sock, 100);
sent = 0;
}
else
{
error("send: %s\n", TCP_STRERROR);
return;
}
} }
total += sent; total += sent;
} }
#ifdef WITH_SCARD #ifdef WITH_SCARD
@ -96,19 +137,19 @@ tcp_send(STREAM s)
STREAM STREAM
tcp_recv(STREAM s, uint32 length) tcp_recv(STREAM s, uint32 length)
{ {
unsigned int new_length, end_offset, p_offset; uint32 new_length, end_offset, p_offset;
int rcvd = 0; int rcvd = 0;
if (s == NULL) if (s == NULL)
{ {
/* read into "new" stream */ /* read into "new" stream */
if (length > in.size) if (length > g_in.size)
{ {
in.data = (uint8 *) xrealloc(in.data, length); g_in.data = (uint8 *) xrealloc(g_in.data, length);
in.size = length; g_in.size = length;
} }
in.end = in.p = in.data; g_in.end = g_in.p = g_in.data;
s = &in; s = &g_in;
} }
else else
{ {
@ -127,15 +168,22 @@ tcp_recv(STREAM s, uint32 length)
while (length > 0) while (length > 0)
{ {
if (!ui_select(sock)) if (!ui_select(g_sock))
/* User quit */ /* User quit */
return NULL; return NULL;
rcvd = recv(sock, s->end, length, 0); rcvd = recv(g_sock, s->end, length, 0);
if (rcvd < 0) if (rcvd < 0)
{ {
error("recv: %s\n", strerror(errno)); if (rcvd == -1 && TCP_BLOCKS)
return NULL; {
rcvd = 0;
}
else
{
error("recv: %s\n", TCP_STRERROR);
return NULL;
}
} }
else if (rcvd == 0) else if (rcvd == 0)
{ {
@ -154,7 +202,8 @@ tcp_recv(STREAM s, uint32 length)
BOOL BOOL
tcp_connect(char *server) tcp_connect(char *server)
{ {
int true_value = 1; socklen_t option_len;
uint32 option_value;
#ifdef IPv6 #ifdef IPv6
@ -175,22 +224,22 @@ tcp_connect(char *server)
} }
ressave = res; ressave = res;
sock = -1; g_sock = -1;
while (res) while (res)
{ {
sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); g_sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (!(sock < 0)) if (!(g_sock < 0))
{ {
if (connect(sock, res->ai_addr, res->ai_addrlen) == 0) if (connect(g_sock, res->ai_addr, res->ai_addrlen) == 0)
break; break;
close(sock); TCP_CLOSE(g_sock);
sock = -1; g_sock = -1;
} }
res = res->ai_next; res = res->ai_next;
} }
freeaddrinfo(ressave); freeaddrinfo(ressave);
if (sock == -1) if (g_sock == -1)
{ {
error("%s: unable to connect\n", server); error("%s: unable to connect\n", server);
return False; return False;
@ -211,34 +260,46 @@ tcp_connect(char *server)
return False; return False;
} }
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{ {
error("socket: %s\n", strerror(errno)); error("socket: %s\n", TCP_STRERROR);
return False; return False;
} }
servaddr.sin_family = AF_INET; servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(g_tcp_port_rdp); servaddr.sin_port = htons((uint16) g_tcp_port_rdp);
if (connect(sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0) if (connect(g_sock, (struct sockaddr *) &servaddr, sizeof(struct sockaddr)) < 0)
{ {
error("connect: %s\n", strerror(errno)); error("connect: %s\n", TCP_STRERROR);
close(sock); TCP_CLOSE(g_sock);
return False; return False;
} }
#endif /* IPv6 */ #endif /* IPv6 */
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *) &true_value, sizeof(true_value)); option_value = 1;
option_len = sizeof(option_value);
setsockopt(g_sock, IPPROTO_TCP, TCP_NODELAY, (void *) &option_value, option_len);
/* receive buffer must be a least 16 K */
if (getsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, &option_len) == 0)
{
if (option_value < (1024 * 16))
{
option_value = 1024 * 16;
option_len = sizeof(option_value);
setsockopt(g_sock, SOL_SOCKET, SO_RCVBUF, (void *) &option_value, option_len);
}
}
in.size = 4096; g_in.size = 4096;
in.data = (uint8 *) xmalloc(in.size); g_in.data = (uint8 *) xmalloc(g_in.size);
#ifdef WITH_SCARD #ifdef WITH_SCARD
scard_tcp_connect(); scard_tcp_connect();
#else #else
out.size = 4096; g_out.size = 4096;
out.data = (uint8 *) xmalloc(out.size); g_out.data = (uint8 *) xmalloc(g_out.size);
#endif #endif
return True; return True;
@ -248,7 +309,7 @@ tcp_connect(char *server)
void void
tcp_disconnect(void) tcp_disconnect(void)
{ {
close(sock); TCP_CLOSE(g_sock);
} }
char * char *
@ -257,9 +318,9 @@ tcp_get_address()
static char ipaddr[32]; static char ipaddr[32];
struct sockaddr_in sockaddr; struct sockaddr_in sockaddr;
socklen_t len = sizeof(sockaddr); socklen_t len = sizeof(sockaddr);
if (getsockname(sock, (struct sockaddr *) &sockaddr, &len) == 0) if (getsockname(g_sock, (struct sockaddr *) &sockaddr, &len) == 0)
{ {
unsigned char *ip = (unsigned char *) &sockaddr.sin_addr; uint8 *ip = (uint8 *) &sockaddr.sin_addr;
sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
} }
else else
@ -272,35 +333,35 @@ tcp_get_address()
void void
tcp_reset_state(void) tcp_reset_state(void)
{ {
sock = -1; /* reset socket */ g_sock = -1; /* reset socket */
/* Clear the incoming stream */ /* Clear the incoming stream */
if (in.data != NULL) if (g_in.data != NULL)
xfree(in.data); xfree(g_in.data);
in.p = NULL; g_in.p = NULL;
in.end = NULL; g_in.end = NULL;
in.data = NULL; g_in.data = NULL;
in.size = 0; g_in.size = 0;
in.iso_hdr = NULL; g_in.iso_hdr = NULL;
in.mcs_hdr = NULL; g_in.mcs_hdr = NULL;
in.sec_hdr = NULL; g_in.sec_hdr = NULL;
in.rdp_hdr = NULL; g_in.rdp_hdr = NULL;
in.channel_hdr = NULL; g_in.channel_hdr = NULL;
/* Clear the outgoing stream(s) */ /* Clear the outgoing stream(s) */
#ifdef WITH_SCARD #ifdef WITH_SCARD
scard_tcp_reset_state(); scard_tcp_reset_state();
#else #else
if (out.data != NULL) if (g_out.data != NULL)
xfree(out.data); xfree(g_out.data);
out.p = NULL; g_out.p = NULL;
out.end = NULL; g_out.end = NULL;
out.data = NULL; g_out.data = NULL;
out.size = 0; g_out.size = 0;
out.iso_hdr = NULL; g_out.iso_hdr = NULL;
out.mcs_hdr = NULL; g_out.mcs_hdr = NULL;
out.sec_hdr = NULL; g_out.sec_hdr = NULL;
out.rdp_hdr = NULL; g_out.rdp_hdr = NULL;
out.channel_hdr = NULL; g_out.channel_hdr = NULL;
#endif #endif
} }