|
|
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.