Example #1
0
static void handle_socket(struct clientsocket * C) {
  static char buffer[BUFFER_SIZE];
  //since these are local sockets, we can safely assume we get whole messages at a time
  int r = socketRead(&C->sock, buffer, BUFFER_SIZE);
  if (r > 0) {
    switch (buffer[0]) {
      case 'S'://status
        if (bb_status.errors[0] != 0) {
          r = snprintf(buffer, BUFFER_SIZE, "Error (%s): %s\n", GITVERSION, bb_status.errors);
        } else {
          if (bb_is_running(bb_status.x_pid)) {
            r = snprintf(buffer, BUFFER_SIZE, "Ready (%s). X is PID %i, %i applications using bumblebeed.\n", GITVERSION, bb_status.x_pid, bb_status.appcount);
          } else {
            r = snprintf(buffer, BUFFER_SIZE, "Ready (%s). X inactive.\n", GITVERSION);
          }
        }
        socketWrite(&C->sock, buffer, r); //we assume the write is fully successful.
        break;
      case 'F'://force VirtualGL if possible
      case 'C'://check if VirtualGL is allowed
        /// \todo Handle power management cases and powering card on/off.
        //no X? attempt to start it
        if (!bb_is_running(bb_status.x_pid)) {
          start_secondary();
        }
        if (bb_is_running(bb_status.x_pid)) {
          r = snprintf(buffer, BUFFER_SIZE, "Yes. X is active.\n");
          if (C->inuse == 0) {
            C->inuse = 1;
            bb_status.appcount++;
          }
        } else {
          if (bb_status.errors[0] != 0) {
            r = snprintf(buffer, BUFFER_SIZE, "No - error: %s\n", bb_status.errors);
          } else {
            r = snprintf(buffer, BUFFER_SIZE, "No, secondary X is not active.\n");
          }
        }
        socketWrite(&C->sock, buffer, r); //we assume the write is fully successful.
        break;
      case 'D'://done, close the socket.
        socketClose(&C->sock);
        break;
      default:
        bb_log(LOG_WARNING, "Unhandled message received: %*s\n", r, buffer);
        break;
    }
  }
}
Example #2
0
int	socketWriteString(int sid, char_t *buf)
{
 #ifdef UNICODE
 	char	*byteBuf;
 	int		r, len;
 
 	len = gstrlen(buf);
 	byteBuf = ballocUniToAsc(buf, len);
 	r = socketWrite(sid, byteBuf, len);
 	bfreeSafe(B_L, byteBuf);
 	return r;
 #else
 	return socketWrite(sid, buf, strlen(buf));
 #endif /* UNICODE */
}
Example #3
0
	size_t TcpSession::send(byte *buf, size_t size)
	{
		size = sendBuf_.write(buf, size);
		socketWrite();

		return size;
	}
int Q3Process::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
    _id = QObject::qt_metacall(_c, _id, _a);
    if (_id < 0)
        return _id;
    if (_c == QMetaObject::InvokeMetaMethod) {
        switch (_id) {
        case 0: readyReadStdout(); break;
        case 1: readyReadStderr(); break;
        case 2: processExited(); break;
        case 3: wroteToStdin(); break;
        case 4: launchFinished(); break;
        case 5: tryTerminate(); break;
        case 6: kill(); break;
        case 7: writeToStdin((*reinterpret_cast< const QByteArray(*)>(_a[1]))); break;
        case 8: writeToStdin((*reinterpret_cast< const QString(*)>(_a[1]))); break;
        case 9: closeStdin(); break;
        case 10: socketRead((*reinterpret_cast< int(*)>(_a[1]))); break;
        case 11: socketWrite((*reinterpret_cast< int(*)>(_a[1]))); break;
        case 12: timeout(); break;
        case 13: closeStdinLaunch(); break;
        }
        _id -= 14;
    }
    return _id;
}
Example #5
0
static void *reader(void *)
{
	printf("reader running\n");

	char line[256];
	while(!done)
	{
		if(!fgets(line, sizeof(line) - 2, stdin))
			break;

		line[strlen(line) - 1] = 0;
		strcat(line, "\r\n");
		int l = strlen(line);
//printf("Writing to socket %d:\n", sock);
//HexDump::dump(stdout, 0, (const unsigned char *)line, l);
		int r = socketWrite(sock, line, l);
		if(r != l)
		{
			printf("l == %d, r == %d socket write error\n", l, r);
			break;
		}
	}

	printf("reader exiting\n");
	
	done = 1;

	return 0;
}
Example #6
0
/*
    Non-blocking write data. Return the number of bytes written or -1 on errors.
    Returns zero if part of the data was written.

    Encode caller's data buffer into an SSL record and write to socket. The encoded data will always be 
    bigger than the incoming data because of the record header (5 bytes) and MAC (16 bytes MD5 / 20 bytes SHA1)
    This would be fine if we were using blocking sockets, but non-blocking presents an interesting problem.  Example:

        A 100 byte input record is encoded to a 125 byte SSL record
        We can send 124 bytes without blocking, leaving one buffered byte
        We can't return 124 to the caller because it's more than they requested
        We can't return 100 to the caller because they would assume all data
        has been written, and we wouldn't get re-called to send the last byte

    We handle the above case by returning 0 to the caller if the entire encoded record could not be sent. Returning 
    0 will prompt us to select this socket for write events, and we'll be called again when the socket is writable.  
    We'll use this mechanism to flush the remaining encoded data, ignoring the bytes sent in, as they have already 
    been encoded.  When it is completely flushed, we return the originally requested length, and resume normal 
    processing.
 */
