Annotation of libwww/Library/src/HTWriter.c, revision 2.40.2.4

2.11      frystyk     1: /*                                                                   HTWrite.c
2.24      frystyk     2: **     FILE WRITER BASED ON A SOCKET
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.40.2.4! eric        6: **     @(#) $Id: HTWriter.c,v 2.40.2.3 1996/11/22 16:46:48 eric Exp $
2.14      frystyk     7: **
                      8: **     This is a try with a non-buffered output stream which remembers
                      9: **     state using the write_pointer. As normally we have a big buffer
                     10: **     somewhere else in the stream chain an extra output buffer will often
2.34      frystyk    11: **     not be needed.
2.1       timbl      12: */
2.11      frystyk    13: 
2.13      frystyk    14: /* Library include files */
2.31      frystyk    15: #include "sysdep.h"
2.33      frystyk    16: #include "WWWUtil.h"
2.34      frystyk    17: #include "WWWCore.h"
2.40.2.1  eric       18: #include "HTNet.h"
2.18      frystyk    19: #include "HTNetMan.h"
2.40.2.4! eric       20: #include "HTWatch.h"
2.14      frystyk    21: #include "HTWriter.h"                                   /* Implemented here */
2.1       timbl      22: 
                     23: struct _HTStream {
2.33      frystyk    24:     const HTStreamClass *      isa;
                     25:     /* ... */
                     26: };
                     27: 
                     28: struct _HTOutputStream {
                     29:     const HTOutputStreamClass *        isa;
                     30:     HTChannel *                        ch;
2.40.2.2  frystyk    31:     HTHost *                   host;
2.33      frystyk    32:     char *                     write;
2.1       timbl      33: #ifdef NOT_ASCII
2.33      frystyk    34:     char *                     ascbuf;     /* Buffer for TOASCII conversion */
2.1       timbl      35: #endif
                     36: };
                     37: 
2.14      frystyk    38: /* ------------------------------------------------------------------------- */
2.1       timbl      39: 
2.33      frystyk    40: PRIVATE int HTWriter_flush (HTOutputStream * me)
                     41: {
                     42:     return HT_OK;                     /* As we don't have any output buffer */
                     43: }
                     44: 
                     45: PRIVATE int HTWriter_free (HTOutputStream * me)
                     46: {
                     47:     return HT_OK;
                     48: }
                     49: 
                     50: PRIVATE int HTWriter_abort (HTOutputStream * me, HTList * e)
                     51: {
                     52:     return HT_ERROR;
                     53: }
                     54: 
2.14      frystyk    55: /*     Write to the socket
                     56: **
                     57: ** According to Solaris 2.3 man on write:
                     58: **
                     59: **    o        If O_NONBLOCK and O_NDELAY are clear, write() blocks
                     60: **     until the data can be accepted.
                     61: **
                     62: **    o        If O_NONBLOCK or O_NDELAY is set, write()  does  not
                     63: **     block  the  process.   If  some  data  can be written
                     64: **     without blocking the process, write() writes what  it
                     65: **     can  and returns the number of bytes written.  Other-
                     66: **     wise, if O_NONBLOCK is set, it returns - 1  and  sets
                     67: **     errno to EAGAIN or if O_NDELAY is set, it returns 0.
                     68: **
                     69: ** According to SunOS 4.1.1 man on write:
                     70: **
                     71: **   + If the descriptor is  marked  for  non-blocking  I/O
                     72: **     using  fcntl()  to  set  the FNONBLOCK or O_NONBLOCK
                     73: **     flag (defined in  <sys/fcntl.h>),  write()  requests
                     74: **     for  {PIPE_BUF}  (see  pathconf(2V))  or fewer bytes
                     75: **     either  succeed  completely  and  return  nbyte,  or
                     76: **     return -1 and set errno to EAGAIN. A write() request
                     77: **     for greater than {PIPE_BUF} bytes  either  transfers
                     78: **     what it can and returns the number of bytes written,
                     79: **     or transfers no data and returns -1 and  sets  errno
                     80: **     to  EAGAIN.  If  a  write()  request is greater than
                     81: **     {PIPE_BUF} bytes and all data previously written  to
                     82: **     the  pipe  has been read, write() transfers at least
                     83: **     {PIPE_BUF} bytes.
                     84: */
