home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscXmodem.m: spawn and control a thread performing a XMODEM file transfer
- // Written by Eric Norum Copyright (c) 1994 by Eric Norum.
- // Version 1.0. All rights reserved.
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the author
- // and its use is governed by the MiscKit license, found in the file
- // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
-
- /*
- * Xmodem file transfer
- *
- * Based on ``XMODEM/YMODEM PROTOCOL REFERENCE -- A compendium of documents
- * describing the XMODEM and YMODEM File Transfer Protocols'', Chuck Forsberg,
- * Omen Technology Incorporated, Portland, Oregon, 1988.
- */
- #import <misckit/misckit.h>
- /* #import "MiscXmodem.h" /* */
-
- /*
- * All timeouts are in seconds
- */
- #define TRANSMIT_TIMEOUT 60
- #define TRANSMIT_BAD_NAK_LIMIT 5
- #define RECEIVE_PACKET_TIMEOUT 10
- #define RECEIVE_CHARACTER_TIMEOUT 1
- #define RECEIVE_CRC_ADAPT_TIMEOUT 3
- #define RECEIVE_PACKET_RETRY_LIMIT 6
- #define RECEIVE_CRC_ADAPT_RETRY_LIMIT 7
-
- #define SOH '\001'
- #define STX '\002'
- #define EOT '\004'
- #define ACK '\006'
- #define NAK '\025'
- #define CTRLZ '\032'
- #define CRC_NAK 'C'
-
- #define MESSAGETYPE_HAVE_PACKET 0
- #define MESSAGETYPE_WANT_PACKET 1
- #define MESSAGETYPE_RETRY 2
- #define MESSAGETYPE_FINAL 3
-
- #define MAX_REPLY_SIZE 200
-
- struct packetMessage {
- msg_header_t h;
- };
-
- struct retryMessage {
- msg_header_t h;
- msg_type_t t1;
- int retry;
- };
-
- struct finalMessage {
- msg_header_t h;
- msg_type_t t1;
- char cbuf[1];
- };
-
- /*
- * See makecrc.c for details.
- */
- #define UPDATE_CRC(c,crc) (crctab[(((crc)>>8) & 0xFF)] ^ (((crc)<<8) | (c)))
- static const unsigned short crctab[256] = {
- 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
- 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
- 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
- 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
- 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
- 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
- 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
- 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
- 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
- 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
- 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
- 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
- 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
- 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
- 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
- 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
- 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
- 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
- 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
- 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
- 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
- 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
- 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
- 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
- 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
- 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
- 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
- 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
- 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
- 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
- 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
- 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
- };
-
- @implementation MiscXmodem
-
- /*
- * Send a message to the `top end'
- */
- static void
- sendPacketMessage (struct MiscXmodem *p, int type)
- {
- struct packetMessage msg;
- kern_return_t r;
-
- msg.h.msg_id = type;
- msg.h.msg_size = sizeof msg;
- msg.h.msg_simple = TRUE;
- msg.h.msg_type = MSG_TYPE_NORMAL;
- msg.h.msg_remote_port = p->messagePort;
- msg.h.msg_local_port = p->replyPort;
-
- r = msg_send ((msg_header_t *)&msg, MSG_OPTION_NONE, 0);
- if (r != SEND_SUCCESS)
- cthread_exit (NULL);
-
- /*
- * Wait for the top end to finish with the packet
- */
- r = msg_receive ((msg_header_t *)&msg, MSG_OPTION_NONE, 0);
- if (r != RCV_SUCCESS)
- cthread_exit (NULL);
- }
-
- static void
- sendRetryMessage (struct MiscXmodem *p, int retryNumber)
- {
- struct retryMessage msg;
- kern_return_t r;
-
- msg.h.msg_id = MESSAGETYPE_RETRY;
- msg.h.msg_size = sizeof msg;
- msg.h.msg_simple = TRUE;
- msg.h.msg_type = MSG_TYPE_NORMAL;
- msg.h.msg_remote_port = p->messagePort;
- msg.h.msg_local_port = PORT_NULL;
-
- msg.t1.msg_type_name = MSG_TYPE_INTEGER_32;
- msg.t1.msg_type_size = 32;
- msg.t1.msg_type_inline = TRUE;
- msg.t1.msg_type_longform = FALSE;
- msg.t1.msg_type_deallocate = FALSE;
- msg.retry = retryNumber;
-
- r = msg_send ((msg_header_t *)&msg, MSG_OPTION_NONE, 0);
- if (r != SEND_SUCCESS)
- cthread_exit (NULL);
- }
-
- static void
- sendFinalMessage (struct MiscXmodem *p, char *aString)
- {
- int length, size;
- struct finalMessage *msgp;
-
- length = strlen (aString) + 1;
- size = sizeof *msgp - 1 + length;
- msgp = alloca (size);
- msgp->h.msg_id = MESSAGETYPE_FINAL;
- msgp->h.msg_size = size;
- msgp->h.msg_simple = TRUE;
- msgp->h.msg_type = MSG_TYPE_NORMAL;
- msgp->h.msg_remote_port = p->messagePort;
- msgp->h.msg_local_port = PORT_NULL;
-
- msgp->t1.msg_type_name = MSG_TYPE_STRING;
- msgp->t1.msg_type_size = 8 * length;
- msgp->t1.msg_type_inline = TRUE;
- msgp->t1.msg_type_longform = FALSE;
- msgp->t1.msg_type_deallocate = FALSE;
- strcpy (msgp->cbuf, aString);
-
- msg_send ((msg_header_t *)msgp, MSG_OPTION_NONE, 0);
- cthread_exit (0);
- }
-
- /*
- * Report a failed system call
- */
- static void
- failedSysCall (struct MiscXmodem *p, const char *aString)
- {
- char cbuf[200];
-
- sprintf (cbuf, "%s failed: %s", aString, strerror (cthread_errno ()));
- sendFinalMessage (p, cbuf);
- }
-
- /*
- * Get characters from TTY
- */
- static BOOL
- readWithTimeout(struct MiscXmodem *p, unsigned char *cp, int length, int seconds)
- {
- int i;
- struct timeval tv;
- fd_set readFdSet;
-
- while (length) {
- tv.tv_usec = 0;
- tv.tv_sec = seconds;
- readFdSet = p->checkFdSet;
- i = select (p->fd+1, &readFdSet, NULL, NULL, &tv);
- if (i < 0)
- failedSysCall (p, "Select");
- if (i == 0)
- return (NO);
- i = read (p->fd, cp, length);
- if (i < 0)
- failedSysCall (p, "Read");
- if (i == 0)
- sendFinalMessage (p, "Unexpected EOF");
- cp += i;
- length -= i;
- }
- return YES;
- }
-
- static int
- getCharacterWithTimeout(struct MiscXmodem *p, int seconds)
- {
- unsigned char c;
-
- if (readWithTimeout (p, &c, 1, seconds) == NO)
- return EOF;
- return c;
- }
-
- /*
- * Clean out TTY read queue
- */
- static void
- flushTTY (struct MiscXmodem *p)
- {
- while (getCharacterWithTimeout (p, 1) != EOF)
- continue;
- }
-
- /*
- * Send a character
- */
- static void
- sendChar (struct MiscXmodem *p, unsigned char c)
- {
- if (write (p->fd, &c, 1) != 1)
- failedSysCall (p, "Character write");
- }
-
- static int
- computePacketSize (struct MiscXmodem *p)
- {
- switch (p->packetBuffer[0]) {
- case SOH:
- return 3 + 128 + (p->useCRC ? 2 : 1);
- break;
-
- case STX:
- return 3 + 1024 + (p->useCRC ? 2 : 1);
- break;
-
- case EOT:
- return 1;
- break;
-
- default:
- return 0;
- }
- }
-
- /*
- * Get packet
- */
- static BOOL
- getPacket (struct MiscXmodem *p)
- {
- int c;
- int nleft;
-
- c = EOF;
- if (p->isDynamicCheckPacket) {
- int pass;
- for (pass = 0 ; pass < RECEIVE_CRC_ADAPT_RETRY_LIMIT ; pass++) {
- sendChar (p, CRC_NAK);
- c = getCharacterWithTimeout (p, RECEIVE_CRC_ADAPT_TIMEOUT);
- if (c != EOF)
- break;
- }
- p->isDynamicCheckPacket = NO;
- if (c == EOF) {
- p->useCRC = NO;
- sendChar (p, NAK);
- }
- }
- if (c == EOF) {
- c = getCharacterWithTimeout (p, RECEIVE_PACKET_TIMEOUT);
- if (c == EOF)
- return NO;
- }
- p->packetBuffer[0] = c;
- nleft = computePacketSize (p) - 1;
- if (nleft < 0)
- return NO;
- if (readWithTimeout (p, p->packetBuffer+1, nleft, RECEIVE_CHARACTER_TIMEOUT) == NO)
- return NO;
- return YES;
- }
-
- /*
- * Compute checksum/CRC
- */
- static void
- computeChecksum (unsigned char *result, unsigned char *cp, int length)
- {
- int checksum = 0;
-
- while (length--)
- checksum += *cp++;
- *result = checksum;
- }
-
- static void
- computeCRC (unsigned char *hi, unsigned char *lo, unsigned char *cp, int length)
- {
- int crc = 0;
-
- while (length--) {
- unsigned char c = *cp++;
- crc = UPDATE_CRC (c, crc);
- }
- *hi = crc >> 8;
- *lo = crc;
- }
-
- /*
- * Check that packet is valid
- */
- static BOOL
- verifyPacket (struct MiscXmodem *p)
- {
- unsigned char *cp = p->packetBuffer;
- int dataCount;
- int packetNumber;
-
- switch (*cp) {
- default:
- return NO;
-
- case EOT:
- return YES;
-
- case SOH:
- dataCount = 128;
- break;
-
- case STX:
- dataCount = 1024;
- break;
- }
- cp++;
- packetNumber = *cp;
- if (packetNumber != (~*(cp+1) & 0xFF))
- return NO;
- if (packetNumber == p->lastPacketNumber)
- return YES;
- if (p->lastPacketNumber < 0)
- p->lastPacketNumber = 0;
- if (packetNumber != ((p->lastPacketNumber + 1) & 0xFF))
- return NO;
- cp += 2;
- if (p->useCRC) {
- unsigned char lo, hi;
- computeCRC (&hi, &lo, cp, dataCount+2);
- if (hi || lo)
- return NO;
- }
- else {
- unsigned char checksum;
- computeChecksum (&checksum, cp, dataCount);
- cp += dataCount;
- if (*cp != checksum)
- return NO;
- }
- p->lastPacketNumber = packetNumber;
- return YES;
- }
-
- /*
- * Xmodem thread entry point to receive data
- */
- static void *
- getFile (void *ap)
- {
- struct MiscXmodem *p = (struct MiscXmodem *)ap;
- int retry;
-
- for (;;) {
- retry = 0;
- for (;;) {
- if (retry != 0)
- sendRetryMessage (p, retry);
- if (getPacket (p) && verifyPacket (p)) {
- sendChar (p, ACK);
- if (p->packetBuffer[0] == EOT)
- sendFinalMessage (p, "");
- sendPacketMessage (p, MESSAGETYPE_HAVE_PACKET);
- break;
- }
- if (retry++ == RECEIVE_PACKET_RETRY_LIMIT)
- sendFinalMessage (p, "Too many bad packetts");
- flushTTY (p);
- sendChar (p, NAK);
- }
- }
- }
-
- /*
- * Send packet
- */
- static void
- sendPacket (struct MiscXmodem *p)
- {
- int pksize;
- int retry;
- int badNakCount;
-
- pksize = computePacketSize (p);
- if (pksize > 1) {
- p->packetBuffer[1] = ++p->lastPacketNumber;
- p->packetBuffer[2] = ~p->packetBuffer[1];
- if (p->useCRC) {
- p->packetBuffer[pksize-2] = 0;
- p->packetBuffer[pksize-1] = 0;
- computeCRC (p->packetBuffer+pksize-2, p->packetBuffer+pksize-1,
- p->packetBuffer+3, pksize-3);
- }
- else {
- computeChecksum (p->packetBuffer+pksize-1, p->packetBuffer+3, pksize-3);
- }
- }
- retry = 0;
- badNakCount = 0;
- for (;;) {
- if (write (p->fd, p->packetBuffer, pksize) != pksize)
- failedSysCall (p, "Packet write");
- switch (getCharacterWithTimeout (p, TRANSMIT_TIMEOUT)) {
- case EOF:
- sendFinalMessage (p, "Timed out waiting for reply");
-
- case ACK:
- return;
-
- case NAK:
- badNakCount = 0;
- break;
-
- default:
- if (++badNakCount == TRANSMIT_BAD_NAK_LIMIT)
- sendFinalMessage (p, "Too many bad NAK's");
- break;
- }
- sendRetryMessage (p, ++retry);
- }
- }
-
- /*
- * Wait for receiver to start
- */
- static void
- awaitReceiver (struct MiscXmodem *p)
- {
- for (;;) {
- switch (getCharacterWithTimeout (p, TRANSMIT_TIMEOUT)) {
- case EOF:
- sendFinalMessage (p, "Timed out waiting for receiver to start");
-
- case NAK:
- p->useCRC = NO;
- return;
-
- case CRC_NAK:
- p->useCRC = YES;
- return;
- }
- }
- }
-
- /*
- * Xmodem thread entry point to send data
- */
- static void *
- putFile (void *ap)
- {
- struct MiscXmodem *p = (struct MiscXmodem *)ap;
-
- p->lastPacketNumber = 0;
- awaitReceiver (p);
- sendPacketMessage (p, MESSAGETYPE_WANT_PACKET);
- for (;;) {
- sendPacket (p);
- if (p->packetBuffer[0] == EOT)
- sendFinalMessage (p, "");
- sendPacketMessage (p, MESSAGETYPE_WANT_PACKET);
- }
- }
-
- /*
- * `Top End' routines
- */
- - (void)sendSmallPacket
- {
- int ncopy;
-
- if (smallPacketCount >= 128)
- ncopy = 128;
- else
- ncopy = smallPacketCount;
- packetBuffer[0] = SOH;
- memcpy (packetBuffer+3, smallPacketData+smallPacketIndex, ncopy);
- if (ncopy < 128)
- memset (packetBuffer+3+ncopy, CTRLZ, 128-ncopy);
- smallPacketIndex += ncopy;
- smallPacketCount -= ncopy;
- kbytes += 128.0 / 1024.0;
- }
-
- /*
- * Handle message from the file transfer thread
- */
- - (void)handleMessage:(msg_header_t *)msg
- {
- kern_return_t r;
-
- switch (msg->msg_id) {
- case MESSAGETYPE_HAVE_PACKET:
- {
- struct packetMessage *msgp = (struct packetMessage *)msg;
- int count = ((packetBuffer[0] == SOH) ? 128 : 1024);
-
- goodPacketCount++;
- kbytes += (float)count / 1024.0;
- if (isText) {
- unsigned char *cp = packetBuffer + 3;
-
- while (count--) {
- if (*cp == CTRLZ)
- break;
- if (*cp != '\r')
- NXPutc (stream, *cp);
- cp++;
- }
- }
- else {
- NXWrite (stream, packetBuffer+3, count);
- }
- msgp->h.msg_local_port = PORT_NULL;
- r = msg_send ((msg_header_t *)msgp, MSG_OPTION_NONE, 0);
- if (r != SEND_SUCCESS)
- abort ();
- if ([delegate respondsTo:@selector(didTransferPacket:kbytes:)])
- [delegate didTransferPacket:goodPacketCount kbytes:kbytes];
- }
- break;
-
- case MESSAGETYPE_WANT_PACKET:
- {
- struct packetMessage *msgp = (struct packetMessage *)msg;
- int nread;
- int fullPacketSize = use1kPackets ? 1024 : 128;
- if (goodPacketCount && [delegate respondsTo:@selector(didTransferPacket:kbytes:)])
- [delegate didTransferPacket:goodPacketCount kbytes:kbytes];
- if (smallPacketCount) {
- [self sendSmallPacket];
- }
- else {
- if (isText) {
- unsigned char *cp = packetBuffer + 3;
- int c;
-
- nread = 0;
- while (nread < fullPacketSize) {
- if (newlineFlag) {
- c = '\n';
- newlineFlag = NO;
- }
- else {
- c = NXGetc (stream);
- if (c == '\n') {
- newlineFlag = YES;
- c = '\r';
- }
- }
- if (c == EOF)
- break;
- *cp++ = c;
- nread++;
- }
- }
- else {
- nread = NXRead (stream, packetBuffer+3, fullPacketSize);
- }
- if (nread == 0) {
- packetBuffer[0] = EOT;
- }
- else if (nread == fullPacketSize) {
- packetBuffer[0] = use1kPackets ? STX : SOH;
- kbytes += use1kPackets ? 1.0 : 1.0 / 8.0;
- }
- else {
- smallPacketIndex = 0;
- smallPacketCount = nread;
- memcpy (smallPacketData, packetBuffer+3, nread);
- [self sendSmallPacket];
- }
- }
- msgp->h.msg_local_port = PORT_NULL;
- r = msg_send ((msg_header_t *)msgp, MSG_OPTION_NONE, 0);
- if (r != SEND_SUCCESS)
- abort ();
- goodPacketCount++;
- }
- break;
-
- case MESSAGETYPE_RETRY:
- {
- struct retryMessage *msgp = (struct retryMessage *)msg;
- if ([delegate respondsTo:@selector(didRetryNumber:)])
- [delegate didRetryNumber:msgp->retry];
- }
- break;
-
- case MESSAGETYPE_FINAL:
- {
- struct finalMessage *msgp = (struct finalMessage *)msg;
- DPSRemovePort (messagePort);
- port_deallocate (task_self(), messagePort);
- port_deallocate (task_self(), replyPort);
- cthread_join (xmodemThread);
- isActive = NO;
- if ([delegate respondsTo:@selector(didFinish:)])
- [delegate didFinish:msgp->cbuf];
- }
- if (serialPortWasSuspended == NO)
- [serialPort resume];
- break;
- }
- }
-
- /*
- * Get message from `Bottom end'
- */
- static void
- messageHandler (msg_header_t *msg, void *ap)
- {
- [(MiscXmodem *)ap handleMessage:msg];
- }
-
- /*
- * Transfer file in appropriate direction
- */
- - transferBetweenStream:(NXStream *)aStream serialPort:aSerialPort toStream:(BOOL)toStream
- {
- if (isActive)
- return nil;
- if (isDynamicCheck) {
- useCRC = YES;
- isDynamicCheckPacket = YES;
- }
- else {
- isDynamicCheckPacket = NO;
- }
- isActive = YES;
- newlineFlag = NO;
- lastPacketNumber = -1;
- goodPacketCount = 0;
- smallPacketIndex = smallPacketCount = 0;
- kbytes = 0;
-
- stream = aStream;
- serialPort = aSerialPort;
- if ((serialPortWasSuspended = [serialPort suspended]) == NO)
- [serialPort suspend];
- fd = [serialPort filedes];
- FD_ZERO (&checkFdSet);
- FD_SET (fd, &checkFdSet);
-
- port_allocate (task_self(), &messagePort);
- port_allocate (task_self(), &replyPort);
- DPSAddPort (messagePort, messageHandler, MAX_REPLY_SIZE, self, NX_BASETHRESHOLD);
- if (toStream)
- xmodemThread = cthread_fork (getFile, self);
- else
- xmodemThread = cthread_fork (putFile, self);
- return self;
- }
-
- - sendToStream:(NXStream *)aStream fromSerialPort:aSerialPort
- {
- return [self transferBetweenStream:aStream serialPort:aSerialPort toStream:YES];
- }
-
- - sendToSerialPort:aSerialPort fromStream:(NXStream *)aStream
- {
- return [self transferBetweenStream:aStream serialPort:aSerialPort toStream:NO];
- }
-
- - init
- {
- [super init];
- isText = YES;
- use1kPackets = YES;
- isDynamicCheck = YES;
- useCRC = YES;
- return self;
- }
-
- - free
- {
- if (isActive) {
- DPSRemovePort (messagePort);
- port_deallocate (task_self(), messagePort);
- port_deallocate (task_self(), replyPort);
-
- /*
- * I hope this works. I wish they had supplied `cthread_terminate'.
- */
- cthread_abort (xmodemThread);
- cthread_join (xmodemThread);
-
- if (serialPortWasSuspended == NO)
- [serialPort resume];
- }
- [super free];
- return self;
- }
-
- - setFileTypeText:(BOOL)flag { isText = flag; return self; }
- - xmodemSet1kPackets:(BOOL)flag { use1kPackets = flag; return self; }
- - xmodemSetCheckTypeDynamic:(BOOL)flag { isDynamicCheck = flag; return self; }
- - xmodemSetCheckTypeCRC:(BOOL)flag { useCRC = flag; return self; }
- - (BOOL)xmodemIsActive { return isActive; }
- - (BOOL)xmodemIsFileTypeText { return isText; }
- - (BOOL)xmodemIs1kPackets { return use1kPackets; }
- - (BOOL)xmodemIsCheckTypeDynamic { return isDynamicCheck; }
- - (BOOL)xmodemIsCheckTypeCRC { return useCRC; }
-
- /*
- * Delegate methods
- */
- - setDelegate:id
- {
- delegate = id;
- return self;
- }
-
- - delegate
- {
- return delegate;
- }
-
- - didTransferPacket:(int)anInt kbytes:(float)aFloat { return self; }
- - didRetryNumber:(int)anInt { return self; }
- - didFinish:(const char *)failureCode { return self; }
-
- @end
-