PUBLIC ssize sslWrite(Webs *wp, void *buf, ssize len)
{
    Ms      *ms;
    uchar   *obuf;
    ssize   encoded, nbytes, written;

    ms = (Ms*) wp->ssl;
    while (len > 0 || ms->outlen > 0) {
        if ((encoded = matrixSslGetOutdata(ms->handle, &obuf)) <= 0) {
            if (ms->outlen <= 0) {
                ms->outbuf = (char*) buf;
                ms->outlen = len;
                ms->written = 0;
                len = 0;
            }
            nbytes = min(ms->outlen, SSL_MAX_PLAINTEXT_LEN);
            if ((encoded = matrixSslEncodeToOutdata(ms->handle, (uchar*) buf, (int) nbytes)) < 0) {
                return encoded;
            }
            ms->outbuf += nbytes;
            ms->outlen -= nbytes;
            ms->written += nbytes;
        }
        if ((written = socketWrite(wp->sid, obuf, encoded)) < 0) {
            return written;
        } else if (written == 0) {
            break;
        }
        matrixSslSentData(ms->handle, (int) written);
    }
    /*
        Only signify all the data has been written if MatrixSSL has absorbed all the data
     */
    return ms->outlen == 0 ? ms->written : 0;
}
Example #7
0
/**
 * Requests a key over the socket
 * @param key The key to be retrieved
 * @param target A pointer to a char to store the value in
 * @param max_len The maximum number of bytes to be written in target, must be
 * greater than 0
 * @return 0 on success, non-zero on failure
 */
int bbsocket_query(const char *key, char *target, size_t max_len) {
  char buff[BUFFER_SIZE];
  snprintf(buff, sizeof buff, "Query %s", key);
  if (!socketWrite(&bb_status.bb_socket, buff, strlen(buff) + 1)) {
    bb_log(LOG_DEBUG, "Write failed for query of %s\n", key);
    return 1;
  }
  while (bb_status.bb_socket != -1) {
    if (socketRead(&bb_status.bb_socket, buff, sizeof (buff))) {
      if (strncmp("Value: ", buff, strlen("Value: "))) {
        bb_log(LOG_DEBUG, "Failed to query for %s: %s\n", key, buff);
        return 1;
      }
      strncpy(target, buff + strlen("Value: "), max_len);
      target[max_len - 1] = 0;
      /* remove trailing newline */
      if (strlen(target)) {
        target[strlen(target) - 1] = 0;
      }
      return 0;
    }
  }
  bb_log(LOG_DEBUG, "Read failed for query of %s\n", key);
  return 1;
}
Example #8
0
QWebProcessor::QWebProcessor(QObject *parent, QWebGlobalData* global) :
    QObject(parent), socket(0)
{
    parser = new QHttpRequestParser();
    rp = new QWebResourseProvider(this, global);
    connect(parser, SIGNAL(headerRecieved()), this, SLOT(onParserHeaderRecieved()));
    connect(parser, SIGNAL(bodyDataBlockRecieved(QByteArray)), rp, SLOT(dataBlockRecieved(QByteArray)));
    connect(parser, SIGNAL(beforeSendHeaders()), rp, SLOT(beforeSendHeaders()));
    connect(parser, SIGNAL(bodyRecieved()), rp, SLOT(bodyRecieved()));
    connect(parser, SIGNAL(sendData(QByteArray)), this, SLOT(socketWrite(QByteArray)));
    connect(parser, SIGNAL(finished()), this, SLOT(onParserFinished()));
}
Example #9
0
/**
 * Prints the status of the Bumblebee server if available
 * @return EXIT_SUCCESS if the status is succesfully retrieved,
 * EXIT_FAILURE otherwise
 */
static int report_daemon_status(void) {
  char buffer[BUFFER_SIZE];
  int r = snprintf(buffer, BUFFER_SIZE, "Status?");
  socketWrite(&bb_status.bb_socket, buffer, r + 1);
  while (bb_status.bb_socket != -1) {
    r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE);
    if (r > 0) {
      printf("Bumblebee status: %*s\n", r, buffer);
      socketClose(&bb_status.bb_socket);
      return EXIT_SUCCESS;
    }
  }
  return EXIT_FAILURE;
}
Example #10
0
void Connection::doWrite() {
  while (true) {
    // Note that size here is the contiguous part of it It may very
    // well be more data on the buffer that is not contiguous and thus
    // would not appear in here.
    m_write_.lock();
    int size = out_.readSize();
    const char* data = out_.readPtr();
    m_write_.unlock();

    int bytes_written = socketWrite(client_fd_, data, size);

    {
      ScopedLock l(&m_write_);

      if ((bytes_written < 0) && (errno == EAGAIN)) {
        acquire();
        io_desc_->writeWhenReady();
        break;

      } else if (bytes_written < 0) {
        // LOG(LogMessage::ERROR) << "Error on write " << strerror(errno);
        std::cout << "Error on write " << strerror(errno) << std::endl;
        break;

      } else if (bytes_written == 0) {
        // LOG(Logmessage::NORMAL) << "Closing on write " << client_fd_;
        std::cout << "Closing on write " << client_fd_ << std::endl;
        break;

      }

      out_.consume(bytes_written);
      if ((size == bytes_written) && (out_.readSize() == 0)) {
        writing_ = false;
        break;
      }

      // Continue writing remaining data.

    }
  }

  // This release matched the acquire that scheduled the doWrite()
  release();
}
Example #11
0
bool QProcess::qt_invoke( int _id, QUObject* _o )
{
    switch ( _id - staticMetaObject()->slotOffset() ) {
    case 0: tryTerminate(); break;
    case 1: kill(); break;
    case 2: writeToStdin((const QByteArray&)*((const QByteArray*)static_QUType_ptr.get(_o+1))); break;
    case 3: writeToStdin((const QString&)static_QUType_QString.get(_o+1)); break;
    case 4: closeStdin(); break;
    case 5: socketRead((int)static_QUType_int.get(_o+1)); break;
    case 6: socketWrite((int)static_QUType_int.get(_o+1)); break;
    case 7: timeout(); break;
    case 8: closeStdinLaunch(); break;
    default:
	return QObject::qt_invoke( _id, _o );
    }
    return TRUE;
}
Example #12
0
static ssize blockingWrite(Webs *wp, void *buf, ssize len)
{
    ssize   written, bytes;
    int     prior;

    prior = socketSetBlock(wp->sid, 1);
    for (written = 0; len > 0; ) {
        if ((bytes = socketWrite(wp->sid, buf, len)) < 0) {
            socketSetBlock(wp->sid, prior);
            return bytes;
        }
        buf += bytes;
        len -= bytes;
        written += bytes;
    }
    socketSetBlock(wp->sid, prior);
    return written;
}
Example #13
0
/*
  Use a timer for polling misc. stuff.
*/
void Q3Process::timeout()
{
    // Disable the timer temporary since one of the slots that are connected to
    // the readyRead...(), etc. signals might trigger recursion if
    // processEvents() is called.
    d->lookup->stop();

    // try to write pending data to stdin
    if ( !d->stdinBuf.isEmpty() )
	socketWrite( 0 );

    if ( ioRedirection ) {
	socketRead( 1 ); // try stdout
	socketRead( 2 ); // try stderr
    }

    if ( isRunning() ) {
	// enable timer again, if needed
	if ( !d->stdinBuf.isEmpty() || ioRedirection || notifyOnExit )
	    d->lookup->start( 100 );
    } else if ( notifyOnExit ) {
	emit processExited();
    }
}
Example #14
0
/*
	Writes a null terminated string to a socket, not including the
	terminating null.
	Returns the number of bytes written or -1 if
	an error occured.
	*/
