Annotation of libwww/Library/src/HTWriter.c, revision 2.22
2.11 frystyk 1: /* HTWrite.c
2: ** FILE WRITER BASED ON A SOCKFD
2.1 timbl 3: **
2.15 frystyk 4: ** (c) COPYRIGHT MIT 1995.
2.11 frystyk 5: ** Please first read the full copyright statement in the file COPYRIGH.
2.14 frystyk 6: **
7: ** This is a try with a non-buffered output stream which remembers
8: ** state using the write_pointer. As normally we have a big buffer
9: ** somewhere else in the stream chain an extra output buffer will often
2.21 frystyk 10: ** not be needed. There is also a small buffer stream that can be used
11: ** if athis is not the case.
2.1 timbl 12: */
2.11 frystyk 13:
2.13 frystyk 14: /* Library include files */
15: #include "tcp.h"
16: #include "HTUtils.h"
17: #include "HTString.h"
2.17 frystyk 18: #include "HTReq.h"
2.18 frystyk 19: #include "HTNetMan.h"
2.21 frystyk 20: #include "HTConLen.h"
2.14 frystyk 21: #include "HTWriter.h" /* Implemented here */
2.1 timbl 22:
23: struct _HTStream {
24: CONST HTStreamClass * isa;
2.17 frystyk 25: SOCKFD sockfd;
26: HTNet * net;
2.21 frystyk 27: char *wptr;
2.17 frystyk 28: BOOL leave_open;
2.1 timbl 29: #ifdef NOT_ASCII
2.14 frystyk 30: BOOL make_ascii; /* Are we writing to the net? */
31: char * ascbuf; /* Buffer for TOASCII conversion */
2.1 timbl 32: #endif
33: };
34:
2.14 frystyk 35: /* ------------------------------------------------------------------------- */
2.1 timbl 36:
2.14 frystyk 37: /* Write to the socket
38: **
39: ** According to Solaris 2.3 man on write:
40: **
41: ** o If O_NONBLOCK and O_NDELAY are clear, write() blocks
42: ** until the data can be accepted.
43: **
44: ** o If O_NONBLOCK or O_NDELAY is set, write() does not
45: ** block the process. If some data can be written
46: ** without blocking the process, write() writes what it
47: ** can and returns the number of bytes written. Other-
48: ** wise, if O_NONBLOCK is set, it returns - 1 and sets
49: ** errno to EAGAIN or if O_NDELAY is set, it returns 0.
50: **
51: ** According to SunOS 4.1.1 man on write:
52: **
53: ** + If the descriptor is marked for non-blocking I/O
54: ** using fcntl() to set the FNONBLOCK or O_NONBLOCK
55: ** flag (defined in <sys/fcntl.h>), write() requests
56: ** for {PIPE_BUF} (see pathconf(2V)) or fewer bytes
57: ** either succeed completely and return nbyte, or
58: ** return -1 and set errno to EAGAIN. A write() request
59: ** for greater than {PIPE_BUF} bytes either transfers
60: ** what it can and returns the number of bytes written,
61: ** or transfers no data and returns -1 and sets errno
62: ** to EAGAIN. If a write() request is greater than
63: ** {PIPE_BUF} bytes and all data previously written to
64: ** the pipe has been read, write() transfers at least
65: ** {PIPE_BUF} bytes.
66: */
2.21 frystyk 67: PRIVATE int HTWriter_write (HTStream * me, CONST char * buf, int len)
2.14 frystyk 68: {
69: int b_write;
70: CONST char *limit = buf+len;
2.1 timbl 71:
2.9 frystyk 72: #ifdef NOT_ASCII
2.14 frystyk 73: if (me->make_ascii && len && !me->ascbuf) { /* Generate new buffer */
74: char *orig=buf;
75: char *dest;
76: int cnt;
77: me->ascbuf = (char *) malloc(len);
78: dest = me->ascbuf;
2.20 frystyk 79: for (cnt=0; cnt<len; cnt++) {
80: *dest = TOASCII(*orig);
81: dest++, orig++;
82: }
2.21 frystyk 83: me->wptr = me->ascbuf;
2.14 frystyk 84: limit = me->ascbuf+len;
2.1 timbl 85: }
2.14 frystyk 86: #else
2.21 frystyk 87: if (!me->wptr)
88: me->wptr = (char *) buf;
2.14 frystyk 89: else
2.21 frystyk 90: len -= (me->wptr - buf);
2.14 frystyk 91: #endif
92:
93: /* Write data to the network */
2.21 frystyk 94: while (me->wptr < limit) {
95: if ((b_write = NETWRITE(me->sockfd, me->wptr, len)) < 0) {
2.14 frystyk 96:
97: #ifdef EAGAIN
2.19 frystyk 98: if (socerrno == EAGAIN || socerrno == EWOULDBLOCK)/* POSIX, SVR4 */
2.14 frystyk 99: #else
2.19 frystyk 100: if (socerrno == EWOULDBLOCK) /* BSD */
2.1 timbl 101: #endif
2.14 frystyk 102: {
103: if (PROT_TRACE)
2.22 ! frystyk 104: TTYPrint(TDEST,"Write Socket WOULD BLOCK %d\n", me->sockfd);
2.17 frystyk 105: HTEvent_Register(me->sockfd,me->net->request,(SockOps)FD_WRITE,
106: me->net->cbf, me->net->priority);
2.14 frystyk 107: return HT_WOULD_BLOCK;
108: } else {
109: if (PROT_TRACE)
2.22 ! frystyk 110: TTYPrint(TDEST, "Write Socket WRITE ERROR %d\n", socerrno);
2.14 frystyk 111: return HT_ERROR;
112: }
2.1 timbl 113: }
2.17 frystyk 114: HTEvent_UnRegister(me->sockfd, (SockOps) FD_WRITE);
2.21 frystyk 115: me->wptr += b_write;
2.14 frystyk 116: len -= b_write;
117: if (PROT_TRACE)
2.22 ! frystyk 118: TTYPrint(TDEST, "Write Socket %d bytes written to socket %d\n",
2.17 frystyk 119: b_write, me->sockfd);
2.1 timbl 120: }
2.14 frystyk 121: #ifdef NOT_ASCII
122: FREE(me->ascbuf);
123: #else
2.21 frystyk 124: me->wptr = NULL;
2.14 frystyk 125: #endif
126: return HT_OK;
2.1 timbl 127: }
128:
129: /* Character handling
130: ** ------------------
131: */
2.21 frystyk 132: PRIVATE int HTWriter_put_character (HTStream * me, char c)
2.1 timbl 133: {
2.14 frystyk 134: return HTWriter_write(me, &c, 1);
2.1 timbl 135: }
136:
137: /* String handling
138: ** ---------------
139: **
140: ** Strings must be smaller than this buffer size.
141: */
2.21 frystyk 142: PRIVATE int HTWriter_put_string (HTStream * me, CONST char * s)
2.1 timbl 143: {
2.14 frystyk 144: return HTWriter_write(me, s, (int) strlen(s));
2.1 timbl 145: }
146:
2.21 frystyk 147: PRIVATE int HTWriter_flush (HTStream * me)
2.1 timbl 148: {
2.16 frystyk 149: return HT_OK; /* As we don't keep any buffer in this stream */
2.1 timbl 150: }
151:
2.21 frystyk 152: PRIVATE int HTWriter_free (HTStream * me)
2.1 timbl 153: {
2.14 frystyk 154: int status = HT_OK;
155: if (!me->leave_open) {
2.17 frystyk 156: if (NETCLOSE(me->sockfd) < 0)
2.14 frystyk 157: status = HT_ERROR;
158: }
2.2 timbl 159: free(me);
2.14 frystyk 160: return status;
2.1 timbl 161: }
162:
2.21 frystyk 163: PRIVATE int HTWriter_abort (HTStream * me, HTError e)
2.1 timbl 164: {
2.14 frystyk 165: if (!me->leave_open)
2.17 frystyk 166: NETCLOSE(me->sockfd);
2.14 frystyk 167: free(me);
168: return HT_ERROR;
2.1 timbl 169: }
170:
171:
172: /* Structured Object Class
173: ** -----------------------
174: */
2.14 frystyk 175: PRIVATE CONST HTStreamClass HTWriter =
2.1 timbl 176: {
2.14 frystyk 177: "SocketWriter",
178: HTWriter_flush,
179: HTWriter_free,
180: HTWriter_abort,
181: HTWriter_put_character,
182: HTWriter_put_string,
183: HTWriter_write
2.1 timbl 184: };
185:
186:
187: /* Subclass-specific Methods
188: ** -------------------------
189: */
2.17 frystyk 190: PUBLIC HTStream* HTWriter_new (HTNet *net, BOOL leave_open)
2.1 timbl 191: {
2.21 frystyk 192: HTStream* me = (HTStream *) calloc(1, sizeof(HTStream));
2.10 frystyk 193: if (me == NULL) outofmem(__FILE__, "HTWriter_new");
2.2 timbl 194: me->isa = &HTWriter;
2.14 frystyk 195: me->leave_open = leave_open;
2.17 frystyk 196: me->sockfd = net->sockfd;
197: me->net = net;
2.2 timbl 198: return me;
2.21 frystyk 199: }
200:
201: /*
202: ** Set up stream to write to a socket. If buf_size > 0 then we set up
203: ** buffered output used for at most buf_size bytes. From that point we
204: ** switch to unbuffered mode. Otherwise we'll use nonbuffered output.
205: */
206: PUBLIC HTStream* HTBufWriter_new (HTNet *net, BOOL leave_open, int buf_size)
207: {
208: return HTBuffer_new(HTWriter_new(net, leave_open), net->request, buf_size);
2.1 timbl 209: }
2.8 luotonen 210:
2.1 timbl 211: /* Subclass-specific Methods
212: ** -------------------------
213: */
2.14 frystyk 214: #ifdef NOT_ASCII
2.17 frystyk 215: PUBLIC HTStream* HTASCIIWriter (HTNet *net, BOOL leave_open)
2.1 timbl 216: {
2.14 frystyk 217: HTStream* me = (HTStream *) calloc(1, sizeof(*me));
218: if (me == NULL) outofmem(__FILE__, "HTASCIIWriter_new");
2.2 timbl 219: me->isa = &HTWriter;
2.14 frystyk 220: me->leave_open = leave_open;
2.2 timbl 221: me->make_ascii = YES;
2.17 frystyk 222: me->sockfd = net->sockfd;
223: me->net = net;
2.2 timbl 224: return me;
2.1 timbl 225: }
2.14 frystyk 226: #endif
Webmaster