2.33      frystyk    85: PRIVATE int HTWriter_write (HTOutputStream * me, const char * buf, int len)
2.14      frystyk    86: {
2.40.2.2  frystyk    87:     HTHost * host = me->host;
                     88:     SOCKET soc = HTChannel_socket(HTHost_channel(host));
                     89:     HTNet * net = HTHost_getWriteNet(host);
2.14      frystyk    90:     int b_write;
2.31      frystyk    91:     const char *limit = buf+len;
2.1       timbl      92: 
2.9       frystyk    93: #ifdef NOT_ASCII
2.34      frystyk    94:     if (len && !me->ascbuf) {                        /* Generate new buffer */
                     95:        const char *orig = buf;
2.14      frystyk    96:        char *dest;
                     97:        int cnt;
2.29      frystyk    98:        if ((me->ascbuf = (char  *) HT_MALLOC(len)) == NULL)
2.34      frystyk    99:            HT_OUTOFMEM("HTWriter_write");
2.14      frystyk   100:        dest = me->ascbuf;
2.20      frystyk   101:        for (cnt=0; cnt<len; cnt++) {
                    102:            *dest = TOASCII(*orig);
                    103:            dest++, orig++;
                    104:        }
2.33      frystyk   105:        me->write = me->ascbuf;
2.14      frystyk   106:        limit = me->ascbuf+len;
2.1       timbl     107:     }
2.14      frystyk   108: #else
2.33      frystyk   109:     if (!me->write)
                    110:        me->write = (char *) buf;
2.14      frystyk   111:     else
2.33      frystyk   112:        len -= (me->write - buf);
2.14      frystyk   113: #endif
                    114: 
                    115:     /* Write data to the network */
2.33      frystyk   116:     while (me->write < limit) {
                    117:        if ((b_write = NETWRITE(soc, me->write, len)) < 0) {
2.14      frystyk   118: #ifdef EAGAIN
2.19      frystyk   119:            if (socerrno == EAGAIN || socerrno == EWOULDBLOCK)/* POSIX, SVR4 */
2.14      frystyk   120: #else
2.19      frystyk   121:            if (socerrno == EWOULDBLOCK)                              /* BSD */
2.1       timbl     122: #endif
2.14      frystyk   123:            {
                    124:                if (PROT_TRACE)
2.33      frystyk   125:                    HTTrace("Write Socket WOULD BLOCK %d\n",soc);
2.40.2.2  frystyk   126:                HTHost_register(host, net, HTEvent_WRITE);
2.14      frystyk   127:                return HT_WOULD_BLOCK;
2.39      frystyk   128: #ifdef EINTR
2.37      frystyk   129:            } else if (socerrno == EINTR) {
                    130:                /*
                    131:                **      EINTR   A signal was caught during the  write  opera-
                    132:                **              tion and no data was transferred.
                    133:                */
                    134:                if (PROT_TRACE)
                    135:                    HTTrace("Write Socket call interruted - try again\n");
                    136:                continue;
2.39      frystyk   137: #endif
2.14      frystyk   138:            } else {
2.33      frystyk   139:                HTRequest_addSystemError(net->request, ERR_FATAL, socerrno, NO,
2.28      frystyk   140:                                         "NETWRITE");
2.14      frystyk   141:                return HT_ERROR;
                    142:            }
2.1       timbl     143:        }
2.40.2.1  eric      144:        /* We do this unconditionally, should we check to see if we ever blocked? */
2.40.2.2  frystyk   145:        HTHost_unregister(host, net, HTEvent_WRITE);
2.40.2.3  eric      146:        HTWatch_logData(me->write, b_write, "HTWriter_write");
2.33      frystyk   147:        me->write += b_write;
2.14      frystyk   148:        len -= b_write;
                    149:        if (PROT_TRACE)
2.30      eric      150:            HTTrace("Write Socket %d bytes written to socket %d\n",
2.33      frystyk   151:                    b_write, soc);
2.39      frystyk   152: #if 0
2.28      frystyk   153:        net->bytes_written += b_write;
2.39      frystyk   154: #endif
2.28      frystyk   155:        {
                    156:            HTAlertCallback *cbf = HTAlert_find(HT_PROG_READ);
2.33      frystyk   157:            if (cbf) (*cbf)(net->request, HT_PROG_WRITE,
                    158:                            HT_MSG_NULL, NULL, NULL, NULL);
2.28      frystyk   159:        }
2.1       timbl     160:     }
2.14      frystyk   161: #ifdef NOT_ASCII
2.29      frystyk   162:     HT_FREE(me->ascbuf);
2.14      frystyk   163: #else
2.33      frystyk   164:     me->write = NULL;
2.14      frystyk   165: #endif
                    166:     return HT_OK;
2.1       timbl     167: }
                    168: 
                    169: /*     Character handling
                    170: **     ------------------
                    171: */
