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

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.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.28      frystyk    21: #include "HTAlert.h"
2.14      frystyk    22: #include "HTWriter.h"                                   /* Implemented here */
2.1       timbl      23: 
                     24: struct _HTStream {
                     25:        CONST HTStreamClass *   isa;
2.24      frystyk    26:        SOCKET                  sockfd;
2.17      frystyk    27:        HTNet *                 net;
2.21      frystyk    28:        char                    *wptr;
2.17      frystyk    29:        BOOL                    leave_open;
2.1       timbl      30: #ifdef NOT_ASCII
2.14      frystyk    31:        BOOL                    make_ascii;    /* Are we writing to the net? */
                     32:        char *                  ascbuf;     /* Buffer for TOASCII conversion */
2.1       timbl      33: #endif
                     34: };
                     35: 
2.14      frystyk    36: /* ------------------------------------------------------------------------- */
2.1       timbl      37: 
2.14      frystyk    38: /*     Write to the socket
                     39: **
                     40: ** According to Solaris 2.3 man on write:
                     41: **
                     42: **    o        If O_NONBLOCK and O_NDELAY are clear, write() blocks
                     43: **     until the data can be accepted.
                     44: **
                     45: **    o        If O_NONBLOCK or O_NDELAY is set, write()  does  not
                     46: **     block  the  process.   If  some  data  can be written
                     47: **     without blocking the process, write() writes what  it
                     48: **     can  and returns the number of bytes written.  Other-
                     49: **     wise, if O_NONBLOCK is set, it returns - 1  and  sets
                     50: **     errno to EAGAIN or if O_NDELAY is set, it returns 0.
                     51: **
                     52: ** According to SunOS 4.1.1 man on write:
                     53: **
                     54: **   + If the descriptor is  marked  for  non-blocking  I/O
                     55: **     using  fcntl()  to  set  the FNONBLOCK or O_NONBLOCK
                     56: **     flag (defined in  <sys/fcntl.h>),  write()  requests
                     57: **     for  {PIPE_BUF}  (see  pathconf(2V))  or fewer bytes
                     58: **     either  succeed  completely  and  return  nbyte,  or
                     59: **     return -1 and set errno to EAGAIN. A write() request
                     60: **     for greater than {PIPE_BUF} bytes  either  transfers
                     61: **     what it can and returns the number of bytes written,
                     62: **     or transfers no data and returns -1 and  sets  errno
                     63: **     to  EAGAIN.  If  a  write()  request is greater than
                     64: **     {PIPE_BUF} bytes and all data previously written  to
                     65: **     the  pipe  has been read, write() transfers at least
                     66: **     {PIPE_BUF} bytes.
                     67: */
