Annotation of embedaddon/mtr/packet/command_cygwin.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:     mtr  --  a network diagnostic tool
                      3:     Copyright (C) 2016  Matt Kimball
                      4: 
                      5:     This program is free software; you can redistribute it and/or modify
                      6:     it under the terms of the GNU General Public License version 2 as
                      7:     published by the Free Software Foundation.
                      8: 
                      9:     This program is distributed in the hope that it will be useful,
                     10:     but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     12:     GNU General Public License for more details.
                     13: 
                     14:     You should have received a copy of the GNU General Public License
                     15:     along with this program; if not, write to the Free Software
                     16:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17: */
                     18: 
                     19: #include "command.h"
                     20: 
                     21: #include <errno.h>
                     22: #include <io.h>
                     23: #include <stdio.h>
                     24: 
                     25: /*
                     26:     A completion routine to be called by Windows when a read from
                     27:     the command stream has completed.
                     28: */
                     29: static
                     30: void CALLBACK finish_read_command(
                     31:     DWORD status,
                     32:     DWORD size_read,
                     33:     OVERLAPPED * overlapped)
                     34: {
                     35:     struct command_buffer_t *buffer;
                     36:     char *read_position;
                     37: 
                     38:     /*
                     39:        hEvent is unusuaed by ReadFileEx, so we use it to pass
                     40:        our command_buffer structure.
                     41:      */
                     42:     buffer = (struct command_buffer_t *) overlapped->hEvent;
                     43: 
                     44:     if (status) {
                     45:         /*  When the stream is closed ERROR_BROKEN_PIPE will be the result  */
                     46:         if (status == ERROR_BROKEN_PIPE) {
                     47:             buffer->platform.pipe_open = false;
                     48:             return;
                     49:         }
                     50: 
                     51:         fprintf(stderr, "ReadFileEx completion failure %d\n", status);
                     52:         exit(EXIT_FAILURE);
                     53:     }
                     54: 
                     55:     /*  Copy from the overlapped I/O buffer to the incoming command buffer  */
                     56:     read_position =
                     57:         &buffer->incoming_buffer[buffer->incoming_read_position];
                     58:     memcpy(read_position, buffer->platform.overlapped_buffer, size_read);
                     59: 
                     60:     /*  Account for the newly read data  */
                     61:     buffer->incoming_read_position += size_read;
                     62:     buffer->platform.read_active = false;
                     63: }
                     64: 
                     65: /*
                     66:     An APC which does nothing, to be used only to wake from the current
                     67:     alertable wait.
                     68: */
                     69: static
                     70: void CALLBACK empty_apc(
                     71:     ULONG * param)
                     72: {
                     73: }
                     74: 
                     75: /*  Wake from the next alertable wait without waiting for newly read data  */
                     76: static
                     77: void queue_empty_apc(
                     78:     void)
                     79: {
                     80:     if (QueueUserAPC((PAPCFUNC) empty_apc, GetCurrentThread(), 0) == 0) {
                     81:         fprintf(stderr, "Unexpected QueueUserAPC failure %d\n",
                     82:                 GetLastError());
                     83:         exit(EXIT_FAILURE);
                     84:     }
                     85: }
                     86: 
                     87: /*  Start a new overlapped I/O read from the command stream  */
                     88: void start_read_command(
                     89:     struct command_buffer_t *buffer)
                     90: {
                     91:     HANDLE command_stream = (HANDLE) get_osfhandle(buffer->command_stream);
                     92:     int space_remaining =
                     93:         COMMAND_BUFFER_SIZE - buffer->incoming_read_position - 1;
                     94:     int err;
                     95: 
                     96:     /*  If a read is already active, or the pipe is closed, do nothing  */
                     97:     if (!buffer->platform.pipe_open || buffer->platform.read_active) {
                     98:         return;
                     99:     }
                    100: 
                    101:     memset(&buffer->platform.overlapped, 0, sizeof(OVERLAPPED));
                    102:     buffer->platform.overlapped.hEvent = (HANDLE) buffer;
                    103: 
                    104:     if (!ReadFileEx
                    105:         (command_stream, buffer->platform.overlapped_buffer,
                    106:          space_remaining, &buffer->platform.overlapped,
                    107:          finish_read_command)) {
                    108: 
                    109:         err = GetLastError();
                    110: 
                    111:         if (err == ERROR_BROKEN_PIPE) {
                    112:             /*  If the command stream has been closed, we need to wake from
                    113:                the next altertable wait to exit the main loop  */
                    114:             buffer->platform.pipe_open = false;
                    115:             queue_empty_apc();
                    116: 
                    117:             return;
                    118:         } else if (err != WAIT_IO_COMPLETION) {
                    119:             fprintf(stderr, "Unexpected ReadFileEx failure %d\n",
                    120:                     GetLastError());
                    121:             exit(EXIT_FAILURE);
                    122:         }
                    123:     }
                    124: 
                    125:     /*  Remember that we have started an overlapped read already  */
                    126:     buffer->platform.read_active = true;
                    127: }
                    128: 
                    129: /*  Initialize the command buffer, and start the first overlapped read  */
                    130: void init_command_buffer(
                    131:     struct command_buffer_t *command_buffer,
                    132:     int command_stream)
                    133: {
                    134:     memset(command_buffer, 0, sizeof(struct command_buffer_t));
                    135:     command_buffer->command_stream = command_stream;
                    136:     command_buffer->platform.pipe_open = true;
                    137: }
                    138: 
                    139: /*
                    140:     Return with errno EPIPE if the command stream has been closed.
                    141:     Otherwise, not much to do for Cygwin, since we are using Overlapped I/O
                    142:     to read commands.
                    143: */
                    144: int read_commands(
                    145:     struct command_buffer_t *buffer)
                    146: {
                    147:     if (!buffer->platform.pipe_open) {
                    148:         errno = EPIPE;
                    149:         return -1;
                    150:     }
                    151: 
                    152:     return 0;
                    153: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>