2.33      frystyk   172: PRIVATE int HTWriter_put_character (HTOutputStream * me, char c)
2.1       timbl     173: {
2.14      frystyk   174:     return HTWriter_write(me, &c, 1);
2.1       timbl     175: }
                    176: 
                    177: /*     String handling
                    178: **     ---------------
                    179: **
                    180: **     Strings must be smaller than this buffer size.
                    181: */
2.33      frystyk   182: PRIVATE int HTWriter_put_string (HTOutputStream * me, const char * s)
2.1       timbl     183: {
2.14      frystyk   184:     return HTWriter_write(me, s, (int) strlen(s));
2.1       timbl     185: }
2.33      frystyk   186: /*
                    187: **     The difference between the close and the free method is that we don't
                    188: **     close the connection in the free method - we only call the free method
                    189: **     of the target stream. That way, we can keep the output stream as long 
                    190: **     as the channel itself.
                    191: */
                    192: PRIVATE int HTWriter_close (HTOutputStream * me)
2.1       timbl     193: {
2.33      frystyk   194:     if (PROT_TRACE) HTTrace("Socket write FREEING....\n");
2.29      frystyk   195:     HT_FREE(me);
2.33      frystyk   196:     return HT_OK;
2.1       timbl     197: }
                    198: 
2.33      frystyk   199: PRIVATE const HTOutputStreamClass HTWriter =
2.1       timbl     200: {              
2.14      frystyk   201:     "SocketWriter",
                    202:     HTWriter_flush,
                    203:     HTWriter_free,
                    204:     HTWriter_abort,
                    205:     HTWriter_put_character,
                    206:     HTWriter_put_string,
2.33      frystyk   207:     HTWriter_write,
                    208:     HTWriter_close
2.1       timbl     209: }; 
                    210: 
2.40.2.2  frystyk   211: PUBLIC HTOutputStream * HTWriter_new (HTHost * host, HTChannel * ch,
2.33      frystyk   212:                                      void * param, int mode)
2.1       timbl     213: {
2.40.2.2  frystyk   214:     if (host && ch) {
2.33      frystyk   215:        HTOutputStream * me = HTChannel_output(ch);
2.40.2.2  frystyk   216:        if (!me) {
2.33      frystyk   217:            if ((me=(HTOutputStream *) HT_CALLOC(1, sizeof(HTOutputStream)))==NULL)
                    218:                HT_OUTOFMEM("HTWriter_new");
                    219:            me->isa = &HTWriter;
                    220:            me->ch = ch;
2.40.2.2  frystyk   221:            me->host = host;
2.33      frystyk   222:        }
                    223:        return me;
                    224:     }
                    225:     return NULL;
2.21      frystyk   226: }

Webmaster