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