00001 #include "sockRoutines.h"
00002
00003 #ifndef CMK_NO_SOCKETS
00004
00005 #include <stdio.h>
00006 #include <errno.h>
00007 #include <stdlib.h>
00008 #include <string.h>
00009 #include <signal.h>
00010 #include <time.h>
00011 #include <ctype.h>
00012 #if CMK_USE_POLL
00013 #include <poll.h>
00014 #endif
00015
00016 #if CMK_BPROC
00017 #include <sys/bproc.h>
00018 #endif
00019
00020 #ifndef CMK_NOT_USE_CONVERSE
00021 # include "converse.h"
00022 #elif CMK_NOT_USE_CONVERSE
00023 # define CMI_TMP_SKIP
00024 # define CmiTmpAlloc(size) malloc(size)
00025 # define CmiTmpFree(ptr) free(ptr)
00026 #endif
00027
00028 #if !CMK_HAS_SOCKLEN
00029 typedef int socklen_t;
00030 #endif
00031
00032 #if CMK_HAS_GETIFADDRS
00033 #include <netinet/in.h>
00034 #include <ifaddrs.h>
00035 #include <net/if.h>
00036 #endif
00037
00038
00039 static int default_skt_abort(SOCKET skt, int code, const char *msg)
00040 {
00041 fprintf(stderr,"Fatal socket error: code %d-- %s\n",code,msg);
00042 exit(1);
00043 return -1;
00044 }
00045
00046 static skt_idleFn idleFunc=NULL;
00047 static skt_abortFn skt_abort=default_skt_abort;
00048 void skt_set_idle(skt_idleFn f) {idleFunc=f;}
00049 skt_abortFn skt_set_abort(skt_abortFn f)
00050 {
00051 skt_abortFn old=skt_abort;
00052 skt_abort=f;
00053 return old;
00054 }
00055
00056
00057
00058
00059 static int skt_ignore_SIGPIPE=0;
00060
00061 #if defined(_WIN32)
00062 static void doCleanup(void)
00063 { WSACleanup();}
00064 static int skt_inited=0;
00065
00066 void skt_init(void)
00067 {
00068 WSADATA WSAData;
00069 WORD version=0x0002;
00070 if (skt_inited) return;
00071 skt_inited=1;
00072 WSAStartup(version, &WSAData);
00073 atexit(doCleanup);
00074 }
00075
00076 void skt_close(SOCKET fd)
00077 {
00078 closesocket(fd);
00079 }
00080 #else
00081
00082 typedef void (*skt_signal_handler_fn)(int sig);
00083 static skt_signal_handler_fn skt_fallback_SIGPIPE=NULL;
00084 static struct sigaction sa;
00085 static void skt_SIGPIPE_handler(int sig) {
00086 if (skt_ignore_SIGPIPE) {
00087 fprintf(stderr,"Caught SIGPIPE.\n");
00088 sigaction(SIGPIPE, &sa, NULL);
00089 }
00090 else
00091 skt_fallback_SIGPIPE(sig);
00092 }
00093
00094 void skt_init(void)
00095 {
00096
00097
00098
00099
00100 struct sigaction old_action;
00101 sa.sa_handler = skt_SIGPIPE_handler;
00102 sigemptyset(&sa.sa_mask);
00103 sa.sa_flags = SA_RESTART;
00104 sigaction(SIGPIPE, &sa, &old_action);
00105 skt_fallback_SIGPIPE = old_action.sa_handler;
00106 }
00107 void skt_close(SOCKET fd)
00108 {
00109 skt_ignore_SIGPIPE=1;
00110 close(fd);
00111 skt_ignore_SIGPIPE=0;
00112 }
00113 #endif
00114
00115 #ifndef SKT_HAS_BUFFER_BEGIN
00116 void skt_buffer_begin(SOCKET sk) {}
00117 void skt_buffer_end(SOCKET sk) {}
00118 #endif
00119
00120
00121 static int ERRNO = -1;
00122
00123
00124
00125
00126
00127
00128 static int skt_should_retry(void)
00129 {
00130 int isinterrupt=0,istransient=0,istimeout=0;
00131 #if defined(_WIN32)
00132 int err=WSAGetLastError();
00133 if (err==WSAEINTR) isinterrupt=1;
00134 if (err==WSATRY_AGAIN||err==WSAECONNREFUSED)
00135 istransient=1;
00136 #else
00137 int err=errno;
00138 if (err==EINTR) isinterrupt=1;
00139 if (err==ETIMEDOUT) istimeout=1;
00140 if (err==EAGAIN||err==ECONNREFUSED
00141 ||err==EWOULDBLOCK||err==ENOBUFS
00142 ||err==ECONNRESET
00143 )
00144 istransient=1;
00145 #endif
00146 ERRNO = err;
00147 if (isinterrupt) {
00148
00149 if (idleFunc!=NULL) idleFunc();
00150 }
00151 else if (istransient)
00152 {
00153 if (idleFunc!=NULL) idleFunc();
00154 else sleep(1);
00155 }
00156 else
00157 return 0;
00158
00159
00160 return 1;
00161 }
00162
00163
00164
00165 int skt_tcp_no_nagle(SOCKET fd)
00166 {
00167 int flag, ok;
00168 flag = 1;
00169 ok = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
00170 return ok;
00171 }
00172
00173 #if CMK_USE_POLL
00174 int skt_select1(SOCKET fd,int msec)
00175 {
00176 struct pollfd fds[1];
00177 int begin, nreadable;
00178 int sec=msec/1000;
00179 int secLeft=sec;
00180
00181 fds[0].fd=fd;
00182 fds[0].events=POLLIN;
00183
00184 if (msec>0) begin = time(0);
00185 do
00186 {
00187 skt_ignore_SIGPIPE=1;
00188 nreadable = poll(fds, 1, msec);
00189 skt_ignore_SIGPIPE=0;
00190
00191 if (nreadable < 0) {
00192 if (skt_should_retry()) continue;
00193 else skt_abort(fd, 93200, "Fatal error in poll");
00194 }
00195 if (nreadable >0) return 1;
00196 }
00197 while(msec>0 && ((secLeft = sec - (time(0) - begin))>0));
00198
00199 return 0;
00200 }
00201
00202 #else
00203
00204
00205 int skt_select1(SOCKET fd,int msec)
00206 {
00207 int sec=msec/1000;
00208 fd_set rfds;
00209 struct timeval tmo;
00210 int secLeft=sec;
00211 int begin, nreadable;
00212
00213 FD_ZERO(&rfds);
00214 FD_SET(fd, &rfds);
00215
00216 if (msec>0) begin = time(0);
00217 do
00218 {
00219 tmo.tv_sec=secLeft;
00220 tmo.tv_usec = (msec-1000*sec)*1000;
00221 skt_ignore_SIGPIPE=1;
00222 nreadable = select(1+fd, &rfds, NULL, NULL, &tmo);
00223 skt_ignore_SIGPIPE=0;
00224
00225 if (nreadable < 0) {
00226 if (skt_should_retry()) continue;
00227 else skt_abort(fd, 93200, "Fatal error in select");
00228 }
00229 if (nreadable >0) return 1;
00230 }
00231 while(msec>0 && ((secLeft = sec - (time(0) - begin))>0));
00232
00233 return 0;
00234 }
00235 #endif
00236
00237
00238 skt_ip_t _skt_invalid_ip={{0}};
00239
00240 skt_ip_t skt_my_ip(void)
00241 {
00242 char hostname[1000];
00243 skt_ip_t ip = _skt_invalid_ip;
00244 int ifcount = 0;
00245 #if CMK_HAS_GETIFADDRS
00246
00247
00248 struct ifaddrs *ifaces=0;
00249 if( getifaddrs(&ifaces) == 0 ) {
00250 struct ifaddrs *iface;
00251 for( iface=ifaces; iface; iface=iface->ifa_next ) {
00252 if( (iface->ifa_flags & IFF_UP) && ! (iface->ifa_flags & IFF_LOOPBACK) ) {
00253 const struct sockaddr_in *addr = (const struct sockaddr_in*)iface->ifa_addr;
00254 if( addr && addr->sin_family==AF_INET ) {
00255 ifcount ++;
00256 if ( ifcount==1 ) memcpy(&ip, &addr->sin_addr, sizeof(ip));
00257 }
00258 }
00259 }
00260 freeifaddrs(ifaces);
00261 }
00262
00263 if (ifcount==1) return ip;
00264 #endif
00265
00266 if (gethostname(hostname, 999)==0) {
00267 skt_ip_t ip2 = skt_lookup_ip(hostname);
00268 if ( ip2.data[0] != 127 ) return ip2;
00269 else if ( ifcount != 0 ) return ip;
00270 }
00271
00272 return _skt_invalid_ip;
00273 }
00274
00275 static int skt_parse_dotted(const char *str,skt_ip_t *ret)
00276 {
00277 int i,v;
00278 *ret=_skt_invalid_ip;
00279 for (i=0;i<sizeof(skt_ip_t);i++) {
00280 if (1!=sscanf(str,"%d",&v)) return 0;
00281 if (v<0 || v>255) return 0;
00282 while (isdigit(*str)) str++;
00283 if (i!=sizeof(skt_ip_t)-1) {
00284 if (*str!='.') return 0;
00285 } else {
00286 if (*str!=0) return 0;
00287 }
00288 str++;
00289 ret->data[i]=(unsigned char)v;
00290 }
00291 return 1;
00292 }
00293
00294
00295 skt_ip_t skt_lookup_ip(const char *name)
00296 {
00297 skt_ip_t ret=_skt_invalid_ip;
00298
00299 if (skt_parse_dotted(name,&ret))
00300 return ret;
00301 else {
00302 struct hostent *h = gethostbyname(name);
00303 if (h==0) return _skt_invalid_ip;
00304 memcpy(&ret,h->h_addr_list[0],h->h_length);
00305 return ret;
00306 }
00307 }
00308
00309
00310
00311
00312 skt_ip_t skt_innode_my_ip(void)
00313 {
00314 #if CMK_BPROC
00315
00316 char hostname[200];
00317 sprintf(hostname, "%d", bproc_currnode());
00318 return skt_innode_lookup_ip(hostname);
00319 #else
00320 return skt_my_ip();
00321 #endif
00322 }
00323
00324 skt_ip_t skt_innode_lookup_ip(const char *name)
00325 {
00326 #if CMK_BPROC
00327 struct sockaddr_in addr;
00328 int len = sizeof(struct sockaddr_in);
00329 if (-1 == bproc_nodeaddr(atoi(name), &addr, &len)) {
00330 return _skt_invalid_ip;
00331 }
00332 else {
00333 skt_ip_t ret;
00334 memcpy(&ret,&addr.sin_addr.s_addr,sizeof(ret));
00335 return ret;
00336 }
00337 #else
00338 return skt_lookup_ip(name);
00339 #endif
00340 }
00341
00342
00343 char *skt_print_ip(char *dest,skt_ip_t addr)
00344 {
00345 char *o=dest;
00346 int i;
00347 for (i=0;i<sizeof(addr);i++) {
00348 const char *trail=".";
00349 if (i==sizeof(addr)-1) trail="";
00350 sprintf(o,"%d%s",(int)addr.data[i],trail);
00351 o+=strlen(o);
00352 }
00353 return dest;
00354 }
00355 int skt_ip_match(skt_ip_t a,skt_ip_t b)
00356 {
00357 return 0==memcmp(&a,&b,sizeof(a));
00358 }
00359 struct sockaddr_in skt_build_addr(skt_ip_t IP,int port)
00360 {
00361 struct sockaddr_in ret={0};
00362 ret.sin_family=AF_INET;
00363 ret.sin_port = htons((short)port);
00364 memcpy(&ret.sin_addr,&IP,sizeof(IP));
00365 return ret;
00366 }
00367
00368 SOCKET skt_datagram(unsigned int *port, int bufsize)
00369 {
00370 int connPort=(port==NULL)?0:*port;
00371 struct sockaddr_in addr=skt_build_addr(_skt_invalid_ip,connPort);
00372 socklen_t len;
00373 SOCKET ret;
00374
00375 retry:
00376 ret = socket(AF_INET,SOCK_DGRAM,0);
00377 if (ret == SOCKET_ERROR) {
00378 if (skt_should_retry()) goto retry;
00379 return skt_abort(-1, 93490, "Error creating datagram socket.");
00380 }
00381 if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
00382 return skt_abort(-1, 93491, "Error binding datagram socket.");
00383
00384 len = sizeof(addr);
00385 if (getsockname(ret, (struct sockaddr *)&addr , &len))
00386 return skt_abort(-1, 93492, "Error getting address on datagram socket.");
00387
00388 if (bufsize)
00389 {
00390 len = sizeof(int);
00391 if (setsockopt(ret, SOL_SOCKET , SO_RCVBUF , (char *)&bufsize, len) == SOCKET_ERROR)
00392 return skt_abort(-1, 93495, "Error on RCVBUF sockopt for datagram socket.");
00393 if (setsockopt(ret, SOL_SOCKET , SO_SNDBUF , (char *)&bufsize, len) == SOCKET_ERROR)
00394 return skt_abort(-1, 93496, "Error on SNDBUF sockopt for datagram socket.");
00395 }
00396
00397 if (port!=NULL) *port = (int)ntohs(addr.sin_port);
00398 return ret;
00399 }
00400 SOCKET skt_server(unsigned int *port)
00401 {
00402 return skt_server_ip(port,NULL);
00403 }
00404
00405 SOCKET skt_server_ip(unsigned int *port,skt_ip_t *ip)
00406 {
00407 SOCKET ret;
00408 socklen_t len;
00409 int on = 1;
00410 int connPort=(port==NULL)?0:*port;
00411 struct sockaddr_in addr=skt_build_addr((ip==NULL)?_skt_invalid_ip:*ip,connPort);
00412
00413 retry:
00414 ret = socket(PF_INET, SOCK_STREAM, 0);
00415
00416 if (ret == SOCKET_ERROR) {
00417 if (skt_should_retry()) goto retry;
00418 else return skt_abort(-1, 93483, "Error creating server socket.");
00419 }
00420 setsockopt(ret, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
00421
00422 if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
00423 return skt_abort(-1, 93484, "Error binding server socket.");
00424 if (listen(ret,5) == SOCKET_ERROR)
00425 return skt_abort(-1, 93485, "Error listening on server socket.");
00426 len = sizeof(addr);
00427 if (getsockname(ret, (struct sockaddr *)&addr, &len) == SOCKET_ERROR)
00428 return skt_abort(-1, 93486, "Error getting name on server socket.");
00429
00430 if (port!=NULL) *port = (int)ntohs(addr.sin_port);
00431 if (ip!=NULL) memcpy(ip, &addr.sin_addr, sizeof(*ip));
00432 return ret;
00433 }
00434
00435 SOCKET skt_accept(SOCKET src_fd,skt_ip_t *pip, unsigned int *port)
00436 {
00437 socklen_t len;
00438 struct sockaddr_in addr={0};
00439 SOCKET ret;
00440 len = sizeof(addr);
00441 retry:
00442 ret = accept(src_fd, (struct sockaddr *)&addr, &len);
00443 if (ret == SOCKET_ERROR) {
00444 if (skt_should_retry()) goto retry;
00445 else return skt_abort(-1, 93523, "Error in accept.");
00446 }
00447
00448 if (port!=NULL) *port=ntohs(addr.sin_port);
00449 if (pip!=NULL) memcpy(pip,&addr.sin_addr,sizeof(*pip));
00450 return ret;
00451 }
00452
00453
00454 SOCKET skt_connect(skt_ip_t ip, int port, int timeout)
00455 {
00456 struct sockaddr_in addr=skt_build_addr(ip,port);
00457 int ok, begin;
00458 SOCKET ret;
00459
00460 begin = time(0);
00461 while (time(0)-begin < timeout)
00462 {
00463 ret = socket(AF_INET, SOCK_STREAM, 0);
00464 if (ret==SOCKET_ERROR)
00465 {
00466 if (skt_should_retry()) continue;
00467 else return skt_abort(-1, 93512, "Error creating socket");
00468 }
00469 ok = connect(ret, (struct sockaddr *)&(addr), sizeof(addr));
00470 if (ok != SOCKET_ERROR)
00471 return ret;
00472 else {
00473 skt_close(ret);
00474 if (skt_should_retry()) continue;
00475 else {
00476 #if ! defined(_WIN32)
00477 if (ERRNO == ETIMEDOUT) continue;
00478 #endif
00479 return skt_abort(-1, 93515, "Error connecting to socket\n");
00480 }
00481 }
00482 }
00483
00484 if (timeout==60)
00485 return skt_abort(-1, 93517, "Timeout in socket connect\n");
00486 return INVALID_SOCKET;
00487 }
00488
00489 void skt_setSockBuf(SOCKET skt, int bufsize)
00490 {
00491 int len = sizeof(int);
00492 if (setsockopt(skt, SOL_SOCKET , SO_SNDBUF , (char *)&bufsize, len) == SOCKET_ERROR)
00493 skt_abort(-1, 93496, "Error on SNDBUF sockopt for datagram socket.");
00494 if (setsockopt(skt, SOL_SOCKET , SO_RCVBUF , (char *)&bufsize, len) == SOCKET_ERROR)
00495 skt_abort(-1, 93496, "Error on RCVBUF sockopt for datagram socket.");
00496 }
00497
00498 int skt_recvN(SOCKET hSocket,void *buff,int nBytes)
00499 {
00500 int nLeft,nRead;
00501 char *pBuff=(char *)buff;
00502
00503 nLeft = nBytes;
00504 while (0 < nLeft)
00505 {
00506 if (0==skt_select1(hSocket,600*1000))
00507 return skt_abort(hSocket, 93610, "Timeout on socket recv!");
00508 skt_ignore_SIGPIPE=1;
00509 nRead = recv(hSocket,pBuff,nLeft,0);
00510 skt_ignore_SIGPIPE=0;
00511 if (nRead<=0)
00512 {
00513 if (nRead==0) return skt_abort(hSocket, 93620, "Socket closed before recv.");
00514 if (skt_should_retry()) continue;
00515 else return skt_abort(hSocket, 93650+hSocket, "Error on socket recv!");
00516 }
00517 else
00518 {
00519 nLeft -= nRead;
00520 pBuff += nRead;
00521 }
00522 }
00523 return 0;
00524 }
00525
00526 int skt_sendN(SOCKET hSocket,const void *buff,int nBytes)
00527 {
00528 int nLeft,nWritten;
00529 const char *pBuff=(const char *)buff;
00530
00531 nLeft = nBytes;
00532 while (0 < nLeft)
00533 {
00534 skt_ignore_SIGPIPE=1;
00535 nWritten = send(hSocket,pBuff,nLeft,0);
00536 skt_ignore_SIGPIPE=0;
00537 if (nWritten<=0)
00538 {
00539 if (nWritten==0) return skt_abort(hSocket, 93720, "Socket closed before send.");
00540 if (skt_should_retry()) continue;
00541 else return skt_abort(hSocket, 93700+hSocket, "Error on socket send!");
00542 }
00543 else
00544 {
00545 nLeft -= nWritten;
00546 pBuff += nWritten;
00547 }
00548 }
00549 return 0;
00550 }
00551
00552
00553
00554
00555 #define skt_sendV_max (16*1024)
00556
00557 int skt_sendV(SOCKET fd,int nBuffers,const void **bufs,int *lens)
00558 {
00559 int b,len=0;
00560 for (b=0;b<nBuffers;b++) len+=lens[b];
00561 if (len<=skt_sendV_max) {
00562 char *buf=(char *)CmiTmpAlloc(skt_sendV_max);
00563 char *dest=buf;
00564 int ret;
00565 for (b=0;b<nBuffers;b++) {
00566 memcpy(dest,bufs[b],lens[b]);
00567 dest+=lens[b];
00568 }
00569 ret=skt_sendN(fd,buf,len);
00570 CmiTmpFree(buf);
00571 return ret;
00572 }
00573 else {
00574 int ret;
00575 for (b=0;b<nBuffers;b++)
00576 if (0!=(ret=skt_sendN(fd,bufs[b],lens[b])))
00577 return ret;
00578 return 0;
00579 }
00580 }
00581
00582 #if !defined(_WIN32)
00583 int skt_sendmsg(SOCKET hSocket, struct msghdr *mh, int num_bufs, int nBytes)
00584 {
00585 while (nBytes > 0) {
00586 skt_ignore_SIGPIPE = 1;
00587 int bytes_sent = sendmsg(hSocket, mh, 0);
00588 skt_ignore_SIGPIPE = 0;
00589 if (bytes_sent <= 0) {
00590 return skt_abort(hSocket, 93700+hSocket, "Error on socket send!");
00591 } else if (bytes_sent < nBytes) {
00592
00593 int offset = 0;
00594 int i;
00595 for (i=0; i < num_bufs; i++) {
00596 int l = mh->msg_iov[i].iov_len;
00597 if ((offset + l) <= bytes_sent) {
00598 mh->msg_iov[i].iov_len = 0;
00599 offset += l;
00600 } else {
00601
00602 int buf_transmitted = (bytes_sent - offset);
00603 mh->msg_iov[i].iov_len -= buf_transmitted;
00604 mh->msg_iov[i].iov_base = (char*)mh->msg_iov[i].iov_base + buf_transmitted;
00605 break;
00606 }
00607 }
00608 }
00609 nBytes -= bytes_sent;
00610 }
00611 return 0;
00612 }
00613 #else
00614 int skt_sendmsg(SOCKET hSocket, WSABUF *buffers, int num_bufs, int nBytes)
00615 {
00616 DWORD bytes_sent = 0;
00617 int rc;
00618 skt_ignore_SIGPIPE = 1;
00619 rc = WSASend(hSocket, buffers, num_bufs, &bytes_sent, 0, NULL, NULL);
00620 skt_ignore_SIGPIPE = 0;
00621 if ((rc != 0) || (bytes_sent != nBytes)) {
00622 return skt_abort(hSocket, 93700+hSocket, "Error on socket send!");
00623 }
00624 return 0;
00625 }
00626 #endif
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 ChMessageInt_t ChMessageInt_new(unsigned int src)
00660 {
00661 int i; ChMessageInt_t ret;
00662 for (i=0;i<4;i++) ret.data[i]=(unsigned char)(src>>(8*(3-i)));
00663 return ret;
00664 }
00665 unsigned int ChMessageInt(ChMessageInt_t src)
00666 {
00667 int i; unsigned int ret=0;
00668 for (i=0;i<4;i++) {ret<<=8;ret+=src.data[i];}
00669 return (int)ret;
00670 }
00671
00672 ChMessageLong_t ChMessageLong_new(CMK_TYPEDEF_UINT8 src)
00673 {
00674 int i; ChMessageLong_t ret;
00675 for (i=0;i<8;i++) ret.data[i]=(unsigned char)(src>>(8*(7-i)));
00676 return ret;
00677 }
00678 CMK_TYPEDEF_UINT8 ChMessageLong(ChMessageLong_t src)
00679 {
00680 int i; CMK_TYPEDEF_UINT8 ret=0;
00681 for (i=0;i<8;i++) {ret<<=8;ret+=src.data[i];}
00682 return (CMK_TYPEDEF_UINT8)ret;
00683 }
00684
00685 int ChMessage_recv(SOCKET fd,ChMessage *dst)
00686 {
00687
00688 if (0!=ChMessageHeader_recv(fd,dst)) return -1;
00689 if (0!=ChMessageData_recv(fd,dst)) return -1;
00690 return 0;
00691 }
00692
00693 int ChMessageHeader_recv(SOCKET fd,ChMessage *dst)
00694 {
00695
00696 if (0!=skt_recvN(fd,(char *)&dst->header,sizeof(dst->header))) return -1;
00697
00698 dst->len=ChMessageInt(dst->header.len);
00699 dst->data=0;
00700 return 0;
00701 }
00702 int ChMessageData_recv(SOCKET fd,ChMessage *dst)
00703 {
00704 dst->data=(char *)malloc(dst->len);
00705
00706 if (0!=skt_recvN(fd,dst->data,dst->len)) return -1;
00707 return 0;
00708 }
00709
00710 void ChMessage_free(ChMessage *doomed)
00711 {
00712 free(doomed->data);
00713 strncpy(doomed->header.type,"Free'd",CH_TYPELEN);
00714 doomed->data=NULL;
00715 doomed->len=-1234;
00716 }
00717 void ChMessageHeader_new(const char *type,int len,ChMessageHeader *dst)
00718 {
00719 dst->len=ChMessageInt_new(len);
00720 if (type==NULL) type="default";
00721 strncpy(dst->type,type,CH_TYPELEN);
00722 }
00723 void ChMessage_new(const char *type,int len,ChMessage *dst)
00724 {
00725 ChMessageHeader_new(type,len,&dst->header);
00726 dst->len=len;
00727 dst->data=(char *)malloc(dst->len);
00728 }
00729 int ChMessage_send(SOCKET fd,const ChMessage *src)
00730 {
00731 const void *bufs[2]; int lens[2];
00732 bufs[0]=&src->header; lens[0]=sizeof(src->header);
00733 bufs[1]=src->data; lens[1]=src->len;
00734 return skt_sendV(fd,2,bufs,lens);
00735 }
00736
00737 #else
00738
00739 skt_ip_t _skt_invalid_ip={{0}};
00740
00741 skt_ip_t skt_my_ip(void)
00742 {
00743 return _skt_invalid_ip;
00744 }
00745
00746 #endif