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