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