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