112 lines
2.8 KiB
C
112 lines
2.8 KiB
C
#include <stdlib.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <arpa/inet.h>
|
|
#include <netdb.h>
|
|
#include <string.h>
|
|
#include "myc_err.h"
|
|
#include "myc_str.h"
|
|
#include "coc_util.h"
|
|
/*-------------------------------------------------------------------------*/
|
|
/* CreateSocketAddress stolen from Tcl. Thanks to John Ousterhout */
|
|
|
|
int CocCreateSockAdr(
|
|
struct sockaddr_in *sockaddrPtr, /* Socket address */
|
|
const char *host, /* Host. NULL implies INADDR_ANY */
|
|
int port) /* Port number */
|
|
{
|
|
struct hostent *hostent; /* Host database entry */
|
|
struct in_addr addr; /* For 64/32 bit madness */
|
|
|
|
(void) memset((char *) sockaddrPtr, '\0', sizeof(struct sockaddr_in));
|
|
sockaddrPtr->sin_family = AF_INET;
|
|
sockaddrPtr->sin_port = htons((unsigned short) (port & 0xFFFF));
|
|
if (host == NULL || host[0]=='\0') {
|
|
addr.s_addr = INADDR_ANY;
|
|
} else {
|
|
hostent = gethostbyname(host);
|
|
if (hostent != NULL) {
|
|
memcpy((char *) &addr,
|
|
(char *) hostent->h_addr_list[0], (size_t) hostent->h_length);
|
|
} else {
|
|
addr.s_addr = inet_addr(host);
|
|
if (addr.s_addr == (unsigned long)-1) {
|
|
return -1; /* error */
|
|
}
|
|
}
|
|
}
|
|
/*
|
|
* There is a rumor that this assignment may require care on
|
|
* some 64 bit machines.
|
|
*/
|
|
|
|
sockaddrPtr->sin_addr.s_addr = addr.s_addr;
|
|
return 0;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
void CocDelay(int msec) {
|
|
struct timeval tmo;
|
|
|
|
tmo.tv_sec=msec / 1000;
|
|
tmo.tv_usec=(msec % 1000)*1000+1;
|
|
select(1,NULL,NULL,NULL,&tmo);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
int CocSend(int fd, char *str, int size) {
|
|
int siz;
|
|
siz=htonl(size);
|
|
ERR_SI(send(fd, &siz, 4, 0));
|
|
ERR_SI(send(fd, str, size, 0));
|
|
return(0);
|
|
OnError: return(-1);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
int CocRecv(int fd, StrBuf *buf, int timeout, int *flag) {
|
|
struct timeval tmo={0,1};
|
|
fd_set mask;
|
|
int i, l;
|
|
int siz, n;
|
|
|
|
if (timeout>=0) {
|
|
tmo.tv_sec=timeout;
|
|
|
|
FD_ZERO(&mask);
|
|
FD_SET(fd, &mask);
|
|
ERR_SI(i=select(fd+1,&mask,NULL,NULL,&tmo));
|
|
if (flag!=NULL) {
|
|
*flag=0;
|
|
if (i==0) return(0);
|
|
} else {
|
|
if (i==0) { ERR_MSG("time out"); }
|
|
}
|
|
}
|
|
|
|
n=0;
|
|
ERR_SI(i=recv(fd, &n, 4, 0));
|
|
if (i!=4) {
|
|
ERR_COD(ECONNRESET);
|
|
}
|
|
siz=ntohl(n);
|
|
if (siz > buf->dsize)
|
|
ERR_MSG("buffer too small");
|
|
ERR_SI(l=recv(fd, buf->buf, siz, 0));
|
|
buf->wrpos=l;
|
|
while (buf->wrpos<siz) {
|
|
if (l==0) {
|
|
ERR_COD(ECONNRESET);
|
|
}
|
|
ERR_SI(l=recv(fd, buf->buf+buf->wrpos, siz, 0));
|
|
buf->wrpos+=l;
|
|
}
|
|
StrReset(buf);
|
|
return(buf->wrpos);
|
|
OnError: return(-1);
|
|
}
|
|
|