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

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

Webmaster