Remove experimental/Networking code
Bug: chromium:1101491 Bug: b/161896447 The motivation here was to remove uses of the word "master". But this code is in experimental/, and it doesn't look to be used (based on code searches in Chromium, Android, and Google3). The last meaningful changes were in 2011; other changes have just been upkeep. Change-Id: I5993402008877ec8c12c0bca4cf09c02dc6de9ec Reviewed-on: https://skia-review.googlesource.com/c/skia/+/305965 Auto-Submit: Leon Scroggins <scroggo@google.com> Commit-Queue: Mike Klein <mtklein@google.com> Reviewed-by: Mike Klein <mtklein@google.com>
This commit is contained in:
parent
1ff07066f9
commit
487d9d1908
@ -1,358 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include "experimental/Networking/SkSockets.h"
|
||||
#include "include/core/SkData.h"
|
||||
|
||||
SkSocket::SkSocket() {
|
||||
fMaxfd = 0;
|
||||
FD_ZERO(&fMasterSet);
|
||||
fConnected = false;
|
||||
fReady = false;
|
||||
fReadSuspended = false;
|
||||
fWriteSuspended = false;
|
||||
fSockfd = this->createSocket();
|
||||
}
|
||||
|
||||
SkSocket::~SkSocket() {
|
||||
this->closeSocket(fSockfd);
|
||||
shutdown(fSockfd, 2); //stop sending/receiving
|
||||
}
|
||||
|
||||
int SkSocket::createSocket() {
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) {
|
||||
SkDebugf("ERROR opening socket\n");
|
||||
return -1;
|
||||
}
|
||||
int reuse = 1;
|
||||
|
||||
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {
|
||||
SkDebugf("error: %s\n", strerror(errno));
|
||||
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;
|
||||
|
||||
close(sockfd);
|
||||
//SkDebugf("Closed fd:%d\n", 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;
|
||||
}
|
||||
|
||||
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)(int, const void*, size_t, DataType,
|
||||
void*), void* context) {
|
||||
if (!fConnected || !fReady || NULL == onRead || NULL == context
|
||||
|| 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 tries\n",
|
||||
// h.done, h.bytes, fSockfd, attempts);
|
||||
stream.write(packet + HEADER_SIZE, h.bytes);
|
||||
bytesReadInPacket = 0;
|
||||
attempts = 0;
|
||||
bytesReadInTransfer += h.bytes;
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
onRead(i, NULL, 0, h.type, context);
|
||||
this->onFailedConnection(i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bytesReadInTransfer > 0) {
|
||||
SkData* data = stream.copyToData();
|
||||
SkASSERT(data->size() == bytesReadInTransfer);
|
||||
onRead(i, data->data(), data->size(), 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;
|
||||
|
||||
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 trying
|
||||
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)
|
||||
continue; //incomplete packet, keep trying
|
||||
|
||||
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)
|
||||
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: %s\n", strerror(errno));
|
||||
fReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
SkTCPServer::~SkTCPServer() {
|
||||
this->disconnectAll();
|
||||
}
|
||||
|
||||
int SkTCPServer::acceptConnections() {
|
||||
if (!fReady)
|
||||
return -1;
|
||||
|
||||
listen(fSockfd, MAX_WAITING_CLIENTS);
|
||||
int newfd;
|
||||
for (int i = 0; i < MAX_WAITING_CLIENTS; ++i) {
|
||||
#ifdef NONBLOCKING_SOCKETS
|
||||
fd_set workingSet;
|
||||
FD_ZERO(&workingSet);
|
||||
FD_SET(fSockfd, &workingSet);
|
||||
timeval timeout;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_usec = 0;
|
||||
int sel = select(fSockfd + 1, &workingSet, NULL, NULL, &timeout);
|
||||
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::disconnectAll() {
|
||||
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) { //cleanup and recreate socket
|
||||
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;
|
||||
}
|
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#ifndef SkNetIO_DEFINED
|
||||
#define SkNetIO_DEFINED
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include "include/core/SkStream.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
/* PACKET and HEADER Format */
|
||||
#define PACKET_SIZE 1024
|
||||
#define HEADER_SIZE 20
|
||||
#define CONTENT_SIZE 1004
|
||||
|
||||
#define DEFAULT_PORT 15555
|
||||
#define MAX_WAITING_CLIENTS 3
|
||||
#define NONBLOCKING_SOCKETS
|
||||
|
||||
class SkSocket {
|
||||
public:
|
||||
SkSocket();
|
||||
virtual ~SkSocket();
|
||||
|
||||
enum State {
|
||||
kError_state,
|
||||
kBegin_state,
|
||||
kIncomplete_state,
|
||||
kDone_state
|
||||
};
|
||||
|
||||
enum DataType {
|
||||
kPipeAppend_type,
|
||||
kPipeReplace_type,
|
||||
kString_type,
|
||||
kInt_type
|
||||
};
|
||||
|
||||
bool isConnected() { return fConnected; }
|
||||
/**
|
||||
* Write data to the socket. Data is a pointer to the beginning of the data
|
||||
* to be sent and dataSize specifies the number of bytes to send. This
|
||||
* method will spread the data across multiple packets if the data can't all
|
||||
* fit in a single packet. The method will write all the data to each of the
|
||||
* socket's open connections until all the bytes have been successfully sent
|
||||
* and return total the number of bytes written to all clients, unless there
|
||||
* was an error during the transfer, in which case the method returns -1.
|
||||
* For blocking sockets, write will block indefinitely if the socket at the
|
||||
* other end of the connection doesn't receive any data.
|
||||
* NOTE: This method guarantees that all of the data will be sent unless
|
||||
* there was an error, so it may block temporarily when the write buffer is
|
||||
* full
|
||||
*/
|
||||
int writePacket(void* data, size_t size, DataType type = kPipeAppend_type);
|
||||
|
||||
/**
|
||||
* Read a logical packet from socket. The data read will be stored
|
||||
* sequentially in the dataArray. This method will keep running until all
|
||||
* the data in a logical chunk has been read (assembling multiple partial
|
||||
* packets if necessary) and return the number of bytes successfully read,
|
||||
* unless there was an error, in which case the method returns -1. \For
|
||||
* nonblocking sockets, read will return 0 if there's nothing to read. For
|
||||
* blocking sockets, read will block indefinitely if the socket doesn't
|
||||
* receive any data.
|
||||
* NOTE: This method guarantees that all the data in a logical packet will
|
||||
* be read so it may block temporarily if it's waiting for parts of a
|
||||
* packet
|
||||
*/
|
||||
int readPacket(void (*onRead)(int cid, const void* data, size_t size,
|
||||
DataType type, void*), void* context);
|
||||
|
||||
/**
|
||||
* Suspend network transfers until resume() is called. Leaves all
|
||||
* connections in tact.
|
||||
*/
|
||||
void suspendAll() { fReadSuspended = fWriteSuspended = true; }
|
||||
/**
|
||||
* Resume all network transfers.
|
||||
*/
|
||||
void resumeAll() { fReadSuspended = fWriteSuspended = false; }
|
||||
/**
|
||||
* Other helper functions
|
||||
*/
|
||||
void suspendRead() { fReadSuspended = true; }
|
||||
void resumeRead() { fReadSuspended = false; }
|
||||
void suspendWrite() { fWriteSuspended = true; }
|
||||
void resumeWrite() { fWriteSuspended = false; }
|
||||
|
||||
protected:
|
||||
struct header {
|
||||
bool done;
|
||||
int bytes;
|
||||
DataType type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a socket and return its file descriptor. Returns -1 on failure
|
||||
*/
|
||||
int createSocket();
|
||||
|
||||
/**
|
||||
* Close the socket specified by the socket file descriptor argument. Will
|
||||
* update fMaxfd and working set properly
|
||||
*/
|
||||
void closeSocket(int sockfd);
|
||||
|
||||
/**
|
||||
* Called when a broken or terminated connection has been detected. Closes
|
||||
* the socket file descriptor and removes it from the master set by default.
|
||||
* Override to handle broken connections differently
|
||||
*/
|
||||
virtual void onFailedConnection(int sockfd);
|
||||
|
||||
/**
|
||||
* Set the socket specified by the socket file descriptor as nonblocking
|
||||
*/
|
||||
void setNonBlocking(int sockfd);
|
||||
|
||||
/**
|
||||
* Add the socket specified by the socket file descriptor to the master
|
||||
* file descriptor set, which is used to in the select() to detect new data
|
||||
* or connections
|
||||
*/
|
||||
void addToMasterSet(int sockfd);
|
||||
|
||||
bool fConnected;
|
||||
bool fReady;
|
||||
bool fReadSuspended;
|
||||
bool fWriteSuspended;
|
||||
int fMaxfd;
|
||||
int fPort;
|
||||
int fSockfd;
|
||||
|
||||
/**
|
||||
* fMasterSet contains all the file descriptors to be used for read/write.
|
||||
* For clients, this only contains the client socket. For servers, this
|
||||
* contains all the file descriptors associated with established connections
|
||||
* to clients
|
||||
*/
|
||||
fd_set fMasterSet;
|
||||
};
|
||||
|
||||
/*
|
||||
* TCP server. Can accept simultaneous connections to multiple SkTCPClients and
|
||||
* read/write data back and forth using read/writePacket calls. Port number can
|
||||
* be specified, but make sure that client/server use the same port
|
||||
*/
|
||||
class SkTCPServer : public SkSocket {
|
||||
public:
|
||||
SkTCPServer(int port = DEFAULT_PORT);
|
||||
virtual ~SkTCPServer();
|
||||
|
||||
/**
|
||||
* Accept any incoming connections to the server, will accept 1 connection
|
||||
* at a time. Returns -1 on error. For blocking sockets, this method will
|
||||
* block until a client calls connectToServer()
|
||||
*/
|
||||
int acceptConnections();
|
||||
|
||||
/**
|
||||
* Disconnect all connections to clients. Returns -1 on error
|
||||
*/
|
||||
int disconnectAll();
|
||||
private:
|
||||
typedef SkSocket INHERITED;
|
||||
};
|
||||
|
||||
/*
|
||||
* TCP client. Will connect to the server specified in the constructor. If a
|
||||
* port number is specified, make sure that it's the same as the port number on
|
||||
* the server
|
||||
*/
|
||||
class SkTCPClient : public SkSocket {
|
||||
public:
|
||||
SkTCPClient(const char* hostname, int port = DEFAULT_PORT);
|
||||
|
||||
/**
|
||||
* Connect to server. Returns -1 on error or failure. Call this to connect
|
||||
* or reconnect to the server. For blocking sockets, this method will block
|
||||
* until the connection is accepted by the server.
|
||||
*/
|
||||
int connectToServer();
|
||||
protected:
|
||||
/**
|
||||
* Client needs to recreate the socket when a connection is broken because
|
||||
* connect can only be called successfully once.
|
||||
*/
|
||||
virtual void onFailedConnection(int sockfd);
|
||||
private:
|
||||
sockaddr_in fServerAddr;
|
||||
typedef SkSocket INHERITED;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user