HTWriter.c
上传用户:zlh9724
上传日期:2007-01-04
资源大小:1991k
文件大小:6k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /*               HTWrite.c
  2. ** FILE WRITER BASED ON A SOCKET
  3. **
  4. ** (c) COPYRIGHT MIT 1995.
  5. ** Please first read the full copyright statement in the file COPYRIGH.
  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. There is also a small buffer stream that can be used
  11. ** if athis is not the case.
  12. */
  13. /* Library include files */
  14. #include "tcp.h"
  15. #include "HTUtils.h"
  16. #include "HTString.h"
  17. #include "HTReq.h"
  18. #include "HTNetMan.h"
  19. #include "HTConLen.h"
  20. #include "HTAlert.h"
  21. #include "HTWriter.h"  /* Implemented here */
  22. struct _HTStream {
  23. CONST HTStreamClass * isa;
  24. SOCKET sockfd;
  25. HTNet * net;
  26. char *wptr;
  27. BOOL leave_open;
  28. #ifdef NOT_ASCII
  29. BOOL make_ascii;    /* Are we writing to the net? */
  30. char * ascbuf;     /* Buffer for TOASCII conversion */
  31. #endif
  32. };
  33. /* ------------------------------------------------------------------------- */
  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 (HTStream * me, CONST char * buf, int len)
  65. {
  66.     int b_write;
  67.     CONST char *limit = buf+len;
  68.     HTRequest * request = me->net->request;
  69.     HTNet * net = me->net;
  70. #ifdef NOT_ASCII
  71.     if (me->make_ascii && len && !me->ascbuf) {       /* Generate new buffer */
  72. char *orig=buf;
  73. char *dest;
  74. int cnt;
  75. if ((me->ascbuf = (char  *) HT_MALLOC(len)) == NULL)
  76.     HT_OUTOFMEM("me->ascbuf ");
  77. dest = me->ascbuf;
  78. for (cnt=0; cnt<len; cnt++) {
  79.     *dest = TOASCII(*orig);
  80.     dest++, orig++;
  81. }
  82. me->wptr = me->ascbuf;
  83. limit = me->ascbuf+len;
  84.     }
  85. #else
  86.     if (!me->wptr)
  87. me->wptr = (char *) buf;
  88.     else
  89. len -= (me->wptr - buf);
  90. #endif
  91.     /* Write data to the network */
  92.     while (me->wptr < limit) {
  93. if ((b_write = NETWRITE(me->sockfd, me->wptr, len)) < 0) {
  94. #ifdef EAGAIN
  95.     if (socerrno == EAGAIN || socerrno == EWOULDBLOCK)/* POSIX, SVR4 */
  96. #else
  97.     if (socerrno == EWOULDBLOCK)       /* BSD */
  98. #endif
  99.     {
  100. if (PROT_TRACE)
  101.     TTYPrint(TDEST,"Write Socket WOULD BLOCK %dn",me->sockfd);
  102. HTEvent_Register(me->sockfd, request, (SockOps) FD_WRITE,
  103.  net->cbf, net->priority);
  104. return HT_WOULD_BLOCK;
  105.     } else {
  106. HTRequest_addSystemError(request,  ERR_FATAL, socerrno, NO,
  107.  "NETWRITE");
  108. return HT_ERROR;
  109.     }
  110. }
  111. HTEvent_UnRegister(me->sockfd, (SockOps) FD_WRITE);
  112. me->wptr += b_write;
  113. len -= b_write;
  114. if (PROT_TRACE)
  115.     TTYPrint(TDEST, "Write Socket %d bytes written to socket %dn",
  116.     b_write, me->sockfd);
  117. net->bytes_written += b_write;
  118. {
  119.     HTAlertCallback *cbf = HTAlert_find(HT_PROG_READ);
  120.     if (cbf) (*cbf)(request, HT_PROG_WRITE,HT_MSG_NULL,NULL,NULL,NULL);
  121. }
  122.     }
  123. #ifdef NOT_ASCII
  124.     HT_FREE(me->ascbuf);
  125. #else
  126.     me->wptr = NULL;
  127. #endif
  128.     return HT_OK;
  129. }
  130. /* Character handling
  131. ** ------------------
  132. */
  133. PRIVATE int HTWriter_put_character (HTStream * me, char c)
  134. {
  135.     return HTWriter_write(me, &c, 1);
  136. }
  137. /* String handling
  138. ** ---------------
  139. **
  140. ** Strings must be smaller than this buffer size.
  141. */
  142. PRIVATE int HTWriter_put_string (HTStream * me, CONST char * s)
  143. {
  144.     return HTWriter_write(me, s, (int) strlen(s));
  145. }
  146. PRIVATE int HTWriter_flush (HTStream * me)
  147. {
  148.     return HT_OK;        /* As we don't keep any buffer in this stream */
  149. }
  150. PRIVATE int HTWriter_free (HTStream * me)
  151. {
  152.     int status = HT_OK;
  153.     if (!me->leave_open) {
  154. if (NETCLOSE(me->sockfd) < 0)
  155.     status = HT_ERROR;
  156.     }
  157.     HT_FREE(me);
  158.     return status;
  159. }
  160. PRIVATE int HTWriter_abort (HTStream * me, HTList * e)
  161. {
  162.     if (!me->leave_open)
  163. NETCLOSE(me->sockfd);
  164.     HT_FREE(me);
  165.     return HT_ERROR;
  166. }
  167. /* Structured Object Class
  168. ** -----------------------
  169. */
  170. PRIVATE CONST HTStreamClass HTWriter =
  171. {
  172.     "SocketWriter",
  173.     HTWriter_flush,
  174.     HTWriter_free,
  175.     HTWriter_abort,
  176.     HTWriter_put_character,
  177.     HTWriter_put_string,
  178.     HTWriter_write
  179. }; 
  180. /* Subclass-specific Methods
  181. ** -------------------------
  182. */
  183. PUBLIC HTStream* HTWriter_new (HTNet *net, BOOL leave_open)
  184. {
  185.     HTStream* me;
  186.     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
  187.         HT_OUTOFMEM("HTWriter_new");
  188.     me->isa = &HTWriter;       
  189.     me->leave_open = leave_open;
  190.     me->sockfd = net->sockfd;
  191.     me->net = net;
  192.     return me;
  193. }
  194. /*
  195. ** Set up stream to write to a socket. If buf_size > 0 then we set up
  196. ** buffered output used for at most buf_size bytes. From that point we 
  197. ** switch to unbuffered mode. Otherwise we'll use nonbuffered output.
  198. */
  199. PUBLIC HTStream* HTBufWriter_new (HTNet *net, BOOL leave_open, int buf_size)
  200. {
  201.     return HTBuffer_new(HTWriter_new(net, leave_open), net->request, buf_size);
  202. }
  203. /* Subclass-specific Methods
  204. ** -------------------------
  205. */
  206. #ifdef NOT_ASCII
  207. PUBLIC HTStream * HTASCIIWriter (HTNet *net, BOOL leave_open)
  208. {
  209.     HTStream * me;
  210.     if ((me = (HTStream  *) HT_CALLOC(1, sizeof(*me))) == NULL)
  211.         HT_OUTOFMEM("HTASCIIWriter_new");
  212.     me->isa = &HTWriter;       
  213.     me->leave_open = leave_open;
  214.     me->make_ascii = YES;
  215.     me->sockfd = net->sockfd;
  216.     me->net = net;
  217.     return me;
  218. }
  219. #else
  220. #ifdef WWW_WIN_DLL
  221. PUBLIC HTStream * HTASCIIWriter (HTNet *net, BOOL leave_open)
  222. {
  223.     return NULL;
  224. }
  225. #endif /* WWW_WIN_DLL */
  226. #endif /* NOT_ASCII */