7ebb440c266609a321211255f26cbbde14679fa0
[charm.git] / src / util / sockRoutines.h
1 /*****************************************************************************
2  * $Source$
3  * $Author$
4  * $Date$
5  * $Revision$
6  *****************************************************************************/
7
8 /**************************************************************************
9  *
10  * SKT - simple TCP and UDP socket routines.  
11  *  All port numbers are taken and returned 
12  *  in *host* byte order.  This means you can hardcode port
13  *  numbers in the code normally, and they will be properly 
14  *  translated even on little-endian machines.
15  *
16  *  SOCKET is just a #define for "unsigned int".
17  *
18  *  skt_ip_t is a flat bytes structure to hold an IP address--
19  *  this is either 4 bytes (for IPv4) or 16 bytes (for IPv6).
20  *  It is always in network byte order.
21  *
22  *  Errors are handled in the library by calling a user-overridable
23  *  abort function.
24  * 
25  * skt_ip_t skt_my_ip(void)
26  *   - return the IP address of the current machine.
27  *
28  * skt_ip_t skt_lookup_ip(const char *name)
29  *   - return the IP address of the given machine (DNS or dotted decimal).
30  *     Returns 0 on failure.
31  *
32  * char *skt_print_ip(char *dest,skt_ip_t addr)
33  *   - Print the given IP address to the given destination as
34  *     dotted decimal.  Dest must be at least 130 bytes long, 
35  *     and will be returned.
36  *
37  * int skt_ip_match(skt_ip_t a,skt_ip_t b)
38  *   - Return 1 if the given IP addresses are identical.
39  *
40  * SOCKET skt_datagram(unsigned int *port, int bufsize)
41  *
42  *   - creates a UDP datagram socket on the given port.  
43  *     Performs the whole socket/bind/getsockname procedure.  
44  *     Returns the actual port of the socket and
45  *     the file descriptor.  Bufsize, if nonzero, controls the amount
46  *     of buffer space the kernel sets aside for the socket.
47  *
48  * SOCKET skt_server(unsigned int *port)
49  *
50  *   - create a TCP server socket on the given port (0 for any port).  
51  *     Performs the whole socket/bind/listen procedure.  
52  *     Returns the actual port of the socket and the file descriptor.
53  *
54  * SOCKET skt_server_ip(unsigned int *port,skt_ip_t *ip)
55  *
56  *   - create a TCP server socket on the given port and IP
57  *     Use 0 for any port and _skt_invalid_ip for any IP.  
58  *     Performs the whole socket/bind/listen procedure.  
59  *     Returns the actual port and IP address of the socket 
60  *     and the file descriptor.
61  *
62  * SOCKET skt_accept(SOCKET src_fd,skt_ip_t *pip, unsigned int *port)
63  *
64  *   - accepts a TCP connection to the specified server socket.  Returns the
65  *     IP of the caller, the port number of the caller, and the file
66  *     descriptor to talk to the caller.
67  *
68  * SOCKET skt_connect(skt_ip_t ip, int port, int timeout)
69  *
70  *   - Opens a TCP connection to the specified server.  Returns a socket for
71  *     communication.
72  *
73  * void skt_close(SOCKET fd)
74  *   - Finishes communication on and closes the given socket.
75  *
76  * int skt_select1(SOCKET fd,int msec)
77  *   - Call select on the given socket, returning as soon as
78  *     the socket can recv or accept, or (failing that) in the given
79  *     number of milliseconds.  Returns 0 on timeout; 1 on readable.
80  *
81  * int skt_recvN(SOCKET fd,      void *buf,int nBytes)
82  * int skt_sendN(SOCKET fd,const void *buf,int nBytes)
83  *   - Blocking send/recv nBytes on the given socket.
84  *     Retries if possible (e.g., if interrupted), but aborts 
85  *     on serious errors.  Returns zero or an abort code.
86  *
87  * int skt_sendV(SOCKET fd,int nBuffers,void **buffers,int *lengths)
88  *   - Blocking call to write from several buffers.  This is much more
89  *     performance-critical than read-from-several buffers, because 
90  *     individual sends go out as separate network packets, and include
91  *     a (35 ms!) timeout for subsequent short messages.  Don't use more
92  *     than 8 buffers.
93  * 
94  * void skt_set_idle(idleFunc f)
95  *   - Specify a routine to be called while waiting for the network.
96  *     Replaces any previous routine.
97  * 
98  * void skt_set_abort(abortFunc f)
99  *   - Specify a routine to be called when an unrecoverable
100  *     (i.e., non-transient) socket error is encountered.
101  *     The default is to log the message to stderr and call exit(1).
102  *
103  **************************************************************************/
104 #ifndef __SOCK_ROUTINES_H
105 #define __SOCK_ROUTINES_H
106
107 #include "conv-config.h" /*<- for CMK_NO_SOCKETS*/
108
109 #ifdef CMK_NO_SOCKETS
110 #define SOCKET int
111 #define SOCKET_ERROR (-1)
112 #define INVALID_SOCKET (SOCKET)(~0)
113 typedef struct {int tag;} skt_ip_t;
114
115 #else /*Use actual sockets*/
116
117 /*Preliminaries*/
118 #if defined(_WIN32) && ! defined(__CYGWIN__)
119   /*For windows systems:*/
120 #include <winsock.h>
121 static void sleep(int secs) {Sleep(1000*secs);}
122
123 #else
124   /*For non-windows (UNIX) systems:*/
125 #include <sys/types.h>
126 #include <sys/time.h>
127 #include <sys/socket.h>
128 #include <netinet/in.h>
129 #include <arpa/inet.h>
130 #include <netdb.h>
131 #include <unistd.h>
132 #include <fcntl.h>
133
134 #ifndef SOCKET
135 #  define SOCKET int
136 #  define INVALID_SOCKET (SOCKET)(~0)
137 #  define SOCKET_ERROR (-1)
138 #endif /*def SOCKET*/
139
140 #endif /*WIN32*/
141
142 #ifdef __cplusplus
143 extern "C" {
144 #endif
145
146 /*Initialization*/
147 void skt_init(void);
148
149 /*Error and idle handling*/
150 typedef void (*skt_idleFn)(void);
151 typedef int (*skt_abortFn)(int errCode,const char *msg);
152 void skt_set_idle(skt_idleFn f);
153 skt_abortFn skt_set_abort(skt_abortFn f);
154
155 /*DNS*/
156 typedef struct { /*IPv4 IP address*/
157         unsigned char data[4];
158 } skt_ip_t;
159 extern skt_ip_t _skt_invalid_ip;
160 skt_ip_t skt_my_ip(void);
161 skt_ip_t skt_lookup_ip(const char *name);
162 skt_ip_t skt_innode_my_ip(void);        /* inner node version */
163 skt_ip_t skt_innode_lookup_ip(const char *name);
164
165 char *skt_print_ip(char *dest,skt_ip_t addr);
166 int skt_ip_match(skt_ip_t a,skt_ip_t b);
167 struct sockaddr_in skt_build_addr(skt_ip_t IP,int port);
168
169 /*UDP*/
170 SOCKET skt_datagram(unsigned int *port, int bufsize);
171
172 /*TCP*/
173 SOCKET skt_server(unsigned int *port);
174 SOCKET skt_server_ip(unsigned int *port,skt_ip_t *ip);
175 SOCKET skt_accept(SOCKET src_fd, skt_ip_t *pip, unsigned int *port);
176 SOCKET skt_connect(skt_ip_t ip, int port, int timeout);
177
178 /*Utility*/
179 void skt_close(SOCKET fd);
180 int skt_select1(SOCKET fd,int msec);
181 void skt_setSockBuf(SOCKET skt, int bufsize);
182
183 /*Blocking Send/Recv*/
184 int skt_sendN(SOCKET hSocket,const void *pBuff,int nBytes);
185 int skt_recvN(SOCKET hSocket,      void *pBuff,int nBytes);
186 int skt_sendV(SOCKET fd,int nBuffers,const void **buffers,int *lengths);
187
188 #ifdef __cplusplus
189 };
190 #endif
191
192 #endif /*!CMK_NO_SOCKETS*/
193
194 /***********************************
195 Conv-host messages: these are a simple
196 binary format message, with the usual header,
197 then data arrangement.
198
199 A fundamental data type is a ChMessageInt_t,
200 a simple 4-byte big-endian (network byte order)
201 integer.  Routines are provided to read/write
202 these integers on all platforms, regardless of 
203 endian-ness or native integer size.
204
205  ChMessage_recv reads a ChMessage on a socket.
206 The ChMessage->data field is allocated to contain
207 the entire message, and the header is filled out
208 with the received fields.  You may keep or dispose 
209 of the message memory with ChMessage_free.
210
211  ChMessageHeader_new fills out the fields of a header--
212 no allocation is done.
213
214  ChMessage_new fills out the header and allocates a 
215 data area of the given size.
216
217  ChMessage_send delivers the given ChMessage to a
218 socket.  You are still responsible for the ChMessage
219 memory (use ChMessage_free).  If you prefer, you may
220 receive sizeof(ChMessageHeader) header bytes, then 
221 header->len data bytes on any socket yourself.
222 */
223 #ifdef __cplusplus
224 extern "C" {
225 #endif
226
227 typedef struct {
228   unsigned char data[4];/*4-byte, big-endian integer*/
229 } ChMessageInt_t;
230 ChMessageInt_t ChMessageInt_new(unsigned int src); /*Convert integer to bytes*/
231 unsigned int ChMessageInt(ChMessageInt_t src); /*Convert bytes to integer*/
232
233 typedef struct {
234   unsigned char data[8];/*8-byte, big-endian integer*/
235 } ChMessageLong_t;
236 ChMessageLong_t ChMessageLong_new(CMK_TYPEDEF_UINT8 src); /*Convert long integer to bytes*/
237 CMK_TYPEDEF_UINT8 ChMessageLong(ChMessageLong_t src); /*Convert bytes to long integer*/
238
239 #define CH_TYPELEN 12 /*Maximum length for the message type field*/
240 typedef struct ChMessageHeader {
241   ChMessageInt_t len; /*Length of message to follow (not incl. header)*/
242   char type[CH_TYPELEN];/*Kind of message to follow:
243      (zero-terminated ASCII string) 
244      "getinfo" -- return a list of node IPs and control ports
245      "req" -- a CCS message
246      */
247 } ChMessageHeader;
248
249 typedef struct ChMessage {
250   ChMessageHeader header;
251   int len; /*Length of message data below*/
252   char *data; /*Pointer to heap-allocated data*/
253 } ChMessage;
254 int ChMessage_recv(SOCKET fd,ChMessage *dst);
255 int ChMessageHeader_recv(SOCKET fd,ChMessage *dst);
256 int ChMessageData_recv(SOCKET fd,ChMessage *dst);
257 void ChMessage_free(ChMessage *doomed);
258 void ChMessageHeader_new(const char *type,int len,ChMessageHeader *dst);
259 void ChMessage_new(const char *type,int len,ChMessage *dst);
260 int ChMessage_send(SOCKET fd,const ChMessage *src); /*You must free after send*/
261
262
263 #if CMK_USE_IBVERBS
264 typedef struct {
265         ChMessageInt_t lid,qpn,psn;
266 } ChInfiAddr ;
267 #endif
268
269
270 typedef struct {
271         ChMessageInt_t nPE; /* Number of compute processors on this node */
272 #if CMK_USE_IBVERBS
273         ChInfiAddr *qpList; /** An array of queue pair identifiers of length CmiNumNodes()-1*/
274 #endif
275         ChMessageInt_t dataport; /* node's data port (UDP or GM) */
276         ChMessageInt_t mach_id; /* node's hardware address (GM-only) */
277 #if CMK_USE_MX
278         ChMessageLong_t nic_id; /* node's NIC hardware address (MX-only) */
279 #endif
280         skt_ip_t IP; /* node's IP address */
281 } ChNodeinfo;
282
283 typedef struct {
284         ChMessageInt_t nodeNo;
285         ChNodeinfo info;
286 } ChSingleNodeinfo;
287
288 /******* CCS Message type (included here for convenience) *******/
289 #define CCS_HANDLERLEN 32 /*Maximum length for the handler field*/
290 typedef struct {
291   ChMessageInt_t len;/*Length of user data to follow header*/
292   ChMessageInt_t pe;/*Destination processor number*/
293   char handler[CCS_HANDLERLEN];/*Handler name for message to follow*/
294 } CcsMessageHeader;
295
296 #ifdef __cplusplus
297 };
298 #endif
299
300 #endif /*SOCK_ROUTINES_H*/
301