typedef struct IoCompletionInfo {
OVERLAPPED overlapped;
int request_type;
- recvbuf_t *buff;
+ union {
+ recvbuf_t *rbuf;
+ transmitbuf_t *tbuf;
+ } buff_space;
} IoCompletionInfo;
+#define recv_buf buff_space.rbuf
+#define trans_buf buff_space.tbuf
+
/*
* local function definitions
*/
static int QueueIORead( struct refclockio *, recvbuf_t *buff, IoCompletionInfo *lpo);
-static int OnSocketRecv(DWORD, IoCompletionInfo *, DWORD);
-static int OnIoReadComplete(DWORD, IoCompletionInfo *, DWORD);
-static int OnWriteComplete(DWORD, IoCompletionInfo *, DWORD);
+static int OnSocketRecv(DWORD, IoCompletionInfo *, DWORD, int);
+static int OnIoReadComplete(DWORD, IoCompletionInfo *, DWORD, int);
+static int OnWriteComplete(DWORD, IoCompletionInfo *, DWORD, int);
#define BUFCHECK_SECS 10
#define MAXHANDLES 3
HANDLE WaitHandles[MAXHANDLES] = { NULL, NULL, NULL };
+//#define USE_HEAP
+
IoCompletionInfo *
GetHeapAlloc(char *fromfunc)
{
IoCompletionInfo *lpo;
+#ifdef USE_HEAP
lpo = (IoCompletionInfo *) HeapAlloc(hHeapHandle,
HEAP_ZERO_MEMORY,
sizeof(IoCompletionInfo));
-
-// lpo = (IoCompletionInfo *) calloc(1, sizeof(IoCompletionInfo));
+#else
+ lpo = (IoCompletionInfo *) calloc(1, sizeof(IoCompletionInfo));
+#endif
#ifdef DEBUG
if (debug > 1) {
printf("Allocation %d memory for %s, ptr %x\n", sizeof(IoCompletionInfo), fromfunc, lpo);
}
#endif
+#ifdef USE_HEAP
HeapFree(hHeapHandle, 0, lpo);
+#else
+ free(lpo);
+#endif
+}
-// free(lpo);
+transmitbuf_t *
+get_trans_buf()
+{
+ transmitbuf_t *tb = calloc(sizeof(transmitbuf_t), 1);
+ tb->wsabuf.len = 0;
+ tb->wsabuf.buf = (char *) &tb->pkt;
+ return (tb);
}
+void
+free_trans_buf(transmitbuf_t *tb)
+{
+ free(tb);
+}
HANDLE
get_io_event()
iocompletionthread(void *NotUsed)
{
BOOL bSuccess = FALSE;
- int errstatus;
+ int errstatus = 0;
DWORD BytesTransferred = 0;
DWORD Key = 0;
IoCompletionInfo * lpo = NULL;
if (lpo == NULL)
{
#ifdef DEBUG
- msyslog(LOG_INFO, "Overlapped IO Thread Exits: %m");
+ if (debug > 2) {
+ printf("Overlapped IO Thread Exits: \n");
+ }
#endif
break; /* fail */
}
-
+
/*
* Deal with errors
*/
+ errstatus = 0;
if (!bSuccess)
{
errstatus = GetLastError();
if (BytesTransferred == 0 && errstatus == WSA_OPERATION_ABORTED)
{
- msyslog(LOG_ERR, "Transfer Operation aborted: %m");
+#ifdef DEBUG
+ if (debug > 2) {
+ printf("Transfer Operation aborted\n");
+ }
+#endif
}
else
{
switch(lpo->request_type)
{
case CLOCK_READ:
- OnIoReadComplete(Key, lpo, BytesTransferred);
+ OnIoReadComplete(Key, lpo, BytesTransferred, errstatus);
break;
case SOCK_RECV:
- OnSocketRecv(Key, lpo, BytesTransferred);
+ OnSocketRecv(Key, lpo, BytesTransferred, errstatus);
break;
case SOCK_SEND:
case CLOCK_WRITE:
- OnWriteComplete(Key, lpo, BytesTransferred);
+ OnWriteComplete(Key, lpo, BytesTransferred, errstatus);
break;
default:
#if DEBUG
- if (debug > 3) {
+ if (debug > 2) {
printf("Unknown request type %d found in completion port\n",
lpo->request_type);
}
memset(buff, 0, sizeof(recvbuf_t));
lpo->request_type = CLOCK_READ;
- lpo->buff = buff;
+ lpo->recv_buf = buff;
buff->fd = rio->fd;
if (!ReadFile((HANDLE) buff->fd, &buff->recv_buffer, sizeof(buff->recv_buffer), NULL, (LPOVERLAPPED) lpo)) {
/* Return 1 on Successful Read */
static int
-OnIoReadComplete(DWORD i, IoCompletionInfo *lpo, DWORD Bytes)
+OnIoReadComplete(DWORD i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus)
{
recvbuf_t *buff;
recvbuf_t *newbuff;
/*
* Get the recvbuf pointer from the overlapped buffer.
*/
- buff = (recvbuf_t *) lpo->buff;
+ buff = (recvbuf_t *) lpo->recv_buf;
/*
* Get a new recv buffer for the next packet
*/
}
else
{
- if (Bytes > 0) { /* ignore 0 bytes read due to timeout's */
+ /*
+ * ignore 0 bytes read due to timeout's and closure on fd
+ */
+ if (Bytes > 0 && errstatus != WSA_OPERATION_ABORTED) {
get_systime(&buff->recv_time);
buff->recv_length = (int) Bytes;
buff->receiver = rio->clock_recv;
int AddrLen;
lpo->request_type = SOCK_RECV;
- lpo->buff = buff;
+ lpo->recv_buf = buff;
if (buff != NULL) {
DWORD BytesReceived = 0;
/* Returns 0 if any Error */
static int
-OnSocketRecv(DWORD i, IoCompletionInfo *lpo, DWORD Bytes)
+OnSocketRecv(DWORD i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus)
{
struct recvbuf *buff = NULL;
recvbuf_t *newbuff;
/* Convert the overlapped pointer back to a recvbuf pointer.
*/
- buff = (struct recvbuf *) lpo->buff;
+ buff = lpo->recv_buf;
+
+ /*
+ * If the socket is closed we get an Operation Aborted error
+ * Just clean up
+ */
+ if (errstatus == WSA_OPERATION_ABORTED)
+ {
+ freerecvbuf(buff);
+ FreeHeap(lpo, "OnSocketRecv: Socket Closed");
+ return (1);
+ }
+
get_systime(&buff->recv_time);
/*
freerecvbuf(buff);
}
}
- if( !SetEvent( WaitableIoEventHandle ) ) {
+ QueueSocketRecv(inter->fd, newbuff, lpo);
+ /*
+ * Now signal we have something to process
+ */
+#if 0
+ if (newbuff != buff) {
+ if( !SetEvent( WaitableIoEventHandle ) ) {
#ifdef DEBUG
- if (debug > 3) {
- printf( "Error %d setting IoEventHandle\n", GetLastError() );
- }
+ if (debug > 3) {
+ printf( "Error %d setting IoEventHandle\n", GetLastError() );
+ }
#endif
+ }
}
+#endif
- QueueSocketRecv(inter->fd, newbuff, lpo);
return 1;
}
}
static int
-OnWriteComplete(DWORD Key, IoCompletionInfo *lpo, DWORD Bytes)
+OnWriteComplete(DWORD Key, IoCompletionInfo *lpo, DWORD Bytes, int errstatus)
{
transmitbuf_t *buff;
(void) Bytes;
(void) Key;
- buff = (transmitbuf_t *) lpo->buff;
+ buff = lpo->trans_buf;
+
+ free_trans_buf(buff);
- free_transmit_buffer(buff);
- FreeHeap(lpo, "OnWriteComplete");
+ if (errstatus == WSA_OPERATION_ABORTED)
+ FreeHeap(lpo, "OnWriteComplete: Socket Closed");
+ else
+ FreeHeap(lpo, "OnWriteComplete");
return 1;
}
return ERROR_OUTOFMEMORY;
if (len <= sizeof(buff->pkt)) {
- buff = get_free_transmit_buffer();
+ buff = get_trans_buf();
if (buff == NULL) {
msyslog(LOG_ERR, "No more transmit buffers left - data discarded");
AddrLen = sizeof(struct sockaddr_in);
lpo->request_type = SOCK_SEND;
- lpo->buff = (recvbuf_t *) buff;
+ lpo->trans_buf = buff;
Result = WSASendTo(inter->fd, &buff->wsabuf, 1, &BytesSent, Flags, (struct sockaddr *) dest, AddrLen, (LPOVERLAPPED) lpo, NULL);
*/
default :
netsyslog(LOG_ERR, "WSASendTo - error sending message: %m");
- free_transmit_buffer(buff);
+ free_trans_buf(buff);
FreeHeap(lpo, "io_completion_port_sendto");
break;
}
return ERROR_OUTOFMEMORY;
if (len <= sizeof(buff->pkt)) {
- buff = get_free_transmit_buffer();
+ buff = get_trans_buf();
if (buff == NULL) {
msyslog(LOG_ERR, "No more transmit buffers left - data discarded");
FreeHeap(lpo, "io_completion_port_write");
}
lpo->request_type = CLOCK_WRITE;
- lpo->buff = (recvbuf_t *)buff;
+ lpo->trans_buf = buff;
memcpy(&buff->pkt, pkt, len);
Result = WriteFile(fd, buff->pkt, len, &lpNumberOfBytesWritten, (LPOVERLAPPED) lpo);
default :
netsyslog(LOG_ERR, "WriteFile - error sending message: %m");
- free_transmit_buffer(buff);
+ free_trans_buf(buff);
FreeHeap(lpo, "io_completion_port_write");
break;
}
*/
int GetReceivedBuffers()
{
- DWORD Index = WaitForMultipleObjectsEx(MAXHANDLES, WaitHandles, FALSE, INFINITE, TRUE);
+// DWORD Index = WaitForMultipleObjects(MAXHANDLES, WaitHandles, FALSE, INFINITE);
+ DWORD Index = WaitForMultipleObjects(MAXHANDLES, WaitHandles, FALSE, 500);
switch (Index) {
case WAIT_OBJECT_0 + 0 : /* exit request */
exit(0);