blob: 8d85446ecc6a54459588c1f29c1a787381f4d28c [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +00007#ifndef SkNetIO_DEFINED
8#define SkNetIO_DEFINED
9
10#include <netinet/in.h>
11#include <sys/socket.h>
12#include "SkTypes.h"
13#include "SkStream.h"
yangsu@google.comf3493f02011-08-08 15:12:05 +000014
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000015/* PACKET and HEADER Format */
16#define PACKET_SIZE 1024
17#define HEADER_SIZE 20
18#define CONTENT_SIZE 1004
19
20#define DEFAULT_PORT 15555
yangsu@google.comf3493f02011-08-08 15:12:05 +000021#define MAX_WAITING_CLIENTS 3
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000022#define NONBLOCKING_SOCKETS
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000023
24class SkSocket {
25public:
26 SkSocket();
robertphillips@google.com05141c22012-04-27 12:54:01 +000027 virtual ~SkSocket();
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000028
29 enum State {
30 kError_state,
31 kBegin_state,
32 kIncomplete_state,
33 kDone_state
34 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000035
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000036 enum DataType {
37 kPipeAppend_type,
38 kPipeReplace_type,
39 kString_type,
40 kInt_type
41 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000042
yangsu@google.comf3493f02011-08-08 15:12:05 +000043 bool isConnected() { return fConnected; }
44 /**
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000045 * Write data to the socket. Data is a pointer to the beginning of the data
46 * to be sent and dataSize specifies the number of bytes to send. This
47 * method will spread the data across multiple packets if the data can't all
48 * fit in a single packet. The method will write all the data to each of the
49 * socket's open connections until all the bytes have been successfully sent
50 * and return total the number of bytes written to all clients, unless there
51 * was an error during the transfer, in which case the method returns -1.
52 * For blocking sockets, write will block indefinitely if the socket at the
53 * other end of the connection doesn't receive any data.
rmistry@google.comd6176b02012-08-23 18:14:13 +000054 * NOTE: This method guarantees that all of the data will be sent unless
55 * there was an error, so it may block temporarily when the write buffer is
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000056 * full
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000057 */
58 int writePacket(void* data, size_t size, DataType type = kPipeAppend_type);
rmistry@google.comd6176b02012-08-23 18:14:13 +000059
yangsu@google.comf3493f02011-08-08 15:12:05 +000060 /**
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000061 * Read a logical packet from socket. The data read will be stored
62 * sequentially in the dataArray. This method will keep running until all
63 * the data in a logical chunk has been read (assembling multiple partial
64 * packets if necessary) and return the number of bytes successfully read,
yangsu@google.comf3493f02011-08-08 15:12:05 +000065 * unless there was an error, in which case the method returns -1. \For
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000066 * nonblocking sockets, read will return 0 if there's nothing to read. For
67 * blocking sockets, read will block indefinitely if the socket doesn't
68 * receive any data.
rmistry@google.comd6176b02012-08-23 18:14:13 +000069 * NOTE: This method guarantees that all the data in a logical packet will
yangsu@google.comef7bdfa2011-08-12 14:27:47 +000070 * be read so it may block temporarily if it's waiting for parts of a
yangsu@google.comf3493f02011-08-08 15:12:05 +000071 * packet
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000072 */
rmistry@google.comd6176b02012-08-23 18:14:13 +000073 int readPacket(void (*onRead)(int cid, const void* data, size_t size,
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000074 DataType type, void*), void* context);
75
yangsu@google.comf3493f02011-08-08 15:12:05 +000076 /**
77 * Suspend network transfers until resume() is called. Leaves all
rmistry@google.comd6176b02012-08-23 18:14:13 +000078 * connections in tact.
yangsu@google.comf3493f02011-08-08 15:12:05 +000079 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000080 void suspendAll() { fReadSuspended = fWriteSuspended = true; }
yangsu@google.comf3493f02011-08-08 15:12:05 +000081 /**
82 * Resume all network transfers.
83 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000084 void resumeAll() { fReadSuspended = fWriteSuspended = false; }
yangsu@google.comf3493f02011-08-08 15:12:05 +000085 /**
86 * Other helper functions
87 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +000088 void suspendRead() { fReadSuspended = true; }
89 void resumeRead() { fReadSuspended = false; }
90 void suspendWrite() { fWriteSuspended = true; }
91 void resumeWrite() { fWriteSuspended = false; }
92
93protected:
94 struct header {
95 bool done;
96 int bytes;
97 DataType type;
98 };
99
yangsu@google.comf3493f02011-08-08 15:12:05 +0000100 /**
101 * Create a socket and return its file descriptor. Returns -1 on failure
102 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000103 int createSocket();
rmistry@google.comd6176b02012-08-23 18:14:13 +0000104
yangsu@google.comf3493f02011-08-08 15:12:05 +0000105 /**
106 * Close the socket specified by the socket file descriptor argument. Will
107 * update fMaxfd and working set properly
108 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000109 void closeSocket(int sockfd);
110
yangsu@google.comf3493f02011-08-08 15:12:05 +0000111 /**
112 * Called when a broken or terminated connection has been detected. Closes
113 * the socket file descriptor and removes it from the master set by default.
114 * Override to handle broken connections differently
115 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000116 virtual void onFailedConnection(int sockfd);
117
yangsu@google.comf3493f02011-08-08 15:12:05 +0000118 /**
119 * Set the socket specified by the socket file descriptor as nonblocking
120 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000121 void setNonBlocking(int sockfd);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000122
yangsu@google.comf3493f02011-08-08 15:12:05 +0000123 /**
124 * Add the socket specified by the socket file descriptor to the master
125 * file descriptor set, which is used to in the select() to detect new data
126 * or connections
127 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000128 void addToMasterSet(int sockfd);
129
130 bool fConnected;
131 bool fReady;
132 bool fReadSuspended;
133 bool fWriteSuspended;
134 int fMaxfd;
135 int fPort;
136 int fSockfd;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000137
138 /**
yangsu@google.comf3493f02011-08-08 15:12:05 +0000139 * fMasterSet contains all the file descriptors to be used for read/write.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000140 * For clients, this only contains the client socket. For servers, this
yangsu@google.comf3493f02011-08-08 15:12:05 +0000141 * contains all the file descriptors associated with established connections
142 * to clients
143 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000144 fd_set fMasterSet;
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000145};
146
147/*
148 * TCP server. Can accept simultaneous connections to multiple SkTCPClients and
149 * read/write data back and forth using read/writePacket calls. Port number can
yangsu@google.comf3493f02011-08-08 15:12:05 +0000150 * be specified, but make sure that client/server use the same port
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000151 */
152class SkTCPServer : public SkSocket {
153public:
154 SkTCPServer(int port = DEFAULT_PORT);
robertphillips@google.com05141c22012-04-27 12:54:01 +0000155 virtual ~SkTCPServer();
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000156
yangsu@google.comf3493f02011-08-08 15:12:05 +0000157 /**
158 * Accept any incoming connections to the server, will accept 1 connection
rmistry@google.comd6176b02012-08-23 18:14:13 +0000159 * at a time. Returns -1 on error. For blocking sockets, this method will
yangsu@google.comf3493f02011-08-08 15:12:05 +0000160 * block until a client calls connectToServer()
161 */
162 int acceptConnections();
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000163
yangsu@google.comf3493f02011-08-08 15:12:05 +0000164 /**
165 * Disconnect all connections to clients. Returns -1 on error
166 */
167 int disconnectAll();
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000168private:
169 typedef SkSocket INHERITED;
170};
171
172/*
173 * TCP client. Will connect to the server specified in the constructor. If a
174 * port number is specified, make sure that it's the same as the port number on
175 * the server
176 */
177class SkTCPClient : public SkSocket {
178public:
179 SkTCPClient(const char* hostname, int port = DEFAULT_PORT);
180
yangsu@google.comf3493f02011-08-08 15:12:05 +0000181 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000182 * Connect to server. Returns -1 on error or failure. Call this to connect
183 * or reconnect to the server. For blocking sockets, this method will block
yangsu@google.comf3493f02011-08-08 15:12:05 +0000184 * until the connection is accepted by the server.
185 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000186 int connectToServer();
yangsu@google.comf3493f02011-08-08 15:12:05 +0000187protected:
188 /**
rmistry@google.comd6176b02012-08-23 18:14:13 +0000189 * Client needs to recreate the socket when a connection is broken because
190 * connect can only be called successfully once.
yangsu@google.comf3493f02011-08-08 15:12:05 +0000191 */
yangsu@google.comc5aeccd2011-07-17 14:42:08 +0000192 virtual void onFailedConnection(int sockfd);
193private:
194 sockaddr_in fServerAddr;
195 typedef SkSocket INHERITED;
196};
197
198#endif