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 + -
显示快捷键?