libcom_tcp.c

来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 2,071 行 · 第 1/5 页

C
2,071
字号
    return(0);
  }

  return(1);
}

void EXPORT_MSCPP tcpTestDLL(void)
{
  MessageBox(NULL, "Testing, one ,two, ...", "TCP Dll", MB_OK);
}

#endif /* _WINDOWS */

/****************************************************************************
 * General definitions
 ****************************************************************************/

/**
 * Shuts down an open socket.
 * @param socket the socket to close
 */
void tcpShutdown(SOCKET socket) {
  shutdown(socket,2);
#ifdef _WINDOWS
  shutdown(socket, 0);
#else
  close(socket);
#endif
}


/**
 * Given a host and port, connect to the server socket.
 * @param hostName may be a host ID or IP address
 * @param port port to connect to on hostName
 * @return file descriptor to socket or -1 if failure
 */
SOCKET tcpConnect(char *hostName, int port)
{
  SOCKET s;
  int ret;
  struct sockaddr_in saddr;
  struct hostent *he;
  u_long addr;

  he = gethostbyname(hostName);

  if (!he) {
    printf("Could not gethostbyname(), trying gethostbyaddr\n");
    addr = inet_addr(hostName);
    if ((int)addr != -1) {
      he = gethostbyaddr((char *)&addr, sizeof(u_long), AF_INET);
      if(he == NULL) {
	return -1;
      }
    }
  }

  if (!he) {
    printf("TCP - Could not resolve host: %s\n", hostName);
    return -1;
  }

  ret = socket(AF_INET, SOCK_STREAM, 0);

  if (ret < 0) {
    printf("TCP - Could not create socket.\n");
    return -1;
  }
  else s = ret;


#ifndef _WINDOWS
  memset((char*)&saddr, 0, sizeof(saddr));
  memcpy((char*)&saddr.sin_addr.s_addr, he->h_addr, he->h_length);
  memset(&(saddr.sin_zero), '\0', 8);
#else
  memcpy((char FAR *) &saddr.sin_addr, (char FAR *)he->h_addr, he->h_length);
#endif

  saddr.sin_family = AF_INET;
  saddr.sin_port = htons(port);

  if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
    printf("TCP - Could not connect to %s #%d\n", hostName,port);
    perror("Reason");
    tcpShutdown(s);
    return -1;
  }

  return s;
}


/**
 * Wait for socket input, or until timeout.
 * @param socket the socket to wait for
 * @param timeout the max wait time in seconds (if 0, blocks)
 * @return the number of file descriptors read
 */
int tcpSelect(SOCKET socket, double timeout) {

  struct timeval  time, *timep = NULL;
#ifndef _WINDOWS
  struct timezone timezone;
#endif

  int width;
  fd_set readfds;

  if (timeout > 0) {
#ifndef _WINDOWS
    if(gettimeofday(&time, &timezone) == -1)
      printf("TCP - error getting time of data\n");
    else {
#endif
      long i;
      i = (long)timeout;        /* Convert double to integer, loss of data ! */
      time.tv_sec = i;    /* Add number of seconds to current time */
      time.tv_usec = 0.5 + (timeout - i) * 1e6;  /* Add fractional msecs */
      timep = &time;
#ifndef _WINDOWS
    }
#endif
  }

  width = socket + 1;          /* Width must include current fd   */
  FD_ZERO(&readfds);           /* Clear fds                       */
  FD_SET(socket, &readfds);    /* Add file descriptor to read set */

  return select(width, &readfds, NULL, NULL, timep);
}

/**
 * Looks up the current ConnectionId. Assumes there is only one
 * connection ID and returns the first. Returns the connection in a
 * new space which should be free'd.
 * @return the connectionId or NULL if none available
 */
EXPORT_MSCPP
char * EXPORT_BORLAND
com_GetDefaultConnectionId()
{
  static ICLTerm *info = NULL;
  ICLTerm *answers = NULL;
  char *result = NULL;

  if (!icl_IsValid(info)) {
    info = icl_NewTermFromData(
      "com_connection_info(Id,Protocol,Type,InfoList,Status)",53);
  }

  /* Make sure there's a valid database */
  if (!commdb)
    return NULL;

  if (db_Solve(commdb, info, ICL_EMPTY, &answers)) {
    ICLTerm *item = icl_NthTerm(answers, 1);
    result = strdup(icl_Str(icl_NthTerm(item, 1)));
  }
  icl_Free(answers);
  return result;
}

/**
 * Returns address tcp(IPAddr,Port) to connected socket.
 * Must be connected first, for this to work!
 * Currently, assumes client connection (should change!)
 */
