Beispiel #1
0
VOID InstanceThread (LPVOID lpvParam)
{
   CHAR chRequest[BUFSIZE];
   CHAR chReply[BUFSIZE];
   DWORD cbBytesRead, cbReplyBytes, cbWritten;
   BOOL fSuccess;
   HANDLE hPipe;

   hPipe = (HANDLE)lpvParam;
   while (1)
     {
	fSuccess = ReadFile(hPipe,
			    chRequest,
			    BUFSIZE,
			    &cbBytesRead,
			    NULL);
	if (!fSuccess || cbBytesRead == 0)
	  break;

	GetAnswerToRequest(chRequest, chReply, &cbReplyBytes);

	fSuccess = WriteFile(hPipe,
			     chReply,
			     cbReplyBytes,
			     &cbWritten,
			     NULL);
	if (!fSuccess || cbReplyBytes != cbWritten)
	  break;
    }

   FlushFileBuffers(hPipe);
   DisconnectNamedPipe(hPipe);
   CloseHandle(hPipe);
}
Beispiel #2
0
	void WINAPI CompletedReadRoutine(DWORD dwErr,DWORD cbBytesRead,LPOVERLAPPED lpOverLap){
		LPPIPEINST lpPipeInst;
		BOOL fWrite = FALSE;
		lpPipeInst = (LPPIPEINST) lpOverLap;
		if ((dwErr == 0) && (cbBytesRead != 0)){
			GetAnswerToRequest(lpPipeInst);
			fWrite = WriteFileEx(lpPipeInst->hPipeInst,lpPipeInst->chReply,
				lpPipeInst->cbToWrite,(LPOVERLAPPED) lpPipeInst,
				(LPOVERLAPPED_COMPLETION_ROUTINE) CompletedWriteRoutine);
		}
		if (!fWrite) DisconnectAndClose(lpPipeInst);
	}
