8.3.2. test/faio/win-1.01.02

Start felix section to test/faio/win-1.01.02-0.flx[1 /1 ]
     1: #line 904 "./lpsrc/flx_faio.pak"
     2: #import <flx.flxh>
     3: include "Flx_faio_win32";
     4: open Faio_win32;
     5: 
     6: // let's add a win32 namedpipe test!
     7: // type WFILE is a HANDLE. that should work.
     8: // note the "r" for felix string raw mode.
     9: var pname = r"\\.\pipe\flx_pipe";
    10: 
    11: // CreateNamedPipe binding (put in a library somewhere)
    12: // duplex, byte stream, one instance,
    13: // guessing 256 bytes for input and output buffers
    14: // 0 default timeout (not using default wait, shouldn't matter)
    15: // default security attributes
    16: // associating with the iocp doesn't work, the pipe must be created with
    17: // FILE_FLAG_OVERLAPPED set in dwOpenMode. Otherwise OVERLAPPED calls block.
    18: proc CreateNamedPipe: lvalue[WFILE]*string =
    19:  '$1 = CreateNamedPipe($2.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,\
    20:      PIPE_TYPE_BYTE, 1, 256, 256, 0, NULL);';
    21: 
    22: // OpenFile in flx_faio_win32 should work fine here
    23: 
    24: print "Creating named pipe "; print pname; endl;
    25: var pipe: WFILE <- CreateNamedPipe(pname);
    26: 
    27: // how to connect with this stuff? can I open it non blockingly?
    28: if pipe == INVALID_HANDLE_VALUE then
    29: {
    30:   print "BUGGER: CreateNamedPipeFailed: "; print (GetLastError()); endl;
    31: } else {
    32:   print "whoo!\n";
    33: } endif;
    34: 
    35: // let's try to associate with IOCP here...
    36: // Hack: the interface requires a SOCKET, which it then casts to a HANDLE.
    37: // don't forget to create pipe with FILE_FLAG_OVERLAPPED, else we
    38: // error #87 -> ERROR_INVALID_PARAMETER
    39: fun HACK_TO_SOCKET: WFILE -> SOCKET = '(SOCKET)$1';
    40: associate_with_iocp(HACK_TO_SOCKET(pipe));
    41: 
    42: header = """
    43: 
    44: using namespace flx;
    45: using namespace demux;
    46: using namespace faio;
    47: 
    48: // wrap up ConnectNamedPipe. This function normally blocks, so we must
    49: // use it in a way that allows us to deschedule the fthread.
    50: class connect_namedpipe
    51:   : public waio_base,  public flx::demux::iocp_wakeup {
    52:   HANDLE pipe;       // for demux
    53: public:
    54:   connect_namedpipe(HANDLE p = INVALID_HANDLE_VALUE) : pipe(p) {}
    55: 
    56:   // this belongs in demux class
    57:   virtual bool start_overlapped()
    58:   {
    59:     fprintf(stderr, "connect named pipe start overlapped %p\\n", pipe);
    60: 
    61:     clear_overlapped();  // everyone's doing this
    62: 
    63:     BOOL success;
    64:     success = ConnectNamedPipe(pipe, &ol);
    65: 
    66:     // fprintf(stderr, "Connect named pipe: %i\\n", success);
    67:     if(success)
    68:     {
    69:       // this shouldn't happen ever. make it an error.
    70:       fprintf(stderr, "ConnectNamedPipe SUCCEEDED (shouldn't happen)\\n");
    71:     } else {
    72:       int err = GetLastError();
    73:       fprintf(stderr, "ConnectNamedPipe returned %i\\n", err);
    74: 
    75:       // this doesn't always signify failure.
    76:       switch(err)
    77:       {
    78:          case ERROR_PIPE_CONNECTED: // got a connection already
    79:            fprintf(stderr, "ALREADY GOT CONNECTION\\n");
    80:            // do fake wakeup here for great greatness. eats user cookie.
    81:            iocp_op_finished(0, 0, &ol, NO_ERROR);
    82:            return true;  // async finished
    83:          break;
    84: 
    85:          case ERROR_IO_PENDING:  // completion packet is in the mail
    86:            fprintf(stderr, "Connection pending... (normal)\\n");
    87:            return false;         // not finished, packet still to come
    88:          break;
    89:          default:
    90:            fprintf(stderr, "ConnectNamedPipe FAILED (%i)\\n", err);
    91:          break;
    92:       }
    93: 
    94:     }
    95: 
    96:     return false;  // let's not get woken, packet still to come (??)
    97:   }
    98: 
    99:   // this belongs in faio class
   100:   bool start_async_op_impl()
   101:   {
   102:     fprintf(stderr,"named_pipe: start async_op_impl\\n");
   103:     fprintf(stderr, "start_async_op for named pipe\\n");
   104:     return start_overlapped();
   105:   }
   106: 
   107:   // as does this
   108:   virtual void iocp_op_finished(DWORD nbytes, ULONG_PTR udat,
   109:     LPOVERLAPPED olp, int err)
   110:   {
   111:     fprintf(stderr, "connect named pipe FINISHED! err: %i\\n", err);
   112:     waio_base::iocp_op_finished(nbytes, udat, olp, err);
   113:   }
   114: 
   115: 
   116: };
   117: """;
   118: 
   119: proc getbyte(f: WFILE, outc: &char)
   120: {
   121:   var c: char;
   122:   val ac = C_hack::address_of(c);
   123:   var len = 1;
   124:   var eof: bool;
   125: 
   126:   ReadFile(f, &len, ac, &eof);
   127:   *outc = c;
   128: }
   129: 
   130: proc putbyte(f: WFILE, c: char)
   131: {
   132:   var copyc = c;
   133:   val ac = C_hack::address_of(copyc);
   134:   var len = 1;
   135:   var eof: bool;
   136: 
   137:   WriteFile(f, &len, ac, &eof);
   138: }
   139: 
   140: // spawn a connect fthread after having created the named pipe
   141: 
   142: // I'm not yet "accepting", but hopefully I can spawn a client here
   143: spawn_fthread {
   144:   // print "Gudday, client thread, trying to open PIPE\n";
   145:   // var p: WFILE <- OpenFile(pname);
   146:   // having trouble getting io...
   147:   var p: WFILE <- OpenFileDuplex(pname);
   148: 
   149:   // print "Client thread returned from OpenFile\n";
   150: 
   151:   if p == INVALID_HANDLE_VALUE then
   152:   { print "BUGGER: client couldn't open pipe: "; print (GetLastError()); endl; }
   153:   else { print "client opened pipe\n"; } endif;
   154: 
   155:   // HUM need to associate.
   156:   print "associating client\n";
   157:   associate_with_iocp(HACK_TO_SOCKET(p));
   158: 
   159:   var c: char;
   160:   getbyte(p, &c);
   161:   print "client got "; print c; endl;
   162:   putbyte(p, char 'b');
   163:   CloseFile(p);
   164: };
   165: 
   166: type np_request = 'connect_namedpipe';
   167: fun mk_np_request: WFILE -> np_request = 'connect_namedpipe($1)';
   168: 
   169: var npr = mk_np_request(pipe);
   170: Faio::faio_req$ &npr;
   171: 
   172: print "poot! got connection (maybe)\n";
   173: print "server trying to put byte\n";
   174: putbyte(pipe, char 'a');
   175: var c: char;
   176: getbyte(pipe, &c);
   177: print "server got "; print c; endl;
   178: CloseFile(pipe);
End felix section to test/faio/win-1.01.02-0.flx[1]
Start data section to test/faio/win-1.01.02-0.expect[1 /1 ]
     1: Creating named pipe \\.\pipe\flx_pipe
     2: whoo!
     3: client opened pipe
     4: associating client
     5: poot! got connection (maybe)
     6: server trying to put byte
     7: client got a
     8: server got b
End data section to test/faio/win-1.01.02-0.expect[1]