491 lines
10 KiB
C
491 lines
10 KiB
C
|
/** _
|
||
|
** (_)_ __ __ ___ _ __ _ __
|
||
|
** | | ' \/ _/ _ \ ' \| ' \
|
||
|
** |_|_|_|_\__\___/_|_|_|_|_|_|
|
||
|
**
|
||
|
** Copyright (C) 2003-2005, Claudio Leite
|
||
|
** All rights reserved.
|
||
|
**
|
||
|
** Please see the file 'COPYING' for licensing information.
|
||
|
**/
|
||
|
|
||
|
#include "imcomm.h"
|
||
|
|
||
|
extern int endianness;
|
||
|
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
extern short refnum;
|
||
|
|
||
|
OSErr
|
||
|
mactcp_recv(void *handle, char *inbuf, size_t len)
|
||
|
{
|
||
|
TCPiopb pb;
|
||
|
OSErr err;
|
||
|
size_t dataRead = 0;
|
||
|
|
||
|
pb.ioCRefNum = refnum;
|
||
|
pb.csCode = TCPRcv;
|
||
|
pb.tcpStream = ((IMCOMM *) handle)->s;
|
||
|
pb.csParam.receive.commandTimeoutValue = 2;
|
||
|
pb.csParam.receive.rcvBuff = inbuf;
|
||
|
pb.csParam.receive.rcvBuffLen = len;
|
||
|
pb.csParam.receive.userDataPtr = (Ptr) handle;
|
||
|
err = PBControlSync((ParmBlkPtr) & pb);
|
||
|
if (err != noErr)
|
||
|
return err;
|
||
|
|
||
|
return noErr;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
#ifndef SEND_QUEUES
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
flap_send(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
|
||
|
{
|
||
|
pkt_t *outpacket;
|
||
|
size_t totallen;
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
TCPiopb pb;
|
||
|
wdsEntry wds[2];
|
||
|
OSErr err;
|
||
|
#endif
|
||
|
|
||
|
totallen = len + 6;
|
||
|
outpacket = pkt_init(totallen);
|
||
|
|
||
|
pkt_add8(outpacket, 0x2A);
|
||
|
pkt_add8(outpacket, channel);
|
||
|
pkt_add16(outpacket, ((IMCOMM *) handle)->seqnum);
|
||
|
pkt_add16(outpacket, (uint16_t) len);
|
||
|
pkt_addraw(outpacket, packet, len);
|
||
|
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
wds[0].length = outpacket->len;
|
||
|
wds[0].ptr = (char *) outpacket->data;
|
||
|
wds[1].length = 0;
|
||
|
|
||
|
pb.ioCRefNum = refnum;
|
||
|
pb.csCode = TCPSend;
|
||
|
pb.tcpStream = ((IMCOMM *) handle)->s;
|
||
|
pb.csParam.send.validityFlags = 0;
|
||
|
pb.csParam.send.pushFlag = TRUE;
|
||
|
pb.csParam.send.urgentFlag = 0;
|
||
|
pb.csParam.send.wdsPtr = (Ptr) wds;
|
||
|
pb.csParam.send.userDataPtr = (Ptr) handle;
|
||
|
err = PBControlSync((ParmBlkPtr) & pb);
|
||
|
#else
|
||
|
if (send
|
||
|
(((IMCOMM *) handle)->socket, outpacket->data, outpacket->len,
|
||
|
0) < 0) {
|
||
|
pkt_free(outpacket);
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (((IMCOMM *) handle)->seqnum < 0xFFFF)
|
||
|
((IMCOMM *) handle)->seqnum++;
|
||
|
else
|
||
|
((IMCOMM *) handle)->seqnum = 0;
|
||
|
|
||
|
if (updateidle == 1) {
|
||
|
((IMCOMM *) handle)->last_operation_time = time(NULL);
|
||
|
if (((IMCOMM *) handle)->isidle == 1)
|
||
|
imcomm_set_idle_time(handle, 0);
|
||
|
}
|
||
|
pkt_free(outpacket);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
struct MultiPacket *
|
||
|
MultiPktInit(void)
|
||
|
{
|
||
|
struct MultiPacket *npkt;
|
||
|
|
||
|
npkt = malloc(sizeof(struct MultiPacket));
|
||
|
npkt->init = -1;
|
||
|
return npkt;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
MultiPktFree(struct MultiPacket * h)
|
||
|
{
|
||
|
struct MultiPacket *trav, *tmp;
|
||
|
|
||
|
for (trav = h; trav != NULL;) {
|
||
|
free(trav->packet);
|
||
|
tmp = trav;
|
||
|
trav = trav->next;
|
||
|
free(tmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
void
|
||
|
flap_addToMulti(struct MultiPacket * mpkt, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
|
||
|
{
|
||
|
struct MultiPacket *trav, *npkt;
|
||
|
int first;
|
||
|
|
||
|
if (mpkt->init == -1) {
|
||
|
npkt = mpkt;
|
||
|
first = 1;
|
||
|
} else {
|
||
|
npkt = malloc(sizeof(struct MultiPacket));
|
||
|
first = 0;
|
||
|
}
|
||
|
|
||
|
npkt->channel = channel;
|
||
|
npkt->packet = malloc(len);
|
||
|
memcpy(npkt->packet, packet, len);
|
||
|
npkt->len = len;
|
||
|
npkt->updateidle = updateidle;
|
||
|
npkt->next = NULL;
|
||
|
npkt->init = 1;
|
||
|
|
||
|
if (!first) {
|
||
|
for (trav = mpkt; trav->next != NULL; trav = trav->next);
|
||
|
trav->next = npkt;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
flap_sendMulti(void *handle, struct MultiPacket * pktlist)
|
||
|
{
|
||
|
pkt_t *outpacket;
|
||
|
size_t totallen;
|
||
|
struct MultiPacket *trav;
|
||
|
int updateidle = 0;
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
TCPiopb pb;
|
||
|
wdsEntry wds[2];
|
||
|
OSErr err;
|
||
|
#endif
|
||
|
|
||
|
for (trav = pktlist, totallen = 0; trav != NULL; trav = trav->next) {
|
||
|
totallen += 6 + trav->len;
|
||
|
if (trav->updateidle == 1)
|
||
|
updateidle = 1;
|
||
|
}
|
||
|
|
||
|
outpacket = pkt_init(totallen);
|
||
|
|
||
|
for (trav = pktlist; trav != NULL; trav = trav->next) {
|
||
|
pkt_add8(outpacket, 0x2A);
|
||
|
pkt_add8(outpacket, trav->channel);
|
||
|
pkt_add16(outpacket, ((IMCOMM *) handle)->seqnum);
|
||
|
pkt_add16(outpacket, (uint16_t) trav->len);
|
||
|
pkt_addraw(outpacket, trav->packet, trav->len);
|
||
|
|
||
|
if (((IMCOMM *) handle)->seqnum < 0xFFFF)
|
||
|
((IMCOMM *) handle)->seqnum++;
|
||
|
else
|
||
|
((IMCOMM *) handle)->seqnum = 0;
|
||
|
}
|
||
|
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
wds[0].length = outpacket->len;
|
||
|
wds[0].ptr = (char *) outpacket->data;
|
||
|
wds[1].length = 0;
|
||
|
|
||
|
pb.ioCRefNum = refnum;
|
||
|
pb.csCode = TCPSend;
|
||
|
pb.tcpStream = ((IMCOMM *) handle)->s;
|
||
|
pb.csParam.send.validityFlags = 0;
|
||
|
pb.csParam.send.pushFlag = TRUE;
|
||
|
pb.csParam.send.urgentFlag = 0;
|
||
|
pb.csParam.send.wdsPtr = (Ptr) wds;
|
||
|
pb.csParam.send.userDataPtr = (Ptr) handle;
|
||
|
err = PBControlSync((ParmBlkPtr) & pb);
|
||
|
#else
|
||
|
if (send
|
||
|
(((IMCOMM *) handle)->socket, outpacket->data, outpacket->len,
|
||
|
0) < 0) {
|
||
|
pkt_free(outpacket);
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
}
|
||
|
#endif
|
||
|
if (updateidle == 1) {
|
||
|
((IMCOMM *) handle)->last_operation_time = time(NULL);
|
||
|
if (((IMCOMM *) handle)->isidle == 1)
|
||
|
imcomm_set_idle_time(handle, 0);
|
||
|
}
|
||
|
pkt_free(outpacket);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
flap_sendAct(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
|
||
|
{
|
||
|
pkt_t *outpacket;
|
||
|
size_t totallen;
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
TCPiopb pb;
|
||
|
wdsEntry wds[2];
|
||
|
OSErr err;
|
||
|
#endif
|
||
|
|
||
|
totallen = len + 6;
|
||
|
outpacket = pkt_init(totallen);
|
||
|
|
||
|
pkt_add8(outpacket, 0x2A);
|
||
|
pkt_add8(outpacket, channel);
|
||
|
pkt_add16(outpacket, ((IMCOMM *) handle)->seqnum);
|
||
|
pkt_add16(outpacket, (uint16_t) len);
|
||
|
pkt_addraw(outpacket, packet, len);
|
||
|
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
wds[0].length = outpacket->len;
|
||
|
wds[0].ptr = (char *) outpacket->data;
|
||
|
wds[1].length = 0;
|
||
|
|
||
|
pb.ioCRefNum = refnum;
|
||
|
pb.csCode = TCPSend;
|
||
|
pb.tcpStream = ((IMCOMM *) handle)->s;
|
||
|
pb.csParam.send.validityFlags = 0;
|
||
|
pb.csParam.send.pushFlag = TRUE;
|
||
|
pb.csParam.send.urgentFlag = 0;
|
||
|
pb.csParam.send.wdsPtr = (Ptr) wds;
|
||
|
pb.csParam.send.userDataPtr = (Ptr) handle;
|
||
|
err = PBControlSync((ParmBlkPtr) & pb);
|
||
|
#else
|
||
|
if (send
|
||
|
(((IMCOMM *) handle)->socket, outpacket->data, outpacket->len,
|
||
|
0) < 0) {
|
||
|
pkt_free(outpacket);
|
||
|
return IMCOMM_RET_ERROR;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (((IMCOMM *) handle)->seqnum < 0xFFFF)
|
||
|
((IMCOMM *) handle)->seqnum++;
|
||
|
else
|
||
|
((IMCOMM *) handle)->seqnum = 0;
|
||
|
|
||
|
if (updateidle == 1) {
|
||
|
((IMCOMM *) handle)->last_operation_time = time(NULL);
|
||
|
if (((IMCOMM *) handle)->isidle == 1)
|
||
|
imcomm_set_idle_time(handle, 0);
|
||
|
}
|
||
|
pkt_free(outpacket);
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
flap_sendnext(void *handle)
|
||
|
{
|
||
|
IMCOMM_RET ret = IMCOMM_RET_OK;
|
||
|
send_q *nq, *head = ((IMCOMM *) handle)->s_queue;
|
||
|
|
||
|
if (head) {
|
||
|
ret =
|
||
|
flap_sendAct(handle, head->channel, head->data, head->len,
|
||
|
head->updateidle);
|
||
|
nq = head;
|
||
|
head = head->next;
|
||
|
((IMCOMM *) handle)->s_queue = head;
|
||
|
free(nq->data);
|
||
|
free(nq);
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
IMCOMM_RET
|
||
|
flap_send(void *handle, uint8_t channel, unsigned char *packet, size_t len, int updateidle)
|
||
|
{
|
||
|
send_q *nq, *trav, *head = ((IMCOMM *) handle)->s_queue;
|
||
|
|
||
|
nq = malloc(sizeof(struct IMCommSendQ));
|
||
|
nq->next = NULL;
|
||
|
nq->updateidle = updateidle;
|
||
|
nq->data = malloc(len);
|
||
|
nq->channel = channel;
|
||
|
memcpy(nq->data, packet, len);
|
||
|
nq->len = len;
|
||
|
|
||
|
if (head == NULL) {
|
||
|
((IMCOMM *) handle)->s_queue = nq;
|
||
|
} else {
|
||
|
for (trav = head; trav->next != NULL; trav = trav->next);
|
||
|
|
||
|
trav->next = nq;
|
||
|
}
|
||
|
|
||
|
return IMCOMM_RET_OK;
|
||
|
}
|
||
|
#endif /* SEND_QUEUES */
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
flap_sendpkt(void *handle, uint8_t channel, pkt_t * pkt, int updateidle)
|
||
|
{
|
||
|
return flap_send(handle, channel, pkt->data, pkt->len, updateidle);
|
||
|
}
|
||
|
|
||
|
/* PROTO */
|
||
|
IMCOMM_RET
|
||
|
flap_decode(void *handle, unsigned char *header, unsigned char *data)
|
||
|
{
|
||
|
pkt_t *packet;
|
||
|
#ifdef DEBUG
|
||
|
int y, z;
|
||
|
int x;
|
||
|
#endif
|
||
|
uint16_t len, sn_len;
|
||
|
uint16_t family, subfamily;
|
||
|
unsigned char *sn = NULL;
|
||
|
IMCOMM_RET ret = IMCOMM_RET_OK;
|
||
|
#ifdef DUMP
|
||
|
FILE *dump;
|
||
|
int xx;
|
||
|
dump = fopen("imcomm.dump", "a");
|
||
|
#endif
|
||
|
|
||
|
memcpy(&len, header + 4, 2);
|
||
|
if (endianness == HOST_LITTLE_ENDIAN)
|
||
|
len = BYTE_SWAP_16(len);
|
||
|
|
||
|
packet = pkt_initP(data, len);
|
||
|
|
||
|
#ifdef DUMP
|
||
|
for (xx = 0; x < 6; xx++)
|
||
|
fputc(header[xx], dump);
|
||
|
|
||
|
for (xx = 0; x < len; xx++)
|
||
|
fputc(data[xx], dump);
|
||
|
|
||
|
fclose(dump);
|
||
|
#endif
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
printf("Packet length: %u\n", (unsigned int) packet->len);
|
||
|
|
||
|
for (x = 0, y = 0; x < len; x++) {
|
||
|
printf("%02X ", data[x]);
|
||
|
y++;
|
||
|
if (y == 16) {
|
||
|
for (y = 15; y >= 0; y--) {
|
||
|
if (data[x - y] > 31 && data[x - y] < 128)
|
||
|
putchar(data[x - y]);
|
||
|
else
|
||
|
putchar('.');
|
||
|
}
|
||
|
printf("\n");
|
||
|
y = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (y < 16) {
|
||
|
for (z = 0; z < (16 - y); z++)
|
||
|
printf(" ");
|
||
|
while (y > 0) {
|
||
|
if (data[x - y] > 31 && data[x - y] < 128)
|
||
|
putchar(data[x - y]);
|
||
|
else
|
||
|
putchar('.');
|
||
|
y--;
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
printf("\n");
|
||
|
#endif
|
||
|
|
||
|
switch (header[1]) {
|
||
|
case 0x02:
|
||
|
ret = snac_decode(handle, data, len);
|
||
|
break;
|
||
|
case 0x04:
|
||
|
family = pkt_get16(packet);
|
||
|
|
||
|
if (family == 0x0009) {
|
||
|
subfamily = pkt_get16(packet);
|
||
|
if (subfamily == 0x0002) {
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_ERROR_OTHER_SIGNON);
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
|
||
|
#else
|
||
|
shutdown(((IMCOMM *) handle)->socket, 2);
|
||
|
((IMCOMM *) handle)->socket = -1;
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
} else if (family == 0x0001) {
|
||
|
|
||
|
/*
|
||
|
* SRV_COOKIE
|
||
|
*/
|
||
|
|
||
|
sn_len = pkt_get16(packet);
|
||
|
sn = pkt_getstr(packet, sn_len);
|
||
|
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_FORMATTED_SN])
|
||
|
((IMCOMM *) handle)->
|
||
|
callbacks[IMCOMM_FORMATTED_SN] (handle, sn);
|
||
|
subfamily = pkt_get16(packet);
|
||
|
|
||
|
switch (subfamily) {
|
||
|
case 0x0005:
|
||
|
{
|
||
|
unsigned char *server, *cookie;
|
||
|
uint16_t server_len, cookie_len;
|
||
|
|
||
|
server_len = pkt_get16(packet);
|
||
|
server = pkt_getstr(packet, server_len);
|
||
|
|
||
|
subfamily = pkt_get16(packet);
|
||
|
#ifdef DEBUG
|
||
|
if (subfamily != 0x0006) {
|
||
|
printf("WARNING: Cookie family not 0x0006!\n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
cookie_len = pkt_get16(packet);
|
||
|
cookie = pkt_getstr(packet, cookie_len);
|
||
|
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
|
||
|
((IMCOMM *) handle)->
|
||
|
callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_STATUS_AUTHDONE);
|
||
|
ret =
|
||
|
bos_signon_phase2(handle, server, cookie,
|
||
|
cookie_len);
|
||
|
free(server);
|
||
|
free(cookie);
|
||
|
}
|
||
|
break;
|
||
|
case 0x0008:
|
||
|
case 0x0004:
|
||
|
if (((IMCOMM *) handle)->callbacks[IMCOMM_ERROR])
|
||
|
((IMCOMM *) handle)->callbacks[IMCOMM_ERROR] (handle,
|
||
|
IMCOMM_ERROR_INVALID_LOGIN);
|
||
|
#ifdef MACINTOSH_CLASSIC
|
||
|
|
||
|
#else
|
||
|
shutdown(((IMCOMM *) handle)->socket, 0x02);
|
||
|
((IMCOMM *) handle)->socket = -1;
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (sn != NULL)
|
||
|
free(sn);
|
||
|
|
||
|
/*
|
||
|
* This'll also free the incoming data buffer
|
||
|
*/
|
||
|
pkt_free(packet);
|
||
|
|
||
|
return ret;
|
||
|
}
|