int socketWrite(SOCKET sock, const char *str)
{
	int r = socketWrite(sock, str, (int)strlen(str));
	return r;
}
Example #15
0
int main(int argc, char* argv[]) {

  /* Setup signal handling before anything else */
  signal(SIGHUP, handle_signal);
  signal(SIGTERM, handle_signal);
  signal(SIGINT, handle_signal);
  signal(SIGQUIT, handle_signal);

  /* Initializing configuration */
  init_config(argc, argv);
  
  /* set runmode depending on leftover arguments */
  if (optind >= argc) {
    bb_status.runmode = BB_RUN_STATUS;
  } else {
    bb_status.runmode = BB_RUN_APP;
  }

  bb_init_log();
  bb_log(LOG_DEBUG, "%s version %s starting...\n", bb_status.program_name, GITVERSION);

  /* Connect to listening daemon */
  bb_status.bb_socket = socketConnect(bb_config.socket_path, SOCK_NOBLOCK);
  if (bb_status.bb_socket < 0) {
    bb_log(LOG_ERR, "Could not connect to bumblebee daemon - is it running?\n");
    bb_closelog();
    return EXIT_FAILURE;
  }
  char buffer[BUFFER_SIZE];
  int r;

  /* Request status */
  if (bb_status.runmode == BB_RUN_STATUS) {
    r = snprintf(buffer, BUFFER_SIZE, "Status?");
    socketWrite(&bb_status.bb_socket, buffer, r);
    while (bb_status.bb_socket != -1) {
      r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE);
      if (r > 0) {
        printf("Bumblebee status: %*s\n", r, buffer);
        socketClose(&bb_status.bb_socket);
      }
    }
  }

  /* Run given application */
  if (bb_status.runmode == BB_RUN_APP) {
    int ranapp = 0;
    r = snprintf(buffer, BUFFER_SIZE, "Checking availability...");
    socketWrite(&bb_status.bb_socket, buffer, r);
    while (bb_status.bb_socket != -1) {
      r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE);
      if (r > 0) {
        bb_log(LOG_INFO, "Response: %*s\n", r, buffer);
        switch (buffer[0]) {
          case 'N': //No, run normally.
            socketClose(&bb_status.bb_socket);
            if (!bb_config.fallback_start){
              bb_log(LOG_ERR, "Cannot access secondary GPU. Aborting.\n");
            }
            break;
          case 'Y': //Yes, run through vglrun
            bb_log(LOG_INFO, "Running application through vglrun.\n");
            ranapp = 1;
            //run vglclient if any method other than proxy is used
            if (strncmp(bb_config.vgl_compress, "proxy", BUFFER_SIZE) != 0) {
              char * vglclient_args[] = {
                "vglclient",
                "-detach",
                0
              };
              bb_run_fork(vglclient_args);
            }
            char ** vglrun_args = malloc(sizeof (char *) * (9 + argc - optind));
            vglrun_args[0] = "vglrun";
            vglrun_args[1] = "-c";
            vglrun_args[2] = bb_config.vgl_compress;
            vglrun_args[3] = "-d";
            vglrun_args[4] = bb_config.x_display;
            vglrun_args[5] = "-ld";
            vglrun_args[6] = bb_config.ld_path;
            vglrun_args[7] = "--";
            for (r = 0; r < argc - optind; r++) {
              vglrun_args[8 + r] = argv[optind + r];
            }
            vglrun_args[8 + r] = 0;
            bb_run_fork_wait(vglrun_args);
            socketClose(&bb_status.bb_socket);
            break;
          default: //Something went wrong - output and exit.
            bb_log(LOG_ERR, "Problem: %*s\n", r, buffer);
            socketClose(&bb_status.bb_socket);
            break;
        }
      }
    }
    if (!ranapp && bb_config.fallback_start) {
      bb_log(LOG_WARNING, "Running application normally.\n");
      bb_run_exec(argv + optind);
    }
  }

  bb_closelog();
  bb_stop_all(); //stop any started processes that are left
  return (EXIT_SUCCESS);
}
Example #16
0
int sendRequest(ParseClientInternal *parseClient, const char *host, const char *httpVerb, const char *httpRequestBody, int addInstallationHeader) {
    short socketHandle = -1;
    short status = socketSslConnect(parseServer, sshPort);

    if (status >= 0) {
        socketHandle = status;

#ifdef REQUEST_DEBUG
        DEBUG_PRINT("\r\n");

        DEBUG_PRINT("[Parse] ---------\r\n");
        DEBUG_PRINT("[Parse] Request :\r\n");
        DEBUG_PRINT("[Parse] --------- Start -\r\n");
#endif /* REQUEST_DEBUG */

        status = buildRequestHeaders(parseClient, host, httpVerb, httpRequestBody, addInstallationHeader);

#ifdef REQUEST_DEBUG
        if (status >= 0) {
            DEBUG_PRINT("%s\r\n", dataBuffer);
        } else {
            DEBUG_PRINT("[Parse] Build request error: %d\r\n", status);
        }

        DEBUG_PRINT("[Parse] ---------  End  -\r\n");
        DEBUG_PRINT("\r\n");
#endif /* REQUEST_DEBUG */
    }

    if (status >= 0) {
        status = socketWrite(socketHandle, dataBuffer, status);
    }

    if (status >= 0) {
#ifdef REQUEST_DEBUG
        DEBUG_PRINT("[Parse] ---------\r\n");
        DEBUG_PRINT("[Parse] Response:\r\n");
        DEBUG_PRINT("[Parse] --------- Start -\r\n");
#endif /* REQUEST_DEBUG */

        memset(dataBuffer, 0, sizeof(dataBuffer));
        status = socketRead(socketHandle, dataBuffer, sizeof(dataBuffer), 5000);

#ifdef REQUEST_DEBUG
        if (status >= 0) {
            DEBUG_PRINT("%s\r\n", dataBuffer);
        } else {
            DEBUG_PRINT("[Parse] Response read error: %d\r\n", status);
        }

        DEBUG_PRINT("[Parse] ---------  End  -\r\n");
        DEBUG_PRINT("\r\n");
#endif /* REQUEST_DEBUG */

        socketClose(socketHandle);
#ifdef REQUEST_DEBUG
    } else {
        DEBUG_PRINT("[Parse] Request write error: %d\r\n", status);
#endif /* REQUEST_DEBUG */
    }

    return status;
}
/*
    Helper function for child process.
    Parameter: socketFD - Socket file descriptor
    Parameter: newSocketFD - New socket file descriptor
    Parameter: buffer - Buffer string
*/
void childHelper(int socketFD, int newSocketFD, char buffer[]) {

    // Instantiate variables
    int temporaryResult;
    long plainTextSize;
    long keySize;

    // Close socket and flush buffer
    close(socketFD);
    bzero(buffer, sizeof(buffer));

    // Display to client the server type and re-Flush
    socketWrite(newSocketFD, "enc_d");
    bzero(buffer, sizeof(buffer));

    // Fetch plainText size from client
    temporaryResult = read(newSocketFD, &plainTextSize, sizeof(plainTextSize));
    if (temporaryResult < 0) {
        printf("Error - Socket Reading!\n");
    }

    // Set plainText length and send ACK response
    long plainTextLength = ntohl(plainTextSize);
    socketWrite(newSocketFD, "ACK");

    // Allocate memory for plainText, begin plainText socket read stream, and terminate
    char *plainText = malloc(sizeof(char) * (plainTextLength + 1));
    long size = socketReadStream(newSocketFD, plainText, plainTextLength);
    plainText[size] = '\0';

    // Send ACK response and flush buffer for client key
    socketWrite(newSocketFD, "ACK");
    bzero(buffer, sizeof(buffer));

    // Fetch client's key size
    temporaryResult = read(newSocketFD, &keySize, sizeof(keySize));
    if (temporaryResult < 0) {
        printf("Error - Socket Reading!\n");
    }

    // Set key length and send ACK response
    long keyLength = ntohl(keySize);
    socketWrite(newSocketFD, "ACK");

    // Allocate memory for client key and start read stream
    char *key = malloc(sizeof(char) * (keyLength + 1));
    size = socketReadStream(newSocketFD, key, keyLength);
    key[size] = '\0';

    // Send ACK response, encrypt plainText with client key, and send result
    socketWrite(newSocketFD, "ACK");
    char *cipherText = encrypt(key, plainText, strlen(plainText));
    socketWrite(newSocketFD, cipherText);

    // Cleanup
    close(newSocketFD);
    free(plainText);
    free(key);
    free(cipherText);

    exit(0);
}
Example #18
0
int32_t write_nbytes(BSOCK * bsock, char *ptr, int32_t nbytes)
{
   int32_t nleft, nwritten;

   if (bsock->is_spooling()) {
      nwritten = fwrite(ptr, 1, nbytes, bsock->m_spool_fd);
      if (nwritten != nbytes) {
         berrno be;
         bsock->b_errno = errno;
         Qmsg3(bsock->jcr(), M_FATAL, 0, _("Attr spool write error. wrote=%d wanted=%d bytes. ERR=%s\n"),
               nbytes, nwritten, be.bstrerror());
         Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes);
         errno = bsock->b_errno;
         return -1;
      }
      return nbytes;
   }

