/* FileCleanup ** ----------- ** This function closes the connection and frees memory. ** Returns YES on OK, else NO */ PRIVATE int FileCleanup (HTRequest *req, int status) { HTNet * net = HTRequest_net(req); file_info * file = (file_info *) HTNet_context(net); HTStream * input = HTRequest_inputStream(req); /* Free stream with data TO Local file system */ if (input) { if (status == HT_INTERRUPTED) (*input->isa->abort)(input, NULL); else (*input->isa->_free)(input); HTRequest_setInputStream(req, NULL); } /* ** Remove if we have registered a timer function as a callback */ if (file->timer) { HTTimer_delete(file->timer); file->timer = NULL; } if (file) { HT_FREE(file->local); HT_FREE(file); } HTNet_delete(net, status); return YES; }
PRIVATE int HTBufferWriter_abort (HTOutputStream * me, HTList * e) { HTTRACE(STREAM_TRACE, "Buffer...... ABORTING...\n"); if (me->timer) { HTTimer_delete(me->timer); me->timer = NULL; } if (me->target) (*me->target->isa->abort)(me->target, e); return HT_ERROR; }
/* ** The difference between the close and the free method is that we don't ** close the connection in the free method - we only call the free method ** of the target stream. That way, we can keep the output stream as long ** as the channel itself. */ PRIVATE int HTBufferWriter_close (HTOutputStream * me) { if (me) { if (me->timer) { HTTimer_delete(me->timer); me->timer = NULL; } if (me->target) (*me->target->isa->close)(me->target); HT_FREE(me->data); HT_FREE(me); } return HT_OK; }
PRIVATE int HTBufferWriter_lazyFlush (HTOutputStream * me) { HTNet * net; int delay; if (me->read <= me->data) { return HT_OK; /* nothing to flush */ } /* ** If we are allowed to delay the flush then set a timer with the ** delay descibed by our delay variable. If we can't delay then flush ** right away. */ delay = HTHost_findWriteDelay(me->host, me->lastFlushTime, me->read - me->data); /* ** Flush immediately */ if (!delay) { int status; HTTRACE(STREAM_TRACE, "Buffer...... Flushing %p\n" _ me); if ((status = HTBufferWriter_flush(me)) && me->timer) { HTTimer_delete(me->timer); me->timer = NULL; } return status; } /* ** Set a timer and tell the host we've done the write if ** we have not already started a timer earlier. If a timer ** does already exist then make sure that it hasn't expired. ** This can be the case if we have a really slow client that ** can't parse the data fast enough. */ if (!me->timer) { net = HTHost_getWriteNet(me->host); me->timer = HTTimer_new(NULL, FlushEvent, me, delay, YES, NO); HTHost_unregister(me->host, net, HTEvent_WRITE); HTTRACE(STREAM_TRACE, "Buffer...... Waiting %dms on %p\n" _ delay _ me); } else { if (HTTimer_hasTimerExpired(me->timer)) { HTTRACE(STREAM_TRACE, "Buffer...... Dispatching old timer %p\n" _ me->timer); HTTimer_dispatch(me->timer); me->timer = NULL; } else { HTTRACE(STREAM_TRACE, "Buffer...... Waiting on unexpired timer %p\n" _ me->timer); } } return HT_OK; }
PRIVATE int ReturnEvent (HTTimer * timer, void * param, HTEventType type) { file_info * file = (file_info *) param; if (timer != file->timer) HTDEBUGBREAK("File timer %p not in sync\n" _ timer); HTTRACE(PROT_TRACE, "HTLoadFile.. Continuing %p with timer %p\n" _ file _ timer); /* ** Delete the timer */ HTTimer_delete(file->timer); file->timer = NULL; /* ** Now call the event again */ return FileEvent(INVSOC, file, HTEvent_READ); }
PRIVATE int FlushEvent (HTTimer * timer, void * param, HTEventType type) { HTOutputStream * me = (HTOutputStream *) param; if (me->timer && timer != me->timer) HTDEBUGBREAK("Buffer Writer timer %p not in sync\n" _ timer); HTTRACE(PROT_TRACE, "Buffer...... Timeout flushing %p with timer %p\n" _ me _ timer); /* ** We ignore the return code here which we shouldn't!!! */ HTBufferWriter_flush(me); /* ** Delete the timer */ HTTimer_delete(me->timer); me->timer = NULL; return HT_OK; }
/* ** Remove the registered information for the specified socket for the actions ** specified in ops. if no actions remain after the unregister, the registered ** info is deleted, and, if the socket has been registered for notification, ** the HTEventCallback will be invoked. */ PUBLIC int HTEventList_unregister (SOCKET s, HTEventType type) { long v = HASH(s); HTList * cur = HashTable[v]; HTList * last = cur; SockEvents * pres; int ret = HT_ERROR; /* if the socket doesn't exists, don't do anything */ if (s == INVSOC) return HT_OK; while (cur && (pres = (SockEvents *) HTList_nextObject(cur))) { if (pres->s == s) { int remaining = 0; /* ** Unregister the event from this action */ pres->events[HTEvent_INDEX(type)] = NULL; remaining = EventList_remaining(pres); /* ** Check to see of there was a timeout connected with the event. ** If so then delete the timeout as well. */ { HTTimer * timer = pres->timeouts[HTEvent_INDEX(type)]; if (timer) HTTimer_delete(timer); pres->timeouts[HTEvent_INDEX(type)] = NULL; } #ifdef WWW_WIN_ASYNC if (WSAAsyncSelect(s, HTSocketWin, HTwinMsg, remaining) < 0) ret = HT_ERROR; #else /* WWW_WIN_ASYNC */ FD_CLR(s, FdArray+HTEvent_INDEX(type)); HTTRACEDATA((char*)FdArray+HTEvent_INDEX(type), 8, "HTEventList_unregister: (s:%d)" _ s); #endif /* !WWW_WIN_ASYNC */ /* ** Check to see if we can delete the action completely. We do this ** if there are no more events registered. */ if (remaining == 0) { HTList * doomed = cur; HTTRACE(THD_TRACE, "Event....... No more events registered for socket %d\n" _ s); #ifndef WWW_WIN_ASYNC /* Check to see if we have to update MaxSock */ if (pres->s >= MaxSock) __ResetMaxSock(); #endif /* !WWW_WIN_ASYNC */ HT_FREE(pres); pres = (SockEvents *) HTList_nextObject(cur); HTList_quickRemoveElement(doomed, last); } ret = HT_OK; HTTRACE(THD_TRACE, "Event....... Socket %d unregistered for %s\n" _ s _ HTEvent_type2str(type)); /* We found the socket and can break */ break; } last = cur; } if (THD_TRACE) { if (ret == HT_ERROR) HTTRACE(THD_TRACE, "Event....... Couldn't find socket %d. Can't unregister type %s\n" _ s _ HTEvent_type2str(type)); } return ret; }