File indexing completed on 2018-03-02 18:44:55 UTC
view on githubraw file Latest commit ec6cf3b0 on 2003-08-26 20:45:25 UTC
ec6cf3b09d Ed H*0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052 #include <string.h>
0053 #include <MacTCPCommonTypes.h>
0054 #include <TCPPB.h>
0055 #include <AddressXlation.h>
0056 #include <GetMyIPAddr.h>
0057 #include "macnapp.h"
0058
0059 #define DEF_STREAM_SIZE 8192
0060 #define MAX_TCPCON 16
0061 #define RDS 8
0062
0063
0064
0065 typedef struct tcpwb {
0066 short rused;
0067 short wused;
0068 rdsEntry rds[RDS+1];
0069 char fflag[RDS+1];
0070 char *buf;
0071 } tcpwb;
0072
0073
0074
0075 typedef struct tcpinfo {
0076 short state;
0077 short rclose;
0078 short lclose;
0079 int havedata:1;
0080 int urgent:1;
0081 int push:1;
0082 int pushed:1;
0083 int reading:1;
0084 int server:1;
0085 int gethost:1;
0086 int dnrdone:1;
0087 short wbnum;
0088 unsigned short wbsize;
0089 unsigned short reason;
0090 StreamPtr stream;
0091 ip_port port;
0092 void *context;
0093 na_tcpreadp *callback;
0094 rdsEntry rrds[RDS+1];
0095 tcpwb wb[2];
0096 struct hostInfo host;
0097 TCPiopb pb;
0098 TCPiopb rpb;
0099 char buf[1];
0100 } tcpinfo;
0101
0102
0103
0104 struct tcpstate {
0105 na_win win;
0106 short tcp_driver;
0107 na_tcpinitp *tcp_initp;
0108 tcpinfo *tcpbufs[MAX_TCPCON];
0109 IOParam *open_pb;
0110 long waiticks, waitstart;
0111 short waitpercent;
0112 long streamsize;
0113 byte TOS, precedence;
0114 unsigned short wbsize;
0115 char localhost[256];
0116 } **tcpstate = NULL;
0117 #define tstate ((struct tcpstate *) win)
0118
0119
0120 #define TCP_PBINUSE 0x04
0121 #define TCP_DNSINUSE 0x08
0122 #define TCP_NOTREADY 0x10
0123
0124 #define TCP_READY 1
0125 #define TCP_RESOLVE (TCP_NOTREADY + TCP_DNSINUSE + 0)
0126 #define TCP_GETHOST (TCP_NOTREADY + TCP_DNSINUSE + 1)
0127 #define TCP_WRITING (TCP_PBINUSE + 0)
0128 #define TCP_CONNECT (TCP_NOTREADY + TCP_PBINUSE + 0)
0129 #define TCP_CLOSING (TCP_NOTREADY + TCP_PBINUSE + 1)
0130 #define TCP_CLOSED 2
0131
0132
0133
0134 static void freewb(tcpwb *wb)
0135 {
0136 short i;
0137
0138 for (i = 0; wb->rds[i].length; ++i) {
0139 if (wb->fflag[i]) {
0140 DisposPtr(wb->rds[i].ptr);
0141 wb->fflag[i] = 0;
0142 }
0143 }
0144 wb->rused = 0;
0145 wb->wused = 0;
0146 }
0147
0148
0149
0150 static short tcp_checkdriver()
0151 {
0152 short msg = NATCP_nodriver;
0153 struct tcpstate *ts = *tcpstate;
0154 IOParam *opb = ts->open_pb;
0155
0156 if (!opb) return (1);
0157 if (opb->ioResult == 1) return (0);
0158 if (opb->ioResult == noErr && OpenResolver(nil) == noErr) {
0159 ts->tcp_driver = opb->ioRefNum;
0160 msg = NATCP_connect;
0161 }
0162 DisposPtr((Ptr) opb);
0163 ts = *tcpstate;
0164 ts->open_pb = NULL;
0165 (*ts->tcp_initp)(msg);
0166
0167 return (1);
0168 }
0169
0170
0171
0172 static short tcp_wait(struct tcpstate *ts, tcpinfo *tcp)
0173 {
0174 KeyMap mapkeys;
0175 #define keys ((unsigned char *)mapkeys)
0176 short percent;
0177
0178 while (!tcp_checkdriver()
0179 || (tcp && (tcp->state & TCP_DNSINUSE) && ! (volatile) tcp->dnrdone)
0180 || (tcp && (tcp->state & TCP_PBINUSE) && (volatile short) tcp->pb.ioResult == 1)) {
0181 if (ts) {
0182 if (!ts->waiticks) return (0);
0183 percent = ((TickCount() - ts->waitstart) * 100) / ts->waiticks;
0184 if (percent > 100) percent = 100;
0185 if (percent != ts->waitpercent) {
0186 (*ts->tcp_initp)(ts->waitpercent = percent);
0187 }
0188 if (percent == 100) return (0);
0189 }
0190 SystemTask();
0191 GetKeys(mapkeys);
0192 if ((keys[0x37 >> 3] >> (0x37 & 7))
0193 & (keys[0x2f >> 3] >> (0x2f & 7)) & 1) {
0194 return (0);
0195 }
0196 }
0197
0198 return (1);
0199 }
0200
0201
0202
0203 static short tcp_closep(na_win *win)
0204 {
0205 short i, j;
0206 tcpinfo *tcp;
0207 tcpwb *wb;
0208 TCPiopb pb;
0209
0210 tstate->waitstart = TickCount();
0211 tstate->waitpercent = 0;
0212 tcp_wait(tstate, NULL);
0213 memset((void *) &pb, 0, sizeof (pb));
0214 for (i = 0; i < MAX_TCPCON; ++i) {
0215 if ((tcp = tstate->tcpbufs[i]) != NULL) {
0216
0217 if (!tcp->server || tcp->state != TCP_CONNECT) tcp_wait(tstate, tcp);
0218 if (!tcp->gethost) {
0219 pb.ioCRefNum = tstate->tcp_driver;
0220 pb.tcpStream = tcp->stream;
0221 pb.csCode = TCPRelease;
0222 PBControl((ParmBlkPtr) &pb, false);
0223 }
0224 freewb(tcp->wb);
0225 freewb(tcp->wb + 1);
0226 DisposPtr((Ptr) tcp);
0227 tstate->tcpbufs[i] = NULL;
0228 }
0229 }
0230 tcpstate = NULL;
0231 if (tstate->tcp_driver) CloseResolver();
0232
0233 return (NA_CLOSED);
0234 }
0235
0236
0237
0238 static short beginwrite(tcpinfo *tcp)
0239 {
0240 tcpwb *wb = tcp->wb + tcp->wbnum;
0241
0242
0243 if (tcp->rclose == 3 || tcp->lclose > 1) return (0);
0244 memset((void *) &tcp->pb.csParam, 0, sizeof (tcp->pb.csParam));
0245 tcp->pb.csCode = TCPSend;
0246 tcp->pb.csParam.send.ulpTimeoutValue = 60;
0247 tcp->pb.csParam.send.ulpTimeoutAction = 0;
0248 tcp->pb.csParam.send.validityFlags = 0xC0;
0249 tcp->pb.csParam.send.wdsPtr = (Ptr) wb->rds;
0250 tcp->pb.csParam.send.pushFlag = tcp->pushed = tcp->push;
0251 PBControl((ParmBlkPtr) &tcp->pb, true);
0252 tcp->push = 0;
0253 tcp->wbnum = 1 - tcp->wbnum;
0254 wb->rused = -1;
0255
0256 return (tcp->state = TCP_WRITING);
0257 }
0258
0259
0260
0261 short NATCPtask(na_win *win)
0262 {
0263 tcpinfo *tcp;
0264 rdsEntry *rds, *trds;
0265 short result, newstate;
0266 short processed = NA_PROCESSED;
0267 na_tcp i;
0268 tcpwb *wb;
0269 int j;
0270
0271
0272 if (!tstate->tcp_driver) {
0273 if (!tcp_checkdriver()) return (NA_NOTPROCESSED);
0274 if (!tstate->tcp_driver) return (NA_REQCLOSE);
0275 }
0276
0277 for (i = 0; i < MAX_TCPCON; ++i) {
0278 if ((tcp = tstate->tcpbufs[i]) != NULL) do {
0279
0280 if (!tcp->reading && !tcp->rclose && tcp->havedata && tcp->state != TCP_CONNECT) {
0281 tcp->rpb.ioCRefNum = tstate->tcp_driver;
0282 tcp->rpb.tcpStream = tcp->stream;
0283 tcp->rpb.csCode = TCPNoCopyRcv;
0284 tcp->rpb.csParam.receive.rdsPtr = (Ptr) tcp->rrds;
0285 tcp->rpb.csParam.receive.commandTimeoutValue = 5;
0286 tcp->rpb.csParam.receive.rdsLength = RDS;
0287 if (tcp->pushed) {
0288 tcp->rpb.csParam.receive.commandTimeoutValue = 1;
0289 tcp->rpb.csParam.receive.rdsLength = 1;
0290 }
0291 tcp->havedata = 0;
0292 PBControl((ParmBlkPtr) &tcp->rpb, tcp->pushed ? false : true);
0293 tcp->reading = 1;
0294 tcp->pushed = 0;
0295 }
0296 if (tcp->reading) {
0297 if ((result = tcp->rpb.ioResult) == 1) {
0298 processed = NA_NOTPROCESSED;
0299 } else {
0300 tcp->reading = 0;
0301 if (result != noErr) {
0302 if (result != commandTimeout) {
0303 (*tcp->callback)(tcp->context, i, NATCP_noread, result, NULL);
0304 }
0305 } else {
0306 result = NATCP_data | NATCP_more;
0307 if (tcp->rpb.csParam.receive.urgentFlag) tcp->urgent = 1;
0308 if (tcp->urgent) result |= NATCP_urgent;
0309 if (tcp->rpb.csParam.receive.markFlag) tcp->urgent = 0;
0310 for (rds = tcp->rrds; rds->length; ++rds) {
0311 if (!rds[1].length) result &= ~NATCP_more;
0312 (*tcp->callback)(tcp->context, i, result,
0313 rds->length, rds->ptr);
0314 }
0315 tcp->rpb.csCode = TCPRcvBfrReturn;
0316 PBControl((ParmBlkPtr) &tcp->rpb, false);
0317 }
0318 }
0319 }
0320 result = tcp->pb.ioResult;
0321 newstate = 0;
0322 switch (tcp->state) {
0323 case TCP_GETHOST:
0324 if (tcp->dnrdone) {
0325 tcp->rclose = 3;
0326 newstate = TCP_CLOSED;
0327 if (tcp->host.rtnCode != noErr) {
0328 (*tcp->callback)(tcp->context, i, NATCP_nohost,
0329 tcp->host.rtnCode, NULL);
0330 } else {
0331 (*tcp->callback)(tcp->context, i, NATCP_connect,
0332 strlen(tcp->host.cname), tcp->host.cname);
0333 strcpy(tstate->localhost, tcp->host.cname);
0334 }
0335 }
0336 break;
0337 case TCP_RESOLVE:
0338 if (tcp->dnrdone) {
0339 if (tcp->host.rtnCode != noErr) {
0340 tcp->rclose = 3;
0341 newstate = TCP_CLOSED;
0342 (*tcp->callback)(tcp->context, i, NATCP_nohost,
0343 tcp->host.rtnCode, NULL);
0344 } else if (!tcp->lclose) {
0345 memset((void *) &tcp->pb, 0, sizeof (tcp->pb));
0346 tcp->pb.ioCRefNum = tstate->tcp_driver;
0347 tcp->pb.tcpStream = tcp->stream;
0348 tcp->pb.csParam.open.ulpTimeoutValue = 30;
0349 tcp->pb.csParam.open.ulpTimeoutAction = 1;
0350 tcp->pb.csParam.open.tosFlags = tstate->TOS;
0351 tcp->pb.csParam.open.precedence = tstate->precedence;
0352 tcp->pb.csParam.open.validityFlags =
0353 timeoutValue|timeoutAction|typeOfService|precedence;
0354 tcp->pb.csParam.open.remoteHost = tcp->host.addr[0];
0355 if (tcp->server) {
0356 tcp->pb.csCode = TCPPassiveOpen;
0357 tcp->pb.csParam.open.commandTimeoutValue = 0;
0358 tcp->pb.csParam.open.remotePort = 0;
0359 tcp->pb.csParam.open.localPort = tcp->port;
0360 } else {
0361 tcp->pb.csCode = TCPActiveOpen;
0362 tcp->pb.csParam.open.remotePort = tcp->port;
0363 tcp->pb.csParam.open.localPort = 0;
0364 }
0365 PBControl((ParmBlkPtr) &tcp->pb, true);
0366 newstate = TCP_CONNECT;
0367 }
0368 }
0369 break;
0370 case TCP_CONNECT:
0371 if (result == 1) {
0372 processed = NA_NOTPROCESSED;
0373 break;
0374 }
0375 if (result != noErr) {
0376 tcp->rclose = 3;
0377 newstate = TCP_CLOSED;
0378 (*tcp->callback)(tcp->context, i, NATCP_nocon, result, NULL);
0379 } else {
0380 newstate = TCP_READY;
0381 if (tcp->server) {
0382 tcp->port = tcp->pb.csParam.open.remotePort;
0383 if (!*tcp->host.cname) {
0384 AddrToStr(tcp->pb.csParam.open.remoteHost, tcp->host.cname);
0385 }
0386 }
0387 (*tcp->callback)(tcp->context, i, NATCP_connect,
0388 tcp->port, tcp->host.cname);
0389 }
0390 break;
0391 case TCP_READY:
0392
0393 wb = tcp->wb + tcp->wbnum;
0394 if (wb->rused && (newstate = beginwrite(tcp))) {
0395 break;
0396 }
0397
0398 if (tcp->rclose == 1) {
0399 tcp->rclose = 2;
0400 (*tcp->callback)(tcp->context, i, NATCP_closing, 0, NULL);
0401 }
0402
0403 if (tcp->lclose == 1) {
0404 tcp->lclose = 2;
0405 tcp->pb.csCode = TCPClose;
0406 tcp->pb.csParam.close.validityFlags = 0xC0;
0407 tcp->pb.csParam.close.ulpTimeoutValue = 30;
0408 tcp->pb.csParam.close.ulpTimeoutAction = 0;
0409 PBControl((ParmBlkPtr) &tcp->pb, true);
0410 newstate = TCP_CLOSING;
0411 break;
0412 }
0413
0414 if (tcp->rclose == 3) {
0415 (*tcp->callback)(tcp->context, i, NATCP_closed, tcp->reason, NULL);
0416 newstate = TCP_CLOSED;
0417 }
0418 break;
0419 case TCP_WRITING:
0420 if (result == 1) {
0421 processed = NA_NOTPROCESSED;
0422 break;
0423 }
0424 wb = tcp->wb;
0425 if (wb->rused != -1) ++wb;
0426 freewb(wb);
0427 if (result != noErr) {
0428 tcp->pushed = 0;
0429 (*tcp->callback)(tcp->context, i, NATCP_nowrite, result, NULL);
0430 }
0431 newstate = TCP_READY;
0432 break;
0433 case TCP_CLOSING:
0434 if (result == 1) {
0435 processed = NA_NOTPROCESSED;
0436 break;
0437 }
0438 newstate = TCP_READY;
0439 break;
0440 case TCP_CLOSED:
0441 if (!tcp->rclose) break;
0442 if (!tcp->gethost) {
0443 tcp->pb.csCode = TCPRelease;
0444 PBControl((ParmBlkPtr)&tcp->pb, false);
0445 }
0446 freewb(tcp->wb);
0447 freewb(tcp->wb + 1);
0448 DisposPtr((Ptr) tcp);
0449 tstate->tcpbufs[i] = NULL;
0450 break;
0451 }
0452 if (newstate) tcp->state = newstate;
0453 } while (newstate);
0454 }
0455
0456 return (processed);
0457 }
0458
0459
0460
0461 static pascal void myTCPNotifyProc(StreamPtr stream, unsigned short eventCode,
0462 Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg)
0463 {
0464 tcpinfo *tcp = (tcpinfo *) userDataPtr;
0465
0466 switch (eventCode) {
0467 case TCPTerminate:
0468 tcp->rclose = 3;
0469 tcp->reason = terminReason;
0470 break;
0471 case TCPClosing:
0472 tcp->rclose = 1;
0473 break;
0474 case TCPDataArrival:
0475 tcp->havedata = 1;
0476 break;
0477 case TCPUrgent:
0478 tcp->urgent = 1;
0479 break;
0480 }
0481 }
0482
0483
0484 static pascal void addrproc(struct hostInfo *hinfop, char *udata)
0485 {
0486 ((tcpinfo *) udata)->dnrdone = 1;
0487 }
0488
0489
0490
0491 static void winreadp(void *context, na_tcp i, short status, long len, char *buf)
0492 {
0493 natcp_win *w;
0494
0495 w = (natcp_win *) NAlockWindow((na_win **) context);
0496 w->s = i;
0497 (*w->readp)(&w->winp, status, len, buf);
0498 NAunlockWindowh((na_win **) context, &w->winp);
0499 }
0500
0501
0502
0503 void NATCPsettings(long streamsize, short type_of_service, short precedence, unsigned short wbsize)
0504 {
0505 if (!streamsize) streamsize = DEF_STREAM_SIZE;
0506 (*tcpstate)->streamsize = streamsize ? streamsize : DEF_STREAM_SIZE;
0507 (*tcpstate)->TOS = type_of_service;
0508 (*tcpstate)->precedence = precedence;
0509 if (!wbsize) wbsize = 1024;
0510 (*tcpstate)->wbsize = wbsize;
0511 }
0512
0513
0514
0515 void NATCPinit(na_tcpinitp *initp)
0516 {
0517 IOParam *pb;
0518 int i;
0519 struct tcpstate *ts;
0520
0521 pb = (IOParam *) NewPtrClear(sizeof (IOParam));
0522 tcpstate = (struct tcpstate **) NAaddtask(NATCPtask, sizeof (struct tcpstate));
0523 if (!tcpstate || !pb) {
0524 (*initp)(NATCP_nomem);
0525 } else {
0526 pb->ioNamePtr = "\p.IPP";
0527 PBOpen((ParmBlkPtr) pb, true);
0528 ts = *tcpstate;
0529 for (i = 0; i < MAX_TCPCON; ++i) ts->tcpbufs[i] = NULL;
0530 ts->waiticks = 60;
0531 ts->win.type = NA_TCPTYPE;
0532 ts->win.closep = tcp_closep;
0533 ts->win.priority = -1;
0534 ts->tcp_initp = initp;
0535 ts->open_pb = pb;
0536 NATCPsettings(0, 0, 0, 0);
0537 }
0538 }
0539
0540
0541
0542 static tcpinfo *getTCPbuf(na_tcpreadp *callback, void *context, int *id)
0543 {
0544 int i;
0545 tcpinfo *tcp;
0546
0547
0548 if (!(*tcpstate)->tcp_driver
0549 && (!tcp_wait(NULL, NULL) || !(*tcpstate)->tcp_driver)) {
0550 (*callback)(context, -1, NATCP_nodriver, 0, NULL);
0551 return (NULL);
0552 }
0553
0554
0555 for (i = 0; i < MAX_TCPCON && (*tcpstate)->tcpbufs[i]; ++i);
0556 if (i == MAX_TCPCON) {
0557 (*callback)(context, -1, NATCP_notcpbuf, 0, NULL);
0558 return (NULL);
0559 }
0560 tcp = (tcpinfo *) NewPtr(sizeof (tcpinfo) - 1
0561 + (*tcpstate)->streamsize + (unsigned long) (*tcpstate)->wbsize * 2);
0562 if (!tcp) {
0563 (*callback)(context, -1, NATCP_nomem, 0, NULL);
0564 return (NULL);
0565 };
0566 *id = i;
0567 (*tcpstate)->tcpbufs[i] = tcp;
0568 memset((char *) tcp, 0, sizeof (tcpinfo));
0569
0570
0571 tcp->wbsize = (*tcpstate)->wbsize;
0572 tcp->wb[0].buf = tcp->buf + (*tcpstate)->streamsize;
0573 tcp->wb[1].buf = tcp->wb[0].buf + tcp->wbsize;
0574 tcp->pb.ioCRefNum = (*tcpstate)->tcp_driver;
0575 tcp->context = context;
0576 tcp->callback = callback;
0577
0578 return (tcp);
0579 }
0580
0581
0582
0583 void NATCPgethost(na_tcpreadp *callback, void *context)
0584 {
0585 int id;
0586 tcpinfo *tcp;
0587 struct IPParamBlock *ippb;
0588 na_win *win;
0589
0590 if ((*tcpstate)->localhost[0]) {
0591 win = NAlockWindow((na_win **) tcpstate);
0592 (*callback)(context, -1, NATCP_connect, strlen(tstate->localhost),
0593 tstate->localhost);
0594 NAunlockWindowh((na_win **) tcpstate, win);
0595 } else if ((tcp = getTCPbuf(callback, context, &id)) != NULL) {
0596
0597
0598
0599 ippb = (struct IPParamBlock *) &tcp->pb;
0600
0601 ippb->ioCRefNum = (*tcpstate)->tcp_driver;
0602 ippb->csCode = ipctlGetAddr;
0603 PBControl((ParmBlkPtr)ippb, false);
0604 if (ippb->ioResult != 0) {
0605 (*callback)(context, -1, NATCP_notcpbuf, ippb->ioResult, NULL);
0606 DisposPtr((Ptr) tcp);
0607 (*tcpstate)->tcpbufs[id] = NULL;
0608 } else {
0609
0610 tcp->dnrdone = 0;
0611 AddrToName(ippb->ourAddress, &tcp->host, addrproc, (char *) tcp);
0612 tcp->state = TCP_GETHOST;
0613 tcp->gethost = 1;
0614 }
0615 }
0616 }
0617
0618
0619
0620 na_tcp NATCPopen(na_tcpreadp *callback, void *context, char *host, long port, short flags)
0621 {
0622 int i, err = NATCP_notcpbuf;
0623 OSErr resolve = noErr;
0624 tcpinfo *tcp;
0625
0626 if ((tcp = getTCPbuf(callback, context, &i)) == NULL) return (-1);
0627 if (flags & NATCP_server) tcp->server = 1;
0628 tcp->port = port;
0629 tcp->pb.csCode = TCPCreate;
0630 tcp->pb.csParam.create.rcvBuff = (Ptr) tcp->buf;
0631 tcp->pb.csParam.create.rcvBuffLen = (*tcpstate)->streamsize;
0632 tcp->pb.csParam.create.notifyProc = myTCPNotifyProc;
0633 tcp->pb.csParam.create.userDataPtr = (Ptr) tcp;
0634 PBControl((ParmBlkPtr)&tcp->pb, false);
0635 if (tcp->pb.ioResult == 0) {
0636 tcp->state = TCP_RESOLVE;
0637 tcp->stream = tcp->pb.tcpStream;
0638
0639 if (!host && tcp->server) return (i);
0640 tcp->dnrdone = 0;
0641 resolve = StrToAddr(host, &tcp->host, addrproc, (char *) tcp);
0642 if (resolve == noErr) tcp->dnrdone = 1;
0643 if (resolve == cacheFault || resolve == noErr) {
0644 return (i);
0645 }
0646 err = NATCP_nohost;
0647 }
0648 DisposPtr((Ptr) tcp);
0649 (*tcpstate)->tcpbufs[i] = NULL;
0650 (*callback)(context, -1, err, resolve, NULL);
0651
0652 return (-1);
0653 }
0654
0655
0656
0657 na_tcp NATCPwinopen(natcp_win *w, char *host, long port, short flags)
0658 {
0659 return (NATCPopen(winreadp, (void *) RecoverHandle((Ptr) w), host, port, flags));
0660 }
0661
0662
0663
0664
0665 short NATCPwrite(na_tcp i, Ptr data, long len, short dispose)
0666 {
0667 tcpinfo *tcp = (*tcpstate)->tcpbufs[i];
0668 rdsEntry *rds = NULL;
0669 tcpwb *wb;
0670 long totallen = 0;
0671 int j;
0672
0673 if (tcp == NULL || tcp->lclose > 0 || tcp->rclose == 3) {
0674 return (NATCP_nocon);
0675 }
0676 wb = tcp->wb + tcp->wbnum;
0677 if (wb->rused == RDS) wb = tcp->wb + (1 - tcp->wbnum);
0678 if (wb->rused == -1 || wb->rused == RDS) return (NATCP_notcpbuf);
0679 for (j = 0; j < wb->rused; ++j) {
0680 totallen += wb->rds[j].length;
0681 }
0682 if (totallen + len >= 65535) return (NATCP_notcpbuf);
0683 rds = wb->rds + wb->rused;
0684 rds->length = len;
0685 rds->ptr = data;
0686 rds[1].length = 0;
0687 if (dispose < 0) {
0688 if (len < tcp->wbsize - wb->wused) {
0689
0690 rds->ptr = wb->buf + wb->wused;
0691 wb->wused += len;
0692 dispose = 0;
0693
0694 if (wb->rused && rds[-1].ptr + rds[-1].length == rds->ptr) {
0695 --wb->rused;
0696 rds[-1].length += len;
0697 rds->length = 0;
0698 }
0699 } else {
0700 rds->ptr = NewPtr(len);
0701 if (!rds->ptr) return (NATCP_nomem);
0702 dispose = 1;
0703 }
0704 memcpy(rds->ptr, data, len);
0705 }
0706 wb->fflag[wb->rused++] = dispose;
0707 if (tcp->push && tcp->state == TCP_READY) {
0708 (void) beginwrite(tcp);
0709 }
0710
0711 return (NATCP_data);
0712 }
0713
0714
0715
0716 short NATCPputchar(na_tcp i, char c)
0717 {
0718 (*tcpstate)->tcpbufs[i]->push = 1;
0719
0720 return (NATCPwrite(i, (Ptr) &c, 1, -1));
0721 }
0722
0723
0724
0725 void NATCPclose(na_tcp i)
0726 {
0727 tcpinfo *tcp = (*tcpstate)->tcpbufs[i];
0728
0729 if (tcp && tcp->lclose < 1) tcp->lclose = 1;
0730 }
0731
0732
0733
0734 void NATCPdone(long waiticks)
0735 {
0736 struct tcpstate *ts;
0737
0738 if (tcpstate) {
0739 ts = (struct tcpstate *) NAlockWindow((na_win **) tcpstate);
0740 ts->waiticks = waiticks;
0741 NAcloseWindow((na_win *) ts, NA_REQCLOSE);
0742 }
0743 }