EXPORT_MSCPP
void EXPORT_BORLAND
cnx_CanonicalAddress(ICLTerm *address, SOCKET socket, ICLTerm **result)
{
  ICLTerm *addressStruct = icl_NewTermFromData("tcp(Host,Port)",14);

  if (icl_Unify(addressStruct, address, NULL) && (socket>0)) {
    struct sockaddr_in* ptr_distaddr;
    struct sockaddr distaddr;
    int remotePortNumber = -1;
    char remoteHostName[255];

    int addrlen = sizeof(distaddr);

    sprintf(remoteHostName, "unknown");
    ptr_distaddr = (struct sockaddr_in *)&(distaddr);

    if (getpeername(socket, &distaddr, &addrlen)==0) {

      /* HACK
         ptr_distaddr->sin_port does not work under windows !
         #ifndef _WINDOWS
         remotePortNumber = ptr_distaddr->sin_port;
         #else
         remotePortNumber = icl_Int(icl_NthTerm(address, 2));
         #endif
      */
      remotePortNumber = icl_Int(icl_NthTerm(address, 2));

      /* To get the host name */
      /*
        disthost=gethostbyaddr((const void*)(&ptr_distaddr->sin_addr), 4, AF_INET);
        if (disthost)
        sprintf(remoteHostName,"%s",disthost->h_name);
      */
      /* To get the IP number */
      sprintf(remoteHostName,"%s",inet_ntoa(ptr_distaddr->sin_addr));


      if (result!=NULL)
        *result = icl_NewStruct("addr", 1,
                                icl_NewStruct("tcp", 2,
                                              icl_NewStr(remoteHostName),
                                              icl_NewInt(remotePortNumber)));

    }
    else {
      comPrintError("%s",
                    "cnx_CanonicalAddress() can only be called on CONNECTED socket!");
    }
  }
  icl_Free(addressStruct);
}

/* -------------------------------------------------------------------------- */

// new functions added to support direct_connect

static void checkEventBuffer() {
  if (eventBuffer == NULL) {
    eventBuffer = icl_NewList(NULL);
  }
} // end of checkEventBuffer(

