rdesktop/iso.c
Matt Chapman e11a571f14 Committing some awesome progress I made while overseas - this commit
really embodies a huge number of changes. We are now able to talk quite
fluently to a French NT Terminal Server - in normal usage only minor
font issues remain (handling of TEXT2 order is not perfect).

The next major hurdle is encryption, and it will be quite a big hurdle
- there seems to be some quite nasty session key stuff.


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@8 423420c4-83ab-492f-b58f-81f9feb106b5
2000-07-25 12:34:29 +00:00

175 lines
3.8 KiB
C

/*
rdesktop: A Remote Desktop Protocol client.
Protocol services - ISO layer
Copyright (C) Matthew Chapman 1999-2000
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 "includes.h"
/* Establish a connection up to the ISO layer */
HCONN iso_connect(char *server)
{
HCONN conn;
uint8 code;
if ((conn = tcp_connect(server)) == NULL)
return NULL;
iso_send_msg(conn, ISO_PDU_CR);
if (!iso_recv_msg(conn, &code) || (code != ISO_PDU_CC))
{
ERROR("ISO error, expected CC\n");
tcp_disconnect(conn);
return NULL;
}
return conn;
}
/* Disconnect from the ISO layer */
void iso_disconnect(HCONN conn)
{
iso_send_msg(conn, ISO_PDU_DR);
tcp_disconnect(conn);
}
/* Send self-contained ISO message identified by code */
BOOL iso_send_msg(HCONN conn, uint8 code)
{
TPKT tpkt;
TPDU tpdu;
iso_make_tpkt(&tpkt, 11);
iso_io_tpkt(&conn->out, &tpkt);
iso_make_tpdu(&tpdu, code);
iso_io_tpdu(&conn->out, &tpdu);
MARK_END(conn->out);
return tcp_send(conn);
}
/* Receive a message on the ISO layer, return code */
BOOL iso_recv_msg(HCONN conn, uint8 *code)
{
TPDU tpdu;
TPKT tpkt;
BOOL res;
res = tcp_recv(conn, 4);
res = res ? iso_io_tpkt(&conn->in, &tpkt) : False;
res = res ? tcp_recv(conn, tpkt.length - 4) : False;
res = res ? iso_io_tpdu(&conn->in, &tpdu) : False;
*code = tpdu.code;
return res;
}
/* Initialise ISO transport data packet */
void iso_init(struct connection *conn)
{
PUSH_LAYER(conn->out, iso_offset, 7);
}
/* Receive ISO transport data packet */
BOOL iso_recv(HCONN conn)
{
uint8 code;
if (!iso_recv_msg(conn, &code) || (code != ISO_PDU_DT))
{
ERROR("ISO error, expected DT\n");
return False;
}
return True;
}
/* Receive ISO transport data packet */
BOOL iso_send(HCONN conn)
{
TPKT tpkt;
TPDU tpdu;
POP_LAYER(conn->out, iso_offset);
iso_make_tpkt(&tpkt, conn->out.end);
iso_io_tpkt(&conn->out, &tpkt);
iso_make_tpdu(&tpdu, ISO_PDU_DT);
iso_io_tpdu(&conn->out, &tpdu);
return tcp_send(conn);
}
/* Initialise a TPKT structure */
void iso_make_tpkt(TPKT *tpkt, int length)
{
tpkt->version = 3;
tpkt->reserved = 0;
tpkt->length = length;
}
/* Marshall/demarshall a TPKT structure */
BOOL iso_io_tpkt(STREAM s, TPKT *tpkt)
{
if (!prs_io_uint8(s, &tpkt->version))
return False;
if (tpkt->version != 3)
{
ERROR("Wrong TPKT version %d\n", tpkt->version);
return False;
}
if (!prs_io_uint8 (s, &tpkt->reserved))
return False;
if (!msb_io_uint16(s, &tpkt->length))
return False;
return True;
}
/* Initialise a TPDU structure */
void iso_make_tpdu(TPDU *tpdu, uint8 code)
{
tpdu->hlen = (code == ISO_PDU_DT) ? 2 : 6;
tpdu->code = code;
tpdu->dst_ref = tpdu->src_ref = 0;
tpdu->class = 0;
tpdu->eot = 0x80;
}
/* Marshall/demarshall a TPDU structure */
BOOL iso_io_tpdu(STREAM s, TPDU *tpdu)
{
BOOL res = True;
res = res ? prs_io_uint8 (s, &tpdu->hlen) : False;
res = res ? prs_io_uint8 (s, &tpdu->code) : False;
if (tpdu->code == ISO_PDU_DT)
{
res = res ? prs_io_uint8(s, &tpdu->eot) : False;
}
else
{
res = res ? msb_io_uint16(s, &tpdu->dst_ref) : False;
res = res ? msb_io_uint16(s, &tpdu->src_ref) : False;
res = res ? prs_io_uint8 (s, &tpdu->class ) : False;
}
return res;
}