boolean
fgsenddata (zdata, cdata)
char *zdata;
int cdata;
{
char *z;
int itt, iseg, csize;
unsigned short icheck;
itt = DATA;
csize = iGremote_packsize;
iseg = iGremote_segsize + 1;
if (cdata < iGremote_packsize)
{
/* If the remote packet size is larger than 64,
the default, we can assume they can handle a
smaller packet as well, which will be more
efficient to send. */
if (iGremote_packsize > 64)
{
/* The packet size is 1 << (iseg + 4). */
iseg = 1;
csize = 32;
while (csize < cdata)
{
csize <<= 1;
++iseg;
}
}
if (csize != cdata)
{
int cshort;
/* We have to move the data within the packet,
unfortunately. It only happens once per
file transfer. It would also be nice if we
computed the checksum as we move. We zero
out the unused bytes.
*/
itt = SHORTDATA;
cshort = csize - cdata;
if (cshort <= 127)
{
memmove (zdata + 1, zdata, cdata);
zdata[0] = (char) cshort;
memset (zdata + cdata + 1, 0, cshort - 1);
}
else
{
memmove (zdata + 2, zdata, cdata);
zdata[0] = (char) (0x80 | (cshort & 0x7f));
zdata[1] = (char) (cshort >> 7);
memset (zdata + cdata + 2, 0, cshort - 2);
}
}
}
z = zdata - CFRAMELEN;
z[IFRAME_DLE] = DLE;
z[IFRAME_K] = (char) iseg;
icheck = (unsigned short) igchecksum (zdata, csize);
/* Wait until there is room in the receiver's window
for us to send the packet. We do this now so that
we send the correct value for the last packet
received. Note that if iGsendseq == iGremote_ack,
this means that the sequence numbers are actually
8 apart, since the packet could not have been
acknowledged before it was sent; this can happen
when the window size is 7. */
while (iGsendseq == iGremote_ack
|| CSEQDIFF (iGsendseq, iGremote_ack) > iGremote_winsize)
{
if (! fgwait_for_packet (TRUE, cGtimeout,
cGretries))
return FALSE;
}
/* Ack all packets up to the next one, since the UUCP
protocol requires that all packets be acked in
order. */
while (CSEQDIFF (iGrecseq, iGlocal_ack) > 1)
{
iGlocal_ack = INEXTSEQ (iGlocal_ack);
if (! fgsend_control (RR, iGlocal_ack))
return FALSE;
}
iGlocal_ack = iGrecseq;
z[IFRAME__CONTROL] = (char) ((itt << 6) | (iGsendseq << 3) | iGrecseq);
iGsendseq = INEXTSEQ (iGsendseq);
icheck = ((unsigned short)
((0xaaaa - (icheck ^ (z[IFRAME_CONTROL] & 0xff))) & 0xffff));
z[IFRAME_CHECKLOW] = (char) (icheck & 0xff);
z[IFRAME_CHECKHIGH] = (char) (icheck >> 8);
z[IFRAME_XOR] = (char) (z[IFRAME_K] ^ z[IFRAME_CHECKLOW]
^ z[IFRAME_CHECKHIGH] ^ z[IFRAME_CONTROL]);
/* If we're waiting for acks of retransmitted
packets, then don't send this packet yet. The
other side may not be ready for it yet. Instead,
code infggot_ack will send the outstanding packets
when an ack is received. */
if (iGretransmit_seq != -1)
return TRUE;
return fsend_data (z, CFRAMELEN + csize, TRUE);
}
/* End of File */