static bool FetchTimespec(struct timespec* dest, const struct timespec* user) { if ( !user ) dest->tv_sec = -1, dest->tv_nsec = 0; else if ( !CopyFromUser(dest, user, sizeof(*dest)) ) return false; return true; }
static struct pollfd* CopyFdsFromUser(struct pollfd* user_fds, size_t nfds) { size_t size = sizeof(struct pollfd) * nfds; struct pollfd* fds = new struct pollfd[nfds]; if ( !fds ) return NULL; if ( !CopyFromUser(fds, user_fds, size) ) { delete[] fds; return NULL; } return fds; }
NTSTATUS NtSetTimer( HANDLE TimerHandle, PLARGE_INTEGER DueTime, PTIMER_APC_ROUTINE TimerApcRoutine, PVOID TimerContext, BOOLEAN Resume, LONG Period, PBOOLEAN PreviousState) { LARGE_INTEGER due; NTSTATUS r = CopyFromUser( &due, DueTime, sizeof due ); if (r < STATUS_SUCCESS) return r; TRACE("due = %llx\n", due.QuadPart); NTTIMER* timer = 0; r = ObjectFromHandle( timer, TimerHandle, TIMER_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (PreviousState) { r = VerifyForWrite( PreviousState, sizeof *PreviousState ); if (r < STATUS_SUCCESS) return r; } BOOLEAN prev = FALSE; r = timer->Set( due, (PKNORMAL_ROUTINE)TimerApcRoutine, TimerContext, Resume, Period, prev ); if (r == STATUS_SUCCESS && PreviousState ) CopyToUser( PreviousState, &prev, sizeof prev ); return r; }
/*----------------------------------------------------------------------------*/ int mtcp_writev(mctx_t mctx, int sockid, struct iovec *iov, int numIOV) { mtcp_manager_t mtcp; socket_map_t socket; tcp_stream *cur_stream; struct tcp_send_vars *sndvar; int ret, to_write, i; mtcp = GetMTCPManager(mctx); if (!mtcp) { return -1; } if (sockid < 0 || sockid >= CONFIG.max_concurrency) { TRACE_API("Socket id %d out of range.\n", sockid); errno = EBADF; return -1; } socket = &mtcp->smap[sockid]; if (socket->socktype == MTCP_SOCK_UNUSED) { TRACE_API("Invalid socket id: %d\n", sockid); errno = EBADF; return -1; } if (socket->socktype != MTCP_SOCK_STREAM) { TRACE_API("Not an end socket. id: %d\n", sockid); errno = ENOTSOCK; return -1; } cur_stream = socket->stream; if (!cur_stream || !(cur_stream->state == TCP_ST_ESTABLISHED || cur_stream->state == TCP_ST_CLOSE_WAIT)) { errno = ENOTCONN; return -1; } sndvar = cur_stream->sndvar; SBUF_LOCK(&sndvar->write_lock); #if BLOCKING_SUPPORT if (!(socket->opts & MTCP_NONBLOCK)) { while (sndvar->snd_wnd <= 0) { TRACE_SNDBUF("Waiting for available sending window...\n"); if (!cur_stream || cur_stream->state != TCP_ST_ESTABLISHED) { SBUF_UNLOCK(&sndvar->write_lock); errno = EINTR; return -1; } pthread_cond_wait(&sndvar->write_cond, &sndvar->write_lock); TRACE_SNDBUF("Sending buffer became ready! snd_wnd: %u\n", sndvar->snd_wnd); } } #endif /* write from the vectored buffers */ to_write = 0; for (i = 0; i < numIOV; i++) { if (iov[i].iov_len <= 0) continue; ret = CopyFromUser(mtcp, cur_stream, iov[i].iov_base, iov[i].iov_len); if (ret <= 0) break; to_write += ret; if (ret < iov[i].iov_len) break; } SBUF_UNLOCK(&sndvar->write_lock); if (to_write > 0 && !(sndvar->on_sendq || sndvar->on_send_list)) { SQ_LOCK(&mtcp->ctx->sendq_lock); sndvar->on_sendq = TRUE; StreamEnqueue(mtcp->sendq, cur_stream); /* this always success */ SQ_UNLOCK(&mtcp->ctx->sendq_lock); mtcp->wakeup_flag = TRUE; } if (to_write == 0 && (socket->opts & MTCP_NONBLOCK)) { to_write = -1; errno = EAGAIN; } /* if there are remaining sending buffer, generate write event */ if (sndvar->snd_wnd > 0) { if (socket->epoll & MTCP_EPOLLOUT && !(socket->epoll & MTCP_EPOLLET)) { AddEpollEvent(mtcp->ep, USR_SHADOW_EVENT_QUEUE, socket, MTCP_EPOLLOUT); #if BLOCKING_SUPPORT } else if (!(socket->opts & MTCP_NONBLOCK)) { if (!cur_stream->on_snd_br_list) { cur_stream->on_snd_br_list = TRUE; TAILQ_INSERT_TAIL(&mtcp->snd_br_list, cur_stream, sndvar->snd_br_link); mtcp->snd_br_list_cnt++; } #endif } } TRACE_API("Stream %d: mtcp_writev() returning %d\n", cur_stream->id, to_write); return to_write; }
// blocking NTSTATUS NTAPI NtRemoveIoCompletion( HANDLE IoCompletionHandle, PULONG IoCompletionKey, PULONG IoCompletionValue, PIO_STATUS_BLOCK IoStatusBlock, PLARGE_INTEGER TimeOut) { NTSTATUS r; TRACE("%p %p %p %p %p\n", IoCompletionHandle, IoCompletionKey, IoCompletionValue, IoStatusBlock, TimeOut); COMPLETION_PORT_IMPL *port = 0; r = ObjectFromHandle( port, IoCompletionHandle, IO_COMPLETION_MODIFY_STATE ); if (r < STATUS_SUCCESS) return r; if (IoCompletionKey) { r = VerifyForWrite( IoCompletionKey, sizeof *IoCompletionKey ); if (r < STATUS_SUCCESS) return r; } if (IoCompletionValue) { r = VerifyForWrite( IoCompletionValue, sizeof *IoCompletionValue ); if (r < STATUS_SUCCESS) return r; } if (IoStatusBlock) { r = VerifyForWrite( IoStatusBlock, sizeof *IoStatusBlock ); if (r < STATUS_SUCCESS) return r; } LARGE_INTEGER t; t.QuadPart = 0LL; if (TimeOut) { r = CopyFromUser( &t, TimeOut, sizeof t ); if (r < STATUS_SUCCESS) return r; TimeOut = &t; } ULONG key = 0, val = 0; IO_STATUS_BLOCK iosb; iosb.Status = 0; iosb.Information = 0; port->Remove( key, val, iosb.Status, iosb.Information, TimeOut ); if (IoCompletionKey) CopyToUser( IoCompletionKey, &key, sizeof key ); if (IoCompletionValue) CopyToUser( IoCompletionValue, &val, sizeof val ); if (IoStatusBlock) CopyToUser( IoStatusBlock, &iosb, sizeof iosb ); return r; }