[BACK] Return to HTWriter.c CVS log [TXT] [DIR] Up to [Public] / libwww / Library / src

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

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.56 ! kahan 6: **   @(#) $Id: HTWriter.c,v 2.55 1999年04月04日 00:13:21 frystyk 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.49 frystyk 15: #include "wwwsys.h"
2.33 frystyk 16: #include "WWWUtil.h"
2.34 frystyk 17: #include "WWWCore.h"
2.41 frystyk 18: #include "HTNet.h"
2.18 frystyk 19: #include "HTNetMan.h"
2.14 frystyk 20: #include "HTWriter.h"                  /* Implemented here */
2.1 timbl 21: 
2.50 frystyk 22: #include "HTHstMan.h"
 23: 
2.1 timbl 24: struct _HTStream {
2.33 frystyk 25:   const HTStreamClass *   isa;
 26:   /* ... */
 27: };
 28: 
 29: struct _HTOutputStream {
 30:   const HTOutputStreamClass *    isa;
 31:   HTChannel *            ch;
2.41 frystyk 32:   HTHost *          host;
2.48 frystyk 33:   int                offset;
2.1 timbl 34: #ifdef NOT_ASCII
2.33 frystyk 35:   char *           ascbuf;   /* Buffer for TOASCII conversion */
2.1 timbl 36: #endif
 37: };
 38: 
2.14 frystyk 39: /* ------------------------------------------------------------------------- */
2.1 timbl 40: 
2.33 frystyk 41: PRIVATE int HTWriter_flush (HTOutputStream * me)
 42: {
 43:   return HT_OK;           /* As we don't have any output buffer */
 44: }
 45: 
 46: PRIVATE int HTWriter_free (HTOutputStream * me)
 47: {
 48:   return HT_OK;
 49: }
 50: 
 51: PRIVATE int HTWriter_abort (HTOutputStream * me, HTList * e)
 52: {
 53:   return HT_ERROR;
 54: }
 55: 
2.14 frystyk 56: /*   Write to the socket
 57: **
 58: ** According to Solaris 2.3 man on write:
 59: **
 60: **  o    If O_NONBLOCK and O_NDELAY are clear, write() blocks
 61: **   until the data can be accepted.
 62: **
 63: **  o    If O_NONBLOCK or O_NDELAY is set, write() does not
 64: **   block the process.  If some data can be written
 65: **   without blocking the process, write() writes what it
 66: **   can and returns the number of bytes written. Other-
 67: **   wise, if O_NONBLOCK is set, it returns - 1 and sets
 68: **   errno to EAGAIN or if O_NDELAY is set, it returns 0.
 69: **
 70: ** According to SunOS 4.1.1 man on write:
 71: **
 72: **  + If the descriptor is marked for non-blocking I/O
 73: **   using fcntl() to set the FNONBLOCK or O_NONBLOCK
 74: **   flag (defined in <sys/fcntl.h>), write() requests
 75: **   for {PIPE_BUF} (see pathconf(2V)) or fewer bytes
 76: **   either succeed completely and return nbyte, or
 77: **   return -1 and set errno to EAGAIN. A write() request
 78: **   for greater than {PIPE_BUF} bytes either transfers
 79: **   what it can and returns the number of bytes written,
 80: **   or transfers no data and returns -1 and sets errno
 81: **   to EAGAIN. If a write() request is greater than
 82: **   {PIPE_BUF} bytes and all data previously written to
 83: **   the pipe has been read, write() transfers at least
 84: **   {PIPE_BUF} bytes.
 85: */
2.33 frystyk 86: PRIVATE int HTWriter_write (HTOutputStream * me, const char * buf, int len)
2.14 frystyk 87: {
2.41 frystyk 88:   HTHost * host = me->host;
 89:   SOCKET soc = HTChannel_socket(HTHost_channel(host));
 90:   HTNet * net = HTHost_getWriteNet(host);
2.14 frystyk 91:   int b_write;
2.48 frystyk 92:   char * wrtp;
2.31 frystyk 93:   const char *limit = buf+len;
2.1 timbl 94: 
2.50 frystyk 95:   /* If we don't have a Net object then return right away */
 96:   if (!net) {
2.55 frystyk 97:    HTTRACE(STREAM_TRACE, "Write Socket No Net object %d (offset %d)\n" _ soc _ me->offset);
2.50 frystyk 98:    return HT_ERROR;
 99:   }
 100: 
2.9 frystyk 101: #ifdef NOT_ASCII
2.34 frystyk 102:   if (len && !me->ascbuf) {            /* Generate new buffer */
 103:    const char *orig = buf;
2.14 frystyk 104:    char *dest;
 105:    int cnt;
2.29 frystyk 106:    if ((me->ascbuf = (char *) HT_MALLOC(len)) == NULL)
2.34 frystyk 107:      HT_OUTOFMEM("HTWriter_write");
2.14 frystyk 108:    dest = me->ascbuf;
2.20 frystyk 109:    for (cnt=0; cnt<len; cnt++) {
 110:      *dest = TOASCII(*orig);
 111:      dest++, orig++;
 112:    }
2.48 frystyk 113:    wrtp = me->ascbuf;
2.14 frystyk 114:    limit = me->ascbuf+len;
2.1 timbl 115:   }
2.14 frystyk 116: #else
2.48 frystyk 117:   if (!me->offset)
 118:    wrtp = (char *) buf;
 119:   else {
 120:    wrtp = (char *) buf + me->offset;
 121:    len -= me->offset;
 122:    me->offset = 0;
 123:   }
2.14 frystyk 124: #endif
 125: 
 126:   /* Write data to the network */
2.48 frystyk 127:   while (wrtp < limit) {
 128:    if ((b_write = NETWRITE(soc, wrtp, len)) < 0) {
2.14 frystyk 129: #ifdef EAGAIN
2.19 frystyk 130:      if (socerrno == EAGAIN || socerrno == EWOULDBLOCK)/* POSIX, SVR4 */
2.14 frystyk 131: #else
2.19 frystyk 132:      if (socerrno == EWOULDBLOCK)               /* BSD */
2.1 timbl 133: #endif
2.14 frystyk 134:      {
2.48 frystyk 135:        HTHost_register(host, net, HTEvent_WRITE);
 136:        me->offset = wrtp - buf;
2.54 frystyk 137:        HTTRACE(STREAM_TRACE, "Write Socket WOULD BLOCK %d (offset %d)\n" _ soc _ me->offset);
2.14 frystyk 138:        return HT_WOULD_BLOCK;
2.39 frystyk 139: #ifdef EINTR
2.37 frystyk 140:      } else if (socerrno == EINTR) {
 141:        /*
 142:        **   EINTR  A signal was caught during the write opera-
 143:        **       tion and no data was transferred.
 144:        */
2.56 ! kahan 145:        HTTRACE(STREAM_TRACE, "Write Socket call interrupted - try again\n");
2.37 frystyk 146:        continue;
2.39 frystyk 147: #endif
2.14 frystyk 148:      } else {
2.56 ! kahan 149:        host->broken_pipe = YES;
2.43 frystyk 150: #ifdef EPIPE
2.56 ! kahan 151:        if (socerrno == EPIPE) {
 ! 152:          /* JK: an experimental bug solution proposed by
 ! 153:            Olga and Mikhael */
2.54 frystyk 154:          HTTRACE(STREAM_TRACE, "Write Socket got EPIPE\n");
2.56 ! kahan 155:          HTHost_unregister(host, net, HTEvent_WRITE);
 ! 156:          HTHost_register(host, net, HTEvent_CLOSE);
 ! 157:          /* @@ JK: seems that some functions check the errors 
 ! 158:            as part of the flow control */
 ! 159:           HTRequest_addSystemError(net->request, ERR_FATAL, socerrno, NO,
 ! 160:                       "NETWRITE");
 ! 161:          return HT_CLOSED;        
 ! 162:        }
2.43 frystyk 163: #endif /* EPIPE */
2.56 ! kahan 164:        /* all errors that aren't EPIPE */
2.33 frystyk 165:        HTRequest_addSystemError(net->request, ERR_FATAL, socerrno, NO,
2.28 frystyk 166:                     "NETWRITE");
2.14 frystyk 167:        return HT_ERROR;
 168:      }
2.1 timbl 169:    }
2.47 frystyk 170: 
2.41 frystyk 171:    /* We do this unconditionally, should we check to see if we ever blocked? */
2.54 frystyk 172:    HTTRACEDATA(wrtp, b_write, "Writing to socket %d" _ soc);
2.51 frystyk 173:    HTNet_addBytesWritten(net, b_write);
2.48 frystyk 174:    wrtp += b_write;
2.14 frystyk 175:    len -= b_write;
2.54 frystyk 176:    HTTRACE(STREAM_TRACE, "Write Socket %d bytes written to %d\n" _ b_write _ soc);
2.28 frystyk 177:    {
2.52 frystyk 178:      HTAlertCallback *cbf = HTAlert_find(HT_PROG_WRITE);
2.53 frystyk 179:      if (cbf) {
 180:        int tw = HTNet_bytesWritten(net);
 181:        (*cbf)(net->request, HT_PROG_WRITE,
 182:            HT_MSG_NULL, NULL, &tw, NULL);
 183:      }
2.28 frystyk 184:    }
2.1 timbl 185:   }
2.14 frystyk 186: #ifdef NOT_ASCII
2.29 frystyk 187:   HT_FREE(me->ascbuf);
2.14 frystyk 188: #endif
 189:   return HT_OK;
2.1 timbl 190: }
 191: 
 192: /*   Character handling
 193: **   ------------------
 194: */
2.33 frystyk 195: PRIVATE int HTWriter_put_character (HTOutputStream * me, char c)
2.1 timbl 196: {
2.14 frystyk 197:   return HTWriter_write(me, &c, 1);
2.1 timbl 198: }
 199: 
 200: /*   String handling
 201: **   ---------------
 202: **
 203: **   Strings must be smaller than this buffer size.
 204: */
2.33 frystyk 205: PRIVATE int HTWriter_put_string (HTOutputStream * me, const char * s)
2.1 timbl 206: {
2.14 frystyk 207:   return HTWriter_write(me, s, (int) strlen(s));
2.1 timbl 208: }
2.33 frystyk 209: /*
 210: **   The difference between the close and the free method is that we don't
 211: **   close the connection in the free method - we only call the free method
 212: **   of the target stream. That way, we can keep the output stream as long 
 213: **   as the channel itself.
 214: */
 215: PRIVATE int HTWriter_close (HTOutputStream * me)
2.1 timbl 216: {
2.54 frystyk 217:   HTTRACE(STREAM_TRACE, "Socket write FREEING....\n");
2.29 frystyk 218:   HT_FREE(me);
2.33 frystyk 219:   return HT_OK;
2.1 timbl 220: }
 221: 
2.33 frystyk 222: PRIVATE const HTOutputStreamClass HTWriter =
2.1 timbl 223: {       
2.14 frystyk 224:   "SocketWriter",
 225:   HTWriter_flush,
 226:   HTWriter_free,
 227:   HTWriter_abort,
 228:   HTWriter_put_character,
 229:   HTWriter_put_string,
2.33 frystyk 230:   HTWriter_write,
 231:   HTWriter_close
2.1 timbl 232: }; 
 233: 
2.41 frystyk 234: PUBLIC HTOutputStream * HTWriter_new (HTHost * host, HTChannel * ch,
2.33 frystyk 235:                   void * param, int mode)
2.1 timbl 236: {
2.41 frystyk 237:   if (host && ch) {
2.33 frystyk 238:    HTOutputStream * me = HTChannel_output(ch);
2.41 frystyk 239:    if (!me) {
2.33 frystyk 240:      if ((me=(HTOutputStream *) HT_CALLOC(1, sizeof(HTOutputStream)))==NULL)
 241:        HT_OUTOFMEM("HTWriter_new");
 242:      me->isa = &HTWriter;
 243:      me->ch = ch;
2.41 frystyk 244:      me->host = host;
2.33 frystyk 245:    }
2.48 frystyk 246:    return me;
2.33 frystyk 247:   }
 248:   return NULL;
2.21 frystyk 249: }

Webmaster

AltStyle によって変換されたページ (->オリジナル) /