Annotation of libwww/Library/src/HTDemux.c, revision 1.1.2.3
1.1.2.1 frystyk 1: /*
2: ** MUX HEADER PARSER STREAM
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
1.1.2.3 ! frystyk 6: ** @(#) $Id: HTDemux.c,v 1.1.2.2 1996/11/02 20:10:19 frystyk Exp $
1.1.2.1 frystyk 7: **
8: ** This stream parses MUX headers.
9: **
10: ** Authors
11: ** HFN Henrik Frystyk Nielsen <frystyk@w3.org>
12: **
13: ** History:
14: ** Oct 96 Written
15: */
16:
17: /* Library include files */
18: #include "sysdep.h"
19: #include "WWWUtil.h"
20: #include "WWWCore.h"
21: #include "HTMuxHeader.h"
22: #include "HTMuxCh.h"
23: #include "HTDemux.h" /* Implemented here */
24:
25: struct _HTStream {
26: const HTStreamClass * isa;
1.1.2.2 frystyk 27: HTChannel * ch;
1.1.2.1 frystyk 28: HTHost * host;
1.1.2.3 ! frystyk 29: HTMuxChannel * muxch;
! 30: HTMuxSession * session;
1.1.2.1 frystyk 31: int next; /* Next header */
1.1.2.3 ! frystyk 32: HTMuxHeader flags;
1.1.2.1 frystyk 33: };
34:
35: /* ------------------------------------------------------------------------- */
36:
37: /*
38: ** Parse through the buffer, identify the headers, and distribute the
39: ** data on the virtual session input streams
40: */
41: PRIVATE int HTDemux_write (HTStream * me, const char * buf, int len)
42: {
43: HTMuxChannel * muxch = me->muxch;
1.1.2.2 frystyk 44: int length = 0;
1.1.2.1 frystyk 45: while (len > 0) {
46:
47: /*
48: ** Look for the next header. If this is the first time through then
49: ** we expect the stream of data to start with a header.
50: */
51: if (!me->next) {
1.1.2.2 frystyk 52: HTMuxHeader header[2];
1.1.2.3 ! frystyk 53: HTMuxSessionId sid = INVSID;
1.1.2.2 frystyk 54: header[0] = HT_WORDSWAP(*(HTMuxHeader *) buf);
1.1.2.1 frystyk 55:
56: /*
57: ** If the long bit is set then we expect another 32 bits as the
58: ** length of the payload
59: */
60: if (MUX_IS_LONG(header[0])) {
1.1.2.3 ! frystyk 61: header[1] = HT_WORDSWAP(*(HTMuxHeader *) (buf+1));
1.1.2.1 frystyk 62: me->next = MUX_LONG_ALIGN(header[1]);
63: buf += 8, len -= 8;
64: } else {
65: me->next = MUX_ALIGN(MUX_GET_LEN(header[0]));
66: buf += 4, len -= 4;
67: }
1.1.2.3 ! frystyk 68: if (MUX_TRACE) HTTrace("Mux Channel. header: %x\n", header[0]);
1.1.2.1 frystyk 69: length = HTMIN(len, me->next);
1.1.2.2 frystyk 70: sid = MUX_GET_SID(header[0]);
1.1.2.1 frystyk 71:
72: /*
1.1.2.2 frystyk 73: ** If this is a control message then handle it here
74: */
75: if (header[0] & MUX_CONTROL) {
76: if (header[0] & MUX_STRING) {
77:
78: ; /* Define the string */
79:
80: } else if (header[0] & MUX_STACK) {
81:
82: ; /* Define the stack */
83:
84: } else if (header[0] & MUX_FRAGMENT) {
1.1.2.3 ! frystyk 85: HTMuxSession_setFragment(muxch, sid, MUX_GET_LEN(header[0]));
1.1.2.2 frystyk 86: } else if (header[0] & MUX_CREDIT) {
1.1.2.3 ! frystyk 87: HTMuxSession_setCredit(muxch, sid, header[1]);
1.1.2.2 frystyk 88: }
1.1.2.3 ! frystyk 89: } else if (header[0] & MUX_SYN)
! 90: me->session = HTMuxSession_register(muxch, sid, MUX_GET_PID(header[0]));
! 91: else {
! 92: me->session = HTMuxChannel_findSessionFromId(muxch, sid);
! 93: me->flags = header[0] & MUX_FLAGS;
1.1.2.2 frystyk 94: }
95: }
96:
97: /*
98: ** If there is data on this session then handle it here.
99: */
100: if (me->next && me->session) {
1.1.2.3 ! frystyk 101: if (HTMuxSession_disposeData(me->session, buf, length) == 1) {
! 102: HTMuxChannel_sendControl(muxch, HTMuxSession_id(me->session),
! 103: MUX_CREDIT, DEFAULT_CREDIT, NULL, 0);
! 104: }
! 105: }
1.1.2.2 frystyk 106:
1.1.2.3 ! frystyk 107: /*
! 108: ** If we have a data flag pending for this segment.
! 109: ** We currently don't do anthing with PUSH.
! 110: */
! 111: if (!me->next && (me->flags & (MUX_FIN | MUX_RST))) {
1.1.2.2 frystyk 112:
1.1.2.3 ! frystyk 113: /* Mark as closed */
1.1.2.2 frystyk 114:
1.1.2.1 frystyk 115: }
1.1.2.3 ! frystyk 116: buf += length, len -= length, me->next -= length;
1.1.2.1 frystyk 117: }
118: return HT_OK;
119: }
120:
121: PRIVATE int HTDemux_put_character (HTStream * me, char c)
122: {
123: return HTDemux_write(me, &c, 1);
124: }
125:
126: PRIVATE int HTDemux_put_string (HTStream * me, const char * s)
127: {
128: return HTDemux_write(me, s, (int) strlen(s));
129: }
130:
131: PRIVATE int HTDemux_flush (HTStream * me)
132: {
133: return HT_OK;
134: }
135:
136: PRIVATE int HTDemux_free (HTStream * me)
137: {
138: return HTDemux_flush(me);
139: }
140:
141: PRIVATE int HTDemux_abort (HTStream * me, HTList * e)
142: {
143: if (PROT_TRACE) HTTrace("MUX Tx...... ABORTING...\n");
144: return HT_ERROR;
145: }
146:
147: PRIVATE const HTStreamClass HTDemux =
148: {
149: "Demux",
150: HTDemux_flush,
151: HTDemux_free,
152: HTDemux_abort,
153: HTDemux_put_character,
154: HTDemux_put_string,
155: HTDemux_write
156: };
157:
1.1.2.2 frystyk 158: PUBLIC HTStream * HTDemux_new (HTHost * host, HTChannel * ch, HTMuxChannel * muxch)
1.1.2.1 frystyk 159: {
160: HTStream * me = NULL;
161: if (muxch) {
162: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
163: HT_OUTOFMEM("HTDemux_new");
164: me->isa = &HTDemux;
1.1.2.3 ! frystyk 165: me->muxch = muxch;
1.1.2.1 frystyk 166: }
167: return me;
168: }
Webmaster