static void com_accept_new_connection(int listenersocket) {
  int connection = -1;
  char* namestring = NULL;
  ICLTerm *readerInfo = NULL;
  ICLTerm *senderInfo = NULL;
  ICLTerm *ev_conn = NULL;

  connection = accept(listenersocket, NULL, NULL);

  if (connection > 0) {
    ICLTerm *canonicalOtherAddress = NULL;
    ICLTerm *newConnectionInfo = NULL;
    ICLTerm *tempList = icl_NewList(NULL);
    char *ConnectionId = new_direct_client_id();
    ICLTerm *templateTcpAddr = icl_NewTermFromData("tcp(Host,Port)",14);
    char buf[1000];

    memset(buf, 0, sizeof(buf));
    cnx_CanonicalAddress(templateTcpAddr, connection, &canonicalOtherAddress);

    icl_AddToList(tempList, icl_NewStruct("other_address", 1, canonicalOtherAddress), FALSE);
    icl_AddToList(tempList, icl_NewStruct("connection", 1, icl_NewInt(connection)),FALSE);

    {
      TermReader* realTr = NULL;
      TermSender* realTs = NULL;
      char* readerPtr;
      char* readerInfoBuf;
      char* senderPtr;
      char* senderInfoBuf;

      if (com_is_binary_listener(listenersocket)) {
        BinaryTermReader* btr;
        BinaryTermSender* bts;
        realTr = termReader_create();
        btr = binaryTermReader_create(realTr, connection);
        realTs = termSender_create();
        bts = binaryTermSender_create(realTs, connection);
      }
      else {
        StringTermReader* str;
        StringTermSender* sts;
        realTr = termReader_create();
        str = stringTermReader_create(realTr, connection);
        realTs = termSender_create();
        sts = stringTermSender_create(realTs, connection);
      }

      readerPtr = pointerToString(realTr);
#ifdef NORMAL_GC
      /* so we don't lose the pointer */
      /*
      if(termReaders == NULL) {
        termReaders = g_ptr_array_new();
      }
      g_ptr_array_add(termReaders, realTr);
      */
      termReaders[++termReadersIdx] = realTr;
#endif
      readerInfoBuf = (char*)malloc(strlen(readerPtr) + 10 + 1);
      strncpy(readerInfoBuf, "reader('", 8);
      strncpy(readerInfoBuf + 8, readerPtr, strlen(readerPtr));
      readerInfoBuf[strlen(readerPtr) + 8] = '\'';
      readerInfoBuf[strlen(readerPtr) + 9] = ')';
      readerInfoBuf[strlen(readerPtr) + 10] = '\0';
      readerInfo = icl_NewTermFromString(readerInfoBuf);
      free(readerPtr);
      free(readerInfoBuf);
      senderPtr = pointerToString(realTs);
#ifdef NORMAL_GC
      /* so we don't lose the pointer */
      /*
      if(termSenders == NULL) {
        termSenders = g_ptr_array_new();
      }
      g_ptr_array_add(termSenders, realTs);
      */
      termSenders[++termSendersIdx] = realTs;
#endif
      senderInfoBuf = (char*)malloc(strlen(senderPtr) + 10 + 1);
      strncpy(senderInfoBuf, "sender('", 8);
      strncpy(senderInfoBuf + 8, senderPtr, strlen(senderPtr));
      senderInfoBuf[strlen(senderPtr) + 8] = '\'';
      senderInfoBuf[strlen(senderPtr) + 9] = ')';
      senderInfoBuf[strlen(senderPtr) + 10] = '\0';
      senderInfo = icl_NewTermFromString(senderInfoBuf);
      free(senderPtr);
      free(senderInfoBuf);
    }

    icl_AddToList(tempList, readerInfo, FALSE);
    icl_AddToList(tempList, senderInfo, FALSE);

    newConnectionInfo = icl_NewStruct("com_connection_info", 5,
                                      icl_NewStr(ConnectionId),
                                      icl_NewStr("tcp"),
                                      icl_NewStr("client"),
                                      tempList,
                                      icl_NewStr("connected"));

    if (newConnectionInfo) {
     db_Assert(commdb, newConnectionInfo, ICL_EMPTY);
     icl_Free(newConnectionInfo);
    }
    else {
     printf("Error! com_connection_info could not be constructed.\n");
    }

    {
    ICLTerm *ConnEvent = NULL;
    ICLTerm *EventTerm = NULL;
    ICLTerm *t1   = NULL;
    // Get the connection acknowledgement from the same ConnectionId.
    // A timeout of 0.0 means we'll block on this socket.
    com_select_event_from_socket(connection, 0.0, &EventTerm);

    ConnEvent = icl_NthTerm(icl_NthTerm(EventTerm, 1), 1);

    if (!icl_Unify(ConnEvent,
                  (t1 = icl_NewStruct("ev_connect",
                                      1,
                                      icl_NewVar("_"))),
                   NULL)) {
      fprintf(stderr, "Warning in com_accept_new_connection: ");
      fprintf(stderr, "Expected ev_connect, got %s\n", icl_Functor(ConnEvent));
      fflush(stderr);
    }
    icl_Free(t1);
    icl_Free(EventTerm);
   }

    namestring = oaa_name_string();
    sprintf(buf, "event(ev_connected([other_name('%s'), "
	               "other_language(c), other_type(client), "
	               "other_version(%s), ascii(%d), binary(%d)]),[])",
	               namestring, oaa_library_version_str,
	               stringPort, binaryPort);
    icl_stFree(namestring);

    ev_conn = icl_NewTermFromString(buf);
    com_SendTerm(ConnectionId, ev_conn);
    icl_Free(ev_conn);
    icl_Free(templateTcpAddr);
    free(ConnectionId);
  }

} // end of com_accept_new_connection

static int com_add_event_to_buffer(ICLTerm *event) {
  int answer = FALSE;
  checkEventBuffer();
  // add to end of list
  answer = icl_AddToList(eventBuffer, event, TRUE);
  return answer;
} //end of com_add_event_to_buffer

static int com_disconnect_all_connection_ids() {
  int answer = TRUE;
  ICLTerm *cids = NULL;
  ICLListType *cidslist = NULL;
  com_find_all_connection_ids(&cids);
  cidslist = icl_List(cids);
  while (icl_ListHasMoreElements(cidslist)) {
    char *cid = icl_Str(icl_ListElement(cidslist));
    if (cid != NULL) {
      answer = com_Disconnect(cid) && answer;
    }
    cidslist = icl_ListNextElement(cidslist);
  }
  icl_Free(cids);
  return answer;
} // end of com_disconnect_from_all_connection_ids


static int com_find_all_connected_sockets(ICLTerm *ids, ICLTerm **sockets) {
  int numberOfSockets = 0;
  ICLListType *idlist = icl_List(ids);
  *sockets = icl_NewList(NULL);
  while(icl_ListHasMoreElements(idlist)) {
    char *id = icl_Str(icl_ListElement(idlist));
    int socket = com_get_socket_from_connection_id(id);
    if (socket > 0) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?