2.21      frystyk    68: PRIVATE int HTWriter_write (HTStream * me, CONST char * buf, int len)
2.14      frystyk    69: {
                     70:     int b_write;
                     71:     CONST char *limit = buf+len;
2.28      frystyk    72:     HTRequest * request = me->net->request;
                     73:     HTNet * net = me->net;
2.1       timbl      74: 
2.9       frystyk    75: #ifdef NOT_ASCII
2.14      frystyk    76:     if (me->make_ascii && len && !me->ascbuf) {              /* Generate new buffer */
                     77:        char *orig=buf;
                     78:        char *dest;
                     79:        int cnt;
2.29    ! frystyk    80:        if ((me->ascbuf = (char  *) HT_MALLOC(len)) == NULL)
        !            81:            HT_OUTOFMEM("me->ascbuf ");
2.14      frystyk    82:        dest = me->ascbuf;
2.20      frystyk    83:        for (cnt=0; cnt<len; cnt++) {
                     84:            *dest = TOASCII(*orig);
                     85:            dest++, orig++;
                     86:        }
2.21      frystyk    87:        me->wptr = me->ascbuf;
2.14      frystyk    88:        limit = me->ascbuf+len;
2.1       timbl      89:     }
2.14      frystyk    90: #else
2.21      frystyk    91:     if (!me->wptr)
                     92:        me->wptr = (char *) buf;
2.14      frystyk    93:     else
2.21      frystyk    94:        len -= (me->wptr - buf);
2.14      frystyk    95: #endif
                     96: 
                     97:     /* Write data to the network */
2.21      frystyk    98:     while (me->wptr < limit) {
                     99:        if ((b_write = NETWRITE(me->sockfd, me->wptr, len)) < 0) {
2.14      frystyk   100: 
                    101: #ifdef EAGAIN
2.19      frystyk   102:            if (socerrno == EAGAIN || socerrno == EWOULDBLOCK)/* POSIX, SVR4 */
2.14      frystyk   103: #else
2.19      frystyk   104:            if (socerrno == EWOULDBLOCK)                              /* BSD */
2.1       timbl     105: #endif
2.14      frystyk   106:            {
                    107:                if (PROT_TRACE)
2.28      frystyk   108:                    TTYPrint(TDEST,"Write Socket WOULD BLOCK %d\n",me->sockfd);
                    109:                HTEvent_Register(me->sockfd, request, (SockOps) FD_WRITE,
                    110:                                 net->cbf, net->priority);
2.14      frystyk   111:                return HT_WOULD_BLOCK;
                    112:            } else {
2.28      frystyk   113:                HTRequest_addSystemError(request,  ERR_FATAL, socerrno, NO,
                    114:                                         "NETWRITE");
2.14      frystyk   115:                return HT_ERROR;
                    116:            }
2.1       timbl     117:        }
2.17      frystyk   118:        HTEvent_UnRegister(me->sockfd, (SockOps) FD_WRITE);
2.21      frystyk   119:        me->wptr += b_write;
2.14      frystyk   120:        len -= b_write;
                    121:        if (PROT_TRACE)
2.22      frystyk   122:            TTYPrint(TDEST, "Write Socket %d bytes written to socket %d\n",
2.17      frystyk   123:                    b_write, me->sockfd);
2.28      frystyk   124:        net->bytes_written += b_write;
                    125:        {
                    126:            HTAlertCallback *cbf = HTAlert_find(HT_PROG_READ);
                    127:            if (cbf) (*cbf)(request, HT_PROG_WRITE,HT_MSG_NULL,NULL,NULL,NULL);
                    128:        }
2.1       timbl     129:     }
2.14      frystyk   130: #ifdef NOT_ASCII
2.29    ! frystyk   131:     HT_FREE(me->ascbuf);
2.14      frystyk   132: #else
2.21      frystyk   133:     me->wptr = NULL;
2.14      frystyk   134: #endif
                    135:     return HT_OK;
2.1       timbl     136: }
                    137: 
                    138: /*     Character handling
                    139: **     ------------------
                    140: */
2.21      frystyk   141: PRIVATE int HTWriter_put_character (HTStream * me, char c)
2.1       timbl     142: {
2.14      frystyk   143:     return HTWriter_write(me, &c, 1);
2.1       timbl     144: }
                    145: 
                    146: /*     String handling
                    147: **     ---------------
                    148: **
                    149: **     Strings must be smaller than this buffer size.
                    150: */
2.21      frystyk   151: PRIVATE int HTWriter_put_string (HTStream * me, CONST char * s)
2.1       timbl     152: {
2.14      frystyk   153:     return HTWriter_write(me, s, (int) strlen(s));
2.1       timbl     154: }
                    155: 
2.21      frystyk   156: PRIVATE int HTWriter_flush (HTStream * me)
2.1       timbl     157: {
2.16      frystyk   158:     return HT_OK;             /* As we don't keep any buffer in this stream */
2.1       timbl     159: }
                    160: 
