From 491769a99f9c284b30ea33c443b4ee16ca2b83b6 Mon Sep 17 00:00:00 2001 From: manojampalam Date: Wed, 13 Apr 2016 19:59:06 -0700 Subject: [PATCH] 4-13 C1 --- contrib/win32/openssh/ssh-agent.vcxproj | 8 +- .../win32/win32compat/ssh-agent/agent-main.c | 15 ++- contrib/win32/win32compat/ssh-agent/agent.c | 84 +++++++-------- contrib/win32/win32compat/ssh-agent/agent.h | 24 +++-- .../win32/win32compat/ssh-agent/connection.c | 100 ++++++++++++++++-- 5 files changed, 162 insertions(+), 69 deletions(-) diff --git a/contrib/win32/openssh/ssh-agent.vcxproj b/contrib/win32/openssh/ssh-agent.vcxproj index 0d18f7a..7f8bf17 100644 --- a/contrib/win32/openssh/ssh-agent.vcxproj +++ b/contrib/win32/openssh/ssh-agent.vcxproj @@ -20,8 +20,12 @@ - - + + + + + + {F6644EC5-D6B6-42A1-828C-75E2977470E0} diff --git a/contrib/win32/win32compat/ssh-agent/agent-main.c b/contrib/win32/win32compat/ssh-agent/agent-main.c index 92af775..2295565 100644 --- a/contrib/win32/win32compat/ssh-agent/agent-main.c +++ b/contrib/win32/win32compat/ssh-agent/agent-main.c @@ -66,7 +66,7 @@ static VOID WINAPI service_handler(DWORD dwControl) { case SERVICE_CONTROL_STOP: { ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 500); - GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0); + agent_shutdown(); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } @@ -79,11 +79,20 @@ static VOID WINAPI service_handler(DWORD dwControl) ReportSvcStatus(service_status.dwCurrentState, NO_ERROR, 0); } +BOOL WINAPI ctrl_c_handler( + _In_ DWORD dwCtrlType + ) { + /* for any Ctrl type, shutdown agent*/ + agent_shutdown(); + return TRUE; +} + int main() { if (!StartServiceCtrlDispatcher(diapatch_table)) { if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { //console app - start_agent(); + SetConsoleCtrlHandler(ctrl_c_handler, TRUE); + return agent_start(); } else return -1; @@ -97,6 +106,6 @@ int scm_start_servie(DWORD num, LPWSTR* args) { service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 300); ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); - return start_agent(); + return agent_start(); } diff --git a/contrib/win32/win32compat/ssh-agent/agent.c b/contrib/win32/win32compat/ssh-agent/agent.c index e2ecb6e..f91349f 100644 --- a/contrib/win32/win32compat/ssh-agent/agent.c +++ b/contrib/win32/win32compat/ssh-agent/agent.c @@ -36,17 +36,11 @@ static HANDLE ioc_port; static volatile long action_queue; static struct agent_connection* list; -enum agent_sm_event { - NEW_CLIENT_CONNECTION = 1, - CONNECTION_DONE = 2, - SHUTDOWN = 3 -}; - #define ACTION_LISTEN 0x80000000 #define ACTION_SHUTDOWN 0x40000000 void agent_sm_process_action_queue() { - long actions_remaining = 0; + do { if (action_queue & ACTION_SHUTDOWN) { /* go through the list and disconect each connection */ @@ -58,10 +52,12 @@ void agent_sm_process_action_queue() { /* remove unwanted queued actions */ InterlockedAnd(&action_queue, ~ACTION_LISTEN); - actions_remaining = InterlockedAnd(&action_queue, ~ACTION_SHUTDOWN); + if (InterlockedAnd(&action_queue, ~ACTION_SHUTDOWN) == ACTION_SHUTDOWN) + break; } else if (action_queue & ACTION_LISTEN) { - HANDLE h; + HANDLE h, temp; + long prev_queue; struct agent_connection* con = (struct agent_connection*)malloc(sizeof(struct agent_connection)); memset(con, 0, sizeof(struct agent_connection)); @@ -78,12 +74,13 @@ void agent_sm_process_action_queue() { NULL); /* remove action from queue before assigning iocp port*/ + con->connection = h; con->next = list; list = con; - actions_remaining = InterlockedAnd(&action_queue, ~ACTION_LISTEN); - CreateIoCompletionPort(h, ioc_port, con, 0); - - + prev_queue = InterlockedAnd(&action_queue, ~ACTION_LISTEN); + temp = CreateIoCompletionPort(h, ioc_port, (ULONG_PTR)con, 0); + if (prev_queue == ACTION_LISTEN) + break; } else { /* cleanup up a done connection*/ @@ -101,35 +98,30 @@ void agent_sm_process_action_queue() { prev = tmp; tmp = tmp->next; } - actions_remaining = InterlockedDecrement(&action_queue); + if (InterlockedDecrement(&action_queue) == 0) + break; } - } while (actions_remaining); + } while (1); } -void agent_sm_raise(enum agent_sm_event event) { - long ret = 0; - switch (event) { - case NEW_CLIENT_CONNECTION: - ret = InterlockedOr(&action_queue, ACTION_LISTEN); - if (ret == 0) - agent_sm_process_action_queue(); - break; - case SHUTDOWN: - ret = InterlockedOr(&action_queue, ACTION_SHUTDOWN); - if (ret == 0) - agent_sm_process_action_queue(); - break; - case CONNECTION_DONE: - ret = InterlockedIncrement(&action_queue); - if (ret == 1) - agent_sm_process_action_queue(); - break; - default: - DebugBreak(); - } +void +agent_cleanup_connection(struct agent_connection* con) { + if (InterlockedIncrement(&action_queue) == 1) + agent_sm_process_action_queue(); +} - /* is this the first action queued */ +void +agent_listen() { + if (InterlockedOr(&action_queue, ACTION_LISTEN) == 0) + agent_sm_process_action_queue(); +} + +void agent_shutdown() { + if (InterlockedOr(&action_queue, ACTION_SHUTDOWN) == 0) + agent_sm_process_action_queue(); + while (list != NULL) + Sleep(100); } HANDLE iocp_workers[4]; @@ -139,7 +131,7 @@ DWORD WINAPI iocp_work(LPVOID lpParam) { struct agent_connection* con; OVERLAPPED *p_ol; while (1) { - GetQueuedCompletionStatus(ioc_port, &bytes, &con, &p_ol, INFINITE); + GetQueuedCompletionStatus(ioc_port, &bytes, &(ULONG_PTR)con, &p_ol, INFINITE); agent_connection_on_io(con, bytes, p_ol); } } @@ -148,17 +140,13 @@ int agent_start() { int i; action_queue = 0; list = NULL; - ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0); + ioc_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)NULL, 0); - for (i = 0; i < 4; i++) - iocp_workers[i] = CreateThread(NULL, 0, iocp_work, NULL, 0, NULL); + for (i = 0; i < 3; i++) + QueueUserWorkItem(iocp_work, NULL, 0); - action_queue = ACTION_LISTEN; - agent_sm_process_action_queue(); + agent_listen(); + iocp_work(NULL); + return 1; } -void agent_shutdown() { - agent_sm_raise(SHUTDOWN); - while (list != NULL) - Sleep(100); -} diff --git a/contrib/win32/win32compat/ssh-agent/agent.h b/contrib/win32/win32compat/ssh-agent/agent.h index 9ea69e8..4cbf158 100644 --- a/contrib/win32/win32compat/ssh-agent/agent.h +++ b/contrib/win32/win32compat/ssh-agent/agent.h @@ -1,20 +1,30 @@ #include #include +#define BUFSIZE 5 * 1024 - -int agent_start(); -void agent_shutdown(); - +#define HEADER_SIZE 4 struct agent_connection { + OVERLAPPED ol; + HANDLE connection; + struct { + DWORD size; + DWORD read; + char buf[BUFSIZE]; + } request; enum { LISTENING = 0, + READING_HEADER, READING, WRITING, DONE } state; - HANDLE connection; - struct agent_con* next; + struct agent_connection* next; }; void agent_connection_on_io(struct agent_connection*, DWORD, OVERLAPPED*); -void agent_connection_disconnect(struct agent_connection*); \ No newline at end of file +void agent_connection_disconnect(struct agent_connection*); + +int agent_start(); +void agent_shutdown(); +void agent_listen(); +void agent_cleanup_connection(struct agent_connection*); diff --git a/contrib/win32/win32compat/ssh-agent/connection.c b/contrib/win32/win32compat/ssh-agent/connection.c index 9d55545..a84e5bd 100644 --- a/contrib/win32/win32compat/ssh-agent/connection.c +++ b/contrib/win32/win32compat/ssh-agent/connection.c @@ -29,18 +29,100 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "agent.h" -#define BUFSIZE 5 * 1024 void agent_connection_on_io(struct agent_connection* con, DWORD bytes, OVERLAPPED* ol) { - switch (con->state) { - case LISTENING: - break; - case READING: - break; - case WRITING: - break; - default: + + /* process error */ + if ( (bytes == 0) && (GetOverlappedResult(con->connection, ol, &bytes, FALSE) == FALSE)) { + con->state = DONE; + agent_cleanup_connection(con); + return; + } + + if (con->state == DONE) DebugBreak(); + + while (1) { + switch (con->state) { + case WRITING: + /* Writing is done, read next request */ + case LISTENING: + con->state = READING_HEADER; + if (con->state == LISTENING) + agent_listen(); + ZeroMemory(&con->request, sizeof(con->request)); + if (ReadFile(con->connection, con->request.buf, + HEADER_SIZE, NULL, &con->ol)) { + bytes = HEADER_SIZE; + continue; + } + if (GetLastError() != ERROR_IO_PENDING) { + con->state = DONE; + agent_cleanup_connection(con); + return; + } + break; + case READING_HEADER: + con->request.read += bytes; + if (con->request.read == HEADER_SIZE) { + con->request.size = *((DWORD*)con->request.buf); + con->state = READING; + if (ReadFile(con->connection, con->request.buf, + con->request.size, NULL, &con->ol)) { + bytes = con->request.size; + continue; + } + if (GetLastError() != ERROR_IO_PENDING) { + con->state = DONE; + agent_cleanup_connection(con); + return; + } + } + else { + if (ReadFile(con->connection, con->request.buf + con->request.read, + HEADER_SIZE - con->request.read, NULL, &con->ol)) { + bytes = HEADER_SIZE - con->request.read; + continue; + } + if (GetLastError() != ERROR_IO_PENDING) { + con->state = DONE; + agent_cleanup_connection(con); + return; + } + } + break; + case READING: + con->request.read += bytes; + if (con->request.read == con->request.size) { + /* process request and get response */ + con->state = WRITING; + if (WriteFile(con->connection, con->request.buf, + con->request.size, NULL, &con->ol)) { + bytes = con->request.size; + continue; + } + if (GetLastError() != ERROR_IO_PENDING) { + con->state = DONE; + agent_cleanup_connection(con); + return; + } + } + else { + if (ReadFile(con->connection, con->request.buf + con->request.read, + con->request.size - con->request.read, NULL, &con->ol)) { + bytes = con->request.size - con->request.read; + continue; + } + if (GetLastError() != ERROR_IO_PENDING) { + con->state = DONE; + agent_cleanup_connection(con); + return; + } + } + break; + default: + DebugBreak(); + } } }