00001 /************************************************************************** 00002 * 00003 * SKT - simple TCP and UDP socket routines. 00004 * All port numbers are taken and returned 00005 * in *host* byte order. This means you can hardcode port 00006 * numbers in the code normally, and they will be properly 00007 * translated even on little-endian machines. 00008 * 00009 * SOCKET is just a #define for "unsigned int". 00010 * 00011 * skt_ip_t is a flat bytes structure to hold an IP address-- 00012 * this is either 4 bytes (for IPv4) or 16 bytes (for IPv6). 00013 * It is always in network byte order. 00014 * 00015 * Errors are handled in the library by calling a user-overridable 00016 * abort function. 00017 * 00018 * skt_ip_t skt_my_ip(void) 00019 * - return the IP address of the current machine. 00020 * 00021 * skt_ip_t skt_lookup_ip(const char *name) 00022 * - return the IP address of the given machine (DNS or dotted decimal). 00023 * Returns 0 on failure. 00024 * 00025 * char *skt_print_ip(char *dest,skt_ip_t addr) 00026 * - Print the given IP address to the given destination as 00027 * dotted decimal. Dest must be at least 130 bytes long, 00028 * and will be returned. 00029 * 00030 * int skt_ip_match(skt_ip_t a,skt_ip_t b) 00031 * - Return 1 if the given IP addresses are identical. 00032 * 00033 * SOCKET skt_datagram(unsigned int *port, int bufsize) 00034 * 00035 * - creates a UDP datagram socket on the given port. 00036 * Performs the whole socket/bind/getsockname procedure. 00037 * Returns the actual port of the socket and 00038 * the file descriptor. Bufsize, if nonzero, controls the amount 00039 * of buffer space the kernel sets aside for the socket. 00040 * 00041 * SOCKET skt_server(unsigned int *port) 00042 * 00043 * - create a TCP server socket on the given port (0 for any port). 00044 * Performs the whole socket/bind/listen procedure. 00045 * Returns the actual port of the socket and the file descriptor. 00046 * 00047 * SOCKET skt_server_ip(unsigned int *port,skt_ip_t *ip) 00048 * 00049 * - create a TCP server socket on the given port and IP 00050 * Use 0 for any port and _skt_invalid_ip for any IP. 00051 * Performs the whole socket/bind/listen procedure. 00052 * Returns the actual port and IP address of the socket 00053 * and the file descriptor. 00054 * 00055 * SOCKET skt_accept(SOCKET src_fd,skt_ip_t *pip, unsigned int *port) 00056 * 00057 * - accepts a TCP connection to the specified server socket. Returns the 00058 * IP of the caller, the port number of the caller, and the file 00059 * descriptor to talk to the caller. 00060 * 00061 * SOCKET skt_connect(skt_ip_t ip, int port, int timeout) 00062 * 00063 * - Opens a TCP connection to the specified server. Returns a socket for 00064 * communication. 00065 * 00066 * void skt_close(SOCKET fd) 00067 * - Finishes communication on and closes the given socket. 00068 * 00069 * int skt_select1(SOCKET fd,int msec) 00070 * - Call select on the given socket, returning as soon as 00071 * the socket can recv or accept, or (failing that) in the given 00072 * number of milliseconds. Returns 0 on timeout; 1 on readable. 00073 * 00074 * int skt_recvN(SOCKET fd, void *buf,int nBytes) 00075 * int skt_sendN(SOCKET fd,const void *buf,int nBytes) 00076 * - Blocking send/recv nBytes on the given socket. 00077 * Retries if possible (e.g., if interrupted), but aborts 00078 * on serious errors. Returns zero or an abort code. 00079 * 00080 * int skt_sendV(SOCKET fd,int nBuffers,void **buffers,int *lengths) 00081 * - Blocking call to write from several buffers. This is much more 00082 * performance-critical than read-from-several buffers, because 00083 * individual sends go out as separate network packets, and include 00084 * a (35 ms!) timeout for subsequent short messages. Don't use more 00085 * than 8 buffers. 00086 * 00087 * void skt_set_idle(idleFunc f) 00088 * - Specify a routine to be called while waiting for the network. 00089 * Replaces any previous routine. 00090 * 00091 * void skt_set_abort(abortFunc f) 00092 * - Specify a routine to be called when an unrecoverable 00093 * (i.e., non-transient) socket error is encountered. 00094 * The default is to log the message to stderr and call exit(1). 00095 * 00096 **************************************************************************/ 00097 #ifndef __SOCK_ROUTINES_H 00098 #define __SOCK_ROUTINES_H 00099 00100 #include "conv-config.h" /*<- for CMK_NO_SOCKETS*/ 00101 00102 #ifdef CMK_NO_SOCKETS 00103 #define SOCKET int 00104 #define SOCKET_ERROR (-1) 00105 #define INVALID_SOCKET (SOCKET)(~0) 00106 typedef struct { 00107 int tag; 00108 } skt_ip_t; 00109 00110 extern skt_ip_t _skt_invalid_ip; 00111 skt_ip_t skt_my_ip(void); 00112 00113 #else /*Use actual sockets*/ 00114 00115 /*Preliminaries*/ 00116 #if defined(_WIN32) 00117 /*For windows systems:*/ 00118 #include <winsock2.h> 00119 static void sleep(int secs) { Sleep(1000 * secs); } 00120 00121 #else 00122 /*For non-windows (UNIX) systems:*/ 00123 #include <sys/types.h> 00124 #include <sys/time.h> 00125 #include <sys/socket.h> 00126 #include <netinet/in.h> 00127 #include <netinet/tcp.h> 00128 #include <arpa/inet.h> 00129 #include <netdb.h> 00130 #include <unistd.h> 00131 #include <fcntl.h> 00132 00133 #ifndef SOCKET 00134 #define SOCKET int 00135 #define INVALID_SOCKET (SOCKET)(~0) 00136 #define SOCKET_ERROR (-1) 00137 #endif /*def SOCKET*/ 00138 00139 #endif /*_WIN32*/ 00140 00141 #ifdef __cplusplus 00142 extern "C" { 00143 #endif 00144 00145 /*Initialization*/ 00146 void skt_init(void); 00147 00148 /*Error and idle handling*/ 00149 typedef void (*skt_idleFn)(void); 00150 typedef int (*skt_abortFn)(SOCKET skt, int errCode, const char *msg); 00151 void skt_set_idle(skt_idleFn f); 00152 skt_abortFn skt_set_abort(skt_abortFn f); 00153 00154 /*DNS*/ 00155 typedef struct {/*IPv4 IP address*/ 00156 unsigned char data[4]; 00157 } skt_ip_t; 00158 extern skt_ip_t _skt_invalid_ip; 00159 skt_ip_t skt_my_ip(void); 00160 skt_ip_t skt_lookup_ip(const char *name); 00161 skt_ip_t skt_innode_my_ip(void); /* inner node version */ 00162 skt_ip_t skt_innode_lookup_ip(const char *name); 00163 00164 char *skt_print_ip(char *dest, skt_ip_t addr); 00165 int skt_ip_match(skt_ip_t a, skt_ip_t b); 00166 struct sockaddr_in skt_build_addr(skt_ip_t IP, int port); 00167 00168 /*UDP*/ 00169 SOCKET skt_datagram(unsigned int *port, int bufsize); 00170 00171 /*TCP*/ 00172 SOCKET skt_server(unsigned int *port); 00173 SOCKET skt_server_ip(unsigned int *port, skt_ip_t *ip); 00174 SOCKET skt_accept(SOCKET src_fd, skt_ip_t *pip, unsigned int *port); 00175 SOCKET skt_connect(skt_ip_t ip, int port, int timeout); 00176 00177 /*Utility*/ 00178 void skt_close(SOCKET fd); 00179 int skt_select1(SOCKET fd, int msec); 00180 void skt_setSockBuf(SOCKET skt, int bufsize); 00181 00182 /*Blocking Send/Recv*/ 00183 int skt_sendN(SOCKET hSocket, const void *pBuff, int nBytes); 00184 int skt_recvN(SOCKET hSocket, void *pBuff, int nBytes); 00185 int skt_sendV(SOCKET fd, int nBuffers, const void **buffers, int *lengths); 00186 #if !defined(_WIN32) 00187 int skt_sendmsg(SOCKET hSocket, struct msghdr *mh, int num_bufs, int total_bytes); 00188 #else 00189 int skt_sendmsg(SOCKET hSocket, WSABUF *buffers, int num_bufs, int total_bytes); 00190 #endif 00191 00192 int skt_tcp_no_nagle(SOCKET fd); 00193 00194 #ifdef __cplusplus 00195 } 00196 #endif 00197 00198 #endif 00200 /*********************************** 00201 Conv-host messages: these are a simple 00202 binary format message, with the usual header, 00203 then data arrangement. 00204 00205 A fundamental data type is a ChMessageInt_t, 00206 a simple 4-byte big-endian (network byte order) 00207 integer. Routines are provided to read/write 00208 these integers on all platforms, regardless of 00209 endian-ness or native integer size. 00210 00211 ChMessage_recv reads a ChMessage on a socket. 00212 The ChMessage->data field is allocated to contain 00213 the entire message, and the header is filled out 00214 with the received fields. You may keep or dispose 00215 of the message memory with ChMessage_free. 00216 00217 ChMessageHeader_new fills out the fields of a header-- 00218 no allocation is done. 00219 00220 ChMessage_new fills out the header and allocates a 00221 data area of the given size. 00222 00223 ChMessage_send delivers the given ChMessage to a 00224 socket. You are still responsible for the ChMessage 00225 memory (use ChMessage_free). If you prefer, you may 00226 receive sizeof(ChMessageHeader) header bytes, then 00227 header->len data bytes on any socket yourself. 00228 */ 00229 #ifdef __cplusplus 00230 extern "C" { 00231 #endif 00232 00233 typedef struct { 00234 unsigned char data[4]; /*4-byte, big-endian integer*/ 00235 } ChMessageInt_t; 00236 ChMessageInt_t ChMessageInt_new(unsigned int src); /*Convert integer to bytes*/ 00237 unsigned int ChMessageInt(ChMessageInt_t src); /*Convert bytes to integer*/ 00238 00239 typedef struct { 00240 unsigned char data[8]; /*8-byte, big-endian integer*/ 00241 } ChMessageLong_t; 00242 ChMessageLong_t 00243 ChMessageLong_new(CMK_TYPEDEF_UINT8 src); /*Convert long integer to bytes*/ 00244 CMK_TYPEDEF_UINT8 00245 ChMessageLong(ChMessageLong_t src); /*Convert bytes to long integer*/ 00246 00247 #define CH_TYPELEN 12 /*Maximum length for the message type field*/ 00248 typedef struct ChMessageHeader { 00249 ChMessageInt_t len; /*Length of message to follow (not incl. header)*/ 00250 char type[CH_TYPELEN]; /*Kind of message to follow: 00251 (zero-terminated ASCII string) 00252 "getinfo" -- return a list of node IPs and control ports 00253 "req" -- a CCS message 00254 */ 00255 } ChMessageHeader; 00256 00257 typedef struct ChMessage { 00258 ChMessageHeader header; 00259 int len; /*Length of message data below*/ 00260 char *data; /*Pointer to heap-allocated data*/ 00261 } ChMessage; 00262 int ChMessage_recv(SOCKET fd, ChMessage *dst); 00263 int ChMessageHeader_recv(SOCKET fd, ChMessage *dst); 00264 int ChMessageData_recv(SOCKET fd, ChMessage *dst); 00265 void ChMessage_free(ChMessage *doomed); 00266 void ChMessageHeader_new(const char *type, int len, ChMessageHeader *dst); 00267 void ChMessage_new(const char *type, int len, ChMessage *dst); 00268 int ChMessage_send(SOCKET fd, 00269 const ChMessage *src); /*You must free after send*/ 00270 00271 #if CMK_USE_IBVERBS | CMK_USE_IBUD 00272 typedef struct { 00273 ChMessageInt_t nodeno; 00274 ChMessageInt_t lid, qpn, psn; 00275 } ChInfiAddr; 00276 #endif 00277 00278 #define ChInitNodetabFields 2 00279 #define ChInitNodeforkFields 2 00280 00281 typedef struct { 00282 ChMessageInt_t nodeno; 00283 ChMessageInt_t nProcessesInPhysNode; /* Number of distinct OS processes on 00284 this physical hardware node */ 00285 ChMessageInt_t nPE; /* Number of worker threads in this OS process */ 00286 ChMessageInt_t dataport; /* node's data port (UDP or GM) */ 00287 ChMessageInt_t mach_id; /* node's hardware address (GM-only) */ 00288 #if CMK_USE_MX 00289 ChMessageLong_t nic_id; /* node's NIC hardware address (MX-only) */ 00290 #endif 00291 skt_ip_t IP; /* node's IP address */ 00292 } ChNodeinfo; 00293 00294 typedef struct { 00295 ChMessageInt_t nodeNo; 00296 ChMessageInt_t num_pus; 00297 ChMessageInt_t num_cores; 00298 ChMessageInt_t num_sockets; 00299 ChNodeinfo info; 00300 } ChSingleNodeinfo; 00301 00302 /******* CCS Message type (included here for convenience) *******/ 00303 #define CCS_HANDLERLEN 32 /*Maximum length for the handler field*/ 00304 typedef struct { 00305 ChMessageInt_t len; /*Length of user data to follow header*/ 00306 ChMessageInt_t pe; /*Destination processor number*/ 00307 char handler[CCS_HANDLERLEN]; /*Handler name for message to follow*/ 00308 } CcsMessageHeader; 00309 00310 #ifdef __cplusplus 00311 } 00312 #endif 00313 00314 #endif /*SOCK_ROUTINES_H*/