blob: 495516a3b675f45b246346d522c25ebc3eca663a [file] [log] [blame]
yangsu@google.comc5aeccd2011-07-17 14:42:08 +00001#ifndef SkNetIO_DEFINED
2#define SkNetIO_DEFINED
3
4#include <netinet/in.h>
5#include <sys/socket.h>
6#include "SkTypes.h"
7#include "SkStream.h"
8/* PACKET and HEADER Format */
9#define PACKET_SIZE 1024
10#define HEADER_SIZE 20
11#define CONTENT_SIZE 1004
12
13#define DEFAULT_PORT 15555
14
15#define NONBLOCKING_SOCKETS
16#ifdef NONBLOCKING_SOCKETS
17#define MAX_CLIENTS 3
18#else
19#define MAX_CLIENTS 1
20#endif
21
22class SkSocket {
23public:
24 SkSocket();
25 ~SkSocket();
26
27 enum State {
28 kError_state,
29 kBegin_state,
30 kIncomplete_state,
31 kDone_state
32 };
33
34 enum DataType {
35 kPipeAppend_type,
36 kPipeReplace_type,
37 kString_type,
38 kInt_type
39 };
40 /*
41 * Write data to the socket. Data is a pointer to the beginning of the data
42 * to be sent and dataSize specifies the number of bytes to send. This
43 * method will spread the data across multiple packets if the data can't all
44 * fit in a single packet. The method will write all the data to each of the
45 * socket's open connections until all the bytes have been successfully sent
46 * and return total the number of bytes written to all clients, unless there
47 * was an error during the transfer, in which case the method returns -1.
48 * For blocking sockets, write will block indefinitely if the socket at the
49 * other end of the connection doesn't receive any data.
50 */
51 int writePacket(void* data, size_t size, DataType type = kPipeAppend_type);
52
53 /*
54 * Read a logical packet from socket. The data read will be stored
55 * sequentially in the dataArray. This method will keep running until all
56 * the data in a logical chunk has been read (assembling multiple partial
57 * packets if necessary) and return the number of bytes successfully read,
58 * unless there was an error, in which case the method returns -1. NOTE: For
59 * nonblocking sockets, read will return 0 if there's nothing to read. For
60 * blocking sockets, read will block indefinitely if the socket doesn't
61 * receive any data.
62 * once
63 */
64 int readPacket(void (*onRead)(const void* data, size_t size,int cid,
65 DataType type, void*), void* context);
66
67 // Suspend network transfers until resume() is called. Leaves all
68 // connections in tact.
69 void suspendAll() { fReadSuspended = fWriteSuspended = true; }
70 // Resume all network transfers.
71 void resumeAll() { fReadSuspended = fWriteSuspended = false; }
72 // Other helper functions
73 void suspendRead() { fReadSuspended = true; }
74 void resumeRead() { fReadSuspended = false; }
75 void suspendWrite() { fWriteSuspended = true; }
76 void resumeWrite() { fWriteSuspended = false; }
77
78protected:
79 struct header {
80 bool done;
81 int bytes;
82 DataType type;
83 };
84
85 // Create a socket and return its file descriptor. Returns -1 on failure
86 int createSocket();
87 // Close the socket specifies by the socket file descriptor passed in. Will
88 // update fMaxfd
89 void closeSocket(int sockfd);
90
91 // called when a broken or terminated connection has been detected. Closes
92 // the socket file descriptor and removes it from the master set by default.
93 // Override to handle broken connections differently
94 virtual void onFailedConnection(int sockfd);
95
96 // set the socket specified by the socket file descriptor as nonblocking
97 void setNonBlocking(int sockfd);
98 // add the socket specified by the socket file descriptor to the master
99 // file descriptor set, which is used to in the select() to detect new data
100 // or connections
101 void addToMasterSet(int sockfd);
102
103 bool fConnected;
104 bool fReady;
105 bool fReadSuspended;
106 bool fWriteSuspended;
107 int fMaxfd;
108 int fPort;
109 int fSockfd;
110 // fMasterSet contains all the file descriptors to be used for read/write.
111 // For clients, this will only contain fSockfd. For servers, this will
112 // contain all the file descriptors associated with established connections
113 // to clients
114 fd_set fMasterSet;
115 timeval fTimeout;
116};
117
118/*
119 * TCP server. Can accept simultaneous connections to multiple SkTCPClients and
120 * read/write data back and forth using read/writePacket calls. Port number can
121 * be specified, but make sure that the clients use the same port for connections
122 */
123class SkTCPServer : public SkSocket {
124public:
125 SkTCPServer(int port = DEFAULT_PORT);
126 ~SkTCPServer();
127
128 // accept any incoming connections to the server, will only accept a limited
129 // number of clients (specified by MAX_CLIENTS) at a time. Returns -1 on
130 // error. For blocking sockets, this method will block until a client has
131 // connected
132 int acceptIncomingConnections();
133
134 // disconnect all connections to clients. Returns -1 on error
135 int disconnectAllConnections();
136private:
137 typedef SkSocket INHERITED;
138};
139
140/*
141 * TCP client. Will connect to the server specified in the constructor. If a
142 * port number is specified, make sure that it's the same as the port number on
143 * the server
144 */
145class SkTCPClient : public SkSocket {
146public:
147 SkTCPClient(const char* hostname, int port = DEFAULT_PORT);
148
149 // Connect to server. Returns -1 on error or failure. Make sure to call this
150 // before any read/write operation to make sure that a connection is
151 // is established or is still open and reconnect to server if necessary. For
152 // blocking sockets, this method will block until the connection is accepted
153 // by the server.
154 int connectToServer();
155
156 // Client needs to recreate the socket when a connection is broken because
157 // connect can only be called successfully once.
158 virtual void onFailedConnection(int sockfd);
159private:
160 sockaddr_in fServerAddr;
161 typedef SkSocket INHERITED;
162};
163
164#endif