Пример #1
1
bool Channel::CreatePipe(const IPC::ChannelHandle &channel_handle) {
  assert(INVALID_HANDLE_VALUE == pipe_);
  std::wstring pipe_name;
  // If we already have a valid pipe for channel just copy it.
  if (channel_handle.pipe.handle) {
    assert(channel_handle.name.empty());
    pipe_name = L"Not Available";  // Just used for LOG
    // Check that the given pipe confirms to the specified mode.  We can
    // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the
    // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0.
    DWORD flags = 0;
    GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL);
    assert(!(flags & PIPE_TYPE_MESSAGE));
    if (!DuplicateHandle(GetCurrentProcess(),
                         channel_handle.pipe.handle,
                         GetCurrentProcess(),
                         &pipe_,
                         0,
                         FALSE,
                         DUPLICATE_SAME_ACCESS)) {
      //LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError();
      return false;
    }
  } else {
	assert(!channel_handle.pipe.handle);
	pipe_name = PipeName(channel_handle.name, &client_secret_);

	//Ïȳ¢ÊÔ´´½¨
    const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
                            FILE_FLAG_FIRST_PIPE_INSTANCE;
    validate_client_ = !!client_secret_;
    pipe_ = CreateNamedPipeW(pipe_name.c_str(),
                             open_mode,
                             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
                             1,
                             kReadBufferSize,
                             kReadBufferSize,
                             5000,
                             NULL);
	if (pipe_ == INVALID_HANDLE_VALUE)
	{
		pipe_ = CreateFileW(pipe_name.c_str(),
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
			FILE_FLAG_OVERLAPPED,
			NULL);

		waiting_connect_ = false;
	}
  } 

  if (pipe_ == INVALID_HANDLE_VALUE) {
    // If this process is being closed, the pipe may be gone already.
    //LOG(WARNING) << "Unable to create pipe \"" << pipe_name <<
    //                "\" in " << (mode & MODE_SERVER_FLAG ? "server" : "client")
    //                << " mode. Error :" << GetLastError();
    return false;
  }

  // Create the Hello message to be sent when Connect is called
  Message* m = new Message(MSG_ROUTING_NONE,
                                    HELLO_MESSAGE_TYPE,
                                    IPC::Message::PRIORITY_NORMAL);
  m->AddRef();
  // Don't send the secret to the untrusted process, and don't send a secret
  // if the value is zero (for IPC backwards compatability).
  int32 secret = validate_client_ ? 0 : client_secret_;
  if (!m->WriteInt(GetCurrentProcessId()) ||
      (secret && !m->WriteUInt32(secret))) {
    CloseHandle(pipe_);
    pipe_ = INVALID_HANDLE_VALUE;
	m->Release();
    return false;
  }

  output_queue_.push(m);
  return true;
}
Пример #2
0
// FIXME: remove socket option functions?
static PRStatus
nsNamedPipeGetSocketOption(PRFileDesc* aFd, PRSocketOptionData* aData)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  MOZ_ASSERT(aFd);
  MOZ_ASSERT(aData);

  switch (aData->option) {
    case PR_SockOpt_Nonblocking:
      aData->value.non_blocking = GetNamedPipeInfo(aFd)->IsNonblocking()
                                  ? PR_TRUE
                                  : PR_FALSE;
      break;
    case PR_SockOpt_Keepalive:
      aData->value.keep_alive = PR_TRUE;
      break;
    case PR_SockOpt_NoDelay:
      aData->value.no_delay = PR_TRUE;
      break;
    default:
      PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      return PR_FAILURE;
  }

  return PR_SUCCESS;
}
Пример #3
0
fcgi_request *fcgi_init_request(int listen_socket, void(*on_accept)(), void(*on_read)(), void(*on_close)())
{
	fcgi_request *req = calloc(1, sizeof(fcgi_request));
	req->listen_socket = listen_socket;
	req->fd = -1;
	req->id = -1;

	/*
	req->in_len = 0;
	req->in_pad = 0;

	req->out_hdr = NULL;

#ifdef TCP_NODELAY
	req->nodelay = 0;
#endif

	req->env = NULL;
	req->has_env = 0;

	*/
	req->out_pos = req->out_buf;
	req->hook.on_accept = on_accept ? on_accept : fcgi_hook_dummy;
	req->hook.on_read = on_read ? on_read : fcgi_hook_dummy;
	req->hook.on_close = on_close ? on_close : fcgi_hook_dummy;

#ifdef _WIN32
	req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif

	fcgi_hash_init(&req->env);

	return req;
}
Пример #4
0
fcgi_request *fcgi_init_request(int listen_socket)
{
	fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
	req->listen_socket = listen_socket;
	req->fd = -1;
	req->id = -1;

	req->in_len = 0;
	req->in_pad = 0;

	req->out_hdr = NULL;
	req->out_pos = req->out_buf;

#ifdef _WIN32
	req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif

#ifdef TCP_NODELAY
	req->nodelay = 0;
#endif

	fcgi_hash_init(&req->env);

	return req;
}
Пример #5
0
/* Return true if HD refers to a socket.  */
static int
is_socket (HANDLE hd)
{
    /* We need to figure out whether we are working on a socket or on a
       handle.  A trivial way would be to check for the return code of
       recv and see if it is WSAENOTSOCK.  However the recv may block
       after the server process died and thus the destroy_reader will
       hang.  Another option is to use getsockopt to test whether it is
       a socket.  The bug here is that once a socket with a certain
       values has been opened, closed and later a CreatePipe returned
       the same value (i.e. handle), getsockopt still believes it is a
       socket.  What we do now is to use a combination of GetFileType
       and GetNamedPipeInfo.  The specs say that the latter may be used
       on anonymous pipes as well.  Note that there are claims that
       since winsocket version 2 ReadFile may be used on a socket but
       only if it is supported by the service provider.  Tests on a
       stock XP using a local TCP socket show that it does not work.  */
    DWORD dummyflags, dummyoutsize, dummyinsize, dummyinst;
    if (GetFileType (hd) == FILE_TYPE_PIPE
            && !GetNamedPipeInfo (hd, &dummyflags, &dummyoutsize,
                                  &dummyinsize, &dummyinst))
        return 1; /* Function failed; thus we assume it is a socket.  */
    else
        return 0; /* Success; this is not a socket.  */
}
Пример #6
0
fcgi_request *fcgi_init_request(fcgi_request *req, int listen_socket)
{
	memset(req, 0, sizeof(fcgi_request));
	req->listen_socket = listen_socket;
	req->fd = -1;
	req->id = -1;

	/*
	req->in_len = 0;
	req->in_pad = 0;

	req->out_hdr = NULL;

#ifdef TCP_NODELAY
	req->nodelay = 0;
#endif

	req->env = NULL;
	req->has_env = 0;

	*/
	req->out_pos = req->out_buf;
	req->hook.on_accept = fcgi_hook_dummy;
	req->hook.on_read = fcgi_hook_dummy;
	req->hook.on_close = fcgi_hook_dummy;

#ifdef _WIN32
	req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif

	fcgi_hash_init(&req->env);

	return req;
}
Пример #7
0
static PRInt32
nsNamedPipeRecv(PRFileDesc* aFd,
                void* aBuffer,
                PRInt32 aAmount,
                PRIntn aFlags,
                PRIntervalTime aTimeout)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  Unused << aTimeout;

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return -1;
  }

  if (aFlags) {
    if (aFlags != PR_MSG_PEEK) {
      PR_SetError(PR_UNKNOWN_ERROR, 0);
      return -1;
    }
    return info->Peek(aBuffer, aAmount);
  }

  return info->Read(aBuffer, aAmount);
}
Пример #8
0
static PRInt64
nsNamedPipeAvailable64(PRFileDesc* aFd)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return -1;
  }
  return static_cast<PRInt64>(info->Available());
}
Пример #9
0
HRESULT NamedPipeChannel::GetMaxInstances(DWORD* count) const {
  if (count == nullptr)
    return E_POINTER;

  if (!IsValid())
    return E_HANDLE;

  if (!GetNamedPipeInfo(handle_, nullptr, nullptr, nullptr, count))
    return HRESULT_FROM_WIN32(GetLastError());

  return S_OK;
}
Пример #10
0
static PRInt16
nsNamedPipePoll(PRFileDesc* aFd, PRInt16 aInFlags, PRInt16* aOutFlags)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return 0;
  }
  return info->GetPollFlags(aInFlags, aOutFlags);
}
Пример #11
0
static PRStatus
nsNamedPipeSync(PRFileDesc* aFd)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return PR_FAILURE;
  }
  return info->Sync(0) ? PR_SUCCESS : PR_FAILURE;
}
Пример #12
0
static inline PRInt32
nsNamedPipeWrite(PRFileDesc* aFd, const void* aBuffer, PRInt32 aAmount)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return -1;
  }
  return info->Write(aBuffer, aAmount);
}
Пример #13
0
void fcgi_init_request(fcgi_request *req, int listen_socket)
{
	memset(req, 0, sizeof(fcgi_request));
	req->listen_socket = listen_socket;
	req->fd = -1;
	req->id = -1;

	req->in_len = 0;
	req->in_pad = 0;

	req->out_hdr = NULL;
	req->out_pos = req->out_buf;

#ifdef _WIN32
	req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif
}
Пример #14
0
static PRStatus
nsNamedPipeClose(PRFileDesc* aFd)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  if (aFd->secret && PR_GetLayersIdentity(aFd) == nsNamedPipeLayerIdentity) {
    RefPtr<NamedPipeInfo> info = dont_AddRef(GetNamedPipeInfo(aFd));
    info->Disconnect();
    aFd->secret = nullptr;
    aFd->identity = PR_INVALID_IO_LAYER;
  }

  MOZ_ASSERT(!aFd->lower);
  PR_DELETE(aFd);

  return PR_SUCCESS;
}
Пример #15
0
static PRInt32
nsNamedPipeSend(PRFileDesc* aFd,
                const void* aBuffer,
                PRInt32 aAmount,
                PRIntn aFlags,
                PRIntervalTime aTimeout)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  Unused << aFlags;
  Unused << aTimeout;

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return -1;
  }
  return info->Write(aBuffer, aAmount);
}
Пример #16
0
static PRStatus
nsNamedPipeConnect(PRFileDesc* aFd,
                   const PRNetAddr* aAddr,
                   PRIntervalTime aTimeout)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  NamedPipeInfo* info = GetNamedPipeInfo(aFd);
  if (!info) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
    return PR_FAILURE;
  }

  if (NS_WARN_IF(NS_FAILED(info->Connect(
      nsDependentCString(aAddr->local.path))))) {
    return PR_FAILURE;
  }

  return PR_SUCCESS;
}
Пример #17
0
static PRStatus
nsNamedPipeSetSocketOption(PRFileDesc* aFd, const PRSocketOptionData* aData)
{
  MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);

  MOZ_ASSERT(aFd);
  MOZ_ASSERT(aData);

  switch (aData->option) {
    case PR_SockOpt_Nonblocking:
      GetNamedPipeInfo(aFd)->SetNonblocking(aData->value.non_blocking);
      break;
    case PR_SockOpt_Keepalive:
    case PR_SockOpt_NoDelay:
      break;
    default:
      PR_SetError(PR_INVALID_METHOD_ERROR, 0);
      return PR_FAILURE;
  }

  return PR_SUCCESS;
}
Пример #18
0
RTDECL(int)  RTPipeFromNative(PRTPIPE phPipe, RTHCINTPTR hNativePipe, uint32_t fFlags)
{
    AssertPtrReturn(phPipe, VERR_INVALID_POINTER);
    AssertReturn(!(fFlags & ~RTPIPE_N_VALID_MASK), VERR_INVALID_PARAMETER);
    AssertReturn(!!(fFlags & RTPIPE_N_READ) != !!(fFlags & RTPIPE_N_WRITE), VERR_INVALID_PARAMETER);

    /*
     * Get and validate the pipe handle info.
     */
    HANDLE hNative = (HANDLE)hNativePipe;
    AssertReturn(GetFileType(hNative) == FILE_TYPE_PIPE, VERR_INVALID_HANDLE);

    DWORD cMaxInstances;
    DWORD fInfo;
    if (!GetNamedPipeInfo(hNative, &fInfo, NULL, NULL, &cMaxInstances))
        return RTErrConvertFromWin32(GetLastError());
    AssertReturn(!(fInfo & PIPE_TYPE_MESSAGE), VERR_INVALID_HANDLE);
    AssertReturn(cMaxInstances == 1, VERR_INVALID_HANDLE);

    DWORD cInstances;
    DWORD fState;
    if (!GetNamedPipeHandleState(hNative, &fState, &cInstances, NULL, NULL, NULL, 0))
        return RTErrConvertFromWin32(GetLastError());
    AssertReturn(!(fState & PIPE_NOWAIT), VERR_INVALID_HANDLE);
    AssertReturn(!(fState & PIPE_READMODE_MESSAGE), VERR_INVALID_HANDLE);
    AssertReturn(cInstances <= 1, VERR_INVALID_HANDLE);

    /*
     * Looks kind of OK, create a handle so we can try rtPipeQueryInfo on it
     * and see if we need to duplicate it to make that call work.
     */
    RTPIPEINTERNAL *pThis = (RTPIPEINTERNAL *)RTMemAllocZ(sizeof(RTPIPEINTERNAL));
    if (!pThis)
        return VERR_NO_MEMORY;
    int rc = RTCritSectInit(&pThis->CritSect);
    if (RT_SUCCESS(rc))
    {
        pThis->Overlapped.hEvent = CreateEvent(NULL, TRUE /*fManualReset*/,
                                               TRUE /*fInitialState*/, NULL /*pName*/);
        if (pThis->Overlapped.hEvent != NULL)
        {
            pThis->u32Magic        = RTPIPE_MAGIC;
            pThis->hPipe           = hNative;
            pThis->fRead           = !!(fFlags & RTPIPE_N_READ);
            //pThis->fIOPending      = false;
            //pThis->fZeroByteRead   = false;
            //pThis->fBrokenPipe     = false;
            //pThisR->fPromisedWritable= false;
            //pThis->cUsers          = 0;
            //pThis->pbBounceBuf     = NULL;
            //pThis->cbBounceBufUsed = 0;
            //pThis->cbBounceBufAlloc= 0;
            pThis->hPollSet        = NIL_RTPOLLSET;

            HANDLE  hNative2 = INVALID_HANDLE_VALUE;
            FILE_PIPE_LOCAL_INFORMATION Info;
            if (rtPipeQueryInfo(pThis, &Info))
                rc = VINF_SUCCESS;
            else
            {
                if (DuplicateHandle(GetCurrentProcess() /*hSrcProcess*/, hNative /*hSrcHandle*/,
                                    GetCurrentProcess() /*hDstProcess*/, &hNative2 /*phDstHandle*/,
                                    pThis->fRead ? GENERIC_READ : GENERIC_WRITE | FILE_READ_ATTRIBUTES /*dwDesiredAccess*/,
                                    !!(fFlags & RTPIPE_N_INHERIT) /*fInheritHandle*/,
                                    0 /*dwOptions*/))
                {
                    pThis->hPipe = hNative2;
                    if (rtPipeQueryInfo(pThis, &Info))
                        rc = VINF_SUCCESS;
                    else
                    {
                        rc = VERR_ACCESS_DENIED;
                        CloseHandle(hNative2);
                    }
                }
                else
                    hNative2 = INVALID_HANDLE_VALUE;
            }
            if (RT_SUCCESS(rc))
            {
                /*
                 * Verify the pipe state and correct the inheritability.
                 */
                AssertStmt(   Info.NamedPipeState == FILE_PIPE_CONNECTED_STATE
                           || Info.NamedPipeState == FILE_PIPE_CLOSING_STATE
                           || Info.NamedPipeState == FILE_PIPE_DISCONNECTED_STATE,
                           VERR_INVALID_HANDLE);
                AssertStmt(   Info.NamedPipeConfiguration
                           == (   Info.NamedPipeEnd == FILE_PIPE_SERVER_END
                               ? (pThis->fRead ? FILE_PIPE_INBOUND  : FILE_PIPE_OUTBOUND)
                               : (pThis->fRead ? FILE_PIPE_OUTBOUND : FILE_PIPE_INBOUND) ),
                           VERR_INVALID_HANDLE);
                if (   RT_SUCCESS(rc)
                    && hNative2 == INVALID_HANDLE_VALUE
                    && !SetHandleInformation(hNative,
                                             HANDLE_FLAG_INHERIT /*dwMask*/,
                                             fFlags & RTPIPE_N_INHERIT ? HANDLE_FLAG_INHERIT : 0))
                {
                    rc = RTErrConvertFromWin32(GetLastError());
                    AssertMsgFailed(("%Rrc\n", rc));
                }
                if (RT_SUCCESS(rc))
                {
                    /*
                     * Ok, we're good!
                     */
                    if (hNative2 != INVALID_HANDLE_VALUE)
                        CloseHandle(hNative);
                    *phPipe = pThis;
                    return VINF_SUCCESS;
                }
            }

            /* Bail out. */
            if (hNative2 != INVALID_HANDLE_VALUE)
                CloseHandle(hNative2);
            CloseHandle(pThis->Overlapped.hEvent);
        }
        RTCritSectDelete(&pThis->CritSect);
    }
    RTMemFree(pThis);
    return rc;
}
RTDECL(int) RTHandleGetStandard(RTHANDLESTD enmStdHandle, PRTHANDLE ph)
{
    /*
     * Validate and convert input.
     */
    AssertPtrReturn(ph, VERR_INVALID_POINTER);
    DWORD dwStdHandle;
    switch (enmStdHandle)
    {
        case RTHANDLESTD_INPUT:  dwStdHandle = STD_INPUT_HANDLE; break;
        case RTHANDLESTD_OUTPUT: dwStdHandle = STD_OUTPUT_HANDLE; break;
        case RTHANDLESTD_ERROR:  dwStdHandle = STD_ERROR_HANDLE; break;
        default:
            AssertFailedReturn(VERR_INVALID_PARAMETER);
    }

    /*
     * Is the requested descriptor valid and which IPRT handle type does it
     * best map on to?
     */
    HANDLE hNative = GetStdHandle(dwStdHandle);
    if (hNative == INVALID_HANDLE_VALUE)
        return RTErrConvertFromWin32(GetLastError());

    DWORD dwInfo;
    if (!GetHandleInformation(hNative, &dwInfo))
        return RTErrConvertFromWin32(GetLastError());
    bool const fInherit = RT_BOOL(dwInfo & HANDLE_FLAG_INHERIT);

    RTHANDLE h;
    DWORD    dwType = GetFileType(hNative);
    switch (dwType & ~FILE_TYPE_REMOTE)
    {
        default:
        case FILE_TYPE_UNKNOWN:
        case FILE_TYPE_CHAR:
        case FILE_TYPE_DISK:
            h.enmType = RTHANDLETYPE_FILE;
            break;

        case FILE_TYPE_PIPE:
        {
            DWORD cMaxInstances;
            DWORD fInfo;
            if (!GetNamedPipeInfo(hNative, &fInfo, NULL, NULL, &cMaxInstances))
                h.enmType = RTHANDLETYPE_SOCKET;
            else
                h.enmType = RTHANDLETYPE_PIPE;
            break;
        }
    }

    /*
     * Create the IPRT handle.
     */
    int rc;
    switch (h.enmType)
    {
        case RTHANDLETYPE_FILE:
            rc = RTFileFromNative(&h.u.hFile, (RTHCUINTPTR)hNative);
            break;

        case RTHANDLETYPE_PIPE:
            rc = RTPipeFromNative(&h.u.hPipe, (RTHCUINTPTR)hNative,
                                    (enmStdHandle == RTHANDLESTD_INPUT ? RTPIPE_N_READ : RTPIPE_N_WRITE)
                                  | (fInherit ? RTPIPE_N_INHERIT : 0));
            break;

        case RTHANDLETYPE_SOCKET:
            rc = rtSocketCreateForNative(&h.u.hSocket, (RTHCUINTPTR)hNative);
            break;

        default: /* shut up gcc */
            return VERR_INTERNAL_ERROR;
    }

    if (RT_SUCCESS(rc))
        *ph = h;

    return rc;
}
Пример #20
0
ssize_t
rpl_write (int fd, const void *buf, size_t count)
{
  for (;;)
    {
      ssize_t ret = write_nothrow (fd, buf, count);

      if (ret < 0)
        {
# if GNULIB_NONBLOCKING
          if (errno == ENOSPC)
            {
              HANDLE h = (HANDLE) _get_osfhandle (fd);
              if (GetFileType (h) == FILE_TYPE_PIPE)
                {
                  /* h is a pipe or socket.  */
                  DWORD state;
                  if (GetNamedPipeHandleState (h, &state, NULL, NULL, NULL,
                                               NULL, 0)
                      && (state & PIPE_NOWAIT) != 0)
                    {
                      /* h is a pipe in non-blocking mode.
                         We can get here in four situations:
                           1. When the pipe buffer is full.
                           2. When count <= pipe_buf_size and the number of
                              free bytes in the pipe buffer is < count.
                           3. When count > pipe_buf_size and the number of free
                              bytes in the pipe buffer is > 0, < pipe_buf_size.
                           4. When count > pipe_buf_size and the pipe buffer is
                              entirely empty.
                         The cases 1 and 2 are POSIX compliant.  In cases 3 and
                         4 POSIX specifies that write() must split the request
                         and succeed with a partial write.  We fix case 4.
                         We don't fix case 3 because it is not essential for
                         programs.  */
                      DWORD out_size; /* size of the buffer for outgoing data */
                      DWORD in_size;  /* size of the buffer for incoming data */
                      if (GetNamedPipeInfo (h, NULL, &out_size, &in_size, NULL))
                        {
                          size_t reduced_count = count;
                          /* In theory we need only one of out_size, in_size.
                             But I don't know which of the two.  The description
                             is ambiguous.  */
                          if (out_size != 0 && out_size < reduced_count)
                            reduced_count = out_size;
                          if (in_size != 0 && in_size < reduced_count)
                            reduced_count = in_size;
                          if (reduced_count < count)
                            {
                              /* Attempt to write only the first part.  */
                              count = reduced_count;
                              continue;
                            }
                        }
                      /* Change errno from ENOSPC to EAGAIN.  */
                      errno = EAGAIN;
                    }
                }
            }
          else
# endif
            {
# if GNULIB_SIGPIPE
              if (GetLastError () == ERROR_NO_DATA
                  && GetFileType ((HANDLE) _get_osfhandle (fd))
                     == FILE_TYPE_PIPE)
                {
                  /* Try to raise signal SIGPIPE.  */
                  raise (SIGPIPE);
                  /* If it is currently blocked or ignored, change errno from
                     EINVAL to EPIPE.  */
                  errno = EPIPE;
                }
# endif
            }
        }
      return ret;
    }
}
Пример #21
0
void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle,
    const char* name, uv_connect_cb cb) {
  uv_loop_t* loop = handle->loop;
  int errno, nameSize;

  handle->handle = INVALID_HANDLE_VALUE;

  uv_req_init(loop, (uv_req_t*) req);
  req->type = UV_CONNECT;
  req->handle = (uv_stream_t*) handle;
  req->cb = cb;

  /* Convert name to UTF16. */
  nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
  handle->name = (wchar_t*)malloc(nameSize);
  if (!handle->name) {
    uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
  }

  if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
    errno = GetLastError();
    goto error;
  }

  if (open_named_pipe(handle) != 0) {
    if (GetLastError() == ERROR_PIPE_BUSY) {
      /* Wait for the server to make a pipe instance available. */
      if (!QueueUserWorkItem(&pipe_connect_thread_proc,
                             req,
                             WT_EXECUTELONGFUNCTION)) {
        errno = GetLastError();
        goto error;
      }

      handle->reqs_pending++;

      return;
    }

    errno = GetLastError();
    goto error;
  }

  assert(handle->handle != INVALID_HANDLE_VALUE);

  /* Ensure that what we just opened is actually a pipe */
  if (!GetNamedPipeInfo(handle->handle, NULL, NULL, NULL, NULL)) {
    errno = WSAENOTSOCK;
    goto error;
  }

  if (uv_set_pipe_handle(loop, (uv_pipe_t*)req->handle, handle->handle)) {
    errno = GetLastError();
    goto error;
  }

  SET_REQ_SUCCESS(req);
  uv_insert_pending_req(loop, (uv_req_t*) req);
  handle->reqs_pending++;
  return;

error:
  if (handle->name) {
    free(handle->name);
    handle->name = NULL;
  }

  if (handle->handle != INVALID_HANDLE_VALUE) {
    CloseHandle(handle->handle);
    handle->handle = INVALID_HANDLE_VALUE;
  }

  /* Make this req pending reporting an error. */
  SET_REQ_ERROR(req, errno);
  uv_insert_pending_req(loop, (uv_req_t*) req);
  handle->reqs_pending++;
  return;
}