Beispiel #3
0
DWORD ReadClient()
{
	while(!loopstop)
	{
		if(startread)
		{
			while(ReadFile(hPipe, chRequest, BUFSIZE, &cbBytesRead, NULL) >0)
			{
				GetAnswerToRequest(chRequest); 
				Sleep(20); 
			}				
			Sleep(100);
			SendToPipe(0, 0);
		}
		else
		{
			Sleep(500);
		}
	}
	return 0;
}
Beispiel #4
0
DWORD WINAPI InstanceThread(LPVOID lpvParam)
{
	ATLTRACE("InstanceThread started\n");
	TGITCacheResponse response;
	DWORD cbBytesRead, cbWritten;
	BOOL fSuccess;
	CAutoFile hPipe;

	// The thread's parameter is a handle to a pipe instance.

	hPipe = lpvParam;
	InterlockedIncrement(&nThreadCount);
	while (bRun)
	{
		// Read client requests from the pipe.
		TGITCacheRequest request;
		fSuccess = ReadFile(
			hPipe,        // handle to pipe
			&request,    // buffer to receive data
			sizeof(request), // size of buffer
			&cbBytesRead, // number of bytes read
			NULL);        // not overlapped I/O

		if (! fSuccess || cbBytesRead == 0)
		{
			DisconnectNamedPipe(hPipe);
			ATLTRACE("Instance thread exited\n");
			InterlockedDecrement(&nThreadCount);
			if (nThreadCount == 0)
				PostMessage(hWnd, WM_CLOSE, 0, 0);
			return 1;
		}

		DWORD responseLength;
		GetAnswerToRequest(&request, &response, &responseLength);

		// Write the reply to the pipe.
		fSuccess = WriteFile(
			hPipe,        // handle to pipe
			&response,      // buffer to write from
			responseLength, // number of bytes to write
			&cbWritten,   // number of bytes written
			NULL);        // not overlapped I/O

		if (! fSuccess || responseLength != cbWritten)
		{
			DisconnectNamedPipe(hPipe);
			ATLTRACE("Instance thread exited\n");
			InterlockedDecrement(&nThreadCount);
			if (nThreadCount == 0)
				PostMessage(hWnd, WM_CLOSE, 0, 0);
			return 1;
		}
	}

	// 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(hPipe);
	DisconnectNamedPipe(hPipe);
	ATLTRACE("Instance thread exited\n");
	InterlockedDecrement(&nThreadCount);
	if (nThreadCount == 0)
		PostMessage(hWnd, WM_CLOSE, 0, 0);
	return 0;
}
void* SocketHandler(void* lp){
    int *csock = (int*)lp;

   char pchRequest[BUFSIZ];
   char pchReply[BUFSIZ];
   DWORD cbBytesRead = 0, cbReplyBytes = 0;

	/*char buffer[1024];
	int buffer_len = 1024;*/
	//int bytecount;

	memset(pchRequest, 0, BUFSIZ);
	if((cbBytesRead = recv(*csock, pchRequest, BUFSIZ, 0)) == (DWORD)-1){
		fprintf(stderr, "Error receiving data %d\n", errno);
		close(*csock);
		free(csock);
	    return 0;
	}
	printf("Received bytes %d\nReceived string \"%s\"\n", cbBytesRead, pchRequest);
	//strcat(buffer, " SERVER ECHO");

	pchRequest[cbBytesRead] = '\0';

	// check for Exit-Message
	if(0 == strcmp(pchRequest, szExitMessage)) {
		printf("Received Exit-Message, pinging Server to stop it.\n");
		stop = true;
		close(*csock);
		free(csock);

        // create a socket connection so that the server comes out of the accept() call		
		pingServerSocket();
		
		return 0;
	}
	
   // Print verbose messages. In production code, this should be for debugging only.
   //printf("InstanceThread created, receiving and processing messages, GLE=%d\n", GetLastError());


	  /*for(DWORD i = 0;i < cbBytesRead+1;i++) {
		  printf("%i/%c ", pchRequest[i], pchRequest[i]);
	  } printf("\n");*/

	char tag[BUFSIZE];

	// look for the tag in the sent data
	char* pos = strchr(pchRequest, '|');

	// if we do not find the pipe, there is no tag information
	if(pos != NULL) {
		strncpy(tag, pchRequest, pos-pchRequest);
		tag[pos-pchRequest] = '\0';
		strcpy(pchRequest, pos+1);
		
		pchRequest[cbBytesRead - (pos-pchRequest+1)] = '\0';

		//printf("Having %d, cutting down to %d: %s\n", cbBytesRead, cbBytesRead - (pos-pchRequest+1), pchRequest);
	}

	//printf("After tagging: %s\n", pchRequest);

	// only set the tag if we have one
	if(pos != NULL && pos > pchRequest) {
		_tprintf(TEXT("Found tag: %s, GLE=%d.\n"), tag, GetLastError());

		DYNATRACE_SET_TAG_FROM_STRING(tag);	// retrieve and set tag
		DYNATRACE_START_SERVER_PUREPATH();				// start server-side PurePath
	} /* does not work... else {
		// start normal purepath if we
		DYNATRACE_START_PUREPATH();
	}*/

	ssize_t cbWritten = 0; 
	{ // create a block for auto-node-capture to work correctly here
	  DYNATRACE_AUTO_NODE_CAPTURE(DYNATRACE_CAPTURE << REPLACEMENT << cbBytesRead);

      // Process the incoming message.
      GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes);

	  _tprintf( TEXT("Handled data, returning: %s (%d), GLE=%d\n"), pchReply, cbReplyBytes, GetLastError());


		if((cbWritten = send(*csock, pchReply, cbReplyBytes, 0))== -1){
			fprintf(stderr, "Error sending data %d\n", errno);
			close(*csock);
			free(csock);
			return 0;
		}
	
	}

	if(pos != NULL && pos > pchRequest) {
		DYNATRACE_END_SERVER_PUREPATH();				// end server-side PurePath
	} /* does not work... based on scoping!! else {
		DYNATRACE_EXIT();
	}*/

      if (/*!fSuccess ||*/ cbReplyBytes != (DWORD)cbWritten)
      {
          _tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError());
		close(*csock);
		free(csock);
		return 0;
      }

	printf("Sent bytes %d\n", (int)cbWritten);

	close(*csock);
	free(csock);
	
	return 0;
}
Beispiel #6
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;
}
Beispiel #7
0
int _tmain(VOID) 
{ 
   DWORD i, dwWait, cbRet, dwErr; 
   BOOL fSuccess; 
   LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\mynamedpipe"); 
 
// The initial loop creates several instances of a named pipe 
// along with an event object for each instance.  An 
// overlapped ConnectNamedPipe operation is started for 
// each instance. 
 
   for (i = 0; i < INSTANCES; i++) 
   { 
 
   // Create an event object for this instance. 
 
      hEvents[i] = CreateEvent( 
         NULL,    // default security attribute 
         TRUE,    // manual-reset event 
         TRUE,    // initial state = signaled 
         NULL);   // unnamed event object 

      if (hEvents[i] == NULL) 
      {
         printf("CreateEvent failed with %d.\n", GetLastError()); 
         return 0;
      }
 
      Pipe[i].oOverlap.hEvent = hEvents[i]; 
 
      Pipe[i].hPipeInst = CreateNamedPipe( 
         lpszPipename,            // pipe name 
         PIPE_ACCESS_DUPLEX |     // read/write access 
         FILE_FLAG_OVERLAPPED,    // overlapped mode 
         PIPE_TYPE_MESSAGE |      // message-type pipe 
         PIPE_READMODE_MESSAGE |  // message-read mode 
         PIPE_WAIT,               // blocking mode 
         INSTANCES,               // number of instances 
         BUFSIZE*sizeof(TCHAR),   // output buffer size 
         BUFSIZE*sizeof(TCHAR),   // input buffer size 
         PIPE_TIMEOUT,            // client time-out 
         NULL);                   // default security attributes 

      if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) 
      {
         printf("CreateNamedPipe failed with %d.\n", GetLastError());
         return 0;
      }
 
   // Call the subroutine to connect to the new client
 
      Pipe[i].fPendingIO = ConnectToNewClient( 
         Pipe[i].hPipeInst, 
         &Pipe[i].oOverlap); 
 
      Pipe[i].dwState = Pipe[i].fPendingIO ? 
         CONNECTING_STATE : // still connecting 
         READING_STATE;     // ready to read 
   } 
 
   while (1) 
   { 
   // Wait for the event object to be signaled, indicating 
   // completion of an overlapped read, write, or 
   // connect operation. 
 
      dwWait = WaitForMultipleObjects( 
         INSTANCES,    // number of event objects 
         hEvents,      // array of event objects 
         FALSE,        // does not wait for all 
         INFINITE);    // waits indefinitely 
 
   // dwWait shows which pipe completed the operation. 
 
      i = dwWait - WAIT_OBJECT_0;  // determines which pipe 
      if (i < 0 || i > (INSTANCES - 1)) 
      {
         printf("Index out of range.\n"); 
         return 0;
      }
 
   // Get the result if the operation was pending. 
 
      if (Pipe[i].fPendingIO) 
      { 
         fSuccess = GetOverlappedResult( 
            Pipe[i].hPipeInst, // handle to pipe 
            &Pipe[i].oOverlap, // OVERLAPPED structure 
            &cbRet,            // bytes transferred 
            FALSE);            // do not wait 
 
         switch (Pipe[i].dwState) 
         { 
         // Pending connect operation 
            case CONNECTING_STATE: 
               if (! fSuccess) 
               {
                   printf("Error %d.\n", GetLastError()); 
                   return 0;
               }
               Pipe[i].dwState = READING_STATE; 
               break; 
 
         // Pending read operation 
            case READING_STATE: 
               if (! fSuccess || cbRet == 0) 
               { 
                  DisconnectAndReconnect(i); 
                  continue; 
               }
               Pipe[i].cbRead = cbRet;
               Pipe[i].dwState = WRITING_STATE; 
               break; 
 
         // Pending write operation 
            case WRITING_STATE: 
               if (! fSuccess || cbRet != Pipe[i].cbToWrite) 
               { 
                  DisconnectAndReconnect(i); 
                  continue; 
               } 
               Pipe[i].dwState = READING_STATE; 
               break; 
 
            default: 
            {
               printf("Invalid pipe state.\n"); 
               return 0;
            }
         }  
      } 
 
   // The pipe state determines which operation to do next. 
 
      switch (Pipe[i].dwState) 
      { 
      // READING_STATE: 
      // The pipe instance is connected to the client 
      // and is ready to read a request from the client. 
 
         case READING_STATE: 
            fSuccess = ReadFile( 
               Pipe[i].hPipeInst, 
               Pipe[i].chRequest, 
               BUFSIZE*sizeof(TCHAR), 
               &Pipe[i].cbRead, 
               &Pipe[i].oOverlap); 
 
         // The read operation completed successfully. 
 
            if (fSuccess && Pipe[i].cbRead != 0) 
            { 
               Pipe[i].fPendingIO = FALSE; 
               Pipe[i].dwState = WRITING_STATE; 
               continue; 
            } 
 
         // The read operation is still pending. 
 
            dwErr = GetLastError(); 
            if (! fSuccess && (dwErr == ERROR_IO_PENDING)) 
            { 
               Pipe[i].fPendingIO = TRUE; 
               continue; 
            } 
 
         // An error occurred; disconnect from the client. 
 
            DisconnectAndReconnect(i); 
            break; 
 
      // WRITING_STATE: 
      // The request was successfully read from the client. 
      // Get the reply data and write it to the client. 
 
         case WRITING_STATE: 
            GetAnswerToRequest(&Pipe[i]); 
 
            fSuccess = WriteFile( 
               Pipe[i].hPipeInst, 
               Pipe[i].chReply, 
               Pipe[i].cbToWrite, 
               &cbRet, 
               &Pipe[i].oOverlap); 
 
         // The write operation completed successfully. 
 
            if (fSuccess && cbRet == Pipe[i].cbToWrite) 
            { 
               Pipe[i].fPendingIO = FALSE; 
               Pipe[i].dwState = READING_STATE; 
               continue; 
            } 
 
         // The write operation is still pending. 
 
            dwErr = GetLastError(); 
            if (! fSuccess && (dwErr == ERROR_IO_PENDING)) 
            { 
               Pipe[i].fPendingIO = TRUE; 
               continue; 
            } 
 
         // An error occurred; disconnect from the client. 
 
            DisconnectAndReconnect(i); 
            break; 
 
         default: 
         {
            printf("Invalid pipe state.\n"); 
            return 0;
         }
      } 
  } 
 
  return 0; 
} 
Beispiel #8
0
DWORD WINAPI InstanceThread(LPVOID lpvParam)
// This routine is a thread processing function to read from and reply to a client
// via the open pipe connection passed from the main loop. Note this allows
// the main loop to continue executing, potentially creating more threads of
// of this procedure to run concurrently, depending on the number of incoming
// client connections.
{ 
	HANDLE hHeap      = GetProcessHeap();
	char* pchRequest = (char*) HeapAlloc(hHeap, 0, BUFSIZE * sizeof(char));
	char* pchReply   = (char*) HeapAlloc(hHeap, 0, BUFSIZE * sizeof(char));

	DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0; 
	BOOL fSuccess = FALSE;
	HANDLE hPipe  = NULL;

	// Do some extra error checking since the app will keep running even if this
	// thread fails.

	if (lpvParam == NULL)
	{
		printf( "\nERROR - Pipe Server Failure:\n");
		printf( "   InstanceThread got an unexpected NULL value in lpvParam.\n");
		printf( "   InstanceThread exitting.\n");
		if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
		if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
		return (DWORD)-1;
	}

	if (pchRequest == NULL)
	{
		printf( "\nERROR - Pipe Server Failure:\n");
		printf( "   InstanceThread got an unexpected NULL heap allocation.\n");
		printf( "   InstanceThread exitting.\n");
		if (pchReply != NULL) HeapFree(hHeap, 0, pchReply);
		return (DWORD)-1;
	}

	if (pchReply == NULL)
	{
		printf( "\nERROR - Pipe Server Failure:\n");
		printf( "   InstanceThread got an unexpected NULL heap allocation.\n");
		printf( "   InstanceThread exitting.\n");
		if (pchRequest != NULL) HeapFree(hHeap, 0, pchRequest);
		return (DWORD)-1;
	}

	// Print verbose messages. In production code, this should be for debugging only.
	printf("InstanceThread created, receiving and processing messages.\n");

	// The thread's parameter is a handle to a pipe object instance. 

	hPipe = (HANDLE) lpvParam; 

	// Loop until done reading
	while (1) 
	{ 
		// Read client requests from the pipe. This simplistic code only allows messages
		// up to BUFSIZE characters in length.
		fSuccess = ReadFile( 
			hPipe,        // handle to pipe 
			pchRequest,    // buffer to receive data 
			BUFSIZE*sizeof(TCHAR), // size of buffer 
			&cbBytesRead, // number of bytes read 
			NULL);        // not overlapped I/O 

		if (!fSuccess || cbBytesRead == 0)
		{   
			if (GetLastError() == ERROR_BROKEN_PIPE)
			{
				_tprintf(TEXT("InstanceThread: client disconnected.\n"), GetLastError()); 
			}
			else
			{
				_tprintf(TEXT("InstanceThread ReadFile failed, GLE=%d.\n"), GetLastError()); 
			}
			break;
		}

		// Process the incoming message.
		GetAnswerToRequest(pchRequest, pchReply, &cbReplyBytes); 

		// Write the reply to the pipe. 
		fSuccess = WriteFile( 
			hPipe,        // handle to pipe 
			pchReply,     // buffer to write from 
			cbReplyBytes, // number of bytes to write 
			&cbWritten,   // number of bytes written 
			NULL);        // not overlapped I/O 

		if (!fSuccess || cbReplyBytes != cbWritten)
		{   
			_tprintf(TEXT("InstanceThread WriteFile failed, GLE=%d.\n"), GetLastError()); 
			break;
		}
	}

	// 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(hPipe); 
	DisconnectNamedPipe(hPipe); 
	CloseHandle(hPipe); 

	HeapFree(hHeap, 0, pchRequest);
	HeapFree(hHeap, 0, pchReply);

	printf("InstanceThread exitting.\n");
	terminateSelf();
	return 1;
}
Beispiel #9
0
unsigned int __stdcall InstanceThread(LPVOID lpvParam)
{
    CCrashReportThread crashthread;
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": InstanceThread started\n");
    TSVNCacheResponse response;
    DWORD cbBytesRead, cbWritten;
    CAutoFile hPipe;

    // The thread's parameter is a handle to a pipe instance.

    hPipe = std::move((HANDLE) lpvParam);

    while (bRun)
    {
        // Read client requests from the pipe.
        TSVNCacheRequest request;
        BOOL fSuccess = ReadFile(
            hPipe,        // handle to pipe
            &request,    // buffer to receive data
            sizeof(request), // size of buffer
            &cbBytesRead, // number of bytes read
            NULL);        // not overlapped I/O

        if (! fSuccess || cbBytesRead == 0)
        {
            DisconnectNamedPipe(hPipe);
            CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Instance thread exited\n");
            return 1;
        }

        // sanitize request:
        // * Make sure the string properly 0-terminated
        //   by resetting overlong paths to the empty string
        // * Set all trailing chars to 0.
        // * Clear unknown flags
        // This is more or less paranoia code but maybe something
        // is feeding garbage into our queue.
        for (size_t i = MAX_PATH+1; (i > 0) && (request.path[i-1] != 0); --i)
            request.path[i-1] = 0;

        size_t pathLength = wcslen (request.path);
        SecureZeroMemory ( request.path + pathLength
                         , sizeof (request.path) - pathLength * sizeof (TCHAR));

        request.flags &= TSVNCACHE_FLAGS_MASK;

        // process request
        DWORD responseLength;
        GetAnswerToRequest(&request, &response, &responseLength);

        // Write the reply to the pipe.
        fSuccess = WriteFile(
            hPipe,        // handle to pipe
            &response,      // buffer to write from
            responseLength, // number of bytes to write
            &cbWritten,   // number of bytes written
            NULL);        // not overlapped I/O

        if (! fSuccess || responseLength != cbWritten)
        {
            DisconnectNamedPipe(hPipe);
            CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Instance thread exited\n");
            return 1;
        }
    }

    // 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(hPipe);
    DisconnectNamedPipe(hPipe);
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": Instance thread exited\n");
    return 0;
}
int PipeManager(LPTSTR lpszPipename, void __cdecl GetAnswerToRequest(LPPIPEINST pipe))
{
    DWORD i, dwWait, cbRet, dwErr; 
    BOOL fSuccess; 

    char pTemp[121];

    // The initial loop creates several instances of a named pipe 
    // along with an event object for each instance.  An 
    // overlapped ConnectNamedPipe operation is started for 
    // each instance. 
    for (i = 0; i < INSTANCES; i++) 
    { 

        // create named pipe
        Pipe[i].sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
        if (!InitializeSecurityDescriptor(Pipe[i].sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
        {
            sprintf_s(pTemp, 120, "PipeManager: InitializeSecurityDescriptor failed, error code = %d", GetLastError());
            WriteLog(pTemp);
            return 0;
        }
        if (!SetSecurityDescriptorDacl(Pipe[i].sa.lpSecurityDescriptor, TRUE, (PACL)0, FALSE))
        {
            sprintf_s(pTemp, 120, "PipeManager: SetSecurityDescriptorDacl failed, error code = %d", GetLastError());
            WriteLog(pTemp);
            return 0;
        }
        Pipe[i].sa.nLength = sizeof Pipe[i].sa;
        Pipe[i].sa.bInheritHandle = TRUE;

        // Create an event object for this instance. 
        hEvents[i] = CreateEvent( 
                NULL,    // default security attribute 
                TRUE,    // manual-reset event 
                TRUE,    // initial state = signaled 
                NULL);   // unnamed event object 

        if (hEvents[i] == NULL) 
        {
            sprintf_s(pTemp, 120, "PipeManager: CreateEvent failed with %d.\n", GetLastError()); 
            WriteLog(pTemp);
            return 0;
        }

        Pipe[i].oOverlap.hEvent = hEvents[i]; 

        Pipe[i].hPipeInst = CreateNamedPipe( 
                lpszPipename,            // pipe name 
                PIPE_ACCESS_DUPLEX |     // read/write access 
                FILE_FLAG_OVERLAPPED,    // overlapped mode 
                PIPE_TYPE_MESSAGE |      // message-type pipe 
                PIPE_READMODE_MESSAGE |  // message-read mode 
                PIPE_WAIT,               // blocking mode 
                INSTANCES,               // number of instances 
                BUFSIZE*sizeof(TCHAR),   // output buffer size 
                BUFSIZE*sizeof(TCHAR),   // input buffer size 
                PIPE_TIMEOUT,            // client time-out 
                &Pipe[i].sa);             // the security attributes 

        if (Pipe[i].hPipeInst == INVALID_HANDLE_VALUE) 
        {
            sprintf_s(pTemp, 120, "PipeManager: CreateNamedPipe failed with %d.\n", GetLastError());
            WriteLog(pTemp);
            return 0;
        }

        // Call the subroutine to connect to the new client
        Pipe[i].fPendingIO = ConnectToNewClient( 
                Pipe[i].hPipeInst, 
                &Pipe[i].oOverlap); 

        Pipe[i].dwState = Pipe[i].fPendingIO ? 
            CONNECTING_STATE : // still connecting 
            READING_STATE;     // ready to read 
    } 

    // Create an event object used to signal that PipeManager shuld exit. 
    hEvents[INSTANCES] = CreateEvent( 
            NULL,    // default security attribute 
            TRUE,    // manual-reset event 
            FALSE,    // initial state = not signaled 
            NULL);   // unnamed event object 

    if (hEvents[INSTANCES] == NULL) 
    {
        sprintf_s(pTemp, 120, "PipeManager: CreateEvent failed with %d.\n", GetLastError()); 
        WriteLog(pTemp);
        return 0;
    }

    while (true) 
    { 
        // Wait for the event object to be signaled, indicating 
        // completion of an overlapped read, write, or 
        // connect operation. 
        dwWait = WaitForMultipleObjects( 
                (INSTANCES +1),    // number of event objects 
                hEvents,      // array of event objects 
                FALSE,        // does not wait for all 
                INFINITE);    // waits indefinitely 


        // dwWait shows which pipe completed the operation. 
        i = dwWait - WAIT_OBJECT_0;  // determines which pipe 

        // If this was the exit PipeManager event, we exits the loop.
        if (i == INSTANCES) {
            break;
        }

        // Chack the range
        if (i < 0 || i > (INSTANCES - 1)) 
        {
            sprintf_s(pTemp, 120, "PipeManager: Index (%d) out of range. 0..%d\n", i, INSTANCES); 
            WriteLog(pTemp);
            return 0;
        }

        // Get the result if the operation was pending. 
        if (Pipe[i].fPendingIO) 
        { 
            fSuccess = GetOverlappedResult( 
                    Pipe[i].hPipeInst, // handle to pipe 
                    &Pipe[i].oOverlap, // OVERLAPPED structure 
                    &cbRet,            // bytes transferred 
                    FALSE);            // do not wait 

            switch (Pipe[i].dwState) 
            { 
                // Pending connect operation 
                case CONNECTING_STATE: 
                    if (! fSuccess) 
                    {
                        sprintf_s(pTemp, 120, "PipeManager, Pipe error %d.\n", GetLastError()); 
                        WriteLog(pTemp);
                        return 0;
                    }
                    Pipe[i].dwState = READING_STATE; 
                    break; 

                    // Pending read operation 
                case READING_STATE: 
                    if (! fSuccess || cbRet == 0) 
                    { 
                        DisconnectAndReconnect(i); 
                        continue; 
                    }
                    Pipe[i].cbRead = cbRet;
                    Pipe[i].dwState = WRITING_STATE; 
                    break; 

                    // Pending write operation 
                case WRITING_STATE: 
                    if (! fSuccess || cbRet != Pipe[i].cbToWrite) 
                    { 
                        DisconnectAndReconnect(i); 
                        continue; 
                    } 
                    Pipe[i].dwState = READING_STATE; 
                    break; 

                default: 
                    {
                        sprintf_s(pTemp, 120, "PipeManager: Invalid pipe state.\n"); 
                        WriteLog(pTemp);
                        return 0;
                    }
            }  
        } 

        // The pipe state determines which operation to do next. 
        switch (Pipe[i].dwState) 
        { 
            // READING_STATE: 
            // The pipe instance is connected to the client 
            // and is ready to read a request from the client. 
            case READING_STATE: 
                fSuccess = ReadFile( 
                        Pipe[i].hPipeInst, 
                        Pipe[i].chRequest, 
                        BUFSIZE*sizeof(TCHAR), 
                        &Pipe[i].cbRead, 
                        &Pipe[i].oOverlap); 

                // The read operation completed successfully.  
                if (fSuccess && Pipe[i].cbRead != 0) 
                { 
                    Pipe[i].fPendingIO = FALSE; 
                    Pipe[i].dwState = WRITING_STATE; 
                    continue; 
                } 

                // The read operation is still pending. 
                dwErr = GetLastError(); 
                if (! fSuccess && (dwErr == ERROR_IO_PENDING)) 
                { 
                    Pipe[i].fPendingIO = TRUE; 
                    continue; 
                } 

                // An error occurred; disconnect from the client. 
                DisconnectAndReconnect(i); 
                break; 

                // WRITING_STATE: 
                // The request was successfully read from the client. 
                // Get the reply data and write it to the client. 
            case WRITING_STATE: 
                GetAnswerToRequest(&Pipe[i]); 

                //make it a valid string.
                ++Pipe[i].cbToWrite;
                Pipe[i].chReply[Pipe[i].cbToWrite] = '\0';

                fSuccess = WriteFile( 
                        Pipe[i].hPipeInst, 
                        Pipe[i].chReply, 
                        Pipe[i].cbToWrite, 
                        &cbRet, 
                        &Pipe[i].oOverlap); 

                // The write operation completed successfully. 
                if (fSuccess && cbRet == Pipe[i].cbToWrite) 
                { 
                    Pipe[i].fPendingIO = FALSE; 
                    Pipe[i].dwState = READING_STATE; 
                    Pipe[i].cbToWrite = 0; //All data is writen
                    continue; 
                } 

                // The write operation is still pending. 
                dwErr = GetLastError(); 
                if (! fSuccess && (dwErr == ERROR_IO_PENDING)) 
                { 
                    Pipe[i].fPendingIO = TRUE; 
                    continue; 
                } 
                else 
                {
                    sprintf_s(pTemp, 120, "PipeManager: WRITING_STATE error 0x%x.\n", dwErr);
                    WriteLog(pTemp);
                }

                // An error occurred; disconnect from the client. 
                DisconnectAndReconnect(i); 
                break; 

            default: 
                {
                    sprintf_s(pTemp, 120, "PipeManager: Invalid pipe state.\n"); 
                    WriteLog(pTemp);
                    return 0;
                }
        } 
    } 

    return 0;


}