]> git.sesse.net Git - rdpsrv/blobdiff - rdp.c
Pull in rdp.c from rdesktop, use rdp_recv().
[rdpsrv] / rdp.c
diff --git a/rdp.c b/rdp.c
new file mode 100644 (file)
index 0000000..1663dfd
--- /dev/null
+++ b/rdp.c
@@ -0,0 +1,193 @@
+/* -*- c-basic-offset: 8 -*-
+   rdesktop: A Remote Desktop Protocol client.
+   Protocol services - RDP layer
+   Copyright (C) Matthew Chapman 1999-2002
+
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <time.h>
+#include "rdesktop.h"
+
+extern uint16 g_mcs_userid;
+extern char g_username[16];
+extern BOOL g_bitmap_compression;
+extern BOOL g_orders;
+BOOL g_encryption = 0;
+extern BOOL g_desktop_save;
+extern BOOL g_use_rdp5;
+extern uint16 g_server_rdp_version;
+extern int g_server_bpp;
+
+uint8 *g_next_packet;
+uint32 g_rdp_shareid;
+
+#if WITH_DEBUG
+static uint32 g_packetno;
+#endif
+
+/* Receive an RDP packet */
+STREAM
+rdp_recv(uint8 * type)
+{
+       static STREAM rdp_s;
+       uint16 length, pdu_type;
+
+       if ((rdp_s == NULL) || (g_next_packet >= rdp_s->end))
+       {
+               rdp_s = sec_recv();
+               if (rdp_s == NULL)
+                       return NULL;
+
+               g_next_packet = rdp_s->p;
+       }
+       else
+       {
+               rdp_s->p = g_next_packet;
+       }
+
+       in_uint16_le(rdp_s, length);
+       /* 32k packets are really 8, keepalive fix */
+       if (length == 0x8000)
+       {
+               g_next_packet += 8;
+               *type = 0;
+               return rdp_s;
+       }
+       in_uint16_le(rdp_s, pdu_type);
+       in_uint8s(rdp_s, 2);    /* userid */
+       *type = pdu_type & 0xf;
+
+#if WITH_DEBUG
+       DEBUG(("RDP packet #%d, (type %x)\n", ++g_packetno, *type));
+       hexdump(g_next_packet, length);
+#endif /*  */
+
+       g_next_packet += length;
+       return rdp_s;
+}
+
+/* Initialise an RDP data packet */
+static STREAM
+rdp_init_data(int maxlen)
+{
+       STREAM s;
+
+       s = sec_init(g_encryption ? SEC_ENCRYPT : 0, maxlen + 18);
+       s_push_layer(s, rdp_hdr, 18);
+
+       return s;
+}
+
+/* Send an RDP data packet */
+static void
+rdp_send_data(STREAM s, uint8 data_pdu_type)
+{
+       uint16 length;
+
+       s_pop_layer(s, rdp_hdr);
+       length = s->end - s->p;
+
+       out_uint16_le(s, length);
+       out_uint16_le(s, (RDP_PDU_DATA | 0x10));
+       out_uint16_le(s, (g_mcs_userid + 1001));
+
+       out_uint32_le(s, g_rdp_shareid);
+       out_uint8(s, 0);        /* pad */
+       out_uint8(s, 1);        /* streamid */
+       out_uint16_le(s, (length - 14));
+       out_uint8(s, data_pdu_type);
+       out_uint8(s, 0);        /* compress_type */
+       out_uint16(s, 0);       /* compress_len */
+
+       sec_send(s, g_encryption ? SEC_ENCRYPT : 0);
+}
+
+/* Output a string in Unicode */
+void
+rdp_out_unistr(STREAM s, char *string, int len)
+{
+       int i = 0, j = 0;
+
+       len += 2;
+
+       while (i < len)
+       {
+               s->p[i++] = string[j++];
+               s->p[i++] = 0;
+       }
+
+       s->p += len;
+}
+
+
+/* Send a control PDU */
+static void
+rdp_send_control(uint16 action)
+{
+       STREAM s;
+
+       s = rdp_init_data(8);
+
+       out_uint16_le(s, action);
+       out_uint16(s, 0);       /* userid */
+       out_uint32(s, 0);       /* control id */
+
+       s_mark_end(s);
+       rdp_send_data(s, RDP_DATA_PDU_CONTROL);
+}
+
+/* Send a synchronisation PDU */
+static void
+rdp_send_synchronise(void)
+{
+       STREAM s;
+
+       s = rdp_init_data(4);
+
+       out_uint16_le(s, 1);    /* type */
+       out_uint16_le(s, 1002);
+
+       s_mark_end(s);
+       rdp_send_data(s, RDP_DATA_PDU_SYNCHRONISE);
+}
+
+/* Send a single input event */
+void
+rdp_send_input(uint32 time, uint16 message_type, uint16 device_flags, uint16 param1, uint16 param2)
+{
+       STREAM s;
+
+       s = rdp_init_data(16);
+
+       out_uint16_le(s, 1);    /* number of events */
+       out_uint16(s, 0);       /* pad */
+
+       out_uint32_le(s, time);
+       out_uint16_le(s, message_type);
+       out_uint16_le(s, device_flags);
+       out_uint16_le(s, param1);
+       out_uint16_le(s, param2);
+
+       s_mark_end(s);
+       rdp_send_data(s, RDP_DATA_PDU_INPUT);
+}
+
+/* Disconnect from the RDP layer */
+void
+rdp_disconnect(void)
+{
+       sec_disconnect();
+}