#ifdef HAVE_TLS
   if (bsock->tls) {
      /* TLS enabled */
      return (tls_bsock_writen(bsock, ptr, nbytes));
   }
#endif /* HAVE_TLS */

   nleft = nbytes;
   while (nleft > 0) {
      do {
         errno = 0;
         nwritten = socketWrite(bsock->m_fd, ptr, nleft);
         if (bsock->is_timed_out() || bsock->is_terminated()) {
            return -1;
         }

#ifdef HAVE_WIN32
         /*
          * For Windows, we must simulate Unix errno on a socket
          *  error in order to handle errors correctly.
          */
         if (nwritten == SOCKET_ERROR) {
            DWORD err = WSAGetLastError();
            nwritten = -1;
            if (err == WSAEINTR) {
               errno = EINTR;
            } else if (err == WSAEWOULDBLOCK) {
               errno = EAGAIN;
            } else {
               errno = EIO;        /* some other error */
            }
         }
#endif

      } while (nwritten == -1 && errno == EINTR);
      /*
       * If connection is non-blocking, we will get EAGAIN, so
       * use select() to keep from consuming all the CPU
       * and try again.
       */
      if (nwritten == -1 && errno == EAGAIN) {
         fd_set fdset;
         struct timeval tv;

         FD_ZERO(&fdset);
         FD_SET((unsigned)bsock->m_fd, &fdset);
         tv.tv_sec = 1;
         tv.tv_usec = 0;
         select(bsock->m_fd + 1, NULL, &fdset, NULL, &tv);
         continue;
      }
      if (nwritten <= 0) {
         return -1;                /* error */
      }
      nleft -= nwritten;
      ptr += nwritten;
      if (bsock->use_bwlimit()) {
         bsock->control_bwlimit(nwritten);
      }
   }
   return nbytes - nleft;
}
Example #19
0
void Q3Process::writeToStdin( const QByteArray& buf )
{
    d->stdinBuf.enqueue( new QByteArray(buf) );
    socketWrite( 0 );
}
Example #20
0
/*
 * Class:     javm_nativeimp_NsDatagramSocketImpl
 * Method:    send
 * Signature: (Lagentj/nativeimp/util/DataPacket;)V
 */
