?? gameswf_xmlsocket.cpp
字號:
// gameswf_xml.h -- Rob Savoye <rob@welcomehome.org> 2005// This source code has been donated to the Public Domain. Do// whatever you want with it.#include <SDL.h>#include "base/utility.h"#include "gameswf_log.h"#include "gameswf_xml.h"#include "gameswf_xmlsocket.h"#include "gameswf_timers.h"#ifdef HAVE_LIBXML#include <sys/types.h>#ifdef HAVE_WINSOCK# include <WinSock2.h># include <windows.h># include <fcntl.h># include <sys/stat.h># include <io.h>#else# include <sys/time.h># include <sys/fcntl.h># include <unistd.h># include <sys/select.h># include <netinet/in.h># include <arpa/inet.h># include <sys/socket.h># include <netdb.h># include <errno.h># include <sys/param.h># include <sys/select.h>#endif#ifndef MAXHOSTNAMELEN#define MAXHOSTNAMELEN 256#endifint xml_fd = 0; // FIXME: This file descriptor is used by // XML::checkSocket() when called from the main // processing loop. namespace gameswf{const int SOCKET_DATA = 1;const int INBUF = 10000;XMLSocket::XMLSocket(){ //log_msg("%s: \n", __FUNCTION__); _data = false; _xmldata = false; _closed = false; _connect = false; _processing = false; _port = 0; _sockfd = 0; xml_fd = 0;}XMLSocket::~XMLSocket(){ //log_msg("%s: \n", __FUNCTION__);}boolXMLSocket::connect(const char *host, int port){ struct sockaddr_in sock_in; fd_set fdset; struct timeval tval; int ret; int retries; char thishostname[MAXHOSTNAMELEN]; struct protoent *proto; if (port < 1024) { log_error("Can't connect to priviledged port #%d!\n", port); _connect = false; return false; } log_msg("%s: to host %s at port %d\n", __FUNCTION__, host, port); memset(&sock_in, 0, sizeof(struct sockaddr_in)); memset(&thishostname, 0, MAXHOSTNAMELEN); if (strlen(host) == 0) { if (gethostname(thishostname, MAXHOSTNAMELEN) == 0) { log_msg("The hostname for this machine is %s.\n", thishostname); } else { log_msg("Couldn't get the hostname for this machine!\n"); return false; } } const struct hostent *hent = ::gethostbyname(host); if (hent > 0) { ::memcpy(&sock_in.sin_addr, hent->h_addr, hent->h_length); } sock_in.sin_family = AF_INET; sock_in.sin_port = ntohs(static_cast<short>(port));#if 0 char ascip[32]; inet_ntop(AF_INET, &sock_in.sin_addr.s_addr, ascip, INET_ADDRSTRLEN); log_msg("The IP address for this client socket is %s\n", ascip);#endif proto = ::getprotobyname("TCP"); _sockfd = ::socket(PF_INET, SOCK_STREAM, proto->p_proto); if (_sockfd < 0) { log_error("unable to create socket : %s\n", strerror(errno)); _sockfd = -1; return false; } retries = 2; while (retries-- > 0) { // We use select to wait for the read file descriptor to be // active, which means there is a client waiting to connect. FD_ZERO(&fdset); FD_SET(_sockfd, &fdset); // Reset the timeout value, since select modifies it on return. To // block, set the timeout to zero. tval.tv_sec = 5; tval.tv_usec = 0; ret = ::select(_sockfd+1, &fdset, NULL, NULL, &tval); // If interupted by a system call, try again if (ret == -1 && errno == EINTR) { log_msg("The connect() socket for fd #%d was interupted by a system call!\n", _sockfd); continue; } if (ret == -1) { log_msg("The connect() socket for fd #%d never was available for writing!\n", _sockfd);#ifdef HAVE_WINSOCK ::shutdown(_sockfd, SHUT_BOTH);#else ::shutdown(_sockfd, SHUT_RDWR);#endif _sockfd = -1; return false; } if (ret == 0) { log_error("The connect() socket for fd #%d timed out waiting to write!\n", _sockfd); continue; } if (ret > 0) { ret = ::connect(_sockfd, reinterpret_cast<struct sockaddr *>(&sock_in), sizeof(sock_in)); if (ret == 0) { log_msg("\tport %d at IP %s for fd #%d\n", port, ::inet_ntoa(sock_in.sin_addr), _sockfd); _connect = true; return true; } if (ret == -1) { log_msg("The connect() socket for fd #%d never was available for writing!\n", _sockfd); _sockfd = -1; return false; } } } // ::close(_sockfd); // return false; printf("\tConnected at port %d on IP %s for fd #%d\n", port, ::inet_ntoa(sock_in.sin_addr), _sockfd); #ifndef HAVE_WINSOCK fcntl(_sockfd, F_SETFL, O_NONBLOCK);#endif xml_fd = _sockfd; // FIXME: This file descriptor is used by // XML::checkSocket() when called from // the main processing loop. _connect = true; return true;}voidXMLSocket::close(){ log_msg("%s: \n", __FUNCTION__); // Since the return code from close() doesn't get used by Shockwave, // we don't care either. if (_sockfd > 0) { ::close(_sockfd); }}// Return true if there is data in the socket, otherwise return false.boolXMLSocket::anydata(char **msgs){ //printf("%s: \n", __FUNCTION__); return anydata(_sockfd, msgs);}bool XMLSocket::processingData(){ //printf("%s: processing flags is is %d\n", __FUNCTION__, _processing); return _processing;}void XMLSocket::processing(bool x){ //printf("%s: set processing flag to %d\n", __FUNCTION__, x); _processing = x;}boolXMLSocket::anydata(int fd, char **msgs){ fd_set fdset; struct timeval tval; int ret = 0; char buf[INBUF]; char *packet; int retries = 10; char *ptr, *eom; int pos; int cr, index = 0; static char *leftover = 0; int adjusted_size; //log_msg("%s: \n", __FUNCTION__); if (fd <= 0) { return false; } //msgs = (char **)realloc(msgs, sizeof(char *)); while (retries-- > 0) { FD_ZERO(&fdset); FD_SET(fd, &fdset); tval.tv_sec = 1; tval.tv_usec = 10; ret = ::select(fd+1, &fdset, NULL, NULL, &tval); // If interupted by a system call, try again if (ret == -1 && errno == EINTR) { log_msg("The socket for fd #%d was interupted by a system call!\n", fd); continue; } if (ret == -1) { log_error("The socket for fd #%d never was available!\n", fd); return false; } if (ret == 0) { //log_msg("There is no data in the socket for fd #%d!\n", fd); return false; } if (ret > 0) { //log_msg("There is data in the socket for fd #%d!\n", fd); //break; } memset(buf, 0, INBUF); ret = ::read(_sockfd, buf, INBUF-2); cr = strlen(buf); //log_msg("%s: read %d bytes, first msg terminates at %d\n", __FUNCTION__, ret, cr); //log_msg("%s: read (%d,%d) %s\n", __FUNCTION__, buf[0], buf[1], buf); ptr = buf; // If we get a single XML message, do less work if (ret == cr + 1) { adjusted_size = memadjust(ret + 1); packet = new char[adjusted_size]; //printf("Packet size is %d at %p\n", ret + 1, packet); memset(packet, 0, adjusted_size); strcpy(packet, ptr); eom = strrchr(packet, '\n'); // drop the CR off the end if there is one if (eom) { *eom = 0; } //data.push_back(packet); msgs[index] = packet; msgs[index+1] = 0; //printf("%d: Pushing Packet of size %d at %p\n", __LINE__, strlen(packet), packet); processing(false); return true; } // If we get multiple messages in a single transmission, break the buffer // into separate messages. while (strchr(ptr, '\n') > 0) { if (leftover) { processing(false); //printf("%s: The remainder is: \"%s\"\n", __FUNCTION__, leftover); //printf("%s: The rest of the message is: \"%s\"\n", __FUNCTION__, ptr); adjusted_size = memadjust(cr + strlen(leftover) + 1); packet = new char[adjusted_size]; memset(packet, 0, adjusted_size); strcpy(packet, leftover); strcat(packet, ptr); eom = strrchr(packet, '\n'); // drop the CR off the end there is one if (eom) { *eom = 0; } //printf("%s: The whole message is: \"%s\"\n", __FUNCTION__, packet); ptr = strchr(ptr, '\n') + 2; // messages are delimited by a "\n\0" delete leftover; leftover = 0; } else { adjusted_size = memadjust(cr + 1); packet = new char[adjusted_size]; memset(packet, 0, adjusted_size); strcpy(packet, ptr); ptr += cr + 1; } // end of if remainder if (*packet == '<') { //printf("%d: Pushing Packet #%d of size %d at %p: %s\n", __LINE__, // data.size(), strlen(packet), packet, packet); eom = strrchr(packet, '\n'); // drop the CR off the end there is one if (eom) { *eom = 0; } //printf("Allocating new packet at %p\n", packet); //data.push_back(packet); msgs[index++] = packet; } else { log_error("Throwing out partial packet %s\n", packet); } //log_msg("%d messages in array now\n", data.size()); cr = strlen(ptr); } // end of while (cr) if (strlen(ptr) > 0) { leftover = new char[strlen(ptr) + 1]; strcpy(leftover, ptr); processing(true); //printf("%s: Adding remainder: \"%s\"\n", __FUNCTION__, leftover); } processing(false); printf("Returning %d messages\n", index); return true; } // end of while (retires) return true;}boolXMLSocket::send(tu_string str){ //log_msg("%s: \n", __FUNCTION__); //str += tu_string( "\0", 1); str += '\0'; int ret = write(_sockfd, str.c_str(), str.size()); //log_msg("%s: sent %d bytes, data was %s\n", __FUNCTION__, ret, str.c_str()); if (ret == str.size()) { return true; } else { return false; }}// CallbacksvoidXMLSocket::onClose(tu_string str){ log_msg("%s: \n", __FUNCTION__);}voidXMLSocket::onConnect(tu_string str){ log_msg("%s: \n", __FUNCTION__);}voidXMLSocket::onData(tu_string str){ log_msg("%s: \n", __FUNCTION__);}voidXMLSocket::onXML(tu_string str){ log_msg("%s: \n", __FUNCTION__);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -