You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.2 KiB
199 lines
6.2 KiB
/*
|
|
* 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 "SkTypes.h"
|
|
#include "SkStream.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
|