|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: ! 26: #include <adsp_local.h> ! 27: #include <lap.h> ! 28: #include <at/at_lap.h> ! 29: #include <at/ddp.h> ! 30: extern at_ddp_cfg_t ddpcfg; ! 31: ! 32: /* ! 33: * GleanSession ! 34: * ! 35: * We just got a packet for this session, glean its address & ! 36: * reset probe timer ! 37: * ! 38: * INPUTS: ! 39: * Session ! 40: * OUTPUTS: ! 41: * none ! 42: */ ! 43: static void GleanSession(sp) /* (CCBPtr sp) */ ! 44: CCBPtr sp; ! 45: { ! 46: if (sp->openState == O_STATE_OPEN) { ! 47: /* This is true for both state = sOpen & sClosing */ ! 48: RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer); ! 49: InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer, ! 50: sp->probeInterval); ! 51: sp->probeCntr = 4; ! 52: } ! 53: ! 54: } ! 55: ! 56: ! 57: /* ! 58: * The same code handles incoming Open Connection Request, ! 59: * Open Request + Ack, Open Connection Ack, Open Connection Denial ! 60: * ! 61: * We could be in four different states, LISTEN, OPENWAIT, ESTABLISHED, ! 62: * OPEN. ! 63: */ ! 64: ! 65: /* ! 66: * ! 67: * Ok, there are 16 combinations. 8 are do-nothings, 2 have to be ! 68: * special cased (Open Deny and Req+Ack on Open session) ! 69: * ! 70: * Build a table of actions: ! 71: * Ignore? ! 72: * What to match on (local socket, whole address, DestCID, SrcCID) ! 73: * What to send (Ack or Req+Ack) ! 74: * Next State (both the ccb state and the open state) ! 75: */ ! 76: ! 77: /* ! 78: * ! 79: */ ! 80: typedef struct { ! 81: u_char match; /* Characteristics that have to match ! 82: * (Bit-Mapped, see below) */ ! 83: char action; /* What to do if CCB matches */ ! 84: char send; /* What to send in response ! 85: * (Bit mapped, same as sendCtl field of ! 86: * CCB) */ ! 87: char openState; /* Next Open state */ ! 88: char state; /* Next ccb state. */ ! 89: char pad; /* Too bad we need this to make structure ! 90: * even size */ ! 91: } TBL, *TBLPtr; ! 92: ! 93: #define M_LSOC 0x01 /* bit 0 - Match on local socket */ ! 94: #define M_ADDR 0x02 /* bit 1 - Match on whole address */ ! 95: #define M_DCID 0x04 /* bit 2 - Match on DestCID */ ! 96: #define M_SCID 0x08 /* bit 3 - Match SrcCID */ ! 97: #define M_DCIDZERO 0x10 /* bit 4 - Dest CID must be 0 */ ! 98: #define M_SCIDZERO 0x20 /* bit 5 - Src CID must be 0 */ ! 99: #define M_FILTER 0x40 /* bit 6 - Match address filter */ ! 100: #define M_IGNORE 0x80 /* bit 7 - Ignore */ ! 101: ! 102: #define A_COMPLETE 0x01 /* Complete open parameter block */ ! 103: #define A_SAVEPARMS 0x02 /* Save connection parameters */ ! 104: #define A_OREQACKOPEN 0x04 /* special case for open Req+Ack on ! 105: * OPEN session */ ! 106: #define A_GLEAN 0x08 /* We'll be talking back to this guy */ ! 107: #define A_DENY 0x10 /* We've been denied! */ ! 108: ! 109: ! 110: /* ! 111: * So here's our table ! 112: */ ! 113: ! 114: static TBL tbl[16] = { ! 115: ! 116: /* ! 117: * For Open Request ($81) ! 118: * ! 119: * LISTENING ! 120: * Match on destination socket ! 121: * Match on address filter ! 122: * Dest CID must be 0 ! 123: * Glean connection ! 124: * Save Open Connection parameters ! 125: * Send OREQACK ! 126: * Change state to ESTABLISHED ! 127: */ ! 128: { M_LSOC + M_DCIDZERO + M_FILTER, ! 129: A_SAVEPARMS + A_GLEAN, ! 130: B_CTL_OREQACK, ! 131: O_STATE_ESTABLISHED, ! 132: sOpening, ! 133: 0 ! 134: }, ! 135: ! 136: /* ! 137: * ! 138: * OPENWAIT ! 139: * Match on Remote Address & destination socket ! 140: * Dest CID must be 0 ! 141: * Save Open Connection parameters ! 142: * Send Ack ! 143: * Change state to ESTABLISHED ! 144: */ ! 145: { M_LSOC + M_ADDR + M_DCIDZERO, ! 146: A_SAVEPARMS + A_GLEAN, ! 147: B_CTL_OACK, ! 148: O_STATE_ESTABLISHED, ! 149: sOpening, ! 150: 0 ! 151: }, ! 152: /* ! 153: * ! 154: * ESTABLISHED ! 155: * Match on Remote Address & SrcCID ! 156: * Dest CID must be 0 ! 157: * Send Req + Ack ! 158: */ ! 159: { M_ADDR + M_SCID + M_DCIDZERO, ! 160: A_GLEAN, ! 161: B_CTL_OACK, ! 162: O_STATE_ESTABLISHED, ! 163: sOpening, ! 164: 0 ! 165: }, ! 166: /* ! 167: * OPEN ! 168: * Ignore ! 169: */ ! 170: { M_IGNORE, ! 171: 0, ! 172: 0, ! 173: 0, ! 174: 0, ! 175: 0 ! 176: }, ! 177: ! 178: /* ! 179: * ! 180: * For Open Ack ($82) ! 181: * ! 182: * LISTENING ! 183: * Ignore ! 184: */ ! 185: { M_IGNORE, ! 186: 0, ! 187: 0, ! 188: 0, ! 189: 0, ! 190: 0 ! 191: }, ! 192: /* ! 193: * ! 194: * OPENWAIT ! 195: * Ignore ! 196: */ ! 197: { M_IGNORE, ! 198: 0, ! 199: 0, ! 200: 0, ! 201: 0, ! 202: 0 ! 203: }, ! 204: /* ! 205: * ! 206: * ESTABLISHED ! 207: * Match on SrcCID & DestCID & Address & Local Socket ! 208: * Complete Listen or Connect PB ! 209: * OPEN ! 210: */ ! 211: { M_ADDR + M_DCID + M_SCID + M_LSOC, ! 212: A_COMPLETE + A_GLEAN, ! 213: 0, ! 214: O_STATE_OPEN, ! 215: sOpen, ! 216: 0 ! 217: }, ! 218: /* ! 219: * ! 220: * OPEN ! 221: * Ignore ! 222: */ ! 223: { M_IGNORE, ! 224: 0, ! 225: 0, ! 226: 0, ! 227: 0, ! 228: 0 ! 229: }, ! 230: ! 231: /* ! 232: * ! 233: * For Open Request + Ack ($83) ! 234: * ! 235: * LISTENING ! 236: * Ignore ! 237: */ ! 238: { M_IGNORE, ! 239: 0, ! 240: 0, ! 241: 0, ! 242: 0, ! 243: 0 ! 244: }, ! 245: /* ! 246: * ! 247: * OPENWAIT ! 248: * Match on DestCID & socket ! 249: * Do not test remote address -- our open req could have ! 250: * been passed to another address by a connection server ! 251: * Save Open Connection parameters ! 252: * Complete Connect parameter block ! 253: * Send Ack ! 254: * OPEN ! 255: */ ! 256: { M_DCID + M_LSOC, ! 257: A_COMPLETE + A_SAVEPARMS + A_GLEAN, ! 258: B_CTL_OACK, ! 259: O_STATE_OPEN, ! 260: sOpen, ! 261: 0 ! 262: }, ! 263: /* ! 264: * ! 265: * ESTABLISHED ! 266: * Ignore ! 267: */ ! 268: { M_IGNORE, ! 269: 0, ! 270: 0, ! 271: 0, ! 272: 0, ! 273: 0 ! 274: }, ! 275: /* ! 276: * ! 277: * OPEN ! 278: * Match on Remote Address & SrcCID & DestCID & Local Socket ! 279: * If we've never gotten any data ! 280: * Send Ack & Retransmit ! 281: */ ! 282: { M_ADDR + M_DCID + M_SCID + M_LSOC, ! 283: A_OREQACKOPEN + A_GLEAN, ! 284: B_CTL_OACK, ! 285: O_STATE_OPEN, ! 286: sOpen, ! 287: 0 ! 288: }, ! 289: ! 290: /* ! 291: * ! 292: * ! 293: * For Open Deny ($84) ! 294: * ! 295: * LISTENING ! 296: * Ignore ! 297: */ ! 298: { M_IGNORE, ! 299: 0, ! 300: 0, ! 301: 0, ! 302: 0, ! 303: 0 ! 304: }, ! 305: /* ! 306: * ! 307: * OPENWAIT ! 308: * Match on DestCID & Address ! 309: * Source CID must be 0 ! 310: * Complete with error ! 311: */ ! 312: { M_SCIDZERO + M_DCID + M_ADDR, ! 313: A_DENY, ! 314: 0, ! 315: O_STATE_NOTHING, ! 316: sClosed, ! 317: 0 ! 318: }, ! 319: /* ! 320: * ! 321: * ESTABLISHED ! 322: * Ignore ! 323: */ ! 324: { M_IGNORE, ! 325: 0, ! 326: 0, ! 327: 0, ! 328: 0, ! 329: 0 ! 330: }, /* %%% No we probably don't want to ignore in this case */ ! 331: /* ! 332: * ! 333: * OPEN ! 334: * Ignore ! 335: */ ! 336: { M_IGNORE, ! 337: 0, ! 338: 0, ! 339: 0, ! 340: 0, ! 341: 0 ! 342: } ! 343: }; ! 344: ! 345: /* ! 346: * Used to search down queue of sessions for a session waiting for an ! 347: * open request. ! 348: */ ! 349: typedef struct { ! 350: AddrUnion addr; ! 351: word dstCID; ! 352: word srcCID; ! 353: byte socket; ! 354: byte descriptor; ! 355: byte idx; /* Index into state tables */ ! 356: TBLPtr t; /* Ptr to entry in table above */ ! 357: } MATCH, *MATCHPtr; ! 358: ! 359: /* ! 360: * MatchStream ! 361: * ! 362: * Called by Rx connection to find which stream (if any) should get this open ! 363: * request/ack/req+ack/deny packet. ! 364: * ! 365: */ ! 366: ! 367: static boolean ! 368: MatchStream(sp, m) /* (CCBPtr sp, MATCHPtr m) */ ! 369: CCBPtr sp; ! 370: MATCHPtr m; ! 371: { ! 372: unsigned char match; ! 373: struct adspcmd *opb; ! 374: ! 375: if (sp->openState < O_STATE_LISTEN || ! 376: sp->openState > O_STATE_OPEN) ! 377: return 0; ! 378: ! 379: ! 380: m->t = &tbl[sp->openState - O_STATE_LISTEN + m->idx]; ! 381: ! 382: match = m->t->match; /* Get match criteria */ ! 383: ! 384: if (match & M_IGNORE) /* Ignore this combination */ ! 385: return 0; ! 386: ! 387: if (match & M_LSOC) { /* Match on Local socket */ ! 388: if (sp->localSocket != m->socket) ! 389: return 0; ! 390: } ! 391: ! 392: if (match & M_ADDR) { /* Match on Address */ ! 393: AddrUnion addr; ! 394: addr = m->addr; /* Make local copy for efficiency */ ! 395: if (sp->remoteAddress.a.node != addr.a.node) ! 396: return 0; ! 397: if (sp->remoteAddress.a.socket != addr.a.socket) ! 398: return 0; ! 399: if ((NET_VALUE(sp->remoteAddress.a.net) && NET_VALUE(addr.a.net)) && ! 400: (NET_VALUE(sp->remoteAddress.a.net) != NET_VALUE(addr.a.net))) ! 401: return 0; ! 402: ! 403: /* ! 404: * Handle special case to reject self-sent open request ! 405: */ ! 406: if ((m->srcCID == sp->locCID) && ! 407: (addr.a.node == ddpcfg.node_addr.node) && ! 408: ((NET_VALUE(addr.a.net) == 0) || ! 409: (NET_VALUE(ddpcfg.node_addr.net) == 0) || ! 410: (NET_VALUE(ddpcfg.node_addr.net) == NET_VALUE(addr.a.net))) ) ! 411: /* CID's match, and */ ! 412: /* If nodeID matches, and */ ! 413: /* network matches, */ ! 414: return 0; /* then came from us! */ ! 415: } ! 416: ! 417: if (match & M_DCID) { /* Match on DestCID */ ! 418: if (sp->locCID != m->dstCID) ! 419: return 0; ! 420: } ! 421: ! 422: if (match & M_SCID) { /* Match on SourceCID */ ! 423: if (sp->remCID != m->srcCID) ! 424: return 0; ! 425: } ! 426: ! 427: if (match & M_DCIDZERO) { /* Destination CID must be 0 */ ! 428: if (m->dstCID != 0) ! 429: return 0; ! 430: } ! 431: ! 432: if (match & M_SCIDZERO) /* Source CID must be 0 */ ! 433: { ! 434: if (m->srcCID != 0) ! 435: return 0; ! 436: } ! 437: ! 438: if (match & M_FILTER) { /* Check address filter? */ ! 439: if (opb = sp->opb) /* There should be a param block... */ ! 440: { ! 441: AddrUnion addr; ! 442: addr = m->addr; /* Make local copy for efficiency */ ! 443: if ((NET_VALUE(opb->u.openParams.filterAddress.net) && ! 444: NET_VALUE(addr.a.net) && ! 445: NET_VALUE(opb->u.openParams.filterAddress.net) != NET_VALUE(addr.a.net)) || ! 446: (opb->u.openParams.filterAddress.node != 0 && ! 447: opb->u.openParams.filterAddress.node != addr.a.node)|| ! 448: (opb->u.openParams.filterAddress.socket != 0 && ! 449: opb->u.openParams.filterAddress.socket != addr.a.socket)) ! 450: return 0; ! 451: } ! 452: } ! 453: ! 454: return 1; ! 455: } ! 456: ! 457: /* ! 458: * MatchListener ! 459: * ! 460: * Called by rx connection to see which connection listener (if any) should ! 461: * get this incoming open connection request. ! 462: * ! 463: */ ! 464: ! 465: static boolean MatchListener(sp, m) /* (CCBPtr sp, MATCHPtr m) */ ! 466: CCBPtr sp; ! 467: MATCHPtr m; ! 468: { ! 469: ! 470: if ((sp->state == (word)sListening) && /* This CCB is a listener */ ! 471: (sp->localSocket == m->socket)) /* on the right socket */ ! 472: return 1; ! 473: ! 474: return 0; ! 475: } ! 476: ! 477: /* ! 478: * RXConnection ! 479: * ! 480: * We just received one of the 4 Open Connection packets ! 481: * Interrupts are masked OFF at this point ! 482: * ! 483: * INPUTS: ! 484: * spPtr Place to put ptr to stream (if we found one -- not ! 485: * for listeners) ! 486: * f Pointer to ADSP header for packet, data follows behind it ! 487: * len # of byte in ADSP header + data ! 488: * addr Who sent the packet ! 489: * dsoc Where they sent it to ! 490: * ! 491: * OUTPUTS: ! 492: * Returns 1 if packet was ignored ! 493: */ ! 494: static int RXConnection(gref, spPtr, f, len, addr, dsoc) ! 495: /* (CCBPtr *spPtr, ADSP_FRAMEPtr f, word len, AddrUnion addr, byte dsoc) */ ! 496: gref_t *gref; /* READ queue */ ! 497: CCBPtr *spPtr; ! 498: ADSP_FRAMEPtr f; ! 499: int len; ! 500: AddrUnion addr; ! 501: unsigned char dsoc; ! 502: { ! 503: CCBPtr sp; ! 504: ADSP_OPEN_DATAPtr op; ! 505: struct adspcmd *pb; ! 506: MATCH m; ! 507: gbuf_t *mp; ! 508: ADSP_FRAMEPtr adspp; ! 509: ADSP_OPEN_DATAPtr adspop; ! 510: int s; ! 511: ! 512: op = (ADSP_OPEN_DATAPtr)&f->data[0]; /* Point to Open-Connection parms */ ! 513: len -= ADSP_FRAME_LEN; ! 514: ! 515: if (len < (sizeof(ADSP_OPEN_DATA))) /* Packet too small */ ! 516: return 1; ! 517: ! 518: ! 519: if (UAS_VALUE(op->version) != netw(0x0100)) { /* Check version num (on even-byte) */ ! 520: /* ! 521: * The open request has been denied. Try to send him a denial. ! 522: */ ! 523: ! 524: mp = gbuf_alloc(AT_WR_OFFSET + DDPL_FRAME_LEN + ADSP_FRAME_LEN + ADSP_OPEN_FRAME_LEN, ! 525: PRI_LO); ! 526: gbuf_rinc(mp,AT_WR_OFFSET); ! 527: gbuf_wset(mp,DDPL_FRAME_LEN); ! 528: adspp = (ADSP_FRAMEPtr)gbuf_wptr(mp); ! 529: gbuf_winc(mp,ADSP_FRAME_LEN); ! 530: bzero((caddr_t) gbuf_rptr(mp),DDPL_FRAME_LEN + ADSP_FRAME_LEN + ! 531: ADSP_OPEN_FRAME_LEN); ! 532: adspp->descriptor = ADSP_CONTROL_BIT | ADSP_CTL_ODENY; ! 533: adspop = (ADSP_OPEN_DATAPtr)gbuf_wptr(mp); ! 534: gbuf_winc(mp,ADSP_OPEN_FRAME_LEN); ! 535: UAS_UAS(adspop->dstCID, f->CID); ! 536: UAS_ASSIGN(adspop->version, 0x100); ! 537: adsp_sendddp(0, mp, DDPL_FRAME_LEN + ADSP_FRAME_LEN + ! 538: ADSP_OPEN_FRAME_LEN, &addr, DDP_ADSP); ! 539: ! 540: return 0; ! 541: } ! 542: m.addr = addr; ! 543: m.socket = dsoc; ! 544: m.descriptor = f->descriptor; ! 545: m.srcCID = UAS_VALUE(f->CID); ! 546: m.dstCID = UAS_VALUE(op->dstCID); /* On even-byte boundry */ ! 547: m.idx = ((f->descriptor & ADSP_CONTROL_MASK) - 1) * 4; ! 548: ! 549: /* ! 550: * See if we can find a stream that knows what to do with this packet ! 551: */ ! 552: if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, (ProcPtr)MatchStream)) == 0) ! 553: { ! 554: struct adspcmd *p; ! 555: struct adspcmd *n; ! 556: struct adspcmd *ot_n; ! 557: gbuf_t *ot_mp; ! 558: /* ! 559: * No match, so look for connection listeners if this is an ! 560: * open request ! 561: */ ! 562: if ((f->descriptor & ADSP_CONTROL_MASK) != (byte)ADSP_CTL_OREQ) ! 563: return 1; ! 564: ! 565: if ((sp = (CCBPtr)qfind_m(AT_ADSP_STREAMS, &m, ! 566: (ProcPtr)MatchListener)) == 0) ! 567: return 1; ! 568: ! 569: ATDISABLE(s, sp->lock); ! 570: p = (struct adspcmd *)&sp->opb; ! 571: while (n = (struct adspcmd *)p->qLink) /* Hunt down list of listens */ ! 572: { ! 573: /* Check address filter */ ! 574: if (((NET_VALUE(n->u.openParams.filterAddress.net) == 0) || ! 575: (NET_VALUE(addr.a.net) == 0) || ! 576: (NET_VALUE(n->u.openParams.filterAddress.net) == NET_VALUE(addr.a.net))) && ! 577: ! 578: ((n->u.openParams.filterAddress.node == 0) || ! 579: (n->u.openParams.filterAddress.node == addr.a.node)) && ! 580: ! 581: ((n->u.openParams.filterAddress.socket == 0) || ! 582: (n->u.openParams.filterAddress.socket == addr.a.socket))) { ! 583: p->qLink = n->qLink; /* Unlink this param block */ ! 584: n->u.openParams.remoteCID = m.srcCID; ! 585: *((AddrUnionPtr)&n->u.openParams.remoteAddress) = addr; ! 586: n->u.openParams.sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)); ! 587: n->u.openParams.sendWindow = netw(UAS_VALUE(f->pktRecvWdw)); ! 588: n->u.openParams.attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq)); ! 589: n->ioResult = 0; ! 590: ATENABLE(s, sp->lock); ! 591: completepb(sp, n); /* complete copy of request */ ! 592: /* complete(n, 0); */ ! 593: return 0; ! 594: } /* found CLListen */ ! 595: ! 596: p = n; /* down the list we go... */ ! 597: ! 598: } /* while */ ! 599: ! 600: ATENABLE(s, sp->lock); ! 601: return 1; ! 602: } ! 603: ! 604: *spPtr = sp; /* Save ptr to stream we just found */ ! 605: ! 606: ATDISABLE(s, sp->lock); ! 607: sp->openState = m.t->openState; /* Move to next state (may be same) */ ! 608: sp->state = m.t->state; /* Move to next state (may be same) */ ! 609: ! 610: if (m.t->action & A_SAVEPARMS) { /* Need to Save open-conn parms */ ! 611: sp->firstRtmtSeq = sp->sendSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)); ! 612: sp->sendWdwSeq = netdw(UAL_VALUE(f->pktNextRecvSeq)) + netw(UAS_VALUE(f->pktRecvWdw)) - 1; ! 613: sp->attnSendSeq = netdw(UAL_VALUE(op->pktAttnRecvSeq)); /* on even boundry */ ! 614: ! 615: ! 616: sp->remCID = UAS_VALUE(f->CID); /* Save Source CID as RemCID */ ! 617: UAS_UAS(sp->of.dstCID, f->CID); /* Save CID in open ctl packet */ ! 618: ! 619: sp->remoteAddress = addr; /* Save his address */ ! 620: ! 621: } ! 622: ATENABLE(s, sp->lock); ! 623: ! 624: if (m.t->action & A_DENY) { /* We've been denied ! */ ! 625: DoClose(sp, errOpenDenied, -1); ! 626: } ! 627: ! 628: if (m.t->action & A_OREQACKOPEN) { ! 629: /* Special case for OREQACK */ ! 630: /* on an open session */ ! 631: RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer); ! 632: sp->sendSeq = sp->firstRtmtSeq; ! 633: sp->pktSendCnt = 0; ! 634: sp->waitingAck = 0; ! 635: sp->callSend = 1; ! 636: } ! 637: ! 638: if (m.t->send) { /* Need to send a response */ ! 639: sp->sendCtl |= m.t->send; ! 640: sp->callSend = 1; ! 641: } ! 642: ! 643: if (m.t->action & A_COMPLETE) { /* Need to complete open param blk */ ! 644: RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer); ! 645: ! 646: if (pb = sp->opb) { ! 647: sp->opb = 0; ! 648: pb->u.openParams.localCID = sp->locCID; ! 649: pb->u.openParams.remoteCID = sp->remCID; ! 650: pb->u.openParams.remoteAddress = ! 651: *((at_inet_t *)&sp->remoteAddress); ! 652: pb->u.openParams.sendSeq = sp->sendSeq; ! 653: pb->u.openParams.sendWindow = sp->sendWdwSeq - sp->sendSeq; ! 654: pb->u.openParams.attnSendSeq = sp->attnSendSeq; ! 655: pb->ioResult = 0; ! 656: completepb(sp, pb); /* complete(pb, 0); */ ! 657: return 0; ! 658: } ! 659: /* Start probe timer */ ! 660: InsertTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer, ! 661: sp->probeInterval); ! 662: } ! 663: return 0; ! 664: } ! 665: ! 666: /* ! 667: * ADSPPacket ! 668: * ! 669: * When a packet is received by the protocol stack with DDP type equal ! 670: * to ADSP, then execution comes here ! 671: * ! 672: * DS is set to ATALK's DGROUP ! 673: * ! 674: * This routine, or one of its children MUST call glean packet ! 675: * ! 676: * INPUTS: ! 677: * Pointer to DDP header ! 678: * OUTPUTS: ! 679: * none ! 680: * ! 681: * Note that the incoming message block (mp) is usually discarded, either ! 682: * by the "ignored" path, or via the "checksend" path. The only case ! 683: * where the message is NOT freed is via the RxData case in the ! 684: * non control packet switch. I zero mp after the RxData case succeeds ! 685: * so that mp will not be freed. ! 686: */ ! 687: int adspPacket(gref, mp) ! 688: /* (bytePtr data, word len, AddrUnion a, byte dsoc) */ ! 689: gref_t *gref; ! 690: gbuf_t *mp; ! 691: { ! 692: unsigned char *bp; ! 693: int len; ! 694: AddrUnion a; ! 695: int dsoc; ! 696: int s; ! 697: register DDPX_FRAME *ddp; /* DDP frame pointer */ ! 698: register ADSP_FRAMEPtr f; /* Frame */ ! 699: CCBPtr sp; ! 700: ! 701: sp = 0; /* No stream */ ! 702: bp = (unsigned char *)gbuf_rptr(mp); ! 703: ddp = (DDPX_FRAME *)bp; ! 704: if (ddp->ddpx_type != DDP_ADSP) ! 705: return -1; ! 706: f = (ADSP_FRAMEPtr)(bp + DDPL_FRAME_LEN); ! 707: ! 708: len = UAS_VALUE(ddp->ddpx_length) & 0x3ff; /* (ten bits of length) */ ! 709: len -= DDPL_FRAME_LEN; ! 710: if (len < (sizeof(ADSP_FRAME) - 1)) /* Packet too small */ ! 711: return -1; /* mark the failure */ ! 712: ! 713: NET_NET(a.a.net, ddp->ddpx_snet); ! 714: a.a.node = ddp->ddpx_snode; ! 715: a.a.socket = ddp->ddpx_source; ! 716: ! 717: dsoc = ddp->ddpx_dest; ! 718: ! 719: if (sp = (CCBPtr)FindSender(f, a)) ! 720: GleanSession(sp); ! 721: ! 722: if (f->descriptor & ADSP_ATTENTION_BIT) { /* ATTN packet */ ! 723: if (sp && RXAttention(sp, mp, f, len)) ! 724: goto ignore; ! 725: else ! 726: mp = 0; /* attention data is being held */ ! 727: } /* ATTENTION BIT */ ! 728: ! 729: else if (f->descriptor & ADSP_CONTROL_BIT) { /* Control packet */ ! 730: switch (f->descriptor & ADSP_CONTROL_MASK) { ! 731: case ADSP_CTL_PROBE: /* Probe or acknowledgement */ ! 732: if (sp) ! 733: CheckRecvSeq(sp, f); ! 734: break; ! 735: ! 736: case ADSP_CTL_OREQ: /* Open Connection Request */ ! 737: case ADSP_CTL_OREQACK: /* Open Request and acknowledgement */ ! 738: case ADSP_CTL_OACK: /* Open Request acknowledgment */ ! 739: case ADSP_CTL_ODENY: /* Open Request denial */ ! 740: if (RXConnection(gref, &sp, f, len, a, dsoc)) ! 741: goto ignore; ! 742: break; ! 743: ! 744: case ADSP_CTL_CLOSE: /* Close connection advice */ ! 745: if (sp) { ! 746: /* This pkt may also ack some data we sent */ ! 747: CheckRecvSeq(sp, f); ! 748: RxClose(sp); ! 749: sp = 0; ! 750: } else ! 751: goto ignore; ! 752: break; ! 753: ! 754: case ADSP_CTL_FRESET: /* Forward Reset */ ! 755: /* May I rot in hell for the code below... */ ! 756: if (sp && (CheckRecvSeq(sp, f), RXFReset(sp, f))) ! 757: goto ignore; ! 758: break; ! 759: ! 760: case ADSP_CTL_FRESET_ACK: /* Forward Reset Acknowledgement */ ! 761: if (sp && (CheckRecvSeq(sp, f), RXFResetAck(sp, f))) ! 762: goto ignore; ! 763: break; ! 764: ! 765: case ADSP_CTL_RETRANSMIT: /* Retransmit advice */ ! 766: if (sp) { ! 767: /* This pkt may also ack some data we sent */ ! 768: CheckRecvSeq(sp, f); ! 769: RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer); ! 770: ATDISABLE(s, sp->lock); ! 771: sp->sendSeq = sp->firstRtmtSeq; ! 772: sp->pktSendCnt = 0; ! 773: sp->waitingAck = 0; ! 774: sp->callSend = 1; ! 775: ATENABLE(s, sp->lock); ! 776: } else ! 777: goto ignore; ! 778: break; ! 779: ! 780: default: ! 781: goto ignore; ! 782: } /* switch */ ! 783: } /* Control packet */ ! 784: ! 785: else { /* Data Packet */ ! 786: if ((sp == 0) || RXData(sp, mp, f, len)) ! 787: goto ignore; ! 788: else ! 789: mp = 0; /* RXData used up the data, DONT free it! */ ! 790: } /* Data Packet */ ! 791: ! 792: if (mp) ! 793: gbuf_freem(mp); ! 794: ! 795: checksend: /* incoming data was not ignored */ ! 796: if (sp && sp->callSend) /* If we have a stream & we need to send */ ! 797: CheckSend(sp); ! 798: ! 799: return 0; ! 800: ! 801: ignore: ! 802: gbuf_freem(mp); ! 803: return 0; ! 804: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.