server: create initial server API.

This commit is contained in:
Vic Lee 2011-08-18 16:06:32 +08:00
parent 3fa7d4a3d4
commit 5fc87c25cf
11 changed files with 722 additions and 0 deletions

View File

@ -133,3 +133,4 @@ if(NOT WIN32)
endif() endif()
add_subdirectory(client) add_subdirectory(client)
add_subdirectory(server)

View File

@ -0,0 +1,64 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RDP Server Listener
*
* Copyright 2011 Vic Lee
*
* 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 __FREERDP_LISTENER_H
#define __FREERDP_LISTENER_H
typedef struct rdp_freerdp_listener freerdp_listener;
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
#include <freerdp/peer.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef boolean (*pcListenerOpen)(freerdp_listener* instance, const char* bind_address, uint16 port);
typedef boolean (*pcListenerGetFileDescriptor)(freerdp_listener* instance, void** rfds, int* rcount);
typedef boolean (*pcListenerCheckFileDescriptor)(freerdp_listener* instance);
typedef void (*pcListenerClose)(freerdp_listener* instance);
typedef void (*pcPeerAccepted)(freerdp_listener* instance, freerdp_peer* client);
struct rdp_freerdp_listener
{
void* listener;
void* param1;
void* param2;
void* param3;
void* param4;
pcListenerOpen Open;
pcListenerGetFileDescriptor GetFileDescriptor;
pcListenerCheckFileDescriptor CheckFileDescriptor;
pcListenerClose Close;
pcPeerAccepted PeerAccepted;
};
FREERDP_API freerdp_listener* freerdp_listener_new(void);
FREERDP_API void freerdp_listener_free(freerdp_listener* instance);
#ifdef __cplusplus
}
#endif
#endif

54
include/freerdp/peer.h Normal file
View File

@ -0,0 +1,54 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RDP Server Peer
*
* Copyright 2011 Vic Lee
*
* 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 __FREERDP_PEER_H
#define __FREERDP_PEER_H
typedef struct rdp_freerdp_peer freerdp_peer;
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
typedef boolean (*pcPeerInitialize)(freerdp_peer* client);
typedef boolean (*pcPeerGetFileDescriptor)(freerdp_peer* client, void** rfds, int* rcount);
typedef boolean (*pcPeerCheckFileDescriptor)(freerdp_peer* client);
typedef void (*pcPeerDisconnect)(freerdp_peer* client);
struct rdp_freerdp_peer
{
void* peer;
void* param1;
void* param2;
void* param3;
void* param4;
rdpSettings* settings;
pcPeerInitialize Initialize;
pcPeerGetFileDescriptor GetFileDescriptor;
pcPeerCheckFileDescriptor CheckFileDescriptor;
pcPeerDisconnect Disconnect;
};
FREERDP_API freerdp_peer* freerdp_peer_new(int sockfd);
FREERDP_API void freerdp_peer_free(freerdp_peer* client);
#endif /* __FREERDP_PEER_H */

View File

@ -84,6 +84,10 @@ set(LIBFREERDP_CORE_SRCS
vchan.h vchan.h
window.c window.c
window.h window.h
listener.c
listener.h
peer.c
peer.h
) )
add_library(freerdp-core SHARED ${LIBFREERDP_CORE_SRCS}) add_library(freerdp-core SHARED ${LIBFREERDP_CORE_SRCS})

215
libfreerdp-core/listener.c Normal file
View File