2.21      frystyk   161: PRIVATE int HTWriter_free (HTStream * me)
2.1       timbl     162: {
2.14      frystyk   163:     int status = HT_OK;
                    164:     if (!me->leave_open) {
2.17      frystyk   165:        if (NETCLOSE(me->sockfd) < 0)
2.14      frystyk   166:            status = HT_ERROR;
                    167:     }
2.29    ! frystyk   168:     HT_FREE(me);
2.14      frystyk   169:     return status;
2.1       timbl     170: }
                    171: 
2.23      frystyk   172: PRIVATE int HTWriter_abort (HTStream * me, HTList * e)
2.1       timbl     173: {
2.14      frystyk   174:     if (!me->leave_open)
2.17      frystyk   175:        NETCLOSE(me->sockfd);
2.29    ! frystyk   176:     HT_FREE(me);
2.14      frystyk   177:     return HT_ERROR;
2.1       timbl     178: }
                    179: 
                    180: 
                    181: /*     Structured Object Class
                    182: **     -----------------------
                    183: */
2.14      frystyk   184: PRIVATE CONST HTStreamClass HTWriter =
2.1       timbl     185: {              
2.14      frystyk   186:     "SocketWriter",
                    187:     HTWriter_flush,
                    188:     HTWriter_free,
                    189:     HTWriter_abort,
                    190:     HTWriter_put_character,
                    191:     HTWriter_put_string,
                    192:     HTWriter_write
2.1       timbl     193: }; 
                    194: 
                    195: 
                    196: /*     Subclass-specific Methods
                    197: **     -------------------------
                    198: */
2.17      frystyk   199: PUBLIC HTStream* HTWriter_new (HTNet *net, BOOL leave_open)
2.1       timbl     200: {
2.29    ! frystyk   201:     HTStream* me;
        !           202:     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
        !           203:         HT_OUTOFMEM("HTWriter_new");
2.2       timbl     204:     me->isa = &HTWriter;       
2.14      frystyk   205:     me->leave_open = leave_open;
2.17      frystyk   206:     me->sockfd = net->sockfd;
                    207:     me->net = net;
2.2       timbl     208:     return me;
2.21      frystyk   209: }
                    210: 
                    211: /*
                    212: **     Set up stream to write to a socket. If buf_size > 0 then we set up
                    213: **     buffered output used for at most buf_size bytes. From that point we 
                    214: **     switch to unbuffered mode. Otherwise we'll use nonbuffered output.
                    215: */
                    216: PUBLIC HTStream* HTBufWriter_new (HTNet *net, BOOL leave_open, int buf_size)
                    217: {
                    218:     return HTBuffer_new(HTWriter_new(net, leave_open), net->request, buf_size);
2.1       timbl     219: }
2.8       luotonen  220: 
2.1       timbl     221: /*     Subclass-specific Methods
                    222: **     -------------------------
                    223: */
2.26      frystyk   224: #ifdef NOT_ASCII
2.25      frystyk   225: PUBLIC HTStream * HTASCIIWriter (HTNet *net, BOOL leave_open)
2.1       timbl     226: {
2.29    ! frystyk   227:     HTStream * me;
        !           228:     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(*me))) == NULL)
        !           229:         HT_OUTOFMEM("HTASCIIWriter_new");
2.2       timbl     230:     me->isa = &HTWriter;       
2.14      frystyk   231:     me->leave_open = leave_open;
2.2       timbl     232:     me->make_ascii = YES;
2.17      frystyk   233:     me->sockfd = net->sockfd;
                    234:     me->net = net;
2.2       timbl     235:     return me;
2.1       timbl     236: }
2.26      frystyk   237: #else
                    238: #ifdef WWW_WIN_DLL
2.27      frystyk   239: PUBLIC HTStream * HTASCIIWriter (HTNet *net, BOOL leave_open)
                    240: {
                    241:     return NULL;
                    242: }
2.26      frystyk   243: #endif /* WWW_WIN_DLL */
                    244: #endif /* NOT_ASCII */

Webmaster