libfreerdp-core: moving TCP out of transport module

This commit is contained in:
Marc-André Moreau 2011-07-03 15:34:15 -04:00
parent 0da3be6e53
commit 347863ffa5
8 changed files with 278 additions and 124 deletions

Binary file not shown.

View File

@ -30,6 +30,8 @@ set(LIBFREERDP_CORE_SRCS
# credssp.h # credssp.h
# ntlmssp.c # ntlmssp.c
# ntlmssp.h # ntlmssp.h
tcp.c
tcp.h
tpdu.c tpdu.c
tpdu.h tpdu.h
tpkt.c tpkt.c

View File

@ -47,23 +47,21 @@ int nego_connect(rdpNego *nego)
nego->state = NEGO_STATE_FAIL; nego->state = NEGO_STATE_FAIL;
} }
DEBUG_NEGO("Negotiating protocol security");
while (nego->state != NEGO_STATE_FINAL) while (nego->state != NEGO_STATE_FINAL)
{ {
nego_send(nego);
DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]); DEBUG_NEGO("state: %s", NEGO_STATE_STRINGS[nego->state]);
nego_send(nego);
if (nego->state == NEGO_STATE_FAIL) if (nego->state == NEGO_STATE_FAIL)
{ {
nego->state = NEGO_STATE_FINAL; nego->state = NEGO_STATE_FINAL;
return 0; return 0;
} }
nego->state = NEGO_STATE_FINAL;
} }
DEBUG_NEGO("Negotiated %s security", PROTOCOL_SECURITY_STRINGS[nego->selected_protocol]);
return 1; return 1;
} }
@ -215,6 +213,10 @@ int nego_recv(rdpTransport * transport, STREAM* s, void * extra)
break; break;
} }
} }
else
{
nego->state = NEGO_STATE_FINAL;
}
return 0; return 0;
} }

View File

@ -38,12 +38,12 @@ typedef enum _NEGO_STATE NEGO_STATE;
char NEGO_STATE_STRINGS[6][25] = char NEGO_STATE_STRINGS[6][25] =
{ {
"NEGO_STATE_INITIAL", "NEGO_STATE_INITIAL",
"NEGO_STATE_NLA", "NEGO_STATE_NLA",
"NEGO_STATE_TLS", "NEGO_STATE_TLS",
"NEGO_STATE_RDP", "NEGO_STATE_RDP",
"NEGO_STATE_FAIL", "NEGO_STATE_FAIL",
"NEGO_STATE_FINAL" "NEGO_STATE_FINAL"
}; };
/* RDP Negotiation Messages */ /* RDP Negotiation Messages */
@ -56,6 +56,13 @@ enum RDP_NEG_MSG
TYPE_RDP_NEG_FAILURE = 0x3 TYPE_RDP_NEG_FAILURE = 0x3
}; };
char PROTOCOL_SECURITY_STRINGS[3][4] =
{
"RDP",
"TLS",
"NLA"
};
struct rdp_nego struct rdp_nego
{ {
int port; int port;

145
libfreerdp-core/tcp.c Normal file
View File

@ -0,0 +1,145 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Transmission Control Protocol (TCP)
*
* Copyright 2011 Vic Lee
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <sys/socket.h>
#include <netdb.h>
#include <fcntl.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/memory.h>
#include "tcp.h"
FRDP_BOOL
tcp_connect(rdpTcp * tcp, const char * hostname, int port)
{
int status;
int sockfd = -1;
char servname[10];
struct addrinfo hints = { 0 };
struct addrinfo * res, * ai;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(servname, sizeof(servname), "%d", port);
status = getaddrinfo(hostname, servname, &hints, &res);
if (status != 0)
{
printf("transport_connect: getaddrinfo (%s)\n", gai_strerror(status));
return False;
}
for (ai = res; ai; ai = ai->ai_next)
{
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd < 0)
continue;
if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == 0)
{
printf("connected to %s:%s\n", hostname, servname);
break;
}
sockfd = -1;
}
freeaddrinfo(res);
if (sockfd == -1)
{
printf("unable to connect to %s:%s\n", hostname, servname);
return False;
}
tcp->sockfd = sockfd;
return True;
}
FRDP_BOOL
tcp_disconnect(rdpTcp * tcp)
{
if (tcp->sockfd != -1)
{
close(tcp->sockfd);
tcp->sockfd = -1;
}
return True;
}
FRDP_BOOL
tcp_set_blocking_mode(rdpTcp * tcp, FRDP_BOOL blocking)
{
int flags;
flags = fcntl(tcp->sockfd, F_GETFL);
if (flags == -1)
{
printf("transport_configure_sockfd: fcntl failed.\n");
return False;
}
if (blocking == True)
{
/* blocking */
fcntl(tcp->sockfd, F_SETFL, flags & ~(O_NONBLOCK));
}
else
{
/* non-blocking */
fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK);
}
return True;
}
rdpTcp*
tcp_new()
{
rdpTcp *tcp = (rdpTcp*) xzalloc(sizeof(rdpTcp));
if (tcp != NULL)
{
tcp->sockfd = -1;
tcp->connect = tcp_connect;
tcp->disconnect = tcp_disconnect;
tcp->set_blocking_mode = tcp_set_blocking_mode;
}
return tcp;
}
void
tcp_free(rdpTcp* tcp)
{
if (tcp != NULL)
{
xfree(tcp);
}
}

