Annotation of libwww/Library/src/HTDemux.c, revision 1.1.2.2
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.2 ! frystyk 6: ** @(#) $Id: HTDemux.c,v 1.1.2.1 1996/10/30 23:21:53 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 "HTSession.h"
24: #include "HTDemux.h" /* Implemented here */
25:
26: struct _HTStream {
27: const HTStreamClass * isa;
1.1.2.2 ! frystyk 28: HTChannel * ch;
1.1.2.1 frystyk 29: HTMuxChannel * muxch;
30: HTHost * host;
1.1.2.2 ! frystyk 31: HTSession * session;
1.1.2.1 frystyk 32: int next; /* Next header */
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: HTSessionId sid = INVSID;
! 53: HTMuxHeader header[2];
! 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.2 ! 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: }
68: length = HTMIN(len, me->next);
1.1.2.2 ! frystyk 69: sid = MUX_GET_SID(header[0]);
1.1.2.1 frystyk 70:
71: /*
1.1.2.2 ! frystyk 72: ** If this is a control message then handle it here
! 73: */
! 74: if (header[0] & MUX_CONTROL) {
! 75: if (header[0] & MUX_STRING) {
! 76:
! 77: ; /* Define the string */
! 78:
! 79: } else if (header[0] & MUX_STACK) {
! 80:
! 81: ; /* Define the stack */
! 82:
! 83: } else if (header[0] & MUX_FRAGMENT) {
! 84: HTSession * ses = HTMuxChannel_findSessionFromId(muxch, sid);
! 85:
! 86: ; /* Assign the fragment size */
! 87:
! 88: } else if (header[0] & MUX_CREDIT) {
! 89: HTSession * ses = HTMuxChannel_findSessionFromId(muxch, sid);
! 90:
! 91: ; /* Assign the fragment size */
! 92:
! 93: }
! 94: } else if (header[0] & MUX_SYN) {
! 95:
! 96: ; /* Register new session */
! 97:
! 98: } else {
! 99:
! 100: /*
! 101: ** Remember any data flags in this session so we know how and
! 102: ** when to terminate the session.
! 103: */
! 104: if ((me->session = HTMuxChannel_findSessionFromId(muxch, sid)))
! 105: HTSession_setState(me->session, header[0]);
! 106: }
! 107: }
! 108:
! 109: /*
! 110: ** If there is data on this session then handle it here.
! 111: */
! 112: if (me->next && me->session) {
! 113: HTNet * net = HTSession_net(me->session);
! 114: HTStream * sink = HTNet_readStream(net);
! 115: int status = sink ? (*sink->isa->put_block)(sink, buf, length) : HT_ERROR;
! 116:
! 117: /*
! 118: ** Now see what the stream responded and pass this information
! 119: ** back to the sender.
! 120: */
! 121: if (status == HT_OK) {
! 122:
! 123: /* Generate a credit message */
! 124:
! 125: } else {
! 126: if (status == HT_WOULD_BLOCK || status == HT_PAUSE) {
! 127: if (PROT_TRACE) HTTrace("Demux....... Target PAUSING\n");
! 128:
! 129: /* Save data in extra buffer */
! 130:
! 131: } else {
! 132: if (PROT_TRACE) HTTrace("Demux....... Target ERROR\n");
! 133:
! 134: /* Send a RST on this session */
! 135:
1.1.2.1 frystyk 136: }
137: }
1.1.2.2 ! frystyk 138: me->next -= length;
1.1.2.1 frystyk 139: }
1.1.2.2 ! frystyk 140: buf += length, len -= length;
1.1.2.1 frystyk 141: }
142: return HT_OK;
143: }
144:
145: PRIVATE int HTDemux_put_character (HTStream * me, char c)
146: {
147: return HTDemux_write(me, &c, 1);
148: }
149:
150: PRIVATE int HTDemux_put_string (HTStream * me, const char * s)
151: {
152: return HTDemux_write(me, s, (int) strlen(s));
153: }
154:
155: PRIVATE int HTDemux_flush (HTStream * me)
156: {
157: return HT_OK;
158: }
159:
160: PRIVATE int HTDemux_free (HTStream * me)
161: {
162: return HTDemux_flush(me);
163: }
164:
165: PRIVATE int HTDemux_abort (HTStream * me, HTList * e)
166: {
167: if (PROT_TRACE) HTTrace("MUX Tx...... ABORTING...\n");
168: return HT_ERROR;
169: }
170:
171: PRIVATE const HTStreamClass HTDemux =
172: {
173: "Demux",
174: HTDemux_flush,
175: HTDemux_free,
176: HTDemux_abort,
177: HTDemux_put_character,
178: HTDemux_put_string,
179: HTDemux_write
180: };
181:
1.1.2.2 ! frystyk 182: PUBLIC HTStream * HTDemux_new (HTHost * host, HTChannel * ch, HTMuxChannel * muxch)
1.1.2.1 frystyk 183: {
184: HTStream * me = NULL;
185: if (muxch) {
186: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
187: HT_OUTOFMEM("HTDemux_new");
188: me->isa = &HTDemux;
1.1.2.2 ! frystyk 189: me->muxch = muxch;
1.1.2.1 frystyk 190: }
191: return me;
192: }
Webmaster