📄 ntp_iocompletionport.c
字号:
msyslog(LOG_ERR, "Can't allocate memory for clock socket: %m"); FreeHeap(lpo, "io_completion_port_add_clock_io"); return 1; } QueueIORead( rio, buff, lpo ); return 0;}/* Queue a receiver on a socket. Returns 0 if no buffer can be queued */static unsigned long QueueSocketRecv(SOCKET s, recvbuf_t *buff, IoCompletionInfo *lpo) { int AddrLen; lpo->request_type = SOCK_RECV; lpo->recv_buf = buff; if (buff != NULL) { DWORD BytesReceived = 0; DWORD Flags = 0; buff->fd = s; AddrLen = sizeof(struct sockaddr_in); buff->src_addr_len = sizeof(struct sockaddr); if (SOCKET_ERROR == WSARecvFrom(buff->fd, &buff->wsabuff, 1, &BytesReceived, &Flags, (struct sockaddr *) &buff->recv_srcadr, (LPINT) &buff->src_addr_len, (LPOVERLAPPED) lpo, NULL)) { DWORD Result = WSAGetLastError(); switch (Result) { case NO_ERROR : case WSA_IO_INCOMPLETE : case WSA_WAIT_IO_COMPLETION : case WSA_IO_PENDING : break ; case WSAENOTSOCK : netsyslog(LOG_ERR, "Can't read from socket, because it isn't a socket: %m"); /* return the buffer */ freerecvbuf(buff); return 0; break; case WSAEFAULT : netsyslog(LOG_ERR, "The buffers parameter is incorrect: %m"); /* return the buffer */ freerecvbuf(buff); return 0; break; default : /* nop */ ; } } } else return 0; return 1;}/* Returns 0 if any Error */static int OnSocketRecv(DWORD i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus){ struct recvbuf *buff = NULL; recvbuf_t *newbuff; isc_boolean_t ignore_this; l_fp arrival_time; struct interface * inter = (struct interface *) i; get_systime(&arrival_time); /* Convert the overlapped pointer back to a recvbuf pointer. */ /* * Check returned structures */ if (lpo == NULL) return (1); /* Nothing to do */ buff = lpo->recv_buf; /* * Make sure we have a buffer */ if (buff == NULL) { return (1); } /* * 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 a new recv buffer for the next packet */ newbuff = get_free_recv_buffer_alloc(); if (newbuff == NULL) { /* * recv buffers not available so we drop the packet * and reuse the buffer. */ newbuff = buff; } else { ignore_this = inter->ignore_packets; /* * If we keep it add some info to the structure */ if (Bytes > 0 && ignore_this == ISC_FALSE) { memcpy(&buff->recv_time, &arrival_time, sizeof(arrival_time)); buff->recv_length = (int) Bytes; buff->receiver = receive; buff->dstadr = inter;#ifdef DEBUG if (debug > 1) printf("Received %d bytes of fd %d in buffer %x from %s\n", Bytes, buff->fd, buff, stoa(&buff->recv_srcadr));#endif add_full_recv_buffer(buff); /* * Now signal we have something to process */ if( !SetEvent( WaitableIoEventHandle ) ) {#ifdef DEBUG if (debug > 1) { printf( "Error %d setting IoEventHandle\n", GetLastError() ); }#endif } } else { freerecvbuf(buff); } } if (newbuff != NULL) QueueSocketRecv(inter->fd, newbuff, lpo); return 1;}/* Add a socket handle to the I/O completion port, and send an I/O * read request to the kernel. * * Note: As per the winsock documentation, we use WSARecvFrom. Using * ReadFile() is less efficient. */extern intio_completion_port_add_socket(SOCKET fd, struct interface *inter){ IoCompletionInfo *lpo; recvbuf_t *buff; if (fd != INVALID_SOCKET) { if (NULL == CreateIoCompletionPort((HANDLE) fd, hIoCompletionPort, (DWORD) inter, 0)) { msyslog(LOG_ERR, "Can't add socket to i/o completion port: %m"); return 1; } } lpo = (IoCompletionInfo *) GetHeapAlloc("io_completion_port_add_socket"); if (lpo == NULL) { msyslog(LOG_ERR, "Can't allocate heap for completion port: %m"); return 1; } buff = get_free_recv_buffer_alloc(); if (buff == NULL) { msyslog(LOG_ERR, "Can't allocate memory for network socket: %m"); FreeHeap(lpo, "io_completion_port_add_socket"); return 1; } QueueSocketRecv(fd, buff, lpo); return 0;}static int OnWriteComplete(DWORD Key, IoCompletionInfo *lpo, DWORD Bytes, int errstatus){ transmitbuf_t *buff; (void) Bytes; (void) Key; buff = lpo->trans_buf; free_trans_buf(buff); if (errstatus == WSA_OPERATION_ABORTED) FreeHeap(lpo, "OnWriteComplete: Socket Closed"); else FreeHeap(lpo, "OnWriteComplete"); return 1;}DWORD io_completion_port_sendto( struct interface *inter, struct pkt *pkt, int len, struct sockaddr_storage* dest){ transmitbuf_t *buff = NULL; DWORD Result = ERROR_SUCCESS; int errval; int AddrLen; IoCompletionInfo *lpo; DWORD BytesSent = 0; DWORD Flags = 0; lpo = (IoCompletionInfo *) GetHeapAlloc("io_completion_port_sendto"); if (lpo == NULL) return ERROR_OUTOFMEMORY; if (len <= sizeof(buff->pkt)) { buff = get_trans_buf(); if (buff == NULL) { msyslog(LOG_ERR, "No more transmit buffers left - data discarded"); FreeHeap(lpo, "io_completion_port_sendto"); return ERROR_OUTOFMEMORY; } memcpy(&buff->pkt, pkt, len); buff->wsabuf.buf = buff->pkt; buff->wsabuf.len = len; AddrLen = sizeof(struct sockaddr_in); lpo->request_type = SOCK_SEND; lpo->trans_buf = buff; Result = WSASendTo(inter->fd, &buff->wsabuf, 1, &BytesSent, Flags, (struct sockaddr *) dest, AddrLen, (LPOVERLAPPED) lpo, NULL); if(Result == SOCKET_ERROR) { errval = WSAGetLastError(); switch (errval) { case NO_ERROR : case WSA_IO_INCOMPLETE : case WSA_WAIT_IO_COMPLETION : case WSA_IO_PENDING : Result = ERROR_SUCCESS; break ; /* * Something bad happened */ default : netsyslog(LOG_ERR, "WSASendTo - error sending message: %m"); free_trans_buf(buff); FreeHeap(lpo, "io_completion_port_sendto"); break; } }#ifdef DEBUG if (debug > 3) printf("WSASendTo - %d bytes to %s : %d\n", len, stoa(dest), Result);#endif return (Result); } else {#ifdef DEBUG if (debug) printf("Packet too large: %d Bytes\n", len);#endif return ERROR_INSUFFICIENT_BUFFER; }}/* * Async IO Write */DWORD io_completion_port_write( HANDLE fd, char *pkt, int len){ DWORD errval; transmitbuf_t *buff = NULL; DWORD lpNumberOfBytesWritten; DWORD Result = ERROR_INSUFFICIENT_BUFFER; IoCompletionInfo *lpo; lpo = (IoCompletionInfo *) GetHeapAlloc("io_completion_port_write"); if (lpo == NULL) return ERROR_OUTOFMEMORY; if (len <= sizeof(buff->pkt)) { 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->trans_buf = buff; memcpy(&buff->pkt, pkt, len); Result = WriteFile(fd, buff->pkt, len, &lpNumberOfBytesWritten, (LPOVERLAPPED) lpo); if(Result == SOCKET_ERROR) { errval = WSAGetLastError(); switch (errval) { case NO_ERROR : case WSA_IO_INCOMPLETE : case WSA_WAIT_IO_COMPLETION : case WSA_IO_PENDING : Result = ERROR_SUCCESS; break ; default : netsyslog(LOG_ERR, "WriteFile - error sending message: %m"); free_trans_buf(buff); FreeHeap(lpo, "io_completion_port_write"); break; } }#ifdef DEBUG if (debug > 2) { printf("WriteFile - %d bytes %d\n", len, Result); }#endif if (Result) return len; } else {#ifdef DEBUG if (debug) printf("Packet too large: %d Bytes\n", len);#endif } return Result;}/* * GetReceivedBuffers * Note that this is in effect the main loop for processing requests * both send and receive. This should be reimplemented */int GetReceivedBuffers(){ isc_boolean_t have_packet = ISC_FALSE; while (!have_packet) { DWORD Index = WaitForMultipleObjects(MAXHANDLES, WaitHandles, FALSE, INFINITE); switch (Index) { case WAIT_OBJECT_0 + 0 : /* Io event */# ifdef DEBUG if ( debug > 3 ) { printf( "IoEvent occurred\n" ); }# endif have_packet = ISC_TRUE; break; case WAIT_OBJECT_0 + 1 : /* exit request */ exit(0); break; case WAIT_OBJECT_0 + 2 : /* timer */ timer(); break; case WAIT_IO_COMPLETION : /* loop */ case WAIT_TIMEOUT : break; case WAIT_FAILED: msyslog(LOG_ERR, "ntpd: WaitForMultipleObjects Failed: Error: %m"); break; /* For now do nothing if not expected */ default: break; } /* switch */ } return (full_recvbuffs()); /* get received buffers */}#else static int NonEmptyCompilationUnit;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -