Class: Winipc::Pipe::Listener
- Inherits:
-
Object
- Object
- Winipc::Pipe::Listener
- Defined in:
- lib/winipc.rb,
ext/winipc/winipc.c
Instance Method Summary collapse
-
#_accept(vms) ⇒ Object
Listener#_accept(timeout_ms) -> Conn, or nil on timeout (-1 ms == INFINITE).
-
#accept(timeout: nil) ⇒ Object
Accept the next client.
- #close ⇒ Object
- #closed? ⇒ Boolean
-
#serve ⇒ Object
Accept clients in a loop, yielding (and closing) each connection.
Instance Method Details
#_accept(vms) ⇒ Object
Listener#_accept(timeout_ms) -> Conn, or nil on timeout (-1 ms == INFINITE).
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'ext/winipc/winipc.c', line 411
static VALUE
listener_accept(VALUE self, VALUE vms)
{
listener_t *l = listener_get(self);
long ms_in = NUM2LONG(vms);
DWORD ms = (ms_in < 0) ? INFINITE : (DWORD)ms_in;
OVERLAPPED ov;
HANDLE cur;
VALUE connobj;
conn_t *c;
DWORD gle, wgle = 0;
int connected = 0;
if (l->closed) rb_raise(eClosed, "winipc: listener is closed");
if (l->pending == INVALID_HANDLE_VALUE)
l->pending = listener_make_instance(l); /* recover if a prior accept failed mid-rotate */
memset(&ov, 0, sizeof(ov));
ov.hEvent = l->event;
ResetEvent(l->event);
if (ConnectNamedPipe(l->pending, &ov)) {
connected = 1; /* completed synchronously (rare) */
} else {
gle = GetLastError();
if (gle == ERROR_PIPE_CONNECTED) {
connected = 1; /* client connected in the create/connect gap — success */
} else if (gle == ERROR_IO_PENDING) {
DWORD w = ov_wait(l->pending, &ov, ms, &wgle);
DWORD n;
if (w == WAIT_TIMEOUT) {
CancelIoEx(l->pending, &ov);
/* If a client connected during the cancel race, keep it rather
* than orphaning it; otherwise report the timeout. */
if (GetOverlappedResult(l->pending, &ov, &n, TRUE))
connected = 1;
else
return Qnil;
} else if (w != WAIT_OBJECT_0) {
ov_drain(l->pending, &ov);
raise_gle("WaitForSingleObject", wgle);
} else if (GetOverlappedResult(l->pending, &ov, &n, FALSE)) {
connected = 1;
} else {
gle = GetLastError();
if (gle == ERROR_OPERATION_ABORTED) return Qnil; /* interrupted */
raise_gle("ConnectNamedPipe", gle);
}
} else {
raise_gle("ConnectNamedPipe", gle);
}
}
if (!connected) return Qnil;
/* Move the connected instance into a Conn (so its free hook owns it), then
* pre-create the next listening instance so the name stays live for the
* next client (no ERROR_FILE_NOT_FOUND gap between accepts). */
cur = l->pending;
connobj = conn_alloc(cConn);
c = conn_get(connobj);
c->h = cur;
c->is_server = 1;
c->message_read = (l->pipe_mode & PIPE_READMODE_MESSAGE) ? 1 : 0;
l->pending = INVALID_HANDLE_VALUE; /* ownership moved to the Conn */
c->read_event = CreateEventW(NULL, TRUE, FALSE, NULL);
c->write_event = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!c->read_event || !c->write_event) raise_gle("CreateEvent", GetLastError());
l->pending = listener_make_instance(l);
return connobj;
}
|
#accept(timeout: nil) ⇒ Object
Accept the next client. Blocks (cooperatively under a scheduler). With a timeout, returns nil if none connects in time.
177 178 179 |
# File 'lib/winipc.rb', line 177 def accept(timeout: nil) Winipc.run_blocking { _accept(Winipc.ms_for(timeout)) } end |
#close ⇒ Object
484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'ext/winipc/winipc.c', line 484
static VALUE
listener_close(VALUE self)
{
listener_t *l = listener_get(self);
if (l->pending && l->pending != INVALID_HANDLE_VALUE) {
DisconnectNamedPipe(l->pending);
CloseHandle(l->pending);
l->pending = INVALID_HANDLE_VALUE;
}
if (l->event) { CloseHandle(l->event); l->event = NULL; }
l->closed = 1;
return Qnil;
}
|
#closed? ⇒ Boolean
498 499 500 501 502 |
# File 'ext/winipc/winipc.c', line 498
static VALUE
listener_closed_p(VALUE self)
{
return listener_get(self)->closed ? Qtrue : Qfalse;
}
|
#serve ⇒ Object
Accept clients in a loop, yielding (and closing) each connection.
182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/winipc.rb', line 182 def serve loop do conn = accept break if conn.nil? begin yield conn ensure conn.close end end end |