@ -0,0 +1,215 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RDP Server Listener
*
* Copyright 2011 Vic Lee
*
* 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 <fcntl.h>
#ifndef _WIN32
#include <netdb.h>
#include <net/if.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#else
#define close(_fd) closesocket(_fd)
#endif
#include "listener.h"
static boolean freerdp_listener_open(freerdp_listener* instance, const char* bind_address, uint16 port)
{
rdpListener* listener = (rdpListener*)instance->listener;
int status;
int sockfd;
char servname[10];
struct addrinfo hints = { 0 };
struct addrinfo* res;
struct addrinfo* ai;
int option_value;
void* sin_addr;
char buf[50];
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if (bind_address == NULL)
hints.ai_flags = AI_PASSIVE;
snprintf(servname, sizeof(servname), "%d", port);
status = getaddrinfo(bind_address, servname, &hints, &res);
if (status != 0)
{
perror("getaddrinfo");
return False;
}
for (ai = res; ai && listener->num_sockfds < 5; ai = ai->ai_next)
{
if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
continue;
sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (sockfd == -1)
{
perror("socket");
continue;
}
option_value = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option_value, sizeof(option_value)) == -1)
{
perror("setsockopt");
}
fcntl(sockfd, F_SETFL, O_NONBLOCK);
status = bind(sockfd, ai->ai_addr, ai->ai_addrlen);
if (status != 0)
{
perror("bind");
close(sockfd);
continue;
}
status = listen(sockfd, 10);
if (status != 0)
{
perror("listen");
close(sockfd);
continue;
}
listener->sockfds[listener->num_sockfds++] = sockfd;
if (ai->ai_family == AF_INET)
sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr);
else
sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr);
printf("Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname);
}
freeaddrinfo(res);
return (listener->num_sockfds > 0 ? True : False);
}
static void freerdp_listener_close(freerdp_listener* instance)
{
int i;
rdpListener* listener = (rdpListener*)instance->listener;
for (i = 0; i < listener->num_sockfds; i++)
{
close(listener->sockfds[i]);
}
listener->num_sockfds = 0;
}
static boolean freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount)
{
rdpListener* listener = (rdpListener*)instance->listener;
int i;
if (listener->num_sockfds < 1)
return False;
for (i = 0; i < listener->num_sockfds; i++)
{
rfds[*rcount] = (void*)(long)(listener->sockfds[i]);
(*rcount)++;
}
return True;
}
static boolean freerdp_listener_check_fds(freerdp_listener* instance)
{
rdpListener* listener = (rdpListener*)instance->listener;
struct sockaddr_storage peer_addr;
socklen_t peer_addr_size;
int peer_sockfd;
int i;
freerdp_peer* client;
void* sin_addr;
if (listener->num_sockfds < 1)
return False;
for (i = 0; i < listener->num_sockfds; i++)
{
peer_addr_size = sizeof(peer_addr);
peer_sockfd = accept(listener->sockfds[i], (struct sockaddr *)&peer_addr, &peer_addr_size);
if (peer_sockfd == -1)
{
if (errno == EAGAIN || errno == EWOULDBLOCK)
continue;
perror("accept");
return False;
}
client = freerdp_peer_new(peer_sockfd);
if (peer_addr.ss_family == AF_INET)
sin_addr = &(((struct sockaddr_in*)&peer_addr)->sin_addr);
else
sin_addr = &(((struct sockaddr_in6*)&peer_addr)->sin6_addr);
client->settings->hostname = xzalloc(50);
inet_ntop(peer_addr.ss_family, sin_addr, client->settings->hostname, 50);
printf("Accepted client from %s.\n", client->settings->hostname);
IFCALL(instance->PeerAccepted, instance, client);
}
return True;
}
freerdp_listener* freerdp_listener_new(void)
{
freerdp_listener* instance;
rdpListener* listener;
instance = xnew(freerdp_listener);
instance->Open = freerdp_listener_open;
instance->GetFileDescriptor = freerdp_listener_get_fds;
instance->CheckFileDescriptor = freerdp_listener_check_fds;
instance->Close = freerdp_listener_close;
listener = xnew(rdpListener);
listener->instance = instance;
instance->listener = (void*)listener;
return instance;
}
void freerdp_listener_free(freerdp_listener* instance)
{
rdpListener* listener;
listener = (rdpListener*)instance->listener;
xfree(listener);
xfree(instance);
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RDP Server Listener
*
* Copyright 2011 Vic Lee
*
* 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 __LISTENER_H
#define __LISTENER_H
typedef struct rdp_listener rdpListener;
#include "rdp.h"
#include <freerdp/listener.h>
struct rdp_listener
{
freerdp_listener* instance;
int sockfds[5];
int num_sockfds;
};
#endif

76
libfreerdp-core/peer.c Normal file
View File

@ -0,0 +1,76 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RDP Server Peer
*
* Copyright 2011 Vic Lee
*
* 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 "peer.h"
static boolean freerdp_peer_initialize(freerdp_peer* client)
{
return True;
}
static boolean freerdp_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
{
rdpPeer* peer = (rdpPeer*)client->peer;
rfds[*rcount] = (void*)(long)(peer->sockfd);
(*rcount)++;
return True;
}
static boolean freerdp_peer_check_fds(freerdp_peer* client)
{
return True;
}
static void freerdp_peer_disconnect(freerdp_peer* client)
{
}
freerdp_peer* freerdp_peer_new(int sockfd)
{
freerdp_peer* client;
rdpPeer* peer;
client = xnew(freerdp_peer);
client->settings = settings_new();
client->Initialize = freerdp_peer_initialize;
client->GetFileDescriptor = freerdp_peer_get_fds;
client->CheckFileDescriptor = freerdp_peer_check_fds;
client->Disconnect = freerdp_peer_disconnect;
peer = xnew(rdpPeer);
peer->client = client;
peer->sockfd = sockfd;
client->peer = (void*)peer;
return client;
}
void freerdp_peer_free(freerdp_peer* client)
{
rdpPeer* peer = (rdpPeer*)client->peer;
xfree(peer);
settings_free(client->settings);
xfree(client);
}

36
libfreerdp-core/peer.h Normal file
View File

@ -0,0 +1,36 @@
/**
* FreeRDP: A Remote Desktop Protocol client.
* RDP Server Peer
*
* Copyright 2011 Vic Lee
*
* 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 __PEER
#define __PEER
typedef struct rdp_peer rdpPeer;
#include "rdp.h"
#include <freerdp/peer.h>
struct rdp_peer
{
freerdp_peer* client;
int sockfd;
};
#endif /* __PEER */

27
server/CMakeLists.txt Normal file
View File

@ -0,0 +1,27 @@
# FreeRDP: A Remote Desktop Protocol Client
# FreeRDP Servers
#
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# 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.
# Servers
if(NOT WIN32)
# Build Test Server
add_subdirectory(test)
endif()

View File

@ -0,0 +1,25 @@
# FreeRDP: A Remote Desktop Protocol Client
# FreeRDP Test Server cmake build script
#
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# 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.
add_executable(freerdp-server-test
freerdp_server.c)
target_link_libraries(freerdp-server-test freerdp-core)
target_link_libraries(freerdp-server-test freerdp-utils)
target_link_libraries(freerdp-server-test freerdp-rfx)

View File

@ -0,0 +1,183 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Test Server
*
* 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 <errno.h>
#include <pthread.h>
#include <freerdp/utils/memory.h>
#include <freerdp/utils/thread.h>
#include <freerdp/listener.h>
static void* test_peer_mainloop(void* arg)
{
freerdp_peer* client = (freerdp_peer*)arg;
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
memset(rfds, 0, sizeof(rfds));
printf("We've got a client %s\n", client->settings->hostname);
client->Initialize(client);
while (1)
{
rcount = 0;
if (client->GetFileDescriptor(client, rfds, &rcount) != True)
{
printf("Failed to get FreeRDP file descriptor\n");
break;
}
max_fds = 0;
FD_ZERO(&rfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
printf("select failed\n");
break;
}
}
if (client->CheckFileDescriptor(client) != True)
break;
}
client->Disconnect(client);
freerdp_peer_free(client);
printf("Client %s disconnected.\n", client->settings->hostname);
return NULL;
}
static void test_peer_accepted(freerdp_listener* instance, freerdp_peer* client)
{
pthread_t th;
pthread_create(&th, 0, test_peer_mainloop, client);
pthread_detach(th);
}
static void test_server_mainloop(freerdp_listener* instance)
{
int i;
int fds;
int max_fds;
int rcount;
void* rfds[32];
fd_set rfds_set;
memset(rfds, 0, sizeof(rfds));
while (1)
{
rcount = 0;
if (instance->GetFileDescriptor(instance, rfds, &rcount) != True)
{
printf("Failed to get FreeRDP file descriptor\n");
break;
}
max_fds = 0;
FD_ZERO(&rfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, NULL, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
printf("select failed\n");
break;
}
}
if (instance->CheckFileDescriptor(instance) != True)
{
printf("Failed to check FreeRDP file descriptor\n");
break;
}
}
instance->Close(instance);
}
int main(int argc, char* argv[])
{
freerdp_listener* instance;
instance = freerdp_listener_new();
instance->PeerAccepted = test_peer_accepted;
/* Open the server socket and start listening. */
if (instance->Open(instance, (argc > 1 ? argv[1] : NULL), 3389))
{
/* Entering the server main loop. In a real server the listener can be run in its own thread. */
test_server_mainloop(instance);
}
freerdp_listener_free(instance);
return 0;
}