
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 {int tag;} skt_ip_t; 00107 00108 extern skt_ip_t _skt_invalid_ip; 00109 skt_ip_t skt_my_ip(void); 00110 00111 #else /*Use actual sockets*/ 00112 00113 /*Preliminaries*/ 00114 #if defined(_WIN32) && ! defined(__CYGWIN__) 00115 /*For windows systems:*/ 00116 #include <winsock.h> 00117 static void sleep(int secs) {Sleep(1000*secs);} 00118 00119 #else 00120 /*For non-windows (UNIX) systems:*/ 00121 #include <sys/types.h> 00122 #include <sys/time.h> 00123 #include <sys/socket.h> 00124 #include <netinet/in.h> 00125 #include <netinet/tcp.h> 00126 #include <arpa/inet.h> 00127 #include <netdb.h> 00128 #include <unistd.h> 00129 #include <fcntl.h> 00130 00131 #ifndef SOCKET 00132 # define SOCKET int 00133 # define INVALID_SOCKET (SOCKET)(~0) 00134 # define SOCKET_ERROR (-1) 00135 #endif /*def SOCKET*/ 00136 00137 #endif /*WIN32*/ 00138 00139 #ifdef __cplusplus 00140 extern "C" { 00141 #endif 00142 00143 /*Initialization*/ 00144 void skt_init(void); 00145 00146 /*Error and idle handling*/ 00147 typedef void (*skt_idleFn)(void); 00148 typedef int (*skt_abortFn)(int errCode,const char *msg); 00149 void skt_set_idle(skt_idleFn f); 00150 skt_abortFn skt_set_abort(skt_abortFn f); 00151 00152 /*DNS*/ 00153 typedef struct { /*IPv4 IP address*/ 00154 unsigned char data[4]; 00155 } skt_ip_t; 00156 extern skt_ip_t _skt_invalid_ip; 00157 skt_ip_t skt_my_ip(void); 00158 skt_ip_t skt_lookup_ip(const char *name); 00159 skt_ip_t skt_innode_my_ip(void); /* inner node version */ 00160 skt_ip_t skt_innode_lookup_ip(const char *name); 00161 00162 char *skt_print_ip(char *dest,skt_ip_t addr); 00163 int skt_ip_match(skt_ip_t a,skt_ip_t b); 00164 struct sockaddr_in skt_build_addr(skt_ip_t IP,int port); 00165 00166 /*UDP*/ 00167 SOCKET skt_datagram(unsigned int *port, int bufsize); 00168 00169 /*TCP*/ 00170 SOCKET skt_server(unsigned int *port); 00171 SOCKET skt_server_ip(unsigned int *port,skt_ip_t *ip); 00172 SOCKET skt_accept(SOCKET src_fd, skt_ip_t *pip, unsigned int *port); 00173 SOCKET skt_connect(skt_ip_t ip, int port, int timeout); 00174 00175 /*Utility*/ 00176 void skt_close(SOCKET fd); 00177 int skt_select1(SOCKET fd,int msec); 00178 void skt_setSockBuf(SOCKET skt, int bufsize); 00179 00180 /*Blocking Send/Recv*/ 00181 int skt_sendN(SOCKET hSocket,const void *pBuff,int nBytes); 00182 int skt_recvN(SOCKET hSocket, void *pBuff,int nBytes); 00183 int skt_sendV(SOCKET fd,int nBuffers,const void **buffers,int *lengths); 00184 00185 int skt_tcp_no_nagle(SOCKET fd); 00186 00187 #ifdef __cplusplus 00188 } 00189 #endif 00190 00191 #endif 00193 /*********************************** 00194 Conv-host messages: these are a simple 00195 binary format message, with the usual header, 00196 then data arrangement. 00197 00198 A fundamental data type is a ChMessageInt_t, 00199 a simple 4-byte big-endian (network byte order) 00200 integer. Routines are provided to read/write 00201 these integers on all platforms, regardless of 00202 endian-ness or native integer size. 00203 00204 ChMessage_recv reads a ChMessage on a socket. 00205 The ChMessage->data field is allocated to contain 00206 the entire message, and the header is filled out 00207 with the received fields. You may keep or dispose 00208 of the message memory with ChMessage_free. 00209 00210 ChMessageHeader_new fills out the fields of a header-- 00211 no allocation is done. 00212 00213 ChMessage_new fills out the header and allocates a 00214 data area of the given size. 00215 00216 ChMessage_send delivers the given ChMessage to a 00217 socket. You are still responsible for the ChMessage 00218 memory (use ChMessage_free). If you prefer, you may 00219 receive sizeof(ChMessageHeader) header bytes, then 00220 header->len data bytes on any socket yourself. 00221 */ 00222 #ifdef __cplusplus 00223 extern "C" { 00224 #endif 00225 00226 typedef struct { 00227 unsigned char data[4];/*4-byte, big-endian integer*/ 00228 } ChMessageInt_t; 00229 ChMessageInt_t ChMessageInt_new(unsigned int src); /*Convert integer to bytes*/ 00230 unsigned int ChMessageInt(ChMessageInt_t src); /*Convert bytes to integer*/ 00231 00232 typedef struct { 00233 unsigned char data[8];/*8-byte, big-endian integer*/ 00234 } ChMessageLong_t; 00235 ChMessageLong_t ChMessageLong_new(CMK_TYPEDEF_UINT8 src); /*Convert long integer to bytes*/ 00236 CMK_TYPEDEF_UINT8 ChMessageLong(ChMessageLong_t src); /*Convert bytes to long integer*/ 00237 00238 #define CH_TYPELEN 12 /*Maximum length for the message type field*/ 00239 typedef struct ChMessageHeader { 00240 ChMessageInt_t len; /*Length of message to follow (not incl. header)*/ 00241 char type[CH_TYPELEN];/*Kind of message to follow: 00242 (zero-terminated ASCII string) 00243 "getinfo" -- return a list of node IPs and control ports 00244 "req" -- a CCS message 00245 */ 00246 } ChMessageHeader; 00247 00248 typedef struct ChMessage { 00249 ChMessageHeader header; 00250 int len; /*Length of message data below*/ 00251 char *data; /*Pointer to heap-allocated data*/ 00252 } ChMessage; 00253 int ChMessage_recv(SOCKET fd,ChMessage *dst); 00254 int ChMessageHeader_recv(SOCKET fd,ChMessage *dst); 00255 int ChMessageData_recv(SOCKET fd,ChMessage *dst); 00256 void ChMessage_free(ChMessage *doomed); 00257 void ChMessageHeader_new(const char *type,int len,ChMessageHeader *dst); 00258 void ChMessage_new(const char *type,int len,ChMessage *dst); 00259 int ChMessage_send(SOCKET fd,const ChMessage *src); /*You must free after send*/ 00260 00261 00262 #if CMK_USE_IBVERBS | CMK_USE_IBUD 00263 typedef struct { 00264 ChMessageInt_t lid,qpn,psn; 00265 } ChInfiAddr ; 00266 #endif 00267 00268 00269 typedef struct { 00270 ChMessageInt_t nPE; /* Number of compute processors on this node */ 00271 #if CMK_USE_IBVERBS 00272 ChInfiAddr *qpList; 00273 #endif 00274 #if CMK_USE_IBUD 00275 ChInfiAddr qp; 00276 #endif 00277 ChMessageInt_t dataport; /* node's data port (UDP or GM) */ 00278 ChMessageInt_t mach_id; /* node's hardware address (GM-only) */ 00279 #if CMK_USE_MX 00280 ChMessageLong_t nic_id; /* node's NIC hardware address (MX-only) */ 00281 #endif 00282 skt_ip_t IP; /* node's IP address */ 00283 } ChNodeinfo; 00284 00285 typedef struct { 00286 ChMessageInt_t nodeNo; 00287 ChNodeinfo info; 00288 } ChSingleNodeinfo; 00289 00290 /******* CCS Message type (included here for convenience) *******/ 00291 #define CCS_HANDLERLEN 32 /*Maximum length for the handler field*/ 00292 typedef struct { 00293 ChMessageInt_t len;/*Length of user data to follow header*/ 00294 ChMessageInt_t pe;/*Destination processor number*/ 00295 char handler[CCS_HANDLERLEN];/*Handler name for message to follow*/ 00296 } CcsMessageHeader; 00297 00298 #ifdef __cplusplus 00299 } 00300 #endif 00301 00302 #endif /*SOCK_ROUTINES_H*/ 00303
1.5.5