JNIEXPORT void JNICALL Java_agentj_nativeimp_NsDatagramSocketImpl_send0
(JNIEnv *env, jobject javaobj, jobject datapacket) {

    PLOG(PL_DEBUG, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Entering\n");

    jclass jobcls = env->GetObjectClass(javaobj); // gets the class signature for the datapacket class

    jmethodID getSocketID = env->GetMethodID(jobcls, "getSocketID", "()I");
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got socket ID = %i\n", getSocketID);

    jclass cls = env->GetObjectClass(datapacket); // gets the class signature for the datapacket class

    if (cls==0) {
        PLOG(PL_FATAL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Can't access DataPacket Class\n");
        exit(0);
    }

    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got data packet class = %u\n", cls);

    jmethodID getDataID = env->GetMethodID(cls, "getData", "()[B");
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got address ID = %i\n", getDataID);
    jmethodID getLengthID = env->GetMethodID(cls, "getLength", "()I");
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got length ID = %i\n", getLengthID);
    jmethodID getOffsetID = env->GetMethodID(cls, "getOffset", "()I");
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got offset ID = %i\n", getOffsetID);
    jmethodID getPortID = env->GetMethodID(cls, "getPort", "()I");
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got port ID  = %i\n", getPortID);
    jmethodID getAddressID = env->GetMethodID(cls, "getAddress", "()J");
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got address ID = %i\n", getAddressID);

    if (getAddressID==0) {
        PLOG(PL_FATAL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Can't access DataPacket Class methods\n");
        exit(0);
    }

    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: All IDs are ok\n");

    jlong addr = env->CallLongMethod(datapacket, getAddressID);

    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Got address %u\n", addr);

    jbyteArray data = (jbyteArray)env->CallObjectMethod(datapacket, getDataID);
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Called getData\n");
    jint len = env->CallIntMethod(datapacket, getLengthID);
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Called getLength = %i\n", len);
    jint off = env->CallIntMethod(datapacket, getOffsetID);
    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Called getOffset = %i\n", off);
    jint port = env->CallIntMethod(datapacket, getPortID);

    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Called getPort = %i\n", port);

    jthrowable exc;
    exc = env->ExceptionOccurred();
    if (exc) {
        env->ExceptionDescribe();
        env->ExceptionClear();
        throwException(env, "helpermethods: getAddress() - Can't get HostName, unknown error, FATAL");
        exit(0);
    }

    PLOG(PL_DETAIL, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Invoking scoketWrite now\n");

    socketWrite(env, javaobj, data, off, len, (unsigned int)addr, port);

    PLOG(PL_DEBUG, "Java_agentj_nativeimp_NsDatagramSocketImpl_send: Exiting\n");
}
Example #21
0
/**
 * Thread to handle a connection, feeds data to the port
 */
void connectionHandler(void *vargp)
{
	int tid;						// Thread ID
	int id;							// Requested robot ID
	int n;
	int aid;						// AprilTag ID
	int head;						// Last location of robot buffer viewed
	int up, bl;						// Flag
	struct Connection *conn;		// Connection information
	char buffer[BUFFERSIZE];		// General use buffer
	char inBuffer[BUFFERSIZE];		// Input buffer from client
	struct socketIO socketio;		// Robust IO buffer for socket
	fd_set read_set, ready_set;		// Read set for select
	struct timeval tv = { 0, 1 };	// Timeout for select

	conn = (struct Connection *) vargp;
	tid = conn->n;

	if (verbose) {
		printf("T%02d: Handler thread initialized\n", tid);
	}

	/* Initialize robust IO on the socket */
	socketInitIO(&socketio, conn->fd);

	if (verbose) {
		printf("T%02d: [%d] Processing new client connection\n", tid, conn->n);
	}

	/* Initialize stuff for select */
	FD_ZERO(&read_set);
	FD_SET(conn->fd, &read_set);

	/* Query user for robot ID */
	id = -1;
	while (id == -1) {
		if (aprilTagConnected) {
			if (socketWrite(conn->fd,
				"Enter the robot ID you wish to view (0 for AprilTag only): ",
				59) < 0) {
				break;
			}
		} else {
			if (socketWrite(conn->fd, "Enter the robot ID you wish to view: ",
				37) < 0) {
				break;
			}
		}

		if (socketReadline(&socketio, buffer, BUFFERSIZE) == 0) {
			break;
		}

		if (sscanf(buffer, "%d\n", &id) != 1) {
			if (socketWrite(conn->fd, "Invalid ID! Try Again.\r\n", 24) < 0) {
				break;
			}
			continue;
		}

		/* Handle bad numbers */
		if (id >= MAXROBOTID || id < 0) {
			id = -1;
			if (socketWrite(conn->fd, "Invalid ID! Try Again.\r\n", 24) < 0) {
				break;
			}
			continue;
		}

		if (id == 0 && !aprilTagConnected) {
			id = -1;
			if (socketWrite(conn->fd, "Invalid ID! Try Again.\r\n", 24) < 0) {
				break;
			}
			continue;
		}

		mutexLock(&robots[id].mutex);
		up = robots[id].up;
		bl = robots[id].blacklisted && !(robots[id].type == REMOTE);
		mutexUnlock(&robots[id].mutex);

		if (up && !bl) {
			if (socketWrite(conn->fd, "Connected!\r\n", 12) < 0) {
				break;
			}
		} else {
			id = -1;
			if (socketWrite(conn->fd, "Robot ID not connected!\r\n", 25) < 0) {
				break;
			}
		}
	}

	/* Close if the connection broke */
	if (id == -1) {
		if (verbose) {
			printf("T%02d: [%d] Done!\n", tid, conn->n);
		}

		Close(conn->fd);
		Free(conn);
		return;
	}

	if (verbose) {
		printf("T%02d: [%d] Connected to robot %02d\n", tid, conn->n, id);
	}

	aid = robots[id].aid;
	if (aprilTagConnected) {
		while (aid == -1) {
			if (socketWrite(conn->fd, "Robot AprilTag (Enter for none): ", 33)
				< 0) {
				break;
			}

			if (socketReadline(&socketio, buffer, BUFFERSIZE) == 0) {
				break;
			}

			if (sscanf(buffer, "%d\n", &aid) != 1) {
				aid = -1;
				break;
			}

			/* Handle bad numbers */
			if (aid >= MAX_APRILTAG || aid < 0) {
				aid = -1;
				if (socketWrite(conn->fd, "Invalid AprilTag! Try Again.\r\n",
					30) < 0) {
					break;
				}
				continue;
			}

			if (aprilTagData[aid].active) {
				if (socketWrite(conn->fd, "AprilTag linked!\r\n", 18) < 0) {
					break;
				}

				if (verbose) {
					printf("T%02d: [%d] Connected to AprilTag %d\n", tid,
						conn->n, aid);
				}
			} else {
				if (socketWrite(conn->fd, "AprilTag not seen!\r\n", 20) < 0) {
					break;
				}
				aid = -1;
			}
		}
	}

	/* Connected to a robot / AprilTag feed */
	if (id != 0 || (id == 0 && aid == -1)) {
		mutexLock(&robots[id].mutex);
		head = robots[id].head;
		mutexUnlock(&robots[id].mutex);

		for (;;) {
			ready_set = read_set;

			/* Check if there is data available from the client. */
			if (select(conn->fd + 1, &ready_set, NULL, NULL, &tv) < 0) {
				break;
			}

			/* Is there is data to be read? */
			if (FD_ISSET(conn->fd, &ready_set)) {
				if (socketRead(&socketio, inBuffer, BUFFERSIZE) != 0) {
					/* Write data out to serial port if the robot is local */
					mutexLock(&robots[id].mutex);
					if (robots[id].type == LOCAL || robots[id].type == HOST) {
						hprintf(robots[id].hSerial, inBuffer);
					}
					mutexUnlock(&robots[id].mutex);
				} else {
					break;
				}
			}
			/* Extensively use the mutex to prevent all data-races */
			mutexLock(&robots[id].mutex);
			/* If there is new data in the robot buffer */
			while (head != robots[id].head) {
				mutexUnlock(&robots[id].mutex);

				fetchData(buffer, id, head, aid, -1);

				if ((n = socketWrite(conn->fd, buffer, strlen(buffer))) < 0) {
					break;
				}

				head = (head + 1) % NUMBUFFER;
				mutexLock(&robots[id].mutex);
			}

			/* If true, connection is broken so exit out. */
			if (n < 0)
				break;

			/* Check if the robot is disconnected. */
			if ((robots[id].blacklisted
				&& !(robots[id].type == REMOTE))
				|| !robots[id].up) {
				socketWrite(conn->fd, "Robot ID disconnected!\r\n", 24);
				mutexUnlock(&robots[id].mutex);
				break;
			}
			mutexUnlock(&robots[id].mutex);
		}
	/* Connected to an AprilTag */
	} else {
		int rid;

		sprintf(tbuffer, "New Connection to AprilTag ID %2d!", aid);
		setToaster(tbuffer);

		mutexLock(&aprilTagData[aid].mutex);
		head = aprilTagData[aid].head;
		mutexUnlock(&aprilTagData[aid].mutex);

		for (;;) {
			mutexLock(&aprilTagData[aid].mutex);
			/* If there is new data in the robot buffer */
			while (head != aprilTagData[aid].head) {
				rid = aprilTagData[aid].rid;
				mutexUnlock(&aprilTagData[aid].mutex);
				fetchData(buffer, rid, -1, aid, -1);

				if ((n = socketWrite(conn->fd, buffer, strlen(buffer))) < 0) {
					break;
				}

				head = (head + 1) % NUMBUFFER_APRILTAG;
				mutexLock(&aprilTagData[aid].mutex);
			}
			mutexUnlock(&aprilTagData[aid].mutex);

			/* If true, connection is broken so exit out. */
			if (n < 0)
				break;
		}
	}

	if (verbose) {
		printf("T%02d: [%d] Done!\n", tid, conn->n);
	}

	/* Clean up. */
	Close(conn->fd);
	Free(conn);

	return;
}
Example #22
0
void Q3Process::flushStdin()
{
    socketWrite( 0 );
}
Example #23
0
/**
 * Starts a program with Bumblebee if possible
 *
 * @param argc The number of arguments
 * @param argv The values of arguments
 * @return The exitcode of the program on success, EXIT_FAILURE if the program
 * could not be started
 */
static int run_app(int argc, char *argv[]) {
  int exitcode = EXIT_FAILURE;
  char buffer[BUFFER_SIZE];
  int r;
  int ranapp = 0;
  r = snprintf(buffer, BUFFER_SIZE, "Checking availability...");
  socketWrite(&bb_status.bb_socket, buffer, r + 1);
  while (bb_status.bb_socket != -1) {
    r = socketRead(&bb_status.bb_socket, buffer, BUFFER_SIZE);
    if (r > 0) {
      bb_log(LOG_INFO, "Response: %s\n", buffer);
      switch (buffer[0]) {
        case 'N': //No, run normally.
          bb_log(LOG_ERR, "Cannot access secondary GPU%s\n", buffer+2);
          socketClose(&bb_status.bb_socket);
          if (!bb_config.fallback_start) {
            bb_log(LOG_ERR, "Aborting because fallback start is disabled.\n");
          }
          break;
        case 'Y': //Yes, run through vglrun
          bb_log(LOG_INFO, "Running application through vglrun.\n");
          ranapp = 1;
          //run vglclient if any method other than proxy is used
          if (strncmp(bb_config.vgl_compress, "proxy", BUFFER_SIZE) != 0) {
            char * vglclient_args[] = {
              "vglclient",
              "-detach",
              0
            };
            bb_run_fork(vglclient_args, 1);
          }
          /* number of options passed to --vgl-options */
          unsigned int vglrun_opts_count = 0;
          char *next_arg = bb_config.vglrun_options;
          /* read vglrun options only if there is an arguments list */
          if (next_arg && next_arg[0]) {
            do {
              ++vglrun_opts_count;
            } while ((next_arg = strchr(next_arg + 1, ' ')));
          }
          /* position of next option */
          unsigned int optno = 0;

          /* 7 for the first options, 1 for the -- and 1 for the trailing 0 */
          char ** vglrun_args = malloc(sizeof (char *) *
                  (9 + vglrun_opts_count + argc - optind));
          vglrun_args[0] = "vglrun";
          vglrun_args[1] = "-c";
          vglrun_args[2] = bb_config.vgl_compress;
          vglrun_args[3] = "-d";
          vglrun_args[4] = bb_config.x_display;
          vglrun_args[5] = "-ld";
          vglrun_args[6] = bb_config.ld_path;
          optno = 7;

          next_arg = bb_config.vglrun_options;
          if (next_arg && next_arg[0]) {
            char *current_arg;
            do {
              current_arg = next_arg;
              next_arg = strchr(current_arg, ' ');
              /* cut the string if a space is found */
              if (next_arg) {
                *next_arg = 0;
                /* the next argument starts at the position after the space */
                next_arg++;
              }
              vglrun_args[optno++] = current_arg;
            } while (next_arg);
          }

          vglrun_args[optno++] = "--";
          for (r = 0; r < argc - optind; r++) {
            vglrun_args[r + optno] = argv[optind + r];
          }
          vglrun_args[optno+=r] = 0;
          exitcode = bb_run_fork(vglrun_args, 0);
          free(vglrun_args);
          socketClose(&bb_status.bb_socket);
          break;
        default: //Something went wrong - output and exit.
          bb_log(LOG_ERR, "Problem: %*s\n", r, buffer);
          socketClose(&bb_status.bb_socket);
          break;
      }
    }
  }
  if (!ranapp) {
    exitcode = run_fallback(argv + optind);
  }
  return exitcode;
}
/*
	This function validate and process commands received from client.

	The command syntax allows the user to open accounts, to start sessions to serve specific
	accounts, and to exit the client process altogether. Here is the command syntax:
		• open accountname
		• start accountname
		• credit amount
		• debit amount
		• balance
		• finish
		• exit

 */
static void socketService(int clientID)
{
	int inService = 1;					/* set service on for current child process (will be used for infinite loop*/
	char line[MaxInputSize+commandLen], *command, *value;
	int clientIdx = -1;					/* controls which account ID child process is holding,
										   negative value means no current account opened  */

	int inputSize, idx1;
	while(inService)
	{
		inputSize = socketRead(clientID, line, sizeof(line));	/* read a line from client socket */

		command = strtok(line, " ");	/* client command */
		value = strtok(NULL, "\n");		/* value after command */

		if(strcmp(command, "open") == 0)
			/*				!!!!!! OPEN COMMAND !!!!!!
				The open command opens a new account for the bank. It is an error if the bank already has a
				full list of accounts, or if an account with the specified name already exists. A client in a customer
				session cannot open new accounts, but another client who is not in a customer session can open
				new accounts. The name specified uniquely identifies the account. An account name will be at
				most 100 characters. The initial balance of a newly opened account is zero. It is only possible to
				open one new account at a time, no matter how many clients are currently connected to the server
			*/
		{	/* Validate provided value */
			if(clientIdx != -1)
			{
				inputSize =  snprintf(line, MaxInputSize, "Command Error: Session is already opened");
			}
			else if(value == NULL)
			{
				inputSize = snprintf(line, MaxInputSize, "Command Error: Please provide a name");
			}
			else
			{
				if(bank->accountCounter >= (MaxAccounts-1))
				{	/* if not sucessful */
					inputSize =  snprintf(line, MaxInputSize, "Command Error: Unable to allocate resources");
				}
				else
				{
					/* Verify if account exists */
					for(idx1=0; idx1 < bank->accountCounter; idx1++)
					{
						if(strcmp(bank->accounts[idx1].name, value) == 0)
						{
							inputSize =  snprintf(line, MaxInputSize, "Command Error: Account name already exists.  Try start command");
							break;
						}
					}

					if(idx1 == bank->accountCounter)
					{
						/* Create Account */
//						LOCK(bank->mutex);
						if(pthread_mutex_lock(&bank->mutex)	!= 0) { perror("pthread_mutex_lock ERROR"); }
						clientIdx = bank->accountCounter++;
						strcpy(bank->accounts[clientIdx].name, value);
						bank->accounts[clientIdx].balance = 0.0;
						bank->accounts[clientIdx].inSession = 1;	//only after start ?
						pthread_mutex_lock(&bank->accounts[clientIdx].mutex);
//						UNLOCK(bank->mutex);
						if(pthread_mutex_unlock(&bank->mutex) != 0)	{ perror("pthread_mutex_unlock ERROR"); }
						inputSize = snprintf(line, MaxInputSize, "Account sucessfully created - %s", bank->accounts[clientIdx].name);
					}
				}
			}

		}
		else
		/*				!!!!!! START COMMAND !!!!!!
			The start command starts a customer session for a specific account. The credit, debit, balance
			and finish commands are only valid in a customer session. It is not possible to start more than one
			customer session in any single client window, although there can be concurrent customer sessions
			for different accounts in different client windows. Under no circumstances can there be concurrent
			customer sessions for the same account. It is possible to have any number of sequential client
			sessions.
		*/
		if(strcmp(command, "start") == 0)
		{
			if(clientIdx != -1)
			{	/* Validate provided value */
				inputSize = snprintf(line, MaxInputSize, "Command Error: Session is already opened");
			}
			else if(value == NULL)
			{
				inputSize = snprintf(line, MaxInputSize, "Command Error: Please provide an account name");
			}
			else
			{
				/* find the account - it MUST exist */
				int accountIsLocked = 0;
//				LOCK(bank->mutex);
				if(pthread_mutex_lock(&bank->mutex)	!= 0)
				{
					perror("pthread_mutex_lock ERROR");
				}
				for(idx1=0; idx1 < bank->accountCounter; idx1++)
				{
					if(strcmp(bank->accounts[idx1].name, value) == 0)
					{
						clientIdx = idx1;	/* save account ID */
						accountIsLocked = pthread_mutex_trylock(&bank->accounts[idx1].mutex); /* try to lock */
						break;
					}
				}
//				UNLOCK(bank->mutex);
				if(pthread_mutex_unlock(&bank->mutex) != 0)	{ perror("pthread_mutex_unlock ERROR"); }

				if(clientIdx == -1)
				{
					inputSize = snprintf(line, MaxInputSize, "Account not found");
				}
				else
				if (accountIsLocked)
				{
					inputSize = snprintf(line, MaxInputSize, "Account is locked by other user");
					/*
					For extra credit. insert the logic to try to lock the mutex every 2 seconds.  If it fails,
					send message ”waiting to start customer session for account” message to the appropriate
					client process
					*/
				}
				else
				/* Reopen the session */
				{
					bank->accounts[clientIdx].inSession = 1;
					inputSize = snprintf(line, MaxInputSize, "%s session reopened", bank->accounts[idx1].name);
				}
			}
		}
		else if(strcmp(command, "credit") == 0)
			/*				!!!!!! CREDIT COMMAND !!!!!!
			    The credit command add amounts to an account balance. Amounts are specified as floating-point numbers.
				Credit command complains if the client is not in a customer session. There are no constraints on the
				size of a credit.
			*/
		{
			if(clientIdx == -1)
			{
				inputSize = snprintf(line, MaxInputSize, "Start or open an account before using credit function");
			}
			else if(value == NULL)
			{
				inputSize = snprintf(line, MaxInputSize, "Please enter an amount to credit");
			}
			else
			{	/* no need to lock account, since only one user per account can be in session */
				bank->accounts[clientIdx].balance += atof(value);
				float balance = bank->accounts[clientIdx].balance;
				inputSize = snprintf(line, MaxInputSize, "%s new balance: %.2f", bank->accounts[clientIdx].name, balance);
			}

		}
		else if(strcmp(command, "debit") == 0)
			/*				!!!!!! DEBIT COMMAND !!!!!!
			 	The debit command subtract amounts from an account balance. Amounts are specified as floating-point numbers.
			 	Debit command complains if the client is not in a customer session.  Debit is invalid if the requested
				amount exceeds the current balance for the account. Invalid debit attempts leave the current balance
				unchanged.
			*/
		{
			if(clientIdx == -1)
			{
				inputSize = snprintf(line, MaxInputSize, "Start or open an account before using debit function");
			}
			else if(value == NULL)
			{
				inputSize = snprintf(line, MaxInputSize, "Please enter an amount to credit");
			}
			else
			{
				float amount_f = atof(value);
				if(amount_f > bank->accounts[clientIdx].balance)
				{
					inputSize = snprintf(line, MaxInputSize, "Overdraft is not allowed for this account");
				}
				else
				{	/* no need to lock account, since only one user per account can be in session */
					bank->accounts[clientIdx].balance -= amount_f;
					float balance = bank->accounts[clientIdx].balance;
					inputSize = snprintf(line, MaxInputSize, "%s new balance: %.2f", bank->accounts[clientIdx].name, balance);
				}
			}
		}
		else if(strcmp(command, "balance") == 0)
			/*				!!!!!! BALANCE COMMAND !!!!!!
			 	 The balance command simply returns the current account balance.
			*/
		{
			if(clientIdx == -1)
			{
				inputSize = snprintf(line, MaxInputSize, "Start or open an account before using balance function");
			}
			else
			{
				inputSize = snprintf(line, MaxInputSize, "%s current balance: %.2f", bank->accounts[clientIdx].name, bank->accounts[clientIdx].balance);
			}
		}
		else if(strcmp(command, "finish") == 0)
			/*				!!!!!! FINISH COMMAND !!!!!!
				The finish command finishes the customer session. Once the customer session is ended, it is
				possible to open new accounts or start a new customer session.
			*/
		{
			if(clientIdx == -1)
			{
				inputSize = snprintf(line, MaxInputSize, "No open account to finish");
			}
			else
			{
				bank->accounts[clientIdx].inSession = 0;	/* clear user session */
				inputSize = snprintf(line, MaxInputSize, "%s transactions finished", bank->accounts[clientIdx].name);
//				UNLOCK(bank->accounts[clientIdx].mutex);	/* unlock account */
				if(pthread_mutex_unlock(&bank->accounts[clientIdx].mutex) != 0)	{ perror("pthread_mutex_unlock ERROR"); }
				clientIdx = -1;								/* reset account index */
			}
		}
		else if(strcmp(command, "exit") == 0)
			/*				!!!!!! EXIT COMMAND !!!!!!
				The exit command disconnects the client from the server and ends the client process. The server process
				should continue execution.
			*/
		{
			inputSize = snprintf(line, MaxInputSize, "Have a good day");
			inService = 0;
			bank->accounts[clientIdx].inSession = 0;	/* mark current account off session */
	//		UNLOCK(bank->accounts[clientIdx].mutex);	/* unlock it for other */
			if(pthread_mutex_unlock(&bank->accounts[clientIdx].mutex) != 0)	{ perror("pthread_mutex_unlock ERROR"); }
			printf("User %i disconnect request granted\n", clientID);
		}
		else if(strcmp(command, "SIGINT") == 0){
			int idx1, status;
			pid_t processID = getpid();

			printf("Abnormal Exit Signal From Client Process %d...\n", processID);

			for(idx1=0; idx1 < MaxSessions+2; idx1++)
			{
				if(childPID[idx1] == processID)
				{
				printf("Freeing Session and Mutex Locks For Child Process...\n");
				bank->accounts[idx1].inSession = 0;
				if(pthread_mutex_unlock(&bank->accounts[idx1].mutex) != 0)	{ perror("pthread_mutex_unlock ERROR"); }
				}
			}

			//Kill Child Process
			kill(childPID[idx1], SIGTERM);
			waitpid(childPID[idx1], &status, 0);
			childPID[idx1] = 0;
			deallocateMEM(0);	//free memory
		}
		else
		{
			inputSize = snprintf(line, MaxInputSize, "I don't understand that command!!!");
		}

		if(socketWrite(clientID, line, inputSize) == 0) snprintf(line, MaxInputSize, "Do you need help?");
	}
	if(clientIdx == -1)
	{ /* This is abnormal.  Display as much info we can for troubleshooting */
		printf ("In-SESSION = %i", bank->accounts[clientIdx].inSession);
		printf("Client disconnected for unknown reason\n");
	}

	/* close the socket service */
	shutdown(clientID, SHUT_RDWR);
	close(clientID);
}