aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/SkSockets.cpp
diff options
context:
space:
mode:
authorGravatar yangsu@google.com <yangsu@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-07-17 14:42:08 +0000
committerGravatar yangsu@google.com <yangsu@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-07-17 14:42:08 +0000
commitc5aeccd8ba0ca51b03512ad5d473adeee82cb6f8 (patch)
tree8aaf5174ca2a1501209bfba753552863550c419e /experimental/SkSockets.cpp
parent1b2d6cc94d3f7fdce126e75a792cb1308ddbec3e (diff)
Updated iOSSampleApp to display FPS and display in OpenGL
git-svn-id: http://skia.googlecode.com/svn/trunk@1879 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental/SkSockets.cpp')
-rw-r--r--experimental/SkSockets.cpp356
1 files changed, 356 insertions, 0 deletions
diff --git a/experimental/SkSockets.cpp b/experimental/SkSockets.cpp
new file mode 100644
index 0000000000..70fbf75c23
--- /dev/null
+++ b/experimental/SkSockets.cpp
@@ -0,0 +1,356 @@
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "SkSockets.h"
+#include "SkData.h"
+
+SkSocket::SkSocket() {
+ fMaxfd = 0;
+ FD_ZERO(&fMasterSet);
+ fConnected = false;
+ fReady = false;
+ fReadSuspended = false;
+ fWriteSuspended = false;
+ fSockfd = this->createSocket();
+ fTimeout.tv_sec = 0;
+ fTimeout.tv_usec = 0;
+}
+
+SkSocket::~SkSocket() {
+ this->closeSocket(fSockfd);
+}
+
+int SkSocket::createSocket() {
+ int sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ //SkDebugf("ERROR opening socket\n");
+ return -1;
+ }
+#ifdef NONBLOCKING_SOCKETS
+ this->setNonBlocking(sockfd);
+#endif
+ //SkDebugf("Opened fd:%d\n", sockfd);
+ fReady = true;
+ return sockfd;
+}
+
+void SkSocket::closeSocket(int sockfd) {
+ if (!fReady)
+ return;
+
+ //SkDebugf("Closed fd:%d\n", sockfd);
+ close(sockfd);
+
+ if (FD_ISSET(sockfd, &fMasterSet)) {
+ FD_CLR(sockfd, &fMasterSet);
+ if (sockfd >= fMaxfd) {
+ while (FD_ISSET(fMaxfd, &fMasterSet) == false && fMaxfd > 0)
+ fMaxfd -= 1;
+ }
+ }
+ if (0 == fMaxfd) {
+ fConnected = false;
+ //SkDebugf("all connections closed\n");
+ }
+}
+
+void SkSocket::onFailedConnection(int sockfd) {
+ this->closeSocket(sockfd);
+}
+
+void SkSocket::setNonBlocking(int sockfd) {
+ int flags = fcntl(sockfd, F_GETFL);
+ fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
+}
+
+void SkSocket::addToMasterSet(int sockfd) {
+ FD_SET(sockfd, &fMasterSet);
+ if (sockfd > fMaxfd)
+ fMaxfd = sockfd;
+}
+
+int SkSocket::readPacket(void (*onRead)(const void*, size_t, int, DataType,
+ void*), void* context) {
+ if (!fConnected || !fReady || NULL == onRead || fReadSuspended)
+ return -1;
+
+ int totalBytesRead = 0;
+
+ char packet[PACKET_SIZE];
+ for (int i = 0; i <= fMaxfd; ++i) {
+ if (!FD_ISSET (i, &fMasterSet))
+ continue;
+
+ memset(packet, 0, PACKET_SIZE);
+ SkDynamicMemoryWStream stream;
+ int attempts = 0;
+ bool failure = false;
+ int bytesReadInTransfer = 0;
+ int bytesReadInPacket = 0;
+ header h;
+ h.done = false;
+ h.bytes = 0;
+ while (!h.done && fConnected && !failure) {
+ int retval = read(i, packet + bytesReadInPacket,
+ PACKET_SIZE - bytesReadInPacket);
+
+ ++attempts;
+ if (retval < 0) {
+#ifdef NONBLOCKING_SOCKETS
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ if (bytesReadInPacket > 0 || bytesReadInTransfer > 0)
+ continue; //incomplete packet or frame, keep tring
+ else
+ break; //nothing to read
+ }
+#endif
+ //SkDebugf("Read() failed with error: %s\n", strerror(errno));
+ failure = true;
+ break;
+ }
+
+ if (retval == 0) {
+ //SkDebugf("Peer closed connection or connection failed\n");
+ failure = true;
+ break;
+ }
+
+ SkASSERT(retval > 0);
+ bytesReadInPacket += retval;
+ if (bytesReadInPacket < PACKET_SIZE) {
+ //SkDebugf("Read %d/%d\n", bytesReadInPacket, PACKET_SIZE);
+ continue; //incomplete packet, keep trying
+ }
+
+ SkASSERT((bytesReadInPacket == PACKET_SIZE) && !failure);
+ memcpy(&h.done, packet, sizeof(bool));
+ memcpy(&h.bytes, packet + sizeof(bool), sizeof(int));
+ memcpy(&h.type, packet + sizeof(bool) + sizeof(int), sizeof(DataType));
+ if (h.bytes > CONTENT_SIZE || h.bytes <= 0) {
+ //SkDebugf("bad packet\n");
+ failure = true;
+ break;
+ }
+ //SkDebugf("read packet(done:%d, bytes:%d) from fd:%d in %d attempts\n",
+ // h.done, h.bytes, fSockfd, attempts);
+ stream.write(packet + HEADER_SIZE, h.bytes);\
+ bytesReadInPacket = 0;
+ attempts = 0;
+ bytesReadInTransfer += h.bytes;
+ }
+
+ if (failure) {
+ onRead(NULL, 0, i, h.type, context);
+ this->onFailedConnection(i);
+ continue;
+ }
+
+ if (bytesReadInTransfer > 0) {
+ SkData* data = stream.copyToData();
+ SkASSERT(data->size() == bytesReadInTransfer);
+ onRead(data->data(), data->size(), i, h.type, context);
+ data->unref();
+
+ totalBytesRead += bytesReadInTransfer;
+ }
+ }
+ return totalBytesRead;
+}
+
+int SkSocket::writePacket(void* data, size_t size, DataType type) {
+ if (size < 0|| NULL == data || !fConnected || !fReady || fWriteSuspended)
+ return -1;
+
+ int totalBytesWritten = 0;
+ header h;
+ char packet[PACKET_SIZE];
+ for (int i = 0; i <= fMaxfd; ++i) {
+ if (!FD_ISSET (i, &fMasterSet))
+ continue;
+
+ //Don't signal broken pipe
+ setsockopt(i, SOL_SOCKET, SO_NOSIGPIPE, (void*)1, sizeof(int));
+ int bytesWrittenInTransfer = 0;
+ int bytesWrittenInPacket = 0;
+ int attempts = 0;
+ bool failure = false;
+ while (bytesWrittenInTransfer < size && fConnected && !failure) {
+ memset(packet, 0, PACKET_SIZE);
+ h.done = (size - bytesWrittenInTransfer <= CONTENT_SIZE);
+ h.bytes = (h.done) ? size - bytesWrittenInTransfer : CONTENT_SIZE;
+ h.type = type;
+ memcpy(packet, &h.done, sizeof(bool));
+ memcpy(packet + sizeof(bool), &h.bytes, sizeof(int));
+ memcpy(packet + sizeof(bool) + sizeof(int), &h.type, sizeof(DataType));
+ memcpy(packet + HEADER_SIZE, (char*)data + bytesWrittenInTransfer,
+ h.bytes);
+
+ int retval = write(i, packet + bytesWrittenInPacket,
+ PACKET_SIZE - bytesWrittenInPacket);
+ attempts++;
+
+ if (retval < 0) {
+ if (errno == EPIPE) {
+ //SkDebugf("broken pipe, client closed connection");
+ failure = true;
+ break;
+ }
+#ifdef NONBLOCKING_SOCKETS
+ else if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ if (bytesWrittenInPacket > 0 || bytesWrittenInTransfer > 0)
+ continue; //incomplete packet or frame, keep tring
+ else
+ break; //client not available, skip current transfer
+ }
+#endif
+ else {
+ //SkDebugf("write(%d) failed with error:%s\n", i,
+ // strerror(errno));
+ failure = true;
+ break;
+ }
+ }
+
+ bytesWrittenInPacket += retval;
+ if (bytesWrittenInPacket < PACKET_SIZE) {
+ //SkDebugf("Wrote %d/%d\n", bytesWrittenInPacket, PACKET_SIZE);
+ continue; //incomplete packet, keep tring
+ }
+
+ SkASSERT(bytesWrittenInPacket == PACKET_SIZE);
+ //SkDebugf("wrote to packet(done:%d, bytes:%d) to fd:%d in %d tries\n",
+ // h.done, h.bytes, i, attempts);
+ bytesWrittenInTransfer += h.bytes;
+ bytesWrittenInPacket = 0;
+ attempts = 0;
+ }
+
+ if (failure) {
+ //SkDebugf("Failed to write to fd:%d, terminating connection\n", i);
+ this->onFailedConnection(i);
+ }
+
+ totalBytesWritten += bytesWrittenInTransfer;
+ }
+ return totalBytesWritten;
+}
+////////////////////////////////////////////////////////////////////////////////
+SkTCPServer::SkTCPServer(int port) {
+ sockaddr_in serverAddr;
+ serverAddr.sin_family = AF_INET;
+ serverAddr.sin_addr.s_addr = INADDR_ANY;
+ serverAddr.sin_port = htons(port);
+
+ if (bind(fSockfd, (sockaddr*)&serverAddr, sizeof(serverAddr)) < 0) {
+ //SkDebugf("ERROR on binding\n");
+ fReady = false;
+ }
+}
+
+SkTCPServer::~SkTCPServer() {
+ this->disconnectAllConnections();
+}
+
+int SkTCPServer::acceptIncomingConnections() {
+ if (!fReady)
+ return -1;
+// if (fConnected)
+// return 0;
+
+ listen(fSockfd, MAX_CLIENTS);
+ ////SkDebugf("Accepting Incoming connections\n");
+ int newfd;
+
+ for (int i = 0; i < MAX_CLIENTS; ++i) {
+#ifdef NONBLOCKING_SOCKETS
+ fd_set workingSet;
+ FD_ZERO(&workingSet);
+ FD_SET(fSockfd, &workingSet);
+ int sel = select(fSockfd + 1, &workingSet, NULL, NULL, &fTimeout);
+ if (sel < 0) {
+ //SkDebugf("select() failed with error %s\n", strerror(errno));
+ continue;
+ }
+ if (sel == 0) //select() timed out
+ continue;
+#endif
+ sockaddr_in clientAddr;
+ socklen_t clientLen = sizeof(clientAddr);
+ newfd = accept(fSockfd, (struct sockaddr*)&clientAddr, &clientLen);
+ if (newfd< 0) {
+ //SkDebugf("accept() failed with error %s\n", strerror(errno));
+ continue;
+ }
+ //SkDebugf("New incoming connection - %d\n", newfd);
+ fConnected = true;
+#ifdef NONBLOCKING_SOCKETS
+ this->setNonBlocking(newfd);
+#endif
+ this->addToMasterSet(newfd);
+ }
+ return 0;
+}
+
+
+int SkTCPServer::disconnectAllConnections() {
+ ////SkDebugf("disconnecting server\n");
+ if (!fConnected || !fReady)
+ return -1;
+ for (int i = 0; i <= fMaxfd; ++i)
+ {
+ if (FD_ISSET(i, &fMasterSet))
+ this->closeSocket(i);
+ }
+ fConnected = false;
+ return 0;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+SkTCPClient::SkTCPClient(const char* hostname, int port) {
+ //Add fSockfd since the client will be using it to read/write
+ this->addToMasterSet(fSockfd);
+
+ hostent* server = gethostbyname(hostname);
+ if (server) {
+ fServerAddr.sin_family = AF_INET;
+ memcpy((char*)&fServerAddr.sin_addr.s_addr, (char*)server->h_addr,
+ server->h_length);
+ fServerAddr.sin_port = htons(port);
+ }
+ else {
+ //SkDebugf("ERROR, no such host\n");
+ fReady = false;
+ }
+}
+
+void SkTCPClient::onFailedConnection(int sockfd) {
+ SkASSERT(sockfd == fSockfd);
+ this->closeSocket(fSockfd);
+ fSockfd = this->createSocket();
+ //Add fSockfd since the client will be using it to read/write
+ this->addToMasterSet(fSockfd);
+}
+
+int SkTCPClient::connectToServer() {
+ if (!fReady)
+ return -1;
+ if (fConnected)
+ return 0;
+
+ int conn = connect(fSockfd, (sockaddr*)&fServerAddr, sizeof(fServerAddr));
+ if (conn < 0) {
+#ifdef NONBLOCKING_SOCKETS
+ if (errno == EINPROGRESS || errno == EALREADY)
+ return conn;
+#endif
+ if (errno != EISCONN) {
+ //SkDebugf("error: %s\n", strerror(errno));
+ this->onFailedConnection(fSockfd);
+ return conn;
+ }
+ }
+ fConnected = true;
+ //SkDebugf("Succesfully reached server\n");
+ return 0;
+}