52
libfreerdp-core/tcp.h Normal file
View File

@ -0,0 +1,52 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Transmission Control Protocol (TCP)
*
* Copyright 2011 Vic Lee
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* 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.
*/
#ifndef __TCP_H
#define __TCP_H
#include <freerdp/types/base.h>
#include <freerdp/utils/stream.h>
typedef struct rdp_tcp rdpTcp;
typedef FRDP_BOOL (*TcpConnect) (rdpTcp * tcp, const char * hostname, int port);
typedef FRDP_BOOL (*TcpDisconnect) (rdpTcp * tcp);
typedef FRDP_BOOL (*TcpSetBlockingMode) (rdpTcp * tcp, FRDP_BOOL blocking);
struct rdp_tcp
{
int sockfd;
TcpConnect connect;
TcpDisconnect disconnect;
TcpSetBlockingMode set_blocking_mode;
};
FRDP_BOOL
tcp_connect(rdpTcp * tcp, const char * hostname, int port);
FRDP_BOOL
tcp_disconnect(rdpTcp * tcp);
FRDP_BOOL
tcp_set_blocking_mode(rdpTcp * tcp, FRDP_BOOL blocking);
rdpTcp*
tcp_new();
void
tcp_free(rdpTcp* tcp);
#endif /* __TCP_H */

View File

@ -34,122 +34,16 @@
#define BUFFER_SIZE 16384 #define BUFFER_SIZE 16384
rdpTransport *
transport_new(void)
{
rdpTransport * transport;
transport = (rdpTransport *) xmalloc(sizeof(rdpTransport));
memset(transport, 0, sizeof(rdpTransport));
transport->sockfd = -1;
/* a small 0.1ms delay when transport is blocking. */
transport->ts.tv_sec = 0;
transport->ts.tv_nsec = 100000;
/* receive buffer for non-blocking read. */
transport->recv_buffer = stream_new(BUFFER_SIZE);
return transport;
}
void
transport_free(rdpTransport * transport)
{
stream_free(transport->recv_buffer);
xfree(transport);
}
static FRDP_BOOL
transport_connect_sockfd(rdpTransport * transport, const char * server, int port)
{
int status;
int sockfd = -1;
char servname[10];
struct addrinfo hints = { 0 };
struct addrinfo * res, * ai;
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
snprintf(servname, sizeof(servname), "%d", port);
status = getaddrinfo(server, servname, &hints, &res);
if (status != 0)
{
printf("transport_connect: getaddrinfo (%s)\n", gai_strerror(status));
return False;
}
for (ai = res; ai; ai = ai->ai_next)
{
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd < 0)
continue;
if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) == 0)
{
printf("connected to %s:%s\n", server, servname);
break;
}
sockfd = -1;
}
freeaddrinfo(res);
if (sockfd == -1)
{
printf("unable to connect to %s:%s\n", server, servname);
return False;
}
transport->sockfd = sockfd;
return True;
}
static FRDP_BOOL
transport_configure_sockfd(rdpTransport * transport)
{
int flags;
flags = fcntl(transport->sockfd, F_GETFL);
if (flags == -1)
{
printf("transport_configure_sockfd: fcntl failed.\n");
return False;
}
fcntl(transport->sockfd, F_SETFL, flags | O_NONBLOCK);
return True;
}
FRDP_BOOL FRDP_BOOL
transport_connect(rdpTransport * transport, const char * server, int port) transport_connect(rdpTransport * transport, const char * server, int port)
{ {
if (transport_connect_sockfd(transport, server, port) != True) return transport->tcp->connect(transport->tcp, server, port);
return False;
if (transport_configure_sockfd(transport) != True)
return False;
return True;
} }
int FRDP_BOOL
transport_disconnect(rdpTransport * transport) transport_disconnect(rdpTransport * transport)
{ {
if (transport->sockfd != -1) return transport->tcp->disconnect(transport->tcp);
{
close(transport->sockfd);
transport->sockfd = -1;
}
return True;
} }
int int
@ -183,7 +77,7 @@ transport_send_tcp(rdpTransport * transport, STREAM * stream)
while (head < tail) while (head < tail)
{ {
bytes = send(transport->sockfd, head, tail - head, MSG_NOSIGNAL); bytes = send(transport->tcp->sockfd, head, tail - head, MSG_NOSIGNAL);
if (bytes < 0) if (bytes < 0)
{ {
@ -226,7 +120,7 @@ transport_recv_tcp(rdpTransport * transport)
stream_check_capacity(transport->recv_buffer, BUFFER_SIZE); stream_check_capacity(transport->recv_buffer, BUFFER_SIZE);
bytes = recv(transport->sockfd, transport->recv_buffer->ptr, BUFFER_SIZE, 0); bytes = recv(transport->tcp->sockfd, transport->recv_buffer->ptr, BUFFER_SIZE, 0);
if (bytes == -1) if (bytes == -1)
{ {
@ -296,3 +190,42 @@ transport_check_fds(rdpTransport * transport)
return bytes; return bytes;
} }
void
transport_init(rdpTransport * transport)
{
transport->state = TRANSPORT_STATE_NEGO;
}
rdpTransport *
transport_new(void)
{
rdpTransport * transport;
transport = (rdpTransport *) xzalloc(sizeof(rdpTransport));
if (transport != NULL)
{
transport->tcp = tcp_new();
/* a small 0.1ms delay when transport is blocking. */
transport->ts.tv_sec = 0;
transport->ts.tv_nsec = 100000;
/* receive buffer for non-blocking read. */
transport->recv_buffer = stream_new(BUFFER_SIZE);
}
return transport;
}
void
transport_free(rdpTransport * transport)
{
if (transport != NULL)
{
stream_free(transport->recv_buffer);
tcp_free(transport->tcp);
xfree(transport);
}
}

View File

@ -20,16 +20,29 @@
#ifndef __TRANSPORT_H #ifndef __TRANSPORT_H
#define __TRANSPORT_H #define __TRANSPORT_H
#include "tcp.h"
#include <time.h> #include <time.h>
#include <freerdp/types/base.h> #include <freerdp/types/base.h>
#include <freerdp/utils/stream.h> #include <freerdp/utils/stream.h>
enum _TRANSPORT_STATE
{
TRANSPORT_STATE_INITIAL,
TRANSPORT_STATE_NEGO,
TRANSPORT_STATE_TLS,
TRANSPORT_STATE_NLA,
TRANSPORT_STATE_FINAL
};
typedef enum _TRANSPORT_STATE TRANSPORT_STATE;
typedef struct rdp_transport rdpTransport; typedef struct rdp_transport rdpTransport;
typedef int (* PacketReceivedCallback) (rdpTransport * transport, STREAM * stream, void* extra); typedef int (* PacketReceivedCallback) (rdpTransport * transport, STREAM * stream, void* extra);
struct rdp_transport struct rdp_transport
{ {
int sockfd; TRANSPORT_STATE state;
struct rdp_tcp * tcp;
struct crypto_tls * tls; struct crypto_tls * tls;
struct timespec ts; struct timespec ts;
STREAM * recv_buffer; STREAM * recv_buffer;