libcom_tcp.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 2,071 行 · 第 1/5 页
C
2,071 行
StringTermSender* sts;
/*
printf("libcom_tcp com_Connect() using ascii format\n");
*/
connection = tcpConnect(icl_Str(host), (int)icl_Int(port));
realTr = termReader_create();
str = stringTermReader_create(realTr, connection);
#ifdef NORMAL_GC
printf("created str (%p) from realTr(%p)\n", str, realTr);
#endif
CHECK_LEAKS();
realTs = termSender_create();
sts = stringTermSender_create(realTs, connection);
CHECK_LEAKS();
}
CHECK_LEAKS();
icl_Free(reply);
CHECK_LEAKS();
close(oldConnection);
termReader_free(initialTr);
termSender_free(initialTs);
CHECK_LEAKS();
#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;
CHECK_LEAKS();
#endif
CHECK_LEAKS();
readerPtr = pointerToString(realTr);
readerInfoBuf = (char*)malloc(strlen(readerPtr) + 10 + 1);
CHECK_LEAKS();
strncpy(readerInfoBuf, "reader('", 8);
strncpy(readerInfoBuf + 8, readerPtr, strlen(readerPtr));
readerInfoBuf[strlen(readerPtr) + 8] = '\'';
readerInfoBuf[strlen(readerPtr) + 9] = ')';
readerInfoBuf[strlen(readerPtr) + 10] = '\0';
CHECK_LEAKS();
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);
}
if (connection>0) {
ICLTerm *canonicalOtherAddress = NULL;
ICLTerm *newConnectionInfo = NULL;
ICLTerm *tempList = icl_NewList(NULL);
ICLTerm *atmp;
ICLTerm *templateTcpAddr = icl_NewStruct("tcp", 2, host, port);
icl_AddToList(tempList, readerInfo, FALSE);
icl_AddToList(tempList, senderInfo, FALSE);
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);
// params added to call for direct_connect so that we
// could get the "correct" other_address into the com_connection_info...
{
ICLTerm *tmp1;
ICLTerm *tmp2;
tmp1 = icl_NewStruct("other_address", 1, icl_NewVar("_"));
if (icl_GetParamValue(tmp1, Params, &tmp2)) {
icl_AddToList(tempList, tmp2, TRUE);
}
icl_Free(tmp1);
}
cHost = icl_CopyTerm(host);
cPort = icl_CopyTerm(port);
atmp = icl_NewStruct("tcp", 2, cHost, cPort);
newConnectionInfo = icl_NewStruct("com_connection_info", 5,
icl_NewStr(ConnectionId),
atmp, /*
icl_NewStruct("tcp", 2, cHost, cPort),*/
icl_NewStr("client"),
tempList,
icl_NewStr("connected"));
printf("libcom_tcp com_Connect() Connected to %s %lld.\n",
icl_Str(host), icl_Int(port));
if (newConnectionInfo) {
db_Assert(commdb, newConnectionInfo, ICL_EMPTY);
/* DEBUG */
/* db_PrintDB(commdb);*/
icl_Free(newConnectionInfo);
}
else {
fprintf(stderr, "Error! com_connection_info could not be constructed.\n");
}
icl_Free(templateTcpAddr);
}
else
fprintf(stderr, "com_Connect: failed to connect to %s %lld.\n",
icl_Str(host), icl_Int(port));
if (!host && !port)
fprintf(stderr, "Make sure you have a valid setup.pl file\n");
}
else {
fprintf(stderr, "Error! Bad arguments to com_Connect()\n");
}
icl_Free(t1);
#ifdef NORMAL_GC
printf("Leaving comConnectFormat\n");
#endif
return connection;
}
/**
* Given a connection ID, shuts down the connection. If Id is NULL,
* shuts down all connections.
* <p>Note: Succeeds silently if there is not an open connection having the
* given id.</p>
*/
EXPORT_MSCPP
int EXPORT_BORLAND
com_Disconnect(char *ConnectionId)
{
ICLTerm *t1, *info = NULL;
if (ConnectionId == NULL) {
return com_disconnect_all_connection_ids();
}
if (ConnectionId && *ConnectionId && commdb) {
if (com_GetInfo(ConnectionId,
(t1 = icl_NewStruct("connection", 1,
icl_NewVar("_"))), &info)) {
tcpShutdown(icl_Int(icl_NthTerm(info, 1)));
icl_Free(info);
icl_Free(t1);
db_Retract(commdb,
(t1 = icl_NewStruct("com_connection_info", 5,
icl_NewStr(ConnectionId),
icl_NewVar("TCP"),
icl_NewVar("_Type"),
icl_NewVar("_Info"),
icl_NewStr("connected"))),
ICL_EMPTY);
}
icl_Free(t1);
return TRUE;
}
else return FALSE;
}
/**
* Return TRUE if the TCP connection is established
*/
EXPORT_MSCPP
SOCKET EXPORT_BORLAND
com_Connected(char* ConnectionId)
{
ICLTerm *t1;
/* Make sure there's a valid connection id */
if (ConnectionId && *ConnectionId) {
ICLTerm *currentStatus = NULL;
com_GetInfo(ConnectionId,
(t1 = icl_NewStruct("status", 1,
icl_NewStr("connected"))),¤tStatus);
icl_Free(t1);
if (currentStatus && STREQ(icl_Str(currentStatus),"connected")) {
icl_Free(currentStatus);
return TRUE;
}
}
return FALSE;
}
/****************************************************************************
* name: com_GetAllValidConnections
* purpose:
* remarks:
****************************************************************************/
EXPORT_MSCPP
int EXPORT_BORLAND
com_GetAllValidConnections(ICLTerm** result)
{
int index;
ICLTerm *resultFromDb = (ICLTerm *)NULL;
static ICLTerm* info = NULL;
if (!icl_IsValid(info)) {
info = icl_NewTermFromData("com_connection_info(Id,Protocol,Type,InfoList,connected)",56);
}
*result = icl_NewList(NULL);
if (db_Solve(commdb, info, ICL_EMPTY, &resultFromDb)) {
/*
Retreives all Id from the list of connected connections.
Not the best optimized way to to it (n^2 order), but lists of connections
are not going to be huge.
*/
ICLTerm *item = NULL;
/* DEBUG */
/*
printf("Result from db_Solve %s\n", icl_NewStringFromTerm(resultFromDb));
*/
for (index = 1; index <= icl_ListLen(resultFromDb) ; index ++) {
item = icl_NthTerm(resultFromDb, index);
icl_AddToList(*result, icl_CopyTerm(icl_NthTerm(item, 1)), TRUE);
}
icl_Free(resultFromDb);
return TRUE;
}
icl_Free(resultFromDb);
return FALSE;
};
/**
* Looks up a connection that contains a given information.
* @return NULL if fail, an IclTerm if success.
*/
int com_GetConnectionFromInfo(ICLTerm *Info, char** connectionName)
{
ICLTerm *resultFromDb = (ICLTerm *)NULL;
int res = FALSE;
static ICLTerm* info = NULL;
if (!icl_IsValid(info)) {
info = icl_NewTermFromData("com_connection_info(Conn,Protocol,Type,InfoList,Status)",55);
}
(void)Info;
if (db_Solve(commdb, info, ICL_EMPTY, &resultFromDb)) {
*connectionName =
strdup(icl_Str(icl_NthTerm(icl_NthTerm(resultFromDb, 1),1)));
res = TRUE;
icl_Free(resultFromDb);
}
return res;
}
/**
* Given a connection ID and an address, initiate a server connection
* <p>Remarks:</p>
* <ul>
* <li>if Address is a variable, instantiates the Address by using
* oaa_ResolveVariables, which looks in a setup file, command line, and
* environment variables for the required info.</li>
* <li>Even if RequestedAddress is fully instantiated, the actual listener
* address could be different, because of user input. Thus, ActualAddress
* should always be used as the return value (and should be a variable
* when called)
* <strong>UNLESS</strong> Params includes resolve_vars(false)</li>
* <li>stores the connection info for connection ID in com_connection_info/5.</li>
* <li>fails if connection can't be made</li>
* </ul>
*/
EXPORT_MSCPP
int EXPORT_BORLAND
com_ListenAt(char *ConnectionId, ICLTerm *Params, ICLTerm *Address)
{
ICLTerm *connectionInfo = NULL, *host = NULL, *port = NULL;
ICLTerm *info = NULL, *t1 = NULL;
ICLTerm *resolve_vars_false = icl_NewTermFromData("resolve_vars(false)",19);
int do_resolve_vars = TRUE;
char cmd[600];
char *addressString = NULL;
char *hostString = NULL;
int res = FALSE;
ICLTerm* addrFromCmdLine = NULL;
ICLTerm* addrFromSetup = NULL;
ICLTerm* addrFromEnv = NULL;
// Make sure database is initialized
if (!commdb)
commdb = db_NewDB();
t1 = icl_NewStruct("tcp", 2, icl_NewVar("Host"), icl_NewVar("Port"));
if (ConnectionId && *ConnectionId && icl_Unify(Address, t1, &connectionInfo)) {
// connectionInfo = tcp(Host,Port)
host = icl_NthTerm(connectionInfo, 1);
port = icl_NthTerm(connectionInfo, 2);
// if variable address, look it up...
do_resolve_vars = !icl_GetParamValue(resolve_vars_false, Params, NULL);
icl_Free(resolve_vars_false);
if (do_resolve_vars && (icl_IsVar(host) || icl_IsVar(port))) {
oaa_ResolveVariable("oaa_connect", &addrFromSetup); // setup file
Address = addrFromSetup;
addressString = getenv("OAA_CONNECT"); // env var
if (addressString) {
icl_Free(Address);
addrFromEnv = icl_NewTermFromString(addressString);
Address = addrFromEnv;
}
if(oaa_ResolveVariable("-oaa_connect", &addrFromCmdLine)) { // cmd line
icl_Free(Address);
Address = addrFromCmdLine;
}
}
icl_Free(connectionInfo);
// by now, host and port should be known
icl_Unify(Address, t1, &connectionInfo);
// connectionInfo = tcp(Host,Port)
host = icl_NthTerm(connectionInfo, 1);
port = icl_NthTerm(connectionInfo, 2);
if (!icl_IsVar(host) && !icl_IsVar(port))
do {
//
hostString = strdup(icl_Str(host));
if (!strcmp("localhost", hostString)) {
icl_stFree(hostString);
hostString = com_get_localhost_ip_address();
}
// stringPort, binaryPort, stringListener, and binaryListener
// have file scope
stringPort = icl_Int(port);
binaryPort = stringPort + OAA_BINARY_PORT_OFFSET;
stringListener = tcpListenAtPort(stringPort);
binaryListener = tcpListenAtPort(binaryPort);
if ( (stringListener > 0) && (binaryListener > 0) ) {
sprintf(cmd, "com_connection_info('%s', tcp, server, \
[oaa_address(addr(tcp('%s',%d))), oaa_host('%s'), oaa_port(%d)], \
connected)",
ConnectionId, hostString, stringPort,
hostString, stringPort);
info = icl_NewTermFromString(cmd);
if (info) {
db_Assert(commdb, info, ICL_EMPTY);
icl_Free(info);
}
else {
printf("Error! com_connection_info could not be constructed.\n");
}
res = TRUE;
}
else {
if (!com_ask_about_tcp_exception(icl_Int(port),
icl_NewStringFromTerm(host))) {
icl_Free(connectionInfo);
icl_Free(t1);
icl_stFree(hostString);
return FALSE;
}
}
} while (!res);
icl_Free(connectionInfo);
}
else {
printf("Error! Bad arguments to com_ListenAt()\n");
db_Assert(commdb, info, ICL_EMPTY);
}
icl_Free(t1);
icl_stFree(hostString);
return res;
} // end of com_ListenAt
/****************************************************************************
* Utility functions for com_ListenAt
****************************************************************************/
void
com_print_tcp_exception_help() {
#ifdef _WINDOWS
#else
printf("I've just attempted to listen on the specified port, but was unable\n");
printf("to gain control of it. This could be because there's already a\n");
printf("Facilitator, or some other program, making use of that port. Or, it\n");
printf("could be that a Facilitator using that port was just terminated. In\n");
printf("such cases, the port may be inaccessible for a brief period (usually\n");
printf("only a few seconds, but sometimes more). It may help to kill any\n");
printf("client agents which may still be connected to the defunct Facilitator.\n");
printf("If you think the specified port may now be accessible, enter \"y\" and\n");
printf("I'll try again. You may request retry any number of times.\n");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?