int main(int argc, char *argv[]) { BOOL fConnected; DWORD dwThreadId; HANDLE hPipe, hThread; LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); // for (;;) // { hPipe = CreateNamedPipe(lpszPipename, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, BUFSIZE, BUFSIZE, PIPE_TIMEOUT, NULL); if (hPipe == INVALID_HANDLE_VALUE) { printf("CreateNamedPipe() failed\n"); return 0; } fConnected = ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError () == ERROR_PIPE_CONNECTED); if (fConnected) { printf("Pipe connected!\n"); DisconnectNamedPipe(hPipe); #if 0 hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InstanceThread, (LPVOID) hPipe, 0, &dwThreadId); if (hThread == NULL) MyErrExit("CreateThread"); #endif } else { // CloseHandle(hPipe); } // } CloseHandle(hPipe); return 0; }
BOOL CreateWorkers(HANDLE hCompletionPort) { DWORD dwThread; HANDLE hThread; DWORD i; SYSTEM_INFO SystemInfo; GetSystemInfo(&SystemInfo); for (i = 0; i < 1; i++) { hThread = CreateThread(NULL, 0, WorkerThread, hCompletionPort, 0, &dwThread); if (!hThread) { MyErrExit("CreateThread WorkerThread"); // Unreachable: return FALSE; } CloseHandle(hThread); } return TRUE; }
DWORD main(int argc, char *argv[]) { HANDLE hPipe; LPVOID lpvMessage; CHAR chBuf[512]; BOOL fSuccess; DWORD cbRead, cbWritten, dwMode; LPTSTR lpszPipename = "\\\\.\\pipe\\mynamedpipe"; /* Try to open a named pipe; wait for it, if necessary. */ while (1) { hPipe = CreateFile( lpszPipename, /* pipe name */ GENERIC_READ | /* read/write access */ GENERIC_WRITE, 0, /* no sharing */ NULL, /* no security attr. */ OPEN_EXISTING, /* opens existing pipe */ 0, /* default attributes */ NULL); /* no template file */ /* Break if the pipe handle is valid. */ if (hPipe != INVALID_HANDLE_VALUE) break; /* Exit if an error other than ERROR_PIPE_BUSY occurs. */ if (GetLastError() != ERROR_PIPE_BUSY) MyErrExit("Could not open pipe"); /* All pipe instances are busy, so wait for 20 seconds. */ if (! WaitNamedPipe(lpszPipename, 20000) ) MyErrExit("Could not open pipe"); } /* The pipe connected; change to message-read mode. */ dwMode = PIPE_READMODE_MESSAGE; fSuccess = SetNamedPipeHandleState( hPipe, /* pipe handle */ &dwMode, /* new pipe mode */ NULL, /* don't set max. bytes */ NULL); /* don't set max. time */ if (! fSuccess) MyErrExit("SetNamedPipeHandleState"); /* Send a message to the pipe server. */ lpvMessage = (argc > 1) ? argv[1] : "default message"; fSuccess = WriteFile( hPipe, /* pipe handle */ lpvMessage, /* message */ strlen(lpvMessage) + 1, /* message length */ &cbWritten, /* bytes written */ NULL); /* not overlapped */ if (! fSuccess) MyErrExit("WriteFile"); do { /* Read from the pipe. */ fSuccess = ReadFile( hPipe, /* pipe handle */ chBuf, /* buffer to receive reply */ 512, /* size of buffer */ &cbRead, /* number of bytes read */ NULL); /* not overlapped */ if (! fSuccess && GetLastError() != ERROR_MORE_DATA) break; /* Reply from the pipe is written to STDOUT. */ if (! WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf, cbRead, &cbWritten, NULL)) break; } while (! fSuccess); /* repeat loop if ERROR_MORE_DATA */ CloseHandle(hPipe); return 0; }
int main(void) { //printf("SHARE %d\n", *KMotionLocal.sharePtr); /* SJH - modified to listen to a TCP socket in addition to the unix domain (local) socket. Listens at port KMOTION_PORT (defined in KMotionDLL.h). FIXME: need to make this an argc/argv parameter. */ #ifdef _DEAMON //daemonize2(); daemonize(); #endif //http://robertoacevedo.net/blog/2012/12/03/socket-server/ pthread_attr_t attr; // Thread attribute pthread_attr_init(&attr); // Creating thread attributes pthread_attr_setschedpolicy(&attr, SCHED_FIFO); // FIFO scheduling for threads pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // Don't want threads (particualrly main) // waiting on each other openlog("KMotionServer", LOG_PID|LOG_CONS, LOG_USER); syslog(LOG_ERR, "KMotionServer started "); int tcp_socket; int main_socket; int client_socket; unsigned int t; struct sockaddr_un local, remote; struct sockaddr_in tlocal, tremote; fd_set rfds; int retval; socklen_t len; bool select_timedout; if ((main_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perrorExit("socket"); } if ((tcp_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perrorExit("tcp socket"); } if (strlen(SOCK_PATH) >= sizeof(local.sun_path)) { perrorExit("path too long!"); } local.sun_family = AF_UNIX; strcpy(local.sun_path, SOCK_PATH); int unlink_err; if((unlink_err = unlink(local.sun_path))){ logError("unlink"); } //http://idletechnology.blogspot.se/2011/12/unix-domain-sockets-on-osx.html #ifdef __APPLE__ local.sun_len = sizeof(local); if (bind(main_socket, (struct sockaddr *)&local, SUN_LEN(&local)) == -1) { #else len = strlen(local.sun_path) + sizeof(local.sun_family); if (bind(main_socket, (struct sockaddr *)&local, len) == -1) { #endif perrorExit("bind"); } tlocal.sin_family = AF_INET; tlocal.sin_port = htons(KMOTION_PORT); tlocal.sin_addr.s_addr = INADDR_ANY; len = sizeof(tlocal); if (bind(tcp_socket, (struct sockaddr *)&tlocal, len) == -1) { perrorExit("tcp bind"); } if (listen(main_socket, 5) == -1) { perrorExit("listen"); } if (listen(tcp_socket, 5) == -1) { perrorExit("tcp listen"); } for (int i=0; i<MAX_BOARDS; i++) ConsolePipeHandle[i]=0; // The main loop creates an instance of the named pipe and // then waits for a client to connect to it. When the client // connects, a thread is created to handle communications // with that client, and the loop is repeated. //pthread_t ct = pthread_self(); //printf("Thread %.8x %.8x: Current thread\n", ct); select_timedout = false; for (;;) { FD_ZERO(&rfds); FD_SET(main_socket, &rfds); FD_SET(tcp_socket, &rfds); if(!select_timedout){ syslog(LOG_ERR,"Main Thread. Waiting for a connection...\n"); } struct timeval timeout; // Initialize the timeout data structure. timeout.tv_sec = 1; timeout.tv_usec = 0; retval = select(tcp_socket+1, &rfds, NULL, NULL, &timeout); select_timedout = retval == 0; if (retval < 0){ perrorExit("select"); } else if(select_timedout){ //If exit() is executed in the processs that started the server we never get here //Hence the reference counting from KMotionDLl.nInstances must be made. if (nClients <= 0) break; // nobody left - terminate server if (KMotionDLL.nInstances() < 2) break; // nobody left - terminate server continue; //timeout } else if (FD_ISSET(main_socket, &rfds)) { t = sizeof(remote); client_socket = accept(main_socket, (struct sockaddr *)&remote, &t); } else if (FD_ISSET(tcp_socket, &rfds)) { t = sizeof(tremote); client_socket = accept(tcp_socket, (struct sockaddr *)&tremote, &t); if (client_socket >= 0) { int flag = 1; setsockopt(client_socket, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); } } else { // select() man page indicates possibility that there is nothing really there continue; } if (client_socket < 0) { perrorExit("Main Thread. accept"); } else { //struct timeval tv; //tv.tv_sec = 5; /* 30 Secs Timeout */ //setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); syslog(LOG_ERR,"Main Thread. Connected descriptor %d %s\n", client_socket, FD_ISSET(tcp_socket, &rfds) ? "(tcp)" : "(local)"); nClients++; syslog(LOG_ERR,"Main Thread. Spawning worker\n"); pthread_t thr; // initialize data to pass to thread thdata data; data.file_desc = client_socket; if(pthread_create(&thr, &attr, &InstanceThread, (void *) &data)) { MyErrExit("Main Thread. pthread_create"); } } } closelog(); syslog(LOG_ERR,"Main Thread. Closing server\n"); exit(EXIT_SUCCESS); } //http://www.amparo.net/ce155/thread-ex.html void * InstanceThread(void *ptr){ thdata *data = (thdata*) ptr; int thread_socket = data->file_desc; //pthread_t ct = pthread_self(); //printf("Thread %.8x %.8x: Current thread\n", ct); syslog(LOG_ERR,"The ID of this of this thread is: %ld\n", syscall(SYS_gettid/*224*/)); syslog(LOG_ERR,"Worker Thread. Nr of Clients when entered %d", nClients); //vsyslog(LOG_INFO, "Inside Thread %d\n", thread_socket); syslog(LOG_ERR, "Worker Thread. Inside Thread %d\n", thread_socket); char chRequest[BUFSIZE]; char chReply[BUFSIZE]; unsigned short cbReplyBytes; int cbBytesRead, cbWritten; // SJH - messages to/from client must now be prefixed with 2-byte length word (except for ACK 0xAA from client // in response to console or error messages). This allows working over // network with SOCK_STREAM sockets where message boundaries are likely to be broken. Even with Unix // domain sockets, this is safer. unsigned short msglen; unsigned short len; enum { RD_LEN, RD_MSG } state; state = RD_LEN; len = 0; msglen = sizeof(msglen); bool cont = true; while(cont) { cbBytesRead = recv(thread_socket, chRequest + len, msglen - len, 0); if (cbBytesRead <= 0) { if (cbBytesRead < 0){ logError("Worker Thread. recv"); } else { syslog(LOG_ERR,"Worker Thread. received 0 bytes"); } break; } len += cbBytesRead; switch (state) { case RD_LEN: if (len == msglen) { memcpy(&msglen, chRequest, sizeof(msglen)); state = RD_MSG; len = 0; if (msglen > sizeof(chRequest)) { // Too long to possibly fit in buffer. This should not happen unless client bad. syslog(LOG_ERR,"Worker Thread. Message prefix %hu too long", msglen); cont = false; continue; } } continue; case RD_MSG: if (len == msglen) { cbBytesRead = len; msglen = sizeof(msglen); state = RD_LEN; len = 0; break; // from switch and process this msg } continue; } GetAnswerToRequest(chRequest, cbBytesRead, chReply+sizeof(msglen), &cbReplyBytes, thread_socket); memcpy(chReply, &cbReplyBytes, sizeof(msglen)); cbReplyBytes += sizeof(msglen); cbWritten = send(thread_socket, chReply, cbReplyBytes, 0); if (cbWritten < 0 || cbReplyBytes != cbWritten) { if (cbWritten < 0){ logError("Worker Thread. send"); } else { syslog(LOG_ERR,"Worker Thread. %d bytes written != %d bytes sent\n",cbWritten,cbReplyBytes); } break; } } syslog(LOG_ERR,"Worker Thread. Exiting thread %d", thread_socket); // Flush the pipe to allow the client to read the pipe's contents // before disconnecting. Then disconnect the pipe, and close the // handle to this pipe instance. // FlushFileBuffers(thread_socket); // DisconnectNamedPipe(thread_socket); // CloseHandle(thread_socket); if(shutdown(thread_socket,SHUT_RDWR)< 0){ logError("thread socket shutdown"); } close(thread_socket); syslog(LOG_ERR,"Worker Thread. Nr of clients left %d", --nClients); pthread_exit(0); return 0; }
void perrorExit(const char *s) { logError(s); MyErrExit(s); }
DWORD main(int argc, char *argv[]) { HANDLE hPipe; SYELOG_MESSAGE Message; BOOL fSuccess; DWORD cbWritten, dwMode; // Try to open a named pipe; wait for it, if necessary. TIME_ZONE_INFORMATION tzi; GetTimeZoneInformation(&tzi); for (;;) { hPipe = CreateFileW(SYELOG_PIPE_NAMEW, // pipe name GENERIC_WRITE, // write access only 0, // no sharing NULL, // no security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file // Break if the pipe handle is valid. if (hPipe != INVALID_HANDLE_VALUE) break; // Exit if an error other than ERROR_PIPE_BUSY occurs. if (GetLastError() != ERROR_PIPE_BUSY) MyErrExit("Could not open pipe"); // All pipe instances are busy, so wait for 1 seconds. if (!WaitNamedPipeW(SYELOG_PIPE_NAMEW, 1000)) MyErrExit("Could not open pipe"); } // The pipe connected; change to message-read mode. dwMode = PIPE_READMODE_MESSAGE; fSuccess = SetNamedPipeHandleState(hPipe, // pipe handle &dwMode, // new pipe mode NULL, // don't set maximum bytes NULL); // don't set maximum time if (!fSuccess) MyErrExit("SetNamedPipeHandleState"); // Send a message to the pipe server. memset(&Message, 0, sizeof(Message)); StringCchCopyA(Message.szMessage, ARRAYSIZE(Message.szMessage), (argc > 1) ? argv[1] : "sltestp: hello world!"); Message.nFacility = SYELOG_FACILITY_APPLICATION; Message.nSeverity = SYELOG_SEVERITY_INFORMATION; Message.nProcessId = GetCurrentProcessId(); GetSystemTimeAsFileTime(&Message.ftOccurance); PCSTR pszEnd = Message.szMessage; for (; *pszEnd; pszEnd++) { // no internal contents. } Message.nBytes = (USHORT)(pszEnd - ((PCSTR)&Message) + 1); fSuccess = WriteFile(hPipe, // pipe handle &Message, // message Message.nBytes, // message length &cbWritten, // bytes written NULL); // not overlapped if (! fSuccess) MyErrExit("WriteFile"); CloseHandle(hPipe); GetTimeZoneInformation(&tzi); return 0; }
DWORD main(int argc, char **argv) { HANDLE hCompletionPort; BOOL fNeedHelp = FALSE; WCHAR wzzDrop[1024] = L"build\0nmake\0"; GetSystemTimeAsFileTime((FILETIME *)&s_llStartTime); StringCchPrintfA(s_szPipe, ARRAYSIZE(s_szPipe), "%s.%d", TBLOG_PIPE_NAME, GetCurrentProcessId()); int arg = 1; for (; arg < argc && (argv[arg][0] == '-' || argv[arg][0] == '/'); arg++) { CHAR *argn = argv[arg] + 1; CHAR *argp = argn; while (*argp && *argp != ':' && *argp != '=') { argp++; } if (*argp == ':' || *argp == '=') { *argp++ = '\0'; } switch (argn[0]) { case 'd': // Drop Processes case 'D': if (*argp) { PWCHAR pwz = wzzDrop; while (*argp) { if (*argp == ';') { *pwz++ = '\0'; } else { *pwz++ = *argp++; } } *pwz++ = '\0'; *pwz = '\0'; } case 'o': // Output file. case 'O': StringCchCopyA(s_szLogFile, ARRAYSIZE(s_szLogFile), argp); break; case 'v': // Verbose case 'V': s_fVerbose = TRUE; break; case '?': // Help. fNeedHelp = TRUE; break; default: fNeedHelp = TRUE; printf("TRACEBLD: Bad argument: %s:%s\n", argn, argp); break; } } if (arg >= argc) { fNeedHelp = TRUE; } if (fNeedHelp) { printf("Usage:\n" " tracebld [options] command {command arguments}\n" "Options:\n" " /o:file Log all events to the output files.\n" " /? Display this help message.\n" "Summary:\n" " Runs the build commands and figures out which files have dependencies..\n" "\n"); exit(9001); } // Create the completion port. hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0); if (hCompletionPort == NULL) { MyErrExit("CreateIoCompletionPort"); } // Create completion port worker threads. // CreateWorkers(hCompletionPort); CreatePipeConnection(hCompletionPort, 0); printf("TRACEBLD: Ready for clients. Press Ctrl-C to stop.\n"); /////////////////////////////////////////////////////////// Validate DLLs. // CHAR szTmpPath[MAX_PATH]; CHAR szExePath[MAX_PATH]; CHAR szDllPath[MAX_PATH]; PCHAR pszFilePart = NULL; if (!GetModuleFileNameA(NULL, szTmpPath, ARRAYSIZE(szTmpPath))) { printf("TRACEBLD: Couldn't retreive exe name.\n"); return 9002; } if (!GetFullPathNameA(szTmpPath, ARRAYSIZE(szExePath), szExePath, &pszFilePart) || pszFilePart == NULL) { printf("TRACEBLD: Error: %s is not a valid path name..\n", szTmpPath); return 9002; } StringCchCopyA(pszFilePart, szExePath + ARRAYSIZE(szExePath) - pszFilePart, "trcbld" DETOURS_STRINGIFY(DETOURS_BITS) ".dll"); StringCchCopyA(szDllPath, ARRAYSIZE(szDllPath), szExePath); ////////////////////////////////////////////////////////////////////////// STARTUPINFOA si; PROCESS_INFORMATION pi; CHAR szCommand[2048]; CHAR szExe[MAX_PATH]; CHAR szFullExe[MAX_PATH] = "\0"; PCHAR pszFileExe = NULL; ZeroMemory(&si, sizeof(si)); ZeroMemory(&pi, sizeof(pi)); si.cb = sizeof(si); szCommand[0] = L'\0'; StringCchCopyA(szExe, sizeof(szExe), argv[arg]); for (; arg < argc; arg++) { if (strchr(argv[arg], ' ') != NULL || strchr(argv[arg], '\t') != NULL) { StringCchCatA(szCommand, sizeof(szCommand), "\""); StringCchCatA(szCommand, sizeof(szCommand), argv[arg]); StringCchCatA(szCommand, sizeof(szCommand), "\""); } else { StringCchCatA(szCommand, sizeof(szCommand), argv[arg]); } if (arg + 1 < argc) { StringCchCatA(szCommand, sizeof(szCommand), " "); } } printf("TRACEBLD: Starting: `%s'\n", szCommand); printf("TRACEBLD: with `%s'\n", szDllPath); fflush(stdout); DWORD dwFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED; SetLastError(0); SearchPathA(NULL, szExe, ".exe", ARRAYSIZE(szFullExe), szFullExe, &pszFileExe); if (!DetourCreateProcessWithDllExA(szFullExe[0] ? szFullExe : NULL, szCommand, NULL, NULL, TRUE, dwFlags, NULL, NULL, &si, &pi, szDllPath, NULL)) { printf("TRACEBLD: DetourCreateProcessWithDllEx failed: %d\n", GetLastError()); ExitProcess(9007); } ZeroMemory(&s_Payload, sizeof(s_Payload)); s_Payload.nParentProcessId = GetCurrentProcessId(); s_Payload.nTraceProcessId = GetCurrentProcessId(); s_Payload.nGeneology = 1; s_Payload.rGeneology[0] = 0; StringCchCopyW(s_Payload.wzStdin, ARRAYSIZE(s_Payload.wzStdin), L"\\\\.\\CONIN$"); StringCchCopyW(s_Payload.wzStdout, ARRAYSIZE(s_Payload.wzStdout), L"\\\\.\\CONOUT$"); StringCchCopyW(s_Payload.wzStderr, ARRAYSIZE(s_Payload.wzStderr), L"\\\\.\\CONOUT$"); StringCchCopyW(s_Payload.wzParents, ARRAYSIZE(s_Payload.wzParents), L""); CopyEnvironment(s_Payload.wzzDrop, wzzDrop); LPWCH pwStrings = GetEnvironmentStringsW(); CopyEnvironment(s_Payload.wzzEnvironment, pwStrings); FreeEnvironmentStringsW(pwStrings); if (!DetourCopyPayloadToProcess(pi.hProcess, s_guidTrace, &s_Payload, sizeof(s_Payload))) { printf("TRACEBLD: DetourCopyPayloadToProcess failed: %d\n", GetLastError()); ExitProcess(9008); } ResumeThread(pi.hThread); WaitForSingleObject(pi.hProcess, INFINITE); DWORD dwResult = 0; if (!GetExitCodeProcess(pi.hProcess, &dwResult)) { printf("TRACEBLD: GetExitCodeProcess failed: %d\n", GetLastError()); return 9008; } printf("TRACEBLD: %d processes.\n", s_nTotalClients); return dwResult; }
// Creates a pipe instance and initiate an accept request. // PCLIENT CreatePipeConnection(HANDLE hCompletionPort, LONG nClient) { HANDLE hPipe = CreateNamedPipeA(s_szPipe, // pipe name PIPE_ACCESS_INBOUND | // read-only access FILE_FLAG_OVERLAPPED, // overlapped mode PIPE_TYPE_MESSAGE | // message-type pipe PIPE_READMODE_MESSAGE | // message read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // unlimited instances 0, // output buffer size 0, // input buffer size 20000, // client time-out NULL); // no security attributes if (hPipe == INVALID_HANDLE_VALUE) { MyErrExit("CreateNamedPipe"); } // Allocate the client data structure. // PCLIENT pClient = (PCLIENT) GlobalAlloc(GPTR, sizeof(CLIENT)); if (pClient == NULL) { MyErrExit("GlobalAlloc pClient"); } CHAR szLogFile[MAX_PATH]; StringCchPrintfA(szLogFile, ARRAYSIZE(szLogFile), "%s.%08d.xml", s_szLogFile, nClient); ZeroMemory(pClient, sizeof(*pClient)); pClient->hPipe = hPipe; pClient->nClient = nClient; pClient->fAwaitingAccept = TRUE; pClient->hFile = CreateFileA(szLogFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (pClient->hFile == INVALID_HANDLE_VALUE) { fprintf(stderr, "TRACEBLD: Error opening output file: %s: %d\n\n", szLogFile, GetLastError()); fflush(stderr); MyErrExit("CreateFile"); } // Associate file with our complietion port. // if (!CreateIoCompletionPort(pClient->hPipe, hCompletionPort, (ULONG_PTR)pClient, 0)) { MyErrExit("CreateIoComplietionPort pClient"); } if (!ConnectNamedPipe(hPipe, pClient)) { DWORD error = GetLastError(); if (error == ERROR_IO_PENDING) { return NULL; } if (error == ERROR_PIPE_CONNECTED) { #if 0 pClient->LogMessageV("<!-- ConnectNamedPipe client already connected. -->"); #endif pClient->fAwaitingAccept = FALSE; } else if (error != ERROR_IO_PENDING && error != ERROR_PIPE_LISTENING) { MyErrExit("ConnectNamedPipe"); } } else { fprintf(stderr, "*** ConnectNamedPipe accepted immediately.\n"); #if 0 pClient->LogMessageV("<!-- ConnectNamedPipe accepted immediately. -->"); #endif pClient->fAwaitingAccept = FALSE; } return pClient; }